[automerger skipped] DO NOT MERGE Track TZDB 2022a rev. 2 changes. [R] am: 9fbd04b765 -s ours am: 197bb11c9e -s ours am: 15e6093090 -s ours am: 63f9ed3df2 -s ours

am skip reason: subject contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/libcore/+/19696571

Change-Id: Ic0d760583904365efc8c06d96f7bfaef0d7c9b20
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index b599141..6d8a0f5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -60,6 +60,7 @@
 build = [
     "JavaLibrary.bp",
     "NativeCode.bp",
+    "Extras.bp",
 ]
 
 java_genrule {
diff --git a/EXPECTED_UPSTREAM b/EXPECTED_UPSTREAM
new file mode 100644
index 0000000..eefa580
--- /dev/null
+++ b/EXPECTED_UPSTREAM
@@ -0,0 +1,2080 @@
+# Copyright (C) 2021 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.
+
+# This table has 3 columns, i.e.
+# <destination path in ojluni>,<upstream release version / git-tag>,<source path in the upstream repository>
+
+ojluni/src/main/java/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java
+ojluni/src/main/java/com/sun/nio/file/ExtendedCopyOption.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/com/sun/nio/file/ExtendedCopyOption.java
+ojluni/src/main/java/com/sun/nio/file/ExtendedOpenOption.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/com/sun/nio/file/ExtendedOpenOption.java
+ojluni/src/main/java/com/sun/nio/file/ExtendedWatchEventModifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/com/sun/nio/file/ExtendedWatchEventModifier.java
+ojluni/src/main/java/com/sun/nio/file/SensitivityWatchEventModifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/com/sun/nio/file/SensitivityWatchEventModifier.java
+ojluni/src/main/java/com/sun/security/cert/internal/x509/X509V1CertImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/com/sun/security/cert/internal/x509/X509V1CertImpl.java
+ojluni/src/main/java/java/awt/font/NumericShaper.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/awt/font/NumericShaper.java
+ojluni/src/main/java/java/awt/font/TextAttribute.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/awt/font/TextAttribute.java
+ojluni/src/main/java/java/beans/ChangeListenerMap.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/beans/ChangeListenerMap.java
+ojluni/src/main/java/java/beans/IndexedPropertyChangeEvent.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/beans/IndexedPropertyChangeEvent.java
+ojluni/src/main/java/java/beans/PropertyChangeEvent.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/beans/PropertyChangeEvent.java
+ojluni/src/main/java/java/beans/PropertyChangeListener.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/beans/PropertyChangeListener.java
+ojluni/src/main/java/java/beans/PropertyChangeListenerProxy.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/beans/PropertyChangeListenerProxy.java
+ojluni/src/main/java/java/beans/PropertyChangeSupport.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/beans/PropertyChangeSupport.java
+ojluni/src/main/java/java/io/Bits.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/Bits.java
+ojluni/src/main/java/java/io/BufferedInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/BufferedInputStream.java
+ojluni/src/main/java/java/io/BufferedOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/BufferedOutputStream.java
+ojluni/src/main/java/java/io/BufferedReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/BufferedReader.java
+ojluni/src/main/java/java/io/BufferedWriter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/BufferedWriter.java
+ojluni/src/main/java/java/io/ByteArrayInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/ByteArrayInputStream.java
+ojluni/src/main/java/java/io/ByteArrayOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/ByteArrayOutputStream.java
+ojluni/src/main/java/java/io/CharArrayReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/CharArrayReader.java
+ojluni/src/main/java/java/io/CharArrayWriter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/CharArrayWriter.java
+ojluni/src/main/java/java/io/CharConversionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/CharConversionException.java
+ojluni/src/main/java/java/io/Closeable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/Closeable.java
+ojluni/src/main/java/java/io/Console.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/Console.java
+ojluni/src/main/java/java/io/DataInput.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/DataInput.java
+ojluni/src/main/java/java/io/DataInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/DataInputStream.java
+ojluni/src/main/java/java/io/DataOutput.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/DataOutput.java
+ojluni/src/main/java/java/io/DataOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/DataOutputStream.java
+ojluni/src/main/java/java/io/DefaultFileSystem.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/java/io/DefaultFileSystem.java
+ojluni/src/main/java/java/io/DeleteOnExitHook.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/DeleteOnExitHook.java
+ojluni/src/main/java/java/io/EOFException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/EOFException.java
+ojluni/src/main/java/java/io/ExpiringCache.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/ExpiringCache.java
+ojluni/src/main/java/java/io/Externalizable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/Externalizable.java
+ojluni/src/main/java/java/io/File.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/File.java
+ojluni/src/main/java/java/io/FileDescriptor.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/io/FileDescriptor.java
+ojluni/src/main/java/java/io/FileFilter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FileFilter.java
+ojluni/src/main/java/java/io/FileInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/FileInputStream.java
+ojluni/src/main/java/java/io/FileNotFoundException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FileNotFoundException.java
+ojluni/src/main/java/java/io/FileOutputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/FileOutputStream.java
+ojluni/src/main/java/java/io/FilePermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FilePermission.java
+ojluni/src/main/java/java/io/FileReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FileReader.java
+ojluni/src/main/java/java/io/FileSystem.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/FileSystem.java
+ojluni/src/main/java/java/io/FileWriter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FileWriter.java
+ojluni/src/main/java/java/io/FilenameFilter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FilenameFilter.java
+ojluni/src/main/java/java/io/FilterInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FilterInputStream.java
+ojluni/src/main/java/java/io/FilterOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FilterOutputStream.java
+ojluni/src/main/java/java/io/FilterReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FilterReader.java
+ojluni/src/main/java/java/io/FilterWriter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/FilterWriter.java
+ojluni/src/main/java/java/io/Flushable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/Flushable.java
+ojluni/src/main/java/java/io/IOError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/IOError.java
+ojluni/src/main/java/java/io/IOException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/IOException.java
+ojluni/src/main/java/java/io/InputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/InputStream.java
+ojluni/src/main/java/java/io/InputStreamReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/InputStreamReader.java
+ojluni/src/main/java/java/io/InterruptedIOException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/InterruptedIOException.java
+ojluni/src/main/java/java/io/InvalidClassException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/InvalidClassException.java
+ojluni/src/main/java/java/io/InvalidObjectException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/InvalidObjectException.java
+ojluni/src/main/java/java/io/LineNumberInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/LineNumberInputStream.java
+ojluni/src/main/java/java/io/LineNumberReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/LineNumberReader.java
+ojluni/src/main/java/java/io/NotActiveException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/NotActiveException.java
+ojluni/src/main/java/java/io/NotSerializableException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/NotSerializableException.java
+ojluni/src/main/java/java/io/ObjectInput.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/ObjectInput.java
+ojluni/src/main/java/java/io/ObjectInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/ObjectInputStream.java
+ojluni/src/main/java/java/io/ObjectInputValidation.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/ObjectInputValidation.java
+ojluni/src/main/java/java/io/ObjectOutput.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/ObjectOutput.java
+ojluni/src/main/java/java/io/ObjectOutputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/ObjectOutputStream.java
+ojluni/src/main/java/java/io/ObjectStreamClass.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/ObjectStreamClass.java
+ojluni/src/main/java/java/io/ObjectStreamConstants.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/ObjectStreamConstants.java
+ojluni/src/main/java/java/io/ObjectStreamException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/ObjectStreamException.java
+ojluni/src/main/java/java/io/ObjectStreamField.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/ObjectStreamField.java
+ojluni/src/main/java/java/io/OptionalDataException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/OptionalDataException.java
+ojluni/src/main/java/java/io/OutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/OutputStream.java
+ojluni/src/main/java/java/io/OutputStreamWriter.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/OutputStreamWriter.java
+ojluni/src/main/java/java/io/PipedInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PipedInputStream.java
+ojluni/src/main/java/java/io/PipedOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PipedOutputStream.java
+ojluni/src/main/java/java/io/PipedReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PipedReader.java
+ojluni/src/main/java/java/io/PipedWriter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PipedWriter.java
+ojluni/src/main/java/java/io/PrintStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PrintStream.java
+ojluni/src/main/java/java/io/PrintWriter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PrintWriter.java
+ojluni/src/main/java/java/io/PushbackInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PushbackInputStream.java
+ojluni/src/main/java/java/io/PushbackReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/PushbackReader.java
+ojluni/src/main/java/java/io/RandomAccessFile.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/RandomAccessFile.java
+ojluni/src/main/java/java/io/Reader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/Reader.java
+ojluni/src/main/java/java/io/SequenceInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/SequenceInputStream.java
+ojluni/src/main/java/java/io/SerialCallbackContext.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/io/SerialCallbackContext.java
+ojluni/src/main/java/java/io/Serializable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/Serializable.java
+ojluni/src/main/java/java/io/SerializablePermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/SerializablePermission.java
+ojluni/src/main/java/java/io/StreamCorruptedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/StreamCorruptedException.java
+ojluni/src/main/java/java/io/StreamTokenizer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/StreamTokenizer.java
+ojluni/src/main/java/java/io/StringBufferInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/StringBufferInputStream.java
+ojluni/src/main/java/java/io/StringReader.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/StringReader.java
+ojluni/src/main/java/java/io/StringWriter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/StringWriter.java
+ojluni/src/main/java/java/io/SyncFailedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/SyncFailedException.java
+ojluni/src/main/java/java/io/UTFDataFormatException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/UTFDataFormatException.java
+ojluni/src/main/java/java/io/UncheckedIOException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/UncheckedIOException.java
+ojluni/src/main/java/java/io/UnixFileSystem.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/io/UnixFileSystem.java
+ojluni/src/main/java/java/io/UnsupportedEncodingException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/UnsupportedEncodingException.java
+ojluni/src/main/java/java/io/WriteAbortedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/WriteAbortedException.java
+ojluni/src/main/java/java/io/Writer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/io/Writer.java
+ojluni/src/main/java/java/lang/AbstractMethodError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/AbstractMethodError.java
+ojluni/src/main/java/java/lang/AbstractStringBuilder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/AbstractStringBuilder.java
+ojluni/src/main/java/java/lang/Appendable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Appendable.java
+ojluni/src/main/java/java/lang/ArithmeticException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ArithmeticException.java
+ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ArrayIndexOutOfBoundsException.java
+ojluni/src/main/java/java/lang/ArrayStoreException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ArrayStoreException.java
+ojluni/src/main/java/java/lang/AssertionError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/AssertionError.java
+ojluni/src/main/java/java/lang/AutoCloseable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/AutoCloseable.java
+ojluni/src/main/java/java/lang/Boolean.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Boolean.java
+ojluni/src/main/java/java/lang/BootstrapMethodError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/BootstrapMethodError.java
+ojluni/src/main/java/java/lang/Byte.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Byte.java
+ojluni/src/main/java/java/lang/CharSequence.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/CharSequence.java
+ojluni/src/main/java/java/lang/Character.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/Character.java
+ojluni/src/main/java/java/lang/Class.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/Class.java
+ojluni/src/main/java/java/lang/ClassCastException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ClassCastException.java
+ojluni/src/main/java/java/lang/ClassCircularityError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ClassCircularityError.java
+ojluni/src/main/java/java/lang/ClassFormatError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ClassFormatError.java
+ojluni/src/main/java/java/lang/ClassLoader.java,jdk8u/jdk8u60-b31,jdk/src/share/classes/java/lang/ClassLoader.java
+ojluni/src/main/java/java/lang/ClassNotFoundException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ClassNotFoundException.java
+ojluni/src/main/java/java/lang/CloneNotSupportedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/CloneNotSupportedException.java
+ojluni/src/main/java/java/lang/Cloneable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Cloneable.java
+ojluni/src/main/java/java/lang/Comparable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Comparable.java
+ojluni/src/main/java/java/lang/Compiler.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Compiler.java
+ojluni/src/main/java/java/lang/Deprecated.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Deprecated.java
+ojluni/src/main/java/java/lang/Double.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Double.java
+ojluni/src/main/java/java/lang/Enum.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Enum.java
+ojluni/src/main/java/java/lang/EnumConstantNotPresentException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/EnumConstantNotPresentException.java
+ojluni/src/main/java/java/lang/Error.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Error.java
+ojluni/src/main/java/java/lang/Exception.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Exception.java
+ojluni/src/main/java/java/lang/ExceptionInInitializerError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ExceptionInInitializerError.java
+ojluni/src/main/java/java/lang/Float.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Float.java
+ojluni/src/main/java/java/lang/FunctionalInterface.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/FunctionalInterface.java
+ojluni/src/main/java/java/lang/IllegalAccessError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IllegalAccessError.java
+ojluni/src/main/java/java/lang/IllegalAccessException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IllegalAccessException.java
+ojluni/src/main/java/java/lang/IllegalArgumentException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IllegalArgumentException.java
+ojluni/src/main/java/java/lang/IllegalCallerException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IllegalCallerException.java
+ojluni/src/main/java/java/lang/IllegalMonitorStateException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IllegalMonitorStateException.java
+ojluni/src/main/java/java/lang/IllegalStateException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IllegalStateException.java
+ojluni/src/main/java/java/lang/IllegalThreadStateException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IllegalThreadStateException.java
+ojluni/src/main/java/java/lang/IncompatibleClassChangeError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IncompatibleClassChangeError.java
+ojluni/src/main/java/java/lang/IndexOutOfBoundsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/IndexOutOfBoundsException.java
+ojluni/src/main/java/java/lang/InheritableThreadLocal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/InheritableThreadLocal.java
+ojluni/src/main/java/java/lang/InstantiationError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/InstantiationError.java
+ojluni/src/main/java/java/lang/InstantiationException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/InstantiationException.java
+ojluni/src/main/java/java/lang/Integer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Integer.java
+ojluni/src/main/java/java/lang/InternalError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/InternalError.java
+ojluni/src/main/java/java/lang/InterruptedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/InterruptedException.java
+ojluni/src/main/java/java/lang/Iterable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Iterable.java
+ojluni/src/main/java/java/lang/LinkageError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/LinkageError.java
+ojluni/src/main/java/java/lang/Long.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Long.java
+ojluni/src/main/java/java/lang/Math.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Math.java
+ojluni/src/main/java/java/lang/NegativeArraySizeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NegativeArraySizeException.java
+ojluni/src/main/java/java/lang/NoClassDefFoundError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NoClassDefFoundError.java
+ojluni/src/main/java/java/lang/NoSuchFieldError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NoSuchFieldError.java
+ojluni/src/main/java/java/lang/NoSuchFieldException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NoSuchFieldException.java
+ojluni/src/main/java/java/lang/NoSuchMethodError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NoSuchMethodError.java
+ojluni/src/main/java/java/lang/NoSuchMethodException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NoSuchMethodException.java
+ojluni/src/main/java/java/lang/NullPointerException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NullPointerException.java
+ojluni/src/main/java/java/lang/Number.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Number.java
+ojluni/src/main/java/java/lang/NumberFormatException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/NumberFormatException.java
+ojluni/src/main/java/java/lang/Object.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/Object.java
+ojluni/src/main/java/java/lang/OutOfMemoryError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/OutOfMemoryError.java
+ojluni/src/main/java/java/lang/Override.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Override.java
+ojluni/src/main/java/java/lang/Package.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/Package.java
+ojluni/src/main/java/java/lang/Process.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/Process.java
+ojluni/src/main/java/java/lang/ProcessBuilder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/ProcessBuilder.java
+ojluni/src/main/java/java/lang/ProcessEnvironment.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/lang/ProcessEnvironment.java
+ojluni/src/main/java/java/lang/ProcessImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/lang/ProcessImpl.java
+ojluni/src/main/java/java/lang/Readable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Readable.java
+ojluni/src/main/java/java/lang/ReflectiveOperationException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ReflectiveOperationException.java
+ojluni/src/main/java/java/lang/Runnable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Runnable.java
+ojluni/src/main/java/java/lang/Runtime.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/Runtime.java
+ojluni/src/main/java/java/lang/RuntimeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/RuntimeException.java
+ojluni/src/main/java/java/lang/RuntimePermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/RuntimePermission.java
+ojluni/src/main/java/java/lang/SafeVarargs.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/SafeVarargs.java
+ojluni/src/main/java/java/lang/SecurityException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/SecurityException.java
+ojluni/src/main/java/java/lang/SecurityManager.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/SecurityManager.java
+ojluni/src/main/java/java/lang/Short.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Short.java
+ojluni/src/main/java/java/lang/StackOverflowError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/StackOverflowError.java
+ojluni/src/main/java/java/lang/StackTraceElement.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/StackTraceElement.java
+ojluni/src/main/java/java/lang/StrictMath.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/StrictMath.java
+ojluni/src/main/java/java/lang/String.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/String.java
+ojluni/src/main/java/java/lang/StringBuffer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/StringBuffer.java
+ojluni/src/main/java/java/lang/StringBuilder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/StringBuilder.java
+ojluni/src/main/java/java/lang/StringIndexOutOfBoundsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/StringIndexOutOfBoundsException.java
+ojluni/src/main/java/java/lang/StringUTF16.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/StringUTF16.java
+ojluni/src/main/java/java/lang/SuppressWarnings.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/SuppressWarnings.java
+ojluni/src/main/java/java/lang/System.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/System.java
+ojluni/src/main/java/java/lang/Thread.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Thread.java
+ojluni/src/main/java/java/lang/ThreadDeath.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ThreadDeath.java
+ojluni/src/main/java/java/lang/ThreadGroup.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/ThreadGroup.java
+ojluni/src/main/java/java/lang/ThreadLocal.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/ThreadLocal.java
+ojluni/src/main/java/java/lang/Throwable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Throwable.java
+ojluni/src/main/java/java/lang/TypeNotPresentException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/TypeNotPresentException.java
+ojluni/src/main/java/java/lang/UNIXProcess.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/lang/UNIXProcess.java
+ojluni/src/main/java/java/lang/UnknownError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/UnknownError.java
+ojluni/src/main/java/java/lang/UnsatisfiedLinkError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/UnsatisfiedLinkError.java
+ojluni/src/main/java/java/lang/UnsupportedClassVersionError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/UnsupportedClassVersionError.java
+ojluni/src/main/java/java/lang/UnsupportedOperationException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/UnsupportedOperationException.java
+ojluni/src/main/java/java/lang/VerifyError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/VerifyError.java
+ojluni/src/main/java/java/lang/VirtualMachineError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/VirtualMachineError.java
+ojluni/src/main/java/java/lang/Void.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/Void.java
+ojluni/src/main/java/java/lang/annotation/Annotation.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/Annotation.java
+ojluni/src/main/java/java/lang/annotation/AnnotationFormatError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/AnnotationFormatError.java
+ojluni/src/main/java/java/lang/annotation/AnnotationTypeMismatchException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/AnnotationTypeMismatchException.java
+ojluni/src/main/java/java/lang/annotation/Documented.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/Documented.java
+ojluni/src/main/java/java/lang/annotation/ElementType.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/ElementType.java
+ojluni/src/main/java/java/lang/annotation/IncompleteAnnotationException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/IncompleteAnnotationException.java
+ojluni/src/main/java/java/lang/annotation/Inherited.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/Inherited.java
+ojluni/src/main/java/java/lang/annotation/Native.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/Native.java
+ojluni/src/main/java/java/lang/annotation/Repeatable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/Repeatable.java
+ojluni/src/main/java/java/lang/annotation/Retention.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/Retention.java
+ojluni/src/main/java/java/lang/annotation/RetentionPolicy.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/RetentionPolicy.java
+ojluni/src/main/java/java/lang/annotation/Target.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/Target.java
+ojluni/src/main/java/java/lang/annotation/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/annotation/package-info.java
+ojluni/src/main/java/java/lang/invoke/CallSite.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/CallSite.java
+ojluni/src/main/java/java/lang/invoke/ConstantCallSite.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java
+ojluni/src/main/java/java/lang/invoke/LambdaConversionException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/LambdaConversionException.java
+ojluni/src/main/java/java/lang/invoke/MethodHandle.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MethodHandle.java
+# java.lang.invoke.MethodHandleImpl in libcore/ doesn't come from the upstream.
+ojluni/src/main/java/java/lang/invoke/MethodHandleInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MethodHandleInfo.java
+ojluni/src/main/java/java/lang/invoke/MethodHandleNatives.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java
+ojluni/src/main/java/java/lang/invoke/MethodHandleStatics.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java
+ojluni/src/main/java/java/lang/invoke/MethodHandles.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MethodHandles.java
+ojluni/src/main/java/java/lang/invoke/MethodType.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MethodType.java
+ojluni/src/main/java/java/lang/invoke/MethodTypeForm.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java
+ojluni/src/main/java/java/lang/invoke/MutableCallSite.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/MutableCallSite.java
+ojluni/src/main/java/java/lang/invoke/Stable.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/Stable.java
+# java.lang.invoke.Transformers isn't in the upstream OpenJDK
+ojluni/src/main/java/java/lang/invoke/VarHandle.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/invoke/VarHandle.java
+ojluni/src/main/java/java/lang/invoke/VolatileCallSite.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/invoke/VolatileCallSite.java
+ojluni/src/main/java/java/lang/invoke/WrongMethodTypeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/invoke/WrongMethodTypeException.java
+ojluni/src/main/java/java/lang/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/package-info.java
+ojluni/src/main/java/java/lang/ref/Cleaner.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ref/Cleaner.java
+ojluni/src/main/java/java/lang/ref/PhantomReference.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ref/PhantomReference.java
+ojluni/src/main/java/java/lang/ref/Reference.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/ref/Reference.java
+ojluni/src/main/java/java/lang/ref/ReferenceQueue.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/ref/ReferenceQueue.java
+ojluni/src/main/java/java/lang/ref/SoftReference.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ref/SoftReference.java
+ojluni/src/main/java/java/lang/ref/WeakReference.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ref/WeakReference.java
+ojluni/src/main/java/java/lang/ref/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/ref/package-info.java
+ojluni/src/main/java/java/lang/reflect/AccessibleObject.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/reflect/AccessibleObject.java
+ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java
+ojluni/src/main/java/java/lang/reflect/Array.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/Array.java
+ojluni/src/main/java/java/lang/reflect/Constructor.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/reflect/Constructor.java
+ojluni/src/main/java/java/lang/reflect/Executable.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/reflect/Executable.java
+ojluni/src/main/java/java/lang/reflect/Field.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/lang/reflect/Field.java
+ojluni/src/main/java/java/lang/reflect/GenericArrayType.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/GenericArrayType.java
+ojluni/src/main/java/java/lang/reflect/GenericDeclaration.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/GenericDeclaration.java
+ojluni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/GenericSignatureFormatError.java
+ojluni/src/main/java/java/lang/reflect/InvocationHandler.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/InvocationHandler.java
+ojluni/src/main/java/java/lang/reflect/InvocationTargetException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java
+ojluni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/MalformedParameterizedTypeException.java
+ojluni/src/main/java/java/lang/reflect/MalformedParametersException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/MalformedParametersException.java
+ojluni/src/main/java/java/lang/reflect/Member.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/Member.java
+ojluni/src/main/java/java/lang/reflect/Method.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/reflect/Method.java
+ojluni/src/main/java/java/lang/reflect/Modifier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/Modifier.java
+ojluni/src/main/java/java/lang/reflect/Parameter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/Parameter.java
+ojluni/src/main/java/java/lang/reflect/ParameterizedType.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/ParameterizedType.java
+ojluni/src/main/java/java/lang/reflect/Proxy.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/reflect/Proxy.java
+ojluni/src/main/java/java/lang/reflect/ReflectPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/ReflectPermission.java
+ojluni/src/main/java/java/lang/reflect/Type.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/Type.java
+ojluni/src/main/java/java/lang/reflect/TypeVariable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/TypeVariable.java
+ojluni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/UndeclaredThrowableException.java
+ojluni/src/main/java/java/lang/reflect/WeakCache.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/reflect/WeakCache.java
+ojluni/src/main/java/java/lang/reflect/WildcardType.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/lang/reflect/WildcardType.java
+ojluni/src/main/java/java/lang/reflect/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/lang/reflect/package-info.java
+ojluni/src/main/java/java/math/BigDecimal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/BigDecimal.java
+ojluni/src/main/java/java/math/BigInteger.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/BigInteger.java
+ojluni/src/main/java/java/math/BitSieve.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/BitSieve.java
+ojluni/src/main/java/java/math/MathContext.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/MathContext.java
+ojluni/src/main/java/java/math/MutableBigInteger.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/MutableBigInteger.java
+ojluni/src/main/java/java/math/RoundingMode.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/RoundingMode.java
+ojluni/src/main/java/java/math/SignedMutableBigInteger.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/SignedMutableBigInteger.java
+ojluni/src/main/java/java/math/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/math/package-info.java
+ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
+ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java
+ojluni/src/main/java/java/net/Authenticator.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/Authenticator.java
+ojluni/src/main/java/java/net/BindException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/BindException.java
+ojluni/src/main/java/java/net/CacheRequest.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/CacheRequest.java
+ojluni/src/main/java/java/net/CacheResponse.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/CacheResponse.java
+ojluni/src/main/java/java/net/ConnectException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/ConnectException.java
+ojluni/src/main/java/java/net/ContentHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/ContentHandler.java
+ojluni/src/main/java/java/net/ContentHandlerFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/ContentHandlerFactory.java
+ojluni/src/main/java/java/net/CookieHandler.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/CookieHandler.java
+ojluni/src/main/java/java/net/CookieManager.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/CookieManager.java
+ojluni/src/main/java/java/net/CookiePolicy.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/CookiePolicy.java
+ojluni/src/main/java/java/net/CookieStore.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/CookieStore.java
+ojluni/src/main/java/java/net/DatagramPacket.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/DatagramPacket.java
+ojluni/src/main/java/java/net/DatagramSocket.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/DatagramSocket.java
+ojluni/src/main/java/java/net/DatagramSocketImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/DatagramSocketImpl.java
+ojluni/src/main/java/java/net/DatagramSocketImplFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/DatagramSocketImplFactory.java
+ojluni/src/main/java/java/net/DefaultDatagramSocketImplFactory.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/net/DefaultDatagramSocketImplFactory.java
+ojluni/src/main/java/java/net/DefaultInterface.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/java/net/DefaultInterface.java
+ojluni/src/main/java/java/net/FileNameMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/FileNameMap.java
+ojluni/src/main/java/java/net/HttpCookie.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/HttpCookie.java
+ojluni/src/main/java/java/net/HttpRetryException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/HttpRetryException.java
+ojluni/src/main/java/java/net/HttpURLConnection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/HttpURLConnection.java
+ojluni/src/main/java/java/net/IDN.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/IDN.java
+ojluni/src/main/java/java/net/InMemoryCookieStore.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/InMemoryCookieStore.java
+ojluni/src/main/java/java/net/Inet4Address.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/Inet4Address.java
+ojluni/src/main/java/java/net/Inet6Address.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/Inet6Address.java
+ojluni/src/main/java/java/net/Inet6AddressImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/Inet6AddressImpl.java
+ojluni/src/main/java/java/net/InetAddress.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/InetAddress.java
+ojluni/src/main/java/java/net/InetAddressContainer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/InetAddressContainer.java
+ojluni/src/main/java/java/net/InetAddressImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/InetAddressImpl.java
+ojluni/src/main/java/java/net/InetSocketAddress.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/InetSocketAddress.java
+ojluni/src/main/java/java/net/InterfaceAddress.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/InterfaceAddress.java
+ojluni/src/main/java/java/net/JarURLConnection.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/JarURLConnection.java
+ojluni/src/main/java/java/net/MalformedURLException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/MalformedURLException.java
+ojluni/src/main/java/java/net/MulticastSocket.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/MulticastSocket.java
+ojluni/src/main/java/java/net/NetPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/NetPermission.java
+ojluni/src/main/java/java/net/NetworkInterface.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/NetworkInterface.java
+ojluni/src/main/java/java/net/NoRouteToHostException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/NoRouteToHostException.java
+ojluni/src/main/java/java/net/PasswordAuthentication.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/PasswordAuthentication.java
+ojluni/src/main/java/java/net/PlainDatagramSocketImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/net/PlainDatagramSocketImpl.java
+ojluni/src/main/java/java/net/PlainSocketImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/net/PlainSocketImpl.java
+ojluni/src/main/java/java/net/PortUnreachableException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/PortUnreachableException.java
+ojluni/src/main/java/java/net/ProtocolException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/ProtocolException.java
+ojluni/src/main/java/java/net/ProtocolFamily.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/ProtocolFamily.java
+ojluni/src/main/java/java/net/Proxy.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/Proxy.java
+ojluni/src/main/java/java/net/ProxySelector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/ProxySelector.java
+ojluni/src/main/java/java/net/ResponseCache.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/ResponseCache.java
+ojluni/src/main/java/java/net/SecureCacheResponse.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SecureCacheResponse.java
+ojluni/src/main/java/java/net/ServerSocket.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/ServerSocket.java
+ojluni/src/main/java/java/net/Socket.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/Socket.java
+ojluni/src/main/java/java/net/SocketAddress.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketAddress.java
+ojluni/src/main/java/java/net/SocketException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketException.java
+ojluni/src/main/java/java/net/SocketImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketImpl.java
+ojluni/src/main/java/java/net/SocketImplFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketImplFactory.java
+ojluni/src/main/java/java/net/SocketInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketInputStream.java
+ojluni/src/main/java/java/net/SocketOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketOption.java
+ojluni/src/main/java/java/net/SocketOptions.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketOptions.java
+ojluni/src/main/java/java/net/SocketOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketOutputStream.java
+ojluni/src/main/java/java/net/SocketPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketPermission.java
+ojluni/src/main/java/java/net/SocketSecrets.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/SocketSecrets.java
+ojluni/src/main/java/java/net/SocketTimeoutException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocketTimeoutException.java
+ojluni/src/main/java/java/net/SocksConsts.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/SocksConsts.java
+ojluni/src/main/java/java/net/SocksSocketImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/SocksSocketImpl.java
+ojluni/src/main/java/java/net/StandardProtocolFamily.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/StandardProtocolFamily.java
+ojluni/src/main/java/java/net/StandardSocketOptions.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/StandardSocketOptions.java
+ojluni/src/main/java/java/net/URI.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/URI.java
+ojluni/src/main/java/java/net/URISyntaxException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/URISyntaxException.java
+ojluni/src/main/java/java/net/URL.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/URL.java
+ojluni/src/main/java/java/net/URLClassLoader.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/URLClassLoader.java
+ojluni/src/main/java/java/net/URLConnection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/URLConnection.java
+ojluni/src/main/java/java/net/URLDecoder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/URLDecoder.java
+ojluni/src/main/java/java/net/URLEncoder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/URLEncoder.java
+ojluni/src/main/java/java/net/URLStreamHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/URLStreamHandler.java
+ojluni/src/main/java/java/net/URLStreamHandlerFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/URLStreamHandlerFactory.java
+ojluni/src/main/java/java/net/UnknownHostException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/UnknownHostException.java
+ojluni/src/main/java/java/net/UnknownServiceException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/net/UnknownServiceException.java
+ojluni/src/main/java/java/net/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/net/package-info.java
+# Some java.nio Buffer and Exception classes are generated from templates, and thus has no direct mapping to an upstream file.
+ojluni/src/main/java/java/nio/Bits.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/Bits.java
+ojluni/src/main/java/java/nio/Buffer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/Buffer.java
+ojluni/src/main/java/java/nio/ByteOrder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/ByteOrder.java
+ojluni/src/main/java/java/nio/CharBufferSpliterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/CharBufferSpliterator.java
+ojluni/src/main/java/java/nio/MappedByteBuffer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/MappedByteBuffer.java
+ojluni/src/main/java/java/nio/StringCharBuffer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/StringCharBuffer.java
+ojluni/src/main/java/java/nio/channels/AsynchronousByteChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/AsynchronousByteChannel.java
+ojluni/src/main/java/java/nio/channels/AsynchronousChannel.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/AsynchronousChannel.java
+ojluni/src/main/java/java/nio/channels/AsynchronousChannelGroup.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/AsynchronousChannelGroup.java
+ojluni/src/main/java/java/nio/channels/AsynchronousFileChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/AsynchronousFileChannel.java
+ojluni/src/main/java/java/nio/channels/AsynchronousServerSocketChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java
+ojluni/src/main/java/java/nio/channels/AsynchronousSocketChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java
+ojluni/src/main/java/java/nio/channels/ByteChannel.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/ByteChannel.java
+ojluni/src/main/java/java/nio/channels/Channel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/Channel.java
+ojluni/src/main/java/java/nio/channels/Channels.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/Channels.java
+ojluni/src/main/java/java/nio/channels/CompletionHandler.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/CompletionHandler.java
+ojluni/src/main/java/java/nio/channels/DatagramChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/DatagramChannel.java
+ojluni/src/main/java/java/nio/channels/FileChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/FileChannel.java
+ojluni/src/main/java/java/nio/channels/FileLock.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/FileLock.java
+ojluni/src/main/java/java/nio/channels/GatheringByteChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/GatheringByteChannel.java
+ojluni/src/main/java/java/nio/channels/InterruptibleChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/InterruptibleChannel.java
+ojluni/src/main/java/java/nio/channels/MembershipKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/MembershipKey.java
+ojluni/src/main/java/java/nio/channels/MulticastChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/MulticastChannel.java
+ojluni/src/main/java/java/nio/channels/NetworkChannel.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/NetworkChannel.java
+ojluni/src/main/java/java/nio/channels/Pipe.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/Pipe.java
+ojluni/src/main/java/java/nio/channels/ReadableByteChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/ReadableByteChannel.java
+ojluni/src/main/java/java/nio/channels/ScatteringByteChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/ScatteringByteChannel.java
+ojluni/src/main/java/java/nio/channels/SeekableByteChannel.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/SeekableByteChannel.java
+ojluni/src/main/java/java/nio/channels/SelectableChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/SelectableChannel.java
+ojluni/src/main/java/java/nio/channels/SelectionKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/SelectionKey.java
+ojluni/src/main/java/java/nio/channels/Selector.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/Selector.java
+ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/ServerSocketChannel.java
+ojluni/src/main/java/java/nio/channels/SocketChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/SocketChannel.java
+ojluni/src/main/java/java/nio/channels/WritableByteChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/WritableByteChannel.java
+ojluni/src/main/java/java/nio/channels/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/package-info.java
+ojluni/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java
+ojluni/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java
+ojluni/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/spi/AbstractSelectionKey.java
+ojluni/src/main/java/java/nio/channels/spi/AbstractSelector.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java
+ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java
+ojluni/src/main/java/java/nio/channels/spi/SelectorProvider.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java
+ojluni/src/main/java/java/nio/charset/Charset.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/charset/Charset.java
+ojluni/src/main/java/java/nio/charset/CoderMalfunctionError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/charset/CoderMalfunctionError.java
+ojluni/src/main/java/java/nio/charset/CoderResult.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/charset/CoderResult.java
+ojluni/src/main/java/java/nio/charset/CodingErrorAction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/charset/CodingErrorAction.java
+ojluni/src/main/java/java/nio/charset/MalformedInputException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/charset/MalformedInputException.java
+ojluni/src/main/java/java/nio/charset/StandardCharsets.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/charset/StandardCharsets.java
+ojluni/src/main/java/java/nio/charset/UnmappableCharacterException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/charset/UnmappableCharacterException.java
+ojluni/src/main/java/java/nio/charset/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/charset/package-info.java
+ojluni/src/main/java/java/nio/charset/spi/CharsetProvider.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/charset/spi/CharsetProvider.java
+ojluni/src/main/java/java/nio/file/AccessDeniedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/AccessDeniedException.java
+ojluni/src/main/java/java/nio/file/AccessMode.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/AccessMode.java
+ojluni/src/main/java/java/nio/file/AtomicMoveNotSupportedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/AtomicMoveNotSupportedException.java
+ojluni/src/main/java/java/nio/file/ClosedDirectoryStreamException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/ClosedDirectoryStreamException.java
+ojluni/src/main/java/java/nio/file/ClosedFileSystemException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/ClosedFileSystemException.java
+ojluni/src/main/java/java/nio/file/ClosedWatchServiceException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/ClosedWatchServiceException.java
+ojluni/src/main/java/java/nio/file/CopyMoveHelper.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/CopyMoveHelper.java
+ojluni/src/main/java/java/nio/file/CopyOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/CopyOption.java
+ojluni/src/main/java/java/nio/file/DirectoryIteratorException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/DirectoryIteratorException.java
+ojluni/src/main/java/java/nio/file/DirectoryNotEmptyException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/DirectoryNotEmptyException.java
+ojluni/src/main/java/java/nio/file/DirectoryStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/DirectoryStream.java
+ojluni/src/main/java/java/nio/file/FileAlreadyExistsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileAlreadyExistsException.java
+ojluni/src/main/java/java/nio/file/FileStore.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/FileStore.java
+ojluni/src/main/java/java/nio/file/FileSystem.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileSystem.java
+ojluni/src/main/java/java/nio/file/FileSystemAlreadyExistsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileSystemAlreadyExistsException.java
+ojluni/src/main/java/java/nio/file/FileSystemException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileSystemException.java
+ojluni/src/main/java/java/nio/file/FileSystemLoopException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileSystemLoopException.java
+ojluni/src/main/java/java/nio/file/FileSystemNotFoundException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileSystemNotFoundException.java
+ojluni/src/main/java/java/nio/file/FileSystems.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/FileSystems.java
+ojluni/src/main/java/java/nio/file/FileTreeIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileTreeIterator.java
+ojluni/src/main/java/java/nio/file/FileTreeWalker.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileTreeWalker.java
+ojluni/src/main/java/java/nio/file/FileVisitOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileVisitOption.java
+ojluni/src/main/java/java/nio/file/FileVisitResult.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileVisitResult.java
+ojluni/src/main/java/java/nio/file/FileVisitor.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/FileVisitor.java
+ojluni/src/main/java/java/nio/file/Files.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/Files.java
+ojluni/src/main/java/java/nio/file/InvalidPathException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/InvalidPathException.java
+ojluni/src/main/java/java/nio/file/LinkOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/LinkOption.java
+ojluni/src/main/java/java/nio/file/LinkPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/LinkPermission.java
+ojluni/src/main/java/java/nio/file/NoSuchFileException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/NoSuchFileException.java
+ojluni/src/main/java/java/nio/file/NotDirectoryException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/NotDirectoryException.java
+ojluni/src/main/java/java/nio/file/NotLinkException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/NotLinkException.java
+ojluni/src/main/java/java/nio/file/OpenOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/OpenOption.java
+ojluni/src/main/java/java/nio/file/Path.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/Path.java
+ojluni/src/main/java/java/nio/file/PathMatcher.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/PathMatcher.java
+ojluni/src/main/java/java/nio/file/Paths.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/Paths.java
+ojluni/src/main/java/java/nio/file/ProviderMismatchException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/ProviderMismatchException.java
+ojluni/src/main/java/java/nio/file/ProviderNotFoundException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/ProviderNotFoundException.java
+ojluni/src/main/java/java/nio/file/ReadOnlyFileSystemException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/ReadOnlyFileSystemException.java
+ojluni/src/main/java/java/nio/file/SecureDirectoryStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/SecureDirectoryStream.java
+ojluni/src/main/java/java/nio/file/SimpleFileVisitor.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/SimpleFileVisitor.java
+ojluni/src/main/java/java/nio/file/StandardCopyOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/StandardCopyOption.java
+ojluni/src/main/java/java/nio/file/StandardOpenOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/StandardOpenOption.java
+ojluni/src/main/java/java/nio/file/StandardWatchEventKinds.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/StandardWatchEventKinds.java
+ojluni/src/main/java/java/nio/file/TempFileHelper.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/TempFileHelper.java
+ojluni/src/main/java/java/nio/file/WatchEvent.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/WatchEvent.java
+ojluni/src/main/java/java/nio/file/WatchKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/WatchKey.java
+ojluni/src/main/java/java/nio/file/WatchService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/WatchService.java
+ojluni/src/main/java/java/nio/file/Watchable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/Watchable.java
+ojluni/src/main/java/java/nio/file/attribute/AclEntry.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/AclEntry.java
+ojluni/src/main/java/java/nio/file/attribute/AclEntryFlag.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/AclEntryFlag.java
+ojluni/src/main/java/java/nio/file/attribute/AclEntryPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/AclEntryPermission.java
+ojluni/src/main/java/java/nio/file/attribute/AclEntryType.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/AclEntryType.java
+ojluni/src/main/java/java/nio/file/attribute/AclFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/AclFileAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/AttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/AttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/BasicFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/BasicFileAttributes.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributes.java
+ojluni/src/main/java/java/nio/file/attribute/DosFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/DosFileAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/DosFileAttributes.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/DosFileAttributes.java
+ojluni/src/main/java/java/nio/file/attribute/FileAttribute.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/FileAttribute.java
+ojluni/src/main/java/java/nio/file/attribute/FileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/FileAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/FileOwnerAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/FileOwnerAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/FileStoreAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/FileStoreAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/FileTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/FileTime.java
+ojluni/src/main/java/java/nio/file/attribute/GroupPrincipal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/GroupPrincipal.java
+ojluni/src/main/java/java/nio/file/attribute/PosixFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/PosixFileAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/PosixFileAttributes.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/PosixFileAttributes.java
+ojluni/src/main/java/java/nio/file/attribute/PosixFilePermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/PosixFilePermission.java
+ojluni/src/main/java/java/nio/file/attribute/PosixFilePermissions.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/PosixFilePermissions.java
+ojluni/src/main/java/java/nio/file/attribute/UserDefinedFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/UserDefinedFileAttributeView.java
+ojluni/src/main/java/java/nio/file/attribute/UserPrincipal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/UserPrincipal.java
+ojluni/src/main/java/java/nio/file/attribute/UserPrincipalLookupService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/UserPrincipalLookupService.java
+ojluni/src/main/java/java/nio/file/attribute/UserPrincipalNotFoundException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/file/attribute/UserPrincipalNotFoundException.java
+ojluni/src/main/java/java/nio/file/spi/FileSystemProvider.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/spi/FileSystemProvider.java
+ojluni/src/main/java/java/nio/file/spi/FileTypeDetector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/nio/file/spi/FileTypeDetector.java
+ojluni/src/main/java/java/nio/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/nio/package-info.java
+ojluni/src/main/java/java/security/AccessControlContext.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/AccessControlContext.java
+ojluni/src/main/java/java/security/AccessControlException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/AccessControlException.java
+ojluni/src/main/java/java/security/AccessController.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/AccessController.java
+ojluni/src/main/java/java/security/AlgorithmConstraints.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/AlgorithmConstraints.java
+ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/AlgorithmParameterGenerator.java
+ojluni/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/AlgorithmParameterGeneratorSpi.java
+ojluni/src/main/java/java/security/AlgorithmParameters.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/AlgorithmParameters.java
+ojluni/src/main/java/java/security/AlgorithmParametersSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/AlgorithmParametersSpi.java
+ojluni/src/main/java/java/security/AllPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/AllPermission.java
+ojluni/src/main/java/java/security/AuthProvider.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/AuthProvider.java
+ojluni/src/main/java/java/security/BasicPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/BasicPermission.java
+ojluni/src/main/java/java/security/Certificate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/Certificate.java
+ojluni/src/main/java/java/security/CodeSigner.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/CodeSigner.java
+ojluni/src/main/java/java/security/CodeSource.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/CodeSource.java
+ojluni/src/main/java/java/security/CryptoPrimitive.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/CryptoPrimitive.java
+ojluni/src/main/java/java/security/DigestException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/DigestException.java
+ojluni/src/main/java/java/security/DigestInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/DigestInputStream.java
+ojluni/src/main/java/java/security/DigestOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/DigestOutputStream.java
+ojluni/src/main/java/java/security/DomainCombiner.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/DomainCombiner.java
+ojluni/src/main/java/java/security/DomainLoadStoreParameter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/DomainLoadStoreParameter.java
+ojluni/src/main/java/java/security/GeneralSecurityException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/GeneralSecurityException.java
+ojluni/src/main/java/java/security/Guard.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/Guard.java
+ojluni/src/main/java/java/security/GuardedObject.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/GuardedObject.java
+ojluni/src/main/java/java/security/Identity.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/Identity.java
+ojluni/src/main/java/java/security/IdentityScope.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/IdentityScope.java
+ojluni/src/main/java/java/security/InvalidAlgorithmParameterException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/InvalidAlgorithmParameterException.java
+ojluni/src/main/java/java/security/InvalidKeyException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/InvalidKeyException.java
+ojluni/src/main/java/java/security/InvalidParameterException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/InvalidParameterException.java
+ojluni/src/main/java/java/security/Key.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/Key.java
+ojluni/src/main/java/java/security/KeyException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyException.java
+ojluni/src/main/java/java/security/KeyFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/KeyFactory.java
+ojluni/src/main/java/java/security/KeyFactorySpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyFactorySpi.java
+ojluni/src/main/java/java/security/KeyManagementException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyManagementException.java
+ojluni/src/main/java/java/security/KeyPair.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyPair.java
+ojluni/src/main/java/java/security/KeyPairGenerator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyPairGenerator.java
+ojluni/src/main/java/java/security/KeyPairGeneratorSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyPairGeneratorSpi.java
+ojluni/src/main/java/java/security/KeyRep.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyRep.java
+ojluni/src/main/java/java/security/KeyStore.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyStore.java
+ojluni/src/main/java/java/security/KeyStoreException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyStoreException.java
+ojluni/src/main/java/java/security/KeyStoreSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/KeyStoreSpi.java
+ojluni/src/main/java/java/security/MessageDigest.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/MessageDigest.java
+ojluni/src/main/java/java/security/MessageDigestSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/MessageDigestSpi.java
+ojluni/src/main/java/java/security/NoSuchAlgorithmException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/NoSuchAlgorithmException.java
+ojluni/src/main/java/java/security/NoSuchProviderException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/NoSuchProviderException.java
+ojluni/src/main/java/java/security/PKCS12Attribute.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/PKCS12Attribute.java
+ojluni/src/main/java/java/security/Permission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/Permission.java
+ojluni/src/main/java/java/security/PermissionCollection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/PermissionCollection.java
+ojluni/src/main/java/java/security/Permissions.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/Permissions.java
+ojluni/src/main/java/java/security/Policy.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/Policy.java
+ojluni/src/main/java/java/security/PolicySpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/PolicySpi.java
+ojluni/src/main/java/java/security/Principal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/Principal.java
+ojluni/src/main/java/java/security/PrivateKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/PrivateKey.java
+ojluni/src/main/java/java/security/PrivilegedAction.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/PrivilegedAction.java
+ojluni/src/main/java/java/security/PrivilegedActionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/PrivilegedActionException.java
+ojluni/src/main/java/java/security/PrivilegedExceptionAction.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/PrivilegedExceptionAction.java
+ojluni/src/main/java/java/security/ProtectionDomain.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/ProtectionDomain.java
+ojluni/src/main/java/java/security/Provider.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/Provider.java
+ojluni/src/main/java/java/security/ProviderException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/ProviderException.java
+ojluni/src/main/java/java/security/PublicKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/PublicKey.java
+ojluni/src/main/java/java/security/SecureClassLoader.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/SecureClassLoader.java
+ojluni/src/main/java/java/security/SecureRandom.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/SecureRandom.java
+ojluni/src/main/java/java/security/SecureRandomSpi.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/SecureRandomSpi.java
+ojluni/src/main/java/java/security/Security.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/Security.java
+ojluni/src/main/java/java/security/SecurityPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/SecurityPermission.java
+ojluni/src/main/java/java/security/Signature.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/Signature.java
+ojluni/src/main/java/java/security/SignatureException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/SignatureException.java
+ojluni/src/main/java/java/security/SignatureSpi.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/SignatureSpi.java
+ojluni/src/main/java/java/security/SignedObject.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/SignedObject.java
+ojluni/src/main/java/java/security/Signer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/Signer.java
+ojluni/src/main/java/java/security/Timestamp.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/Timestamp.java
+ojluni/src/main/java/java/security/UnrecoverableEntryException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/UnrecoverableEntryException.java
+ojluni/src/main/java/java/security/UnrecoverableKeyException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/UnrecoverableKeyException.java
+ojluni/src/main/java/java/security/UnresolvedPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/UnresolvedPermission.java
+ojluni/src/main/java/java/security/UnresolvedPermissionCollection.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java
+ojluni/src/main/java/java/security/acl/Acl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/Acl.java
+ojluni/src/main/java/java/security/acl/AclEntry.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/AclEntry.java
+ojluni/src/main/java/java/security/acl/AclNotFoundException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/AclNotFoundException.java
+ojluni/src/main/java/java/security/acl/Group.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/Group.java
+ojluni/src/main/java/java/security/acl/LastOwnerException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/LastOwnerException.java
+ojluni/src/main/java/java/security/acl/NotOwnerException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/NotOwnerException.java
+ojluni/src/main/java/java/security/acl/Owner.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/Owner.java
+ojluni/src/main/java/java/security/acl/Permission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/acl/Permission.java
+ojluni/src/main/java/java/security/acl/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/acl/package-info.java
+ojluni/src/main/java/java/security/cert/CRL.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CRL.java
+ojluni/src/main/java/java/security/cert/CRLException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CRLException.java
+ojluni/src/main/java/java/security/cert/CRLReason.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CRLReason.java
+ojluni/src/main/java/java/security/cert/CRLSelector.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CRLSelector.java
+ojluni/src/main/java/java/security/cert/CertPath.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertPath.java
+ojluni/src/main/java/java/security/cert/CertPathBuilder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertPathBuilder.java
+ojluni/src/main/java/java/security/cert/CertPathBuilderException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathBuilderException.java
+ojluni/src/main/java/java/security/cert/CertPathBuilderResult.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathBuilderResult.java
+ojluni/src/main/java/java/security/cert/CertPathBuilderSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathBuilderSpi.java
+ojluni/src/main/java/java/security/cert/CertPathChecker.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathChecker.java
+ojluni/src/main/java/java/security/cert/CertPathHelperImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertPathHelperImpl.java
+ojluni/src/main/java/java/security/cert/CertPathParameters.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathParameters.java
+ojluni/src/main/java/java/security/cert/CertPathValidator.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertPathValidator.java
+ojluni/src/main/java/java/security/cert/CertPathValidatorException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathValidatorException.java
+ojluni/src/main/java/java/security/cert/CertPathValidatorResult.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathValidatorResult.java
+ojluni/src/main/java/java/security/cert/CertPathValidatorSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertPathValidatorSpi.java
+ojluni/src/main/java/java/security/cert/CertSelector.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertSelector.java
+ojluni/src/main/java/java/security/cert/CertStore.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertStore.java
+ojluni/src/main/java/java/security/cert/CertStoreException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertStoreException.java
+ojluni/src/main/java/java/security/cert/CertStoreParameters.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertStoreParameters.java
+ojluni/src/main/java/java/security/cert/CertStoreSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/CertStoreSpi.java
+ojluni/src/main/java/java/security/cert/Certificate.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/Certificate.java
+ojluni/src/main/java/java/security/cert/CertificateEncodingException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateEncodingException.java
+ojluni/src/main/java/java/security/cert/CertificateException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateException.java
+ojluni/src/main/java/java/security/cert/CertificateExpiredException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateExpiredException.java
+ojluni/src/main/java/java/security/cert/CertificateFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateFactory.java
+ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateFactorySpi.java
+ojluni/src/main/java/java/security/cert/CertificateNotYetValidException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateNotYetValidException.java
+ojluni/src/main/java/java/security/cert/CertificateParsingException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateParsingException.java
+ojluni/src/main/java/java/security/cert/CertificateRevokedException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CertificateRevokedException.java
+ojluni/src/main/java/java/security/cert/CollectionCertStoreParameters.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/CollectionCertStoreParameters.java
+ojluni/src/main/java/java/security/cert/Extension.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/Extension.java
+ojluni/src/main/java/java/security/cert/LDAPCertStoreParameters.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/LDAPCertStoreParameters.java
+ojluni/src/main/java/java/security/cert/PKIXBuilderParameters.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/PKIXBuilderParameters.java
+ojluni/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/PKIXCertPathBuilderResult.java
+ojluni/src/main/java/java/security/cert/PKIXCertPathChecker.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/PKIXCertPathChecker.java
+ojluni/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/PKIXCertPathValidatorResult.java
+ojluni/src/main/java/java/security/cert/PKIXParameters.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/PKIXParameters.java
+ojluni/src/main/java/java/security/cert/PKIXReason.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/PKIXReason.java
+ojluni/src/main/java/java/security/cert/PKIXRevocationChecker.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java
+ojluni/src/main/java/java/security/cert/PolicyNode.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/PolicyNode.java
+ojluni/src/main/java/java/security/cert/PolicyQualifierInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/PolicyQualifierInfo.java
+ojluni/src/main/java/java/security/cert/TrustAnchor.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/TrustAnchor.java
+ojluni/src/main/java/java/security/cert/URICertStoreParameters.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/cert/URICertStoreParameters.java
+ojluni/src/main/java/java/security/cert/X509CRL.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/X509CRL.java
+ojluni/src/main/java/java/security/cert/X509CRLEntry.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/X509CRLEntry.java
+ojluni/src/main/java/java/security/cert/X509CRLSelector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/X509CRLSelector.java
+ojluni/src/main/java/java/security/cert/X509CertSelector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/X509CertSelector.java
+ojluni/src/main/java/java/security/cert/X509Certificate.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/X509Certificate.java
+ojluni/src/main/java/java/security/cert/X509Extension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/X509Extension.java
+ojluni/src/main/java/java/security/cert/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/cert/package-info.java
+ojluni/src/main/java/java/security/interfaces/DSAKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/DSAKey.java
+ojluni/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/DSAKeyPairGenerator.java
+ojluni/src/main/java/java/security/interfaces/DSAParams.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/DSAParams.java
+ojluni/src/main/java/java/security/interfaces/DSAPrivateKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/DSAPrivateKey.java
+ojluni/src/main/java/java/security/interfaces/DSAPublicKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/DSAPublicKey.java
+ojluni/src/main/java/java/security/interfaces/ECKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/ECKey.java
+ojluni/src/main/java/java/security/interfaces/ECPrivateKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/ECPrivateKey.java
+ojluni/src/main/java/java/security/interfaces/ECPublicKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/ECPublicKey.java
+ojluni/src/main/java/java/security/interfaces/EdECKey.java,jdk17u/jdk-17.0.2-ga,src/java.base/share/classes/java/security/interfaces/EdECKey.java
+ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java,jdk17u/jdk-17.0.2-ga,src/java.base/share/classes/java/security/interfaces/EdECPrivateKey.java
+ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java,jdk17u/jdk-17.0.2-ga,src/java.base/share/classes/java/security/interfaces/EdECPublicKey.java
+ojluni/src/main/java/java/security/interfaces/RSAKey.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/interfaces/RSAKey.java
+ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
+ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/RSAPrivateCrtKey.java
+ojluni/src/main/java/java/security/interfaces/RSAPrivateKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/RSAPrivateKey.java
+ojluni/src/main/java/java/security/interfaces/RSAPublicKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/RSAPublicKey.java
+ojluni/src/main/java/java/security/interfaces/XECKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/XECKey.java
+ojluni/src/main/java/java/security/interfaces/XECPrivateKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/XECPrivateKey.java
+ojluni/src/main/java/java/security/interfaces/XECPublicKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/interfaces/XECPublicKey.java
+ojluni/src/main/java/java/security/interfaces/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/interfaces/package-info.java
+ojluni/src/main/java/java/security/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/package-info.java
+ojluni/src/main/java/java/security/spec/AlgorithmParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/AlgorithmParameterSpec.java
+ojluni/src/main/java/java/security/spec/DSAParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/DSAParameterSpec.java
+ojluni/src/main/java/java/security/spec/DSAPrivateKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/DSAPrivateKeySpec.java
+ojluni/src/main/java/java/security/spec/DSAPublicKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/DSAPublicKeySpec.java
+ojluni/src/main/java/java/security/spec/ECField.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECField.java
+ojluni/src/main/java/java/security/spec/ECFieldF2m.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECFieldF2m.java
+ojluni/src/main/java/java/security/spec/ECFieldFp.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECFieldFp.java
+ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECGenParameterSpec.java
+ojluni/src/main/java/java/security/spec/ECParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECParameterSpec.java
+ojluni/src/main/java/java/security/spec/ECPoint.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECPoint.java
+ojluni/src/main/java/java/security/spec/ECPrivateKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECPrivateKeySpec.java
+ojluni/src/main/java/java/security/spec/ECPublicKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/ECPublicKeySpec.java
+ojluni/src/main/java/java/security/spec/EdECPoint.java,jdk17u/jdk-17.0.2-ga,src/java.base/share/classes/java/security/spec/EdECPoint.java
+ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java,jdk17u/jdk-17.0.2-ga,src/java.base/share/classes/java/security/spec/EdECPrivateKeySpec.java
+ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java,jdk17u/jdk-17.0.2-ga,src/java.base/share/classes/java/security/spec/EdECPublicKeySpec.java
+ojluni/src/main/java/java/security/spec/EllipticCurve.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/EllipticCurve.java
+ojluni/src/main/java/java/security/spec/EncodedKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/EncodedKeySpec.java
+ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/InvalidKeySpecException.java
+ojluni/src/main/java/java/security/spec/InvalidParameterSpecException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/InvalidParameterSpecException.java
+ojluni/src/main/java/java/security/spec/KeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/KeySpec.java
+ojluni/src/main/java/java/security/spec/MGF1ParameterSpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/MGF1ParameterSpec.java
+ojluni/src/main/java/java/security/spec/NamedParameterSpec.java,jdk17u/jdk-17.0.2-ga,src/java.base/share/classes/java/security/spec/NamedParameterSpec.java
+ojluni/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/PKCS8EncodedKeySpec.java
+ojluni/src/main/java/java/security/spec/PSSParameterSpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/PSSParameterSpec.java
+ojluni/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/RSAKeyGenParameterSpec.java
+ojluni/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
+ojluni/src/main/java/java/security/spec/RSAOtherPrimeInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/RSAOtherPrimeInfo.java
+ojluni/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/RSAPrivateCrtKeySpec.java
+ojluni/src/main/java/java/security/spec/RSAPrivateKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/RSAPrivateKeySpec.java
+ojluni/src/main/java/java/security/spec/RSAPublicKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/RSAPublicKeySpec.java
+ojluni/src/main/java/java/security/spec/X509EncodedKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/X509EncodedKeySpec.java
+ojluni/src/main/java/java/security/spec/XECPrivateKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/XECPrivateKeySpec.java
+ojluni/src/main/java/java/security/spec/XECPublicKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/security/spec/XECPublicKeySpec.java
+ojluni/src/main/java/java/security/spec/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/security/spec/package-info.java
+ojluni/src/main/java/java/sql/Array.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Array.java
+ojluni/src/main/java/java/sql/BatchUpdateException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/BatchUpdateException.java
+ojluni/src/main/java/java/sql/Blob.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Blob.java
+ojluni/src/main/java/java/sql/CallableStatement.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/CallableStatement.java
+ojluni/src/main/java/java/sql/ClientInfoStatus.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/java/sql/ClientInfoStatus.java
+ojluni/src/main/java/java/sql/Clob.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Clob.java
+ojluni/src/main/java/java/sql/Connection.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Connection.java
+ojluni/src/main/java/java/sql/DataTruncation.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/DataTruncation.java
+ojluni/src/main/java/java/sql/DatabaseMetaData.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/DatabaseMetaData.java
+ojluni/src/main/java/java/sql/Date.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Date.java
+ojluni/src/main/java/java/sql/Driver.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Driver.java
+ojluni/src/main/java/java/sql/DriverManager.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/DriverManager.java
+ojluni/src/main/java/java/sql/DriverPropertyInfo.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/DriverPropertyInfo.java
+ojluni/src/main/java/java/sql/NClob.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/NClob.java
+ojluni/src/main/java/java/sql/ParameterMetaData.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/java/sql/ParameterMetaData.java
+ojluni/src/main/java/java/sql/PreparedStatement.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/PreparedStatement.java
+ojluni/src/main/java/java/sql/Ref.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/java/sql/Ref.java
+ojluni/src/main/java/java/sql/ResultSet.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/ResultSet.java
+ojluni/src/main/java/java/sql/ResultSetMetaData.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/ResultSetMetaData.java
+ojluni/src/main/java/java/sql/RowId.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/java/sql/RowId.java
+ojluni/src/main/java/java/sql/RowIdLifetime.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/java/sql/RowIdLifetime.java
+ojluni/src/main/java/java/sql/SQLClientInfoException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLClientInfoException.java
+ojluni/src/main/java/java/sql/SQLData.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/java/sql/SQLData.java
+ojluni/src/main/java/java/sql/SQLDataException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLDataException.java
+ojluni/src/main/java/java/sql/SQLException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLException.java
+ojluni/src/main/java/java/sql/SQLFeatureNotSupportedException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLFeatureNotSupportedException.java
+ojluni/src/main/java/java/sql/SQLInput.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLInput.java
+ojluni/src/main/java/java/sql/SQLIntegrityConstraintViolationException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLIntegrityConstraintViolationException.java
+ojluni/src/main/java/java/sql/SQLInvalidAuthorizationSpecException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLInvalidAuthorizationSpecException.java
+ojluni/src/main/java/java/sql/SQLNonTransientConnectionException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLNonTransientConnectionException.java
+ojluni/src/main/java/java/sql/SQLNonTransientException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLNonTransientException.java
+ojluni/src/main/java/java/sql/SQLOutput.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLOutput.java
+ojluni/src/main/java/java/sql/SQLPermission.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLPermission.java
+ojluni/src/main/java/java/sql/SQLRecoverableException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLRecoverableException.java
+ojluni/src/main/java/java/sql/SQLSyntaxErrorException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLSyntaxErrorException.java
+ojluni/src/main/java/java/sql/SQLTimeoutException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLTimeoutException.java
+ojluni/src/main/java/java/sql/SQLTransactionRollbackException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLTransactionRollbackException.java
+ojluni/src/main/java/java/sql/SQLTransientConnectionException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLTransientConnectionException.java
+ojluni/src/main/java/java/sql/SQLTransientException.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLTransientException.java
+ojluni/src/main/java/java/sql/SQLWarning.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLWarning.java
+ojluni/src/main/java/java/sql/SQLXML.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/SQLXML.java
+ojluni/src/main/java/java/sql/Savepoint.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/java/sql/Savepoint.java
+ojluni/src/main/java/java/sql/Statement.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Statement.java
+ojluni/src/main/java/java/sql/Struct.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Struct.java
+ojluni/src/main/java/java/sql/Time.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Time.java
+ojluni/src/main/java/java/sql/Timestamp.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Timestamp.java
+ojluni/src/main/java/java/sql/Types.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Types.java
+ojluni/src/main/java/java/sql/Wrapper.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/sql/Wrapper.java
+ojluni/src/main/java/java/text/Annotation.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/Annotation.java
+ojluni/src/main/java/java/text/AttributedCharacterIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/AttributedCharacterIterator.java
+ojluni/src/main/java/java/text/AttributedString.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/AttributedString.java
+ojluni/src/main/java/java/text/Bidi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/Bidi.java
+ojluni/src/main/java/java/text/BreakIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/BreakIterator.java
+ojluni/src/main/java/java/text/CalendarBuilder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/CalendarBuilder.java
+ojluni/src/main/java/java/text/CharacterIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/CharacterIterator.java
+ojluni/src/main/java/java/text/CharacterIteratorFieldDelegate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/CharacterIteratorFieldDelegate.java
+ojluni/src/main/java/java/text/ChoiceFormat.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/ChoiceFormat.java
+ojluni/src/main/java/java/text/CollationElementIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/CollationElementIterator.java
+ojluni/src/main/java/java/text/CollationKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/CollationKey.java
+ojluni/src/main/java/java/text/Collator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/Collator.java
+ojluni/src/main/java/java/text/DateFormat.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/DateFormat.java
+ojluni/src/main/java/java/text/DateFormatSymbols.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/DateFormatSymbols.java
+ojluni/src/main/java/java/text/DecimalFormat.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/DecimalFormat.java
+ojluni/src/main/java/java/text/DecimalFormatSymbols.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/DecimalFormatSymbols.java
+ojluni/src/main/java/java/text/DontCareFieldPosition.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/DontCareFieldPosition.java
+ojluni/src/main/java/java/text/EntryPair.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/EntryPair.java
+ojluni/src/main/java/java/text/FieldPosition.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/FieldPosition.java
+ojluni/src/main/java/java/text/Format.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/Format.java
+# java.text.IcuIteratorWrapper doesn't come from the upstream OpenJDK.
+ojluni/src/main/java/java/text/MergeCollation.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/MergeCollation.java
+ojluni/src/main/java/java/text/MessageFormat.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/MessageFormat.java
+ojluni/src/main/java/java/text/Normalizer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/Normalizer.java
+ojluni/src/main/java/java/text/NumberFormat.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/NumberFormat.java
+ojluni/src/main/java/java/text/ParseException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/ParseException.java
+ojluni/src/main/java/java/text/ParsePosition.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/ParsePosition.java
+ojluni/src/main/java/java/text/PatternEntry.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/PatternEntry.java
+ojluni/src/main/java/java/text/RuleBasedCollator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/RuleBasedCollator.java
+ojluni/src/main/java/java/text/SimpleDateFormat.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/SimpleDateFormat.java
+ojluni/src/main/java/java/text/StringCharacterIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/text/StringCharacterIterator.java
+ojluni/src/main/java/java/time/Clock.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/Clock.java
+ojluni/src/main/java/java/time/DateTimeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/DateTimeException.java
+ojluni/src/main/java/java/time/DayOfWeek.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/DayOfWeek.java
+ojluni/src/main/java/java/time/Duration.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/Duration.java
+ojluni/src/main/java/java/time/Instant.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/Instant.java
+ojluni/src/main/java/java/time/LocalDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/LocalDate.java
+ojluni/src/main/java/java/time/LocalDateTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/LocalDateTime.java
+ojluni/src/main/java/java/time/LocalTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/LocalTime.java
+ojluni/src/main/java/java/time/Month.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/Month.java
+ojluni/src/main/java/java/time/MonthDay.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/MonthDay.java
+ojluni/src/main/java/java/time/OffsetDateTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/OffsetDateTime.java
+ojluni/src/main/java/java/time/OffsetTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/OffsetTime.java
+ojluni/src/main/java/java/time/Period.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/Period.java
+ojluni/src/main/java/java/time/Ser.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/Ser.java
+ojluni/src/main/java/java/time/Year.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/Year.java
+ojluni/src/main/java/java/time/YearMonth.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/YearMonth.java
+ojluni/src/main/java/java/time/ZoneId.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/ZoneId.java
+ojluni/src/main/java/java/time/ZoneOffset.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/ZoneOffset.java
+ojluni/src/main/java/java/time/ZoneRegion.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/ZoneRegion.java
+ojluni/src/main/java/java/time/ZonedDateTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/ZonedDateTime.java
+ojluni/src/main/java/java/time/chrono/AbstractChronology.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/AbstractChronology.java
+ojluni/src/main/java/java/time/chrono/ChronoLocalDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java
+ojluni/src/main/java/java/time/chrono/ChronoLocalDateImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java
+ojluni/src/main/java/java/time/chrono/ChronoLocalDateTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java
+ojluni/src/main/java/java/time/chrono/ChronoLocalDateTimeImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java
+ojluni/src/main/java/java/time/chrono/ChronoPeriod.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoPeriod.java
+ojluni/src/main/java/java/time/chrono/ChronoPeriodImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java
+ojluni/src/main/java/java/time/chrono/ChronoZonedDateTime.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java
+ojluni/src/main/java/java/time/chrono/ChronoZonedDateTimeImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java
+ojluni/src/main/java/java/time/chrono/Chronology.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/Chronology.java
+ojluni/src/main/java/java/time/chrono/Era.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/Era.java
+ojluni/src/main/java/java/time/chrono/HijrahChronology.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/HijrahChronology.java
+ojluni/src/main/java/java/time/chrono/HijrahDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/HijrahDate.java
+ojluni/src/main/java/java/time/chrono/HijrahEra.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/HijrahEra.java
+ojluni/src/main/java/java/time/chrono/IsoChronology.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/IsoChronology.java
+ojluni/src/main/java/java/time/chrono/IsoEra.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/IsoEra.java
+ojluni/src/main/java/java/time/chrono/JapaneseChronology.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/JapaneseChronology.java
+ojluni/src/main/java/java/time/chrono/JapaneseDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/JapaneseDate.java
+ojluni/src/main/java/java/time/chrono/JapaneseEra.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/JapaneseEra.java
+ojluni/src/main/java/java/time/chrono/MinguoChronology.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/MinguoChronology.java
+ojluni/src/main/java/java/time/chrono/MinguoDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/MinguoDate.java
+ojluni/src/main/java/java/time/chrono/MinguoEra.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/MinguoEra.java
+ojluni/src/main/java/java/time/chrono/Ser.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/Ser.java
+ojluni/src/main/java/java/time/chrono/ThaiBuddhistChronology.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java
+ojluni/src/main/java/java/time/chrono/ThaiBuddhistDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ThaiBuddhistDate.java
+ojluni/src/main/java/java/time/chrono/ThaiBuddhistEra.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/ThaiBuddhistEra.java
+ojluni/src/main/java/java/time/chrono/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/package-info.java
+ojluni/src/main/java/java/time/format/DateTimeFormatter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/DateTimeFormatter.java
+ojluni/src/main/java/java/time/format/DateTimeFormatterBuilder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
+ojluni/src/main/java/java/time/format/DateTimeParseContext.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/DateTimeParseContext.java
+ojluni/src/main/java/java/time/format/DateTimeParseException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/DateTimeParseException.java
+ojluni/src/main/java/java/time/format/DateTimePrintContext.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/DateTimePrintContext.java
+ojluni/src/main/java/java/time/format/DateTimeTextProvider.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/DateTimeTextProvider.java
+ojluni/src/main/java/java/time/format/DecimalStyle.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/DecimalStyle.java
+ojluni/src/main/java/java/time/format/FormatStyle.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/FormatStyle.java
+ojluni/src/main/java/java/time/format/Parsed.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/Parsed.java
+ojluni/src/main/java/java/time/format/ResolverStyle.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/ResolverStyle.java
+ojluni/src/main/java/java/time/format/SignStyle.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/SignStyle.java
+ojluni/src/main/java/java/time/format/TextStyle.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/TextStyle.java
+ojluni/src/main/java/java/time/format/ZoneName.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/ZoneName.java.template
+ojluni/src/main/java/java/time/format/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/format/package-info.java
+ojluni/src/main/java/java/time/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/package-info.java
+ojluni/src/main/java/java/time/temporal/ChronoField.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/ChronoField.java
+ojluni/src/main/java/java/time/temporal/ChronoUnit.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/ChronoUnit.java
+ojluni/src/main/java/java/time/temporal/IsoFields.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/IsoFields.java
+ojluni/src/main/java/java/time/temporal/JulianFields.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/JulianFields.java
+ojluni/src/main/java/java/time/temporal/Temporal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/Temporal.java
+ojluni/src/main/java/java/time/temporal/TemporalAccessor.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalAccessor.java
+ojluni/src/main/java/java/time/temporal/TemporalAdjuster.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalAdjuster.java
+ojluni/src/main/java/java/time/temporal/TemporalAdjusters.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalAdjusters.java
+ojluni/src/main/java/java/time/temporal/TemporalAmount.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalAmount.java
+ojluni/src/main/java/java/time/temporal/TemporalField.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalField.java
+ojluni/src/main/java/java/time/temporal/TemporalQueries.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalQueries.java
+ojluni/src/main/java/java/time/temporal/TemporalQuery.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalQuery.java
+ojluni/src/main/java/java/time/temporal/TemporalUnit.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/TemporalUnit.java
+ojluni/src/main/java/java/time/temporal/UnsupportedTemporalTypeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/UnsupportedTemporalTypeException.java
+ojluni/src/main/java/java/time/temporal/ValueRange.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/ValueRange.java
+ojluni/src/main/java/java/time/temporal/WeekFields.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/WeekFields.java
+ojluni/src/main/java/java/time/temporal/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/temporal/package-info.java
+# java.time.zone.IcuZoneRulesProvider doesn't come from the upstream OpenJDK.
+ojluni/src/main/java/java/time/zone/Ser.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/zone/Ser.java
+ojluni/src/main/java/java/time/zone/ZoneOffsetTransition.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java
+ojluni/src/main/java/java/time/zone/ZoneOffsetTransitionRule.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/zone/ZoneOffsetTransitionRule.java
+ojluni/src/main/java/java/time/zone/ZoneRules.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/zone/ZoneRules.java
+ojluni/src/main/java/java/time/zone/ZoneRulesException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/zone/ZoneRulesException.java
+ojluni/src/main/java/java/time/zone/ZoneRulesProvider.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java
+ojluni/src/main/java/java/time/zone/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/zone/package-info.java
+ojluni/src/main/java/java/util/AbstractCollection.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/AbstractCollection.java
+ojluni/src/main/java/java/util/AbstractList.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/AbstractList.java
+ojluni/src/main/java/java/util/AbstractMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/AbstractMap.java
+ojluni/src/main/java/java/util/AbstractQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/AbstractQueue.java
+ojluni/src/main/java/java/util/AbstractSequentialList.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/AbstractSequentialList.java
+ojluni/src/main/java/java/util/AbstractSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/AbstractSet.java
+ojluni/src/main/java/java/util/ArrayDeque.java,jdk9/jdk-9+113,jdk/src/java.base/share/classes/java/util/ArrayDeque.java
+ojluni/src/main/java/java/util/ArrayList.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/ArrayList.java
+ojluni/src/main/java/java/util/ArrayPrefixHelpers.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ArrayPrefixHelpers.java
+ojluni/src/main/java/java/util/Arrays.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Arrays.java
+ojluni/src/main/java/java/util/ArraysParallelSortHelpers.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ArraysParallelSortHelpers.java
+ojluni/src/main/java/java/util/Base64.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Base64.java
+ojluni/src/main/java/java/util/BitSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/BitSet.java
+ojluni/src/main/java/java/util/Calendar.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Calendar.java
+ojluni/src/main/java/java/util/Collection.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Collection.java
+ojluni/src/main/java/java/util/Collections.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Collections.java
+ojluni/src/main/java/java/util/ComparableTimSort.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ComparableTimSort.java
+ojluni/src/main/java/java/util/Comparator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Comparator.java
+ojluni/src/main/java/java/util/Comparators.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Comparators.java
+ojluni/src/main/java/java/util/ConcurrentModificationException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ConcurrentModificationException.java
+ojluni/src/main/java/java/util/Currency.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Currency.java
+ojluni/src/main/java/java/util/Date.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Date.java
+ojluni/src/main/java/java/util/Deque.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Deque.java
+ojluni/src/main/java/java/util/Dictionary.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Dictionary.java
+ojluni/src/main/java/java/util/DoubleSummaryStatistics.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/DoubleSummaryStatistics.java
+ojluni/src/main/java/java/util/DualPivotQuicksort.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/DualPivotQuicksort.java
+ojluni/src/main/java/java/util/DuplicateFormatFlagsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/DuplicateFormatFlagsException.java
+ojluni/src/main/java/java/util/EmptyStackException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/EmptyStackException.java
+ojluni/src/main/java/java/util/EnumMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/EnumMap.java
+ojluni/src/main/java/java/util/EnumSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/EnumSet.java
+ojluni/src/main/java/java/util/Enumeration.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Enumeration.java
+ojluni/src/main/java/java/util/EventListener.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/EventListener.java
+ojluni/src/main/java/java/util/EventListenerProxy.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/EventListenerProxy.java
+ojluni/src/main/java/java/util/EventObject.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/EventObject.java
+ojluni/src/main/java/java/util/FormatFlagsConversionMismatchException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/FormatFlagsConversionMismatchException.java
+ojluni/src/main/java/java/util/Formattable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Formattable.java
+ojluni/src/main/java/java/util/FormattableFlags.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/FormattableFlags.java
+ojluni/src/main/java/java/util/Formatter.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Formatter.java
+ojluni/src/main/java/java/util/FormatterClosedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/FormatterClosedException.java
+ojluni/src/main/java/java/util/GregorianCalendar.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/GregorianCalendar.java
+ojluni/src/main/java/java/util/HashMap.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/HashMap.java
+ojluni/src/main/java/java/util/HashSet.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/HashSet.java
+ojluni/src/main/java/java/util/Hashtable.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Hashtable.java
+ojluni/src/main/java/java/util/IdentityHashMap.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/IdentityHashMap.java
+ojluni/src/main/java/java/util/IllegalFormatCodePointException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IllegalFormatCodePointException.java
+ojluni/src/main/java/java/util/IllegalFormatConversionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IllegalFormatConversionException.java
+ojluni/src/main/java/java/util/IllegalFormatException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IllegalFormatException.java
+ojluni/src/main/java/java/util/IllegalFormatFlagsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IllegalFormatFlagsException.java
+ojluni/src/main/java/java/util/IllegalFormatPrecisionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IllegalFormatPrecisionException.java
+ojluni/src/main/java/java/util/IllegalFormatWidthException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IllegalFormatWidthException.java
+ojluni/src/main/java/java/util/IllformedLocaleException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IllformedLocaleException.java
+ojluni/src/main/java/java/util/ImmutableCollections.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ImmutableCollections.java
+ojluni/src/main/java/java/util/InputMismatchException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/InputMismatchException.java
+ojluni/src/main/java/java/util/IntSummaryStatistics.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/IntSummaryStatistics.java
+ojluni/src/main/java/java/util/InvalidPropertiesFormatException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/InvalidPropertiesFormatException.java
+ojluni/src/main/java/java/util/Iterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Iterator.java
+ojluni/src/main/java/java/util/JapaneseImperialCalendar.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/JapaneseImperialCalendar.java
+ojluni/src/main/java/java/util/JumboEnumSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/JumboEnumSet.java
+ojluni/src/main/java/java/util/KeyValueHolder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/KeyValueHolder.java
+ojluni/src/main/java/java/util/LinkedHashMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/LinkedHashMap.java
+ojluni/src/main/java/java/util/LinkedHashSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/LinkedHashSet.java
+ojluni/src/main/java/java/util/LinkedList.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/LinkedList.java
+ojluni/src/main/java/java/util/List.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/List.java
+ojluni/src/main/java/java/util/ListIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ListIterator.java
+ojluni/src/main/java/java/util/ListResourceBundle.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ListResourceBundle.java
+ojluni/src/main/java/java/util/Locale.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Locale.java
+ojluni/src/main/java/java/util/LongSummaryStatistics.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/LongSummaryStatistics.java
+ojluni/src/main/java/java/util/Map.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Map.java
+ojluni/src/main/java/java/util/MissingFormatArgumentException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/MissingFormatArgumentException.java
+ojluni/src/main/java/java/util/MissingFormatWidthException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/MissingFormatWidthException.java
+ojluni/src/main/java/java/util/MissingResourceException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/MissingResourceException.java
+ojluni/src/main/java/java/util/NavigableMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/NavigableMap.java
+ojluni/src/main/java/java/util/NavigableSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/NavigableSet.java
+ojluni/src/main/java/java/util/NoSuchElementException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/NoSuchElementException.java
+ojluni/src/main/java/java/util/Objects.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Objects.java
+ojluni/src/main/java/java/util/Observable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Observable.java
+ojluni/src/main/java/java/util/Observer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Observer.java
+ojluni/src/main/java/java/util/Optional.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Optional.java
+ojluni/src/main/java/java/util/OptionalDouble.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/OptionalDouble.java
+ojluni/src/main/java/java/util/OptionalInt.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/OptionalInt.java
+ojluni/src/main/java/java/util/OptionalLong.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/OptionalLong.java
+ojluni/src/main/java/java/util/PrimitiveIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/PrimitiveIterator.java
+ojluni/src/main/java/java/util/PriorityQueue.java,jdk9/jdk-9+113,jdk/src/java.base/share/classes/java/util/PriorityQueue.java
+ojluni/src/main/java/java/util/Properties.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Properties.java
+ojluni/src/main/java/java/util/PropertyPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/PropertyPermission.java
+ojluni/src/main/java/java/util/PropertyResourceBundle.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/PropertyResourceBundle.java
+ojluni/src/main/java/java/util/Queue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Queue.java
+ojluni/src/main/java/java/util/Random.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Random.java
+ojluni/src/main/java/java/util/RandomAccess.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/RandomAccess.java
+ojluni/src/main/java/java/util/RegularEnumSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/RegularEnumSet.java
+ojluni/src/main/java/java/util/ResourceBundle.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/ResourceBundle.java
+ojluni/src/main/java/java/util/Scanner.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Scanner.java
+ojluni/src/main/java/java/util/ServiceConfigurationError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/ServiceConfigurationError.java
+ojluni/src/main/java/java/util/ServiceLoader.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/ServiceLoader.java
+ojluni/src/main/java/java/util/Set.java,jdk9/jdk-9+181,jdk/src/java.base/share/classes/java/util/Set.java
+ojluni/src/main/java/java/util/SimpleTimeZone.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/SimpleTimeZone.java
+ojluni/src/main/java/java/util/SortedMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/SortedMap.java
+ojluni/src/main/java/java/util/SortedSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/SortedSet.java
+ojluni/src/main/java/java/util/Spliterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Spliterator.java
+ojluni/src/main/java/java/util/Spliterators.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Spliterators.java
+ojluni/src/main/java/java/util/SplittableRandom.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/SplittableRandom.java
+ojluni/src/main/java/java/util/Stack.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Stack.java
+ojluni/src/main/java/java/util/StringJoiner.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/StringJoiner.java
+ojluni/src/main/java/java/util/StringTokenizer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/StringTokenizer.java
+ojluni/src/main/java/java/util/TimSort.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/TimSort.java
+ojluni/src/main/java/java/util/TimeZone.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/TimeZone.java
+ojluni/src/main/java/java/util/Timer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Timer.java
+ojluni/src/main/java/java/util/TimerTask.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/TimerTask.java
+ojluni/src/main/java/java/util/TooManyListenersException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/TooManyListenersException.java
+ojluni/src/main/java/java/util/TreeMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/TreeMap.java
+ojluni/src/main/java/java/util/TreeSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/TreeSet.java
+ojluni/src/main/java/java/util/Tripwire.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/Tripwire.java
+ojluni/src/main/java/java/util/UUID.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/UUID.java
+ojluni/src/main/java/java/util/UnknownFormatConversionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/UnknownFormatConversionException.java
+ojluni/src/main/java/java/util/UnknownFormatFlagsException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/UnknownFormatFlagsException.java
+ojluni/src/main/java/java/util/Vector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/Vector.java
+ojluni/src/main/java/java/util/WeakHashMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/WeakHashMap.java
+ojluni/src/main/java/java/util/XMLUtils.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/java/util/XMLUtils.java
+ojluni/src/main/java/java/util/concurrent/AbstractExecutorService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java
+ojluni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java
+ojluni/src/main/java/java/util/concurrent/BlockingDeque.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/BlockingDeque.java
+ojluni/src/main/java/java/util/concurrent/BlockingQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/BlockingQueue.java
+ojluni/src/main/java/java/util/concurrent/BrokenBarrierException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/BrokenBarrierException.java
+ojluni/src/main/java/java/util/concurrent/Callable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Callable.java
+ojluni/src/main/java/java/util/concurrent/CancellationException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CancellationException.java
+ojluni/src/main/java/java/util/concurrent/CompletableFuture.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CompletableFuture.java
+ojluni/src/main/java/java/util/concurrent/CompletionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CompletionException.java
+ojluni/src/main/java/java/util/concurrent/CompletionService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CompletionService.java
+ojluni/src/main/java/java/util/concurrent/CompletionStage.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CompletionStage.java
+ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java
+ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java
+ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
+ojluni/src/main/java/java/util/concurrent/ConcurrentMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java
+ojluni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ConcurrentNavigableMap.java
+ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java
+ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java
+ojluni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java
+ojluni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java
+ojluni/src/main/java/java/util/concurrent/CountDownLatch.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CountDownLatch.java
+ojluni/src/main/java/java/util/concurrent/CountedCompleter.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CountedCompleter.java
+ojluni/src/main/java/java/util/concurrent/CyclicBarrier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java
+ojluni/src/main/java/java/util/concurrent/DelayQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/DelayQueue.java
+ojluni/src/main/java/java/util/concurrent/Delayed.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Delayed.java
+ojluni/src/main/java/java/util/concurrent/Exchanger.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Exchanger.java
+ojluni/src/main/java/java/util/concurrent/ExecutionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ExecutionException.java
+ojluni/src/main/java/java/util/concurrent/Executor.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Executor.java
+ojluni/src/main/java/java/util/concurrent/ExecutorCompletionService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java
+ojluni/src/main/java/java/util/concurrent/ExecutorService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ExecutorService.java
+ojluni/src/main/java/java/util/concurrent/Executors.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Executors.java
+ojluni/src/main/java/java/util/concurrent/Flow.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Flow.java
+ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
+ojluni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
+ojluni/src/main/java/java/util/concurrent/Future.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Future.java
+ojluni/src/main/java/java/util/concurrent/FutureTask.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/FutureTask.java
+ojluni/src/main/java/java/util/concurrent/Helpers.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Helpers.java
+ojluni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java
+ojluni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java
+ojluni/src/main/java/java/util/concurrent/LinkedTransferQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java
+ojluni/src/main/java/java/util/concurrent/Phaser.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Phaser.java
+ojluni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java
+ojluni/src/main/java/java/util/concurrent/RecursiveAction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/RecursiveAction.java
+ojluni/src/main/java/java/util/concurrent/RecursiveTask.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/RecursiveTask.java
+ojluni/src/main/java/java/util/concurrent/RejectedExecutionException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/RejectedExecutionException.java
+ojluni/src/main/java/java/util/concurrent/RejectedExecutionHandler.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/RejectedExecutionHandler.java
+ojluni/src/main/java/java/util/concurrent/RunnableFuture.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/RunnableFuture.java
+ojluni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/RunnableScheduledFuture.java
+ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java
+ojluni/src/main/java/java/util/concurrent/ScheduledFuture.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ScheduledFuture.java
+ojluni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java
+ojluni/src/main/java/java/util/concurrent/Semaphore.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/Semaphore.java
+ojluni/src/main/java/java/util/concurrent/SubmissionPublisher.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java
+ojluni/src/main/java/java/util/concurrent/SynchronousQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java
+ojluni/src/main/java/java/util/concurrent/ThreadFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ThreadFactory.java
+ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java
+ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java
+ojluni/src/main/java/java/util/concurrent/TimeUnit.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/TimeUnit.java
+ojluni/src/main/java/java/util/concurrent/TimeoutException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/TimeoutException.java
+ojluni/src/main/java/java/util/concurrent/TransferQueue.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/TransferQueue.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicLong.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicReference.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+ojluni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java
+ojluni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
+ojluni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java
+ojluni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
+ojluni/src/main/java/java/util/concurrent/atomic/LongAdder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java
+ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
+ojluni/src/main/java/java/util/concurrent/atomic/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/atomic/package-info.java
+ojluni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
+ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
+ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+ojluni/src/main/java/java/util/concurrent/locks/Condition.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/Condition.java
+ojluni/src/main/java/java/util/concurrent/locks/Lock.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/Lock.java
+ojluni/src/main/java/java/util/concurrent/locks/LockSupport.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java
+ojluni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java
+ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java
+ojluni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java
+ojluni/src/main/java/java/util/concurrent/locks/StampedLock.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java
+ojluni/src/main/java/java/util/concurrent/locks/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/locks/package-info.java
+ojluni/src/main/java/java/util/concurrent/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/concurrent/package-info.java
+ojluni/src/main/java/java/util/function/BiConsumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/BiConsumer.java
+ojluni/src/main/java/java/util/function/BiFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/BiFunction.java
+ojluni/src/main/java/java/util/function/BiPredicate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/BiPredicate.java
+ojluni/src/main/java/java/util/function/BinaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/BinaryOperator.java
+ojluni/src/main/java/java/util/function/BooleanSupplier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/BooleanSupplier.java
+ojluni/src/main/java/java/util/function/Consumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/Consumer.java
+ojluni/src/main/java/java/util/function/DoubleBinaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoubleBinaryOperator.java
+ojluni/src/main/java/java/util/function/DoubleConsumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoubleConsumer.java
+ojluni/src/main/java/java/util/function/DoubleFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoubleFunction.java
+ojluni/src/main/java/java/util/function/DoublePredicate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoublePredicate.java
+ojluni/src/main/java/java/util/function/DoubleSupplier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoubleSupplier.java
+ojluni/src/main/java/java/util/function/DoubleToIntFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoubleToIntFunction.java
+ojluni/src/main/java/java/util/function/DoubleToLongFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoubleToLongFunction.java
+ojluni/src/main/java/java/util/function/DoubleUnaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/DoubleUnaryOperator.java
+ojluni/src/main/java/java/util/function/Function.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/Function.java
+ojluni/src/main/java/java/util/function/IntBinaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntBinaryOperator.java
+ojluni/src/main/java/java/util/function/IntConsumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntConsumer.java
+ojluni/src/main/java/java/util/function/IntFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntFunction.java
+ojluni/src/main/java/java/util/function/IntPredicate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntPredicate.java
+ojluni/src/main/java/java/util/function/IntSupplier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntSupplier.java
+ojluni/src/main/java/java/util/function/IntToDoubleFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntToDoubleFunction.java
+ojluni/src/main/java/java/util/function/IntToLongFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntToLongFunction.java
+ojluni/src/main/java/java/util/function/IntUnaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/IntUnaryOperator.java
+ojluni/src/main/java/java/util/function/LongBinaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongBinaryOperator.java
+ojluni/src/main/java/java/util/function/LongConsumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongConsumer.java
+ojluni/src/main/java/java/util/function/LongFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongFunction.java
+ojluni/src/main/java/java/util/function/LongPredicate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongPredicate.java
+ojluni/src/main/java/java/util/function/LongSupplier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongSupplier.java
+ojluni/src/main/java/java/util/function/LongToDoubleFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongToDoubleFunction.java
+ojluni/src/main/java/java/util/function/LongToIntFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongToIntFunction.java
+ojluni/src/main/java/java/util/function/LongUnaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/LongUnaryOperator.java
+ojluni/src/main/java/java/util/function/ObjDoubleConsumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ObjDoubleConsumer.java
+ojluni/src/main/java/java/util/function/ObjIntConsumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ObjIntConsumer.java
+ojluni/src/main/java/java/util/function/ObjLongConsumer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ObjLongConsumer.java
+ojluni/src/main/java/java/util/function/Predicate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/Predicate.java
+ojluni/src/main/java/java/util/function/Supplier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/Supplier.java
+ojluni/src/main/java/java/util/function/ToDoubleBiFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ToDoubleBiFunction.java
+ojluni/src/main/java/java/util/function/ToDoubleFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ToDoubleFunction.java
+ojluni/src/main/java/java/util/function/ToIntBiFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ToIntBiFunction.java
+ojluni/src/main/java/java/util/function/ToIntFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ToIntFunction.java
+ojluni/src/main/java/java/util/function/ToLongBiFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ToLongBiFunction.java
+ojluni/src/main/java/java/util/function/ToLongFunction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/ToLongFunction.java
+ojluni/src/main/java/java/util/function/UnaryOperator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/UnaryOperator.java
+ojluni/src/main/java/java/util/function/package-info.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/function/package-info.java
+ojluni/src/main/java/java/util/jar/Attributes.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/jar/Attributes.java
+ojluni/src/main/java/java/util/jar/JarEntry.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/jar/JarEntry.java
+ojluni/src/main/java/java/util/jar/JarException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/jar/JarException.java
+ojluni/src/main/java/java/util/jar/JarFile.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/jar/JarFile.java
+ojluni/src/main/java/java/util/jar/JarInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/jar/JarInputStream.java
+ojluni/src/main/java/java/util/jar/JarOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/jar/JarOutputStream.java
+ojluni/src/main/java/java/util/jar/JarVerifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/jar/JarVerifier.java
+ojluni/src/main/java/java/util/jar/Manifest.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/jar/Manifest.java
+ojluni/src/main/java/java/util/jar/Pack200.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/jar/Pack200.java
+ojluni/src/main/java/java/util/logging/ConsoleHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/ConsoleHandler.java
+ojluni/src/main/java/java/util/logging/ErrorManager.java,jdk11u/jdk-11.0.13-ga,src/java.logging/share/classes/java/util/logging/ErrorManager.java
+ojluni/src/main/java/java/util/logging/FileHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/FileHandler.java
+ojluni/src/main/java/java/util/logging/Filter.java,jdk11u/jdk-11.0.13-ga,src/java.logging/share/classes/java/util/logging/Filter.java
+ojluni/src/main/java/java/util/logging/Formatter.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/Formatter.java
+ojluni/src/main/java/java/util/logging/Handler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/Handler.java
+ojluni/src/main/java/java/util/logging/Level.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/Level.java
+ojluni/src/main/java/java/util/logging/LogManager.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/LogManager.java
+ojluni/src/main/java/java/util/logging/LogRecord.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/LogRecord.java
+ojluni/src/main/java/java/util/logging/Logger.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/Logger.java
+ojluni/src/main/java/java/util/logging/Logging.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/Logging.java
+ojluni/src/main/java/java/util/logging/LoggingMXBean.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/LoggingMXBean.java
+ojluni/src/main/java/java/util/logging/LoggingPermission.java,jdk11u/jdk-11.0.13-ga,src/java.logging/share/classes/java/util/logging/LoggingPermission.java
+ojluni/src/main/java/java/util/logging/LoggingProxyImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/LoggingProxyImpl.java
+ojluni/src/main/java/java/util/logging/MemoryHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/MemoryHandler.java
+ojluni/src/main/java/java/util/logging/SimpleFormatter.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/SimpleFormatter.java
+ojluni/src/main/java/java/util/logging/SocketHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/SocketHandler.java
+ojluni/src/main/java/java/util/logging/StreamHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/StreamHandler.java
+ojluni/src/main/java/java/util/logging/XMLFormatter.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/logging/XMLFormatter.java
+ojluni/src/main/java/java/util/prefs/AbstractPreferences.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/AbstractPreferences.java
+ojluni/src/main/java/java/util/prefs/BackingStoreException.java,jdk11u/jdk-11.0.13-ga,src/java.prefs/share/classes/java/util/prefs/BackingStoreException.java
+ojluni/src/main/java/java/util/prefs/Base64.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/Base64.java
+ojluni/src/main/java/java/util/prefs/FileSystemPreferences.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/util/prefs/FileSystemPreferences.java
+ojluni/src/main/java/java/util/prefs/FileSystemPreferencesFactory.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/java/util/prefs/FileSystemPreferencesFactory.java
+ojluni/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java,jdk11u/jdk-11.0.13-ga,src/java.prefs/share/classes/java/util/prefs/InvalidPreferencesFormatException.java
+ojluni/src/main/java/java/util/prefs/NodeChangeEvent.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/NodeChangeEvent.java
+ojluni/src/main/java/java/util/prefs/NodeChangeListener.java,jdk11u/jdk-11.0.13-ga,src/java.prefs/share/classes/java/util/prefs/NodeChangeListener.java
+ojluni/src/main/java/java/util/prefs/PreferenceChangeEvent.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/PreferenceChangeEvent.java
+ojluni/src/main/java/java/util/prefs/PreferenceChangeListener.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/PreferenceChangeListener.java
+ojluni/src/main/java/java/util/prefs/Preferences.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/Preferences.java
+ojluni/src/main/java/java/util/prefs/PreferencesFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/PreferencesFactory.java
+ojluni/src/main/java/java/util/prefs/XmlSupport.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/prefs/XmlSupport.java
+ojluni/src/main/java/java/util/regex/MatchResult.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/regex/MatchResult.java
+ojluni/src/main/java/java/util/regex/Matcher.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/regex/Matcher.java
+ojluni/src/main/java/java/util/regex/Pattern.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/regex/Pattern.java
+ojluni/src/main/java/java/util/regex/PatternSyntaxException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/regex/PatternSyntaxException.java
+ojluni/src/main/java/java/util/stream/AbstractPipeline.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/AbstractPipeline.java
+ojluni/src/main/java/java/util/stream/AbstractShortCircuitTask.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/AbstractShortCircuitTask.java
+ojluni/src/main/java/java/util/stream/AbstractSpinedBuffer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/AbstractSpinedBuffer.java
+ojluni/src/main/java/java/util/stream/AbstractTask.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/AbstractTask.java
+ojluni/src/main/java/java/util/stream/BaseStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/BaseStream.java
+ojluni/src/main/java/java/util/stream/Collector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/Collector.java
+ojluni/src/main/java/java/util/stream/Collectors.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/Collectors.java
+ojluni/src/main/java/java/util/stream/DistinctOps.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/DistinctOps.java
+ojluni/src/main/java/java/util/stream/DoublePipeline.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/DoublePipeline.java
+ojluni/src/main/java/java/util/stream/DoubleStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/DoubleStream.java
+ojluni/src/main/java/java/util/stream/FindOps.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/FindOps.java
+ojluni/src/main/java/java/util/stream/ForEachOps.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/ForEachOps.java
+ojluni/src/main/java/java/util/stream/IntPipeline.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/IntPipeline.java
+ojluni/src/main/java/java/util/stream/IntStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/IntStream.java
+ojluni/src/main/java/java/util/stream/LongPipeline.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/LongPipeline.java
+ojluni/src/main/java/java/util/stream/LongStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/LongStream.java
+ojluni/src/main/java/java/util/stream/MatchOps.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/MatchOps.java
+ojluni/src/main/java/java/util/stream/Node.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/Node.java
+ojluni/src/main/java/java/util/stream/Nodes.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/Nodes.java
+ojluni/src/main/java/java/util/stream/PipelineHelper.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/PipelineHelper.java
+ojluni/src/main/java/java/util/stream/ReduceOps.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/ReduceOps.java
+ojluni/src/main/java/java/util/stream/ReferencePipeline.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/ReferencePipeline.java
+ojluni/src/main/java/java/util/stream/Sink.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/Sink.java
+ojluni/src/main/java/java/util/stream/SliceOps.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/SliceOps.java
+ojluni/src/main/java/java/util/stream/SortedOps.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/SortedOps.java
+ojluni/src/main/java/java/util/stream/SpinedBuffer.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/SpinedBuffer.java
+ojluni/src/main/java/java/util/stream/Stream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/Stream.java
+ojluni/src/main/java/java/util/stream/StreamOpFlag.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/StreamOpFlag.java
+ojluni/src/main/java/java/util/stream/StreamShape.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/StreamShape.java
+ojluni/src/main/java/java/util/stream/StreamSpliterators.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/StreamSpliterators.java
+ojluni/src/main/java/java/util/stream/StreamSupport.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/StreamSupport.java
+ojluni/src/main/java/java/util/stream/Streams.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/Streams.java
+ojluni/src/main/java/java/util/stream/TerminalOp.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/TerminalOp.java
+ojluni/src/main/java/java/util/stream/TerminalSink.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/TerminalSink.java
+ojluni/src/main/java/java/util/stream/Tripwire.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/stream/Tripwire.java
+ojluni/src/main/java/java/util/stream/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/stream/package-info.java
+ojluni/src/main/java/java/util/zip/Adler32.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/Adler32.java
+ojluni/src/main/java/java/util/zip/CRC32.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/CRC32.java
+ojluni/src/main/java/java/util/zip/CheckedInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/CheckedInputStream.java
+ojluni/src/main/java/java/util/zip/CheckedOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/CheckedOutputStream.java
+ojluni/src/main/java/java/util/zip/Checksum.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/Checksum.java
+ojluni/src/main/java/java/util/zip/DataFormatException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/DataFormatException.java
+ojluni/src/main/java/java/util/zip/Deflater.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/Deflater.java
+ojluni/src/main/java/java/util/zip/DeflaterInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/DeflaterInputStream.java
+ojluni/src/main/java/java/util/zip/DeflaterOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java
+ojluni/src/main/java/java/util/zip/GZIPInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/GZIPInputStream.java
+ojluni/src/main/java/java/util/zip/GZIPOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/GZIPOutputStream.java
+ojluni/src/main/java/java/util/zip/Inflater.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/Inflater.java
+ojluni/src/main/java/java/util/zip/InflaterInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/InflaterInputStream.java
+ojluni/src/main/java/java/util/zip/InflaterOutputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/InflaterOutputStream.java
+ojluni/src/main/java/java/util/zip/ZStreamRef.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/ZStreamRef.java
+ojluni/src/main/java/java/util/zip/ZipCoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/ZipCoder.java
+ojluni/src/main/java/java/util/zip/ZipConstants.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/ZipConstants.java
+ojluni/src/main/java/java/util/zip/ZipConstants64.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/ZipConstants64.java
+ojluni/src/main/java/java/util/zip/ZipEntry.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/ZipEntry.java
+ojluni/src/main/java/java/util/zip/ZipError.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/ZipError.java
+ojluni/src/main/java/java/util/zip/ZipException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/util/zip/ZipException.java
+ojluni/src/main/java/java/util/zip/ZipFile.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/ZipFile.java
+ojluni/src/main/java/java/util/zip/ZipInputStream.java,jdk11u/jdk-11+28,src/java.base/share/classes/java/util/zip/ZipInputStream.java
+ojluni/src/main/java/java/util/zip/ZipOutputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/ZipOutputStream.java
+ojluni/src/main/java/java/util/zip/ZipUtils.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/java/util/zip/ZipUtils.java
+ojluni/src/main/java/javax/crypto/AEADBadTagException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/AEADBadTagException.java
+ojluni/src/main/java/javax/crypto/BadPaddingException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/BadPaddingException.java
+ojluni/src/main/java/javax/crypto/Cipher.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/Cipher.java
+ojluni/src/main/java/javax/crypto/CipherInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/CipherInputStream.java
+ojluni/src/main/java/javax/crypto/CipherOutputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/CipherOutputStream.java
+ojluni/src/main/java/javax/crypto/CipherSpi.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/CipherSpi.java
+ojluni/src/main/java/javax/crypto/CryptoAllPermission.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/CryptoAllPermission.java
+ojluni/src/main/java/javax/crypto/CryptoPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/CryptoPermission.java
+ojluni/src/main/java/javax/crypto/CryptoPermissions.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/CryptoPermissions.java
+ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/CryptoPolicyParser.java
+ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/EncryptedPrivateKeyInfo.java
+ojluni/src/main/java/javax/crypto/ExemptionMechanism.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/ExemptionMechanism.java
+ojluni/src/main/java/javax/crypto/ExemptionMechanismException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/ExemptionMechanismException.java
+ojluni/src/main/java/javax/crypto/ExemptionMechanismSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/ExemptionMechanismSpi.java
+ojluni/src/main/java/javax/crypto/IllegalBlockSizeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/IllegalBlockSizeException.java
+ojluni/src/main/java/javax/crypto/JarVerifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/JarVerifier.java
+ojluni/src/main/java/javax/crypto/JceSecurity.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/JceSecurity.java
+ojluni/src/main/java/javax/crypto/JceSecurityManager.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/JceSecurityManager.java
+ojluni/src/main/java/javax/crypto/KeyAgreement.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/KeyAgreement.java
+ojluni/src/main/java/javax/crypto/KeyAgreementSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/KeyAgreementSpi.java
+ojluni/src/main/java/javax/crypto/KeyGenerator.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/KeyGenerator.java
+ojluni/src/main/java/javax/crypto/KeyGeneratorSpi.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/KeyGeneratorSpi.java
+ojluni/src/main/java/javax/crypto/Mac.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/Mac.java
+ojluni/src/main/java/javax/crypto/MacSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/MacSpi.java
+ojluni/src/main/java/javax/crypto/NoSuchPaddingException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/NoSuchPaddingException.java
+ojluni/src/main/java/javax/crypto/NullCipher.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/NullCipher.java
+ojluni/src/main/java/javax/crypto/NullCipherSpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/NullCipherSpi.java
+ojluni/src/main/java/javax/crypto/SealedObject.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/SealedObject.java
+ojluni/src/main/java/javax/crypto/SecretKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/SecretKey.java
+ojluni/src/main/java/javax/crypto/SecretKeyFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/SecretKeyFactory.java
+ojluni/src/main/java/javax/crypto/SecretKeyFactorySpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/SecretKeyFactorySpi.java
+ojluni/src/main/java/javax/crypto/ShortBufferException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/ShortBufferException.java
+ojluni/src/main/java/javax/crypto/interfaces/DHKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/interfaces/DHKey.java
+ojluni/src/main/java/javax/crypto/interfaces/DHPrivateKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/interfaces/DHPrivateKey.java
+ojluni/src/main/java/javax/crypto/interfaces/DHPublicKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/interfaces/DHPublicKey.java
+ojluni/src/main/java/javax/crypto/interfaces/PBEKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/interfaces/PBEKey.java
+ojluni/src/main/java/javax/crypto/spec/DESKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/DESKeySpec.java
+ojluni/src/main/java/javax/crypto/spec/DESedeKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/DESedeKeySpec.java
+ojluni/src/main/java/javax/crypto/spec/DHGenParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/DHGenParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/DHParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/DHParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/DHPrivateKeySpec.java
+ojluni/src/main/java/javax/crypto/spec/DHPublicKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/DHPublicKeySpec.java
+ojluni/src/main/java/javax/crypto/spec/GCMParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/GCMParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/IvParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/IvParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/OAEPParameterSpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/spec/OAEPParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/PBEKeySpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/PBEKeySpec.java
+ojluni/src/main/java/javax/crypto/spec/PBEParameterSpec.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/crypto/spec/PBEParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/PSource.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/spec/PSource.java
+ojluni/src/main/java/javax/crypto/spec/RC2ParameterSpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/spec/RC2ParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/RC5ParameterSpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/spec/RC5ParameterSpec.java
+ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/crypto/spec/SecretKeySpec.java
+ojluni/src/main/java/javax/net/ServerSocketFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ServerSocketFactory.java
+ojluni/src/main/java/javax/net/SocketFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/SocketFactory.java
+ojluni/src/main/java/javax/net/ssl/CertPathTrustManagerParameters.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/CertPathTrustManagerParameters.java
+ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/ExtendedSSLSession.java
+ojluni/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java
+ojluni/src/main/java/javax/net/ssl/HandshakeCompletedListener.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/HandshakeCompletedListener.java
+ojluni/src/main/java/javax/net/ssl/HostnameVerifier.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/HostnameVerifier.java
+ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java
+ojluni/src/main/java/javax/net/ssl/KeyManager.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/KeyManager.java
+ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/KeyManagerFactory.java
+ojluni/src/main/java/javax/net/ssl/KeyManagerFactorySpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/KeyManagerFactorySpi.java
+ojluni/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/KeyStoreBuilderParameters.java
+ojluni/src/main/java/javax/net/ssl/ManagerFactoryParameters.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/ManagerFactoryParameters.java
+ojluni/src/main/java/javax/net/ssl/SNIHostName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SNIHostName.java
+ojluni/src/main/java/javax/net/ssl/SNIMatcher.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SNIMatcher.java
+ojluni/src/main/java/javax/net/ssl/SNIServerName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SNIServerName.java
+ojluni/src/main/java/javax/net/ssl/SSLContext.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLContext.java
+ojluni/src/main/java/javax/net/ssl/SSLContextSpi.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLContextSpi.java
+ojluni/src/main/java/javax/net/ssl/SSLEngine.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLEngine.java
+ojluni/src/main/java/javax/net/ssl/SSLEngineResult.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLEngineResult.java
+ojluni/src/main/java/javax/net/ssl/SSLException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLException.java
+ojluni/src/main/java/javax/net/ssl/SSLHandshakeException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SSLHandshakeException.java
+ojluni/src/main/java/javax/net/ssl/SSLKeyException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SSLKeyException.java
+ojluni/src/main/java/javax/net/ssl/SSLParameters.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLParameters.java
+ojluni/src/main/java/javax/net/ssl/SSLPeerUnverifiedException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SSLPeerUnverifiedException.java
+ojluni/src/main/java/javax/net/ssl/SSLPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLPermission.java
+ojluni/src/main/java/javax/net/ssl/SSLProtocolException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SSLProtocolException.java
+ojluni/src/main/java/javax/net/ssl/SSLServerSocket.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLServerSocket.java
+ojluni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java
+ojluni/src/main/java/javax/net/ssl/SSLSession.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLSession.java
+ojluni/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SSLSessionBindingEvent.java
+ojluni/src/main/java/javax/net/ssl/SSLSessionBindingListener.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SSLSessionBindingListener.java
+ojluni/src/main/java/javax/net/ssl/SSLSessionContext.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/SSLSessionContext.java
+ojluni/src/main/java/javax/net/ssl/SSLSocket.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLSocket.java
+ojluni/src/main/java/javax/net/ssl/SSLSocketFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java
+ojluni/src/main/java/javax/net/ssl/StandardConstants.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/StandardConstants.java
+ojluni/src/main/java/javax/net/ssl/TrustManager.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/TrustManager.java
+ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/TrustManagerFactory.java
+ojluni/src/main/java/javax/net/ssl/TrustManagerFactorySpi.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/TrustManagerFactorySpi.java
+ojluni/src/main/java/javax/net/ssl/X509ExtendedKeyManager.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/X509ExtendedKeyManager.java
+ojluni/src/main/java/javax/net/ssl/X509ExtendedTrustManager.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/X509ExtendedTrustManager.java
+ojluni/src/main/java/javax/net/ssl/X509KeyManager.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/net/ssl/X509KeyManager.java
+ojluni/src/main/java/javax/net/ssl/X509TrustManager.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/javax/net/ssl/X509TrustManager.java
+ojluni/src/main/java/javax/security/auth/AuthPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/AuthPermission.java
+ojluni/src/main/java/javax/security/auth/DestroyFailedException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/DestroyFailedException.java
+ojluni/src/main/java/javax/security/auth/Destroyable.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/Destroyable.java
+ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java
+ojluni/src/main/java/javax/security/auth/Subject.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/Subject.java
+ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java
+ojluni/src/main/java/javax/security/auth/callback/Callback.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/callback/Callback.java
+ojluni/src/main/java/javax/security/auth/callback/CallbackHandler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/callback/CallbackHandler.java
+ojluni/src/main/java/javax/security/auth/callback/PasswordCallback.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/callback/PasswordCallback.java
+ojluni/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/callback/UnsupportedCallbackException.java
+ojluni/src/main/java/javax/security/auth/callback/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/callback/package-info.java
+ojluni/src/main/java/javax/security/auth/login/LoginException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/login/LoginException.java
+ojluni/src/main/java/javax/security/auth/login/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/login/package-info.java
+ojluni/src/main/java/javax/security/auth/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/package-info.java
+ojluni/src/main/java/javax/security/auth/x500/X500Principal.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/x500/X500Principal.java
+ojluni/src/main/java/javax/security/auth/x500/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/auth/x500/package-info.java
+ojluni/src/main/java/javax/security/cert/Certificate.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/Certificate.java
+ojluni/src/main/java/javax/security/cert/CertificateEncodingException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/CertificateEncodingException.java
+ojluni/src/main/java/javax/security/cert/CertificateException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/CertificateException.java
+ojluni/src/main/java/javax/security/cert/CertificateExpiredException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/CertificateExpiredException.java
+ojluni/src/main/java/javax/security/cert/CertificateNotYetValidException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/CertificateNotYetValidException.java
+ojluni/src/main/java/javax/security/cert/CertificateParsingException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/CertificateParsingException.java
+ojluni/src/main/java/javax/security/cert/X509Certificate.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/X509Certificate.java
+ojluni/src/main/java/javax/security/cert/package-info.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/javax/security/cert/package-info.java
+ojluni/src/main/java/javax/sql/CommonDataSource.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/javax/sql/CommonDataSource.java
+ojluni/src/main/java/javax/sql/ConnectionEvent.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/ConnectionEvent.java
+ojluni/src/main/java/javax/sql/ConnectionEventListener.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/ConnectionEventListener.java
+ojluni/src/main/java/javax/sql/ConnectionPoolDataSource.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/javax/sql/ConnectionPoolDataSource.java
+ojluni/src/main/java/javax/sql/DataSource.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/javax/sql/DataSource.java
+ojluni/src/main/java/javax/sql/PooledConnection.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/javax/sql/PooledConnection.java
+ojluni/src/main/java/javax/sql/RowSet.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/javax/sql/RowSet.java
+ojluni/src/main/java/javax/sql/RowSetEvent.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/RowSetEvent.java
+ojluni/src/main/java/javax/sql/RowSetInternal.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/RowSetInternal.java
+ojluni/src/main/java/javax/sql/RowSetListener.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/RowSetListener.java
+ojluni/src/main/java/javax/sql/RowSetMetaData.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/RowSetMetaData.java
+ojluni/src/main/java/javax/sql/RowSetReader.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/RowSetReader.java
+ojluni/src/main/java/javax/sql/RowSetWriter.java,jdk11u/jdk-11.0.13-ga,src/java.sql/share/classes/javax/sql/RowSetWriter.java
+ojluni/src/main/java/javax/sql/StatementEvent.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/javax/sql/StatementEvent.java
+ojluni/src/main/java/javax/sql/StatementEventListener.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/javax/sql/StatementEventListener.java
+ojluni/src/main/java/jdk/internal/HotSpotIntrinsicCandidate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/HotSpotIntrinsicCandidate.java
+ojluni/src/main/java/jdk/internal/math/DoubleConsts.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/math/DoubleConsts.java
+ojluni/src/main/java/jdk/internal/math/FDBigInteger.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/math/FDBigInteger.java
+ojluni/src/main/java/jdk/internal/math/FloatConsts.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/math/FloatConsts.java
+ojluni/src/main/java/jdk/internal/math/FloatingDecimal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java
+ojluni/src/main/java/jdk/internal/math/FormattedFloatingDecimal.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java
+ojluni/src/main/java/jdk/internal/misc/InnocuousThread.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java
+ojluni/src/main/java/jdk/internal/misc/JavaIOFileDescriptorAccess.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/misc/JavaIOFileDescriptorAccess.java
+ojluni/src/main/java/jdk/internal/misc/JavaObjectInputStreamAccess.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/misc/JavaObjectInputStreamAccess.java
+ojluni/src/main/java/jdk/internal/misc/SharedSecrets.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java
+ojluni/src/main/java/jdk/internal/misc/Unsafe.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/misc/Unsafe.java
+ojluni/src/main/java/jdk/internal/misc/VM.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/misc/VM.java
+ojluni/src/main/java/jdk/internal/ref/Cleaner.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/ref/Cleaner.java
+ojluni/src/main/java/jdk/internal/ref/CleanerFactory.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/ref/CleanerFactory.java
+ojluni/src/main/java/jdk/internal/ref/CleanerImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java
+ojluni/src/main/java/jdk/internal/ref/PhantomCleanable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/ref/PhantomCleanable.java
+ojluni/src/main/java/jdk/internal/reflect/CallerSensitive.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/reflect/CallerSensitive.java
+ojluni/src/main/java/jdk/internal/reflect/Reflection.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/reflect/Reflection.java
+ojluni/src/main/java/jdk/internal/util/ArraysSupport.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/util/ArraysSupport.java
+ojluni/src/main/java/jdk/internal/util/Preconditions.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/util/Preconditions.java
+ojluni/src/main/java/jdk/internal/vm/annotation/Contended.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/vm/annotation/Contended.java
+ojluni/src/main/java/jdk/internal/vm/annotation/ReservedStackAccess.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/vm/annotation/ReservedStackAccess.java
+ojluni/src/main/java/jdk/internal/vm/annotation/Stable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java
+ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java,jdk11u/jdk-11.0.13-ga,src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java
+ojluni/src/main/java/jdk/net/NetworkPermission.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/jdk/net/NetworkPermission.java
+ojluni/src/main/java/jdk/net/SocketFlow.java,jdk11u/jdk-11.0.13-ga,src/jdk.net/share/classes/jdk/net/SocketFlow.java
+ojluni/src/main/java/jdk/net/Sockets.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/jdk/net/Sockets.java
+ojluni/src/main/java/sun/invoke/util/BytecodeDescriptor.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java
+ojluni/src/main/java/sun/invoke/util/VerifyAccess.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/invoke/util/VerifyAccess.java
+ojluni/src/main/java/sun/invoke/util/Wrapper.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/invoke/util/Wrapper.java
+ojluni/src/main/java/sun/misc/ASCIICaseInsensitiveComparator.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java
+ojluni/src/main/java/sun/misc/BASE64Decoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/BASE64Decoder.java
+ojluni/src/main/java/sun/misc/BASE64Encoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/BASE64Encoder.java
+ojluni/src/main/java/sun/misc/CEFormatException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/CEFormatException.java
+ojluni/src/main/java/sun/misc/CEStreamExhausted.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/CEStreamExhausted.java
+ojluni/src/main/java/sun/misc/CharacterDecoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/CharacterDecoder.java
+ojluni/src/main/java/sun/misc/CharacterEncoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/CharacterEncoder.java
+ojluni/src/main/java/sun/misc/Cleaner.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/Cleaner.java
+ojluni/src/main/java/sun/misc/CompoundEnumeration.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/CompoundEnumeration.java
+ojluni/src/main/java/sun/misc/FileURLMapper.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/misc/FileURLMapper.java
+ojluni/src/main/java/sun/misc/FpUtils.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/FpUtils.java
+ojluni/src/main/java/sun/misc/HexDumpEncoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/HexDumpEncoder.java
+ojluni/src/main/java/sun/misc/IOUtils.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/IOUtils.java
+ojluni/src/main/java/sun/misc/InvalidJarIndexException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/InvalidJarIndexException.java
+ojluni/src/main/java/sun/misc/JarIndex.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/JarIndex.java
+ojluni/src/main/java/sun/misc/JavaIOFileDescriptorAccess.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
+ojluni/src/main/java/sun/misc/LRUCache.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/LRUCache.java
+ojluni/src/main/java/sun/misc/MessageUtils.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/MessageUtils.java
+ojluni/src/main/java/sun/misc/MetaIndex.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/MetaIndex.java
+ojluni/src/main/java/sun/misc/REException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/REException.java
+ojluni/src/main/java/sun/misc/RegexpPool.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/RegexpPool.java
+ojluni/src/main/java/sun/misc/RegexpTarget.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/RegexpTarget.java
+ojluni/src/main/java/sun/misc/Resource.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/Resource.java
+ojluni/src/main/java/sun/misc/SharedSecrets.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/SharedSecrets.java
+ojluni/src/main/java/sun/misc/URLClassPath.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/URLClassPath.java
+ojluni/src/main/java/sun/misc/Unsafe.java,jdk7u/jdk7u40-b60,jdk/src/share/classes/sun/misc/Unsafe.java
+ojluni/src/main/java/sun/misc/VM.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/VM.java
+ojluni/src/main/java/sun/misc/Version.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/misc/Version.java.template
+ojluni/src/main/java/sun/net/ApplicationProxy.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ApplicationProxy.java
+ojluni/src/main/java/sun/net/ConnectionResetException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ConnectionResetException.java
+ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java
+ojluni/src/main/java/sun/net/NetHooks.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/net/NetHooks.java
+ojluni/src/main/java/sun/net/NetProperties.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/NetProperties.java
+ojluni/src/main/java/sun/net/NetworkClient.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/NetworkClient.java
+ojluni/src/main/java/sun/net/ProgressEvent.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ProgressEvent.java
+ojluni/src/main/java/sun/net/ProgressListener.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ProgressListener.java
+ojluni/src/main/java/sun/net/ProgressMeteringPolicy.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java
+ojluni/src/main/java/sun/net/ProgressMonitor.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/ProgressMonitor.java
+ojluni/src/main/java/sun/net/ProgressSource.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ProgressSource.java
+ojluni/src/main/java/sun/net/ResourceManager.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/ResourceManager.java
+ojluni/src/main/java/sun/net/SocksProxy.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/SocksProxy.java
+ojluni/src/main/java/sun/net/TelnetInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/TelnetInputStream.java
+ojluni/src/main/java/sun/net/TelnetOutputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/TelnetOutputStream.java
+ojluni/src/main/java/sun/net/TelnetProtocolException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/TelnetProtocolException.java
+ojluni/src/main/java/sun/net/ext/ExtendedSocketOptions.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java
+ojluni/src/main/java/sun/net/ftp/FtpClient.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/ftp/FtpClient.java
+ojluni/src/main/java/sun/net/ftp/FtpClientProvider.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java
+ojluni/src/main/java/sun/net/ftp/FtpDirEntry.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ftp/FtpDirEntry.java
+ojluni/src/main/java/sun/net/ftp/FtpDirParser.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ftp/FtpDirParser.java
+ojluni/src/main/java/sun/net/ftp/FtpLoginException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ftp/FtpLoginException.java
+ojluni/src/main/java/sun/net/ftp/FtpProtocolException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ftp/FtpProtocolException.java
+ojluni/src/main/java/sun/net/ftp/FtpReplyCode.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ftp/FtpReplyCode.java
+ojluni/src/main/java/sun/net/ftp/impl/DefaultFtpClientProvider.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/ftp/impl/DefaultFtpClientProvider.java
+ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java
+ojluni/src/main/java/sun/net/spi/DefaultProxySelector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java
+ojluni/src/main/java/sun/net/spi/nameservice/NameService.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/spi/nameservice/NameService.java
+ojluni/src/main/java/sun/net/util/IPAddressUtil.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/util/IPAddressUtil.java
+ojluni/src/main/java/sun/net/util/URLUtil.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/util/URLUtil.java
+ojluni/src/main/java/sun/net/www/MessageHeader.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/MessageHeader.java
+ojluni/src/main/java/sun/net/www/MeteredStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/MeteredStream.java
+ojluni/src/main/java/sun/net/www/ParseUtil.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/ParseUtil.java
+ojluni/src/main/java/sun/net/www/URLConnection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/URLConnection.java
+ojluni/src/main/java/sun/net/www/protocol/file/FileURLConnection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/protocol/file/FileURLConnection.java
+ojluni/src/main/java/sun/net/www/protocol/file/Handler.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/net/www/protocol/file/Handler.java
+ojluni/src/main/java/sun/net/www/protocol/ftp/FtpURLConnection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
+ojluni/src/main/java/sun/net/www/protocol/ftp/Handler.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java
+ojluni/src/main/java/sun/net/www/protocol/jar/Handler.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/protocol/jar/Handler.java
+ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java
+ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/protocol/jar/JarURLConnection.java
+ojluni/src/main/java/sun/net/www/protocol/jar/URLJarFile.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/net/www/protocol/jar/URLJarFile.java
+ojluni/src/main/java/sun/nio/ByteBuffered.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ByteBuffered.java
+ojluni/src/main/java/sun/nio/ch/AbstractPollArrayWrapper.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java
+ojluni/src/main/java/sun/nio/ch/AbstractPollSelectorImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java
+ojluni/src/main/java/sun/nio/ch/AllocatedNativeObject.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/AllocatedNativeObject.java
+ojluni/src/main/java/sun/nio/ch/AsynchronousChannelGroupImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java
+ojluni/src/main/java/sun/nio/ch/AsynchronousFileChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/AsynchronousServerSocketChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/AsynchronousSocketChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/Cancellable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/Cancellable.java
+ojluni/src/main/java/sun/nio/ch/ChannelInputStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java
+ojluni/src/main/java/sun/nio/ch/CompletedFuture.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/CompletedFuture.java
+ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/DatagramDispatcher.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/ch/DatagramDispatcher.java
+ojluni/src/main/java/sun/nio/ch/DatagramSocketAdaptor.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java
+ojluni/src/main/java/sun/nio/ch/DefaultAsynchronousChannelProvider.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/DefaultAsynchronousChannelProvider.java
+ojluni/src/main/java/sun/nio/ch/DefaultSelectorProvider.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/DefaultSelectorProvider.java
+ojluni/src/main/java/sun/nio/ch/DirectBuffer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/DirectBuffer.java
+ojluni/src/main/java/sun/nio/ch/EPoll.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/EPoll.java
+ojluni/src/main/java/sun/nio/ch/EPollPort.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/EPollPort.java
+ojluni/src/main/java/sun/nio/ch/ExtendedSocketOption.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/ExtendedSocketOption.java
+ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java
+# sun.nio.ch.FileDescriptorHolderSocketImpl doesn’t come from the upstream OpenJDK.
+ojluni/src/main/java/sun/nio/ch/FileDispatcher.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/FileDispatcher.java
+ojluni/src/main/java/sun/nio/ch/FileDispatcherImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java
+ojluni/src/main/java/sun/nio/ch/FileKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/ch/FileKey.java
+ojluni/src/main/java/sun/nio/ch/FileLockImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/FileLockImpl.java
+ojluni/src/main/java/sun/nio/ch/FileLockTable.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/FileLockTable.java
+ojluni/src/main/java/sun/nio/ch/Groupable.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/Groupable.java
+ojluni/src/main/java/sun/nio/ch/IOStatus.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/IOStatus.java
+ojluni/src/main/java/sun/nio/ch/IOUtil.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/IOUtil.java
+ojluni/src/main/java/sun/nio/ch/IOVecWrapper.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/IOVecWrapper.java
+ojluni/src/main/java/sun/nio/ch/Interruptible.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/Interruptible.java
+ojluni/src/main/java/sun/nio/ch/Invoker.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/Invoker.java
+ojluni/src/main/java/sun/nio/ch/LinuxAsynchronousChannelProvider.java,jdk11u/jdk-11.0.13-ga,src/java.base/linux/classes/sun/nio/ch/LinuxAsynchronousChannelProvider.java
+ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/MembershipKeyImpl.java
+ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/MembershipRegistry.java
+ojluni/src/main/java/sun/nio/ch/NativeDispatcher.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/NativeDispatcher.java
+ojluni/src/main/java/sun/nio/ch/NativeObject.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/NativeObject.java
+ojluni/src/main/java/sun/nio/ch/NativeThread.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/ch/NativeThread.java
+ojluni/src/main/java/sun/nio/ch/NativeThreadSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/NativeThreadSet.java
+ojluni/src/main/java/sun/nio/ch/Net.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/Net.java
+ojluni/src/main/java/sun/nio/ch/OptionKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/OptionKey.java
+ojluni/src/main/java/sun/nio/ch/PendingFuture.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/PendingFuture.java
+ojluni/src/main/java/sun/nio/ch/PipeImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/ch/PipeImpl.java
+ojluni/src/main/java/sun/nio/ch/PollArrayWrapper.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java
+ojluni/src/main/java/sun/nio/ch/PollSelectorImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/PollSelectorImpl.java
+ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/ch/PollSelectorProvider.java
+ojluni/src/main/java/sun/nio/ch/Port.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/ch/Port.java
+ojluni/src/main/java/sun/nio/ch/SelChImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/SelChImpl.java
+ojluni/src/main/java/sun/nio/ch/SelectionKeyImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/SelectionKeyImpl.java
+ojluni/src/main/java/sun/nio/ch/SelectorImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/SelectorImpl.java
+ojluni/src/main/java/sun/nio/ch/SelectorProviderImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/SelectorProviderImpl.java
+ojluni/src/main/java/sun/nio/ch/ServerSocketAdaptor.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java
+ojluni/src/main/java/sun/nio/ch/ServerSocketChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/SinkChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/SocketAdaptor.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/SocketAdaptor.java
+ojluni/src/main/java/sun/nio/ch/SocketChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/SocketDispatcher.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/SocketDispatcher.java
+# sun.nio.ch.SocketOptionRegistry was generated by C code and Make file in 8u121-b13. In the future, we can map this file to
+# src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template when the file is upgraded to OpenJDK 11
+# ojluni/src/main/java/sun/nio/ch/SocketOptionRegistry.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/ch/SocketOptionRegistry.java.template
+ojluni/src/main/java/sun/nio/ch/SourceChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/ThreadPool.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/ThreadPool.java
+ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
+ojluni/src/main/java/sun/nio/ch/Util.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/ch/Util.java
+ojluni/src/main/java/sun/nio/cs/ArrayDecoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/cs/ArrayDecoder.java
+ojluni/src/main/java/sun/nio/cs/ArrayEncoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/cs/ArrayEncoder.java
+ojluni/src/main/java/sun/nio/cs/HistoricallyNamedCharset.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/cs/HistoricallyNamedCharset.java
+ojluni/src/main/java/sun/nio/cs/StreamDecoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/cs/StreamDecoder.java
+ojluni/src/main/java/sun/nio/cs/StreamEncoder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/cs/StreamEncoder.java
+ojluni/src/main/java/sun/nio/cs/ThreadLocalCoders.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/cs/ThreadLocalCoders.java
+ojluni/src/main/java/sun/nio/fs/AbstractBasicFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/fs/AbstractBasicFileAttributeView.java
+ojluni/src/main/java/sun/nio/fs/AbstractFileSystemProvider.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/AbstractFileSystemProvider.java
+ojluni/src/main/java/sun/nio/fs/AbstractFileTypeDetector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/AbstractFileTypeDetector.java
+ojluni/src/main/java/sun/nio/fs/AbstractPath.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/AbstractPath.java
+ojluni/src/main/java/sun/nio/fs/AbstractPoller.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/AbstractPoller.java
+ojluni/src/main/java/sun/nio/fs/AbstractUserDefinedFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/fs/AbstractUserDefinedFileAttributeView.java
+ojluni/src/main/java/sun/nio/fs/AbstractWatchKey.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java
+ojluni/src/main/java/sun/nio/fs/AbstractWatchService.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/fs/AbstractWatchService.java
+ojluni/src/main/java/sun/nio/fs/BasicFileAttributesHolder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/fs/BasicFileAttributesHolder.java
+ojluni/src/main/java/sun/nio/fs/Cancellable.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/Cancellable.java
+ojluni/src/main/java/sun/nio/fs/DefaultFileSystemProvider.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/DefaultFileSystemProvider.java
+ojluni/src/main/java/sun/nio/fs/DefaultFileTypeDetector.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/DefaultFileTypeDetector.java
+ojluni/src/main/java/sun/nio/fs/DynamicFileAttributeView.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/fs/DynamicFileAttributeView.java
+ojluni/src/main/java/sun/nio/fs/FileOwnerAttributeViewImpl.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/fs/FileOwnerAttributeViewImpl.java
+ojluni/src/main/java/sun/nio/fs/Globs.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/nio/fs/Globs.java
+ojluni/src/main/java/sun/nio/fs/LinuxDosFileAttributeView.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/LinuxDosFileAttributeView.java
+ojluni/src/main/java/sun/nio/fs/LinuxFileStore.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/LinuxFileStore.java
+ojluni/src/main/java/sun/nio/fs/LinuxFileSystem.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystem.java
+ojluni/src/main/java/sun/nio/fs/LinuxFileSystemProvider.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/LinuxFileSystemProvider.java
+ojluni/src/main/java/sun/nio/fs/LinuxNativeDispatcher.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/LinuxNativeDispatcher.java
+ojluni/src/main/java/sun/nio/fs/LinuxUserDefinedFileAttributeView.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/LinuxUserDefinedFileAttributeView.java
+ojluni/src/main/java/sun/nio/fs/LinuxWatchService.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/LinuxWatchService.java
+ojluni/src/main/java/sun/nio/fs/MimeTypesFileTypeDetector.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/MimeTypesFileTypeDetector.java
+ojluni/src/main/java/sun/nio/fs/NativeBuffer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/NativeBuffer.java
+ojluni/src/main/java/sun/nio/fs/NativeBuffers.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/NativeBuffers.java
+ojluni/src/main/java/sun/nio/fs/PollingWatchService.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/PollingWatchService.java
+ojluni/src/main/java/sun/nio/fs/UnixChannelFactory.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixChannelFactory.java
+# sun.nio.fs.UnixConstants was generated by C code and Make-like file in jdk8u/jdk8u121. But in a later version, the file
+# is generated by a template file, and we can map to the template when the file is upgraded to OpenJDK 11.
+# ojluni/src/main/java/sun/nio/fs/UnixConstants.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template
+ojluni/src/main/java/sun/nio/fs/UnixCopyFile.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixCopyFile.java
+ojluni/src/main/java/sun/nio/fs/UnixDirectoryStream.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java
+ojluni/src/main/java/sun/nio/fs/UnixException.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixException.java
+ojluni/src/main/java/sun/nio/fs/UnixFileAttributeViews.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixFileAttributeViews.java
+ojluni/src/main/java/sun/nio/fs/UnixFileAttributes.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixFileAttributes.java
+ojluni/src/main/java/sun/nio/fs/UnixFileKey.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixFileKey.java
+ojluni/src/main/java/sun/nio/fs/UnixFileModeAttribute.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixFileModeAttribute.java
+ojluni/src/main/java/sun/nio/fs/UnixFileStore.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixFileStore.java
+ojluni/src/main/java/sun/nio/fs/UnixFileStoreAttributes.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixFileStoreAttributes.java
+ojluni/src/main/java/sun/nio/fs/UnixFileSystem.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixFileSystem.java
+ojluni/src/main/java/sun/nio/fs/UnixFileSystemProvider.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixFileSystemProvider.java
+ojluni/src/main/java/sun/nio/fs/UnixMountEntry.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixMountEntry.java
+ojluni/src/main/java/sun/nio/fs/UnixNativeDispatcher.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java
+ojluni/src/main/java/sun/nio/fs/UnixPath.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixPath.java
+ojluni/src/main/java/sun/nio/fs/UnixSecureDirectoryStream.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java
+ojluni/src/main/java/sun/nio/fs/UnixUriUtils.java,jdk8u/jdk8u121-b13,jdk/src/solaris/classes/sun/nio/fs/UnixUriUtils.java
+ojluni/src/main/java/sun/nio/fs/UnixUserPrincipals.java,jdk11u/jdk-11.0.13-ga,src/java.base/unix/classes/sun/nio/fs/UnixUserPrincipals.java
+ojluni/src/main/java/sun/nio/fs/Util.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/nio/fs/Util.java
+ojluni/src/main/java/sun/reflect/CallerSensitive.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/reflect/CallerSensitive.java
+ojluni/src/main/java/sun/reflect/Reflection.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/reflect/Reflection.java
+ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java
+ojluni/src/main/java/sun/security/action/GetBooleanAction.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/action/GetBooleanAction.java
+ojluni/src/main/java/sun/security/action/GetIntegerAction.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/action/GetIntegerAction.java
+ojluni/src/main/java/sun/security/action/GetPropertyAction.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/action/GetPropertyAction.java
+ojluni/src/main/java/sun/security/jca/GetInstance.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/jca/GetInstance.java
+ojluni/src/main/java/sun/security/jca/JCAUtil.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/jca/JCAUtil.java
+ojluni/src/main/java/sun/security/jca/ProviderConfig.java,jdk8u/jdk8u60-b31,jdk/src/share/classes/sun/security/jca/ProviderConfig.java
+ojluni/src/main/java/sun/security/jca/ProviderList.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/jca/ProviderList.java
+ojluni/src/main/java/sun/security/jca/Providers.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/jca/Providers.java
+ojluni/src/main/java/sun/security/jca/ServiceId.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/jca/ServiceId.java
+ojluni/src/main/java/sun/security/pkcs/ContentInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/pkcs/ContentInfo.java
+ojluni/src/main/java/sun/security/pkcs/PKCS7.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/pkcs/PKCS7.java
+ojluni/src/main/java/sun/security/pkcs/PKCS8Key.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/pkcs/PKCS8Key.java
+ojluni/src/main/java/sun/security/pkcs/PKCS9Attribute.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/pkcs/PKCS9Attribute.java
+ojluni/src/main/java/sun/security/pkcs/PKCS9Attributes.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/pkcs/PKCS9Attributes.java
+ojluni/src/main/java/sun/security/pkcs/ParsingException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/pkcs/ParsingException.java
+ojluni/src/main/java/sun/security/pkcs/SignerInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/pkcs/SignerInfo.java
+ojluni/src/main/java/sun/security/pkcs/SigningCertificateInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/pkcs/SigningCertificateInfo.java
+# CertPathProvider was introduced in bf0403930ae8d1e86b3914d18b9711eeeec0adb9. Apparently, it came from SunEntries in the upstream.
+# CertPathProvider implemented only some of SunEntries because Android kept CertPathBuilder and CertPathValidator providers.
+ojluni/src/main/java/sun/security/provider/CertPathProvider.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/SunEntries.java
+ojluni/src/main/java/sun/security/provider/X509Factory.java,jdk8u/jdk8u60-b31,jdk/src/share/classes/sun/security/provider/X509Factory.java
+ojluni/src/main/java/sun/security/provider/certpath/AdaptableX509CertSelector.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/AdaptableX509CertSelector.java
+ojluni/src/main/java/sun/security/provider/certpath/AdjacencyList.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java
+ojluni/src/main/java/sun/security/provider/certpath/AlgorithmChecker.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java
+ojluni/src/main/java/sun/security/provider/certpath/BasicChecker.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java
+ojluni/src/main/java/sun/security/provider/certpath/BuildStep.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java
+ojluni/src/main/java/sun/security/provider/certpath/Builder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/Builder.java
+ojluni/src/main/java/sun/security/provider/certpath/CertId.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/CertId.java
+ojluni/src/main/java/sun/security/provider/certpath/CertPathHelper.java,jdk11u/jdk-11+28,src/java.base/share/classes/sun/security/provider/certpath/CertPathHelper.java
+ojluni/src/main/java/sun/security/provider/certpath/CertStoreHelper.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java
+ojluni/src/main/java/sun/security/provider/certpath/ConstraintsChecker.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/ConstraintsChecker.java
+ojluni/src/main/java/sun/security/provider/certpath/DistributionPointFetcher.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
+ojluni/src/main/java/sun/security/provider/certpath/ForwardBuilder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/ForwardBuilder.java
+ojluni/src/main/java/sun/security/provider/certpath/ForwardState.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/ForwardState.java
+ojluni/src/main/java/sun/security/provider/certpath/KeyChecker.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/KeyChecker.java
+ojluni/src/main/java/sun/security/provider/certpath/OCSP.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/OCSP.java
+ojluni/src/main/java/sun/security/provider/certpath/OCSPRequest.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java
+ojluni/src/main/java/sun/security/provider/certpath/OCSPResponse.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
+ojluni/src/main/java/sun/security/provider/certpath/PKIX.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/PKIX.java
+ojluni/src/main/java/sun/security/provider/certpath/PKIXCertPathValidator.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
+ojluni/src/main/java/sun/security/provider/certpath/PKIXMasterCertPathValidator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
+ojluni/src/main/java/sun/security/provider/certpath/PolicyChecker.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java
+ojluni/src/main/java/sun/security/provider/certpath/PolicyNodeImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java
+ojluni/src/main/java/sun/security/provider/certpath/RevocationChecker.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
+ojluni/src/main/java/sun/security/provider/certpath/State.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/State.java
+ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
+ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderException.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderException.java
+ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderResult.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/SunCertPathBuilderResult.java
+ojluni/src/main/java/sun/security/provider/certpath/URICertStore.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java
+ojluni/src/main/java/sun/security/provider/certpath/Vertex.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/provider/certpath/Vertex.java
+ojluni/src/main/java/sun/security/provider/certpath/X509CertPath.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/X509CertPath.java
+ojluni/src/main/java/sun/security/provider/certpath/X509CertificatePair.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/provider/certpath/X509CertificatePair.java
+ojluni/src/main/java/sun/security/timestamp/TimestampToken.java,jdk8u/jdk8u60-b31,jdk/src/share/classes/sun/security/timestamp/TimestampToken.java
+ojluni/src/main/java/sun/security/util/AbstractAlgorithmConstraints.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java
+ojluni/src/main/java/sun/security/util/AlgorithmDecomposer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/AlgorithmDecomposer.java
+ojluni/src/main/java/sun/security/util/AnchorCertificates.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/AnchorCertificates.java
+ojluni/src/main/java/sun/security/util/BitArray.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/BitArray.java
+ojluni/src/main/java/sun/security/util/ByteArrayLexOrder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/ByteArrayLexOrder.java
+ojluni/src/main/java/sun/security/util/ByteArrayTagOrder.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/ByteArrayTagOrder.java
+ojluni/src/main/java/sun/security/util/Cache.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/Cache.java
+ojluni/src/main/java/sun/security/util/CertConstraintParameters.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/CertConstraintParameters.java
+ojluni/src/main/java/sun/security/util/Debug.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/Debug.java
+ojluni/src/main/java/sun/security/util/DerEncoder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/util/DerEncoder.java
+ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/DerIndefLenConverter.java
+ojluni/src/main/java/sun/security/util/DerInputBuffer.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/DerInputBuffer.java
+ojluni/src/main/java/sun/security/util/DerInputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/DerInputStream.java
+ojluni/src/main/java/sun/security/util/DerOutputStream.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/DerOutputStream.java
+ojluni/src/main/java/sun/security/util/DerValue.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/DerValue.java
+ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java
+ojluni/src/main/java/sun/security/util/KeyUtil.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/KeyUtil.java
+ojluni/src/main/java/sun/security/util/Length.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/util/Length.java
+ojluni/src/main/java/sun/security/util/ManifestDigester.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/ManifestDigester.java
+ojluni/src/main/java/sun/security/util/ManifestEntryVerifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java
+ojluni/src/main/java/sun/security/util/ObjectIdentifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/ObjectIdentifier.java
+ojluni/src/main/java/sun/security/util/PropertyExpander.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/PropertyExpander.java
+ojluni/src/main/java/sun/security/util/Resources.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/Resources.java
+ojluni/src/main/java/sun/security/util/ResourcesMgr.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/ResourcesMgr.java
+ojluni/src/main/java/sun/security/util/SecurityConstants.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/util/SecurityConstants.java
+ojluni/src/main/java/sun/security/util/SignatureFileVerifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java
+ojluni/src/main/java/sun/security/x509/AVA.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/AVA.java
+ojluni/src/main/java/sun/security/x509/AccessDescription.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/AccessDescription.java
+ojluni/src/main/java/sun/security/x509/AlgorithmId.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/AlgorithmId.java
+ojluni/src/main/java/sun/security/x509/AttributeNameEnumeration.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/AttributeNameEnumeration.java
+ojluni/src/main/java/sun/security/x509/AuthorityInfoAccessExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java
+ojluni/src/main/java/sun/security/x509/AuthorityKeyIdentifierExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/AuthorityKeyIdentifierExtension.java
+ojluni/src/main/java/sun/security/x509/BasicConstraintsExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/BasicConstraintsExtension.java
+ojluni/src/main/java/sun/security/x509/CRLDistributionPointsExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CRLDistributionPointsExtension.java
+ojluni/src/main/java/sun/security/x509/CRLExtensions.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CRLExtensions.java
+ojluni/src/main/java/sun/security/x509/CRLNumberExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CRLNumberExtension.java
+ojluni/src/main/java/sun/security/x509/CRLReasonCodeExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CRLReasonCodeExtension.java
+ojluni/src/main/java/sun/security/x509/CertAttrSet.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/CertAttrSet.java
+ojluni/src/main/java/sun/security/x509/CertificateAlgorithmId.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/CertificateAlgorithmId.java
+ojluni/src/main/java/sun/security/x509/CertificateExtensions.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificateExtensions.java
+ojluni/src/main/java/sun/security/x509/CertificateIssuerExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificateIssuerExtension.java
+ojluni/src/main/java/sun/security/x509/CertificateIssuerName.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/CertificateIssuerName.java
+ojluni/src/main/java/sun/security/x509/CertificatePoliciesExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificatePoliciesExtension.java
+ojluni/src/main/java/sun/security/x509/CertificatePolicyId.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificatePolicyId.java
+ojluni/src/main/java/sun/security/x509/CertificatePolicyMap.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/CertificatePolicyMap.java
+ojluni/src/main/java/sun/security/x509/CertificatePolicySet.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificatePolicySet.java
+ojluni/src/main/java/sun/security/x509/CertificateSerialNumber.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificateSerialNumber.java
+ojluni/src/main/java/sun/security/x509/CertificateSubjectName.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/CertificateSubjectName.java
+ojluni/src/main/java/sun/security/x509/CertificateValidity.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificateValidity.java
+ojluni/src/main/java/sun/security/x509/CertificateVersion.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/CertificateVersion.java
+ojluni/src/main/java/sun/security/x509/CertificateX509Key.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/CertificateX509Key.java
+ojluni/src/main/java/sun/security/x509/DNSName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/DNSName.java
+ojluni/src/main/java/sun/security/x509/DeltaCRLIndicatorExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java
+ojluni/src/main/java/sun/security/x509/DistributionPoint.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/DistributionPoint.java
+ojluni/src/main/java/sun/security/x509/DistributionPointName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/DistributionPointName.java
+ojluni/src/main/java/sun/security/x509/EDIPartyName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/EDIPartyName.java
+ojluni/src/main/java/sun/security/x509/ExtendedKeyUsageExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java
+ojluni/src/main/java/sun/security/x509/Extension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/Extension.java
+ojluni/src/main/java/sun/security/x509/FreshestCRLExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/FreshestCRLExtension.java
+ojluni/src/main/java/sun/security/x509/GeneralName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/GeneralName.java
+ojluni/src/main/java/sun/security/x509/GeneralNameInterface.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/GeneralNameInterface.java
+ojluni/src/main/java/sun/security/x509/GeneralNames.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/GeneralNames.java
+ojluni/src/main/java/sun/security/x509/GeneralSubtree.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/GeneralSubtree.java
+ojluni/src/main/java/sun/security/x509/GeneralSubtrees.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/GeneralSubtrees.java
+ojluni/src/main/java/sun/security/x509/IPAddressName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/IPAddressName.java
+ojluni/src/main/java/sun/security/x509/InhibitAnyPolicyExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/InhibitAnyPolicyExtension.java
+ojluni/src/main/java/sun/security/x509/InvalidityDateExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/InvalidityDateExtension.java
+ojluni/src/main/java/sun/security/x509/IssuerAlternativeNameExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/IssuerAlternativeNameExtension.java
+ojluni/src/main/java/sun/security/x509/IssuingDistributionPointExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/IssuingDistributionPointExtension.java
+ojluni/src/main/java/sun/security/x509/KeyIdentifier.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/KeyIdentifier.java
+ojluni/src/main/java/sun/security/x509/KeyUsageExtension.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/KeyUsageExtension.java
+ojluni/src/main/java/sun/security/x509/NameConstraintsExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/NameConstraintsExtension.java
+ojluni/src/main/java/sun/security/x509/NetscapeCertTypeExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/NetscapeCertTypeExtension.java
+ojluni/src/main/java/sun/security/x509/OCSPNoCheckExtension.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/OCSPNoCheckExtension.java
+ojluni/src/main/java/sun/security/x509/OIDMap.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/OIDMap.java
+ojluni/src/main/java/sun/security/x509/OIDName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/OIDName.java
+ojluni/src/main/java/sun/security/x509/OtherName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/OtherName.java
+ojluni/src/main/java/sun/security/x509/PKIXExtensions.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/PKIXExtensions.java
+ojluni/src/main/java/sun/security/x509/PolicyConstraintsExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/PolicyConstraintsExtension.java
+ojluni/src/main/java/sun/security/x509/PolicyInformation.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/PolicyInformation.java
+ojluni/src/main/java/sun/security/x509/PolicyMappingsExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/PolicyMappingsExtension.java
+ojluni/src/main/java/sun/security/x509/PrivateKeyUsageExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/PrivateKeyUsageExtension.java
+ojluni/src/main/java/sun/security/x509/RDN.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/RDN.java
+ojluni/src/main/java/sun/security/x509/RFC822Name.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/RFC822Name.java
+ojluni/src/main/java/sun/security/x509/ReasonFlags.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/ReasonFlags.java
+ojluni/src/main/java/sun/security/x509/SerialNumber.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/SerialNumber.java
+ojluni/src/main/java/sun/security/x509/SubjectAlternativeNameExtension.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/SubjectAlternativeNameExtension.java
+ojluni/src/main/java/sun/security/x509/SubjectInfoAccessExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/SubjectInfoAccessExtension.java
+ojluni/src/main/java/sun/security/x509/SubjectKeyIdentifierExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/SubjectKeyIdentifierExtension.java
+ojluni/src/main/java/sun/security/x509/URIName.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/URIName.java
+ojluni/src/main/java/sun/security/x509/UniqueIdentity.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/UniqueIdentity.java
+ojluni/src/main/java/sun/security/x509/X400Address.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/X400Address.java
+ojluni/src/main/java/sun/security/x509/X500Name.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/X500Name.java
+ojluni/src/main/java/sun/security/x509/X509AttributeName.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/security/x509/X509AttributeName.java
+ojluni/src/main/java/sun/security/x509/X509CRLEntryImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java
+ojluni/src/main/java/sun/security/x509/X509CRLImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/X509CRLImpl.java
+ojluni/src/main/java/sun/security/x509/X509CertImpl.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/X509CertImpl.java
+ojluni/src/main/java/sun/security/x509/X509CertInfo.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/X509CertInfo.java
+ojluni/src/main/java/sun/security/x509/X509Key.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/security/x509/X509Key.java
+ojluni/src/main/java/sun/util/ResourceBundleEnumeration.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/ResourceBundleEnumeration.java
+ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/calendar/AbstractCalendar.java
+ojluni/src/main/java/sun/util/calendar/BaseCalendar.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/calendar/BaseCalendar.java
+ojluni/src/main/java/sun/util/calendar/CalendarDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/calendar/CalendarDate.java
+ojluni/src/main/java/sun/util/calendar/CalendarSystem.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/calendar/CalendarSystem.java
+ojluni/src/main/java/sun/util/calendar/CalendarUtils.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/calendar/CalendarUtils.java
+ojluni/src/main/java/sun/util/calendar/Era.java,jdk8u/jdk8u212-b01,jdk/src/share/classes/sun/util/calendar/Era.java
+ojluni/src/main/java/sun/util/calendar/Gregorian.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/calendar/Gregorian.java
+ojluni/src/main/java/sun/util/calendar/ImmutableGregorianDate.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/calendar/ImmutableGregorianDate.java
+ojluni/src/main/java/sun/util/calendar/JulianCalendar.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/calendar/JulianCalendar.java
+ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/calendar/LocalGregorianCalendar.java
+ojluni/src/main/java/sun/util/locale/BaseLocale.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/locale/BaseLocale.java
+ojluni/src/main/java/sun/util/locale/Extension.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/locale/Extension.java
+ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/locale/InternalLocaleBuilder.java
+ojluni/src/main/java/sun/util/locale/LanguageTag.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/locale/LanguageTag.java
+ojluni/src/main/java/sun/util/locale/LocaleEquivalentMaps.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/locale/LocaleEquivalentMaps.java
+ojluni/src/main/java/sun/util/locale/LocaleExtensions.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/locale/LocaleExtensions.java
+ojluni/src/main/java/sun/util/locale/LocaleMatcher.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/locale/LocaleMatcher.java
+ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/locale/LocaleObjectCache.java
+ojluni/src/main/java/sun/util/locale/LocaleSyntaxException.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/locale/LocaleSyntaxException.java
+ojluni/src/main/java/sun/util/locale/LocaleUtils.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/locale/LocaleUtils.java
+ojluni/src/main/java/sun/util/locale/ParseStatus.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/locale/ParseStatus.java
+ojluni/src/main/java/sun/util/locale/StringTokenIterator.java,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/sun/util/locale/StringTokenIterator.java
+ojluni/src/main/java/sun/util/locale/UnicodeLocaleExtension.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/locale/UnicodeLocaleExtension.java
+ojluni/src/main/java/sun/util/locale/provider/CalendarDataUtility.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java
+ojluni/src/main/java/sun/util/logging/LoggingProxy.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/logging/LoggingProxy.java
+ojluni/src/main/java/sun/util/logging/LoggingSupport.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/logging/LoggingSupport.java
+ojluni/src/main/java/sun/util/logging/PlatformLogger.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/logging/PlatformLogger.java
+ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java,jdk8u/jdk8u121-b13,jdk/src/share/classes/sun/util/resources/OpenListResourceBundle.java
+ojluni/src/main/native/Adler32.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/util/zip/Adler32.c
+ojluni/src/main/native/CRC32.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/util/zip/CRC32.c
+# Character.cpp doesn’t come from the upstream OpenJDK.
+ojluni/src/main/native/Console_md.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/java/io/Console_md.c
+ojluni/src/main/native/DatagramChannelImpl.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c
+ojluni/src/main/native/DatagramDispatcher.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/DatagramDispatcher.c
+ojluni/src/main/native/Deflater.c,jdk8u/jdk8u60-b31,jdk/src/share/native/java/util/zip/Deflater.c
+ojluni/src/main/native/Double.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/lang/Double.c
+ojluni/src/main/native/EPoll.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/EPoll.c
+ojluni/src/main/native/EPollPort.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/EPollPort.c
+ojluni/src/main/native/FileChannelImpl.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c
+ojluni/src/main/native/FileDescriptor_md.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/io/FileDescriptor_md.c
+ojluni/src/main/native/FileDispatcherImpl.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/FileDispatcherImpl.c
+ojluni/src/main/native/FileInputStream.c,jdk7u/jdk7u40-b60,jdk/src/share/native/java/io/FileInputStream.c
+ojluni/src/main/native/FileKey.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/sun/nio/ch/FileKey.c
+ojluni/src/main/native/FileSystemPreferences.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/util/FileSystemPreferences.c
+ojluni/src/main/native/Float.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/lang/Float.c
+ojluni/src/main/native/IOUtil.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/IOUtil.c
+ojluni/src/main/native/Inet4Address.c,jdk7u/jdk7u40-b60,jdk/src/share/native/java/net/Inet4Address.c
+ojluni/src/main/native/Inet6Address.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/net/Inet6Address.c
+ojluni/src/main/native/InetAddress.c,jdk8u/jdk8u60-b31,jdk/src/share/native/java/net/InetAddress.c
+ojluni/src/main/native/Inflater.c,jdk8u/jdk8u60-b31,jdk/src/share/native/java/util/zip/Inflater.c
+# JniConstants.cpp doesn’t come from the upstream OpenJDK.
+ojluni/src/main/native/LinuxNativeDispatcher.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/fs/LinuxNativeDispatcher.c
+ojluni/src/main/native/LinuxWatchService.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c
+ojluni/src/main/native/MappedByteBuffer.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/java/nio/MappedByteBuffer.c
+# Math.c doesn’t come from the upstream OpenJDK.
+ojluni/src/main/native/NativeThread.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/NativeThread.c
+ojluni/src/main/native/Net.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/Net.c
+ojluni/src/main/native/ObjectInputStream.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/io/ObjectInputStream.c
+ojluni/src/main/native/ObjectOutputStream.c,jdk7u/jdk7u40-b60,jdk/src/share/native/java/io/ObjectOutputStream.c
+ojluni/src/main/native/ObjectStreamClass.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/io/ObjectStreamClass.c
+# OnLoad.cpp doesn’t come from the upstream OpenJDK.
+ojluni/src/main/native/PollArrayWrapper.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/PollArrayWrapper.c
+ojluni/src/main/native/ProcessEnvironment_md.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/lang/ProcessEnvironment_md.c
+ojluni/src/main/native/Runtime.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/lang/Runtime.c
+ojluni/src/main/native/ServerSocketChannelImpl.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/ServerSocketChannelImpl.c
+ojluni/src/main/native/SocketChannelImpl.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/SocketChannelImpl.c
+ojluni/src/main/native/SocketInputStream.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/net/SocketInputStream.c
+ojluni/src/main/native/SocketOutputStream.c,jdk8u/jdk8u60-b31,jdk/src/solaris/native/java/net/SocketOutputStream.c
+ojluni/src/main/native/StrictMath.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/lang/StrictMath.c
+ojluni/src/main/native/System.c,jdk7u/jdk7u40-b60,jdk/src/share/native/java/lang/System.c
+ojluni/src/main/native/UNIXProcess_md.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/lang/UNIXProcess_md.c
+ojluni/src/main/native/UnixAsynchronousServerSocketChannelImpl.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.c
+ojluni/src/main/native/UnixAsynchronousSocketChannelImpl.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/ch/UnixAsynchronousSocketChannelImpl.c
+ojluni/src/main/native/UnixCopyFile.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/sun/nio/fs/UnixCopyFile.c
+ojluni/src/main/native/UnixFileSystem_md.c,jdk8u/jdk8u121-b13,jdk/src/solaris/native/java/io/UnixFileSystem_md.c
+ojluni/src/main/native/UnixNativeDispatcher.c,jdk8u/jdk8u60-b31,jdk/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c
+ojluni/src/main/native/ZipFile.c,jdk8u/jdk8u60-b31,jdk/src/share/native/java/util/zip/ZipFile.c
+ojluni/src/main/native/canonicalize_md.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/io/canonicalize_md.c
+ojluni/src/main/native/io_util.c,jdk7u/jdk7u40-b60,jdk/src/share/native/java/io/io_util.c
+ojluni/src/main/native/io_util_md.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/io/io_util_md.c
+ojluni/src/main/native/jni_util.c,jdk8u/jdk8u60-b31,jdk/src/share/native/common/jni_util.c
+ojluni/src/main/native/jni_util_md.c,jdk8u/jdk8u60-b31,jdk/src/solaris/native/common/jni_util_md.c
+ojluni/src/main/native/linux_close.cpp,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/net/linux_close.c
+ojluni/src/main/native/net_util.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/net/net_util.c
+ojluni/src/main/native/net_util_md.c,jdk7u/jdk7u40-b60,jdk/src/solaris/native/java/net/net_util_md.c
+# socket_tagger_util.cpp doesn’t come from the upstream OpenJDK.
+ojluni/src/main/native/zip_util.c,jdk8u/jdk8u121-b13,jdk/src/share/native/java/util/zip/zip_util.c
+ojluni/src/main/resources/calendars.properties,jdk8u/jdk8u212-b01,jdk/src/share/lib/calendars.properties
+ojluni/src/main/resources/java/time/chrono/hijrah-config-islamic-umalqura.properties,jdk11u/jdk-11.0.13-ga,src/java.base/share/classes/java/time/chrono/hijrah-config-islamic-umalqura.properties
+ojluni/src/test/java/io/Reader/NullReader.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/io/Reader/NullReader.java
+ojluni/src/test/java/io/Reader/TransferTo.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/io/Reader/TransferTo.java
+ojluni/src/test/java/io/Writer/NullWriter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/io/Writer/NullWriter.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleBaseTest.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleMethodReferenceTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleMethodReferenceTest.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessModeMethodNames.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessModeMethodNames.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java
+ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestReflection.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/VarHandleTestReflection.java
+ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template
+ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
+ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template
+ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template
+ojluni/src/test/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java
+ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/A.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/accessibility/pkg/A.java
+ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/B_extends_A.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/accessibility/pkg/B_extends_A.java
+ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/C.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/accessibility/pkg/C.java
+ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/B_extends_A.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/B_extends_A.java
+ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/C.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/C.java
+ojluni/src/test/java/lang/invoke/VarHandles/generate-vh-tests.sh,jdk11u/jdk-11.0.13-ga,test/jdk/java/lang/invoke/VarHandles/generate-vh-tests.sh
+ojluni/src/test/java/math/BigDecimal/AddTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/AddTests.java
+ojluni/src/test/java/math/BigDecimal/CompareToTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/CompareToTests.java
+ojluni/src/test/java/math/BigDecimal/Constructor.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/Constructor.java
+ojluni/src/test/java/math/BigDecimal/DivideMcTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/DivideMcTests.java
+ojluni/src/test/java/math/BigDecimal/DivideTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/DivideTests.java
+ojluni/src/test/java/math/BigDecimal/EqualsTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/EqualsTests.java
+ojluni/src/test/java/math/BigDecimal/FloatDoubleValueTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/FloatDoubleValueTests.java
+ojluni/src/test/java/math/BigDecimal/IntegralDivisionTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/IntegralDivisionTests.java
+ojluni/src/test/java/math/BigDecimal/LongValueExactTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/LongValueExactTests.java
+ojluni/src/test/java/math/BigDecimal/MultiplyTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/MultiplyTests.java
+ojluni/src/test/java/math/BigDecimal/NegateTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/NegateTests.java
+ojluni/src/test/java/math/BigDecimal/PowTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/PowTests.java
+ojluni/src/test/java/math/BigDecimal/PrecisionTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/PrecisionTests.java
+ojluni/src/test/java/math/BigDecimal/RangeTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/RangeTests.java
+ojluni/src/test/java/math/BigDecimal/RoundingTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/RoundingTests.java
+ojluni/src/test/java/math/BigDecimal/ScaleByPowerOfTenTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java
+ojluni/src/test/java/math/BigDecimal/SerializationTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/SerializationTests.java
+ojluni/src/test/java/math/BigDecimal/SquareRootTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/SquareRootTests.java
+ojluni/src/test/java/math/BigDecimal/StringConstructor.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/StringConstructor.java
+ojluni/src/test/java/math/BigDecimal/StrippingZerosTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/StrippingZerosTest.java
+ojluni/src/test/java/math/BigDecimal/ToPlainStringTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/ToPlainStringTests.java
+ojluni/src/test/java/math/BigDecimal/ZeroScalingTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigDecimal/ZeroScalingTests.java
+ojluni/src/test/java/math/BigInteger/BigIntegerTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/BigIntegerTest.java
+ojluni/src/test/java/math/BigInteger/CompareToTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/CompareToTests.java
+ojluni/src/test/java/math/BigInteger/ModPow.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/ModPow.java
+ojluni/src/test/java/math/BigInteger/OperatorNpeTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/OperatorNpeTests.java
+ojluni/src/test/java/math/BigInteger/PrimeTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/PrimeTest.java
+ojluni/src/test/java/math/BigInteger/PrimitiveConversionTests.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/PrimitiveConversionTests.java
+ojluni/src/test/java/math/BigInteger/ProbablePrime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/ProbablePrime.java
+ojluni/src/test/java/math/BigInteger/StringConstructor.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/StringConstructor.java
+ojluni/src/test/java/math/BigInteger/TestValueExact.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/TestValueExact.java
+ojluni/src/test/java/math/BigInteger/UnicodeConstructor.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/math/BigInteger/UnicodeConstructor.java
+ojluni/src/test/java/nio/channels/SelectionKey/AtomicUpdates.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/nio/channels/SelectionKey/AtomicUpdates.java
+ojluni/src/test/java/nio/channels/Selector/ByteServer.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/nio/channels/Selector/ByteServer.java
+ojluni/src/test/java/nio/channels/Selector/SelectAfterRead.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/nio/channels/Selector/SelectAfterRead.java
+ojluni/src/test/java/nio/channels/Selector/SelectWithConsumer.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/nio/channels/Selector/SelectWithConsumer.java
+ojluni/src/test/java/security/cert/CertPathEncodingTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/security/cert/CertPathEncodingTest.java
+ojluni/src/test/java/security/cert/GetInstance.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/security/cert/GetInstance.java
+ojluni/src/test/java/security/cert/URICertStoreParameters/TestBasic.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/security/cert/URICertStoreParameters/TestBasic.java
+ojluni/src/test/java/security/cert/X509CertSelectorTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/security/cert/X509CertSelectorTest.java
+ojluni/src/test/java/time/jdk/testlibrary/RandomFactory.java,jdk11u/jdk-11.0.13-ga,test/lib/jdk/test/lib/RandomFactory.java
+ojluni/src/test/java/time/tck/java/time/AbstractDateTimeTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/AbstractDateTimeTest.java
+ojluni/src/test/java/time/tck/java/time/AbstractTCKTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/AbstractTCKTest.java
+ojluni/src/test/java/time/tck/java/time/MockSimplePeriod.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/MockSimplePeriod.java
+ojluni/src/test/java/time/tck/java/time/TCKClock.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKClock.java
+ojluni/src/test/java/time/tck/java/time/TCKClock_Fixed.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKClock_Fixed.java
+ojluni/src/test/java/time/tck/java/time/TCKClock_Offset.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKClock_Offset.java
+ojluni/src/test/java/time/tck/java/time/TCKClock_System.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKClock_System.java
+ojluni/src/test/java/time/tck/java/time/TCKClock_Tick.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKClock_Tick.java
+ojluni/src/test/java/time/tck/java/time/TCKDayOfWeek.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKDayOfWeek.java
+ojluni/src/test/java/time/tck/java/time/TCKDuration.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKDuration.java
+ojluni/src/test/java/time/tck/java/time/TCKInstant.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKInstant.java
+ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKLocalDate.java
+ojluni/src/test/java/time/tck/java/time/TCKLocalDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKLocalDateTime.java
+ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKLocalTime.java
+ojluni/src/test/java/time/tck/java/time/TCKMonth.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKMonth.java
+ojluni/src/test/java/time/tck/java/time/TCKMonthDay.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKMonthDay.java
+ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKOffsetDateTime.java
+ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKOffsetTime.java
+ojluni/src/test/java/time/tck/java/time/TCKPeriod.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKPeriod.java
+ojluni/src/test/java/time/tck/java/time/TCKYear.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKYear.java
+ojluni/src/test/java/time/tck/java/time/TCKYearMonth.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKYearMonth.java
+ojluni/src/test/java/time/tck/java/time/TCKZoneId.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKZoneId.java
+ojluni/src/test/java/time/tck/java/time/TCKZoneOffset.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKZoneOffset.java
+ojluni/src/test/java/time/tck/java/time/TCKZonedDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TCKZonedDateTime.java
+ojluni/src/test/java/time/tck/java/time/TestIsoChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/TestIsoChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/CopticChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/CopticChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/CopticDate.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/CopticDate.java
+ojluni/src/test/java/time/tck/java/time/chrono/CopticEra.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/CopticEra.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoLocalDate.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKChronoLocalDate.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoLocalDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKChronoLocalDateTime.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoPeriod.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKChronoPeriod.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoZonedDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKChronoZonedDateTime.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKHijrahChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKHijrahChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKHijrahEra.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKHijrahEra.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKIsoChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKIsoChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKIsoEra.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKIsoEra.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKJapaneseEra.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKMinguoChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKMinguoChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKMinguoEra.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKMinguoEra.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKTestServiceLoader.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKTestServiceLoader.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKThaiBuddhistChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKThaiBuddhistChronology.java
+ojluni/src/test/java/time/tck/java/time/chrono/TCKThaiBuddhistEra.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/TCKThaiBuddhistEra.java
+ojluni/src/test/java/time/tck/java/time/chrono/serial/TCKChronoLocalDateSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/serial/TCKChronoLocalDateSerialization.java
+ojluni/src/test/java/time/tck/java/time/chrono/serial/TCKChronoLocalDateTimeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/serial/TCKChronoLocalDateTimeSerialization.java
+ojluni/src/test/java/time/tck/java/time/chrono/serial/TCKChronoZonedDateTimeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/serial/TCKChronoZonedDateTimeSerialization.java
+ojluni/src/test/java/time/tck/java/time/chrono/serial/TCKChronologySerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/serial/TCKChronologySerialization.java
+ojluni/src/test/java/time/tck/java/time/chrono/serial/TCKCopticSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/serial/TCKCopticSerialization.java
+ojluni/src/test/java/time/tck/java/time/chrono/serial/TCKEraSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/chrono/serial/TCKEraSerialization.java
+ojluni/src/test/java/time/tck/java/time/format/TCKChronoPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKChronoPrinterParser.java
+ojluni/src/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKDTFParsedInstant.java
+ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeFormatter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKDateTimeFormatter.java
+ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
+ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKDateTimeFormatters.java
+ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKDateTimeParseResolver.java
+ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java
+ojluni/src/test/java/time/tck/java/time/format/TCKDecimalStyle.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKDecimalStyle.java
+ojluni/src/test/java/time/tck/java/time/format/TCKFormatStyle.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKFormatStyle.java
+ojluni/src/test/java/time/tck/java/time/format/TCKInstantPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKInstantPrinterParser.java
+ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKLocalizedFieldParser.java
+ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedFieldPrinter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKLocalizedFieldPrinter.java
+ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java
+ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKLocalizedPrinterParser.java
+ojluni/src/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKOffsetPrinterParser.java
+ojluni/src/test/java/time/tck/java/time/format/TCKPadPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKPadPrinterParser.java
+ojluni/src/test/java/time/tck/java/time/format/TCKResolverStyle.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKResolverStyle.java
+ojluni/src/test/java/time/tck/java/time/format/TCKSignStyle.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKSignStyle.java
+ojluni/src/test/java/time/tck/java/time/format/TCKTextStyle.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKTextStyle.java
+ojluni/src/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKClockSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKClockSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKDurationSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKDurationSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKInstantSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKInstantSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKLocalDateSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKLocalDateSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKLocalDateTimeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKLocalDateTimeSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKLocalTimeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKLocalTimeSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKMonthDaySerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKMonthDaySerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKOffsetDateTimeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKOffsetDateTimeSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKOffsetTimeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKOffsetTimeSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKPeriodSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKPeriodSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKYearMonthSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKYearMonthSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKYearSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKYearSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKZoneIdSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKZoneIdSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKZoneOffsetSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKZoneOffsetSerialization.java
+ojluni/src/test/java/time/tck/java/time/serial/TCKZonedDateTimeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/serial/TCKZonedDateTimeSerialization.java
+ojluni/src/test/java/time/tck/java/time/temporal/TCKChronoField.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/TCKChronoField.java
+ojluni/src/test/java/time/tck/java/time/temporal/TCKChronoUnit.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/TCKChronoUnit.java
+ojluni/src/test/java/time/tck/java/time/temporal/TCKIsoFields.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/TCKIsoFields.java
+ojluni/src/test/java/time/tck/java/time/temporal/TCKJulianFields.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/TCKJulianFields.java
+ojluni/src/test/java/time/tck/java/time/temporal/TCKTemporalAdjusters.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/TCKTemporalAdjusters.java
+ojluni/src/test/java/time/tck/java/time/temporal/TCKWeekFields.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/TCKWeekFields.java
+ojluni/src/test/java/time/tck/java/time/temporal/serial/TCKChronoFieldSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/serial/TCKChronoFieldSerialization.java
+ojluni/src/test/java/time/tck/java/time/temporal/serial/TCKChronoUnitSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/serial/TCKChronoUnitSerialization.java
+ojluni/src/test/java/time/tck/java/time/temporal/serial/TCKJulianFieldsSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/serial/TCKJulianFieldsSerialization.java
+ojluni/src/test/java/time/tck/java/time/temporal/serial/TCKValueRangeSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/serial/TCKValueRangeSerialization.java
+ojluni/src/test/java/time/tck/java/time/temporal/serial/TCKWeekFieldsSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/temporal/serial/TCKWeekFieldsSerialization.java
+ojluni/src/test/java/time/tck/java/time/zone/TCKFixedZoneRules.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/TCKFixedZoneRules.java
+ojluni/src/test/java/time/tck/java/time/zone/TCKZoneOffsetTransition.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/TCKZoneOffsetTransition.java
+ojluni/src/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java
+ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/TCKZoneRules.java
+ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/TCKZoneRulesProvider.java
+ojluni/src/test/java/time/tck/java/time/zone/serial/TCKFixedZoneRulesSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/serial/TCKFixedZoneRulesSerialization.java
+ojluni/src/test/java/time/tck/java/time/zone/serial/TCKZoneOffsetTransitionRuleSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/serial/TCKZoneOffsetTransitionRuleSerialization.java
+ojluni/src/test/java/time/tck/java/time/zone/serial/TCKZoneOffsetTransitionSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/serial/TCKZoneOffsetTransitionSerialization.java
+ojluni/src/test/java/time/tck/java/time/zone/serial/TCKZoneRulesSerialization.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/tck/java/time/zone/serial/TCKZoneRulesSerialization.java
+ojluni/src/test/java/time/test/java/time/AbstractTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/AbstractTest.java
+ojluni/src/test/java/time/test/java/time/MockSimplePeriod.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/MockSimplePeriod.java
+ojluni/src/test/java/time/test/java/time/TestClock_Fixed.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestClock_Fixed.java
+ojluni/src/test/java/time/test/java/time/TestClock_Offset.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestClock_Offset.java
+ojluni/src/test/java/time/test/java/time/TestClock_System.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestClock_System.java
+ojluni/src/test/java/time/test/java/time/TestClock_Tick.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestClock_Tick.java
+ojluni/src/test/java/time/test/java/time/TestDuration.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestDuration.java
+ojluni/src/test/java/time/test/java/time/TestInstant.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestInstant.java
+ojluni/src/test/java/time/test/java/time/TestLocalDate.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestLocalDate.java
+ojluni/src/test/java/time/test/java/time/TestLocalDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestLocalDateTime.java
+ojluni/src/test/java/time/test/java/time/TestLocalTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestLocalTime.java
+ojluni/src/test/java/time/test/java/time/TestMonthDay.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestMonthDay.java
+ojluni/src/test/java/time/test/java/time/TestOffsetDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestOffsetDateTime.java
+ojluni/src/test/java/time/test/java/time/TestOffsetDateTime_instants.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestOffsetDateTime_instants.java
+ojluni/src/test/java/time/test/java/time/TestOffsetTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestOffsetTime.java
+ojluni/src/test/java/time/test/java/time/TestPeriod.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestPeriod.java
+ojluni/src/test/java/time/test/java/time/TestYear.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestYear.java
+ojluni/src/test/java/time/test/java/time/TestYearMonth.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestYearMonth.java
+ojluni/src/test/java/time/test/java/time/TestZoneId.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestZoneId.java
+ojluni/src/test/java/time/test/java/time/TestZoneOffset.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestZoneOffset.java
+ojluni/src/test/java/time/test/java/time/TestZonedDateTime.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/TestZonedDateTime.java
+ojluni/src/test/java/time/test/java/time/chrono/TestChronoLocalDate.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestChronoLocalDate.java
+ojluni/src/test/java/time/test/java/time/chrono/TestChronologyPerf.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestChronologyPerf.java
+ojluni/src/test/java/time/test/java/time/chrono/TestEraDisplayName.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestEraDisplayName.java
+ojluni/src/test/java/time/test/java/time/chrono/TestExampleCode.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestExampleCode.java
+ojluni/src/test/java/time/test/java/time/chrono/TestIsoChronoImpl.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestIsoChronoImpl.java
+ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronoImpl.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestJapaneseChronoImpl.java
+ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestJapaneseChronology.java
+ojluni/src/test/java/time/test/java/time/chrono/TestServiceLoader.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestServiceLoader.java
+ojluni/src/test/java/time/test/java/time/chrono/TestThaiBuddhistChronoImpl.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestThaiBuddhistChronoImpl.java
+ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java
+ojluni/src/test/java/time/test/java/time/format/AbstractTestPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/AbstractTestPrinterParser.java
+ojluni/src/test/java/time/test/java/time/format/MockIOExceptionAppendable.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/MockIOExceptionAppendable.java
+ojluni/src/test/java/time/test/java/time/format/TestCharLiteralParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestCharLiteralParser.java
+ojluni/src/test/java/time/test/java/time/format/TestCharLiteralPrinter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestCharLiteralPrinter.java
+ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestDateTimeFormatter.java
+ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
+ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java
+ojluni/src/test/java/time/test/java/time/format/TestDateTimeParsing.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestDateTimeParsing.java
+ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestDateTimeTextProvider.java
+ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java
+ojluni/src/test/java/time/test/java/time/format/TestDecimalStyle.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestDecimalStyle.java
+ojluni/src/test/java/time/test/java/time/format/TestFractionPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestFractionPrinterParser.java
+ojluni/src/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java
+ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestNonIsoFormatter.java
+ojluni/src/test/java/time/test/java/time/format/TestNumberParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestNumberParser.java
+ojluni/src/test/java/time/test/java/time/format/TestNumberPrinter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestNumberPrinter.java
+ojluni/src/test/java/time/test/java/time/format/TestPadPrinterDecorator.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestPadPrinterDecorator.java
+ojluni/src/test/java/time/test/java/time/format/TestReducedParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestReducedParser.java
+ojluni/src/test/java/time/test/java/time/format/TestReducedPrinter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestReducedPrinter.java
+ojluni/src/test/java/time/test/java/time/format/TestSettingsParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestSettingsParser.java
+ojluni/src/test/java/time/test/java/time/format/TestStringLiteralParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestStringLiteralParser.java
+ojluni/src/test/java/time/test/java/time/format/TestStringLiteralPrinter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestStringLiteralPrinter.java
+ojluni/src/test/java/time/test/java/time/format/TestTextParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestTextParser.java
+ojluni/src/test/java/time/test/java/time/format/TestTextParserWithLocale.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestTextParserWithLocale.java
+ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestTextPrinter.java
+ojluni/src/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestTextPrinterWithLocale.java
+ojluni/src/test/java/time/test/java/time/format/TestUnicodeExtension.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestUnicodeExtension.java
+ojluni/src/test/java/time/test/java/time/format/TestZoneOffsetParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestZoneOffsetParser.java
+ojluni/src/test/java/time/test/java/time/format/TestZoneOffsetPrinter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestZoneOffsetPrinter.java
+ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/TestZoneTextPrinterParser.java
+ojluni/src/test/java/time/test/java/time/format/ZoneName.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/format/ZoneName.java
+ojluni/src/test/java/time/test/java/time/temporal/MockFieldNoValue.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/MockFieldNoValue.java
+ojluni/src/test/java/time/test/java/time/temporal/MockFieldValue.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/MockFieldValue.java
+ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/TestChronoField.java
+ojluni/src/test/java/time/test/java/time/temporal/TestChronoUnit.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/TestChronoUnit.java
+ojluni/src/test/java/time/test/java/time/temporal/TestDateTimeBuilderCombinations.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/TestDateTimeBuilderCombinations.java
+ojluni/src/test/java/time/test/java/time/temporal/TestDateTimeValueRange.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/TestDateTimeValueRange.java
+ojluni/src/test/java/time/test/java/time/temporal/TestIsoWeekFields.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/TestIsoWeekFields.java
+ojluni/src/test/java/time/test/java/time/temporal/TestJulianFields.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/temporal/TestJulianFields.java
+ojluni/src/test/java/time/test/java/time/zone/TestFixedZoneRules.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/zone/TestFixedZoneRules.java
+ojluni/src/test/java/time/test/java/time/zone/TestZoneRules.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/time/zone/TestZoneRules.java
+ojluni/src/test/java/time/test/java/util/TestFormatter.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/time/test/java/util/TestFormatter.java
+ojluni/src/test/java/util/zip/ZipFile/Zip64SizeTest.java,jdk11u/jdk-11.0.13-ga,test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java
diff --git a/Extras.bp b/Extras.bp
new file mode 100644
index 0000000..776bf00
--- /dev/null
+++ b/Extras.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2022 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.
+
+//
+// Definitions to expose small parts of the core library that are
+// independent from the whole Android core library.
+//
+
+// Java host library containing just the xmlpull sources
+java_library_host {
+    name: "core-xml-for-host",
+    srcs: ["xml/src/main/java/org/xmlpull/**/*.java"],
+    visibility: ["//packages/modules/Permission:__subpackages__"],
+}
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index dcbff3b..f070571 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -82,14 +82,28 @@
     srcs: [":openjdk_java_files"],
 }
 
+// http://b/129765390, http://b/188966706
+// Rewrite links to "platform" or "technotes" folders which are siblings
+// (and thus outside of) {@docRoot}.
+//
+// We have to escape \ as \\ and $ as $$ here because they get resolved by
+// different layers of the build tooling. The arguments are wrapped in '' so
+// that the shell doesn't add yet another level of escaping.
+rewrite_openjdk_doc_links = "sed 's" +
+    "!\\({@docRoot}/\\.\\.\\/\\|[./]\\+\\)\\(\\(platform\\|technotes\\).\\+\\)\">" +
+    "!https://docs.oracle.com/javase/8/docs/\\2\">!' " +
+    "$(in) > $(out)"
+
 // OpenJDK source is not annotated with @hide so we need this separate
 // filegroup for just the parts that contribute to the API.
-filegroup {
+gensrcs {
     name: "core_oj_api_files",
+    cmd: rewrite_openjdk_doc_links,
     srcs: [":openjdk_javadoc_files"],
+    output_extension: "java",
 }
 
-// The source files that go into core-libart.
+// The source files that go into core-libart.l
 filegroup {
     name: "core_libart_java_files",
     visibility: [
@@ -144,6 +158,7 @@
         javacflags: [
             "-Xep:MissingOverride:OFF", // Ignore missing @Override.
             "-Xep:ConstantOverflow:WARN", // Known constant overflow in SplittableRandom
+            "-Xep:UnicodeInCode:WARN", // XML parser uses line feeds in whitespace
         ],
     },
     min_sdk_version: "31",
@@ -186,7 +201,6 @@
     },
 
     java_resources: core_resources,
-    java_version: "1.9",
 
     installable: false,
 
@@ -265,6 +279,7 @@
             "java.lang.Object",
             "java.lang.String",
             "java.lang.invoke.MethodHandle",
+            "java.lang.invoke.VarHandle",
             "java.lang.ref.Reference",
             "java.lang.reflect.Proxy",
             "java.util.AbstractMap",
@@ -302,7 +317,6 @@
     hostdex: true,
 
     srcs: [":core_libart_java_files"],
-    java_version: "1.9",
 
     sdk_version: "none",
     system_modules: "core-all-system-modules",
@@ -415,7 +429,8 @@
 java_library {
     name: "core-lambda-stubs-for-system-modules",
     visibility: [
-        "//libcore/mmodules/core_platform_api",
+        "//art/build/sdk",
+        "//build/soong/java/core-libraries",
     ],
     defaults: ["core_lambda_stubs_defaults"],
     srcs: [
@@ -431,7 +446,8 @@
 java_library {
     name: "core-generated-annotation-stubs",
     visibility: [
-        "//libcore/mmodules/core_platform_api",
+        "//art/build/sdk",
+        "//build/soong/java/core-libraries",
     ],
     defaults: ["libcore_java_defaults"],
     srcs: [
@@ -457,6 +473,7 @@
         "//frameworks/base/location/tests/locationtests",
         "//frameworks/base/core/tests/coretests",
         "//frameworks/base/wifi/tests",
+        "//libcore/luni/src/test/java9compatibility",
         "//packages/modules/Wifi/framework/tests",
     ],
     hostdex: true,
@@ -535,6 +552,11 @@
     libs: [
         "junit",
     ],
+    errorprone: {
+        javacflags: [
+            "-Xep:DoNotCall:OFF",
+        ],
+    },
 }
 
 // A filegroup that provides access to a source file for a toolchain test that
@@ -545,6 +567,14 @@
     visibility: ["//libcore/luni/src/test/java9language"],
 }
 
+// A filegroup that provides access to a source file for a toolchain test that
+// checks Java 11 language features are handled properly by JarJar.
+filegroup {
+    name: "core-java-11-language-features-source",
+    srcs: ["luni/src/main/java/libcore/internal/Java11LanguageFeatures.java"],
+    visibility: ["//libcore/luni/src/test/java11language"],
+}
+
 genrule {
     name: "core-tests-smali-dex",
     srcs: ["luni/src/test/java/**/*.smali"],
@@ -615,7 +645,9 @@
 
     static_libs: [
         "core-compat-test-rules",
+        "core-java-9-compatibility-tests",
         "core-java-9-language-tests",
+        "core-java-11-language-tests",
         "core-test-rules",
         "core-tests-support",
         "junit-params",
@@ -633,6 +665,7 @@
         javacflags: [
             "-Xep:TryFailThrowable:ERROR",
             "-Xep:ComparisonOutOfRange:ERROR",
+            "-Xep:DoNotCall:OFF",
         ],
     },
 
@@ -651,6 +684,7 @@
         "luni/src/test/java/libcore/javax/crypto/**/*.java",
         "luni/src/test/java/libcore/javax/net/ssl/**/*.java",
         "luni/src/test/java/libcore/libcore/util/SerializationTester.java",
+        "luni/src/test/java/libcore/sun/security/**/*.java",
         "luni/src/test/java/org/apache/harmony/crypto/**/*.java",
     ],
 
@@ -680,6 +714,7 @@
     srcs: [
         "ojluni/src/test/java/**/*.java",
         "ojluni/src/test/javax/**/*.java",
+        "ojluni/src/test/sun/**/*.java",
     ],
     java_resource_dirs: [
         "ojluni/src/test/java",
@@ -717,6 +752,13 @@
     // deleting those tests or moving them to a different
     // package.
     patch_module: "java.base",
+
+    errorprone: {
+        javacflags: [
+            "-Xep:AlwaysThrows:OFF",
+            "-Xep:DoNotCall:OFF",
+        ],
+    },
 }
 
 // Builds the core-ojtests-public library. Excludes any private API tests.
@@ -731,6 +773,7 @@
     srcs: [
         "ojluni/src/test/java/**/*.java",
         "ojluni/src/test/javax/**/*.java",
+        "ojluni/src/test/sun/**/*.java",
     ],
     // Filter out the following:
     // 1.) DeserializeMethodTest and SerializedLambdaTest, because they depends on stub classes
@@ -761,6 +804,13 @@
         "okhttp",
         "testng",
     ],
+
+    errorprone: {
+        javacflags: [
+            "-Xep:AlwaysThrows:OFF",
+            "-Xep:DoNotCall:OFF",
+        ],
+    },
 }
 
 // Exports annotated stubs source files in ojluni/annotations/sdk to make them
@@ -784,7 +834,6 @@
 droiddoc_exported_dir {
     name: "ojluni-annotated-mmodule-stubs",
     visibility: [
-        "//libcore/mmodules/core_platform_api",
         "//libcore/mmodules/intracoreapi",
     ],
     path: "ojluni/annotations/mmodule",
@@ -816,7 +865,6 @@
         ":core_oj_api_files",
         ":core_libart_api_files",
     ],
-    java_version: "1.9",
     installable: false,
     sdk_version: "none",
     system_modules: "none",
@@ -851,21 +899,6 @@
     ],
 }
 
-// http://b/129765390 Rewrite links to "platform" or "technotes" folders
-// which are siblings (and thus outside of) {@docRoot}.
-//
-// We have to escape \ as \\ and $ as $$ here because they get resolved by
-// different layers of the build tooling. The arguments are wrapped in '' so
-// that the shell doesn't add yet another level of escaping.
-rewrite_openjdk_doc_args = "--replace-documentation " +
-    // packages whose descendants to apply replacement to (all packages from
-    // libcore/ojluni/src/main/java that contribute to documentation).
-    "com.sun:java:javax:jdk.net:sun " +
-    // regex of the string to replace
-    "'(<a\\s+href\\s?=[\\*\\s]*\")(?:(?:\\{@docRoot\\}/\\.\\./)|(?:(?:\\.\\./)+))((?:platform|technotes).+)\">' " +
-    // replacement (with $1, $2 backreferences to the regex groups)
-    "'$$1https://docs.oracle.com/javase/8/docs/$$2\">' "
-
 java_library {
     name: "framework-api-annotations-lib",
     srcs: [":framework-api-annotations"],
@@ -883,9 +916,13 @@
     name: "art.module.public.api",
     visibility: [
         "//art/build/sdk",
-        "//libcore/mmodules/core_platform_api",
+        "//build/soong/java/core-libraries",
         "//frameworks/base",
         "//frameworks/base/api",
+
+        // DO NOT REMOVE: Legacy visibility, needed for snapshots that are
+        // generated for the S build.
+        "//libcore/mmodules/core_platform_api",
     ],
     srcs: [
         ":core_oj_api_files",
@@ -910,7 +947,6 @@
         "i18n.module.intra.core.api.stubs",
     ],
     stub_only_static_libs: ["notices-for-stubs-jar"],
-    java_version: "1.9",
 
     // Make dex jars for the stubs available for use by hiddenapi processing.
     compile_dex: true,
@@ -927,7 +963,6 @@
 
     api_only: true,
     droiddoc_options: [
-        rewrite_openjdk_doc_args,
         "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* ",
         "--hide-annotation libcore.api.Hide",
     ],
@@ -1014,102 +1049,6 @@
     ],
 }
 
-// A stubs target containing the parts of the public SDK API provided by the
-// core library.
-//
-// Don't use this directly, use "sdk_version: core_current".
-java_library {
-    name: "core.current.stubs",
-    visibility: ["//visibility:public"],
-    static_libs: [
-        "art.module.public.api.stubs",
-        "conscrypt.module.public.api.stubs",
-        "i18n.module.public.api.stubs",
-    ],
-    sdk_version: "none",
-    system_modules: "none",
-
-    dist: {
-        targets: [
-            "sdk",
-            "win_sdk",
-        ],
-    },
-}
-
-// Distributed with the SDK for turning into system modules to compile apps
-// against.
-java_library {
-    name: "core-current-stubs-for-system-modules",
-    visibility: ["//development/sdk"],
-    static_libs: [
-        "core.current.stubs",
-        // This one is not on device but it's needed when javac compiles code
-        // containing lambdas.
-        "core-lambda-stubs-for-system-modules",
-        // This one is not on device but it's needed when javac compiles code
-        // containing @Generated annotations produced by some code generation
-        // tools.
-        // See http://b/123891440.
-        "core-generated-annotation-stubs",
-    ],
-    sdk_version: "none",
-    system_modules: "none",
-    dist: {
-        dest: "core-for-system-modules.jar",
-        targets: [
-            "sdk",
-            "win_sdk",
-        ],
-    },
-}
-
-// Used when compiling higher-level code against core.current.stubs.
-java_system_modules {
-    name: "core-current-stubs-system-modules",
-    visibility: ["//visibility:public"],
-    libs: [
-        "core-current-stubs-for-system-modules",
-    ],
-}
-
-// A stubs target containing the parts of the public SDK & @SystemApi(MODULE_LIBRARIES) API
-// provided by the core library.
-//
-// Don't use this directly, use "sdk_version: module_current".
-java_library {
-    name: "core.module_lib.stubs",
-    static_libs: [
-        "art.module.public.api.stubs.module_lib",
-
-        // Replace the following with the module-lib correspondence when Conscrypt or i18N module
-        // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
-        // @SystemApi(MODULE_LIBRARIES).
-        "conscrypt.module.public.api.stubs",
-        "i18n.module.public.api.stubs",
-    ],
-    sdk_version: "none",
-    system_modules: "none",
-    visibility: ["//visibility:private"],
-}
-
-// Used when compiling higher-level code with sdk_version "module_current"
-java_system_modules {
-    name: "core-module-lib-stubs-system-modules",
-    libs: [
-        "core.module_lib.stubs",
-        // This one is not on device but it's needed when javac compiles code
-        // containing lambdas.
-        "core-lambda-stubs-for-system-modules",
-        // This one is not on device but it's needed when javac compiles code
-        // containing @Generated annotations produced by some code generation
-        // tools.
-        // See http://b/123891440.
-        "core-generated-annotation-stubs",
-    ],
-    visibility: ["//visibility:public"],
-}
-
 // Target for validating nullability annotations for correctness and
 // completeness. To check that there are no nullability errors:
 //   m art-module-public-api-stubs-nullability-validation
@@ -1154,6 +1093,9 @@
 // avoid introducing compile time cycles.
 java_library {
     name: "art.module.api.annotations.for.system.modules",
+    visibility: [
+        "//art/libartservice",
+    ],
     srcs: [
         ":api_surface_annotation_files",
     ],
@@ -1177,6 +1119,5 @@
     srcs: [
         ":api_surface_annotation_files",
     ],
-    java_version: "1.9",
     sdk_version: "core_current",
 }
diff --git a/NativeCode.bp b/NativeCode.bp
index a7f18ea..2db7019 100644
--- a/NativeCode.bp
+++ b/NativeCode.bp
@@ -135,12 +135,21 @@
     ],
 
     target: {
-        linux_glibc: {
-            cflags: [ // Sigh.
+        musl: {
+            cflags: [
+                // Sigh.
                 "-D_LARGEFILE64_SOURCE",
                 "-D_GNU_SOURCE",
                 "-DLINUX",
+            ],
+        },
+        glibc: {
+            cflags: [
                 "-D__GLIBC__",
+                // Sigh.
+                "-D_LARGEFILE64_SOURCE",
+                "-D_GNU_SOURCE",
+                "-DLINUX",
             ],
         },
         android: {
@@ -198,16 +207,13 @@
         "luni/src/test/native/libcore_java_io_FileTest.cpp",
         "luni/src/test/native/libcore_java_lang_ThreadTest.cpp",
         "luni/src/test/native/libcore_java_nio_BufferTest.cpp",
+        "luni/src/test/native/libcore_java_time_BionicTzdbConsistencyTest.cpp",
         "luni/src/test/native/libcore_libcore_util_NativeAllocationRegistryTest.cpp",
     ],
     shared_libs: [
         "liblog",
         "libnativehelper",
     ],
-
-    strip: {
-        keep_symbols: true,
-    },
 }
 
 // Set of gtest unit tests.
diff --git a/OWNERS b/OWNERS
index 56d718b..234b99e 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,21 +1,28 @@
 # Bug component: 24949
 
-# Use this reviewer by default.
-android-libcore-team+review@google.com
+# Ideally, we would use this reviewer by default, but gerrit and
+# checkowners.py do not recognize email subaddresses:
+# android-libcore-team+review@google.com
 
 # People who can approve changes for submission; don't send review emails to them
 # unless you know what you're doing.
-dauletz@google.com
+miguelaranda@google.com
 mingaleev@google.com
-nfuller@google.com
 nikitai@google.com
-paulduffin@google.com
+oth@google.com
 prb@google.com
-rpl@google.com
+skvadrik@google.com
+sorinbasca@google.com
 vichang@google.com
 
+# Emeritus libcore team members; don't send review emails to them
+# unless you are in the libcore team.
+nfuller@google.com #{LAST_RESORT_SUGGESTION}
+paulduffin@google.com #{LAST_RESORT_SUGGESTION}
+
 # Don't send these folks any review emails for this project.
-calin@google.com
-narayan@google.com
-ngeoffray@google.com
-vmarko@google.com
+hboehm@google.com #{LAST_RESORT_SUGGESTION}
+narayan@google.com #{LAST_RESORT_SUGGESTION}
+ngeoffray@google.com #{LAST_RESORT_SUGGESTION}
+rpl@google.com #{LAST_RESORT_SUGGESTION}
+vmarko@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6044f3f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+Android Core Library
+
+[Existing open bugs](http://b/issues?q=componentid:24949%20status:open)
+
+[File a new bug](http://b/new?component=24949)
+
+[File a new public bug](https://issuetracker.google.com/issues/new?component=192710)
+
+[Import files from OpenJDK](tools/expected_upstream/README.md)
+
+[Add nullability annotations](ojluni/annotations/README)
+
+[Run benchmark tests](benchmarks/README.md)
diff --git a/api/current.txt b/api/current.txt
index 5276996..fb751ea 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -726,6 +726,16 @@
     field public final String version;
   }
 
+  public final class SystemCleaner {
+    method @NonNull public static java.lang.ref.Cleaner cleaner();
+  }
+
+  public final class VmSocketAddress extends java.net.SocketAddress {
+    ctor public VmSocketAddress(int, int);
+    method public int getSvmCid();
+    method public int getSvmPort();
+  }
+
 }
 
 package dalvik.annotation {
@@ -1307,6 +1317,8 @@
     method public int available();
     method public int read();
     method public int read(byte[], int, int);
+    method public byte[] readAllBytes();
+    method public int readNBytes(byte[], int, int);
     method public void reset();
     method public long skip(long);
     field protected byte[] buf;
@@ -1322,9 +1334,11 @@
     method public int size();
     method @NonNull public byte[] toByteArray();
     method @NonNull public String toString(@NonNull String) throws java.io.UnsupportedEncodingException;
+    method @NonNull public String toString(@NonNull java.nio.charset.Charset);
     method @Deprecated @NonNull public String toString(int);
     method public void write(int);
     method public void write(@NonNull byte[], int, int);
+    method public void writeBytes(byte[]);
     method public void writeTo(@NonNull java.io.OutputStream) throws java.io.IOException;
     field @NonNull protected byte[] buf;
     field protected int count;
@@ -1573,6 +1587,8 @@
     ctor public FileReader(String) throws java.io.FileNotFoundException;
     ctor public FileReader(java.io.File) throws java.io.FileNotFoundException;
     ctor public FileReader(java.io.FileDescriptor);
+    ctor public FileReader(String, java.nio.charset.Charset) throws java.io.IOException;
+    ctor public FileReader(java.io.File, java.nio.charset.Charset) throws java.io.IOException;
   }
 
   public class FileWriter extends java.io.OutputStreamWriter {
@@ -1581,6 +1597,10 @@
     ctor public FileWriter(java.io.File) throws java.io.IOException;
     ctor public FileWriter(java.io.File, boolean) throws java.io.IOException;
     ctor public FileWriter(java.io.FileDescriptor);
+    ctor public FileWriter(String, java.nio.charset.Charset) throws java.io.IOException;
+    ctor public FileWriter(String, java.nio.charset.Charset, boolean) throws java.io.IOException;
+    ctor public FileWriter(java.io.File, java.nio.charset.Charset) throws java.io.IOException;
+    ctor public FileWriter(java.io.File, java.nio.charset.Charset, boolean) throws java.io.IOException;
   }
 
   @java.lang.FunctionalInterface public interface FilenameFilter {
@@ -1635,11 +1655,16 @@
     method public void close() throws java.io.IOException;
     method public void mark(int);
     method public boolean markSupported();
+    method public static java.io.InputStream nullInputStream();
     method public abstract int read() throws java.io.IOException;
     method public int read(byte[]) throws java.io.IOException;
     method public int read(byte[], int, int) throws java.io.IOException;
+    method public byte[] readAllBytes() throws java.io.IOException;
+    method public byte[] readNBytes(int) throws java.io.IOException;
+    method public int readNBytes(byte[], int, int) throws java.io.IOException;
     method public void reset() throws java.io.IOException;
     method public long skip(long) throws java.io.IOException;
+    method public long transferTo(java.io.OutputStream) throws java.io.IOException;
   }
 
   public class InputStreamReader extends java.io.Reader {
@@ -1876,6 +1901,7 @@
     ctor public OutputStream();
     method public void close() throws java.io.IOException;
     method public void flush() throws java.io.IOException;
+    method public static java.io.OutputStream nullOutputStream();
     method public abstract void write(int) throws java.io.IOException;
     method public void write(byte[]) throws java.io.IOException;
     method public void write(byte[], int, int) throws java.io.IOException;
@@ -1936,10 +1962,13 @@
     ctor public PrintStream(java.io.OutputStream);
     ctor public PrintStream(java.io.OutputStream, boolean);
     ctor public PrintStream(java.io.OutputStream, boolean, String) throws java.io.UnsupportedEncodingException;
+    ctor public PrintStream(java.io.OutputStream, boolean, java.nio.charset.Charset);
     ctor public PrintStream(String) throws java.io.FileNotFoundException;
     ctor public PrintStream(String, String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public PrintStream(String, java.nio.charset.Charset) throws java.io.IOException;
     ctor public PrintStream(java.io.File) throws java.io.FileNotFoundException;
     ctor public PrintStream(java.io.File, String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public PrintStream(java.io.File, java.nio.charset.Charset) throws java.io.IOException;
     method public java.io.PrintStream append(CharSequence);
     method public java.io.PrintStream append(CharSequence, int, int);
     method public java.io.PrintStream append(char);
@@ -1980,10 +2009,13 @@
     ctor public PrintWriter(@NonNull java.io.Writer, boolean);
     ctor public PrintWriter(@NonNull java.io.OutputStream);
     ctor public PrintWriter(@NonNull java.io.OutputStream, boolean);
+    ctor public PrintWriter(@NonNull java.io.OutputStream, boolean, @NonNull java.nio.charset.Charset);
     ctor public PrintWriter(@NonNull String) throws java.io.FileNotFoundException;
     ctor public PrintWriter(@NonNull String, @NonNull String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public PrintWriter(@NonNull String, @NonNull java.nio.charset.Charset) throws java.io.IOException;
     ctor public PrintWriter(@NonNull java.io.File) throws java.io.FileNotFoundException;
     ctor public PrintWriter(@NonNull java.io.File, @NonNull String) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException;
+    ctor public PrintWriter(@NonNull java.io.File, @NonNull java.nio.charset.Charset) throws java.io.IOException;
     method @NonNull public java.io.PrintWriter append(@Nullable CharSequence);
     method @NonNull public java.io.PrintWriter append(@Nullable CharSequence, int, int);
     method @NonNull public java.io.PrintWriter append(char);
@@ -2090,6 +2122,7 @@
     ctor protected Reader(Object);
     method public void mark(int) throws java.io.IOException;
     method public boolean markSupported();
+    method public static java.io.Reader nullReader();
     method public int read(java.nio.CharBuffer) throws java.io.IOException;
     method public int read() throws java.io.IOException;
     method public int read(char[]) throws java.io.IOException;
@@ -2097,6 +2130,7 @@
     method public boolean ready() throws java.io.IOException;
     method public void reset() throws java.io.IOException;
     method public long skip(long) throws java.io.IOException;
+    method public long transferTo(java.io.Writer) throws java.io.IOException;
     field protected Object lock;
   }
 
@@ -2210,6 +2244,7 @@
     method public java.io.Writer append(CharSequence) throws java.io.IOException;
     method public java.io.Writer append(CharSequence, int, int) throws java.io.IOException;
     method public java.io.Writer append(char) throws java.io.IOException;
+    method public static java.io.Writer nullWriter();
     method public void write(int) throws java.io.IOException;
     method public void write(char[]) throws java.io.IOException;
     method public abstract void write(char[], int, int) throws java.io.IOException;
@@ -2240,8 +2275,8 @@
 
   public class ArrayIndexOutOfBoundsException extends java.lang.IndexOutOfBoundsException {
     ctor public ArrayIndexOutOfBoundsException();
-    ctor public ArrayIndexOutOfBoundsException(int);
     ctor public ArrayIndexOutOfBoundsException(String);
+    ctor public ArrayIndexOutOfBoundsException(int);
   }
 
   public class ArrayStoreException extends java.lang.RuntimeException {
@@ -2266,8 +2301,8 @@
   }
 
   public final class Boolean implements java.lang.Comparable<java.lang.Boolean> java.io.Serializable {
-    ctor public Boolean(boolean);
-    ctor public Boolean(@Nullable String);
+    ctor @Deprecated public Boolean(boolean);
+    ctor @Deprecated public Boolean(@Nullable String);
     method public boolean booleanValue();
     method public static int compare(boolean, boolean);
     method public int compareTo(@NonNull Boolean);
@@ -2968,8 +3003,8 @@
   }
 
   public final class Double extends java.lang.Number implements java.lang.Comparable<java.lang.Double> {
-    ctor public Double(double);
-    ctor public Double(@NonNull String) throws java.lang.NumberFormatException;
+    ctor @Deprecated public Double(double);
+    ctor @Deprecated public Double(@NonNull String) throws java.lang.NumberFormatException;
     method public static int compare(double, double);
     method public int compareTo(@NonNull Double);
     method public static long doubleToLongBits(double);
@@ -3049,9 +3084,9 @@
   }
 
   public final class Float extends java.lang.Number implements java.lang.Comparable<java.lang.Float> {
-    ctor public Float(float);
-    ctor public Float(double);
-    ctor public Float(@NonNull String) throws java.lang.NumberFormatException;
+    ctor @Deprecated public Float(float);
+    ctor @Deprecated public Float(double);
+    ctor @Deprecated public Float(@NonNull String) throws java.lang.NumberFormatException;
     method public static int compare(float, float);
     method public int compareTo(@NonNull Float);
     method public double doubleValue();
@@ -3133,6 +3168,7 @@
   public class IndexOutOfBoundsException extends java.lang.RuntimeException {
     ctor public IndexOutOfBoundsException();
     ctor public IndexOutOfBoundsException(String);
+    ctor public IndexOutOfBoundsException(int);
   }
 
   public class InheritableThreadLocal<T> extends java.lang.ThreadLocal<T> {
@@ -3151,8 +3187,8 @@
   }
 
   public final class Integer extends java.lang.Number implements java.lang.Comparable<java.lang.Integer> {
-    ctor public Integer(int);
-    ctor public Integer(@NonNull String) throws java.lang.NumberFormatException;
+    ctor @Deprecated public Integer(int);
+    ctor @Deprecated public Integer(@NonNull String) throws java.lang.NumberFormatException;
     method public static int bitCount(int);
     method public static int compare(int, int);
     method public int compareTo(@NonNull Integer);
@@ -3174,8 +3210,10 @@
     method public static int numberOfLeadingZeros(int);
     method public static int numberOfTrailingZeros(int);
     method public static int parseInt(@NonNull String, int) throws java.lang.NumberFormatException;
+    method public static int parseInt(@NonNull CharSequence, int, int, int) throws java.lang.NumberFormatException;
     method public static int parseInt(@NonNull String) throws java.lang.NumberFormatException;
     method public static int parseUnsignedInt(@NonNull String, int) throws java.lang.NumberFormatException;
+    method public static int parseUnsignedInt(@NonNull CharSequence, int, int, int) throws java.lang.NumberFormatException;
     method public static int parseUnsignedInt(@NonNull String) throws java.lang.NumberFormatException;
     method public static int remainderUnsigned(int, int);
     method public static int reverse(int);
@@ -3227,8 +3265,8 @@
   }
 
   public final class Long extends java.lang.Number implements java.lang.Comparable<java.lang.Long> {
-    ctor public Long(long);
-    ctor public Long(@NonNull String) throws java.lang.NumberFormatException;
+    ctor @Deprecated public Long(long);
+    ctor @Deprecated public Long(@NonNull String) throws java.lang.NumberFormatException;
     method public static int bitCount(long);
     method public static int compare(long, long);
     method public int compareTo(@NonNull Long);
@@ -3250,8 +3288,10 @@
     method public static int numberOfLeadingZeros(long);
     method public static int numberOfTrailingZeros(long);
     method public static long parseLong(@NonNull String, int) throws java.lang.NumberFormatException;
+    method public static long parseLong(@NonNull CharSequence, int, int, int) throws java.lang.NumberFormatException;
     method public static long parseLong(@NonNull String) throws java.lang.NumberFormatException;
     method public static long parseUnsignedLong(@NonNull String, int) throws java.lang.NumberFormatException;
+    method public static long parseUnsignedLong(@NonNull CharSequence, int, int, int) throws java.lang.NumberFormatException;
     method public static long parseUnsignedLong(@NonNull String) throws java.lang.NumberFormatException;
     method public static long remainderUnsigned(long, long);
     method public static long reverse(long);
@@ -3306,6 +3346,8 @@
     method public static int floorMod(int, int);
     method public static int floorMod(long, int);
     method public static long floorMod(long, long);
+    method public static double fma(double, double, double);
+    method public static float fma(float, float, float);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
@@ -3588,7 +3630,7 @@
     method public void checkExit(int);
     method public void checkLink(String);
     method public void checkListen(int);
-    method public void checkMemberAccess(Class<?>, int);
+    method @Deprecated public void checkMemberAccess(Class<?>, int);
     method public void checkMulticast(java.net.InetAddress);
     method @Deprecated public void checkMulticast(java.net.InetAddress, byte);
     method public void checkPackageAccess(String);
@@ -3604,7 +3646,7 @@
     method public void checkSecurityAccess(String);
     method public void checkSetFactory();
     method public void checkSystemClipboardAccess();
-    method public boolean checkTopLevelWindow(Object);
+    method @Deprecated public boolean checkTopLevelWindow(Object);
     method public void checkWrite(java.io.FileDescriptor);
     method public void checkWrite(String);
     method @Deprecated protected int classDepth(String);
@@ -3689,6 +3731,8 @@
     method public static int floorMod(int, int);
     method public static int floorMod(long, int);
     method public static long floorMod(long, long);
+    method public static double fma(double, double, double);
+    method public static float fma(float, float, float);
     method public static int getExponent(float);
     method public static int getExponent(double);
     method public static double hypot(double, double);
@@ -3781,6 +3825,7 @@
     method public int indexOf(@NonNull String);
     method public int indexOf(@NonNull String, int);
     method @NonNull public String intern();
+    method public boolean isBlank();
     method public boolean isEmpty();
     method @NonNull public static String join(@NonNull CharSequence, @Nullable java.lang.CharSequence...);
     method @NonNull public static String join(@NonNull CharSequence, @NonNull Iterable<? extends java.lang.CharSequence>);
@@ -3789,10 +3834,12 @@
     method public int lastIndexOf(@NonNull String);
     method public int lastIndexOf(@NonNull String, int);
     method public int length();
+    method @NonNull public java.util.stream.Stream<java.lang.String> lines();
     method public boolean matches(@NonNull String);
     method public int offsetByCodePoints(int, int);
     method public boolean regionMatches(int, @NonNull String, int, int);
     method public boolean regionMatches(boolean, int, @NonNull String, int, int);
+    method @NonNull public String repeat(int);
     method @NonNull public String replace(char, char);
     method @NonNull public String replace(@NonNull CharSequence, @NonNull CharSequence);
     method @NonNull public String replaceAll(@NonNull String, @NonNull String);
@@ -3801,6 +3848,9 @@
     method @NonNull public String[] split(@NonNull String);
     method public boolean startsWith(@NonNull String, int);
     method public boolean startsWith(@NonNull String);
+    method @NonNull public String strip();
+    method @NonNull public String stripLeading();
+    method @NonNull public String stripTrailing();
     method @NonNull public CharSequence subSequence(int, int);
     method @NonNull public String substring(int);
     method @NonNull public String substring(int, int);
@@ -3986,6 +4036,7 @@
     ctor public Thread(@Nullable Runnable, @NonNull String);
     ctor public Thread(@Nullable ThreadGroup, @Nullable Runnable, @NonNull String);
     ctor public Thread(@Nullable ThreadGroup, @Nullable Runnable, @NonNull String, long);
+    ctor public Thread(@Nullable ThreadGroup, @Nullable Runnable, @NonNull String, long, boolean);
     method public static int activeCount();
     method public final void checkAccess();
     method @Deprecated public int countStackFrames();
@@ -4012,6 +4063,7 @@
     method public final void join(long) throws java.lang.InterruptedException;
     method public final void join(long, int) throws java.lang.InterruptedException;
     method public final void join() throws java.lang.InterruptedException;
+    method public static void onSpinWait();
     method @Deprecated public final void resume();
     method public void run();
     method public void setContextClassLoader(@Nullable ClassLoader);
@@ -4248,8 +4300,10 @@
 
   public abstract class MethodHandle {
     method public java.lang.invoke.MethodHandle asCollector(Class<?>, int);
+    method public java.lang.invoke.MethodHandle asCollector(int, Class<?>, int);
     method public java.lang.invoke.MethodHandle asFixedArity();
     method public java.lang.invoke.MethodHandle asSpreader(Class<?>, int);
+    method public java.lang.invoke.MethodHandle asSpreader(int, Class<?>, int);
     method public java.lang.invoke.MethodHandle asType(java.lang.invoke.MethodType);
     method public java.lang.invoke.MethodHandle asVarargsCollector(Class<?>);
     method public java.lang.invoke.MethodHandle bindTo(Object);
@@ -4259,6 +4313,7 @@
     method public Object invokeWithArguments(java.util.List<?>) throws java.lang.Throwable;
     method public boolean isVarargsCollector();
     method public java.lang.invoke.MethodType type();
+    method public java.lang.invoke.MethodHandle withVarargs(boolean);
   }
 
   public interface MethodHandleInfo {
@@ -4286,28 +4341,47 @@
   }
 
   public class MethodHandles {
+    method public static java.lang.invoke.MethodHandle arrayConstructor(Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle arrayElementGetter(Class<?>) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle arrayElementSetter(Class<?>) throws java.lang.IllegalArgumentException;
+    method public static java.lang.invoke.VarHandle arrayElementVarHandle(Class<?>) throws java.lang.IllegalArgumentException;
+    method public static java.lang.invoke.MethodHandle arrayLength(Class<?>) throws java.lang.IllegalArgumentException;
+    method public static java.lang.invoke.VarHandle byteArrayViewVarHandle(Class<?>, java.nio.ByteOrder) throws java.lang.IllegalArgumentException;
+    method public static java.lang.invoke.VarHandle byteBufferViewVarHandle(Class<?>, java.nio.ByteOrder) throws java.lang.IllegalArgumentException;
     method public static java.lang.invoke.MethodHandle catchException(java.lang.invoke.MethodHandle, Class<? extends java.lang.Throwable>, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle collectArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle constant(Class<?>, Object);
+    method public static java.lang.invoke.MethodHandle countedLoop(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle countedLoop(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle doWhileLoop(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, Class<?>...);
+    method public static java.lang.invoke.MethodHandle dropArgumentsToMatch(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>, int);
+    method public static java.lang.invoke.MethodHandle empty(java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandle explicitCastArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
     method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle identity(Class<?>);
     method public static java.lang.invoke.MethodHandle insertArguments(java.lang.invoke.MethodHandle, int, java.lang.Object...);
     method public static java.lang.invoke.MethodHandle invoker(java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle iteratedLoop(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandles.Lookup lookup();
+    method public static java.lang.invoke.MethodHandle loop(java.lang.invoke.MethodHandle[]...);
     method public static java.lang.invoke.MethodHandle permuteArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, int...);
+    method public static java.lang.invoke.MethodHandles.Lookup privateLookupIn(Class<?>, java.lang.invoke.MethodHandles.Lookup) throws java.lang.IllegalAccessException;
     method public static java.lang.invoke.MethodHandles.Lookup publicLookup();
     method public static <T extends java.lang.reflect.Member> T reflectAs(Class<T>, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle spreadInvoker(java.lang.invoke.MethodType, int);
     method public static java.lang.invoke.MethodHandle throwException(Class<?>, Class<? extends java.lang.Throwable>);
+    method public static java.lang.invoke.MethodHandle tryFinally(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle varHandleExactInvoker(java.lang.invoke.VarHandle.AccessMode, java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle varHandleInvoker(java.lang.invoke.VarHandle.AccessMode, java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle whileLoop(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
+    method public static java.lang.invoke.MethodHandle zero(Class<?>);
   }
 
   public static final class MethodHandles.Lookup {
@@ -4319,6 +4393,8 @@
     method public java.lang.invoke.MethodHandle findStatic(Class<?>, String, java.lang.invoke.MethodType) throws java.lang.IllegalAccessException, java.lang.NoSuchMethodException;
     method public java.lang.invoke.MethodHandle findStaticGetter(Class<?>, String, Class<?>) throws java.lang.IllegalAccessException, java.lang.NoSuchFieldException;
     method public java.lang.invoke.MethodHandle findStaticSetter(Class<?>, String, Class<?>) throws java.lang.IllegalAccessException, java.lang.NoSuchFieldException;
+    method public java.lang.invoke.VarHandle findStaticVarHandle(Class<?>, String, Class<?>) throws java.lang.IllegalAccessException, java.lang.NoSuchFieldException;
+    method public java.lang.invoke.VarHandle findVarHandle(Class<?>, String, Class<?>) throws java.lang.IllegalAccessException, java.lang.NoSuchFieldException;
     method public java.lang.invoke.MethodHandle findVirtual(Class<?>, String, java.lang.invoke.MethodType) throws java.lang.IllegalAccessException, java.lang.NoSuchMethodException;
     method public java.lang.invoke.MethodHandles.Lookup in(Class<?>);
     method public Class<?> lookupClass();
@@ -4329,6 +4405,7 @@
     method public java.lang.invoke.MethodHandle unreflectGetter(java.lang.reflect.Field) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflectSetter(java.lang.reflect.Field) throws java.lang.IllegalAccessException;
     method public java.lang.invoke.MethodHandle unreflectSpecial(java.lang.reflect.Method, Class<?>) throws java.lang.IllegalAccessException;
+    method public java.lang.invoke.VarHandle unreflectVarHandle(java.lang.reflect.Field) throws java.lang.IllegalAccessException;
     field public static final int PACKAGE = 8; // 0x8
     field public static final int PRIVATE = 2; // 0x2
     field public static final int PROTECTED = 4; // 0x4
@@ -4350,6 +4427,7 @@
     method public boolean hasWrappers();
     method public java.lang.invoke.MethodType insertParameterTypes(int, Class<?>...);
     method public java.lang.invoke.MethodType insertParameterTypes(int, java.util.List<java.lang.Class<?>>);
+    method public Class<?> lastParameterType();
     method public static java.lang.invoke.MethodType methodType(Class<?>, Class<?>[]);
     method public static java.lang.invoke.MethodType methodType(Class<?>, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodType methodType(Class<?>, Class<?>, Class<?>...);
@@ -4374,6 +4452,86 @@
     method public void setTarget(java.lang.invoke.MethodHandle);
   }
 
+  public abstract class VarHandle {
+    method public final java.lang.invoke.MethodType accessModeType(java.lang.invoke.VarHandle.AccessMode);
+    method public static void acquireFence();
+    method public final Object compareAndExchange(java.lang.Object...);
+    method public final Object compareAndExchangeAcquire(java.lang.Object...);
+    method public final Object compareAndExchangeRelease(java.lang.Object...);
+    method public final boolean compareAndSet(java.lang.Object...);
+    method public final java.util.List<java.lang.Class<?>> coordinateTypes();
+    method public static void fullFence();
+    method public final Object get(java.lang.Object...);
+    method public final Object getAcquire(java.lang.Object...);
+    method public final Object getAndAdd(java.lang.Object...);
+    method public final Object getAndAddAcquire(java.lang.Object...);
+    method public final Object getAndAddRelease(java.lang.Object...);
+    method public final Object getAndBitwiseAnd(java.lang.Object...);
+    method public final Object getAndBitwiseAndAcquire(java.lang.Object...);
+    method public final Object getAndBitwiseAndRelease(java.lang.Object...);
+    method public final Object getAndBitwiseOr(java.lang.Object...);
+    method public final Object getAndBitwiseOrAcquire(java.lang.Object...);
+    method public final Object getAndBitwiseOrRelease(java.lang.Object...);
+    method public final Object getAndBitwiseXor(java.lang.Object...);
+    method public final Object getAndBitwiseXorAcquire(java.lang.Object...);
+    method public final Object getAndBitwiseXorRelease(java.lang.Object...);
+    method public final Object getAndSet(java.lang.Object...);
+    method public final Object getAndSetAcquire(java.lang.Object...);
+    method public final Object getAndSetRelease(java.lang.Object...);
+    method public final Object getOpaque(java.lang.Object...);
+    method public final Object getVolatile(java.lang.Object...);
+    method public final boolean isAccessModeSupported(java.lang.invoke.VarHandle.AccessMode);
+    method public static void loadLoadFence();
+    method public static void releaseFence();
+    method public final void set(java.lang.Object...);
+    method public final void setOpaque(java.lang.Object...);
+    method public final void setRelease(java.lang.Object...);
+    method public final void setVolatile(java.lang.Object...);
+    method public static void storeStoreFence();
+    method public final java.lang.invoke.MethodHandle toMethodHandle(java.lang.invoke.VarHandle.AccessMode);
+    method public final Class<?> varType();
+    method public final boolean weakCompareAndSet(java.lang.Object...);
+    method public final boolean weakCompareAndSetAcquire(java.lang.Object...);
+    method public final boolean weakCompareAndSetPlain(java.lang.Object...);
+    method public final boolean weakCompareAndSetRelease(java.lang.Object...);
+  }
+
+  public enum VarHandle.AccessMode {
+    method public String methodName();
+    method public static java.lang.invoke.VarHandle.AccessMode valueFromMethodName(String);
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode COMPARE_AND_EXCHANGE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode COMPARE_AND_EXCHANGE_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode COMPARE_AND_EXCHANGE_RELEASE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode COMPARE_AND_SET;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_ADD;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_ADD_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_ADD_RELEASE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_AND;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_AND_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_AND_RELEASE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_OR;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_OR_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_OR_RELEASE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_XOR;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_XOR_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_BITWISE_XOR_RELEASE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_SET;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_SET_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_AND_SET_RELEASE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_OPAQUE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode GET_VOLATILE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode SET;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode SET_OPAQUE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode SET_RELEASE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode SET_VOLATILE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode WEAK_COMPARE_AND_SET;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode WEAK_COMPARE_AND_SET_ACQUIRE;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode WEAK_COMPARE_AND_SET_PLAIN;
+    enum_constant public static final java.lang.invoke.VarHandle.AccessMode WEAK_COMPARE_AND_SET_RELEASE;
+  }
+
   public class VolatileCallSite extends java.lang.invoke.CallSite {
     ctor public VolatileCallSite(java.lang.invoke.MethodType);
     ctor public VolatileCallSite(java.lang.invoke.MethodHandle);
@@ -4391,6 +4549,16 @@
 
 package java.lang.ref {
 
+  public final class Cleaner {
+    method public static java.lang.ref.Cleaner create();
+    method public static java.lang.ref.Cleaner create(java.util.concurrent.ThreadFactory);
+    method public java.lang.ref.Cleaner.Cleanable register(Object, Runnable);
+  }
+
+  public static interface Cleaner.Cleanable {
+    method public void clean();
+  }
+
   public class PhantomReference<T> extends java.lang.ref.Reference<T> {
     ctor public PhantomReference(T, java.lang.ref.ReferenceQueue<? super T>);
   }
@@ -4401,6 +4569,7 @@
     method public T get();
     method @Deprecated public boolean isEnqueued();
     method public static void reachabilityFence(Object);
+    method public final boolean refersTo(T);
   }
 
   public class ReferenceQueue<T> {
@@ -4549,6 +4718,7 @@
 
   public class MalformedParameterizedTypeException extends java.lang.RuntimeException {
     ctor public MalformedParameterizedTypeException();
+    ctor public MalformedParameterizedTypeException(String);
   }
 
   public class MalformedParametersException extends java.lang.RuntimeException {
@@ -4700,9 +4870,9 @@
     method public java.math.BigDecimal add(java.math.BigDecimal, java.math.MathContext);
     method public byte byteValueExact();
     method public int compareTo(java.math.BigDecimal);
-    method public java.math.BigDecimal divide(java.math.BigDecimal, int, int);
+    method @Deprecated public java.math.BigDecimal divide(java.math.BigDecimal, int, int);
     method public java.math.BigDecimal divide(java.math.BigDecimal, int, java.math.RoundingMode);
-    method public java.math.BigDecimal divide(java.math.BigDecimal, int);
+    method @Deprecated public java.math.BigDecimal divide(java.math.BigDecimal, int);
     method public java.math.BigDecimal divide(java.math.BigDecimal, java.math.RoundingMode);
     method public java.math.BigDecimal divide(java.math.BigDecimal);
     method public java.math.BigDecimal divide(java.math.BigDecimal, java.math.MathContext);
@@ -4735,10 +4905,11 @@
     method public int scale();
     method public java.math.BigDecimal scaleByPowerOfTen(int);
     method public java.math.BigDecimal setScale(int, java.math.RoundingMode);
-    method public java.math.BigDecimal setScale(int, int);
+    method @Deprecated public java.math.BigDecimal setScale(int, int);
     method public java.math.BigDecimal setScale(int);
     method public short shortValueExact();
     method public int signum();
+    method public java.math.BigDecimal sqrt(java.math.MathContext);
     method public java.math.BigDecimal stripTrailingZeros();
     method public java.math.BigDecimal subtract(java.math.BigDecimal);
     method public java.math.BigDecimal subtract(java.math.BigDecimal, java.math.MathContext);
@@ -4752,20 +4923,22 @@
     method public static java.math.BigDecimal valueOf(long);
     method public static java.math.BigDecimal valueOf(double);
     field public static final java.math.BigDecimal ONE;
-    field public static final int ROUND_CEILING = 2; // 0x2
-    field public static final int ROUND_DOWN = 1; // 0x1
-    field public static final int ROUND_FLOOR = 3; // 0x3
-    field public static final int ROUND_HALF_DOWN = 5; // 0x5
-    field public static final int ROUND_HALF_EVEN = 6; // 0x6
-    field public static final int ROUND_HALF_UP = 4; // 0x4
-    field public static final int ROUND_UNNECESSARY = 7; // 0x7
-    field public static final int ROUND_UP = 0; // 0x0
+    field @Deprecated public static final int ROUND_CEILING = 2; // 0x2
+    field @Deprecated public static final int ROUND_DOWN = 1; // 0x1
+    field @Deprecated public static final int ROUND_FLOOR = 3; // 0x3
+    field @Deprecated public static final int ROUND_HALF_DOWN = 5; // 0x5
+    field @Deprecated public static final int ROUND_HALF_EVEN = 6; // 0x6
+    field @Deprecated public static final int ROUND_HALF_UP = 4; // 0x4
+    field @Deprecated public static final int ROUND_UNNECESSARY = 7; // 0x7
+    field @Deprecated public static final int ROUND_UP = 0; // 0x0
     field public static final java.math.BigDecimal TEN;
     field public static final java.math.BigDecimal ZERO;
   }
 
   public class BigInteger extends java.lang.Number implements java.lang.Comparable<java.math.BigInteger> {
+    ctor public BigInteger(byte[], int, int);
     ctor public BigInteger(byte[]);
+    ctor public BigInteger(int, byte[], int, int);
     ctor public BigInteger(int, byte[]);
     ctor public BigInteger(@NonNull String, int);
     ctor public BigInteger(@NonNull String);
@@ -4810,6 +4983,8 @@
     method @NonNull public java.math.BigInteger shiftRight(int);
     method public short shortValueExact();
     method public int signum();
+    method @NonNull public java.math.BigInteger sqrt();
+    method @NonNull public java.math.BigInteger[] sqrtAndRemainder();
     method @NonNull public java.math.BigInteger subtract(@NonNull java.math.BigInteger);
     method public boolean testBit(int);
     method public byte[] toByteArray();
@@ -4818,6 +4993,7 @@
     method @NonNull public java.math.BigInteger xor(@NonNull java.math.BigInteger);
     field @NonNull public static final java.math.BigInteger ONE;
     field @NonNull public static final java.math.BigInteger TEN;
+    field @NonNull public static final java.math.BigInteger TWO;
     field @NonNull public static final java.math.BigInteger ZERO;
   }
 
@@ -4974,6 +5150,7 @@
     method public java.net.InetAddress getLocalAddress();
     method public int getLocalPort();
     method public java.net.SocketAddress getLocalSocketAddress();
+    method public <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
     method public int getPort();
     method public int getReceiveBufferSize() throws java.net.SocketException;
     method public java.net.SocketAddress getRemoteSocketAddress();
@@ -4988,11 +5165,13 @@
     method public void send(java.net.DatagramPacket) throws java.io.IOException;
     method public void setBroadcast(boolean) throws java.net.SocketException;
     method public static void setDatagramSocketImplFactory(java.net.DatagramSocketImplFactory) throws java.io.IOException;
+    method public <T> java.net.DatagramSocket setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public void setReceiveBufferSize(int) throws java.net.SocketException;
     method public void setReuseAddress(boolean) throws java.net.SocketException;
     method public void setSendBufferSize(int) throws java.net.SocketException;
     method public void setSoTimeout(int) throws java.net.SocketException;
     method public void setTrafficClass(int) throws java.net.SocketException;
+    method public java.util.Set<java.net.SocketOption<?>> supportedOptions();
   }
 
   public abstract class DatagramSocketImpl implements java.net.SocketOptions {
@@ -5004,6 +5183,7 @@
     method protected void disconnect();
     method protected java.io.FileDescriptor getFileDescriptor();
     method protected int getLocalPort();
+    method protected <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
     method @Deprecated protected abstract byte getTTL() throws java.io.IOException;
     method protected abstract int getTimeToLive() throws java.io.IOException;
     method protected abstract void join(java.net.InetAddress) throws java.io.IOException;
@@ -5014,8 +5194,10 @@
     method protected abstract int peekData(java.net.DatagramPacket) throws java.io.IOException;
     method protected abstract void receive(java.net.DatagramPacket) throws java.io.IOException;
     method protected abstract void send(java.net.DatagramPacket) throws java.io.IOException;
+    method protected <T> void setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method @Deprecated protected abstract void setTTL(byte) throws java.io.IOException;
     method protected abstract void setTimeToLive(int) throws java.io.IOException;
+    method protected java.util.Set<java.net.SocketOption<?>> supportedOptions();
     field protected java.io.FileDescriptor fd;
     field protected int localPort;
   }
@@ -5336,17 +5518,20 @@
     method public java.net.InetAddress getInetAddress();
     method public int getLocalPort();
     method public java.net.SocketAddress getLocalSocketAddress();
+    method public <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
     method public int getReceiveBufferSize() throws java.net.SocketException;
     method public boolean getReuseAddress() throws java.net.SocketException;
     method public int getSoTimeout() throws java.io.IOException;
     method protected final void implAccept(java.net.Socket) throws java.io.IOException;
     method public boolean isBound();
     method public boolean isClosed();
+    method public <T> java.net.ServerSocket setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public void setPerformancePreferences(int, int, int);
     method public void setReceiveBufferSize(int) throws java.net.SocketException;
     method public void setReuseAddress(boolean) throws java.net.SocketException;
     method public void setSoTimeout(int) throws java.net.SocketException;
     method public static void setSocketFactory(java.net.SocketImplFactory) throws java.io.IOException;
+    method public java.util.Set<java.net.SocketOption<?>> supportedOptions();
   }
 
   public class Socket implements java.io.Closeable {
@@ -5371,6 +5556,7 @@
     method public int getLocalPort();
     method public java.net.SocketAddress getLocalSocketAddress();
     method public boolean getOOBInline() throws java.net.SocketException;
+    method public <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
     method public java.io.OutputStream getOutputStream() throws java.io.IOException;
     method public int getPort();
     method public int getReceiveBufferSize() throws java.net.SocketException;
@@ -5389,6 +5575,7 @@
     method public void sendUrgentData(int) throws java.io.IOException;
     method public void setKeepAlive(boolean) throws java.net.SocketException;
     method public void setOOBInline(boolean) throws java.net.SocketException;
+    method public <T> java.net.Socket setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method public void setPerformancePreferences(int, int, int);
     method public void setReceiveBufferSize(int) throws java.net.SocketException;
     method public void setReuseAddress(boolean) throws java.net.SocketException;
@@ -5400,6 +5587,7 @@
     method public void setTrafficClass(int) throws java.net.SocketException;
     method public void shutdownInput() throws java.io.IOException;
     method public void shutdownOutput() throws java.io.IOException;
+    method public java.util.Set<java.net.SocketOption<?>> supportedOptions();
   }
 
   public abstract class SocketAddress implements java.io.Serializable {
@@ -5425,13 +5613,16 @@
     method protected java.net.InetAddress getInetAddress();
     method protected abstract java.io.InputStream getInputStream() throws java.io.IOException;
     method protected int getLocalPort();
+    method protected <T> T getOption(java.net.SocketOption<T>) throws java.io.IOException;
     method protected abstract java.io.OutputStream getOutputStream() throws java.io.IOException;
     method protected int getPort();
     method protected abstract void listen(int) throws java.io.IOException;
     method protected abstract void sendUrgentData(int) throws java.io.IOException;
+    method protected <T> void setOption(java.net.SocketOption<T>, T) throws java.io.IOException;
     method protected void setPerformancePreferences(int, int, int);
     method protected void shutdownInput() throws java.io.IOException;
     method protected void shutdownOutput() throws java.io.IOException;
+    method protected java.util.Set<java.net.SocketOption<?>> supportedOptions();
     method protected boolean supportsUrgentData();
     field protected java.net.InetAddress address;
     field protected java.io.FileDescriptor fd;
@@ -5462,6 +5653,7 @@
     field public static final int SO_OOBINLINE = 4099; // 0x1003
     field public static final int SO_RCVBUF = 4098; // 0x1002
     field public static final int SO_REUSEADDR = 4; // 0x4
+    field public static final int SO_REUSEPORT = 14; // 0xe
     field public static final int SO_SNDBUF = 4097; // 0x1001
     field public static final int SO_TIMEOUT = 4102; // 0x1006
     field public static final int TCP_NODELAY = 1; // 0x1
@@ -5493,6 +5685,7 @@
     field public static final java.net.SocketOption<java.lang.Integer> SO_LINGER;
     field public static final java.net.SocketOption<java.lang.Integer> SO_RCVBUF;
     field public static final java.net.SocketOption<java.lang.Boolean> SO_REUSEADDR;
+    field public static final java.net.SocketOption<java.lang.Boolean> SO_REUSEPORT;
     field public static final java.net.SocketOption<java.lang.Integer> SO_SNDBUF;
     field public static final java.net.SocketOption<java.lang.Boolean> TCP_NODELAY;
   }
@@ -5646,11 +5839,13 @@
     ctor public URLDecoder();
     method @Deprecated public static String decode(String);
     method public static String decode(String, String) throws java.io.UnsupportedEncodingException;
+    method public static String decode(String, java.nio.charset.Charset);
   }
 
   public class URLEncoder {
     method @Deprecated public static String encode(String);
     method public static String encode(String, String) throws java.io.UnsupportedEncodingException;
+    method public static String encode(String, java.nio.charset.Charset);
   }
 
   public abstract class URLStreamHandler {
@@ -5716,6 +5911,8 @@
   }
 
   public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable<java.nio.ByteBuffer> {
+    method @NonNull public final java.nio.ByteBuffer alignedSlice(int);
+    method public final int alignmentOffset(int, int);
     method @NonNull public static java.nio.ByteBuffer allocate(int);
     method @NonNull public static java.nio.ByteBuffer allocateDirect(int);
     method @NonNull public final byte[] array();
@@ -6060,8 +6257,10 @@
     method public static java.io.OutputStream newOutputStream(java.nio.channels.AsynchronousByteChannel);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int);
     method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, String);
+    method public static java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.Charset);
     method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int);
     method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, String);
+    method public static java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.Charset);
   }
 
   public class ClosedByInterruptException extends java.nio.channels.AsynchronousCloseException {
@@ -6279,6 +6478,8 @@
     method public abstract java.nio.channels.SelectableChannel channel();
     method public abstract int interestOps();
     method public abstract java.nio.channels.SelectionKey interestOps(int);
+    method public int interestOpsAnd(int);
+    method public int interestOpsOr(int);
     method public final boolean isAcceptable();
     method public final boolean isConnectable();
     method public final boolean isReadable();
@@ -6300,7 +6501,10 @@
     method public abstract java.nio.channels.spi.SelectorProvider provider();
     method public abstract int select(long) throws java.io.IOException;
     method public abstract int select() throws java.io.IOException;
+    method public int select(java.util.function.Consumer<java.nio.channels.SelectionKey>, long) throws java.io.IOException;
+    method public int select(java.util.function.Consumer<java.nio.channels.SelectionKey>) throws java.io.IOException;
     method public abstract int selectNow() throws java.io.IOException;
+    method public int selectNow(java.util.function.Consumer<java.nio.channels.SelectionKey>) throws java.io.IOException;
     method public abstract java.util.Set<java.nio.channels.SelectionKey> selectedKeys();
     method public abstract java.nio.channels.Selector wakeup();
   }
@@ -6628,6 +6832,7 @@
   public abstract class FileStore {
     ctor protected FileStore();
     method public abstract Object getAttribute(String) throws java.io.IOException;
+    method public long getBlockSize() throws java.io.IOException;
     method public abstract <V extends java.nio.file.attribute.FileStoreAttributeView> V getFileStoreAttributeView(Class<V>);
     method public abstract long getTotalSpace() throws java.io.IOException;
     method public abstract long getUnallocatedSpace() throws java.io.IOException;
@@ -7493,6 +7698,8 @@
     method public static java.security.KeyStore getInstance(String) throws java.security.KeyStoreException;
     method public static java.security.KeyStore getInstance(String, String) throws java.security.KeyStoreException, java.security.NoSuchProviderException;
     method public static java.security.KeyStore getInstance(String, java.security.Provider) throws java.security.KeyStoreException;
+    method public static final java.security.KeyStore getInstance(java.io.File, char[]) throws java.security.cert.CertificateException, java.io.IOException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException;
+    method public static final java.security.KeyStore getInstance(java.io.File, java.security.KeyStore.LoadStoreParameter) throws java.security.cert.CertificateException, java.io.IOException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException;
     method public final java.security.Key getKey(String, char[]) throws java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
     method public final java.security.Provider getProvider();
     method public final String getType();
@@ -7515,6 +7722,7 @@
     method public abstract java.security.KeyStore.ProtectionParameter getProtectionParameter(String) throws java.security.KeyStoreException;
     method public static java.security.KeyStore.Builder newInstance(java.security.KeyStore, java.security.KeyStore.ProtectionParameter);
     method public static java.security.KeyStore.Builder newInstance(String, java.security.Provider, java.io.File, java.security.KeyStore.ProtectionParameter);
+    method public static java.security.KeyStore.Builder newInstance(java.io.File, java.security.KeyStore.ProtectionParameter);
     method public static java.security.KeyStore.Builder newInstance(String, java.security.Provider, java.security.KeyStore.ProtectionParameter);
   }
 
@@ -7590,6 +7798,7 @@
     method public abstract boolean engineIsKeyEntry(String);
     method public abstract void engineLoad(java.io.InputStream, char[]) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
     method public void engineLoad(java.security.KeyStore.LoadStoreParameter) throws java.security.cert.CertificateException, java.io.IOException, java.security.NoSuchAlgorithmException;
+    method public boolean engineProbe(java.io.InputStream) throws java.io.IOException;
     method public abstract void engineSetCertificateEntry(String, java.security.cert.Certificate) throws java.security.KeyStoreException;
     method public void engineSetEntry(String, java.security.KeyStore.Entry, java.security.KeyStore.ProtectionParameter) throws java.security.KeyStoreException;
     method public abstract void engineSetKeyEntry(String, java.security.Key, char[], java.security.cert.Certificate[]) throws java.security.KeyStoreException;
@@ -7942,56 +8151,56 @@
 
 package java.security.acl {
 
-  public interface Acl extends java.security.acl.Owner {
-    method public boolean addEntry(java.security.Principal, java.security.acl.AclEntry) throws java.security.acl.NotOwnerException;
-    method public boolean checkPermission(java.security.Principal, java.security.acl.Permission);
-    method public java.util.Enumeration<java.security.acl.AclEntry> entries();
-    method public String getName();
-    method public java.util.Enumeration<java.security.acl.Permission> getPermissions(java.security.Principal);
-    method public boolean removeEntry(java.security.Principal, java.security.acl.AclEntry) throws java.security.acl.NotOwnerException;
-    method public void setName(java.security.Principal, String) throws java.security.acl.NotOwnerException;
-    method public String toString();
+  @Deprecated public interface Acl extends java.security.acl.Owner {
+    method @Deprecated public boolean addEntry(java.security.Principal, java.security.acl.AclEntry) throws java.security.acl.NotOwnerException;
+    method @Deprecated public boolean checkPermission(java.security.Principal, java.security.acl.Permission);
+    method @Deprecated public java.util.Enumeration<java.security.acl.AclEntry> entries();
+    method @Deprecated public String getName();
+    method @Deprecated public java.util.Enumeration<java.security.acl.Permission> getPermissions(java.security.Principal);
+    method @Deprecated public boolean removeEntry(java.security.Principal, java.security.acl.AclEntry) throws java.security.acl.NotOwnerException;
+    method @Deprecated public void setName(java.security.Principal, String) throws java.security.acl.NotOwnerException;
+    method @Deprecated public String toString();
   }
 
-  public interface AclEntry extends java.lang.Cloneable {
-    method public boolean addPermission(java.security.acl.Permission);
-    method public boolean checkPermission(java.security.acl.Permission);
-    method public Object clone();
-    method public java.security.Principal getPrincipal();
-    method public boolean isNegative();
-    method public java.util.Enumeration<java.security.acl.Permission> permissions();
-    method public boolean removePermission(java.security.acl.Permission);
-    method public void setNegativePermissions();
-    method public boolean setPrincipal(java.security.Principal);
-    method public String toString();
+  @Deprecated public interface AclEntry extends java.lang.Cloneable {
+    method @Deprecated public boolean addPermission(java.security.acl.Permission);
+    method @Deprecated public boolean checkPermission(java.security.acl.Permission);
+    method @Deprecated public Object clone();
+    method @Deprecated public java.security.Principal getPrincipal();
+    method @Deprecated public boolean isNegative();
+    method @Deprecated public java.util.Enumeration<java.security.acl.Permission> permissions();
+    method @Deprecated public boolean removePermission(java.security.acl.Permission);
+    method @Deprecated public void setNegativePermissions();
+    method @Deprecated public boolean setPrincipal(java.security.Principal);
+    method @Deprecated public String toString();
   }
 
-  public class AclNotFoundException extends java.lang.Exception {
-    ctor public AclNotFoundException();
+  @Deprecated public class AclNotFoundException extends java.lang.Exception {
+    ctor @Deprecated public AclNotFoundException();
   }
 
-  public interface Group extends java.security.Principal {
-    method public boolean addMember(java.security.Principal);
-    method public boolean isMember(java.security.Principal);
-    method public java.util.Enumeration<? extends java.security.Principal> members();
-    method public boolean removeMember(java.security.Principal);
+  @Deprecated public interface Group extends java.security.Principal {
+    method @Deprecated public boolean addMember(java.security.Principal);
+    method @Deprecated public boolean isMember(java.security.Principal);
+    method @Deprecated public java.util.Enumeration<? extends java.security.Principal> members();
+    method @Deprecated public boolean removeMember(java.security.Principal);
   }
 
-  public class LastOwnerException extends java.lang.Exception {
-    ctor public LastOwnerException();
+  @Deprecated public class LastOwnerException extends java.lang.Exception {
+    ctor @Deprecated public LastOwnerException();
   }
 
-  public class NotOwnerException extends java.lang.Exception {
-    ctor public NotOwnerException();
+  @Deprecated public class NotOwnerException extends java.lang.Exception {
+    ctor @Deprecated public NotOwnerException();
   }
 
-  public interface Owner {
-    method public boolean addOwner(java.security.Principal, java.security.Principal) throws java.security.acl.NotOwnerException;
-    method public boolean deleteOwner(java.security.Principal, java.security.Principal) throws java.security.acl.LastOwnerException, java.security.acl.NotOwnerException;
-    method public boolean isOwner(java.security.Principal);
+  @Deprecated public interface Owner {
+    method @Deprecated public boolean addOwner(java.security.Principal, java.security.Principal) throws java.security.acl.NotOwnerException;
+    method @Deprecated public boolean deleteOwner(java.security.Principal, java.security.Principal) throws java.security.acl.LastOwnerException, java.security.acl.NotOwnerException;
+    method @Deprecated public boolean isOwner(java.security.Principal);
   }
 
-  public interface Permission {
+  @Deprecated public interface Permission {
   }
 
 }
@@ -8399,6 +8608,12 @@
     method public final java.security.cert.X509Certificate getTrustedCert();
   }
 
+  public final class URICertStoreParameters implements java.security.cert.CertStoreParameters {
+    ctor public URICertStoreParameters(java.net.URI);
+    method public java.security.cert.URICertStoreParameters clone();
+    method public java.net.URI getURI();
+  }
+
   public abstract class X509CRL extends java.security.cert.CRL implements java.security.cert.X509Extension {
     ctor protected X509CRL();
     method public abstract byte[] getEncoded() throws java.security.cert.CRLException;
@@ -8583,6 +8798,18 @@
     field public static final long serialVersionUID = -3314988629879632826L; // 0xd1fecb679990cc46L
   }
 
+  public interface EdECKey {
+    method public java.security.spec.NamedParameterSpec getParams();
+  }
+
+  public interface EdECPrivateKey extends java.security.interfaces.EdECKey java.security.PrivateKey {
+    method public java.util.Optional<byte[]> getBytes();
+  }
+
+  public interface EdECPublicKey extends java.security.interfaces.EdECKey java.security.PublicKey {
+    method public java.security.spec.EdECPoint getPoint();
+  }
+
   public interface RSAKey {
     method public java.math.BigInteger getModulus();
   }
@@ -8618,6 +8845,18 @@
     field public static final long serialVersionUID = -8727434096241101194L; // 0x86e1ecedeceab676L
   }
 
+  public interface XECKey {
+    method public java.security.spec.AlgorithmParameterSpec getParams();
+  }
+
+  public interface XECPrivateKey extends java.security.interfaces.XECKey java.security.PrivateKey {
+    method public java.util.Optional<byte[]> getScalar();
+  }
+
+  public interface XECPublicKey extends java.security.interfaces.XECKey java.security.PublicKey {
+    method public java.math.BigInteger getU();
+  }
+
 }
 
 package java.security.spec {
@@ -8668,9 +8907,8 @@
     method public java.math.BigInteger getP();
   }
 
-  public class ECGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+  public class ECGenParameterSpec extends java.security.spec.NamedParameterSpec implements java.security.spec.AlgorithmParameterSpec {
     ctor public ECGenParameterSpec(String);
-    method public String getName();
   }
 
   public class ECParameterSpec implements java.security.spec.AlgorithmParameterSpec {
@@ -8700,6 +8938,24 @@
     method public java.security.spec.ECPoint getW();
   }
 
+  public final class EdECPoint {
+    ctor public EdECPoint(boolean, @NonNull java.math.BigInteger);
+    method @NonNull public java.math.BigInteger getY();
+    method public boolean isXOdd();
+  }
+
+  public final class EdECPrivateKeySpec implements java.security.spec.KeySpec {
+    ctor public EdECPrivateKeySpec(@NonNull java.security.spec.NamedParameterSpec, @NonNull byte[]);
+    method @NonNull public byte[] getBytes();
+    method @NonNull public java.security.spec.NamedParameterSpec getParams();
+  }
+
+  public final class EdECPublicKeySpec implements java.security.spec.KeySpec {
+    ctor public EdECPublicKeySpec(@NonNull java.security.spec.NamedParameterSpec, @NonNull java.security.spec.EdECPoint);
+    method @NonNull public java.security.spec.NamedParameterSpec getParams();
+    method @NonNull public java.security.spec.EdECPoint getPoint();
+  }
+
   public class EllipticCurve {
     ctor public EllipticCurve(java.security.spec.ECField, java.math.BigInteger, java.math.BigInteger);
     ctor public EllipticCurve(java.security.spec.ECField, java.math.BigInteger, java.math.BigInteger, byte[]);
@@ -8740,6 +8996,15 @@
     field public static final java.security.spec.MGF1ParameterSpec SHA512;
   }
 
+  public class NamedParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+    ctor public NamedParameterSpec(@NonNull String);
+    method @NonNull public String getName();
+    field public static final java.security.spec.NamedParameterSpec ED25519;
+    field public static final java.security.spec.NamedParameterSpec ED448;
+    field public static final java.security.spec.NamedParameterSpec X25519;
+    field public static final java.security.spec.NamedParameterSpec X448;
+  }
+
   public class PKCS8EncodedKeySpec extends java.security.spec.EncodedKeySpec {
     ctor public PKCS8EncodedKeySpec(byte[]);
     method public final String getFormat();
@@ -8809,6 +9074,18 @@
     method public final String getFormat();
   }
 
+  public class XECPrivateKeySpec implements java.security.spec.KeySpec {
+    ctor public XECPrivateKeySpec(java.security.spec.AlgorithmParameterSpec, byte[]);
+    method public java.security.spec.AlgorithmParameterSpec getParams();
+    method public byte[] getScalar();
+  }
+
+  public class XECPublicKeySpec implements java.security.spec.KeySpec {
+    ctor public XECPublicKeySpec(java.security.spec.AlgorithmParameterSpec, java.math.BigInteger);
+    method public java.security.spec.AlgorithmParameterSpec getParams();
+    method public java.math.BigInteger getU();
+  }
+
 }
 
 package java.sql {
@@ -12256,6 +12533,34 @@
     method public static int binarySearch(@NonNull Object[], int, int, @NonNull Object);
     method public static <T> int binarySearch(@NonNull T[], T, @Nullable java.util.Comparator<? super T>);
     method public static <T> int binarySearch(@NonNull T[], int, int, T, @Nullable java.util.Comparator<? super T>);
+    method public static int compare(@Nullable boolean[], @Nullable boolean[]);
+    method public static int compare(@NonNull boolean[], int, int, @NonNull boolean[], int, int);
+    method public static int compare(@Nullable byte[], @Nullable byte[]);
+    method public static int compare(@NonNull byte[], int, int, @NonNull byte[], int, int);
+    method public static int compare(@Nullable short[], @Nullable short[]);
+    method public static int compare(@NonNull short[], int, int, @NonNull short[], int, int);
+    method public static int compare(@Nullable char[], @Nullable char[]);
+    method public static int compare(@NonNull char[], int, int, @NonNull char[], int, int);
+    method public static int compare(@Nullable int[], @Nullable int[]);
+    method public static int compare(@NonNull int[], int, int, @NonNull int[], int, int);
+    method public static int compare(@Nullable long[], @Nullable long[]);
+    method public static int compare(@NonNull long[], int, int, @NonNull long[], int, int);
+    method public static int compare(@Nullable float[], @Nullable float[]);
+    method public static int compare(@NonNull float[], int, int, @NonNull float[], int, int);
+    method public static int compare(@Nullable double[], @Nullable double[]);
+    method public static int compare(@NonNull double[], int, int, @NonNull double[], int, int);
+    method public static <T extends java.lang.Comparable<? super T>> int compare(@Nullable T[], @Nullable T[]);
+    method public static <T extends java.lang.Comparable<? super T>> int compare(@NonNull T[], int, int, @NonNull T[], int, int);
+    method public static <T> int compare(@Nullable T[], @Nullable T[], @NonNull java.util.Comparator<? super T>);
+    method public static <T> int compare(@NonNull T[], int, int, @NonNull T[], int, int, @NonNull java.util.Comparator<? super T>);
+    method public static int compareUnsigned(@Nullable byte[], @Nullable byte[]);
+    method public static int compareUnsigned(@NonNull byte[], int, int, @NonNull byte[], int, int);
+    method public static int compareUnsigned(@Nullable short[], @Nullable short[]);
+    method public static int compareUnsigned(@NonNull short[], int, int, @NonNull short[], int, int);
+    method public static int compareUnsigned(@Nullable int[], @Nullable int[]);
+    method public static int compareUnsigned(@NonNull int[], int, int, @NonNull int[], int, int);
+    method public static int compareUnsigned(@Nullable long[], @Nullable long[]);
+    method public static int compareUnsigned(@NonNull long[], int, int, @NonNull long[], int, int);
     method @NonNull public static <T> T[] copyOf(@NonNull T[], int);
     method @NonNull public static <T, U> T[] copyOf(@NonNull U[], int, @NonNull Class<? extends T[]>);
     method @NonNull public static byte[] copyOf(@NonNull byte[], int);
@@ -12280,14 +12585,25 @@
     method public static int deepHashCode(@Nullable Object[]);
     method @NonNull public static String deepToString(@Nullable Object[]);
     method public static boolean equals(@Nullable long[], @Nullable long[]);
+    method public static boolean equals(@NonNull long[], int, int, @NonNull long[], int, int);
     method public static boolean equals(@Nullable int[], @Nullable int[]);
+    method public static boolean equals(@NonNull int[], int, int, @NonNull int[], int, int);
     method public static boolean equals(@Nullable short[], @Nullable short[]);
+    method public static boolean equals(@NonNull short[], int, int, @NonNull short[], int, int);
     method public static boolean equals(@Nullable char[], @Nullable char[]);
+    method public static boolean equals(@NonNull char[], int, int, @NonNull char[], int, int);
     method public static boolean equals(@Nullable byte[], @Nullable byte[]);
+    method public static boolean equals(@NonNull byte[], int, int, @NonNull byte[], int, int);
     method public static boolean equals(@Nullable boolean[], @Nullable boolean[]);
+    method public static boolean equals(@NonNull boolean[], int, int, @NonNull boolean[], int, int);
     method public static boolean equals(@Nullable double[], @Nullable double[]);
+    method public static boolean equals(@NonNull double[], int, int, @NonNull double[], int, int);
     method public static boolean equals(@Nullable float[], @Nullable float[]);
+    method public static boolean equals(@NonNull float[], int, int, @NonNull float[], int, int);
     method public static boolean equals(@Nullable Object[], @Nullable Object[]);
+    method public static boolean equals(@NonNull Object[], int, int, @NonNull Object[], int, int);
+    method public static <T> boolean equals(@Nullable T[], @Nullable T[], @NonNull java.util.Comparator<? super T>);
+    method public static <T> boolean equals(@NonNull T[], int, int, @NonNull T[], int, int, @NonNull java.util.Comparator<? super T>);
     method public static void fill(@NonNull long[], long);
     method public static void fill(@NonNull long[], int, int, long);
     method public static void fill(@NonNull int[], int);
@@ -12315,6 +12631,26 @@
     method public static int hashCode(@Nullable float[]);
     method public static int hashCode(@Nullable double[]);
     method public static int hashCode(@Nullable Object[]);
+    method public static int mismatch(@NonNull boolean[], @NonNull boolean[]);
+    method public static int mismatch(@NonNull boolean[], int, int, @NonNull boolean[], int, int);
+    method public static int mismatch(@NonNull byte[], @NonNull byte[]);
+    method public static int mismatch(byte[], int, int, byte[], int, int);
+    method public static int mismatch(@NonNull char[], @NonNull char[]);
+    method public static int mismatch(@NonNull char[], int, int, @NonNull char[], int, int);
+    method public static int mismatch(@NonNull short[], @NonNull short[]);
+    method public static int mismatch(@NonNull short[], int, int, @NonNull short[], int, int);
+    method public static int mismatch(@NonNull int[], @NonNull int[]);
+    method public static int mismatch(@NonNull int[], int, int, @NonNull int[], int, int);
+    method public static int mismatch(@NonNull long[], @NonNull long[]);
+    method public static int mismatch(@NonNull long[], int, int, @NonNull long[], int, int);
+    method public static int mismatch(@NonNull float[], @NonNull float[]);
+    method public static int mismatch(@NonNull float[], int, int, @NonNull float[], int, int);
+    method public static int mismatch(@NonNull double[], @NonNull double[]);
+    method public static int mismatch(@NonNull double[], int, int, @NonNull double[], int, int);
+    method public static int mismatch(@NonNull Object[], @NonNull Object[]);
+    method public static int mismatch(@NonNull Object[], int, int, @NonNull Object[], int, int);
+    method public static <T> int mismatch(@NonNull T[], @NonNull T[], @NonNull java.util.Comparator<? super T>);
+    method public static <T> int mismatch(@NonNull T[], int, int, @NonNull T[], int, int, @NonNull java.util.Comparator<? super T>);
     method public static <T> void parallelPrefix(@NonNull T[], @NonNull java.util.function.BinaryOperator<T>);
     method public static <T> void parallelPrefix(@NonNull T[], int, int, @NonNull java.util.function.BinaryOperator<T>);
     method public static void parallelPrefix(@NonNull long[], @NonNull java.util.function.LongBinaryOperator);
@@ -12607,6 +12943,7 @@
     method @NonNull public default java.util.stream.Stream<E> stream();
     method @NonNull public Object[] toArray();
     method @NonNull public <T> T[] toArray(@NonNull T[]);
+    method @NonNull public default <T> T[] toArray(@NonNull java.util.function.IntFunction<T[]>);
   }
 
   public class Collections {
@@ -12833,6 +13170,7 @@
   }
 
   public interface Enumeration<E> {
+    method public default java.util.Iterator<E> asIterator();
     method public boolean hasMoreElements();
     method public E nextElement();
   }
@@ -13020,6 +13358,7 @@
 
   public class IntSummaryStatistics implements java.util.function.IntConsumer {
     ctor public IntSummaryStatistics();
+    ctor public IntSummaryStatistics(long, int, int, long) throws java.lang.IllegalArgumentException;
     method public void accept(int);
     method public void combine(java.util.IntSummaryStatistics);
     method public final double getAverage();
@@ -13244,6 +13583,7 @@
 
   public class LongSummaryStatistics implements java.util.function.IntConsumer java.util.function.LongConsumer {
     ctor public LongSummaryStatistics();
+    ctor public LongSummaryStatistics(long, long, long, long) throws java.lang.IllegalArgumentException;
     method public void accept(int);
     method public void accept(long);
     method public void combine(java.util.LongSummaryStatistics);
@@ -13384,69 +13724,86 @@
     method @NonNull public static String toString(@Nullable Object, @NonNull String);
   }
 
-  public class Observable {
-    ctor public Observable();
-    method public void addObserver(java.util.Observer);
-    method protected void clearChanged();
-    method public int countObservers();
-    method public void deleteObserver(java.util.Observer);
-    method public void deleteObservers();
-    method public boolean hasChanged();
-    method public void notifyObservers();
-    method public void notifyObservers(Object);
-    method protected void setChanged();
+  @Deprecated public class Observable {
+    ctor @Deprecated public Observable();
+    method @Deprecated public void addObserver(java.util.Observer);
+    method @Deprecated protected void clearChanged();
+    method @Deprecated public int countObservers();
+    method @Deprecated public void deleteObserver(java.util.Observer);
+    method @Deprecated public void deleteObservers();
+    method @Deprecated public boolean hasChanged();
+    method @Deprecated public void notifyObservers();
+    method @Deprecated public void notifyObservers(Object);
+    method @Deprecated protected void setChanged();
   }
 
-  public interface Observer {
-    method public void update(java.util.Observable, Object);
+  @Deprecated public interface Observer {
+    method @Deprecated public void update(java.util.Observable, Object);
   }
 
   public final class Optional<T> {
     method public static <T> java.util.Optional<T> empty();
     method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
-    method public <U> java.util.Optional<U> flatMap(java.util.function.Function<? super T,java.util.Optional<U>>);
+    method public <U> java.util.Optional<U> flatMap(java.util.function.Function<? super T,? extends java.util.Optional<? extends U>>);
     method public T get();
     method public void ifPresent(java.util.function.Consumer<? super T>);
+    method public void ifPresentOrElse(java.util.function.Consumer<? super T>, Runnable);
+    method public boolean isEmpty();
     method public boolean isPresent();
     method public <U> java.util.Optional<U> map(java.util.function.Function<? super T,? extends U>);
     method public static <T> java.util.Optional<T> of(T);
     method public static <T> java.util.Optional<T> ofNullable(T);
+    method public java.util.Optional<T> or(java.util.function.Supplier<? extends java.util.Optional<? extends T>>);
     method public T orElse(T);
     method public T orElseGet(java.util.function.Supplier<? extends T>);
+    method public T orElseThrow();
     method public <X extends java.lang.Throwable> T orElseThrow(java.util.function.Supplier<? extends X>) throws X;
+    method public java.util.stream.Stream<T> stream();
   }
 
   public final class OptionalDouble {
     method public static java.util.OptionalDouble empty();
     method public double getAsDouble();
     method public void ifPresent(java.util.function.DoubleConsumer);
+    method public void ifPresentOrElse(java.util.function.DoubleConsumer, Runnable);
+    method public boolean isEmpty();
     method public boolean isPresent();
     method public static java.util.OptionalDouble of(double);
     method public double orElse(double);
     method public double orElseGet(java.util.function.DoubleSupplier);
-    method public <X extends java.lang.Throwable> double orElseThrow(java.util.function.Supplier<X>) throws X;
+    method public double orElseThrow();
+    method public <X extends java.lang.Throwable> double orElseThrow(java.util.function.Supplier<? extends X>) throws X;
+    method public java.util.stream.DoubleStream stream();
   }
 
   public final class OptionalInt {
     method public static java.util.OptionalInt empty();
     method public int getAsInt();
     method public void ifPresent(java.util.function.IntConsumer);
+    method public void ifPresentOrElse(java.util.function.IntConsumer, Runnable);
+    method public boolean isEmpty();
     method public boolean isPresent();
     method public static java.util.OptionalInt of(int);
     method public int orElse(int);
     method public int orElseGet(java.util.function.IntSupplier);
-    method public <X extends java.lang.Throwable> int orElseThrow(java.util.function.Supplier<X>) throws X;
+    method public int orElseThrow();
+    method public <X extends java.lang.Throwable> int orElseThrow(java.util.function.Supplier<? extends X>) throws X;
+    method public java.util.stream.IntStream stream();
   }
 
   public final class OptionalLong {
     method public static java.util.OptionalLong empty();
     method public long getAsLong();
     method public void ifPresent(java.util.function.LongConsumer);
+    method public void ifPresentOrElse(java.util.function.LongConsumer, Runnable);
+    method public boolean isEmpty();
     method public boolean isPresent();
     method public static java.util.OptionalLong of(long);
     method public long orElse(long);
     method public long orElseGet(java.util.function.LongSupplier);
-    method public <X extends java.lang.Throwable> long orElseThrow(java.util.function.Supplier<X>) throws X;
+    method public long orElseThrow();
+    method public <X extends java.lang.Throwable> long orElseThrow(java.util.function.Supplier<? extends X>) throws X;
+    method public java.util.stream.LongStream stream();
   }
 
   public interface PrimitiveIterator<T, T_CONS> extends java.util.Iterator<T> {
@@ -13861,6 +14218,7 @@
     method public java.util.stream.LongStream longs(long, long, long);
     method public java.util.stream.LongStream longs(long, long);
     method public boolean nextBoolean();
+    method public void nextBytes(byte[]);
     method public double nextDouble();
     method public double nextDouble(double);
     method public double nextDouble(double, double);
@@ -14105,6 +14463,7 @@
     ctor public ArrayBlockingQueue(int, boolean, java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
     method public int drainTo(java.util.Collection<? super E>, int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
     method public boolean offer(E);
     method public boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
@@ -14345,7 +14704,7 @@
     method public final boolean isEmpty();
     method @NonNull public java.util.Iterator<K> iterator();
     method public boolean remove(@NonNull Object);
-    method public final boolean removeAll(@NonNull java.util.Collection<?>);
+    method public boolean removeAll(@NonNull java.util.Collection<?>);
     method public final boolean retainAll(@NonNull java.util.Collection<?>);
     method public final int size();
     method @NonNull public java.util.Spliterator<K> spliterator();
@@ -14361,6 +14720,7 @@
     method public void addLast(E);
     method public java.util.Iterator<E> descendingIterator();
     method public E element();
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E getFirst();
     method public E getLast();
     method public java.util.Iterator<E> iterator();
@@ -14386,6 +14746,7 @@
   public class ConcurrentLinkedQueue<E> extends java.util.AbstractQueue<E> implements java.util.Queue<E> java.io.Serializable {
     ctor public ConcurrentLinkedQueue();
     ctor public ConcurrentLinkedQueue(java.util.Collection<? extends E>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
     method public boolean offer(E);
     method public E peek();
@@ -14675,6 +15036,7 @@
     ctor public ForkJoinPool();
     ctor public ForkJoinPool(int);
     ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
+    ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean, int, int, int, java.util.function.Predicate<? super java.util.concurrent.ForkJoinPool>, long, java.util.concurrent.TimeUnit);
     method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
     method public static java.util.concurrent.ForkJoinPool commonPool();
@@ -14801,6 +15163,7 @@
     method public java.util.Iterator<E> descendingIterator();
     method public int drainTo(java.util.Collection<? super E>);
     method public int drainTo(java.util.Collection<? super E>, int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E getFirst();
     method public E getLast();
     method public java.util.Iterator<E> iterator();
@@ -14841,6 +15204,7 @@
     ctor public LinkedBlockingQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
     method public int drainTo(java.util.Collection<? super E>, int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
     method public boolean offer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
     method public boolean offer(E);
@@ -14858,6 +15222,7 @@
     ctor public LinkedTransferQueue(java.util.Collection<? extends E>);
     method public int drainTo(java.util.Collection<? super E>);
     method public int drainTo(java.util.Collection<? super E>, int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public int getWaitingConsumerCount();
     method public boolean hasWaitingConsumer();
     method public java.util.Iterator<E> iterator();
@@ -14907,6 +15272,7 @@
     method public java.util.Comparator<? super E> comparator();
     method public int drainTo(java.util.Collection<? super E>);
     method public int drainTo(java.util.Collection<? super E>, int);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public java.util.Iterator<E> iterator();
     method public boolean offer(E);
     method public boolean offer(E, long, java.util.concurrent.TimeUnit);
@@ -15004,6 +15370,29 @@
     method public boolean tryAcquire(int, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
   }
 
+  public class SubmissionPublisher<T> implements java.lang.AutoCloseable java.util.concurrent.Flow.Publisher<T> {
+    ctor public SubmissionPublisher(java.util.concurrent.Executor, int, java.util.function.BiConsumer<? super java.util.concurrent.Flow.Subscriber<? super T>,? super java.lang.Throwable>);
+    ctor public SubmissionPublisher(java.util.concurrent.Executor, int);
+    ctor public SubmissionPublisher();
+    method public void close();
+    method public void closeExceptionally(Throwable);
+    method public java.util.concurrent.CompletableFuture<java.lang.Void> consume(java.util.function.Consumer<? super T>);
+    method public int estimateMaximumLag();
+    method public long estimateMinimumDemand();
+    method public Throwable getClosedException();
+    method public java.util.concurrent.Executor getExecutor();
+    method public int getMaxBufferCapacity();
+    method public int getNumberOfSubscribers();
+    method public java.util.List<java.util.concurrent.Flow.Subscriber<? super T>> getSubscribers();
+    method public boolean hasSubscribers();
+    method public boolean isClosed();
+    method public boolean isSubscribed(java.util.concurrent.Flow.Subscriber<? super T>);
+    method public int offer(T, java.util.function.BiPredicate<java.util.concurrent.Flow.Subscriber<? super T>,? super T>);
+    method public int offer(T, long, java.util.concurrent.TimeUnit, java.util.function.BiPredicate<java.util.concurrent.Flow.Subscriber<? super T>,? super T>);
+    method public int submit(T);
+    method public void subscribe(java.util.concurrent.Flow.Subscriber<? super T>);
+  }
+
   public class SynchronousQueue<E> extends java.util.AbstractQueue<E> implements java.util.concurrent.BlockingQueue<E> java.io.Serializable {
     ctor public SynchronousQueue();
     ctor public SynchronousQueue(boolean);
@@ -15045,7 +15434,7 @@
     method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
     method protected void beforeExecute(Thread, Runnable);
     method public void execute(Runnable);
-    method protected void finalize();
+    method @Deprecated protected void finalize();
     method public int getActiveCount();
     method public long getCompletedTaskCount();
     method public int getCorePoolSize();
@@ -15096,9 +15485,12 @@
 
   public enum TimeUnit {
     method public long convert(long, java.util.concurrent.TimeUnit);
+    method public long convert(java.time.Duration);
+    method public static java.util.concurrent.TimeUnit of(java.time.temporal.ChronoUnit);
     method public void sleep(long) throws java.lang.InterruptedException;
     method public void timedJoin(Thread, long) throws java.lang.InterruptedException;
     method public void timedWait(Object, long) throws java.lang.InterruptedException;
+    method public java.time.temporal.ChronoUnit toChronoUnit();
     method public long toDays(long);
     method public long toHours(long);
     method public long toMicros(long);
@@ -15135,12 +15527,25 @@
   public class AtomicBoolean implements java.io.Serializable {
     ctor public AtomicBoolean(boolean);
     ctor public AtomicBoolean();
+    method public final boolean compareAndExchange(boolean, boolean);
+    method public final boolean compareAndExchangeAcquire(boolean, boolean);
+    method public final boolean compareAndExchangeRelease(boolean, boolean);
     method public final boolean compareAndSet(boolean, boolean);
     method public final boolean get();
+    method public final boolean getAcquire();
     method public final boolean getAndSet(boolean);
+    method public final boolean getOpaque();
+    method public final boolean getPlain();
     method public final void lazySet(boolean);
     method public final void set(boolean);
-    method public boolean weakCompareAndSet(boolean, boolean);
+    method public final void setOpaque(boolean);
+    method public final void setPlain(boolean);
+    method public final void setRelease(boolean);
+    method @Deprecated public boolean weakCompareAndSet(boolean, boolean);
+    method public final boolean weakCompareAndSetAcquire(boolean, boolean);
+    method public boolean weakCompareAndSetPlain(boolean, boolean);
+    method public final boolean weakCompareAndSetRelease(boolean, boolean);
+    method public final boolean weakCompareAndSetVolatile(boolean, boolean);
   }
 
   public class AtomicInteger extends java.lang.Number implements java.io.Serializable {
@@ -15148,24 +15553,37 @@
     ctor public AtomicInteger();
     method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int);
+    method public final int compareAndExchange(int, int);
+    method public final int compareAndExchangeAcquire(int, int);
+    method public final int compareAndExchangeRelease(int, int);
     method public final boolean compareAndSet(int, int);
     method public final int decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final int get();
+    method public final int getAcquire();
     method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int);
     method public final int getAndDecrement();
     method public final int getAndIncrement();
     method public final int getAndSet(int);
     method public final int getAndUpdate(java.util.function.IntUnaryOperator);
+    method public final int getOpaque();
+    method public final int getPlain();
     method public final int incrementAndGet();
     method public int intValue();
     method public final void lazySet(int);
     method public long longValue();
     method public final void set(int);
+    method public final void setOpaque(int);
+    method public final void setPlain(int);
+    method public final void setRelease(int);
     method public final int updateAndGet(java.util.function.IntUnaryOperator);
-    method public final boolean weakCompareAndSet(int, int);
+    method @Deprecated public final boolean weakCompareAndSet(int, int);
+    method public final boolean weakCompareAndSetAcquire(int, int);
+    method public final boolean weakCompareAndSetPlain(int, int);
+    method public final boolean weakCompareAndSetRelease(int, int);
+    method public final boolean weakCompareAndSetVolatile(int, int);
   }
 
   public class AtomicIntegerArray implements java.io.Serializable {
@@ -15173,21 +15591,34 @@
     ctor public AtomicIntegerArray(int[]);
     method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator);
     method public final int addAndGet(int, int);
+    method public final int compareAndExchange(int, int, int);
+    method public final int compareAndExchangeAcquire(int, int, int);
+    method public final int compareAndExchangeRelease(int, int, int);
     method public final boolean compareAndSet(int, int, int);
     method public final int decrementAndGet(int);
     method public final int get(int);
+    method public final int getAcquire(int);
     method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator);
     method public final int getAndAdd(int, int);
     method public final int getAndDecrement(int);
     method public final int getAndIncrement(int);
     method public final int getAndSet(int, int);
     method public final int getAndUpdate(int, java.util.function.IntUnaryOperator);
+    method public final int getOpaque(int);
+    method public final int getPlain(int);
     method public final int incrementAndGet(int);
     method public final void lazySet(int, int);
     method public final int length();
     method public final void set(int, int);
+    method public final void setOpaque(int, int);
+    method public final void setPlain(int, int);
+    method public final void setRelease(int, int);
     method public final int updateAndGet(int, java.util.function.IntUnaryOperator);
-    method public final boolean weakCompareAndSet(int, int, int);
+    method @Deprecated public final boolean weakCompareAndSet(int, int, int);
+    method public final boolean weakCompareAndSetAcquire(int, int, int);
+    method public final boolean weakCompareAndSetPlain(int, int, int);
+    method public final boolean weakCompareAndSetRelease(int, int, int);
+    method public final boolean weakCompareAndSetVolatile(int, int, int);
   }
 
   public abstract class AtomicIntegerFieldUpdater<T> {
@@ -15216,24 +15647,37 @@
     ctor public AtomicLong();
     method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator);
     method public final long addAndGet(long);
+    method public final long compareAndExchange(long, long);
+    method public final long compareAndExchangeAcquire(long, long);
+    method public final long compareAndExchangeRelease(long, long);
     method public final boolean compareAndSet(long, long);
     method public final long decrementAndGet();
     method public double doubleValue();
     method public float floatValue();
     method public final long get();
+    method public final long getAcquire();
     method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(long);
     method public final long getAndDecrement();
     method public final long getAndIncrement();
     method public final long getAndSet(long);
     method public final long getAndUpdate(java.util.function.LongUnaryOperator);
+    method public final long getOpaque();
+    method public final long getPlain();
     method public final long incrementAndGet();
     method public int intValue();
     method public final void lazySet(long);
     method public long longValue();
     method public final void set(long);
+    method public final void setOpaque(long);
+    method public final void setPlain(long);
+    method public final void setRelease(long);
     method public final long updateAndGet(java.util.function.LongUnaryOperator);
-    method public final boolean weakCompareAndSet(long, long);
+    method @Deprecated public final boolean weakCompareAndSet(long, long);
+    method public final boolean weakCompareAndSetAcquire(long, long);
+    method public final boolean weakCompareAndSetPlain(long, long);
+    method public final boolean weakCompareAndSetRelease(long, long);
+    method public final boolean weakCompareAndSetVolatile(long, long);
   }
 
   public class AtomicLongArray implements java.io.Serializable {
@@ -15241,21 +15685,34 @@
     ctor public AtomicLongArray(long[]);
     method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator);
     method public long addAndGet(int, long);
+    method public final long compareAndExchange(int, long, long);
+    method public final long compareAndExchangeAcquire(int, long, long);
+    method public final long compareAndExchangeRelease(int, long, long);
     method public final boolean compareAndSet(int, long, long);
     method public final long decrementAndGet(int);
     method public final long get(int);
+    method public final long getAcquire(int);
     method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator);
     method public final long getAndAdd(int, long);
     method public final long getAndDecrement(int);
     method public final long getAndIncrement(int);
     method public final long getAndSet(int, long);
     method public final long getAndUpdate(int, java.util.function.LongUnaryOperator);
+    method public final long getOpaque(int);
+    method public final long getPlain(int);
     method public final long incrementAndGet(int);
     method public final void lazySet(int, long);
     method public final int length();
     method public final void set(int, long);
+    method public final void setOpaque(int, long);
+    method public final void setPlain(int, long);
+    method public final void setRelease(int, long);
     method public final long updateAndGet(int, java.util.function.LongUnaryOperator);
-    method public final boolean weakCompareAndSet(int, long, long);
+    method @Deprecated public final boolean weakCompareAndSet(int, long, long);
+    method public final boolean weakCompareAndSetAcquire(int, long, long);
+    method public final boolean weakCompareAndSetPlain(int, long, long);
+    method public final boolean weakCompareAndSetRelease(int, long, long);
+    method public final boolean weakCompareAndSetVolatile(int, long, long);
   }
 
   public abstract class AtomicLongFieldUpdater<T> {
@@ -15294,31 +15751,57 @@
     ctor public AtomicReference(V);
     ctor public AtomicReference();
     method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>);
+    method public final V compareAndExchange(V, V);
+    method public final V compareAndExchangeAcquire(V, V);
+    method public final V compareAndExchangeRelease(V, V);
     method public final boolean compareAndSet(V, V);
     method public final V get();
+    method public final V getAcquire();
     method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>);
     method public final V getAndSet(V);
     method public final V getAndUpdate(java.util.function.UnaryOperator<V>);
+    method public final V getOpaque();
+    method public final V getPlain();
     method public final void lazySet(V);
     method public final void set(V);
+    method public final void setOpaque(V);
+    method public final void setPlain(V);
+    method public final void setRelease(V);
     method public final V updateAndGet(java.util.function.UnaryOperator<V>);
-    method public final boolean weakCompareAndSet(V, V);
+    method @Deprecated public final boolean weakCompareAndSet(V, V);
+    method public final boolean weakCompareAndSetAcquire(V, V);
+    method public final boolean weakCompareAndSetPlain(V, V);
+    method public final boolean weakCompareAndSetRelease(V, V);
+    method public final boolean weakCompareAndSetVolatile(V, V);
   }
 
   public class AtomicReferenceArray<E> implements java.io.Serializable {
     ctor public AtomicReferenceArray(int);
     ctor public AtomicReferenceArray(E[]);
     method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>);
+    method public final E compareAndExchange(int, E, E);
+    method public final E compareAndExchangeAcquire(int, E, E);
+    method public final E compareAndExchangeRelease(int, E, E);
     method public final boolean compareAndSet(int, E, E);
     method public final E get(int);
+    method public final E getAcquire(int);
     method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>);
     method public final E getAndSet(int, E);
     method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>);
+    method public final E getOpaque(int);
+    method public final E getPlain(int);
     method public final void lazySet(int, E);
     method public final int length();
     method public final void set(int, E);
+    method public final void setOpaque(int, E);
+    method public final void setPlain(int, E);
+    method public final void setRelease(int, E);
     method public final E updateAndGet(int, java.util.function.UnaryOperator<E>);
-    method public final boolean weakCompareAndSet(int, E, E);
+    method @Deprecated public final boolean weakCompareAndSet(int, E, E);
+    method public final boolean weakCompareAndSetAcquire(int, E, E);
+    method public final boolean weakCompareAndSetPlain(int, E, E);
+    method public final boolean weakCompareAndSetRelease(int, E, E);
+    method public final boolean weakCompareAndSetVolatile(int, E, E);
   }
 
   public abstract class AtomicReferenceFieldUpdater<T, V> {
@@ -15610,7 +16093,11 @@
     method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock();
     method public java.util.concurrent.locks.Lock asWriteLock();
     method public int getReadLockCount();
+    method public static boolean isLockStamp(long);
+    method public static boolean isOptimisticReadStamp(long);
+    method public static boolean isReadLockStamp(long);
     method public boolean isReadLocked();
+    method public static boolean isWriteLockStamp(long);
     method public boolean isWriteLocked();
     method public long readLock();
     method public long readLockInterruptibly() throws java.lang.InterruptedException;
@@ -15807,6 +16294,7 @@
     method public default java.util.function.Predicate<T> and(java.util.function.Predicate<? super T>);
     method public static <T> java.util.function.Predicate<T> isEqual(Object);
     method public default java.util.function.Predicate<T> negate();
+    method public static <T> java.util.function.Predicate<T> not(java.util.function.Predicate<? super T>);
     method public default java.util.function.Predicate<T> or(java.util.function.Predicate<? super T>);
     method public boolean test(T);
   }
@@ -15898,6 +16386,7 @@
     method public java.util.jar.Attributes getAttributes() throws java.io.IOException;
     method public java.security.cert.Certificate[] getCertificates();
     method public java.security.CodeSigner[] getCodeSigners();
+    method public String getRealName();
     field public static final int CENATT = 36; // 0x24
     field public static final int CENATX = 38; // 0x26
     field public static final int CENCOM = 32; // 0x20
@@ -16640,6 +17129,8 @@
     method public static <T> java.util.stream.Collector<T,?,java.lang.Double> averagingLong(java.util.function.ToLongFunction<? super T>);
     method public static <T, A, R, RR> java.util.stream.Collector<T,A,RR> collectingAndThen(java.util.stream.Collector<T,A,R>, java.util.function.Function<R,RR>);
     method public static <T> java.util.stream.Collector<T,?,java.lang.Long> counting();
+    method public static <T, A, R> java.util.stream.Collector<T,?,R> filtering(java.util.function.Predicate<? super T>, java.util.stream.Collector<? super T,A,R>);
+    method public static <T, U, A, R> java.util.stream.Collector<T,?,R> flatMapping(java.util.function.Function<? super T,? extends java.util.stream.Stream<? extends U>>, java.util.stream.Collector<? super U,A,R>);
     method public static <T, K> java.util.stream.Collector<T,?,java.util.Map<K,java.util.List<T>>> groupingBy(java.util.function.Function<? super T,? extends K>);
     method public static <T, K, A, D> java.util.stream.Collector<T,?,java.util.Map<K,D>> groupingBy(java.util.function.Function<? super T,? extends K>, java.util.stream.Collector<? super T,A,D>);
     method public static <T, K, D, A, M extends java.util.Map<K, D>> java.util.stream.Collector<T,?,M> groupingBy(java.util.function.Function<? super T,? extends K>, java.util.function.Supplier<M>, java.util.stream.Collector<? super T,A,D>);
@@ -16672,6 +17163,10 @@
     method public static <T, K, U> java.util.stream.Collector<T,?,java.util.Map<K,U>> toMap(java.util.function.Function<? super T,? extends K>, java.util.function.Function<? super T,? extends U>, java.util.function.BinaryOperator<U>);
     method public static <T, K, U, M extends java.util.Map<K, U>> java.util.stream.Collector<T,?,M> toMap(java.util.function.Function<? super T,? extends K>, java.util.function.Function<? super T,? extends U>, java.util.function.BinaryOperator<U>, java.util.function.Supplier<M>);
     method public static <T> java.util.stream.Collector<T,?,java.util.Set<T>> toSet();
+    method public static <T> java.util.stream.Collector<T,?,java.util.List<T>> toUnmodifiableList();
+    method public static <T, K, U> java.util.stream.Collector<T,?,java.util.Map<K,U>> toUnmodifiableMap(java.util.function.Function<? super T,? extends K>, java.util.function.Function<? super T,? extends U>);
+    method public static <T, K, U> java.util.stream.Collector<T,?,java.util.Map<K,U>> toUnmodifiableMap(java.util.function.Function<? super T,? extends K>, java.util.function.Function<? super T,? extends U>, java.util.function.BinaryOperator<U>);
+    method public static <T> java.util.stream.Collector<T,?,java.util.Set<T>> toUnmodifiableSet();
   }
 
   public interface DoubleStream extends java.util.stream.BaseStream<java.lang.Double,java.util.stream.DoubleStream> {
@@ -19297,6 +19792,7 @@
     ctor public JSONObject(@NonNull String) throws org.json.JSONException;
     ctor public JSONObject(@NonNull org.json.JSONObject, @NonNull String[]) throws org.json.JSONException;
     method @NonNull public org.json.JSONObject accumulate(@NonNull String, @Nullable Object) throws org.json.JSONException;
+    method @NonNull public org.json.JSONObject append(@NonNull String, @Nullable Object) throws org.json.JSONException;
     method @NonNull public Object get(@NonNull String) throws org.json.JSONException;
     method public boolean getBoolean(@NonNull String) throws org.json.JSONException;
     method public double getDouble(@NonNull String) throws org.json.JSONException;
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 15741a7..c85cffb 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -105,12 +105,6 @@
     method public static android.system.UnixSocketAddress createFileSystem(String);
   }
 
-  public final class VmSocketAddress extends java.net.SocketAddress {
-    ctor public VmSocketAddress(int, int);
-    method public int getSvmCid();
-    method public int getSvmPort();
-  }
-
 }
 
 package com.android.okhttp.internalandroidapi {
@@ -162,6 +156,9 @@
   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface FastNative {
   }
 
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface NeverCompile {
+  }
+
 }
 
 package dalvik.system {
@@ -226,6 +223,7 @@
 
   public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
     ctor public DelegateLastClassLoader(String, String, ClassLoader, ClassLoader[]);
+    ctor public DelegateLastClassLoader(String, String, ClassLoader, ClassLoader[], ClassLoader[]);
   }
 
   @Deprecated public final class DexFile {
@@ -246,6 +244,7 @@
 
   public class PathClassLoader extends dalvik.system.BaseDexClassLoader {
     ctor public PathClassLoader(@NonNull String, @Nullable String, @Nullable ClassLoader, @Nullable ClassLoader[]);
+    ctor public PathClassLoader(@NonNull String, @Nullable String, @Nullable ClassLoader, @Nullable ClassLoader[], @Nullable ClassLoader[]);
   }
 
   public final class RuntimeHooks {
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index 8548176..b2ea8cf 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -33,4 +33,29 @@
         "caliper-api-target",
         "android.test.base",
     ],
+    errorprone: {
+        javacflags: ["-Xep:EqualsNull:WARN"],
+    },
+}
+
+android_test {
+    name: "LibcoreBenchmarkTests",
+    srcs: [],
+    static_libs: [
+        "androidx.benchmark_benchmark-junit4",
+        "LibcoreBenchmarkTestsLib",
+    ],
+    sdk_version: "current",
+    manifest: "AndroidManifest.xml",
+    test_suites: ["general-tests"],
+}
+
+java_library {
+    name: "LibcoreBenchmarkTestsLib",
+    srcs: ["src_androidx/**/*.java"],
+    static_libs: [
+        "androidx.benchmark_benchmark-junit4",
+    ],
+    sdk_version: "none",
+    system_modules: "core-all-system-modules",
 }
diff --git a/benchmarks/AndroidManifest.xml b/benchmarks/AndroidManifest.xml
new file mode 100644
index 0000000..611b18b
--- /dev/null
+++ b/benchmarks/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="libcore.benchmark">
+    <!-- Important: disable debuggable for accurate performance results -->
+    <application android:debuggable="false"/>
+
+    <instrumentation
+        android:name="androidx.benchmark.junit4.AndroidBenchmarkRunner"
+        android:targetPackage="libcore.benchmark"/>
+</manifest>
\ No newline at end of file
diff --git a/benchmarks/AndroidTest.xml b/benchmarks/AndroidTest.xml
new file mode 100644
index 0000000..fe1ad99
--- /dev/null
+++ b/benchmarks/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<configuration description="Runs libcore benchmark tests">
+    <!--Test app needs to be installed when we change its settings below-->
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="LibcoreBenchmarkTests.apk"/>
+        <option name="cleanup-apks" value="true"/>
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-tag" value="LibcoreBenchmarkTests"/>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="libcore.benchmark"/>
+        <option name="runner" value="androidx.benchmark.junit4.AndroidBenchmarkRunner"/>
+        <option name="hidden-api-checks" value="false"/>
+        <option name="instrumentation-arg" key="androidx.benchmark.suppressErrors"
+                value="EMULATOR,LOW-BATTERY"/>
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/benchmarks/README.md b/benchmarks/README.md
new file mode 100644
index 0000000..7fef94d
--- /dev/null
+++ b/benchmarks/README.md
@@ -0,0 +1,57 @@
+
+# Run Caliper benchmark tests using vogar on a rooted device
+
+- It uses the [Caliper library](https://github.com/google/caliper) developed by Google.
+- Vogar source codes can be found at `external/vogar`.
+
+1. Preparation
+
+```shell
+# vogar requires com.android.art.testing
+m vogar com.android.art.testing
+# remount if you haven't done so.
+adb root && adb remount && adb reboot && adb wait-for-device root
+cd libcore/benchmarks/src
+```
+
+Extra options to reduce noise:
+```shell
+adb shell stop # to kill frameworks and zygote
+```
+
+2. Run an individual test
+
+```shell
+vogar --benchmark benchmarks/regression/ScannerBenchmark.java
+```
+
+The source code of the tests can be found at `src/benchmarks/`
+
+# Run Jetpack benchmark tests
+Docs about Jetpack Benchmark can be found at
+[https://developer.android.com/studio/profile/benchmarking-overview]()
+
+1. Preparation
+
+To lock CPU clocks on a rooted device,
+run the script provided at [https://developer.android.com/studio/profile/run-benchmarks-in-ci#clock-locking]().
+
+2. Run an individual test
+```shell
+atest LibcoreBenchmarkTests:libcore.benchmark.FormatterTest#stringFormatNumber_allLocales
+```
+
+The source code of the tests can be found at `src_androidx/libcore/benchmark/`
+
+## Outdated documentation / Not working
+
+###VM Options
+
+
+The VM's configuration will have a substantial impact on performance.
+Use Caliper's -J<name> <value 1>,<value 2>,<value 3> syntax to compare different VM options. For example:
+```shell
+vogar --benchmark ~/svn/dalvik/benchmarks/regression/CrespoFileIoRegressionBenchmark.java \
+-- -Jgc -Xgc:noconcurrent,-Xgc:concurrent -Jint -Xint:fast,-Xint:jit,-Xint:portable
+```
+
diff --git a/benchmarks/src/benchmarks/ImtConflictBenchmarkGen.py b/benchmarks/src/benchmarks/ImtConflictBenchmarkGen.py
old mode 100644
new mode 100755
index 8f1fd7e..29fea35
--- a/benchmarks/src/benchmarks/ImtConflictBenchmarkGen.py
+++ b/benchmarks/src/benchmarks/ImtConflictBenchmarkGen.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
 #
 # Copyright 2016 The Android Open Source Project
 #
@@ -65,38 +66,38 @@
 # Warm up interface method tables
 print("    @BeforeExperiment")
 print("    public void setup() {")
-for i in xrange(max_conflict_depth):
+for i in range(max_conflict_depth):
     print("        C{0} c{0} = new C{0}();".format(i))
-    for j in xrange(i+1):
+    for j in range(i+1):
         print("        callF{}(c{});".format(imt_size * j, i))
 print("    }")
 
 # Print test cases--one for each conflict depth
-for i in xrange(max_conflict_depth):
+for i in range(max_conflict_depth):
     print("    public void timeConflictDepth{:02d}(int nreps) {{".format(i+1))
     print("        C{0} c{0} = new C{0}();".format(i))
     print("        for (int i = 0; i < nreps; i++) {")
     # Cycle through each interface method in an IMT entry in order
     # to test all conflict resolution possibilities
-    for j in xrange(max_conflict_depth):
+    for j in range(max_conflict_depth):
         print("            callF{}(c{});".format(imt_size * (j % (i + 1)), i))
     print("        }")
     print("    }")
 
 # Make calls through the IMTs
-for i in xrange(max_conflict_depth):
+for i in range(max_conflict_depth):
     print("    public void callF{0}(I{1} i) {{ i.f{0}(); }}".format(imt_size*i, i))
 
 # Class definitions, implementing varying amounts of interfaces
-for i in xrange(max_conflict_depth):
-    interfaces = ", ".join(["I{}".format(j) for j in xrange(i+1)])
+for i in range(max_conflict_depth):
+    interfaces = ", ".join(["I{}".format(j) for j in range(i+1)])
     print("    static class C{} implements {} {{}}".format(i, interfaces))
 
 # Interface definitions, each with enough methods to fill an entire IMT
-for i in xrange(max_conflict_depth):
+for i in range(max_conflict_depth):
     print("    static interface I{} {{".format(i))
-    for j in xrange(imt_size):
+    for j in range(imt_size):
         print("        default void f{}() {{}}".format(i*imt_size + j))
     print("    }")
 
-print "}"
+print("}")
diff --git a/benchmarks/src/benchmarks/regression/ScannerBenchmark.java b/benchmarks/src/benchmarks/regression/ScannerBenchmark.java
new file mode 100644
index 0000000..3aebb30
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/ScannerBenchmark.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 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 benchmarks.regression;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import com.google.caliper.Param;
+
+import java.io.ByteArrayInputStream;
+import java.util.Random;
+import java.util.Scanner;
+
+public class ScannerBenchmark {
+
+    private static final Random RANDOM = new Random();
+
+    enum LineLength {
+        TINY(1, 5),
+        SHORT(10, 50),
+        MEDIUM(100, 1_000),
+        LONG(10_000, 50_000);
+
+        private final int from;
+        private final int to;
+
+        LineLength(int from, int to) {
+            this.from = from;
+            this.to = to;
+        }
+
+        int get() {
+            return RANDOM.nextInt(to - from) + from;
+        }
+
+        int getMax() {
+            return to;
+        }
+    }
+
+    @Param({"TINY", "SHORT", "MEDIUM"})
+    private LineLength lineLength;
+
+    @Param({"1", "5", "10", "100", "1000", "10000", "25000"})
+    private int linesCount;
+
+    private byte[] data;
+    private int size;
+
+    @BeforeExperiment
+    void setUp() {
+        data = new byte[lineLength.getMax() * linesCount];
+        size = 0;
+
+        for (int i = 0; i < linesCount; ++i) {
+            append(makeString(lineLength.get()));
+            append("\n");
+        }
+
+        byte[] temp = new byte[size];
+        System.arraycopy(data, 0, temp, 0, size);
+        data = temp;
+    }
+
+    private void doubleSize() {
+        byte[] temp = new byte[data.length * 2];
+        System.arraycopy(data, 0, temp, 0, size);
+        data = temp;
+    }
+
+    private void append(String line) {
+        byte[] lineBytes = line.getBytes();
+
+        while (lineBytes.length + size > data.length) {
+            doubleSize();
+        }
+
+        System.arraycopy(lineBytes, 0, data, size, lineBytes.length);
+        size += lineBytes.length;
+    }
+
+    private String makeString(int length) {
+        StringBuilder builder = new StringBuilder(length);
+
+        for (int i = 0; i < length; ++i) {
+            builder.append(i % 10).append(", ");
+        }
+
+        return builder.toString();
+    }
+
+    @Benchmark
+    void readAll() {
+        Scanner scanner = new Scanner(new ByteArrayInputStream(data));
+        while (scanner.hasNext()) {
+            scanner.nextLine();
+        }
+    }
+}
diff --git a/benchmarks/src_androidx/libcore/benchmark/FormatterTest.java b/benchmarks/src_androidx/libcore/benchmark/FormatterTest.java
new file mode 100644
index 0000000..a13a0d6
--- /dev/null
+++ b/benchmarks/src_androidx/libcore/benchmark/FormatterTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 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.benchmark;
+
+import androidx.benchmark.BenchmarkState;
+import androidx.benchmark.junit4.BenchmarkRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+
+@RunWith(AndroidJUnit4.class)
+public class FormatterTest {
+    @Rule
+    public BenchmarkRule benchmarkRule = new BenchmarkRule();
+
+    @Test
+    public void stringFormatNumber_allLocales() {
+        final BenchmarkState state = benchmarkRule.getState();
+        while (state.keepRunning()) {
+            for (Locale locale : Locale.getAvailableLocales()) {
+                // String.format is the most common usage of the Formatter because it's implemented
+                // by Formatter
+                String.format(locale, "%d s", 0);
+            }
+        }
+    }
+
+    @Test
+    public void stringFormatNumber_withWidth_allLocales() {
+        final BenchmarkState state = benchmarkRule.getState();
+        while (state.keepRunning()) {
+            for (Locale locale : Locale.getAvailableLocales()) {
+                String.format(locale, "%05d s", 123);
+            }
+        }
+    }
+
+    @Test
+    public void stringFormatString_allLocales() {
+        final BenchmarkState state = benchmarkRule.getState();
+        while (state.keepRunning()) {
+            for (Locale locale : Locale.getAvailableLocales()) {
+                String.format(locale, "foo-%s-baz", "bar");
+            }
+        }
+    }
+}
diff --git a/benchmarks/src_androidx/libcore/benchmark/StringTest.java b/benchmarks/src_androidx/libcore/benchmark/StringTest.java
new file mode 100644
index 0000000..082db01
--- /dev/null
+++ b/benchmarks/src_androidx/libcore/benchmark/StringTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 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.benchmark;
+
+import androidx.benchmark.BenchmarkState;
+import androidx.benchmark.junit4.BenchmarkRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class StringTest {
+  @Rule
+  public BenchmarkRule benchmarkRule = new BenchmarkRule();
+
+  @Test
+  public void stringRepeat_art_x10() {
+    final BenchmarkState state = benchmarkRule.getState();
+    while (state.keepRunning()) {
+      "hello, world!".repeat(10);
+    }
+  }
+
+  @Test
+  public void timeStringRepeat_art_x100k() {
+    final BenchmarkState state = benchmarkRule.getState();
+    while (state.keepRunning()) {
+      "hello, world!".repeat(100_000);
+    }
+  }
+
+  @Test
+  public void timeStringRepeat_java_x10() {
+    final BenchmarkState state = benchmarkRule.getState();
+    while (state.keepRunning()) {
+      repeatStringBuilder("hello, world!", 10);
+    }
+  }
+
+  @Test
+  public void timeStringRepeat_java_x100k() {
+    final BenchmarkState state = benchmarkRule.getState();
+    while (state.keepRunning()) {
+      repeatStringBuilder("hello, world!", 100_000);
+    }
+  }
+
+  @Test
+  public void stringRepeat_art_x1m_singleChar() {
+    final BenchmarkState state = benchmarkRule.getState();
+    while (state.keepRunning()) {
+      "h".repeat(1_000_000);
+    }
+  }
+
+  @Test
+  public void stringRepeat_java_x1m_singleChar() {
+    final BenchmarkState state = benchmarkRule.getState();
+    while (state.keepRunning()) {
+      repeatStringBuilder("h", 1_000_000);
+    }
+  }
+
+  private static String repeatStringBuilder(String s, int count) {
+    StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < count; i++) {
+      builder.append(s);
+    }
+    return builder.toString();
+  }
+}
diff --git a/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java b/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java
index 95a87af..f131f8b 100644
--- a/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java
+++ b/dalvik/src/main/java/dalvik/annotation/codegen/CovariantReturnType.java
@@ -65,7 +65,6 @@
 @Retention(RetentionPolicy.CLASS)
 @Target({ ElementType.METHOD})
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public @interface CovariantReturnType {
 
     /**
@@ -75,7 +74,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     Class<?> returnType();
 
     /**
@@ -85,18 +83,15 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     int presentAfter();
 
     /** @hide */
     @Retention(RetentionPolicy.CLASS)
     @Target({ElementType.METHOD})
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @interface CovariantReturnTypes {
         /** @hide */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         CovariantReturnType[] value();
     }
 }
diff --git a/dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java b/dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java
index 9d4d3fa..110fcd7 100644
--- a/dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java
+++ b/dalvik/src/main/java/dalvik/annotation/compat/VersionCodes.java
@@ -71,4 +71,16 @@
      */
     @IntraCoreApi
     public static final int S = 31;
+
+    /**
+     * The version code for Android Sv2 (API version 32).
+     */
+    @IntraCoreApi
+    public static final int S_V2 = 32;
+
+    /**
+     * The version code for Android T (API version 33).
+     */
+    @IntraCoreApi
+    public static final int TIRAMISU = 33;
 }
diff --git a/dalvik/src/main/java/dalvik/annotation/optimization/CriticalNative.java b/dalvik/src/main/java/dalvik/annotation/optimization/CriticalNative.java
index 0dac897..2f30bc0 100644
--- a/dalvik/src/main/java/dalvik/annotation/optimization/CriticalNative.java
+++ b/dalvik/src/main/java/dalvik/annotation/optimization/CriticalNative.java
@@ -97,7 +97,6 @@
  *
  * @hide
  */
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @SystemApi(client = MODULE_LIBRARIES)
 @Retention(RetentionPolicy.CLASS)  // Save memory, don't instantiate as an object at runtime.
 @Target(ElementType.METHOD)
diff --git a/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java b/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java
index db3efe0..04aa7b8 100644
--- a/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java
+++ b/dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java
@@ -76,7 +76,6 @@
  *
  * @hide
  */
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @SystemApi(client = MODULE_LIBRARIES)
 @libcore.api.IntraCoreApi
 @Retention(RetentionPolicy.CLASS)  // Save memory, don't instantiate as an object at runtime.
diff --git a/dalvik/src/main/java/dalvik/annotation/optimization/NeverCompile.java b/dalvik/src/main/java/dalvik/annotation/optimization/NeverCompile.java
new file mode 100644
index 0000000..b5e72fc
--- /dev/null
+++ b/dalvik/src/main/java/dalvik/annotation/optimization/NeverCompile.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dalvik.annotation.optimization;
+
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
+import android.annotation.SystemApi;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that an API should never be compiled.
+ *
+ * <p>
+ * NeverCompile can be used to annotate methods that should not be compiled and included in .odex
+ * files. Methods that are not called frequently, are never speed-critical, or are only used for
+ * debugging do not necessarily need to run quickly. Applying this annotation to prevent these
+ * methods from being compiled will return some size improvements in the .odex file that they would
+ * otherwise be included in.
+ * </p>
+ *
+ * <p>
+ * This annotation will have no effect when applied to native methods, as JNI stubs will still be
+ * compiled. In addition, it will not stop overriding methods from being compiled, so applying this
+ * annotation to abstract methods will not do anything.
+ * </p>
+ *
+ * <p>
+ * The <code>dumpPackageLPr</code> method in com.android.server.pm can be used as a concrete
+ * example. This is a debug method used to dump all of the information about a device's installed
+ * packages. When it is compiled, it is included in services.odex. Annotating this method with
+ * NeverCompile can be seen to reduce the size of services.odex by roughly 28KB.
+ * </p>
+ * @hide
+ */
+@SystemApi(client = MODULE_LIBRARIES)
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.METHOD)
+public @interface NeverCompile {}
diff --git a/dalvik/src/main/java/dalvik/system/AppSpecializationHooks.java b/dalvik/src/main/java/dalvik/system/AppSpecializationHooks.java
index e311902..5c05f46 100644
--- a/dalvik/src/main/java/dalvik/system/AppSpecializationHooks.java
+++ b/dalvik/src/main/java/dalvik/system/AppSpecializationHooks.java
@@ -26,7 +26,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class AppSpecializationHooks {
 
     private AppSpecializationHooks() {}
@@ -43,7 +42,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void handleCompatChangesBeforeBindingApplication() {
         com.android.i18n.system.AppSpecializationHooks
                 .handleCompatChangesBeforeBindingApplication();
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
index 60511a9..5fbf585 100644
--- a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
@@ -73,6 +73,19 @@
     protected final ClassLoader[] sharedLibraryLoaders;
 
     /**
+     * Array of ClassLoaders identical to {@code sharedLibraryLoaders} except that these library
+     * loaders are always checked after the {@code pathList} when looking up classes and resources.
+     *
+     * The placement of a library into this group is done by the OEM and cannot be configured by
+     * an App.
+     *
+     * <p>{@code null} if the class loader has no shared library.
+     *
+     * @hide
+     */
+    protected final ClassLoader[] sharedLibraryLoadersAfter;
+
+    /**
      * Constructs an instance.
      * Note that all the *.jar and *.apk files from {@code dexPath} might be
      * first extracted in-memory before the code is loaded. This can be avoided
@@ -89,7 +102,7 @@
      */
     public BaseDexClassLoader(String dexPath, File optimizedDirectory,
             String librarySearchPath, ClassLoader parent) {
-        this(dexPath, librarySearchPath, parent, null, false);
+        this(dexPath, librarySearchPath, parent, null, null, false);
     }
 
     /**
@@ -98,7 +111,7 @@
     @UnsupportedAppUsage
     public BaseDexClassLoader(String dexPath, File optimizedDirectory,
             String librarySearchPath, ClassLoader parent, boolean isTrusted) {
-        this(dexPath, librarySearchPath, parent, null, isTrusted);
+        this(dexPath, librarySearchPath, parent, null, null, isTrusted);
     }
 
     /**
@@ -106,10 +119,19 @@
      */
     public BaseDexClassLoader(String dexPath,
             String librarySearchPath, ClassLoader parent, ClassLoader[] libraries) {
-        this(dexPath, librarySearchPath, parent, libraries, false);
+        this(dexPath, librarySearchPath, parent, libraries, null, false);
     }
 
     /**
+     * @hide
+     */
+    public BaseDexClassLoader(String dexPath, String librarySearchPath,
+            ClassLoader parent, ClassLoader[] libraries, ClassLoader[] librariesAfter) {
+        this(dexPath, librarySearchPath, parent, libraries, librariesAfter, false);
+    }
+
+
+    /**
      * BaseDexClassLoader implements the Android
      * <a href=https://developer.android.com/guide/topics/manifest/uses-library-element>
      * shared libraries</a> feature by changing the typical parent delegation mechanism
@@ -119,11 +141,15 @@
      * after the parent.
      * The shared library loaders are always checked before the {@code pathList} when looking
      * up classes and resources.
+     * <p>
+     * The shared library loaders defined in sharedLibraryLoadersAfter are always checked
+     * <b>after</b> the {@code pathList}
      *
      * @hide
      */
     public BaseDexClassLoader(String dexPath,
             String librarySearchPath, ClassLoader parent, ClassLoader[] sharedLibraryLoaders,
+            ClassLoader[] sharedLibraryLoadersAfter,
             boolean isTrusted) {
         super(parent);
         // Setup shared libraries before creating the path list. ART relies on the class loader
@@ -133,6 +159,9 @@
                 : Arrays.copyOf(sharedLibraryLoaders, sharedLibraryLoaders.length);
         this.pathList = new DexPathList(this, dexPath, librarySearchPath, null, isTrusted);
 
+        this.sharedLibraryLoadersAfter = sharedLibraryLoadersAfter == null
+                ? null
+                : Arrays.copyOf(sharedLibraryLoadersAfter, sharedLibraryLoadersAfter.length);
         // Run background verification after having set 'pathList'.
         this.pathList.maybeRunBackgroundVerification(this);
 
@@ -145,7 +174,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void reportClassLoaderChain() {
         if (reporter == null) {
             return;
@@ -193,6 +221,7 @@
     public BaseDexClassLoader(ByteBuffer[] dexFiles, String librarySearchPath, ClassLoader parent) {
         super(parent);
         this.sharedLibraryLoaders = null;
+        this.sharedLibraryLoadersAfter = null;
         this.pathList = new DexPathList(this, librarySearchPath);
         this.pathList.initByteBufferDexPath(dexFiles);
         // Run background verification after having set 'pathList'.
@@ -214,6 +243,18 @@
         // this classloader operates on.
         List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
         Class c = pathList.findClass(name, suppressedExceptions);
+        if (c != null) {
+            return c;
+        }
+        // Now, check whether the class is present in the "after" shared libraries.
+        if (sharedLibraryLoadersAfter != null) {
+            for (ClassLoader loader : sharedLibraryLoadersAfter) {
+                try {
+                    return loader.loadClass(name);
+                } catch (ClassNotFoundException ignored) {
+                }
+            }
+        }
         if (c == null) {
             ClassNotFoundException cnfe = new ClassNotFoundException(
                     "Didn't find class \"" + name + "\" on path: " + pathList);
@@ -234,7 +275,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void addDexPath(@Nullable String dexPath) {
         addDexPath(dexPath, false /*isTrusted*/);
     }
@@ -256,7 +296,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void addNativePath(@NonNull Collection<String> libPaths) {
         pathList.addNativePath(libPaths);
     }
@@ -271,28 +310,59 @@
                 }
             }
         }
-        return pathList.findResource(name);
+        URL url = pathList.findResource(name);
+        if (url != null) {
+            return url;
+        }
+        if (sharedLibraryLoadersAfter != null) {
+            for (ClassLoader loader : sharedLibraryLoadersAfter) {
+                URL url2 = loader.getResource(name);
+                if (url2 != null) {
+                    return url2;
+                }
+            }
+        }
+        return null;
     }
 
     @Override
     protected Enumeration<URL> findResources(String name) {
         Enumeration<URL> myResources = pathList.findResources(name);
-        if (sharedLibraryLoaders == null) {
+        if (sharedLibraryLoaders == null && sharedLibraryLoadersAfter == null) {
           return myResources;
         }
 
+        int sharedLibraryLoadersCount =
+                (sharedLibraryLoaders != null) ? sharedLibraryLoaders.length : 0;
+        int sharedLibraryLoadersAfterCount =
+                (sharedLibraryLoadersAfter != null) ? sharedLibraryLoadersAfter.length : 0;
+
         Enumeration<URL>[] tmp =
-            (Enumeration<URL>[]) new Enumeration<?>[sharedLibraryLoaders.length + 1];
+                (Enumeration<URL>[]) new Enumeration<?>[sharedLibraryLoadersCount +
+                        sharedLibraryLoadersAfterCount
+                        + 1];
+        // First add sharedLibrary resources.
         // This will add duplicate resources if a shared library is loaded twice, but that's ok
         // as we don't guarantee uniqueness.
-        for (int i = 0; i < sharedLibraryLoaders.length; i++) {
+        int i = 0;
+        for (; i < sharedLibraryLoadersCount; i++) {
             try {
                 tmp[i] = sharedLibraryLoaders[i].getResources(name);
             } catch (IOException e) {
                 // Ignore.
             }
         }
-        tmp[sharedLibraryLoaders.length] = myResources;
+        // Then add resource from this dex path.
+        tmp[i++] = myResources;
+
+        // Finally add resources from shared libraries that are to be loaded after.
+        for (int j = 0; j < sharedLibraryLoadersAfterCount; i++, j++) {
+            try {
+                tmp[i] = sharedLibraryLoadersAfter[j].getResources(name);
+            } catch (IOException e) {
+                // Ignore.
+            }
+        }
         return new CompoundEnumeration<>(tmp);
     }
 
@@ -353,7 +423,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public @NonNull String getLdLibraryPath() {
         StringBuilder result = new StringBuilder();
         for (File directory : pathList.getNativeLibraryDirectories()) {
@@ -379,7 +448,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setReporter(@Nullable Reporter newReporter) {
         reporter = newReporter;
     }
@@ -398,7 +466,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public interface Reporter {
         /**
          * Reports the construction of a BaseDexClassLoader and provides opaque information about
@@ -413,7 +480,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         void report(@NonNull Map<String, String> contextsMap);
     }
 }
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java
index 3472f70..ecc2e92 100644
--- a/dalvik/src/main/java/dalvik/system/BlockGuard.java
+++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java
@@ -38,7 +38,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 public final class BlockGuard {
 
@@ -51,7 +50,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public interface Policy {
         /**
@@ -60,7 +58,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         void onWriteToDisk();
 
         /**
@@ -70,7 +67,6 @@
          */
         @UnsupportedAppUsage
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         void onReadFromDisk();
 
         /**
@@ -88,7 +84,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         void onUnbufferedIO();
 
         /**
@@ -109,7 +104,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         int getPolicyMask();
     }
 
@@ -118,7 +112,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public interface VmPolicy {
         /**
          * Called by core libraries code when the given path is accessed. This
@@ -142,7 +135,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         void onPathAccess(@NonNull String path);
     }
 
@@ -200,7 +192,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final Policy LAX_POLICY = new Policy() {
         @Override public String toString() { return "LAX_POLICY"; }
         @Override public void onWriteToDisk() {}
@@ -221,7 +212,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final VmPolicy LAX_VM_POLICY = new VmPolicy() {
         @Override public String toString() { return "LAX_VM_POLICY"; }
         @Override public void onPathAccess(String path) {}
@@ -246,7 +236,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public static @NonNull Policy getThreadPolicy() {
         return threadPolicy.get();
@@ -265,7 +254,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setThreadPolicy(@NonNull Policy policy) {
         threadPolicy.set(Objects.requireNonNull(policy));
     }
@@ -279,7 +267,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull VmPolicy getVmPolicy() {
         return vmPolicy;
     }
@@ -296,7 +283,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setVmPolicy(@NonNull VmPolicy policy) {
         vmPolicy = Objects.requireNonNull(policy);
     }
diff --git a/dalvik/src/main/java/dalvik/system/CloseGuard.java b/dalvik/src/main/java/dalvik/system/CloseGuard.java
index 959a5a3..e56ad2b 100644
--- a/dalvik/src/main/java/dalvik/system/CloseGuard.java
+++ b/dalvik/src/main/java/dalvik/system/CloseGuard.java
@@ -114,7 +114,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 public final class CloseGuard {
 
@@ -151,7 +150,6 @@
      */
     @UnsupportedAppUsage(trackingBug=111170242)
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public static CloseGuard get() {
         return new CloseGuard();
@@ -170,7 +168,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setEnabled(boolean enabled) {
         CloseGuard.stackAndTrackingEnabled = enabled;
     }
@@ -194,7 +191,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setReporter(Reporter rep) {
         if (rep == null) {
             throw new NullPointerException("reporter == null");
@@ -210,7 +206,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static Reporter getReporter() {
         return reporter;
     }
@@ -257,7 +252,6 @@
      */
     @UnsupportedAppUsage(trackingBug=111170242)
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public void open(String closer) {
         openWithCallSite(closer, null /* callsite */);
@@ -276,7 +270,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void openWithCallSite(String closer, String callsite) {
         // always perform the check for valid API usage...
         if (closer == null) {
@@ -315,7 +308,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public void close() {
         Tracker tracker = currentTracker;
@@ -337,7 +329,6 @@
      */
     @UnsupportedAppUsage(trackingBug=111170242)
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public void warnIfOpen() {
         if (closerNameOrAllocationInfo != null) {
@@ -371,7 +362,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public interface Reporter {
         /**
          *
@@ -379,7 +369,6 @@
          */
         @UnsupportedAppUsage
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         void report(String message, Throwable allocationSite);
 
         /**
@@ -387,7 +376,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         default void report(String message) {}
     }
 
diff --git a/dalvik/src/main/java/dalvik/system/DelegateLastClassLoader.java b/dalvik/src/main/java/dalvik/system/DelegateLastClassLoader.java
index 5966139..25a9557 100644
--- a/dalvik/src/main/java/dalvik/system/DelegateLastClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/DelegateLastClassLoader.java
@@ -132,12 +132,47 @@
      *
      * @hide
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public DelegateLastClassLoader(
             String dexPath, String librarySearchPath, ClassLoader parent,
             ClassLoader[] sharedLibraryLoaders) {
-        super(dexPath, librarySearchPath, parent, sharedLibraryLoaders);
+        this(dexPath, librarySearchPath, parent, sharedLibraryLoaders, null);
+    }
+
+    /**
+     * Creates a {@code DelegateLastClassLoader} that operates on a given {@code dexPath}
+     * and a {@code librarySearchPath}.
+     *
+     * The {@code dexPath} should consist of one or more of the following, separated by
+     * {@code File.pathSeparator}, which is {@code ":"} on Android.
+     *
+     * <ul>
+     * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file as well as arbitrary
+     * resources.
+     * <li>Raw ".dex" files (not inside a zip file).
+     * </ul>
+     *
+     * @param dexPath the list of jar/apk files containing classes and resources, delimited by
+     *                {@code File.pathSeparator}, which defaults to {@code ":"} on Android.
+     * @param librarySearchPath the list of directories containing native libraries, delimited
+     *                          by {@code File.pathSeparator}; may be {@code null}.
+     * @param parent the parent class loader. May be {@code null} for the boot classloader.
+     * @param sharedLibraryLoaders class loaders of Java shared libraries
+     *                             used by this new class loader. The shared library loaders are
+     *                             always checked before the {@code dexPath} when looking
+     *                             up classes and resources.
+     * @param sharedLibraryLoadersAfter class loaders of Java shared libraries
+     *                             used by this new class loader. These shared library loaders are
+     *                             always checked <b>after</b> the {@code dexPath} when looking
+     *                             up classes and resources.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public DelegateLastClassLoader(
+            String dexPath, String librarySearchPath, ClassLoader parent,
+            ClassLoader[] sharedLibraryLoaders, ClassLoader[] sharedLibraryLoadersAfter) {
+        super(dexPath, librarySearchPath, parent, sharedLibraryLoaders, sharedLibraryLoadersAfter);
         // Delegating is the default behavior.
         this.delegateResourceLoading = true;
     }
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index f8e7f42..8a4fb46 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -465,7 +465,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int NO_DEXOPT_NEEDED = 0;
 
     /**
@@ -496,7 +495,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int DEX2OAT_FOR_FILTER = 3;
 
 
@@ -544,7 +542,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native int getDexOptNeeded(@NonNull String fileName,
             @NonNull String instructionSet, @NonNull String compilerFilter, @Nullable String classLoaderContext,
             boolean newProfile, boolean downgrade)
@@ -570,7 +567,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final class OptimizationInfo {
         // The human readable refined optimization status of the validity of the odex file.
         private final String status;
@@ -591,7 +587,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         public @NonNull String getStatus() {
             return status;
         }
@@ -604,7 +599,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         public @NonNull String getReason() {
             return reason;
         }
@@ -621,7 +615,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull OptimizationInfo getDexFileOptimizationInfo(
             @NonNull String fileName, @NonNull String instructionSet) throws FileNotFoundException {
         String[] status = getDexFileOptimizationStatus(fileName, instructionSet);
@@ -655,7 +648,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native @Nullable String[] getDexFileOutputPaths(@NonNull String fileName, @NonNull String instructionSet)
         throws FileNotFoundException;
 
@@ -668,7 +660,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native static boolean isValidCompilerFilter(@NonNull String filter);
 
     /**
@@ -680,7 +671,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native static boolean isProfileGuidedCompilerFilter(@NonNull String filter);
 
     /**
@@ -706,7 +696,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native static @NonNull String getSafeModeCompilerFilter(@NonNull String filter);
 
     /**
diff --git a/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java b/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java
index 7a1c20b..3c7b653 100644
--- a/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java
+++ b/dalvik/src/main/java/dalvik/system/EmulatedStackFrame.java
@@ -16,6 +16,8 @@
 
 package dalvik.system;
 
+import sun.invoke.util.Wrapper;
+
 import java.lang.invoke.MethodType;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -35,12 +37,6 @@
     private final MethodType type;
 
     /**
-     * The type of the callsite that produced this stack frame. This contains the types of
-     * the original arguments, before any conversions etc. were performed.
-     */
-    private final MethodType callsiteType;
-
-    /**
      * All reference arguments and reference return values that belong to this argument array.
      *
      * If the return type is a reference, it will be the last element of this array.
@@ -80,10 +76,8 @@
      */
     private final byte[] stackFrame;
 
-    private EmulatedStackFrame(MethodType type, MethodType callsiteType, Object[] references,
-                               byte[] stackFrame) {
+    private EmulatedStackFrame(MethodType type, Object[] references, byte[] stackFrame) {
         this.type = type;
-        this.callsiteType = callsiteType;
         this.references = references;
         this.stackFrame = stackFrame;
     }
@@ -94,11 +88,6 @@
     public final MethodType getMethodType() { return type; }
 
     /**
-     * Returns the {@code MethodType} corresponding to the callsite of the
-     */
-    public final MethodType getCallsiteType() { return callsiteType; }
-
-    /**
      * Represents a range of arguments on an {@code EmulatedStackFrame}.
      *
      * @hide
@@ -110,6 +99,8 @@
         public final int stackFrameStart;
         public final int numBytes;
 
+        private static Range EMPTY_RANGE = new Range(0, 0, 0, 0);
+
         private Range(int referencesStart, int numReferences, int stackFrameStart, int numBytes) {
             this.referencesStart = referencesStart;
             this.numReferences = numReferences;
@@ -117,18 +108,29 @@
             this.numBytes = numBytes;
         }
 
+        /** Creates a {@code Range} spanning all arguments.
+         * @param frameType the type of the frame.
+         */
         public static Range all(MethodType frameType) {
             return of(frameType, 0, frameType.parameterCount());
         }
 
+        /** Creates a {@code Range} spanning specified arguments.
+         * @param frameType the type of the frame.
+         * @param startArg the first argument in the range to be created.
+         * @param endArg the argument ending the range to be created.
+         */
         public static Range of(MethodType frameType, int startArg, int endArg) {
-            final Class<?>[] ptypes = frameType.ptypes();
+            if (startArg >= endArg) {
+                return EMPTY_RANGE;
+            }
 
             int referencesStart = 0;
             int numReferences = 0;
             int stackFrameStart = 0;
             int numBytes = 0;
 
+            final Class<?>[] ptypes = frameType.ptypes();
             for (int i = 0; i < startArg; ++i) {
                 Class<?> cl = ptypes[i];
                 if (!cl.isPrimitive()) {
@@ -149,6 +151,14 @@
 
             return new Range(referencesStart, numReferences, stackFrameStart, numBytes);
         }
+
+        /** Creates a {@code Range} covering all arguments starting from specified position.
+         * @param frameType the type of the frame.
+         * @param startArg the first argument in the range to be created.
+         */
+        public static Range from(MethodType frameType, int startArg) {
+            return of(frameType, startArg, frameType.parameterCount());
+        }
     }
 
     /**
@@ -172,8 +182,21 @@
             frameSize += getSize(rtype);
         }
 
-        return new EmulatedStackFrame(frameType, frameType, new Object[numRefs],
-                new byte[frameSize]);
+        return new EmulatedStackFrame(frameType, new Object[numRefs], new byte[frameSize]);
+    }
+
+    /**
+     * Convert parameter index to index within references array.
+     */
+    int getReferenceIndex(int parameterIndex) {
+        final Class [] ptypes = type.ptypes();
+        int refIndex = 0;
+        for (int i = 0; i < parameterIndex; ++i) {
+            if (!ptypes[i].isPrimitive()) {
+                refIndex += 1;
+            }
+        }
+        return refIndex;
     }
 
     /**
@@ -184,12 +207,11 @@
         if (idx < 0 || idx >= ptypes.length) {
             throw new IllegalArgumentException("Invalid index: " + idx);
         }
-
         if (reference != null && !ptypes[idx].isInstance(reference)) {
             throw new IllegalStateException("reference is not of type: " + type.ptypes()[idx]);
         }
-
-        references[idx] = reference;
+        int referenceIndex = getReferenceIndex(idx);
+        references[referenceIndex] = reference;
     }
 
     /**
@@ -200,8 +222,8 @@
             throw new IllegalArgumentException("Argument: " + idx +
                     " is of type " + type.ptypes()[idx] + " expected " + referenceType + "");
         }
-
-        return (T) references[idx];
+        int referenceIndex = getReferenceIndex(idx);
+        return (T) references[referenceIndex];
     }
 
     /**
@@ -333,13 +355,14 @@
 
         public StackFrameAccessor attach(EmulatedStackFrame stackFrame, int argumentIdx,
                                          int referencesOffset, int frameOffset) {
-            frame = stackFrame;
-            frameBuf = ByteBuffer.wrap(frame.stackFrame).order(ByteOrder.LITTLE_ENDIAN);
-            numArgs = frame.type.ptypes().length;
-            if (frameOffset != 0) {
-                frameBuf.position(frameOffset);
+            if (frame != stackFrame) {
+                // Re-initialize storage if not re-attaching to the same stackFrame.
+                frame = stackFrame;
+                frameBuf = ByteBuffer.wrap(frame.stackFrame).order(ByteOrder.LITTLE_ENDIAN);
+                numArgs = frame.type.ptypes().length;
             }
 
+            frameBuf.position(frameOffset);
             this.referencesOffset = referencesOffset;
             this.argumentIdx = argumentIdx;
 
@@ -387,26 +410,36 @@
             }
         }
 
-        public static void copyNext(StackFrameReader reader, StackFrameWriter writer,
-                                    Class<?> type) {
-            if (!type.isPrimitive()) {
-                writer.putNextReference(reader.nextReference(type), type);
-            } else if (type == boolean.class) {
-                writer.putNextBoolean(reader.nextBoolean());
-            } else if (type == byte.class) {
-                writer.putNextByte(reader.nextByte());
-            } else if (type == char.class) {
-                writer.putNextChar(reader.nextChar());
-            } else if (type == short.class) {
-                writer.putNextShort(reader.nextShort());
-            } else if (type == int.class) {
-                writer.putNextInt(reader.nextInt());
-            } else if (type == long.class) {
-                writer.putNextLong(reader.nextLong());
-            } else if (type == float.class) {
-                writer.putNextFloat(reader.nextFloat());
-            } else if (type == double.class) {
-                writer.putNextDouble(reader.nextDouble());
+        public static void copyNext(
+                StackFrameReader reader, StackFrameWriter writer, Class<?> type) {
+            switch (Wrapper.basicTypeChar(type)) {
+                case 'L':
+                    writer.putNextReference(reader.nextReference(type), type);
+                    break;
+                case 'Z':
+                    writer.putNextBoolean(reader.nextBoolean());
+                    break;
+                case 'B':
+                    writer.putNextByte(reader.nextByte());
+                    break;
+                case 'C':
+                    writer.putNextChar(reader.nextChar());
+                    break;
+                case 'S':
+                    writer.putNextShort(reader.nextShort());
+                    break;
+                case 'I':
+                    writer.putNextInt(reader.nextInt());
+                    break;
+                case 'J':
+                    writer.putNextLong(reader.nextLong());
+                    break;
+                case 'F':
+                    writer.putNextFloat(reader.nextFloat());
+                    break;
+                case 'D':
+                    writer.putNextDouble(reader.nextDouble());
+                    break;
             }
         }
     }
@@ -530,4 +563,52 @@
             return (T) frame.references[referencesOffset++];
         }
     }
+
+    /**
+     * Provides sequential and non-sequential read access to an emulated stack frame. Allows reads
+     * to argument slots as well as to return value slots.
+     */
+    public static class RandomOrderStackFrameReader extends StackFrameReader {
+        int [] frameOffsets;
+        int [] referencesOffsets;
+
+        private void buildTables(MethodType methodType) {
+            final Class<?> [] ptypes = methodType.parameterArray();
+            frameOffsets = new int [ptypes.length];
+            referencesOffsets = new int [ptypes.length];
+            int frameOffset = 0;
+            int referenceOffset = 0;
+            for (int i = 0; i < ptypes.length; ++i) {
+                frameOffsets[i] = frameOffset;
+                referencesOffsets[i] = referenceOffset;
+
+                final Class<?> ptype = ptypes[i];
+                if (ptype.isPrimitive()) {
+                    frameOffset += getSize(ptype);
+                } else {
+                    referenceOffset += 1;
+                }
+            }
+        }
+
+        @Override
+        public StackFrameAccessor attach(EmulatedStackFrame stackFrame, int argumentIdx,
+                int referencesOffset, int frameOffset) {
+            super.attach(stackFrame, argumentIdx, referencesOffset, frameOffset);
+            buildTables(stackFrame.getMethodType());
+            return this;
+        }
+
+        /**
+         * Position to read argument at specific index.
+         * @param argumentIndex the index of the next argument to be read.
+         * @return this reader.
+         */
+        public RandomOrderStackFrameReader moveTo(int argumentIndex) {
+            referencesOffset = referencesOffsets[argumentIndex];
+            frameBuf.position(frameOffsets[argumentIndex]);
+            argumentIdx = argumentIndex;
+            return this;
+        }
+    }
 }
diff --git a/dalvik/src/main/java/dalvik/system/PathClassLoader.java b/dalvik/src/main/java/dalvik/system/PathClassLoader.java
index 1b74cd9..5174d05 100644
--- a/dalvik/src/main/java/dalvik/system/PathClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/PathClassLoader.java
@@ -100,10 +100,49 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public PathClassLoader(
             @NonNull String dexPath, @Nullable String librarySearchPath, @Nullable ClassLoader parent,
             @Nullable ClassLoader[] sharedLibraryLoaders) {
-        super(dexPath, librarySearchPath, parent, sharedLibraryLoaders);
+        this(dexPath, librarySearchPath, parent, sharedLibraryLoaders, null);
+    }
+
+    /**
+     * Creates a {@code PathClassLoader} that operates on two given
+     * lists of files and directories. The entries of the first list
+     * should be one of the following:
+     *
+     * <ul>
+     * <li>JAR/ZIP/APK files, possibly containing a "classes.dex" file as
+     * well as arbitrary resources.
+     * <li>Raw ".dex" files (not inside a zip file).
+     * </ul>
+     *
+     * The entries of the second list should be directories containing
+     * native library files.
+     *
+     * @param dexPath the list of jar/apk files containing classes and
+     * resources, delimited by {@code File.pathSeparator}, which
+     * defaults to {@code ":"} on Android
+     * @param librarySearchPath the list of directories containing native
+     * libraries, delimited by {@code File.pathSeparator}; may be
+     * {@code null}
+     * @param parent the parent class loader
+     * @param sharedLibraryLoaders class loaders of Java shared libraries
+     * used by this new class loader. The shared library loaders are always
+     * checked before the {@code dexPath} when looking
+     * up classes and resources.
+     * @param sharedLibraryLoadersAfter class loaders of Java shared libraries
+     * used by this new class loader. These shared library loaders are always
+     * checked <b>after</b> the {@code dexPath} when looking
+     * up classes and resources.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    public PathClassLoader(
+            @NonNull String dexPath, @Nullable String librarySearchPath,
+            @Nullable ClassLoader parent, @Nullable ClassLoader[] sharedLibraryLoaders,
+            @Nullable ClassLoader[] sharedLibraryLoadersAfter) {
+        super(dexPath, librarySearchPath, parent, sharedLibraryLoaders, sharedLibraryLoadersAfter);
     }
 }
diff --git a/dalvik/src/main/java/dalvik/system/RuntimeHooks.java b/dalvik/src/main/java/dalvik/system/RuntimeHooks.java
index d86998b..74ee28a 100644
--- a/dalvik/src/main/java/dalvik/system/RuntimeHooks.java
+++ b/dalvik/src/main/java/dalvik/system/RuntimeHooks.java
@@ -37,7 +37,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class RuntimeHooks {
 
     private static Supplier<String> zoneIdSupplier;
@@ -61,7 +60,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setTimeZoneIdSupplier(@NonNull Supplier<String> zoneIdSupplier) {
         if (RuntimeHooks.zoneIdSupplier != null) {
             throw new UnsupportedOperationException("zoneIdSupplier instance already set");
@@ -71,6 +69,14 @@
     }
 
     /**
+     * @hide
+     */
+    // VisibleForTesting
+    public static void clearTimeZoneIdSupplier() {
+        RuntimeHooks.zoneIdSupplier = null;
+    }
+
+    /**
      * Returns the {@link Supplier} that should be used to discover the time zone.
      *
      * @hide
@@ -91,7 +97,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setUncaughtExceptionPreHandler(
             @Nullable Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
         Thread.setUncaughtExceptionPreHandler(uncaughtExceptionHandler);
diff --git a/dalvik/src/main/java/dalvik/system/SocketTagger.java b/dalvik/src/main/java/dalvik/system/SocketTagger.java
index 62803d9..e88acec 100644
--- a/dalvik/src/main/java/dalvik/system/SocketTagger.java
+++ b/dalvik/src/main/java/dalvik/system/SocketTagger.java
@@ -31,7 +31,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public abstract class SocketTagger {
 
     private static SocketTagger tagger = new SocketTagger() {
@@ -44,7 +43,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public SocketTagger() {
     }
 
@@ -59,7 +57,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public abstract void tag(FileDescriptor socketDescriptor) throws SocketException;
 
     /**
@@ -76,7 +73,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public abstract void untag(FileDescriptor socketDescriptor) throws SocketException;
 
     /**
@@ -91,7 +87,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final void tag(Socket socket) throws SocketException {
         if (!socket.isClosed()) {
             tag(socket.getFileDescriptor$());
@@ -114,7 +109,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final void untag(Socket socket) throws SocketException {
         if (!socket.isClosed()) {
             untag(socket.getFileDescriptor$());
@@ -132,7 +126,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final void tag(DatagramSocket socket) throws SocketException {
         if (!socket.isClosed()) {
             tag(socket.getFileDescriptor$());
@@ -154,7 +147,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final void untag(DatagramSocket socket) throws SocketException {
         if (!socket.isClosed()) {
             untag(socket.getFileDescriptor$());
@@ -169,7 +161,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static synchronized void set(SocketTagger tagger) {
         if (tagger == null) {
             throw new NullPointerException("tagger == null");
@@ -186,7 +177,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static synchronized SocketTagger get() {
         return tagger;
     }
diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/dalvik/src/main/java/dalvik/system/VMDebug.java
index 512d5ab..8cafb6c 100644
--- a/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -38,7 +38,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class VMDebug {
     /**
      * flag for startMethodTracing(), which adds the results from
@@ -47,7 +46,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     // Must match android.os.Debug.TRACE_COUNT_ALLOCS.
     public static final int TRACE_COUNT_ALLOCS = 1;
 
@@ -71,7 +69,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_GLOBAL_ALLOCATED_OBJECTS =
         KIND_ALLOCATED_OBJECTS;
 
@@ -82,7 +79,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_GLOBAL_ALLOCATED_BYTES =
         KIND_ALLOCATED_BYTES;
 
@@ -93,7 +89,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_GLOBAL_FREED_OBJECTS =
         KIND_FREED_OBJECTS;
 
@@ -104,7 +99,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_GLOBAL_FREED_BYTES =
         KIND_FREED_BYTES;
 
@@ -115,7 +109,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_GLOBAL_GC_INVOCATIONS =
         KIND_GC_INVOCATIONS;
 
@@ -126,7 +119,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_GLOBAL_CLASS_INIT_COUNT =
         KIND_CLASS_INIT_COUNT;
 
@@ -137,7 +129,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_GLOBAL_CLASS_INIT_TIME =
         KIND_CLASS_INIT_TIME;
 
@@ -148,7 +139,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_THREAD_ALLOCATED_OBJECTS =
         KIND_ALLOCATED_OBJECTS << 16;
 
@@ -159,7 +149,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_THREAD_ALLOCATED_BYTES =
         KIND_ALLOCATED_BYTES << 16;
 
@@ -170,7 +159,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_THREAD_GC_INVOCATIONS =
         KIND_GC_INVOCATIONS << 16;
 
@@ -180,7 +168,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int KIND_ALL_COUNTS = 0xffffffff;
 
     /* all methods are static */
@@ -194,7 +181,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public static native long lastDebuggerActivity();
 
@@ -207,7 +193,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public static native boolean isDebuggingEnabled();
 
@@ -220,7 +205,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public static native boolean isDebuggerConnected();
 
@@ -234,7 +218,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native String[] getVmFeatureList();
 
     /**
@@ -262,7 +245,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void startMethodTracing(String traceFileName, int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
         startMethodTracingFilename(traceFileName, checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
     }
@@ -289,7 +271,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void startMethodTracing(String traceFileName, FileDescriptor fd, int bufferSize,
                                           int flags, boolean samplingEnabled, int intervalUs,
                                           boolean streamingOutput) {
@@ -317,7 +298,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void startMethodTracingDdms(int bufferSize, int flags, boolean samplingEnabled, int intervalUs) {
         startMethodTracingDdmsImpl(checkBufferSize(bufferSize), flags, samplingEnabled, intervalUs);
     }
@@ -345,7 +325,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native int getMethodTracingMode();
 
     /**
@@ -354,7 +333,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void stopMethodTracing();
 
     /**
@@ -372,7 +350,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public static native long threadCpuTimeNanos();
 
@@ -382,7 +359,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void startAllocCounting();
 
     /**
@@ -391,7 +367,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void stopAllocCounting();
 
     /**
@@ -403,7 +378,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native int getAllocCount(int kind);
 
     /**
@@ -414,7 +388,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void resetAllocCount(int kinds);
 
     /**
@@ -477,7 +450,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public static native void printLoadedClasses(int flags);
 
@@ -489,7 +461,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public static native int getLoadedClassCount();
 
@@ -506,7 +477,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void dumpHprofData(String filename) throws IOException {
         if (filename == null) {
             throw new NullPointerException("filename == null");
@@ -523,7 +493,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void dumpHprofDataDdms();
 
     /**
@@ -538,7 +507,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void dumpHprofData(String fileName, FileDescriptor fd)
             throws IOException {
        dumpHprofData(fileName, fd != null ? fd.getInt$() : -1);
@@ -555,7 +523,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void dumpReferenceTables();
 
     /**
@@ -573,7 +540,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native long countInstancesOfClass(Class klass, boolean assignable);
 
     /**
@@ -593,7 +559,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native long[] countInstancesOfClasses(Class[] classes, boolean assignable);
 
     /**
@@ -628,6 +593,7 @@
         runtimeStatsMap.put("art.gc.blocking-gc-count-rate-histogram", 7);
         runtimeStatsMap.put("art.gc.objects-allocated", 8);
         runtimeStatsMap.put("art.gc.total-time-waiting-for-gc", 9);
+        runtimeStatsMap.put("art.gc.pre-oome-gc-count", 10);
     }
 
     /**
@@ -641,7 +607,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static String getRuntimeStat(String statName) {
         if (statName == null) {
             throw new NullPointerException("statName == null");
@@ -662,7 +627,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static Map<String, String> getRuntimeStats() {
         HashMap<String, String> map = new HashMap<>();
         String[] values = getRuntimeStatsInternal();
@@ -688,7 +652,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void attachAgent(String agent, ClassLoader classLoader) throws IOException {
         nativeAttachAgent(agent, classLoader);
     }
@@ -719,6 +682,5 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void setAllocTrackerStackDepth(int stackDepth);
 }
diff --git a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
index a17a257..bfe1945 100644
--- a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
+++ b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
@@ -20,6 +20,7 @@
 
 import android.annotation.SystemApi;
 
+import libcore.icu.DecimalFormatData;
 import libcore.icu.ICU;
 
 import java.io.File;
@@ -28,6 +29,10 @@
 import java.lang.ClassNotFoundException;
 import java.lang.NoSuchMethodException;
 import java.lang.ReflectiveOperationException;
+import libcore.icu.SimpleDateFormatData;
+
+import sun.util.locale.BaseLocale;
+import java.util.Locale;
 
 /**
  * Provides hooks for the zygote to call back into the runtime to perform
@@ -36,10 +41,10 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class ZygoteHooks {
     private static long token;
     private static Method enableMemoryMappedDataMethod;
+    private static boolean inZygoteProcess = true;
 
     /** All methods are static, no need to instantiate. */
     private ZygoteHooks() {
@@ -52,7 +57,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void startZygoteNoThreadCreation();
 
     /**
@@ -61,11 +65,12 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void onBeginPreload() {
         com.android.i18n.system.ZygoteHooks.onBeginPreload();
 
         ICU.initializeCacheInZygote();
+        DecimalFormatData.initializeCacheInZygote();
+        SimpleDateFormatData.initializeCacheInZygote();
 
         // Look up JaCoCo on the boot classpath, if it exists. This will be used later for enabling
         // memory-mapped Java coverage.
@@ -87,7 +92,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void onEndPreload() {
         com.android.i18n.system.ZygoteHooks.onEndPreload();
 
@@ -98,6 +102,16 @@
     }
 
     /**
+     * Called after GC but before fork, it cleans stale cache entries in
+     * BaseLocale and Locale, so to avoid the cleaning to happen in every
+     * child process.
+     */
+    private static void cleanLocaleCaches() {
+        BaseLocale.cleanCache();
+        Locale.cleanCache();
+    }
+
+    /**
      * Runs several special GCs to try to clean up a few generations of
      * softly- and final-reachable objects, along with any other garbage.
      * This is only useful just before a fork().
@@ -105,7 +119,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void gcAndFinalize() {
         final VMRuntime runtime = VMRuntime.getRuntime();
 
@@ -114,6 +127,7 @@
          */
         System.gc();
         runtime.runFinalizationSync();
+        cleanLocaleCaches();
         System.gc();
     }
 
@@ -124,7 +138,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void stopZygoteNoThreadCreation();
 
     /**
@@ -137,7 +150,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void preFork() {
         Daemons.stop();
         token = nativePreFork();
@@ -153,7 +165,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void postForkSystemServer(int runtimeFlags) {
         nativePostForkSystemServer(runtimeFlags);
     }
@@ -170,10 +181,12 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void postForkChild(int runtimeFlags, boolean isSystemServer,
             boolean isChildZygote, String instructionSet) {
         nativePostForkChild(token, runtimeFlags, isSystemServer, isChildZygote, instructionSet);
+        if (!isChildZygote) {
+          inZygoteProcess = false;
+        }
 
         Math.setRandomSeedInternal(System.currentTimeMillis());
 
@@ -196,7 +209,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void postForkCommon() {
         // Notify the runtime before creating new threads.
         nativePostZygoteFork();
@@ -214,11 +226,18 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean isIndefiniteThreadSuspensionSafe() {
         return nativeZygoteLongSuspendOk();
     }
 
+    /**
+     * Are we still in a zygote?
+     * @hide
+     */
+    public static boolean inZygote() {
+      return inZygoteProcess;
+    }
+
     // Hook for SystemServer specific early initialization post-forking.
     private static native void nativePostForkSystemServer(int runtimeFlags);
 
diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java
index 38b4113..2317614 100644
--- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java
+++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/Chunk.java
@@ -32,7 +32,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class Chunk {
 
     /**
@@ -41,7 +40,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public int type;                // chunk type
     /**
      * @hide
@@ -75,7 +73,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public Chunk(int type, byte[] data, int offset, int length) {
         this.type = type;
         this.data = data;
@@ -94,7 +91,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public Chunk(int type, ByteBuffer buf) {
         this.type = type;
 
diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java
index fe936d5..4e8c763 100644
--- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java
+++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/ChunkHandler.java
@@ -32,7 +32,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public abstract class ChunkHandler {
 
     /**
@@ -42,7 +41,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final ByteOrder CHUNK_ORDER = ByteOrder.BIG_ENDIAN;
 
     /**
@@ -56,7 +54,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public ChunkHandler() {}
 
     /**
@@ -66,7 +63,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public abstract void onConnected();
 
     /**
@@ -76,7 +72,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public abstract void onDisconnected();
 
     /**
@@ -91,7 +86,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public abstract Chunk handleChunk(Chunk request);
 
     /**
@@ -105,7 +99,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static Chunk createFailChunk(int errorCode, String msg) {
         if (msg == null)
             msg = "";
@@ -131,7 +124,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static ByteBuffer wrapChunk(Chunk request) {
         ByteBuffer in;
 
@@ -146,7 +138,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int type(String typeName) {
         if (typeName.length() != 4) {
             throw new IllegalArgumentException("Bad type name: " + typeName);
@@ -164,7 +155,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static String name(int type)
     {
         char[] ascii = new char[4];
diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java
index 1465641..110fe51 100644
--- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java
+++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmServer.java
@@ -34,7 +34,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class DdmServer {
 
     private static HashMap<Integer,ChunkHandler> mHandlerMap =
@@ -65,7 +64,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void registerHandler(int type, ChunkHandler handler) {
         if (handler == null) {
             throw new NullPointerException("handler == null");
@@ -87,7 +85,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static ChunkHandler unregisterHandler(int type) {
         synchronized (mHandlerMap) {
             return mHandlerMap.remove(type);
@@ -101,7 +98,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void registrationComplete() {
         // sync on mHandlerMap because it's convenient and makes a kind of
         // sense
@@ -123,7 +119,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void sendChunk(Chunk chunk) {
         nativeSendChunk(chunk.type, chunk.data, chunk.offset, chunk.length);
     }
diff --git a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java
index 8aca688..1aebf6f 100644
--- a/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java
+++ b/dalvik/src/main/java/org/apache/harmony/dalvik/ddmc/DdmVmInternal.java
@@ -27,7 +27,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class DdmVmInternal {
 
     /* do not instantiate */
@@ -43,7 +42,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     native public static void setThreadNotifyEnabled(boolean enabled);
 
     /**
@@ -74,6 +72,5 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     native public static void setRecentAllocationsTrackingEnabled(boolean enabled);
 }
diff --git a/dalvik/src/test/java/libcore/dalvik/system/SocketTaggerTest.java b/dalvik/src/test/java/libcore/dalvik/system/SocketTaggerTest.java
new file mode 100644
index 0000000..16e17c9
--- /dev/null
+++ b/dalvik/src/test/java/libcore/dalvik/system/SocketTaggerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2022 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.dalvik.system;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import dalvik.system.SocketTagger;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SocketTaggerTest {
+
+    private static class MySocketTagger extends SocketTagger {
+
+        private FileDescriptor lastTaggedFd = null;
+        private FileDescriptor lastUntaggedFd = null;
+
+        @Override
+        public void tag(FileDescriptor fd) {
+            lastTaggedFd = fd;
+        }
+
+        @Override
+        public void untag(FileDescriptor fd) {
+            lastUntaggedFd = fd;
+        }
+    }
+
+    @Test
+    public void testTagDatagramSocket() throws SocketException {
+        MySocketTagger tagger = new MySocketTagger();
+        DatagramSocket socket = new DatagramSocket();
+        tagger.tag(socket);
+        assertSame(socket.getFileDescriptor$(), tagger.lastTaggedFd);
+
+        // Test closed socket
+        tagger = new MySocketTagger();
+        socket = new DatagramSocket();
+        socket.close();
+        tagger.tag(socket);
+        assertNull(tagger.lastTaggedFd);
+    }
+
+    @Test
+    public void testUntagDatagramSocket() throws SocketException {
+        MySocketTagger tagger = new MySocketTagger();
+        DatagramSocket socket = new DatagramSocket();
+        tagger.untag(socket);
+        assertSame(socket.getFileDescriptor$(), tagger.lastUntaggedFd);
+
+        // Test closed socket
+        tagger = new MySocketTagger();
+        socket = new DatagramSocket();
+        socket.close();
+        tagger.untag(socket);
+        assertNull(tagger.lastUntaggedFd);
+    }
+
+    @Test
+    public void testTagSocket() throws IOException {
+        MySocketTagger tagger = new MySocketTagger();
+        Socket socket = new Socket();
+        tagger.tag(socket);
+        assertSame(socket.getFileDescriptor$(), tagger.lastTaggedFd);
+
+        // Test closed socket
+        tagger = new MySocketTagger();
+        socket = new Socket();
+        socket.close();
+        tagger.tag(socket);
+        assertNull(tagger.lastTaggedFd);
+    }
+
+    @Test
+    public void testUntagSocket() throws IOException {
+        MySocketTagger tagger = new MySocketTagger();
+        Socket socket = new Socket();
+        tagger.untag(socket);
+        assertSame(socket.getFileDescriptor$(), tagger.lastUntaggedFd);
+
+        // Test closed socket
+        tagger = new MySocketTagger();
+        socket = new Socket();
+        socket.close();
+        tagger.untag(socket);
+        assertNull(tagger.lastUntaggedFd);
+    }
+
+    @Test
+    public void testSet() {
+        SocketTagger originalTagger = SocketTagger.get();
+
+        try {
+            SocketTagger myTagger = new MySocketTagger();
+            SocketTagger.set(myTagger);
+            assertSame(myTagger, SocketTagger.get());
+        } finally {
+            SocketTagger.set(originalTagger);
+        }
+    }
+}
diff --git a/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/ChunkHandlerTest.java b/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/ChunkHandlerTest.java
new file mode 100644
index 0000000..7e42a25
--- /dev/null
+++ b/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/ChunkHandlerTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 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.org.apache.harmony.dalvik.ddmc;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import org.apache.harmony.dalvik.ddmc.Chunk;
+import org.apache.harmony.dalvik.ddmc.ChunkHandler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ChunkHandlerTest {
+
+    @Test
+    public void name() {
+        assertEquals("ABCD", ChunkHandler.name(0x41424344));
+        assertEquals("0123", ChunkHandler.name(0x30313233));
+        assertEquals("0000", ChunkHandler.name(0x30303030));
+        assertEquals("FAIL", ChunkHandler.name(0x4641494c));
+        assertEquals("abcd", ChunkHandler.name(0x61626364));
+        assertEquals("\"#$%", ChunkHandler.name(0x22232425));
+
+        // all printable ASCII chars
+        for (int i = 32; i <= 126; i++) {
+            int test = (i << 24) | (i << 16) | (i << 8) | i;
+            assertEquals(String.format("%c%c%c%c", i, i, i, i), ChunkHandler.name(test));
+        }
+    }
+
+    @Test
+    public void wrapChunk_simple() {
+        final byte[] buf = new byte[]{ 0x00, 0x01 };
+        Chunk request = new Chunk(ChunkHandler.CHUNK_FAIL, buf, 0, 2);
+        ByteBuffer result = ChunkHandler.wrapChunk(request);
+
+        assertArrayEquals(buf, result.array());
+        assertEquals(0, result.arrayOffset());
+        assertEquals(ByteOrder.BIG_ENDIAN, result.order());
+    }
+
+    @Test
+    public void wrapChunk_stress() {
+        final byte[][] BUFS = new byte[][]{
+                {0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
+                {0x41, 0x42, 0x43, 0x44, 0x45},
+        };
+        final int[] TYPES = new int[]{
+                ChunkHandler.type("FAIL"),
+                ChunkHandler.type("1234"),
+                ChunkHandler.type("yeah"),
+        };
+
+        for (byte[] buf : BUFS) {
+            for (int type : TYPES) {
+                for (int offset = 0; offset < buf.length; offset++) {
+                    Chunk request = new Chunk(type, buf, offset, buf.length - offset);
+                    ByteBuffer result = ChunkHandler.wrapChunk(request);
+
+                    assertArrayEquals(buf, result.array());
+                    assertEquals(0, result.arrayOffset());
+                    assertEquals(ByteOrder.BIG_ENDIAN, result.order());
+
+                    for (int i = 0; i < buf.length - offset; i++) {
+                        assertEquals(buf[i + offset], result.get());
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/DdmVmInternalTest.java b/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/DdmVmInternalTest.java
new file mode 100644
index 0000000..b69b385
--- /dev/null
+++ b/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/DdmVmInternalTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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.org.apache.harmony.dalvik.ddmc;
+
+import static org.junit.Assert.assertNotEquals;
+
+import dalvik.system.VMDebug;
+import java.io.File;
+import java.io.IOException;
+import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DdmVmInternalTest {
+
+    public static Stuff stuff;
+
+    /**
+     * Simplified version of art/tools/ahat/src/test-dump/Main.java
+     * @throws IOException
+     */
+    @Test
+    public void setRecentAllocationsTrackingEnabled() throws IOException {
+        stuff = new Stuff();
+
+        // Create a bunch of unreachable objects pointing to basicString
+        for (int i = 0; i < 100; i++) {
+            stuff.basicStringRef = new Object[]{stuff.basicString};
+        }
+
+        String beforePath = File.createTempFile("before", "").getAbsolutePath();
+        String afterPath = File.createTempFile("after", "").getAbsolutePath();
+
+        VMDebug.dumpHprofData(beforePath);
+        DdmVmInternal.setRecentAllocationsTrackingEnabled(true);
+        VMDebug.dumpHprofData(afterPath);
+        DdmVmInternal.setRecentAllocationsTrackingEnabled(false);
+
+        File before = new File(beforePath);
+        File after = new File(afterPath);
+        before.delete();
+        after.delete();
+    }
+}
diff --git a/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/Stuff.java b/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/Stuff.java
new file mode 100644
index 0000000..542fb59
--- /dev/null
+++ b/dalvik/src/test/java/libcore/org/apache/harmony/dalvik/ddmc/Stuff.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 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.org.apache.harmony.dalvik.ddmc;
+
+public class Stuff {
+    public String basicString = "hello, world";
+    public String nonAscii = "Sigma (Ʃ) is not ASCII";
+    public Object[] basicStringRef;
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java
index 601d522..bd5c687 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java
@@ -122,7 +122,7 @@
 
         // regression for HARMONY-1195
         try {
-            os = new PrintStream(bos, true, null);
+            os = new PrintStream(bos, true, (String) null);
             fail("Should throw NPE");
         } catch (NullPointerException e) {
         }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java
index 2465071..74bd62d 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/CharacterTest.java
@@ -16,6 +16,7 @@
 
 package org.apache.harmony.tests.java.lang;
 
+import android.icu.util.VersionInfo;
 import java.util.Arrays;
 
 import junit.framework.TestCase;
@@ -753,7 +754,9 @@
         assertTrue(Character.getType(0x2FFFF) == Character.UNASSIGNED);
         assertTrue(Character.getType(0x3134B) == Character.UNASSIGNED);
 
-        assertTrue(Character.getType(0x9FFF) == Character.UNASSIGNED);
+        byte charType9FFF = VersionInfo.ICU_VERSION.getMajor() >= 70 ? Character.OTHER_LETTER
+            : Character.UNASSIGNED;
+        assertTrue(Character.getType(0x9FFF) == charType9FFF);
         assertTrue(Character.getType(0x110000) == Character.UNASSIGNED);
 
         assertTrue(Character.getType(0x0041) == Character.UPPERCASE_LETTER);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/String2Test.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/String2Test.java
index de7ec1a..2af3b59 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/String2Test.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/String2Test.java
@@ -751,8 +751,8 @@
             hw1.substring(4, 1);
         } catch (StringIndexOutOfBoundsException ex) {
             String msg = ex.getMessage();
-            assertTrue("Expected message to contain -3: " + msg, msg
-                    .indexOf("-3") != -1);
+            assertTrue("Expected message to contain 4 and 1: " + msg,
+                msg.contains("4") && msg.contains("1"));
         }
         try {
             hw1.substring(0, 100);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ThreadTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ThreadTest.java
index 2fc03c5..1e19609 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ThreadTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/ThreadTest.java
@@ -154,6 +154,7 @@
     /**
      * java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.Runnable)
      */
+    @SuppressWarnings("removal")
     public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_Runnable() {
         // Test for method java.lang.Thread(java.lang.ThreadGroup,
         // java.lang.Runnable)
@@ -258,7 +259,7 @@
     /**
      * java.lang.Thread#countStackFrames()
      */
-    @SuppressWarnings("deprecation")
+    @SuppressWarnings("removal")
     public void test_countStackFrames() {
         /*
          * Thread.countStackFrames() is unpredictable, so we just test that it
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/MalformedParameterizedTypeExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/MalformedParameterizedTypeExceptionTest.java
index 04266d5..fa27f12 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/MalformedParameterizedTypeExceptionTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/reflect/MalformedParameterizedTypeExceptionTest.java
@@ -31,4 +31,9 @@
         assertNull(e.getMessage());
     }
 
+    public void testMalformedParameterizedTypeExceptionWithMessage() {
+        MalformedParameterizedTypeException e = new MalformedParameterizedTypeException("message");
+        assertNotNull(e);
+        assertEquals(e.getMessage(), "message");
+    }
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketImplTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketImplTest.java
index fb2d78b..f79c2f3 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketImplTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/DatagramSocketImplTest.java
@@ -25,6 +25,9 @@
 import java.net.NetworkInterface;
 import java.net.SocketAddress;
 import java.net.SocketException;
+import java.net.SocketOption;
+import java.net.SocketOptions;
+import java.net.StandardSocketOptions;
 import libcore.junit.junit3.TestCaseWithRules;
 import libcore.junit.util.ResourceLeakageDetector;
 import org.junit.Rule;
@@ -54,9 +57,34 @@
         // disconnect
         impl.test_disconnect();
     }
+
+    /**
+     * API test for {@link DatagramSocketImpl#setOption(SocketOption, Object)}.
+     */
+    public void testSetOption() throws IOException {
+        // The value isn't sent to the kernel, because the mock intercepts the value in this test.
+        MockDatagramSocketImpl impl = new MockDatagramSocketImpl();
+        setAndAssertOption(impl, StandardSocketOptions.SO_SNDBUF,
+                SocketOptions.SO_SNDBUF, 1);
+        setAndAssertOption(impl, StandardSocketOptions.SO_RCVBUF,
+                SocketOptions.SO_RCVBUF, 2);
+        setAndAssertOption(impl, StandardSocketOptions.SO_REUSEADDR,
+                SocketOptions.SO_REUSEADDR, true);
+        setAndAssertOption(impl, StandardSocketOptions.IP_TOS,
+                SocketOptions.IP_TOS, 3);
+    }
+
+    private static void setAndAssertOption(MockDatagramSocketImpl sockImpl, SocketOption option,
+            int optionInt,  Object value) throws IOException {
+        sockImpl.setSuperOption(option, value);
+        assertEquals(sockImpl.optionInt, optionInt);
+        assertEquals(sockImpl.optionValue, value);
+    }
 }
 
 class MockDatagramSocketImpl extends DatagramSocketImpl {
+    int optionInt;
+    Object optionValue;
 
     @Override
     public FileDescriptor getFileDescriptor() {
@@ -135,8 +163,14 @@
 
     }
 
+    @Override
     public void setOption(int optID, Object val) throws SocketException {
-        // empty
+        this.optionInt = optID;
+        this.optionValue = val;
+    }
+
+    public void setSuperOption(SocketOption option, Object value) throws IOException {
+        super.setOption(option, value);
     }
 
     @Override
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
index dab784a..de0af3a 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
@@ -697,47 +697,40 @@
     @Test
     public void setNetworkInterfaceLjava_net_NetworkInterface_IPv4() throws Exception {
         Assume.assumeTrue(supportsMulticast);
-        check_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv4);
+        check_setNetworkInterfaceLjava_net_NetworkInterface(ipv4NetworkInterface, GOOD_IPv4);
     }
 
     @Test
     public void setNetworkInterfaceLjava_net_NetworkInterface_IPv6() throws Exception {
         Assume.assumeTrue(supportsMulticast);
-        check_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
+        check_setNetworkInterfaceLjava_net_NetworkInterface(ipv6NetworkInterface, GOOD_IPv6);
     }
 
-    private void check_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
+    private void check_setNetworkInterfaceLjava_net_NetworkInterface(
+            NetworkInterface networkInterface, InetAddress group)
             throws IOException, InterruptedException {
         // Set up the receiving socket and join the group.
-        Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
-        while (theInterfaces.hasMoreElements()) {
-            NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
-            if (willWorkForMulticast(thisInterface)) {
-                if ((!(thisInterface.getInetAddresses().nextElement()).isLoopbackAddress())) {
-                    MulticastSocket receivingSocket = createReceivingSocket(0);
-                    InetSocketAddress groupAddress =
-                            new InetSocketAddress(group, receivingSocket.getLocalPort());
-                    receivingSocket.joinGroup(groupAddress, thisInterface);
+        MulticastSocket receivingSocket = createReceivingSocket(0);
+        InetSocketAddress groupAddress =
+                new InetSocketAddress(group, receivingSocket.getLocalPort());
+        receivingSocket.joinGroup(groupAddress, networkInterface);
 
-                    // Send the packets on a particular interface. The source address in the
-                    // received packet should be one of the addresses for the interface set.
-                    MulticastSocket sendingSocket = new MulticastSocket(0);
-                    sendingSocket.setNetworkInterface(thisInterface);
-                    String msg = thisInterface.getName();
-                    DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
-                    sendingSocket.send(sdp);
+        // Send the packets on a particular interface. The source address in the
+        // received packet should be one of the addresses for the interface set.
+        MulticastSocket sendingSocket = new MulticastSocket(0);
+        sendingSocket.setNetworkInterface(networkInterface);
+        String msg = networkInterface.getName();
+        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+        sendingSocket.send(sdp);
 
-                    DatagramPacket rdp = createReceiveDatagramPacket();
-                    receivingSocket.receive(rdp);
-                    String receivedMessage = extractMessage(rdp);
-                    assertEquals("Group member did not recv data sent on a specific interface",
-                            msg, receivedMessage);
-                    // Stop the server.
-                    receivingSocket.close();
-                    sendingSocket.close();
-                }
-            }
-        }
+        DatagramPacket rdp = createReceiveDatagramPacket();
+        receivingSocket.receive(rdp);
+        String receivedMessage = extractMessage(rdp);
+        assertEquals("Group member did not recv data sent on a specific interface",
+                msg, receivedMessage);
+        // Stop the server.
+        receivingSocket.close();
+        sendingSocket.close();
     }
 
     @Test
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
index 31124ce..cb3c01d 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
@@ -220,7 +220,7 @@
         // if channel closed
         msc.close();
         try {
-            msc.register(acceptSelector, SelectionKey.OP_READ, null);
+            msc.register(acceptSelector, SelectionKey.OP_ACCEPT, null);
             fail("Should throw ClosedChannelException");
         } catch (ClosedChannelException e) {
             // expected
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/NumberFormatTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/NumberFormatTest.java
index df9eefc4..d1b408a 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/NumberFormatTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/text/NumberFormatTest.java
@@ -148,7 +148,7 @@
         // Test for method java.text.NumberFormat
         // getIntegerInstance(java.util.Locale)
         Locale usLocale = Locale.US;
-        Locale arLocale = new Locale("ar", "AE");
+        Locale arLocale = new Locale("ar", "EG");
 
         DecimalFormat format = (DecimalFormat) NumberFormat
                 .getIntegerInstance(usLocale);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/AbstractCollectionTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/AbstractCollectionTest.java
index 9ea6efc..76f75f2 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/AbstractCollectionTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/AbstractCollectionTest.java
@@ -285,7 +285,7 @@
             }
         };
         try {
-            ac.toArray(null);
+            ac.toArray((Object[]) null);
             fail("No expected NullPointerException");
         } catch (NullPointerException e) {
             // expected
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ArrayDequeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ArrayDequeTest.java
index 0b83223..5049cd1 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ArrayDequeTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ArrayDequeTest.java
@@ -868,7 +868,7 @@
         assertEquals(5, testQue.size());
         assertEquals(testObjOne, testQue.peek());
         try {
-            testQue.toArray(null);
+            testQue.toArray((Object[]) null);
             fail("should throw NullPointerException");
         } catch (NullPointerException e) {
             // expected
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedHashSetTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedHashSetTest.java
index d403b2a..0f275f4 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedHashSetTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedHashSetTest.java
@@ -317,7 +317,7 @@
         }
 
         try {
-            lhs.toArray(null);
+            lhs.toArray((Object[]) null);
             fail("NullPointerException expected");
         } catch (NullPointerException e) {
             //expected
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedListTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedListTest.java
index e045161..59daae4 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedListTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/LinkedListTest.java
@@ -646,7 +646,7 @@
             assertTrue("Lists are not equal", li.next() == ri.next());
 
         try {
-            ll.toArray(null);
+            ll.toArray((Object[]) null);
             fail("NullPointerException expected");
         } catch (NullPointerException e) {
             //expected
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PriorityQueueTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PriorityQueueTest.java
index 7a37a6f..a855ff1 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PriorityQueueTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/PriorityQueueTest.java
@@ -774,7 +774,7 @@
             assertNull(returnArray[i]);
         }
         try {
-            integerQueue.toArray(null);
+            integerQueue.toArray((Object[]) null);
             fail("should throw NullPointerException");
         } catch (NullPointerException e) {
             // expected
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java
index 85899f3..aaefd46 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/ScannerTest.java
@@ -1600,7 +1600,7 @@
         assertEquals((float)23456.7, s.nextFloat());
 
         s = new Scanner("-123.4 123.4- -123.4-");
-        s.useLocale(new Locale("ar", "AE"));
+        s.useLocale(new Locale("ar", "EG"));
         // FIXME
 //        assertEquals((float)-123.4, s.nextFloat());
 //        //The following test case fails on RI
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java
index 3f4ed3b..ab2397b 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarEntryTest.java
@@ -114,6 +114,19 @@
         attrJar.close();
     }
 
+    public void test_getRealName() throws Exception {
+        Support_Resources.copyFile(resources, null, attJarName);
+        File file = new File(resources, attJarName);
+        JarFile attrJar = new JarFile(file);
+
+        jarEntry = attrJar.getJarEntry(attEntryName);
+        assertEquals("HasAttributes.txt", jarEntry.getRealName());
+
+        jarEntry = attrJar.getJarEntry(attEntryName2);
+        assertEquals("NoAttributes.txt", jarEntry.getRealName());
+        attrJar.close();
+    }
+
     // http://b/1864326
     public void testCertificatesAndCodesigners() throws Exception {
         zipEntry = jarFile.getEntry(entryName2);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/DocumentBuilderFactoryTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/DocumentBuilderFactoryTest.java
index 0cbb138..970c505 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/DocumentBuilderFactoryTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/DocumentBuilderFactoryTest.java
@@ -23,17 +23,27 @@
 import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
 
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.io.IOException;
+import java.net.URL;
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
+import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.FactoryConfigurationError;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.SchemaFactoryLoader;
 
 public class DocumentBuilderFactoryTest extends TestCase {
 
@@ -688,18 +698,65 @@
     /**
      * javax.xml.parsers.DocumentBuilderFactory#setSchema(javax.xml.validation.Schema).
      */
- /*   public void test_setSchemaLjavax_xml_validation_Schema() {
-        SchemaFactory sf =
-            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+    public void test_setSchemaLjavax_xml_validation_Schema()
+        throws MalformedURLException, SAXException, SAXNotSupportedException {
+        String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;
+        String propName = SchemaFactory.class.getName() + ":" + language;
+        String className =
+            "org.apache.harmony.tests.javax.xml.parsers.MockSchemaFactory";
+
+        // Test `SchemaFactory.newInstance` methods. Set system property for
+        // schema language to make `newInstance` use the mock implementation of
+        // `SchemaFactory`.
+        System.setProperty(propName, className);
+        SchemaFactory f1 = SchemaFactory.newInstance(language);
+        SchemaFactory f2 = SchemaFactory.newInstance(language, className, null);
+
+        // Test `SchemaFactory.newSchema` method for `File`, `URL` and `Source`.
         try {
-            Schema schema = sf.newSchema();
-            dbf.setSchema(schema);
+            Schema s = f1.newSchema();
+            s = f1.newSchema(new File("test.dtd"));
+            s = f1.newSchema(new URL("https://test.org"));
+            s = f1.newSchema(new StreamSource());
+            dbf.setSchema(s);
             assertNotNull(dbf.getSchema());
-        } catch (SAXException sax) {
-            fail("Unexpected exception " + sax.toString());
+        } catch (UnsupportedOperationException e) {
+            // Expected.
+        }
+
+        // Test `newFactory` method for the mock `SchemaFactoryLoader`.
+        SchemaFactoryLoader loader = new MockSchemaFactoryLoader();
+        assertNull(loader.newFactory(language));
+
+        // Test `getFeature` (the mock implementation always throws).
+        try {
+            f2.getFeature("woot");
+        } catch (SAXNotRecognizedException e) {
+            // Expected.
+        }
+
+        // Test `setFeature` (the mock implementation always throws).
+        try {
+            f2.setFeature("woot", true);
+        } catch (SAXNotRecognizedException e) {
+            // Expected.
+        }
+
+        // Test `getProperty` (the mock implementation always throws).
+        try {
+            f2.getProperty("woot");
+        } catch (SAXNotRecognizedException e) {
+            // Expected.
+        }
+
+        // Test `setProperty` (the mock implementation always throws).
+        try {
+            f2.setProperty("woot", null);
+        } catch (SAXNotRecognizedException e) {
+            // Expected.
         }
     }
-*/
+
     /**
      * javax.xml.parsers.DocumentBuilderFactory#setValidating(boolean).
      */
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/MockSchemaFactory.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/MockSchemaFactory.java
new file mode 100644
index 0000000..1f3ca5b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/MockSchemaFactory.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 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.tests.javax.xml.parsers;
+
+import org.w3c.dom.ls.LSResourceResolver;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+import javax.xml.transform.Source;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.SchemaFactoryLoader;
+
+public final class MockSchemaFactory extends SchemaFactory {
+    @Override
+    public Schema newSchema() throws SAXException {
+        return null;
+    }
+
+    @Override
+    public Schema newSchema(Source[] schemas) throws SAXException {
+        return null;
+    }
+
+    @Override
+    public LSResourceResolver getResourceResolver() {
+        return null;
+    }
+
+    @Override
+    public void setResourceResolver(LSResourceResolver resourceResolver) {
+    }
+
+    @Override
+    public ErrorHandler getErrorHandler() {
+        return null;
+    }
+
+    @Override
+    public void setErrorHandler(ErrorHandler errorHandler) {
+    }
+
+    @Override
+    public boolean isSchemaLanguageSupported(String schemaLanguage) {
+        return true;
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/MockSchemaFactoryLoader.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/MockSchemaFactoryLoader.java
new file mode 100644
index 0000000..d49e499
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/xml/parsers/MockSchemaFactoryLoader.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 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.tests.javax.xml.parsers;
+
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.SchemaFactoryLoader;
+
+public final class MockSchemaFactoryLoader extends SchemaFactoryLoader {
+    @Override
+    public SchemaFactory newFactory(String schemaLanguage) {
+        return null;
+    };
+}
\ No newline at end of file
diff --git a/json/src/main/java/org/json/JSONObject.java b/json/src/main/java/org/json/JSONObject.java
index c7a881d..1d9b77a 100644
--- a/json/src/main/java/org/json/JSONObject.java
+++ b/json/src/main/java/org/json/JSONObject.java
@@ -296,7 +296,7 @@
      * mapped to {@code name}. In aggregate, this allows values to be added to a
      * mapping one at a time.
      *
-     * <p> Note that {@code append(String, Object)} provides better semantics.
+     * <p> Note that {@link #append(String, Object)} provides better semantics.
      * In particular, the mapping for {@code name} will <b>always</b> be a
      * {@link JSONArray}. Using {@code accumulate} will result in either a
      * {@link JSONArray} or a mapping whose type is the type of {@code value}
@@ -306,8 +306,6 @@
      *     Integer, Long, Double, {@link #NULL} or null. May not be {@link
      *     Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
      */
-    // TODO: Change {@code append) to {@link #append} when append is
-    // unhidden.
     @NonNull public JSONObject accumulate(@NonNull String name, @Nullable Object value) throws JSONException {
         Object current = nameValuePairs.get(checkName(name));
         if (current == null) {
@@ -334,11 +332,8 @@
      *
      * @throws JSONException if {@code name} is {@code null} or if the mapping for
      *         {@code name} is non-null and is not a {@link JSONArray}.
-     *
-     * @hide
      */
-    @UnsupportedAppUsage
-    public JSONObject append(String name, Object value) throws JSONException {
+    @NonNull public JSONObject append(@NonNull String name, @Nullable Object value) throws JSONException {
         Object current = nameValuePairs.get(checkName(name));
 
         final JSONArray array;
@@ -683,7 +678,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @NonNull public Set<@NonNull String> keySet() {
         return nameValuePairs.keySet();
     }
diff --git a/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java b/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java
index 23cc6b9..982001f 100644
--- a/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ArrayDequeTest.java
@@ -722,7 +722,7 @@
         ArrayDeque l = new ArrayDeque();
         l.add(new Object());
         try {
-            l.toArray(null);
+            l.toArray((Object[]) null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java b/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java
index 1a188e1..0da4e78 100644
--- a/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/BlockingQueueTest.java
@@ -138,7 +138,7 @@
     public void testToArray_NullArray() {
         final Collection q = emptyCollection();
         try {
-            q.toArray(null);
+            q.toArray((Object[]) null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/jsr166-tests/src/test/java/jsr166/CompletableFutureTest.java b/jsr166-tests/src/test/java/jsr166/CompletableFutureTest.java
index 28517aa..53e0398 100644
--- a/jsr166-tests/src/test/java/jsr166/CompletableFutureTest.java
+++ b/jsr166-tests/src/test/java/jsr166/CompletableFutureTest.java
@@ -147,7 +147,7 @@
         assertFalse(f.isCancelled());
         assertTrue(f.isDone());
         assertTrue(f.isCompletedExceptionally());
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
+        assertTrue(f.toString().contains("[Completed exceptionally:"));
     }
 
     void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
@@ -202,7 +202,7 @@
         assertTrue(f.isDone());
         assertTrue(f.isCompletedExceptionally());
         assertTrue(f.isCancelled());
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
+        assertTrue(f.toString().contains("[Completed exceptionally:"));
     }
 
     /**
@@ -349,12 +349,12 @@
 
         f = new CompletableFuture<String>();
         assertTrue(f.completeExceptionally(new IndexOutOfBoundsException()));
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
+        assertTrue(f.toString().contains("[Completed exceptionally:"));
 
         for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
             f = new CompletableFuture<String>();
             assertTrue(f.cancel(mayInterruptIfRunning));
-            assertTrue(f.toString().contains("[Completed exceptionally]"));
+            assertTrue(f.toString().contains("[Completed exceptionally:"));
         }
     }
 
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java
index 6625e7e..767d4a0 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedDequeTest.java
@@ -677,7 +677,7 @@
     public void testToArray_NullArg() {
         ConcurrentLinkedDeque q = populatedDeque(SIZE);
         try {
-            q.toArray(null);
+            q.toArray((Object[]) null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java
index 70519a4..ea90a8f 100644
--- a/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/ConcurrentLinkedQueueTest.java
@@ -408,7 +408,7 @@
     public void testToArray_NullArg() {
         ConcurrentLinkedQueue q = populatedQueue(SIZE);
         try {
-            q.toArray(null);
+            q.toArray((Object[]) null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/jsr166-tests/src/test/java/jsr166/LinkedListTest.java b/jsr166-tests/src/test/java/jsr166/LinkedListTest.java
index 9c971b4..5c5f798 100644
--- a/jsr166-tests/src/test/java/jsr166/LinkedListTest.java
+++ b/jsr166-tests/src/test/java/jsr166/LinkedListTest.java
@@ -363,7 +363,7 @@
         LinkedList l = new LinkedList();
         l.add(new Object());
         try {
-            l.toArray(null);
+            l.toArray((Object[]) null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/jsr166-tests/src/test/java/jsr166/StampedLockTest.java b/jsr166-tests/src/test/java/jsr166/StampedLockTest.java
index d347c7d..fa58fbd 100644
--- a/jsr166-tests/src/test/java/jsr166/StampedLockTest.java
+++ b/jsr166-tests/src/test/java/jsr166/StampedLockTest.java
@@ -606,7 +606,7 @@
             }});
 
         running.await();
-        waitForThreadToEnterWaitState(t, 100);
+        waitForThreadToEnterWaitState(t, 2000);
         t.interrupt();
         awaitTermination(t);
         releaseWriteLock(lock, s);
diff --git a/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java b/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java
index 9d3f212..77e6b8e 100644
--- a/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java
+++ b/jsr166-tests/src/test/java/jsr166/SynchronousQueueTest.java
@@ -431,7 +431,7 @@
     public void testToArray_null(boolean fair) {
         final SynchronousQueue q = new SynchronousQueue(fair);
         try {
-            Object[] o = q.toArray(null);
+            Object[] o = q.toArray((Object[]) null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/libart/src/main/java/dalvik/system/AnnotatedStackTraceElement.java b/libart/src/main/java/dalvik/system/AnnotatedStackTraceElement.java
index cce747d..1936822 100644
--- a/libart/src/main/java/dalvik/system/AnnotatedStackTraceElement.java
+++ b/libart/src/main/java/dalvik/system/AnnotatedStackTraceElement.java
@@ -30,7 +30,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class AnnotatedStackTraceElement {
     /**
      * The traditional StackTraceElement describing the Java stack frame.
@@ -61,7 +60,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @NonNull public StackTraceElement getStackTraceElement() {
         return stackTraceElement;
     }
@@ -75,7 +73,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @Nullable public Object[] getHeldLocks() {
         return heldLocks;
     }
@@ -90,7 +87,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @Nullable public Object getBlockedOn() {
         return blockedOn;
     }
diff --git a/libart/src/main/java/dalvik/system/ClassExt.java b/libart/src/main/java/dalvik/system/ClassExt.java
index e523035..7acc3f3 100644
--- a/libart/src/main/java/dalvik/system/ClassExt.java
+++ b/libart/src/main/java/dalvik/system/ClassExt.java
@@ -27,6 +27,13 @@
  */
 public final class ClassExt {
     /**
+     * If the class is in an erroneous state, we must return the same error on subsequent tries.
+     *
+     * This field is a logical part of the 'Class' type.
+     */
+    private Throwable erroneousStateError;
+
+    /**
      * A Pointer-sized-array of instance jfieldIDs in the same order as the ifields_ array.
      * The jfieldID is associated with the ArtField at the corresonding index in the ifields_ array.
      */
@@ -91,14 +98,6 @@
     private Object staticJfieldIDs;
 
     /**
-     * If class verify fails, we must return same error on subsequent tries. We may store either
-     * the class of the error, or an actual instance of Throwable here.
-     *
-     * This field is a logical part of the 'Class' type.
-     */
-    private Object verifyError;
-
-    /**
      * If set, native pointer to the initial, pre-redefine, dex file associated with the related
      * class. This is different from the {@code originalDexFile} which is the pre-retransform dex
      * file, i.e. could contain the bytes of the dex file provided during redefine.
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 2b5d8cd..8d180fd 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -27,8 +27,6 @@
 import dalvik.annotation.compat.VersionCodes;
 import dalvik.annotation.optimization.FastNative;
 
-import libcore.api.CorePlatformApi;
-
 import java.lang.ref.FinalizerReference;
 import java.util.HashMap;
 import java.util.Map;
@@ -43,7 +41,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 public final class VMRuntime {
 
@@ -108,7 +105,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public interface HiddenApiUsageLogger {
 
         // The following ACCESS_METHOD_ constants must match the values in
@@ -120,7 +116,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         public static final int ACCESS_METHOD_NONE = 0;
 
         /**
@@ -129,7 +124,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         public static final int ACCESS_METHOD_REFLECTION = 1;
 
         /**
@@ -138,7 +132,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         public static final int ACCESS_METHOD_JNI = 2;
 
         /**
@@ -148,7 +141,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         public static final int ACCESS_METHOD_LINKING = 3;
 
         /**
@@ -168,7 +160,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
         public void hiddenApiUsed(int sampledValue, String appPackageName,
             String signature, int accessType, boolean accessDenied);
     }
@@ -186,7 +177,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setHiddenApiUsageLogger(HiddenApiUsageLogger hiddenApiUsageLogger) {
         VMRuntime.hiddenApiUsageLogger = hiddenApiUsageLogger;
     }
@@ -211,7 +201,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     // Must match android.os.Build.VERSION_CODES.CUR_DEVELOPMENT.
     public static final int SDK_VERSION_CUR_DEVELOPMENT = 10000;
 
@@ -242,7 +231,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public static VMRuntime getRuntime() {
         return THE_ONE;
@@ -286,7 +274,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native String vmLibrary();
 
     /**
@@ -298,7 +285,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native String vmInstructionSet();
 
     /**
@@ -310,7 +296,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @FastNative
     public native boolean is64Bit();
 
@@ -323,7 +308,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public native boolean isCheckJniEnabled();
 
@@ -394,7 +378,6 @@
     @UnsupportedAppUsage(maxTargetSdk=0, publicAlternatives="Use the {@code targetSdkVersion}"
         +" attribute in the {@code uses-sdk} manifest tag instead.")
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public synchronized void setTargetSdkVersion(int targetSdkVersion) {
         this.targetSdkVersion = targetSdkVersion;
         setTargetSdkVersionNative(this.targetSdkVersion);
@@ -411,7 +394,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public synchronized void setDisabledCompatChanges(long[] disabledCompatChanges) {
         this.disabledCompatChanges = disabledCompatChanges;
         setDisabledCompatChangesNative(this.disabledCompatChanges);
@@ -426,7 +408,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public synchronized int getTargetSdkVersion() {
         return targetSdkVersion;
     }
@@ -533,7 +514,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void setHiddenApiExemptions(String[] signaturePrefixes);
 
     /**
@@ -545,7 +525,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void setHiddenApiAccessLogSamplingRate(int rate);
 
     /**
@@ -561,7 +540,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     @FastNative
     public native Object newNonMovableArray(Class<?> componentType, int length);
@@ -579,7 +557,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public native Object newUnpaddedArray(Class<?> componentType, int minLength);
 
@@ -587,14 +564,14 @@
      * Returns the address of {@code array[0]}. This differs from using JNI in that JNI
      * might lie and give you the address of a copy of the array when in forcecopy mode.
      *
-     * @param array the object we want the native address of.
+     * @param array the object we want the native address of. Must be a non-movable
+     * primitive array.
      * @return native address of {@code array[0]}.
      *
      * @hide
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     @FastNative
     public native long addressOf(Object array);
@@ -607,7 +584,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void clearGrowthLimit();
 
     /**
@@ -617,7 +593,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void clampGrowthLimit();
 
     /**
@@ -628,7 +603,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @FastNative
     public native boolean isNativeDebuggable();
 
@@ -655,7 +629,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void registerNativeAllocation(long bytes);
 
     /**
@@ -670,7 +643,6 @@
     @UnsupportedAppUsage
     @Deprecated
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void registerNativeAllocation(int bytes) {
         registerNativeAllocation((long) bytes);
     }
@@ -684,7 +656,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void registerNativeFree(long bytes);
 
     /**
@@ -698,7 +669,6 @@
     @UnsupportedAppUsage
     @Deprecated
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void registerNativeFree(int bytes) {
         registerNativeFree((long) bytes);
     }
@@ -774,7 +744,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void requestConcurrentGC();
 
     /**
@@ -816,7 +785,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void updateProcessState(int state);
 
     /**
@@ -826,7 +794,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void notifyStartupCompleted();
 
     /**
@@ -836,7 +803,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public native void preloadDexCaches();
 
     /**
@@ -847,7 +813,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int CODE_PATH_TYPE_PRIMARY_APK = 1 << 0;
     /**
      * Flag denoting that the code paths passed to
@@ -857,7 +822,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int CODE_PATH_TYPE_SPLIT_APK = 1 << 1;
     /**
      * Flag denoting that the code paths passed to
@@ -867,7 +831,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int CODE_PATH_TYPE_SECONDARY_DEX = 1 << 2;
 
     /**
@@ -888,7 +851,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void registerAppInfo(
             String packageName,
             String currentProfileFile,
@@ -909,7 +871,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static String getInstructionSet(String abi) {
         final String instructionSet = ABI_TO_INSTRUCTION_SET_MAP.get(abi);
         if (instructionSet == null) {
@@ -929,7 +890,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean is64BitInstructionSet(String instructionSet) {
         return "arm64".equals(instructionSet) ||
                 "x86_64".equals(instructionSet) ||
@@ -947,7 +907,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean is64BitAbi(String abi) {
         return is64BitInstructionSet(getInstructionSet(abi));
     }
@@ -967,7 +926,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void bootCompleted();
 
     /**
@@ -978,7 +936,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void resetJitCounters();
 
     /**
@@ -990,7 +947,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native String getCurrentInstructionSet();
 
     /**
@@ -1000,7 +956,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void registerSensitiveThread();
 
     /**
@@ -1019,7 +974,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setNonSdkApiUsageConsumer(Consumer<String> consumer) {
         nonSdkApiUsageConsumer = consumer;
     }
@@ -1033,7 +987,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void setDedupeHiddenApiWarnings(boolean dedupe);
 
     /**
@@ -1044,7 +997,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void setProcessPackageName(String packageName);
 
     /**
@@ -1055,7 +1007,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void setProcessDataDirectory(String dataDir);
 
     /**
@@ -1071,6 +1022,5 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native boolean isValidClassLoaderContext(String encodedClassLoaderContext);
 }
diff --git a/libart/src/main/java/dalvik/system/VMStack.java b/libart/src/main/java/dalvik/system/VMStack.java
index 9a84f0f..04872bd 100644
--- a/libart/src/main/java/dalvik/system/VMStack.java
+++ b/libart/src/main/java/dalvik/system/VMStack.java
@@ -31,7 +31,6 @@
  *
  * @hide
  */
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @SystemApi(client = MODULE_LIBRARIES)
 public final class VMStack {
 
@@ -111,7 +110,6 @@
      *
      * @hide
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     @FastNative
     native public static @Nullable AnnotatedStackTraceElement[]
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java
index 6e05cea..5b2adb3 100644
--- a/libart/src/main/java/java/lang/Daemons.java
+++ b/libart/src/main/java/java/lang/Daemons.java
@@ -136,7 +136,14 @@
             } else {
                 PRE_ZYGOTE_START_LATCH.countDown();
             }
-            runInternal();
+            try {
+                runInternal();
+            } catch (Throwable ex) {
+                // Should never happen, but may not o.w. get reported, e.g. in zygote.
+                // Risk logging redundantly, rather than losing it.
+                System.logE("Uncaught exception in system thread " + name, ex);
+                throw ex;
+            }
         }
 
         public abstract void runInternal();
@@ -204,17 +211,29 @@
         @UnsupportedAppUsage
         private static final ReferenceQueueDaemon INSTANCE = new ReferenceQueueDaemon();
 
+        // Monitored by FinalizerWatchdogDaemon to make sure we're still working.
+        private final AtomicInteger progressCounter = new AtomicInteger(0);
+
         ReferenceQueueDaemon() {
             super("ReferenceQueueDaemon");
         }
 
         @Override public void runInternal() {
+            FinalizerWatchdogDaemon.INSTANCE.monitoringNeeded(FinalizerWatchdogDaemon.RQ_DAEMON);
             while (isRunning()) {
                 Reference<?> list;
                 try {
                     synchronized (ReferenceQueue.class) {
-                        while (ReferenceQueue.unenqueued == null) {
-                            ReferenceQueue.class.wait();
+                        if (ReferenceQueue.unenqueued == null) {
+                            progressCounter.incrementAndGet();
+                            FinalizerWatchdogDaemon.INSTANCE.monitoringNotNeeded(
+                                    FinalizerWatchdogDaemon.RQ_DAEMON);
+                            do {
+                               ReferenceQueue.class.wait();
+                            } while (ReferenceQueue.unenqueued == null);
+                            progressCounter.incrementAndGet();
+                            FinalizerWatchdogDaemon.INSTANCE.monitoringNeeded(
+                                    FinalizerWatchdogDaemon.RQ_DAEMON);
                         }
                         list = ReferenceQueue.unenqueued;
                         ReferenceQueue.unenqueued = null;
@@ -224,9 +243,14 @@
                 } catch (OutOfMemoryError e) {
                     continue;
                 }
-                ReferenceQueue.enqueuePending(list);
+                ReferenceQueue.enqueuePending(list, progressCounter);
+                FinalizerWatchdogDaemon.INSTANCE.resetTimeouts();
             }
         }
+
+        ReferenceQueue currentlyProcessing() {
+          return ReferenceQueue.getCurrentQueue();
+        }
     }
 
     private static class FinalizerDaemon extends Daemon {
@@ -257,6 +281,8 @@
             // Local copy of progressCounter; saves a fence per increment on ARM and MIPS.
             int localProgressCounter = progressCounter.get();
 
+            FinalizerWatchdogDaemon.INSTANCE.monitoringNeeded(
+                    FinalizerWatchdogDaemon.FINALIZER_DAEMON);
             while (isRunning()) {
                 try {
                     // Use non-blocking poll to avoid FinalizerWatchdogDaemon communication
@@ -269,11 +295,13 @@
                         finalizingObject = null;
                         progressCounter.lazySet(++localProgressCounter);
                         // Slow path; block.
-                        FinalizerWatchdogDaemon.INSTANCE.goToSleep();
+                        FinalizerWatchdogDaemon.INSTANCE.monitoringNotNeeded(
+                                FinalizerWatchdogDaemon.FINALIZER_DAEMON);
                         finalizingReference = (FinalizerReference<?>)queue.remove();
                         finalizingObject = finalizingReference.get();
                         progressCounter.set(++localProgressCounter);
-                        FinalizerWatchdogDaemon.INSTANCE.wakeUp();
+                        FinalizerWatchdogDaemon.INSTANCE.monitoringNeeded(
+                                FinalizerWatchdogDaemon.FINALIZER_DAEMON);
                     }
                     doFinalize(finalizingReference);
                 } catch (InterruptedException ignored) {
@@ -300,31 +328,47 @@
     }
 
     /**
-     * The watchdog exits the VM if the finalizer ever gets stuck. We consider
-     * the finalizer to be stuck if it spends more than MAX_FINALIZATION_MILLIS
-     * on one instance.
+     * The watchdog exits the VM if either the FinalizerDaemon, or the ReferenceQueueDaemon
+     * gets stuck. We consider the finalizer to be stuck if it spends more than
+     * MAX_FINALIZATION_MILLIS on one instance. We consider ReferenceQueueDaemon to be
+     * potentially stuck if it spends more than MAX_FINALIZATION_MILLIS processing a single
+     * Cleaner or transferring objects into a single queue, but only report if this happens
+     * a few times in a row, to compensate for the fact that multiple Cleaners may be involved.
      */
     private static class FinalizerWatchdogDaemon extends Daemon {
+        // Single bit values to identify daemon to be watched.
+        static final int FINALIZER_DAEMON = 1;
+        static final int RQ_DAEMON = 2;
+
         @UnsupportedAppUsage
         private static final FinalizerWatchdogDaemon INSTANCE = new FinalizerWatchdogDaemon();
 
-        private boolean needToWork = true;  // Only accessed in synchronized methods.
+        private int activeWatchees;  // Only synchronized accesses.
 
         private long finalizerTimeoutNs = 0;  // Lazily initialized.
 
+        // We tolerate this many timeouts during an enqueuePending call.
+        // This number is > 1, since we may only report enqueuePending progress rarely.
+        private static final int TOLERATED_REFERENCE_QUEUE_TIMEOUTS = 5;
+        private static final AtomicInteger observedReferenceQueueTimeouts = new AtomicInteger(0);
+
         FinalizerWatchdogDaemon() {
             super("FinalizerWatchdogDaemon");
         }
 
+        void resetTimeouts() {
+            observedReferenceQueueTimeouts.lazySet(0);
+        }
+
         @Override public void runInternal() {
             while (isRunning()) {
                 if (!sleepUntilNeeded()) {
                     // We have been interrupted, need to see if this daemon has been stopped.
                     continue;
                 }
-                final Object finalizing = waitForFinalization();
-                if (finalizing != null && !VMDebug.isDebuggerConnected()) {
-                    finalizerTimedOut(finalizing);
+                final TimeoutException exception = waitForProgress();
+                if (exception != null && !VMDebug.isDebuggerConnected()) {
+                    timedOut(exception);
                     break;
                 }
             }
@@ -336,7 +380,7 @@
          * See also http://code.google.com/p/android/issues/detail?id=22778.
          */
         private synchronized boolean sleepUntilNeeded() {
-            while (!needToWork) {
+            while (activeWatchees == 0) {
                 try {
                     wait();
                 } catch (InterruptedException e) {
@@ -353,20 +397,24 @@
          * Notify daemon that it's OK to sleep until notified that something is ready to be
          * finalized.
          */
-        private synchronized void goToSleep() {
-            needToWork = false;
+        private synchronized void monitoringNotNeeded(int whichDaemon) {
+            activeWatchees &= ~whichDaemon;
         }
 
         /**
          * Notify daemon that there is something ready to be finalized.
          */
-        private synchronized void wakeUp() {
-            needToWork = true;
-            notify();
+        private synchronized void monitoringNeeded(int whichDaemon) {
+            int oldWatchees = activeWatchees;
+            activeWatchees |= whichDaemon;
+
+            if (oldWatchees == 0) {
+                notify();
+            }
         }
 
-        private synchronized boolean getNeedToWork() {
-            return needToWork;
+        private synchronized boolean isActive(int whichDaemon) {
+            return (activeWatchees & whichDaemon) != 0;
         }
 
         /**
@@ -402,37 +450,52 @@
 
 
         /**
-         * Return an object that took too long to finalize or return null.
+         * Return null (normal case) or an exception describing what timed out.
          * Wait VMRuntime.getFinalizerTimeoutMs.  If the FinalizerDaemon took essentially the
-         * whole time processing a single reference, return that reference.  Otherwise return
-         * null.  Only called from a single thread.
+         * whole time processing a single reference, or the ReferenceQueueDaemon failed to make
+         * visible progress during that time, return an exception.  Only called from a single
+         * thread.
          */
-        private Object waitForFinalization() {
+        private TimeoutException waitForProgress() {
             if (finalizerTimeoutNs == 0) {
                 finalizerTimeoutNs =
                         NANOS_PER_MILLI * VMRuntime.getRuntime().getFinalizerTimeoutMs();
                 // Temporary app backward compatibility. Remove eventually.
                 MAX_FINALIZE_NANOS = finalizerTimeoutNs;
             }
-            long startCount = FinalizerDaemon.INSTANCE.progressCounter.get();
+            boolean monitorFinalizer = false;
+            int finalizerStartCount = 0;
+            if (isActive(FINALIZER_DAEMON)) {
+                monitorFinalizer = true;
+                finalizerStartCount = FinalizerDaemon.INSTANCE.progressCounter.get();
+            }
+            boolean monitorRefQueue = false;
+            int refQueueStartCount = 0;
+            if (isActive(RQ_DAEMON)) {
+                monitorRefQueue = true;
+                refQueueStartCount = ReferenceQueueDaemon.INSTANCE.progressCounter.get();
+            }
+
             // Avoid remembering object being finalized, so as not to keep it alive.
             if (!sleepForNanos(finalizerTimeoutNs)) {
                 // Don't report possibly spurious timeout if we are interrupted.
                 return null;
             }
-            if (getNeedToWork() && FinalizerDaemon.INSTANCE.progressCounter.get() == startCount) {
-                // We assume that only remove() and doFinalize() may take time comparable to
-                // the finalizer timeout.
-                // We observed neither the effect of the gotoSleep() nor the increment preceding a
-                // later wakeUp. Any remove() call by the FinalizerDaemon during our sleep
-                // interval must have been followed by a wakeUp call before we checked needToWork.
-                // But then we would have seen the counter increment.  Thus there cannot have
-                // been such a remove() call.
+            if (FinalizerDaemon.INSTANCE.progressCounter.get() == finalizerStartCount
+                && monitorFinalizer && isActive(FINALIZER_DAEMON)) {
+                // We assume that only remove() and doFinalize() may take time comparable to the
+                // finalizer timeout.
+                // We observed neither the effect of the monitoringNotNeeded() nor the increment
+                // preceding a later wakeUp. Any remove() call by the FinalizerDaemon during our
+                // sleep interval must have been followed by a monitoringNeeded() call before we
+                // checked activeCallees.  But then we would have seen the counter increment.
+                // Thus there cannot have been such a remove() call.
                 // The FinalizerDaemon must not have progressed (from either the beginning or the
-                // last progressCounter increment) to either the next increment or gotoSleep()
-                // call.  Thus we must have taken essentially the whole finalizerTimeoutMs in a
-                // single doFinalize() call.  Thus it's OK to time out.  finalizingObject was set
-                // just before the counter increment, which preceded the doFinalize call.  Thus we
+                // last progressCounter increment) to either the next increment or
+                // monitoringNotNeeded() call.
+                // Thus we must have taken essentially the whole finalizerTimeoutMs in a single
+                // doFinalize() call.  Thus it's OK to time out.  finalizingObject was set just
+                // before the counter increment, which preceded the doFinalize() call.  Thus we
                 // are guaranteed to get the correct finalizing value below, unless doFinalize()
                 // just finished as we were timing out, in which case we may get null or a later
                 // one.  In this last case, we are very likely to discard it below.
@@ -440,22 +503,37 @@
                 sleepForNanos(500 * NANOS_PER_MILLI);
                 // Recheck to make it even less likely we report the wrong finalizing object in
                 // the case which a very slow finalization just finished as we were timing out.
-                if (getNeedToWork()
-                        && FinalizerDaemon.INSTANCE.progressCounter.get() == startCount) {
-                    return finalizing;
+                if (isActive(FINALIZER_DAEMON)
+                        && FinalizerDaemon.INSTANCE.progressCounter.get() == finalizerStartCount) {
+                    return finalizerTimeoutException(finalizing);
+                }
+            }
+            if (ReferenceQueueDaemon.INSTANCE.progressCounter.get() == refQueueStartCount
+                && monitorRefQueue && isActive(RQ_DAEMON)) {
+                if (observedReferenceQueueTimeouts.incrementAndGet()
+                        > TOLERATED_REFERENCE_QUEUE_TIMEOUTS) {
+                    return refQueueTimeoutException(
+                            ReferenceQueueDaemon.INSTANCE.currentlyProcessing());
                 }
             }
             return null;
         }
 
-        private static void finalizerTimedOut(Object object) {
-            // The current object has exceeded the finalization deadline; abort!
+        private static TimeoutException finalizerTimeoutException(Object object) {
             String message = object.getClass().getName() + ".finalize() timed out after "
                     + VMRuntime.getRuntime().getFinalizerTimeoutMs() / 1000 + " seconds";
-            Exception syntheticException = new TimeoutException(message);
+            TimeoutException syntheticException = new TimeoutException(message);
             // We use the stack from where finalize() was running to show where it was stuck.
             syntheticException.setStackTrace(FinalizerDaemon.INSTANCE.getStackTrace());
+            return syntheticException;
+        }
 
+        private static TimeoutException refQueueTimeoutException(ReferenceQueue rq) {
+            String message = "ReferenceQueueDaemon timed out while targeting " + rq;
+            return new TimeoutException(message);
+        }
+
+        private static void timedOut(TimeoutException exception) {
             // Send SIGQUIT to get native stack traces.
             try {
                 Os.kill(Os.getpid(), OsConstants.SIGQUIT);
@@ -472,7 +550,7 @@
             // handler to dispatch to, either via a handler set on itself, via its ThreadGroup
             // object or via the defaultUncaughtExceptionHandler.
             //
-            // As an approximation, we log by hand an exit if there's no pre-exception handler nor
+            // As an approximation, we log by hand and exit if there's no pre-exception handler nor
             // a default uncaught exception handler.
             //
             // Note that this condition will only ever be hit by ART host tests and standalone
@@ -481,14 +559,14 @@
             if (Thread.getUncaughtExceptionPreHandler() == null &&
                     Thread.getDefaultUncaughtExceptionHandler() == null) {
                 // If we have no handler, log and exit.
-                System.logE(message, syntheticException);
+                System.logE(exception.getMessage(), exception);
                 System.exit(2);
             }
 
             // Otherwise call the handler to do crash reporting.
             // We don't just throw because we're not the thread that
             // timed out; we're the thread that detected it.
-            Thread.currentThread().dispatchUncaughtException(syntheticException);
+            Thread.currentThread().dispatchUncaughtException(exception);
         }
     }
 
diff --git a/libart/src/main/java/java/lang/invoke/FieldVarHandle.java b/libart/src/main/java/java/lang/invoke/FieldVarHandle.java
index 0921040..beb056a 100644
--- a/libart/src/main/java/java/lang/invoke/FieldVarHandle.java
+++ b/libart/src/main/java/java/lang/invoke/FieldVarHandle.java
@@ -20,27 +20,24 @@
 import java.lang.reflect.Modifier;
 
 /**
- * A VarHandle that's associated with an ArtField.
+ * A VarHandle that's associated with an instance field.
  * @hide
  */
-final class FieldVarHandle extends VarHandle {
+class FieldVarHandle extends VarHandle {
     private final long artField;
 
-    private FieldVarHandle(Field field, Class<?> declaringClass) {
-        super(field.getType(), Modifier.isFinal(field.getModifiers()), declaringClass);
+    private FieldVarHandle(Field field, Class<?> coordinateType0) {
+        super(field.getType(), Modifier.isFinal(field.getModifiers()), coordinateType0);
         artField = field.getArtField();
     }
 
-    private FieldVarHandle(Field field) {
+    protected FieldVarHandle(Field field) {
         super(field.getType(), Modifier.isFinal(field.getModifiers()));
         artField = field.getArtField();
     }
 
     static FieldVarHandle create(Field field) {
-        if (Modifier.isStatic(field.getModifiers())) {
-            return new FieldVarHandle(field);
-        } else {
-            return new FieldVarHandle(field, field.getDeclaringClass());
-        }
+        assert !Modifier.isStatic(field.getModifiers());
+        return new FieldVarHandle(field, field.getDeclaringClass());
     }
 }
diff --git a/libart/src/main/java/java/lang/invoke/StaticFieldVarHandle.java b/libart/src/main/java/java/lang/invoke/StaticFieldVarHandle.java
new file mode 100644
index 0000000..e5faeb7
--- /dev/null
+++ b/libart/src/main/java/java/lang/invoke/StaticFieldVarHandle.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.invoke;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * A VarHandle that's associated with a static field.
+ * @hide
+ */
+final class StaticFieldVarHandle extends FieldVarHandle {
+    private final Class declaringClass;
+
+    private StaticFieldVarHandle(Field staticField) {
+        super(staticField);
+        declaringClass = staticField.getDeclaringClass();
+    }
+
+    static StaticFieldVarHandle create(Field staticField) {
+        assert Modifier.isStatic(staticField.getModifiers());
+        return new StaticFieldVarHandle(staticField);
+    }
+}
diff --git a/libart/src/main/java/java/lang/invoke/TEST_MAPPING b/libart/src/main/java/java/lang/invoke/TEST_MAPPING
index 2b6135d..a5e285b 100644
--- a/libart/src/main/java/java/lang/invoke/TEST_MAPPING
+++ b/libart/src/main/java/java/lang/invoke/TEST_MAPPING
@@ -13,8 +13,11 @@
       "options": [
         {
           "include-filter": "org.openjdk.tests.java.lang.invoke"
+        },
+        {
+          "include-filter": "test.java.lang.invoke"
         }
       ]
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/lint-baseline.xml b/lint-baseline.xml
new file mode 100644
index 0000000..440e203
--- /dev/null
+++ b/lint-baseline.xml
@@ -0,0 +1,627 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 7.2.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.2.0-dev">
+<!-- generated by libcore/tools/update-lint-baseline/update-lint-baseline.sh -->
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="final class ArrayElementVarHandle extends VarHandle {"
+        errorLine2="                                          ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/ArrayElementVarHandle.java"
+            line="26"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="        new BigDecimal(BigInteger.TWO,        2,  0, 1),"
+        errorLine2="                       ~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigDecimal.java"
+            line="296"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                rb = BigInteger.TWO.pow(exponent).multiply(compactVal);"
+        errorLine2="                     ~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigDecimal.java"
+            line="956"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="            return TWO;"
+        errorLine2="                   ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="865"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                        result = result.add(TWO);"
+        errorLine2="                                            ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="883"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                result = result.add(TWO);"
+        errorLine2="                                    ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="896"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                z = z.modPow(TWO, this);"
+        errorLine2="                             ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="1113"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="        if (w.equals(TWO))"
+        errorLine2="                     ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="3846"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="final class ByteArrayViewVarHandle extends VarHandle {"
+        errorLine2="                                           ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/ByteArrayViewVarHandle.java"
+            line="25"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="final class ByteBufferViewVarHandle extends VarHandle {"
+        errorLine2="                                            ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/ByteBufferViewVarHandle.java"
+            line="26"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.ref.Cleaner.Cleanable`"
+        errorLine1="                Cleanable ref = (Cleanable) queue.remove(60 * 1000L);"
+        errorLine2="                                 ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/jdk/internal/ref/CleanerImpl.java"
+            line="152"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/DatagramSocketImpl.java"
+            line="288"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/DatagramSocketImpl.java"
+            line="333"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.security.spec.NamedParameterSpec`"
+        errorLine1="public class ECGenParameterSpec extends NamedParameterSpec implements AlgorithmParameterSpec {"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java"
+            line="38"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.security.interfaces.EdECKey`"
+        errorLine1="public interface EdECPrivateKey extends EdECKey, PrivateKey {"
+        errorLine2="                                        ~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java"
+            line="44"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.security.interfaces.EdECKey`"
+        errorLine1="public interface EdECPublicKey extends EdECKey, PublicKey {"
+        errorLine2="                                       ~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java"
+            line="42"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="class FieldVarHandle extends VarHandle {"
+        errorLine2="                             ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/FieldVarHandle.java"
+            line="26"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="                                || VarHandle.class.isAssignableFrom(declaringClass))) {"
+        errorLine2="                                   ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java"
+            line="165"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="            } else if (refc == VarHandle.class) {"
+        errorLine2="                               ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java"
+            line="955"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="        Class&lt;?> refc = VarHandle.class;"
+        errorLine2="                        ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java"
+            line="2580"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="        MethodType methodType = type.insertParameterTypes(0, VarHandle.class);"
+        errorLine2="                                                             ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java"
+            line="2587"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.lang.ref.Cleaner.Cleanable`"
+        errorLine1="        implements Cleaner.Cleanable {"
+        errorLine2="                   ~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/jdk/internal/ref/PhantomCleanable.java"
+            line="44"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/SocketImpl.java"
+            line="400"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 33 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/SocketImpl.java"
+            line="443"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.security.cert.URICertStoreParameters`"
+        errorLine1="        if (p == null || (!(p instanceof URICertStoreParameters))) {"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/cert/URICertStoreParameters.java"
+            line="127"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.security.cert.URICertStoreParameters`"
+        errorLine1="        URICertStoreParameters other = (URICertStoreParameters)p;"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/cert/URICertStoreParameters.java"
+            line="135"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.security.interfaces.XECKey`"
+        errorLine1="public interface XECPrivateKey extends XECKey, PrivateKey {"
+        errorLine2="                                       ~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/XECPrivateKey.java"
+            line="45"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 33 (current min is 31): `java.security.interfaces.XECKey`"
+        errorLine1="public interface XECPublicKey extends XECKey, PublicKey {"
+        errorLine2="                                      ~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/XECPublicKey.java"
+            line="45"
+            column="39"/>
+    </issue>
+
+    <!-- TODO(b/205570605): The following repeats all the issues above, but with
+         required API level 32 instead of 33 in the messages. This happens in
+         unbundled Mainline builds, e.g.
+         m TARGET_PRODUCT=mainline_modules_arm TARGET_BUILD_APPS=com.android.art TARGET_BUILD_UNBUNDLED=true lint-check
+    -->
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="final class ArrayElementVarHandle extends VarHandle {"
+        errorLine2="                                          ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/ArrayElementVarHandle.java"
+            line="26"
+            column="43"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="        new BigDecimal(BigInteger.TWO,        2,  0, 1),"
+        errorLine2="                       ~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigDecimal.java"
+            line="296"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                rb = BigInteger.TWO.pow(exponent).multiply(compactVal);"
+        errorLine2="                     ~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigDecimal.java"
+            line="956"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="            return TWO;"
+        errorLine2="                   ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="865"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                        result = result.add(TWO);"
+        errorLine2="                                            ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="883"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                result = result.add(TWO);"
+        errorLine2="                                    ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="896"
+            column="37"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="                z = z.modPow(TWO, this);"
+        errorLine2="                             ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="1113"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.math.BigInteger#TWO`"
+        errorLine1="        if (w.equals(TWO))"
+        errorLine2="                     ~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/math/BigInteger.java"
+            line="3846"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="final class ByteArrayViewVarHandle extends VarHandle {"
+        errorLine2="                                           ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/ByteArrayViewVarHandle.java"
+            line="25"
+            column="44"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="final class ByteBufferViewVarHandle extends VarHandle {"
+        errorLine2="                                            ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/ByteBufferViewVarHandle.java"
+            line="26"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.ref.Cleaner.Cleanable`"
+        errorLine1="                Cleanable ref = (Cleanable) queue.remove(60 * 1000L);"
+        errorLine2="                                 ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/jdk/internal/ref/CleanerImpl.java"
+            line="152"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/DatagramSocketImpl.java"
+            line="288"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/DatagramSocketImpl.java"
+            line="333"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.security.spec.NamedParameterSpec`"
+        errorLine1="public class ECGenParameterSpec extends NamedParameterSpec implements AlgorithmParameterSpec {"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java"
+            line="38"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.security.interfaces.EdECKey`"
+        errorLine1="public interface EdECPrivateKey extends EdECKey, PrivateKey {"
+        errorLine2="                                        ~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java"
+            line="44"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.security.interfaces.EdECKey`"
+        errorLine1="public interface EdECPublicKey extends EdECKey, PublicKey {"
+        errorLine2="                                       ~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java"
+            line="42"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="class FieldVarHandle extends VarHandle {"
+        errorLine2="                             ~~~~~~~~~">
+        <location
+            file="libcore/libart/src/main/java/java/lang/invoke/FieldVarHandle.java"
+            line="26"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="                                || VarHandle.class.isAssignableFrom(declaringClass))) {"
+        errorLine2="                                   ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java"
+            line="165"
+            column="36"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="            } else if (refc == VarHandle.class) {"
+        errorLine2="                               ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java"
+            line="955"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="        Class&lt;?> refc = VarHandle.class;"
+        errorLine2="                        ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java"
+            line="2580"
+            column="25"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.invoke.VarHandle`"
+        errorLine1="        MethodType methodType = type.insertParameterTypes(0, VarHandle.class);"
+        errorLine2="                                                             ~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/lang/invoke/MethodHandles.java"
+            line="2587"
+            column="62"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.lang.ref.Cleaner.Cleanable`"
+        errorLine1="        implements Cleaner.Cleanable {"
+        errorLine2="                   ~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/jdk/internal/ref/PhantomCleanable.java"
+            line="44"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/SocketImpl.java"
+            line="400"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Field requires API level 32 (current min is 31): `java.net.StandardSocketOptions#SO_REUSEPORT`"
+        errorLine1="        } else if (name == StandardSocketOptions.SO_REUSEPORT &amp;&amp;"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/net/SocketImpl.java"
+            line="443"
+            column="28"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.security.cert.URICertStoreParameters`"
+        errorLine1="        if (p == null || (!(p instanceof URICertStoreParameters))) {"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/cert/URICertStoreParameters.java"
+            line="127"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.security.cert.URICertStoreParameters`"
+        errorLine1="        URICertStoreParameters other = (URICertStoreParameters)p;"
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/cert/URICertStoreParameters.java"
+            line="135"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.security.interfaces.XECKey`"
+        errorLine1="public interface XECPrivateKey extends XECKey, PrivateKey {"
+        errorLine2="                                       ~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/XECPrivateKey.java"
+            line="45"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="Class requires API level 32 (current min is 31): `java.security.interfaces.XECKey`"
+        errorLine1="public interface XECPublicKey extends XECKey, PublicKey {"
+        errorLine2="                                      ~~~~~~">
+        <location
+            file="libcore/ojluni/src/main/java/java/security/interfaces/XECPublicKey.java"
+            line="45"
+            column="39"/>
+    </issue>
+
+</issues>
diff --git a/luni/src/main/java/android/compat/Compatibility.java b/luni/src/main/java/android/compat/Compatibility.java
index 28147dd..c85f76b 100644
--- a/luni/src/main/java/android/compat/Compatibility.java
+++ b/luni/src/main/java/android/compat/Compatibility.java
@@ -21,7 +21,6 @@
 import android.annotation.SystemApi;
 import android.compat.annotation.ChangeId;
 
-import libcore.api.CorePlatformApi;
 import libcore.api.IntraCoreApi;
 
 import java.util.Collections;
@@ -38,7 +37,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@CorePlatformApi(status = CorePlatformApi.Status.STABLE)
 @IntraCoreApi
 public final class Compatibility {
 
@@ -61,7 +59,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @IntraCoreApi
     public static void reportUnconditionalChange(@ChangeId long changeId) {
         sCallbacks.onChangeReported(changeId);
@@ -85,7 +82,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @IntraCoreApi
     public static boolean isChangeEnabled(@ChangeId long changeId) {
         return sCallbacks.isChangeEnabled(changeId);
@@ -103,7 +99,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void setBehaviorChangeDelegate(BehaviorChangeDelegate callbacks) {
         sCallbacks = Objects.requireNonNull(callbacks);
     }
@@ -114,7 +109,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void clearBehaviorChangeDelegate() {
         sCallbacks = DEFAULT_CALLBACKS;
     }
@@ -126,7 +120,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void setOverrides(ChangeConfig overrides) {
         // Setting overrides twice in a row does not need to be supported because
         // this method is only for enabling/disabling changes for the duration of
@@ -145,7 +138,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void clearOverrides() {
         if (!(sCallbacks instanceof OverrideCallbacks)) {
             throw new IllegalStateException("No overrides set");
@@ -158,12 +150,11 @@
      * to logcat.
      *
      * This is provided as a class rather than an interface to allow new methods to be added without
-     * breaking @CorePlatformApi binary compatibility.
+     * breaking @SystemApi binary compatibility.
      *
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public interface BehaviorChangeDelegate {
         /**
          * Called when a change is reported via {@link Compatibility#reportUnconditionalChange}
@@ -171,7 +162,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         default void onChangeReported(long changeId) {
             // Do not use String.format here (b/160912695)
             System.logW("No Compatibility callbacks set! Reporting change " + changeId);
@@ -183,7 +173,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         default boolean isChangeEnabled(long changeId) {
             // Do not use String.format here (b/160912695)
             System.logW("No Compatibility callbacks set! Querying change " + changeId);
@@ -195,7 +184,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @IntraCoreApi
     public static final class ChangeConfig {
         private final Set<Long> enabled;
@@ -205,7 +193,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public ChangeConfig(@NonNull Set<@NonNull Long> enabled, @NonNull Set<@NonNull Long> disabled) {
             this.enabled = Objects.requireNonNull(enabled);
@@ -228,7 +215,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public boolean isEmpty() {
             return enabled.isEmpty() && disabled.isEmpty();
@@ -247,7 +233,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public @NonNull long[] getEnabledChangesArray() {
             return toLongArray(enabled);
@@ -258,7 +243,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public @NonNull long[] getDisabledChangesArray() {
             return toLongArray(disabled);
@@ -269,7 +253,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public @NonNull Set<@NonNull Long> getEnabledSet() {
             return Collections.unmodifiableSet(enabled);
@@ -280,7 +263,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public @NonNull Set<@NonNull Long> getDisabledSet() {
             return Collections.unmodifiableSet(disabled);
@@ -291,7 +273,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public boolean isForceEnabled(long changeId) {
             return enabled.contains(changeId);
@@ -302,7 +283,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         @IntraCoreApi
         public boolean isForceDisabled(long changeId) {
             return disabled.contains(changeId);
diff --git a/luni/src/main/java/android/system/NetlinkSocketAddress.java b/luni/src/main/java/android/system/NetlinkSocketAddress.java
index ecccfa3..27db766 100644
--- a/luni/src/main/java/android/system/NetlinkSocketAddress.java
+++ b/luni/src/main/java/android/system/NetlinkSocketAddress.java
@@ -52,7 +52,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class NetlinkSocketAddress extends SocketAddress {
     /**
      * port ID
@@ -93,7 +92,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public NetlinkSocketAddress(int nlPortId, int nlGroupsMask) {
         this.nlPortId = nlPortId;
         this.nlGroupsMask = nlGroupsMask;
@@ -107,7 +105,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public int getPortId() {
         return nlPortId;
     }
@@ -120,7 +117,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public int getGroupsMask() {
         return nlGroupsMask;
     }
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index 9beb8786..3977eb1 100755
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -85,7 +85,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @Nullable StructCapUserData[] capget(@NonNull StructCapUserHeader hdr) throws ErrnoException {
         return Libcore.os.capget(hdr);
     }
@@ -109,7 +108,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void capset(@NonNull StructCapUserHeader hdr, @NonNull StructCapUserData[] data)
             throws ErrnoException {
         Libcore.os.capset(hdr, data);
@@ -259,7 +257,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int getpgid(int pid) throws ErrnoException { return Libcore.os.getpgid(pid); }
 
     /**
@@ -290,7 +287,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @Nullable StructRlimit getrlimit(int resource) throws ErrnoException { return Libcore.os.getrlimit(resource); }
 
     /**
@@ -322,7 +318,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int getsockoptInt(@NonNull FileDescriptor fd, int level, int option) throws ErrnoException { return Libcore.os.getsockoptInt(fd, level, option); }
 
     /**
@@ -343,7 +338,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @Nullable StructLinger getsockoptLinger(@NonNull FileDescriptor fd, int level, int option) throws ErrnoException { return Libcore.os.getsockoptLinger(fd, level, option); }
 
     /**
@@ -405,7 +399,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int ioctlInt(@NonNull FileDescriptor fd, int cmd) throws ErrnoException {
         return Libcore.os.ioctlInt(fd, cmd);
     }
@@ -526,7 +519,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @Nullable FileDescriptor[] pipe2(int flags) throws ErrnoException { return Libcore.os.pipe2(flags); }
 
     /**
@@ -603,7 +595,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public static @Nullable String realpath(@Nullable String path) throws ErrnoException { return Libcore.os.realpath(path); }
 
@@ -719,7 +710,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setpgid(int pid, int pgid) throws ErrnoException { Libcore.os.setpgid(pid, pgid); }
 
     /**
@@ -736,7 +726,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setregid(int rgid, int egid) throws ErrnoException { Libcore.os.setregid(rgid, egid); }
 
     /**
@@ -753,7 +742,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setreuid(int ruid, int euid) throws ErrnoException { Libcore.os.setreuid(ruid, euid); }
 
     /**
@@ -785,7 +773,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setsockoptIfreq(@NonNull FileDescriptor fd, int level, int option, @Nullable String value) throws ErrnoException { Libcore.os.setsockoptIfreq(fd, level, option, value); }
 
     /**
@@ -813,7 +800,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setsockoptLinger(@NonNull FileDescriptor fd, int level, int option, @NonNull StructLinger value) throws ErrnoException { Libcore.os.setsockoptLinger(fd, level, option, value); }
 
     /**
@@ -910,7 +896,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static long splice(@NonNull FileDescriptor fdIn, @Nullable Int64Ref offIn, @NonNull FileDescriptor fdOut, @Nullable Int64Ref offOut, long len, int flags) throws ErrnoException { return Libcore.os.splice(fdIn, offIn, fdOut, offOut, len, flags); }
 
     /**
@@ -980,7 +965,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void unlink(@Nullable String pathname) throws ErrnoException { Libcore.os.unlink(pathname); }
 
     /**
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index 2c09edb..18fee90 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -40,7 +40,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int CAP_TO_INDEX(int x) { return x >>> 5; }
 
     /**
@@ -55,7 +54,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int CAP_TO_MASK(int x) { return 1 << (x & 31); }
 
     /**
@@ -191,7 +189,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int ARPHRD_LOOPBACK = placeholder();
     public static final int CAP_AUDIT_CONTROL = placeholder();
     public static final int CAP_AUDIT_WRITE = placeholder();
@@ -332,7 +329,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int EUSERS = placeholder();
     // On Linux, EWOULDBLOCK == EAGAIN. Use EAGAIN instead, to reduce confusion.
     public static final int EXDEV = placeholder();
@@ -429,7 +425,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int _LINUX_CAPABILITY_VERSION_3 = placeholder();
     public static final int MAP_FIXED = placeholder();
     public static final int MAP_ANONYMOUS = placeholder();
@@ -442,7 +437,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int MAP_POPULATE = placeholder();
     public static final int MAP_PRIVATE = placeholder();
     public static final int MAP_SHARED = placeholder();
@@ -499,7 +493,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int O_DIRECT = placeholder();
     public static final int O_EXCL = placeholder();
     public static final int O_NOCTTY = placeholder();
@@ -531,7 +524,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int PR_CAP_AMBIENT = placeholder();
     /**
      * The capability specified in {@code arg3} of {@link Os#prctl(int, long, long, long, long)}
@@ -544,7 +536,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int PR_CAP_AMBIENT_RAISE = placeholder();
     public static final int PR_GET_DUMPABLE = placeholder();
     public static final int PR_SET_DUMPABLE = placeholder();
@@ -568,7 +559,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int RLIMIT_NOFILE = placeholder();
     public static final int RT_SCOPE_HOST = placeholder();
     public static final int RT_SCOPE_LINK = placeholder();
@@ -585,7 +575,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int RTMGRP_IPV4_IFADDR = placeholder();
     /** @hide */
     @UnsupportedAppUsage
@@ -734,7 +723,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int SPLICE_F_MOVE = placeholder();
     /** @hide */
     @UnsupportedAppUsage
@@ -752,7 +740,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int SPLICE_F_MORE = placeholder();
     public static final int STDERR_FILENO = placeholder();
     public static final int STDIN_FILENO = placeholder();
@@ -802,7 +789,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int TIOCOUTQ = placeholder();
     /**
      * Sockopt option to encapsulate ESP packets in UDP.
@@ -811,7 +797,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int UDP_ENCAP = placeholder();
     /** @hide */
     @UnsupportedAppUsage
@@ -819,7 +804,6 @@
     /** @hide */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int UDP_ENCAP_ESPINUDP = placeholder();
     /** @hide */
     @UnsupportedAppUsage
@@ -842,7 +826,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int XATTR_CREATE = placeholder();
     /**
      * {@code flags} option for {@link Os#setxattr(String, String, byte[], int)}.
@@ -856,7 +839,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int XATTR_REPLACE = placeholder();
     public static final int X_OK = placeholder();
     public static final int _SC_2_CHAR_TERM = placeholder();
diff --git a/luni/src/main/java/android/system/PacketSocketAddress.java b/luni/src/main/java/android/system/PacketSocketAddress.java
index dca8d06..2d421c3 100644
--- a/luni/src/main/java/android/system/PacketSocketAddress.java
+++ b/luni/src/main/java/android/system/PacketSocketAddress.java
@@ -34,7 +34,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class PacketSocketAddress extends SocketAddress {
     /**
      * Protocol. An Ethernet protocol type, e.g., {@link OsConstants#ETH_P_IPV6}.
@@ -99,7 +98,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public PacketSocketAddress(int sll_protocol, int sll_ifindex, byte[] sll_addr) {
         this.sll_protocol = sll_protocol;
         this.sll_ifindex = sll_ifindex;
diff --git a/luni/src/main/java/android/system/StructCapUserData.java b/luni/src/main/java/android/system/StructCapUserData.java
index a4aa87c..c159140 100644
--- a/luni/src/main/java/android/system/StructCapUserData.java
+++ b/luni/src/main/java/android/system/StructCapUserData.java
@@ -32,7 +32,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class StructCapUserData {
     /**
      * Effective capability mask.
@@ -40,7 +39,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final int effective; /* __u32 */
 
     /**
@@ -49,7 +47,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final int permitted; /* __u32 */
 
     /**
@@ -58,7 +55,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final int inheritable; /* __u32 */
 
     /**
@@ -71,7 +67,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public StructCapUserData(int effective, int permitted, int inheritable) {
         this.effective = effective;
         this.permitted = permitted;
diff --git a/luni/src/main/java/android/system/StructCapUserHeader.java b/luni/src/main/java/android/system/StructCapUserHeader.java
index 249313a..664e244 100644
--- a/luni/src/main/java/android/system/StructCapUserHeader.java
+++ b/luni/src/main/java/android/system/StructCapUserHeader.java
@@ -31,7 +31,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class StructCapUserHeader {
     /**
      * Version of the header. Note this is not final as capget() may mutate the field when an
@@ -61,7 +60,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public StructCapUserHeader(int version, int pid) {
         this.version = version;
         this.pid = pid;
diff --git a/luni/src/main/java/android/system/StructLinger.java b/luni/src/main/java/android/system/StructLinger.java
index 52f4f8e..40fc21f 100644
--- a/luni/src/main/java/android/system/StructLinger.java
+++ b/luni/src/main/java/android/system/StructLinger.java
@@ -41,7 +41,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class StructLinger {
     /**
      * Whether or not linger is enabled. Non-zero is on.
@@ -56,7 +55,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final int l_linger;
 
     /**
@@ -67,8 +65,8 @@
      *
      * @hide
      */
+    @SuppressWarnings("NewApi") // False positive lint limitation, see b/177434707.
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public StructLinger(int l_onoff, int l_linger) {
         this.l_onoff = l_onoff;
         this.l_linger = l_linger;
@@ -81,8 +79,8 @@
      *
      * @hide
      */
+    @SuppressWarnings("NewApi") // False positive lint limitation, see b/177434707.
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public boolean isOn() {
         return l_onoff != 0;
     }
diff --git a/luni/src/main/java/android/system/StructRlimit.java b/luni/src/main/java/android/system/StructRlimit.java
index b35c075..c7620ab 100644
--- a/luni/src/main/java/android/system/StructRlimit.java
+++ b/luni/src/main/java/android/system/StructRlimit.java
@@ -31,7 +31,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class StructRlimit {
 
     /**
@@ -40,7 +39,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public final long rlim_cur;
     /**
      * Hard limit (ceiling for rlim_cur)
diff --git a/luni/src/main/java/android/system/SystemCleaner.java b/luni/src/main/java/android/system/SystemCleaner.java
new file mode 100644
index 0000000..82060af
--- /dev/null
+++ b/luni/src/main/java/android/system/SystemCleaner.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.system;
+
+import java.lang.ref.Cleaner;
+import jdk.internal.ref.CleanerFactory;
+import libcore.util.NonNull;
+
+/**
+ * Java.lang.ref.Cleaner encourages each library to create a Cleaner, with an associated
+ * thread, to process Cleaner Runnables for that library's registered cleaning actions.
+ * This approach isolates cleaning actions from different libraries from each other; a slow cleaning
+ * action in one library will only minimally affect cleaning actions in another.
+ *
+ * However, this comes at the cost of introducing one Cleaner thread per library that uses
+ * Cleaners. This could introduce dozens of additional threads per process, which is often
+ * not an acceptable cost, especially on memory-limited devices.
+ *
+ * SystemCleaner instead provides access to a shared Cleaner, shared across the entire process.
+ * It is greatly preferred when all cleaning actions registered by a client are known to
+ * complete quickly, without explicit I/O, interprocess communication, or network access.
+ * Registering a non-terminating or excessively slow cleaning action with the shared cleaner
+ * may cause the process to perform very badly, hang, or be killed.
+ *
+ * Only for developers of the Android platform itself: As with all Cleaners, use of SystemCleaner
+ * requires an extra thread to be started. This is unsafe for zygote-callable code. Use
+ * NativeAllocationRegistry.
+ */
+public final class SystemCleaner {
+
+    private SystemCleaner() {}
+
+    /**
+     * Return a single Cleaner that's shared across the entire process. Thread-safe.
+     */
+    @NonNull public static Cleaner cleaner() {
+        // We just abuse CleanerFactory. That has the down side that a runaway Cleaner will cause
+        // issues for system libraries. If this eventually becomes a problem due to widespread use,
+        // we can set up another thread here.
+        // TODO: Add some sort of watchdog for this.
+        return CleanerFactory.cleaner();
+    }
+}
+
diff --git a/luni/src/main/java/android/system/UnixSocketAddress.java b/luni/src/main/java/android/system/UnixSocketAddress.java
index 3a7c822..a949e01 100644
--- a/luni/src/main/java/android/system/UnixSocketAddress.java
+++ b/luni/src/main/java/android/system/UnixSocketAddress.java
@@ -34,7 +34,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class UnixSocketAddress extends SocketAddress {
 
     private static final int NAMED_PATH_LENGTH = OsConstants.UNIX_PATH_MAX;
@@ -92,7 +91,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static UnixSocketAddress createFileSystem(String pathName) {
         byte[] pathNameBytes = pathName.getBytes(StandardCharsets.UTF_8);
         // File system sockets have a path that ends with (byte) 0.
diff --git a/luni/src/main/java/android/system/VmSocketAddress.java b/luni/src/main/java/android/system/VmSocketAddress.java
index 1ff85bd..0169f68 100644
--- a/luni/src/main/java/android/system/VmSocketAddress.java
+++ b/luni/src/main/java/android/system/VmSocketAddress.java
@@ -16,13 +16,7 @@
 
 package android.system;
 
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.SystemApi;
-
 import java.net.SocketAddress;
-import libcore.api.CorePlatformApi;
-import libcore.util.Objects;
 
 /**
  * A virtio-vsock address {@link VmSocketAddress}.
@@ -36,13 +30,11 @@
  *
  * <p>
  * Currently virtio-vsock is used as a generic purpose pipe in emulators
- * to talk to the host.
+ * to talk to the host. Most I/O operations using this address via {@link Os} class will require
+ * additional permissions to talk to the host.
  *
  * @see <a href="https://man7.org/linux/man-pages/man7/vsock.7.html">vsock(7)</a>
- * @hide
  */
-@SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = CorePlatformApi.Status.STABLE)
 public final class VmSocketAddress extends SocketAddress {
     /**
       * sockaddr_vm::svmPort, see {@code struct sockaddr_vm} in
@@ -60,14 +52,10 @@
      * Creates a new instance of VmSocketAddress.
      *
      * @param svmPort      The svmPort field value,
-     *                     see {@link OsConstants.VMADDR_PORT_ANY}.
+     *                     see {@link OsConstants#VMADDR_PORT_ANY}.
      * @param svmCid       The svmCid field value,
      *                     see OsConstants.VMADDR_CID_* for VMADDR_CID_* values.
-     *
-     * @hide
      */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public VmSocketAddress(int svmPort, int svmCid) {
         this.svmPort = svmPort;
         this.svmCid = svmCid;
@@ -75,22 +63,14 @@
 
     /**
      * Returns the value of the svmPort field
-     *
-     * @hide
      */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public int getSvmPort() {
         return svmPort;
     }
 
     /**
      * Returns the value of the svmCid field
-     *
-     * @hide
      */
-    @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public int getSvmCid() {
         return svmCid;
     }
diff --git a/luni/src/main/java/java/nio/NIOAccess.java b/luni/src/main/java/java/nio/NIOAccess.java
index 13968fb..4c1b006 100644
--- a/luni/src/main/java/java/nio/NIOAccess.java
+++ b/luni/src/main/java/java/nio/NIOAccess.java
@@ -29,7 +29,6 @@
  */
 // @VisibleForTesting : was default
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class NIOAccess {
 
     private NIOAccess() {}
@@ -61,7 +60,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static Object getBaseArray(Buffer b) {
         return b.hasArray() ? b.array() : null;
     }
@@ -80,7 +78,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int getBaseArrayOffset(Buffer b) {
         return b.hasArray() ? ((b.arrayOffset() + b.position) << b._elementSizeShift) : 0;
     }
diff --git a/luni/src/main/java/java/nio/NioUtils.java b/luni/src/main/java/java/nio/NioUtils.java
index cfac508..c2660b9 100644
--- a/luni/src/main/java/java/nio/NioUtils.java
+++ b/luni/src/main/java/java/nio/NioUtils.java
@@ -36,7 +36,6 @@
  * @hide internal use only
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class NioUtils {
     private NioUtils() {
     }
@@ -50,7 +49,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void freeDirectBuffer(ByteBuffer buffer) {
         if (buffer == null) {
             return;
@@ -98,7 +96,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static byte[] unsafeArray(ByteBuffer b) {
         return b.array();
     }
@@ -114,7 +111,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int unsafeArrayOffset(ByteBuffer b) {
         return b.arrayOffset();
     }
diff --git a/luni/src/main/java/javax/xml/parsers/DocumentBuilder.java b/luni/src/main/java/javax/xml/parsers/DocumentBuilder.java
index 96c191f..3021981 100644
--- a/luni/src/main/java/javax/xml/parsers/DocumentBuilder.java
+++ b/luni/src/main/java/javax/xml/parsers/DocumentBuilder.java
@@ -60,16 +60,16 @@
     }
 
     /**
-      * <p>Reset this <code>DocumentBuilder</code> to its original configuration.</p>
+      * <p>Reset this <code>DocumentBuilder</code>.</p>
       *
-      * <p><code>DocumentBuilder</code> is reset to the same state as when it was created with
-      * {@link DocumentBuilderFactory#newDocumentBuilder()}.
-      * <code>reset()</code> is designed to allow the reuse of existing <code>DocumentBuilder</code>s
-      * thus saving resources associated with the creation of new <code>DocumentBuilder</code>s.</p>
+      * This method removes both the <code>EntityResolver</code> and <code>ErrorHandler</code>
+      * instances associated with this <code>DocumentBuilder</code> and sets all internal
+      * properties to false including those set by the <code>DocumentBuilderFactory</code> when
+      * this <code>DocumentBuilder</code> was created.
       *
-      * <p>The reset <code>DocumentBuilder</code> is not guaranteed to have the same {@link EntityResolver} or {@link ErrorHandler}
-      * <code>Object</code>s, e.g. {@link Object#equals(Object obj)}.  It is guaranteed to have a functionally equal
-      * <code>EntityResolver</code> and <code>ErrorHandler</code>.</p>
+      * @see #setEntityResolver(EntityResolver)
+      * @see #setErrorHandler(ErrorHandler)
+      * @see DocumentBuilderFactory
       *
       * @since 1.5
       */
diff --git a/luni/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java b/luni/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java
index a1982a1..ba3c72a 100644
--- a/luni/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java
+++ b/luni/src/main/java/javax/xml/parsers/DocumentBuilderFactory.java
@@ -307,21 +307,10 @@
      * </p>
      *
      * <p>
-     * All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
-     * When the feature is:</p>
-     * <ul>
-     *   <li>
-     *     <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
-     *     Examples include entity expansion limits and XML Schema constructs that would consume large amounts of resources.
-     *     If XML processing is limited for security reasons, it will be reported via a call to the registered
-     *    {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
-     *     See {@link  DocumentBuilder#setErrorHandler(org.xml.sax.ErrorHandler errorHandler)}.
-     *   </li>
-     *   <li>
-     *     <code>false</code>: the implementation will processing XML according to the XML specifications without
-     *     regard to possible implementation limits.
-     *   </li>
-     * </ul>
+     * Earlier versions of this documentation have mandated support for the
+     * {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature, but this is not a
+     * supported feature on any version of Android.
+     * </p>
      *
      * @param name Feature name.
      * @param value Is feature state <code>true</code> or <code>false</code>.
diff --git a/luni/src/main/java/libcore/content/type/MimeMap.java b/luni/src/main/java/libcore/content/type/MimeMap.java
index fcd08ec..55eff4a 100644
--- a/luni/src/main/java/libcore/content/type/MimeMap.java
+++ b/luni/src/main/java/libcore/content/type/MimeMap.java
@@ -29,7 +29,6 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.function.Supplier;
-import libcore.api.CorePlatformApi;
 import libcore.util.NonNull;
 import libcore.util.Nullable;
 
@@ -39,7 +38,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = CorePlatformApi.Status.STABLE)
 public final class MimeMap {
 
     /**
@@ -52,7 +50,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static @NonNull Builder builder() {
         return new Builder();
     }
@@ -68,7 +65,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public @NonNull Builder buildUpon() {
         return new Builder(mimeToExt, extToMime);
     }
@@ -115,7 +111,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static @NonNull MimeMap getDefault() {
         return Objects.requireNonNull(instanceSupplier.get());
     }
@@ -134,7 +129,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static void setDefaultSupplier(@NonNull Supplier<@NonNull MimeMap> mimeMapSupplier) {
         instanceSupplier = new MemoizingSupplier<>(Objects.requireNonNull(mimeMapSupplier));
     }
@@ -149,7 +143,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public final boolean hasExtension(@Nullable String extension) {
         return guessMimeTypeFromExtension(extension) != null;
     }
@@ -165,7 +158,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public final @Nullable String guessMimeTypeFromExtension(@Nullable String extension) {
         if (extension == null) {
             return null;
@@ -184,7 +176,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public final boolean hasMimeType(@Nullable String mimeType) {
         return guessExtensionFromMimeType(mimeType) != null;
     }
@@ -200,7 +191,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public final @Nullable String guessExtensionFromMimeType(@Nullable String mimeType) {
         if (mimeType == null) {
             return null;
@@ -219,7 +209,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public @NonNull Set<String> mimeTypes() {
         return Collections.unmodifiableSet(mimeToExt.keySet());
     }
@@ -235,7 +224,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public @NonNull Set<String> extensions() {
         return Collections.unmodifiableSet(extToMime.keySet());
     }
@@ -294,7 +282,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public static final class Builder {
         private final Map<String, String> mimeToExt;
         private final Map<String, String> extToMime;
@@ -399,7 +386,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         public @NonNull Builder addMimeMapping(@NonNull String mimeSpec, @NonNull List<@NonNull String> extensionSpecs)
         {
             Element mimeElement = Element.ofMimeSpec(mimeSpec); // validate mimeSpec unconditionally
@@ -433,7 +419,6 @@
          * @hide
          */
         @SystemApi(client = MODULE_LIBRARIES)
-        @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
         public @NonNull MimeMap build() {
             return new MimeMap(mimeToExt, extToMime);
         }
diff --git a/luni/src/main/java/libcore/icu/DecimalFormatData.java b/luni/src/main/java/libcore/icu/DecimalFormatData.java
new file mode 100644
index 0000000..c52f16f
--- /dev/null
+++ b/luni/src/main/java/libcore/icu/DecimalFormatData.java
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+package libcore.icu;
+
+import android.icu.text.DecimalFormat;
+import android.icu.text.DecimalFormatSymbols;
+import android.icu.text.NumberFormat;
+import android.icu.text.NumberingSystem;
+import android.icu.util.ULocale;
+import com.android.icu.text.ExtendedDecimalFormatSymbols;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Data cache for classes, e.g. {@link java.text.DecimalFormat} and
+ * {@link java.text.DecimalFormatSymbols}.
+ *
+ * @hide
+ */
+public class DecimalFormatData {
+
+    // TODO(http://b/217881004): Replace this with a LRU cache.
+    private static final ConcurrentHashMap<String, DecimalFormatData> CACHE =
+            new ConcurrentHashMap<>(/* initialCapacity */ 3);
+
+    private final char zeroDigit;
+    private final char decimalSeparator;
+    private final char groupingSeparator;
+    private final char patternSeparator;
+    private final String percent;
+    private final String perMill;
+    private final char monetarySeparator;
+    private final String minusSign;
+    private final String exponentSeparator;
+    private final String infinity;
+    private final String NaN;
+
+    private final String numberPattern;
+    private final String currencyPattern;
+    private final String percentPattern;
+
+    private DecimalFormatData(Locale locale) {
+        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
+
+        decimalSeparator = dfs.getDecimalSeparator();
+        groupingSeparator = dfs.getGroupingSeparator();
+        percent = dfs.getPercentString();
+        perMill = dfs.getPerMillString();
+        monetarySeparator = dfs.getMonetaryDecimalSeparator();
+        minusSign = dfs.getMinusSignString();
+        exponentSeparator = dfs.getExponentSeparator();
+        infinity = dfs.getInfinity();
+        NaN = dfs.getNaN();
+        zeroDigit = dfs.getZeroDigit();
+
+        // Libcore localizes pattern separator while ICU doesn't. http://b/112080617
+        patternSeparator = loadPatternSeparator(locale);
+
+        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(
+                locale, NumberFormat.NUMBERSTYLE);
+        numberPattern = df.toPattern();
+
+        df = (DecimalFormat) NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
+        currencyPattern = df.toPattern();
+
+        df = (DecimalFormat) NumberFormat.getInstance(locale, NumberFormat.PERCENTSTYLE);
+        percentPattern = df.toPattern();
+    }
+
+    /**
+     * Returns an instance.
+     *
+     * @param locale can't be null
+     * @throws NullPointerException if {@code locale} is null
+     * @return a {@link DecimalFormatData} instance
+     */
+    public static DecimalFormatData getInstance(Locale locale) {
+        Objects.requireNonNull(locale, "locale can't be null");
+
+        locale = LocaleData.getCompatibleLocaleForBug159514442(locale);
+
+        final String languageTag = locale.toLanguageTag();
+
+        DecimalFormatData data = CACHE.get(languageTag);
+        if (data != null) {
+            return data;
+        }
+
+        data = new DecimalFormatData(locale);
+        DecimalFormatData prev = CACHE.putIfAbsent(languageTag, data);
+        if (prev != null) {
+            return prev;
+        }
+        return data;
+    }
+
+    /**
+     * Ensure that we pull in the locale data for the root locale, en_US, and the user's default
+     * locale. All devices must support the root locale and en_US, and they're used for various
+     * system things. Pre-populating the cache is especially useful on Android because
+     * we'll share this via the Zygote.
+     */
+    public static void initializeCacheInZygote() {
+        getInstance(Locale.ROOT);
+        getInstance(Locale.US);
+        getInstance(Locale.getDefault());
+    }
+
+    public char getZeroDigit() {
+        return zeroDigit;
+    }
+
+    public char getDecimalSeparator() {
+        return decimalSeparator;
+    }
+
+    public char getGroupingSeparator() {
+        return groupingSeparator;
+    }
+
+    public char getPatternSeparator() {
+        return patternSeparator;
+    }
+
+    public String getPercent() {
+        return percent;
+    }
+
+    public String getPerMill() {
+        return perMill;
+    }
+
+    public char getMonetarySeparator() {
+        return monetarySeparator;
+    }
+
+    public String getMinusSign() {
+        return minusSign;
+    }
+
+    public String getExponentSeparator() {
+        return exponentSeparator;
+    }
+
+    public String getInfinity() {
+        return infinity;
+    }
+
+    public String getNaN() {
+        return NaN;
+    }
+
+    public String getNumberPattern() {
+        return numberPattern;
+    }
+
+    public String getCurrencyPattern() {
+        return currencyPattern;
+    }
+
+    public String getPercentPattern() {
+        return percentPattern;
+    }
+
+    // Libcore localizes pattern separator while ICU doesn't. http://b/112080617
+    private static char loadPatternSeparator(Locale locale) {
+        ULocale uLocale = ULocale.forLocale(locale);
+        NumberingSystem ns = NumberingSystem.getInstance(uLocale);
+        // A numbering system could be numeric or algorithmic. DecimalFormat can only use
+        // a numeric and decimal-based (radix == 10) system. Fallback to a Latin, a known numeric
+        // and decimal-based if the default numbering system isn't. All locales should have data
+        // for Latin numbering system after locale data fallback. See Numbering system section
+        // in Unicode Technical Standard #35 for more details.
+        if (ns == null || ns.getRadix() != 10 || ns.isAlgorithmic()) {
+            ns = NumberingSystem.LATIN;
+        }
+        String patternSeparator = ExtendedDecimalFormatSymbols.getInstance(uLocale, ns)
+                .getLocalizedPatternSeparator();
+
+        if (patternSeparator == null || patternSeparator.isEmpty()) {
+            patternSeparator = ";";
+        }
+
+        // Pattern separator in libcore supports single java character only.
+        return patternSeparator.charAt(0);
+    }
+}
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index e72d707..784a24d 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -447,17 +447,27 @@
     boolean remove_B_and_b = (contains_B || contains_b) && (pattern.indexOf('H') != -1);
 
     if (remove_B_and_b) {
-      pattern = rewriteIcuDateTimePattern(pattern);
+      return removeBFromDateTimePattern(pattern);
     }
+
+    // Non-ideal workaround until http://b/68139386 is implemented.
+    // This workaround may create a pattern that isn't usual / common for the language users.
+    if (pattern.indexOf('h') != -1) {
+      if (contains_b) {
+        pattern = pattern.replace('b', 'a');
+      }
+      if (contains_B) {
+        pattern = pattern.replace('B', 'a');
+      }
+    }
+
     return pattern;
   }
 
   /**
-   * Rewrite pattern with heuristics. It's known to
-   *   - Remove 'b' and 'B' from simple patterns, e.g. "B H:mm" and "dd-MM-yy B HH:mm:ss" only.
-   *   - (Append the new heuristics)
+   * Remove 'b' and 'B' from simple patterns, e.g. "B H:mm" and "dd-MM-yy B HH:mm:ss" only.
    */
-  private static String rewriteIcuDateTimePattern(String pattern) {
+  private static String removeBFromDateTimePattern(String pattern) {
     // The below implementation can likely be replaced by a regular expression via
     // String.replaceAll(). However, it's known that libcore's regex implementation is more
     // memory-intensive, and the below implementation is likely cheaper, but it's not yet measured.
@@ -599,4 +609,24 @@
               .setKeywordValue("calendar", calendarType);
       return ExtendedCalendar.getInstance(uLocale);
   }
+
+  /**
+   * Converts CLDR LDML short time zone id to an ID that can be recognized by
+   * {@link java.util.TimeZone#getTimeZone(String)}.
+   * @param cldrShortTzId
+   * @return null if no tz id can be matched to the short id.
+   */
+  public static String convertToTzId(String cldrShortTzId) {
+    if (cldrShortTzId == null) {
+      return null;
+    }
+    String tzid = ULocale.toLegacyType("tz", cldrShortTzId);
+    // ULocale.toLegacyType() returns the lower case of the input ID if it matches the spec, but
+    // it's not a valid tz id.
+    if (tzid == null || tzid.equals(cldrShortTzId.toLowerCase(Locale.ROOT))) {
+      return null;
+    }
+    return tzid;
+  }
+
 }
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index 04170a6..2fd8221 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -19,22 +19,12 @@
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.compat.Compatibility;
 import android.icu.text.DateFormatSymbols;
-import android.icu.text.DecimalFormat;
-import android.icu.text.DecimalFormatSymbols;
-import android.icu.text.NumberFormat;
-import android.icu.text.NumberingSystem;
 import android.icu.util.Calendar;
 import android.icu.util.GregorianCalendar;
-import android.icu.util.ULocale;
-
-import com.android.icu.text.ExtendedDecimalFormatSymbols;
-import com.android.icu.util.ExtendedCalendar;
 
 import dalvik.system.VMRuntime;
 
-import java.text.DateFormat;
 import java.util.HashMap;
 import java.util.Locale;
 import libcore.util.Objects;
@@ -87,6 +77,7 @@
     @EnabledAfter(targetSdkVersion=29 /* Android Q */)
     public static final long USE_REAL_ROOT_LOCALE = 159047832L;
 
+    // TODO(http://b/217881004): Replace this with a LRU cache.
     // A cache for the locale-specific data.
     private static final HashMap<String, LocaleData> localeDataCache = new HashMap<String, LocaleData>();
     static {
@@ -127,22 +118,14 @@
     public String[] shortStandAloneWeekdayNames; // "Sun", ...
     public String[] tinyStandAloneWeekdayNames; // "S", ...
 
-    // today and tomorrow is only kept for @UnsupportedAppUsage.
+    // zeroDigit, today and tomorrow is only kept for @UnsupportedAppUsage.
     // Their value is hard-coded, not localized.
     @UnsupportedAppUsage
     public String today; // "Today".
     @UnsupportedAppUsage
     public String tomorrow; // "Tomorrow".
-
-    public String fullTimeFormat;
-    public String longTimeFormat;
-    public String mediumTimeFormat;
-    public String shortTimeFormat;
-
-    public String fullDateFormat;
-    public String longDateFormat;
-    public String mediumDateFormat;
-    public String shortDateFormat;
+    @UnsupportedAppUsage
+    public char zeroDigit; // '0'
 
     // timeFormat_hm and timeFormat_Hm are only kept for @UnsupportedAppUsage.
     // Their value is hard-coded, not localized.
@@ -151,32 +134,10 @@
     @UnsupportedAppUsage
     public String timeFormat_Hm;
 
-    // Used by DecimalFormatSymbols.
-    @UnsupportedAppUsage
-    public char zeroDigit;
-    public char decimalSeparator;
-    public char groupingSeparator;
-    public char patternSeparator;
-    public String percent;
-    public String perMill;
-    public char monetarySeparator;
-    public String minusSign;
-    public String exponentSeparator;
-    public String infinity;
-    public String NaN;
-
-    // Used by DecimalFormat and NumberFormat.
-    public String numberPattern;
-    public String integerPattern;
-    public String currencyPattern;
-    public String percentPattern;
-
-    private final Locale mLocale;
-
-    private LocaleData(Locale locale) {
-        mLocale = locale;
+    private LocaleData() {
         today = "Today";
         tomorrow = "Tomorrow";
+        zeroDigit = '0';
         timeFormat_hm = "h:mm a";
         timeFormat_Hm = "HH:mm";
     }
@@ -246,106 +207,18 @@
         return Objects.toString(this);
     }
 
-    public String getDateFormat(int style) {
-        switch (style) {
-        case DateFormat.SHORT:
-            return shortDateFormat;
-        case DateFormat.MEDIUM:
-            return mediumDateFormat;
-        case DateFormat.LONG:
-            return longDateFormat;
-        case DateFormat.FULL:
-            return fullDateFormat;
-        }
-        throw new AssertionError();
-    }
-
-    public String getTimeFormat(int style) {
-        // Do not cache ICU.getTimePattern() return value in the LocaleData instance
-        // because most users do not enable this setting, hurts performance in critical path,
-        // e.g. b/161846393, and ICU.getBestDateTimePattern will cache it in  ICU.CACHED_PATTERNS
-        // on demand.
-        switch (style) {
-        case DateFormat.SHORT:
-            if (DateFormat.is24Hour == null) {
-                return shortTimeFormat;
-            } else {
-                return ICU.getTimePattern(mLocale, DateFormat.is24Hour, false);
-            }
-        case DateFormat.MEDIUM:
-            if (DateFormat.is24Hour == null) {
-                return mediumTimeFormat;
-            } else {
-                return ICU.getTimePattern(mLocale, DateFormat.is24Hour, true);
-            }
-        case DateFormat.LONG:
-            // CLDR doesn't really have anything we can use to obey the 12-/24-hour preference.
-            return longTimeFormat;
-        case DateFormat.FULL:
-            // CLDR doesn't really have anything we can use to obey the 12-/24-hour preference.
-            return fullTimeFormat;
-        }
-        throw new AssertionError();
-    }
-
     /*
      * This method is made public for testing
      */
     public static LocaleData initLocaleData(Locale locale) {
-        LocaleData localeData = new LocaleData(locale);
+        LocaleData localeData = new LocaleData();
 
-        localeData.initializeDateTimePatterns(locale);
         localeData.initializeDateFormatData(locale);
-        localeData.initializeDecimalFormatData(locale);
         localeData.initializeCalendarData(locale);
 
-        // Libcore localizes pattern separator while ICU doesn't. http://b/112080617
-        initializePatternSeparator(localeData, locale);
-
-        // Fix up a couple of patterns.
-        if (localeData.fullTimeFormat != null) {
-            // There are some full time format patterns in ICU that use the pattern character 'v'.
-            // Java doesn't accept this, so we replace it with 'z' which has about the same result
-            // as 'v', the timezone name.
-            // 'v' -> "PT", 'z' -> "PST", v is the generic timezone and z the standard tz
-            // "vvvv" -> "Pacific Time", "zzzz" -> "Pacific Standard Time"
-            localeData.fullTimeFormat = localeData.fullTimeFormat.replace('v', 'z');
-        }
-        if (localeData.numberPattern != null) {
-            // The number pattern might contain positive and negative subpatterns. Arabic, for
-            // example, might look like "#,##0.###;#,##0.###-" because the minus sign should be
-            // written last. Macedonian supposedly looks something like "#,##0.###;(#,##0.###)".
-            // (The negative subpattern is optional, though, and not present in most locales.)
-            // By only swallowing '#'es and ','s after the '.', we ensure that we don't
-            // accidentally eat too much.
-            localeData.integerPattern = localeData.numberPattern.replaceAll("\\.[#,]*", "");
-        }
         return localeData;
     }
 
-    // Libcore localizes pattern separator while ICU doesn't. http://b/112080617
-    private static void initializePatternSeparator(LocaleData localeData, Locale locale) {
-        ULocale uLocale = ULocale.forLocale(locale);
-        NumberingSystem ns = NumberingSystem.getInstance(uLocale);
-        // A numbering system could be numeric or algorithmic. DecimalFormat can only use
-        // a numeric and decimal-based (radix == 10) system. Fallback to a Latin, a known numeric
-        // and decimal-based if the default numbering system isn't. All locales should have data
-        // for Latin numbering system after locale data fallback. See Numbering system section
-        // in Unicode Technical Standard #35 for more details.
-        if (ns == null || ns.getRadix() != 10 || ns.isAlgorithmic()) {
-            ns = NumberingSystem.LATIN;
-        }
-        String patternSeparator = ExtendedDecimalFormatSymbols.getInstance(uLocale, ns)
-                .getLocalizedPatternSeparator();
-
-        if (patternSeparator == null || patternSeparator.isEmpty()) {
-            patternSeparator = ";";
-        }
-
-        // Pattern separator in libcore supports single java character only.
-        localeData.patternSeparator = patternSeparator.charAt(0);
-    }
-
     private void initializeDateFormatData(Locale locale) {
         DateFormatSymbols dfs = new DateFormatSymbols(GregorianCalendar.class, locale);
 
@@ -375,65 +248,10 @@
 
     }
 
-    private void initializeDecimalFormatData(Locale locale) {
-        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
-
-        decimalSeparator = dfs.getDecimalSeparator();
-        groupingSeparator = dfs.getGroupingSeparator();
-        patternSeparator = dfs.getPatternSeparator();
-        percent = dfs.getPercentString();
-        perMill = dfs.getPerMillString();
-        monetarySeparator = dfs.getMonetaryDecimalSeparator();
-        minusSign = dfs.getMinusSignString();
-        exponentSeparator = dfs.getExponentSeparator();
-        infinity = dfs.getInfinity();
-        NaN = dfs.getNaN();
-        zeroDigit = dfs.getZeroDigit();
-
-        DecimalFormat df = (DecimalFormat) NumberFormat
-            .getInstance(locale, NumberFormat.NUMBERSTYLE);
-        numberPattern = df.toPattern();
-
-        df = (DecimalFormat) NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
-        currencyPattern = df.toPattern();
-
-        df = (DecimalFormat) NumberFormat.getInstance(locale, NumberFormat.PERCENTSTYLE);
-        percentPattern = df.toPattern();
-
-    }
-
     private void initializeCalendarData(Locale locale) {
         Calendar calendar = Calendar.getInstance(locale);
 
         firstDayOfWeek = calendar.getFirstDayOfWeek();
         minimalDaysInFirstWeek = calendar.getMinimalDaysInFirstWeek();
     }
-
-    private void initializeDateTimePatterns(Locale locale) {
-        // libcore's java.text supports Gregorian calendar only.
-        ExtendedCalendar extendedCalendar = ICU.getExtendedCalendar(locale, "gregorian");
-
-        fullTimeFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.FULL);
-        longTimeFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.LONG);
-        mediumTimeFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.NONE, android.icu.text.DateFormat. MEDIUM);
-        shortTimeFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.SHORT);
-        fullDateFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.FULL, android.icu.text.DateFormat.NONE);
-        longDateFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.LONG, android.icu.text.DateFormat.NONE);
-        mediumDateFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.MEDIUM, android.icu.text.DateFormat.NONE);
-        shortDateFormat = getDateTimeFormatString(extendedCalendar,
-            android.icu.text.DateFormat.SHORT, android.icu.text.DateFormat.NONE);
-    }
-
-    private static String getDateTimeFormatString(ExtendedCalendar extendedCalendar,
-            int dateStyle, int timeStyle) {
-        return ICU.transformIcuDateTimePattern_forJavaText(
-                extendedCalendar.getDateTimePattern(dateStyle, timeStyle));
-    }
 }
diff --git a/luni/src/main/java/libcore/icu/SimpleDateFormatData.java b/luni/src/main/java/libcore/icu/SimpleDateFormatData.java
new file mode 100644
index 0000000..500dd33
--- /dev/null
+++ b/luni/src/main/java/libcore/icu/SimpleDateFormatData.java
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+package libcore.icu;
+
+import com.android.icu.util.ExtendedCalendar;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Pattern cache for {@link SimpleDateFormat}
+ *
+ * @hide
+ */
+public class SimpleDateFormatData {
+
+    // TODO(http://b/217881004): Replace this with a LRU cache.
+    private static final ConcurrentHashMap<String, SimpleDateFormatData> CACHE =
+            new ConcurrentHashMap<>(/* initialCapacity */ 3);
+
+    private final Locale locale;
+
+    private final String fullTimeFormat;
+    private final String longTimeFormat;
+    private final String mediumTimeFormat;
+    private final String shortTimeFormat;
+
+    private final String fullDateFormat;
+    private final String longDateFormat;
+    private final String mediumDateFormat;
+    private final String shortDateFormat;
+
+    private SimpleDateFormatData(Locale locale) {
+        this.locale = locale;
+
+        // libcore's java.text supports Gregorian calendar only.
+        ExtendedCalendar extendedCalendar = ICU.getExtendedCalendar(locale, "gregorian");
+
+        String tmpFullTimeFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.FULL);
+
+        // Fix up a couple of patterns.
+        if (tmpFullTimeFormat != null) {
+            // There are some full time format patterns in ICU that use the pattern character 'v'.
+            // Java doesn't accept this, so we replace it with 'z' which has about the same result
+            // as 'v', the timezone name.
+            // 'v' -> "PT", 'z' -> "PST", v is the generic timezone and z the standard tz
+            // "vvvv" -> "Pacific Time", "zzzz" -> "Pacific Standard Time"
+            tmpFullTimeFormat = tmpFullTimeFormat.replace('v', 'z');
+        }
+        fullTimeFormat = tmpFullTimeFormat;
+
+        longTimeFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.LONG);
+        mediumTimeFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.MEDIUM);
+        shortTimeFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.NONE, android.icu.text.DateFormat.SHORT);
+        fullDateFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.FULL, android.icu.text.DateFormat.NONE);
+        longDateFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.LONG, android.icu.text.DateFormat.NONE);
+        mediumDateFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.MEDIUM, android.icu.text.DateFormat.NONE);
+        shortDateFormat = getDateTimeFormatString(extendedCalendar,
+                android.icu.text.DateFormat.SHORT, android.icu.text.DateFormat.NONE);
+    }
+
+    /**
+     * Returns an instance.
+     *
+     * @param locale can't be null
+     * @throws NullPointerException if {@code locale} is null
+     * @return a {@link SimpleDateFormatData} instance
+     */
+    public static SimpleDateFormatData getInstance(Locale locale) {
+        Objects.requireNonNull(locale, "locale can't be null");
+
+        locale = LocaleData.getCompatibleLocaleForBug159514442(locale);
+
+        final String languageTag = locale.toLanguageTag();
+
+        SimpleDateFormatData data = CACHE.get(languageTag);
+        if (data != null) {
+            return data;
+        }
+
+        data = new SimpleDateFormatData(locale);
+        SimpleDateFormatData prev = CACHE.putIfAbsent(languageTag, data);
+        if (prev != null) {
+            return prev;
+        }
+        return data;
+    }
+
+    /**
+     * Ensure that we pull in the locale data for the root locale, en_US, and the user's default
+     * locale. All devices must support the root locale and en_US, and they're used for various
+     * system things. Pre-populating the cache is especially useful on Android because
+     * we'll share this via the Zygote.
+     */
+    public static void initializeCacheInZygote() {
+        getInstance(Locale.ROOT);
+        getInstance(Locale.US);
+        getInstance(Locale.getDefault());
+    }
+
+    /**
+     * @throws AssertionError if style is not one of the 4 styles specified in {@link DateFormat}
+     * @return a date pattern string
+     */
+    public String getDateFormat(int style) {
+        switch (style) {
+            case DateFormat.SHORT:
+                return shortDateFormat;
+            case DateFormat.MEDIUM:
+                return mediumDateFormat;
+            case DateFormat.LONG:
+                return longDateFormat;
+            case DateFormat.FULL:
+                return fullDateFormat;
+        }
+        // TODO: fix this legacy behavior of throwing AssertionError introduced in
+        //  the commit 6ca85c4.
+        throw new AssertionError();
+    }
+
+    /**
+     * @throws AssertionError if style is not one of the 4 styles specified in {@link DateFormat}
+     * @return a time pattern string
+     */
+    public String getTimeFormat(int style) {
+        // Do not cache ICU.getTimePattern() return value in the LocaleData instance
+        // because most users do not enable this setting, hurts performance in critical path,
+        // e.g. b/161846393, and ICU.getBestDateTimePattern will cache it in  ICU.CACHED_PATTERNS
+        // on demand.
+        switch (style) {
+            case DateFormat.SHORT:
+                if (DateFormat.is24Hour == null) {
+                    return shortTimeFormat;
+                } else {
+                    return ICU.getTimePattern(locale, DateFormat.is24Hour, false);
+                }
+            case DateFormat.MEDIUM:
+                if (DateFormat.is24Hour == null) {
+                    return mediumTimeFormat;
+                } else {
+                    return ICU.getTimePattern(locale, DateFormat.is24Hour, true);
+                }
+            case DateFormat.LONG:
+                // CLDR doesn't really have anything we can use to obey the 12-/24-hour preference.
+                return longTimeFormat;
+            case DateFormat.FULL:
+                // CLDR doesn't really have anything we can use to obey the 12-/24-hour preference.
+                return fullTimeFormat;
+        }
+        // TODO: fix this legacy behavior of throwing AssertionError introduced in
+        //  the commit 6ca85c4.
+        throw new AssertionError();
+    }
+
+    private static String getDateTimeFormatString(ExtendedCalendar extendedCalendar,
+            int dateStyle, int timeStyle) {
+        return ICU.transformIcuDateTimePattern_forJavaText(
+                extendedCalendar.getDateTimePattern(dateStyle, timeStyle));
+    }
+
+}
diff --git a/luni/src/main/java/libcore/internal/Java11LanguageFeatures.java b/luni/src/main/java/libcore/internal/Java11LanguageFeatures.java
new file mode 100644
index 0000000..250d473
--- /dev/null
+++ b/luni/src/main/java/libcore/internal/Java11LanguageFeatures.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 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.internal;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Proof of concept / fake code whose only purpose is to demonstrate that Java 11
+ * language features are supported in libcore.
+ */
+public class Java11LanguageFeatures {
+
+    public static String collectUpperCaseStrings(List<String> list) {
+        // Language feature: local-variable syntax for lambda
+        return list.stream()
+            .map((var item) -> item.toUpperCase())
+            .collect(Collectors.joining(" "));
+    }
+
+    public static String guessTheString(String guess) {
+        // Language feature (Java 10): local-variable type inference
+        var answer = "The answer to the universe, life and everything";
+        if (!(answer instanceof String)) {
+            return null;
+        }
+        if (!guess.equals(answer)) {
+            return "";
+        }
+        return answer;
+    }
+
+    public static class Person {
+        // Language feature: Reflection on private fields/methods of nest-mates
+        // Note: This at the moment is not supported yet in Android and calling these methods will
+        // result in exceptions (b/210843415).
+        private final String name;
+        private final Vocabulary vocabulary = new Vocabulary();
+
+        public Person(String name) {
+            this.name = name;
+        }
+
+        public String greet() throws NoSuchMethodException, InvocationTargetException,
+               NoSuchFieldException, IllegalAccessException {
+            Method greetFn = Vocabulary.class.getDeclaredMethod("greet");
+            return (String) greetFn.invoke(vocabulary);
+        }
+
+        private class Vocabulary {
+
+            private String greet() throws NoSuchFieldException, IllegalAccessException {
+                Field nameField = Person.class.getDeclaredField("name");
+                String nameValue = (String) nameField.get(Person.this);
+                return "Hello " + nameValue;
+            }
+        }
+    }
+}
diff --git a/luni/src/main/java/libcore/io/BlockGuardOs.java b/luni/src/main/java/libcore/io/BlockGuardOs.java
index 5b331b1..f160f84 100755
--- a/luni/src/main/java/libcore/io/BlockGuardOs.java
+++ b/luni/src/main/java/libcore/io/BlockGuardOs.java
@@ -137,6 +137,7 @@
         return (domain == AF_INET) || (domain == AF_INET6);
     }
 
+    @SuppressWarnings("NewApi") // False positive lint limitation, see b/177434707.
     private static boolean isLingerSocket(FileDescriptor fd) throws ErrnoException {
         StructLinger linger = Libcore.os.getsockoptLinger(fd, SOL_SOCKET, SO_LINGER);
         return linger.isOn() && linger.l_linger > 0;
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 8320be0..fd5655d 100755
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -58,7 +58,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class ForwardingOs implements Os {
     @UnsupportedAppUsage
     private final Os os;
@@ -72,7 +71,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     protected ForwardingOs(@NonNull Os os) {
         this.os = Objects.requireNonNull(os);
     }
@@ -123,7 +121,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 
     /**
      * @hide
@@ -563,7 +560,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public FileDescriptor open(@Nullable String path, int flags, int mode) throws ErrnoException { return os.open(path, flags, mode); }
 
     /**
@@ -674,7 +670,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void remove(@Nullable String path) throws ErrnoException { os.remove(path); }
 
     /**
@@ -700,7 +695,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void rename(@Nullable String oldPath, @Nullable String newPath) throws ErrnoException { os.rename(oldPath, newPath); }
 
     /**
@@ -849,7 +843,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public @Nullable StructStat stat(@Nullable String path) throws ErrnoException { return os.stat(path); }
 
     /**
@@ -927,7 +920,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public void unlink(@Nullable String pathname) throws ErrnoException { os.unlink(pathname); }
 
     /**
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index 2fb6d58..541e187 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -95,7 +95,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class IoBridge {
 
     private IoBridge() {
@@ -294,7 +293,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void closeAndSignalBlockedThreads(@NonNull FileDescriptor fd) throws IOException {
         if (fd == null) {
             return;
@@ -372,6 +370,7 @@
         }
     }
 
+    @SuppressWarnings("NewApi") // False positive lint limitation, see b/177434707.
     private static Object getSocketOptionErrno(FileDescriptor fd, int option) throws ErrnoException, SocketException {
         switch (option) {
         case SocketOptions.IP_MULTICAST_IF:
@@ -446,6 +445,7 @@
         }
     }
 
+    @SuppressWarnings("NewApi") // False positive lint limitation, see b/177434707.
     private static void setSocketOptionErrno(FileDescriptor fd, int option, Object value) throws ErrnoException, SocketException {
         switch (option) {
         case SocketOptions.IP_MULTICAST_IF:
@@ -554,7 +554,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull FileDescriptor open(@NonNull String path, int flags) throws FileNotFoundException {
         FileDescriptor fd = null;
         try {
@@ -596,7 +595,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int read(@NonNull FileDescriptor fd, @NonNull byte[] bytes, int byteOffset, int byteCount) throws IOException {
         ArrayUtils.throwsIfOutOfBounds(bytes.length, byteOffset, byteCount);
         if (byteCount == 0) {
@@ -638,7 +636,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void write(@NonNull FileDescriptor fd,@NonNull  byte[] bytes, int byteOffset, int byteCount) throws IOException {
         ArrayUtils.throwsIfOutOfBounds(bytes.length, byteOffset, byteCount);
         if (byteCount == 0) {
diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java
index 6820868..d5ddf94 100644
--- a/luni/src/main/java/libcore/io/IoUtils.java
+++ b/luni/src/main/java/libcore/io/IoUtils.java
@@ -43,7 +43,6 @@
 
 /** @hide */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class IoUtils {
     private IoUtils() {
     }
@@ -65,7 +64,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int acquireRawFd(@NonNull FileDescriptor fd) {
         Objects.requireNonNull(fd);
 
@@ -151,7 +149,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setFdOwner(@NonNull FileDescriptor fd, @NonNull Object owner) {
         Objects.requireNonNull(fd);
         Objects.requireNonNull(owner);
@@ -179,7 +176,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void close(@Nullable FileDescriptor fd) throws IOException {
         IoBridge.closeAndSignalBlockedThreads(fd);
     }
@@ -193,7 +189,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void closeQuietly(@Nullable AutoCloseable closeable) {
         if (closeable != null) {
             try {
@@ -214,7 +209,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void closeQuietly(@Nullable FileDescriptor fd) {
         try {
             IoUtils.close(fd);
@@ -231,7 +225,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void closeQuietly(@Nullable Socket socket) {
         if (socket != null) {
             try {
@@ -254,7 +247,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setBlocking(@NonNull FileDescriptor fd, boolean blocking) throws IOException {
         try {
             int flags = Libcore.os.fcntlVoid(fd, F_GETFL);
@@ -280,7 +272,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull byte[] readFileAsByteArray(@NonNull String absolutePath) throws IOException {
         return new FileReader(absolutePath).readFully().toByteArray();
     }
@@ -296,7 +287,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull String readFileAsString(@NonNull String absolutePath) throws IOException {
         return new FileReader(absolutePath).readFully().toString(StandardCharsets.UTF_8);
     }
diff --git a/luni/src/main/java/libcore/io/Memory.java b/luni/src/main/java/libcore/io/Memory.java
index ac8ccb9..d9df6d5 100644
--- a/luni/src/main/java/libcore/io/Memory.java
+++ b/luni/src/main/java/libcore/io/Memory.java
@@ -26,7 +26,6 @@
 
 import dalvik.annotation.optimization.FastNative;
 
-import libcore.api.CorePlatformApi;
 import libcore.util.NonNull;
 
 /**
@@ -34,7 +33,6 @@
  *
  * @hide
  */
-@CorePlatformApi(status = CorePlatformApi.Status.STABLE)
 @SystemApi(client = MODULE_LIBRARIES)
 public final class Memory {
     private Memory() { }
@@ -67,7 +65,6 @@
      *
      * @hide
      */
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static int peekInt(@NonNull byte[] src, int offset, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
@@ -121,7 +118,6 @@
      *
      * @hide
      */
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static short peekShort(@NonNull byte[] src, int offset, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
@@ -142,7 +138,6 @@
      *
      * @hide
      */
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static void pokeInt(@NonNull byte[] dst, int offset, int value, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
@@ -169,7 +164,6 @@
      *
      * @hide
      */
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static void pokeLong(@NonNull byte[] dst, int offset, long value, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
@@ -208,7 +202,6 @@
      *
      * @hide
      */
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static void pokeShort(@NonNull byte[] dst, int offset, short value, @NonNull ByteOrder order) {
         if (order == ByteOrder.BIG_ENDIAN) {
@@ -239,7 +232,6 @@
      *
      * @hide make type-safe before making public?
      */
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static native void memmove(@NonNull Object dstObject, int dstOffset, @NonNull Object srcObject, int srcOffset, long byteCount);
 
@@ -295,36 +287,43 @@
      * @hide
      */
     @UnsupportedAppUsage
+    @FastNative
     public static native void peekByteArray(long address, byte[] dst, int dstOffset, int byteCount);
 
     /**
      * @hide
      */
+    @FastNative
     public static native void peekCharArray(long address, char[] dst, int dstOffset, int charCount, boolean swap);
 
     /**
      * @hide
      */
+    @FastNative
     public static native void peekDoubleArray(long address, double[] dst, int dstOffset, int doubleCount, boolean swap);
 
     /**
      * @hide
      */
+    @FastNative
     public static native void peekFloatArray(long address, float[] dst, int dstOffset, int floatCount, boolean swap);
 
     /**
      * @hide
      */
+    @FastNative
     public static native void peekIntArray(long address, int[] dst, int dstOffset, int intCount, boolean swap);
 
     /**
      * @hide
      */
+    @FastNative
     public static native void peekLongArray(long address, long[] dst, int dstOffset, int longCount, boolean swap);
 
     /**
      * @hide
      */
+    @FastNative
     public static native void peekShortArray(long address, short[] dst, int dstOffset, int shortCount, boolean swap);
 
     /**
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index 0c58455..092de59 100755
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -59,7 +59,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public interface Os {
 
     /**
@@ -790,7 +789,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean compareAndSetDefault(Os expect, Os update) {
         return Libcore.compareAndSetOs(expect, update);
     }
@@ -801,7 +799,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static Os getDefault() {
         return Libcore.getOs();
     }
diff --git a/luni/src/main/java/libcore/io/Streams.java b/luni/src/main/java/libcore/io/Streams.java
index 6002118..457a36f 100644
--- a/luni/src/main/java/libcore/io/Streams.java
+++ b/luni/src/main/java/libcore/io/Streams.java
@@ -39,7 +39,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class Streams {
     private static AtomicReference<byte[]> skipBuffer = new AtomicReference<byte[]>();
 
@@ -58,7 +57,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int readSingleByte(@NonNull InputStream in) throws IOException {
         byte[] buffer = new byte[1];
         int result = in.read(buffer, 0, 1);
@@ -78,7 +76,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void writeSingleByte(@NonNull OutputStream out, int b) throws IOException {
         byte[] buffer = new byte[1];
         buffer[0] = (byte) (b & 0xff);
@@ -97,7 +94,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void readFully(@NonNull InputStream in, @NonNull byte[] dst) throws IOException {
         readFully(in, dst, 0, dst.length);
     }
@@ -143,7 +139,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull byte[] readFully(@NonNull InputStream in) throws IOException {
         try {
             return readFullyNoClose(in);
@@ -163,7 +158,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull byte[] readFullyNoClose(@NonNull InputStream in) throws IOException {
         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
         byte[] buffer = new byte[1024];
@@ -184,7 +178,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull String readFully(@NonNull Reader reader) throws IOException {
         try {
             StringWriter writer = new StringWriter();
@@ -229,7 +222,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static long skipByReading(@NonNull InputStream in, long byteCount) throws IOException {
         // acquire the shared skip buffer.
         byte[] buffer = skipBuffer.getAndSet(null);
@@ -269,7 +261,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int copy(@NonNull InputStream in, @NonNull OutputStream out) throws IOException {
         int total = 0;
         byte[] buffer = new byte[8192];
diff --git a/luni/src/main/java/libcore/net/InetAddressUtils.java b/luni/src/main/java/libcore/net/InetAddressUtils.java
index a3860b5..b3b7297 100644
--- a/luni/src/main/java/libcore/net/InetAddressUtils.java
+++ b/luni/src/main/java/libcore/net/InetAddressUtils.java
@@ -35,7 +35,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class InetAddressUtils {
 
     private static final int NETID_UNSET = 0;
@@ -59,7 +58,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean isNumericAddress(String address) {
         return parseNumericAddressNoThrow(address) != null;
     }
@@ -80,7 +78,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static InetAddress parseNumericAddress(String address) {
         InetAddress result = parseNumericAddressNoThrow(address);
         if (result == null) {
diff --git a/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java b/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java
index ab4678e..aa7cde0 100644
--- a/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java
+++ b/luni/src/main/java/libcore/net/NetworkSecurityPolicy.java
@@ -35,7 +35,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 public abstract class NetworkSecurityPolicy {
 
@@ -49,7 +48,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public NetworkSecurityPolicy() {
     }
@@ -62,7 +60,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public static NetworkSecurityPolicy getInstance() {
         return instance;
@@ -76,7 +73,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void setInstance(NetworkSecurityPolicy policy) {
         if (policy == null) {
             throw new NullPointerException("policy == null");
@@ -109,7 +105,6 @@
      */
     @UnsupportedAppUsage
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public abstract boolean isCleartextTrafficPermitted();
 
     /**
@@ -125,7 +120,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public abstract boolean isCleartextTrafficPermitted(String hostname);
 
     /**
@@ -142,7 +136,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public abstract boolean isCertificateTransparencyVerificationRequired(String hostname);
 
diff --git a/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java b/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java
index 4324a61..eb57545 100644
--- a/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java
+++ b/luni/src/main/java/libcore/net/event/NetworkEventDispatcher.java
@@ -29,7 +29,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class NetworkEventDispatcher {
 
   private static final NetworkEventDispatcher instance = new NetworkEventDispatcher();
@@ -46,7 +45,6 @@
    */
   @UnsupportedAppUsage
   @SystemApi(client = MODULE_LIBRARIES)
-  @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
   public static NetworkEventDispatcher getInstance() {
     return instance;
   }
@@ -90,7 +88,6 @@
    * @hide
    */
   @SystemApi(client = MODULE_LIBRARIES)
-  @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
   public void dispatchNetworkConfigurationChange() {
     for (NetworkEventListener listener : listeners) {
       try {
diff --git a/luni/src/main/java/libcore/net/http/Dns.java b/luni/src/main/java/libcore/net/http/Dns.java
index a5bb423..9f1de62 100644
--- a/luni/src/main/java/libcore/net/http/Dns.java
+++ b/luni/src/main/java/libcore/net/http/Dns.java
@@ -20,8 +20,6 @@
 
 import android.annotation.SystemApi;
 
-import libcore.api.CorePlatformApi;
-
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.List;
@@ -33,7 +31,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@CorePlatformApi(status = CorePlatformApi.Status.STABLE)
 public interface Dns extends com.android.okhttp.internalandroidapi.Dns {
     /**
      * Returns the IP addresses of {@code hostname}, in the order they should
@@ -44,6 +41,5 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @NonNull List<@NonNull InetAddress> lookup(@Nullable String hostname) throws UnknownHostException;
 }
\ No newline at end of file
diff --git a/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java b/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java
index 9a713bd..98d06dd 100644
--- a/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java
+++ b/luni/src/main/java/libcore/net/http/HttpURLConnectionFactory.java
@@ -20,8 +20,6 @@
 
 import android.annotation.SystemApi;
 
-import libcore.api.CorePlatformApi;
-
 import java.io.IOException;
 import java.net.Proxy;
 import java.net.URL;
@@ -39,7 +37,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@CorePlatformApi(status = CorePlatformApi.Status.STABLE)
 public class HttpURLConnectionFactory {
     private final com.android.okhttp.internalandroidapi.HttpURLConnectionFactory mFactory;
 
@@ -49,7 +46,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     @NonNull public static HttpURLConnectionFactory createInstance() {
         return new HttpURLConnectionFactory();
     }
@@ -69,7 +65,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public void setNewConnectionPool(int maxIdleConnections, long keepAliveDuration,
             @NonNull TimeUnit timeUnit) {
         mFactory.setNewConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);
@@ -83,7 +78,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public void setDns(@NonNull Dns dns) {
         mFactory.setDns(dns);
     }
@@ -102,7 +96,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @CorePlatformApi(status = CorePlatformApi.Status.STABLE)
     public URLConnection openConnection(@NonNull URL url, @NonNull SocketFactory socketFactory,
             @NonNull Proxy proxy) throws IOException {
         return mFactory.openConnection(url, socketFactory, proxy);
diff --git a/luni/src/main/java/libcore/util/EmptyArray.java b/luni/src/main/java/libcore/util/EmptyArray.java
index f34fe02..aa6a6fd 100644
--- a/luni/src/main/java/libcore/util/EmptyArray.java
+++ b/luni/src/main/java/libcore/util/EmptyArray.java
@@ -27,20 +27,17 @@
  *
  * @hide
  */
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @SystemApi(client = MODULE_LIBRARIES)
 public final class EmptyArray {
     private EmptyArray() {}
 
     /** @hide */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final @NonNull boolean[] BOOLEAN = new boolean[0];
 
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q,
             publicAlternatives="Use {@code new byte[0]} instead.")
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final @NonNull byte[] BYTE = new byte[0];
 
@@ -51,21 +48,18 @@
     public static final double[] DOUBLE = new double[0];
 
     /** @hide */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final @NonNull float[] FLOAT = new float[0];
 
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q,
             publicAlternatives="Use {@code new int[0]} instead.")
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final @NonNull int[] INT = new int[0];
 
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q,
             publicAlternatives="Use {@code new long[0]} instead.")
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final @NonNull long[] LONG = new long[0];
 
@@ -75,12 +69,10 @@
     /** @hide */
     @UnsupportedAppUsage(maxTargetSdk=VersionCodes.Q,
             publicAlternatives="Use {@code new Object[0]} instead.")
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final @NonNull Object[] OBJECT = new Object[0];
 
     /** @hide */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @SystemApi(client = MODULE_LIBRARIES)
     public static final @NonNull String[] STRING = new String[0];
 
diff --git a/luni/src/main/java/libcore/util/FP16.java b/luni/src/main/java/libcore/util/FP16.java
index d5a78ed..09a2e76 100644
--- a/luni/src/main/java/libcore/util/FP16.java
+++ b/luni/src/main/java/libcore/util/FP16.java
@@ -91,7 +91,6 @@
  */
 
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final class FP16 {
     /**
      * The number of bits used to represent a half-precision float value.
@@ -99,7 +98,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int SIZE = 16;
 
     /**
@@ -109,7 +107,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short EPSILON = (short) 0x1400;
 
     /**
@@ -118,7 +115,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int MAX_EXPONENT = 15;
     /**
      * Minimum exponent a normalized half-precision float may have.
@@ -126,7 +122,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int MIN_EXPONENT = -14;
 
     /**
@@ -135,7 +130,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short LOWEST_VALUE = (short) 0xfbff;
     /**
      * Maximum positive finite value a half-precision float may have.
@@ -143,7 +137,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short MAX_VALUE = (short) 0x7bff;
     /**
      * Smallest positive normal value a half-precision float may have.
@@ -151,7 +144,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short MIN_NORMAL = (short) 0x0400;
     /**
      * Smallest positive non-zero value a half-precision float may have.
@@ -159,7 +151,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short MIN_VALUE = (short) 0x0001;
     /**
      * A Not-a-Number representation of a half-precision float.
@@ -167,7 +158,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short NaN = (short) 0x7e00;
     /**
      * Negative infinity of type half-precision float.
@@ -175,7 +165,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short NEGATIVE_INFINITY = (short) 0xfc00;
     /**
      * Negative 0 of type half-precision float.
@@ -183,7 +172,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short NEGATIVE_ZERO = (short) 0x8000;
     /**
      * Positive infinity of type half-precision float.
@@ -191,7 +179,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short POSITIVE_INFINITY = (short) 0x7c00;
     /**
      * Positive 0 of type half-precision float.
@@ -199,7 +186,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final short POSITIVE_ZERO = (short) 0x0000;
 
     /**
@@ -208,7 +194,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int SIGN_SHIFT                = 15;
 
     /**
@@ -217,7 +202,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int EXPONENT_SHIFT            = 10;
 
     /**
@@ -226,7 +210,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int SIGN_MASK                 = 0x8000;
 
     /**
@@ -235,7 +218,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int SHIFTED_EXPONENT_MASK     = 0x1f;
 
     /**
@@ -244,7 +226,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int SIGNIFICAND_MASK          = 0x3ff;
 
     /**
@@ -253,7 +234,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int EXPONENT_SIGNIFICAND_MASK = 0x7fff;
 
     /**
@@ -262,7 +242,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static final int EXPONENT_BIAS             = 15;
 
     private static final int FP32_SIGN_SHIFT            = 31;
@@ -299,7 +278,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static int compare(short x, short y) {
         if (less(x, y)) return -1;
         if (greater(x, y)) return 1;
@@ -332,7 +310,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static short rint(short h) {
         int bits = h & 0xffff;
         int abs = bits & EXPONENT_SIGNIFICAND_MASK;
@@ -378,7 +355,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static short ceil(short h) {
         int bits = h & 0xffff;
         int abs = bits & EXPONENT_SIGNIFICAND_MASK;
@@ -422,7 +398,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static short floor(short h) {
         int bits = h & 0xffff;
         int abs = bits & EXPONENT_SIGNIFICAND_MASK;
@@ -464,7 +439,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static short trunc(short h) {
         int bits = h & 0xffff;
         int abs = bits & EXPONENT_SIGNIFICAND_MASK;
@@ -496,7 +470,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static short min(short x, short y) {
         if (isNaN(x)) return NaN;
         if (isNaN(y)) return NaN;
@@ -525,7 +498,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static short max(short x, short y) {
         if (isNaN(x)) return NaN;
         if (isNaN(y)) return NaN;
@@ -551,7 +523,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean less(short x, short y) {
         if (isNaN(x)) return false;
         if (isNaN(y)) return false;
@@ -573,7 +544,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean lessEquals(short x, short y) {
         if (isNaN(x)) return false;
         if (isNaN(y)) return false;
@@ -595,7 +565,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean greater(short x, short y) {
         if (isNaN(x)) return false;
         if (isNaN(y)) return false;
@@ -617,7 +586,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean greaterEquals(short x, short y) {
         if (isNaN(x)) return false;
         if (isNaN(y)) return false;
@@ -639,7 +607,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean equals(short x, short y) {
         if (isNaN(x)) return false;
         if (isNaN(y)) return false;
@@ -658,7 +625,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean isInfinite(short h) {
         return (h & EXPONENT_SIGNIFICAND_MASK) == POSITIVE_INFINITY;
     }
@@ -673,7 +639,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean isNaN(short h) {
         return (h & EXPONENT_SIGNIFICAND_MASK) > POSITIVE_INFINITY;
     }
@@ -691,7 +656,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static boolean isNormalized(short h) {
         return (h & POSITIVE_INFINITY) != 0 && (h & POSITIVE_INFINITY) != POSITIVE_INFINITY;
     }
@@ -714,7 +678,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static float toFloat(short h) {
         int bits = h & 0xffff;
         int s = bits & SIGN_MASK;
@@ -772,7 +735,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static short toHalf(float f) {
         int bits = Float.floatToRawIntBits(f);
         int s = (bits >>> FP32_SIGN_SHIFT    );
@@ -855,7 +817,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static String toHexString(short h) {
         StringBuilder o = new StringBuilder();
 
diff --git a/luni/src/main/java/libcore/util/HexEncoding.java b/luni/src/main/java/libcore/util/HexEncoding.java
index 5edcb20..7404896 100644
--- a/luni/src/main/java/libcore/util/HexEncoding.java
+++ b/luni/src/main/java/libcore/util/HexEncoding.java
@@ -25,7 +25,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class HexEncoding {
 
     private static final char[] LOWER_CASE_DIGITS = {
@@ -50,7 +49,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static String encodeToString(byte b, boolean upperCase) {
         char[] digits = upperCase ? UPPER_CASE_DIGITS : LOWER_CASE_DIGITS;
         char[] buf = new char[2]; // We always want two digits.
@@ -68,7 +66,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static char[] encode(byte[] data) {
         return encode(data, 0, data.length, true /* upperCase */);
     }
@@ -84,7 +81,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static char[] encode(byte[] data, boolean upperCase) {
         return encode(data, 0, data.length, upperCase);
     }
@@ -100,7 +96,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static char[] encode(byte[] data, int offset, int len) {
         return encode(data, offset, len, true /* upperCase */);
     }
@@ -130,7 +125,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static String encodeToString(byte[] data) {
         return encodeToString(data, true /* upperCase */);
     }
@@ -146,7 +140,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static String encodeToString(byte[] data, boolean upperCase) {
         return new String(encode(data, upperCase));
     }
@@ -163,7 +156,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static byte[] decode(String encoded) throws IllegalArgumentException {
         return decode(encoded.toCharArray());
     }
@@ -182,7 +174,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static byte[] decode(String encoded, boolean allowSingleChar)
             throws IllegalArgumentException {
         return decode(encoded.toCharArray(), allowSingleChar);
@@ -200,7 +191,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static byte[] decode(char[] encoded) throws IllegalArgumentException {
         return decode(encoded, false);
     }
@@ -219,7 +209,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static byte[] decode(char[] encoded, boolean allowSingleChar)
             throws IllegalArgumentException {
         int encodedLength = encoded.length;
diff --git a/luni/src/main/java/libcore/util/NativeAllocationRegistry.java b/luni/src/main/java/libcore/util/NativeAllocationRegistry.java
index e336525..d176390 100644
--- a/luni/src/main/java/libcore/util/NativeAllocationRegistry.java
+++ b/luni/src/main/java/libcore/util/NativeAllocationRegistry.java
@@ -47,7 +47,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 public class NativeAllocationRegistry {
 
@@ -86,7 +85,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static NativeAllocationRegistry createNonmalloced(
             @NonNull ClassLoader classLoader, long freeFunction, long size) {
         return new NativeAllocationRegistry(classLoader, freeFunction, size, false);
@@ -117,7 +115,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static NativeAllocationRegistry createMalloced(
             @NonNull ClassLoader classLoader, long freeFunction, long size) {
         return new NativeAllocationRegistry(classLoader, freeFunction, size, true);
@@ -137,7 +134,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public static NativeAllocationRegistry createMalloced(
             @NonNull ClassLoader classLoader, long freeFunction) {
@@ -211,7 +207,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public NativeAllocationRegistry(@NonNull ClassLoader classLoader, long freeFunction, long size) {
         this(classLoader, freeFunction, size, size == 0);
     }
@@ -251,7 +246,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     @libcore.api.IntraCoreApi
     public @NonNull Runnable registerNativeAllocation(@NonNull Object referent, long nativePtr) {
         if (referent == null) {
@@ -346,7 +340,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static native void applyFreeFunction(long freeFunction, long nativePtr);
 }
 
diff --git a/luni/src/main/java/libcore/util/SneakyThrow.java b/luni/src/main/java/libcore/util/SneakyThrow.java
index 5a347d9..94582a1 100644
--- a/luni/src/main/java/libcore/util/SneakyThrow.java
+++ b/luni/src/main/java/libcore/util/SneakyThrow.java
@@ -30,7 +30,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class SneakyThrow {
 
     private SneakyThrow() {
@@ -45,7 +44,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static void sneakyThrow(@NonNull Throwable t) {
         SneakyThrow.<RuntimeException>sneakyThrow_(t);
     }
diff --git a/luni/src/main/java/libcore/util/XmlObjectFactory.java b/luni/src/main/java/libcore/util/XmlObjectFactory.java
index 7a1d7ec..fe13075 100644
--- a/luni/src/main/java/libcore/util/XmlObjectFactory.java
+++ b/luni/src/main/java/libcore/util/XmlObjectFactory.java
@@ -33,7 +33,6 @@
  * @hide
  */
 @SystemApi(client = MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class XmlObjectFactory {
 
     private XmlObjectFactory() {}
@@ -47,7 +46,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull XmlSerializer newXmlSerializer() {
         return new KXmlSerializer();
     }
@@ -61,7 +59,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull XmlPullParser newXmlPullParser() {
         return new KXmlParser();
     }
@@ -74,7 +71,6 @@
      * @hide
      */
     @SystemApi(client = MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static @NonNull XMLReader newXMLReader() {
         return new ExpatReader();
     }
diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp
index 5127fa1..0992e55 100755
--- a/luni/src/main/native/JniConstants.cpp
+++ b/luni/src/main/native/JniConstants.cpp
@@ -43,98 +43,72 @@
 // Flag indicating whether cached constants are valid
 static bool g_constants_valid = false;
 
-// Constants
-jclass booleanClass;
-jclass byteBufferClass;
-jclass doubleClass;
-jclass errnoExceptionClass;
-jclass fileDescriptorClass;
-jclass gaiExceptionClass;
-jclass inet6AddressClass;
-jclass inet6AddressHolderClass;
-jclass inetAddressClass;
-jclass inetAddressHolderClass;
-jclass inetSocketAddressClass;
-jclass inetSocketAddressHolderClass;
-jclass integerClass;
-jclass localeDataClass;
-jclass longClass;
-jclass netlinkSocketAddressClass;
-jclass packetSocketAddressClass;
-jclass vmSocketAddressClass;
-jclass primitiveByteArrayClass;
-jclass stringClass;
-jclass structAddrinfoClass;
-jclass structCmsghdrClass;
-jclass structGroupReqClass;
-jclass structIfaddrsClass;
-jclass structLingerClass;
-jclass structMsghdrClass;
-jclass structPasswdClass;
-jclass structPollfdClass;
-jclass structStatClass;
-jclass structStatVfsClass;
-jclass structTimespecClass;
-jclass structTimevalClass;
-jclass structUcredClass;
-jclass structUtsnameClass;
-jclass unixSocketAddressClass;
+// Mapping between C++ names and java class descriptors.
+#define JCLASS_CONSTANTS_LIST(V)                                                            \
+    V(BooleanClass, "java/lang/Boolean")                                                    \
+    V(ByteBufferClass, "java/nio/ByteBuffer")                                               \
+    V(DoubleClass, "java/lang/Double")                                                      \
+    V(ErrnoExceptionClass, "android/system/ErrnoException")                                 \
+    V(FileDescriptorClass, "java/io/FileDescriptor")                                        \
+    V(GaiExceptionClass, "android/system/GaiException")                                     \
+    V(Inet6AddressClass, "java/net/Inet6Address")                                           \
+    V(Inet6AddressHolderClass, "java/net/Inet6Address$Inet6AddressHolder")                  \
+    V(InetAddressClass, "java/net/InetAddress")                                             \
+    V(InetAddressHolderClass, "java/net/InetAddress$InetAddressHolder")                     \
+    V(InetSocketAddressClass, "java/net/InetSocketAddress")                                 \
+    V(InetSocketAddressHolderClass, "java/net/InetSocketAddress$InetSocketAddressHolder")   \
+    V(IntegerClass, "java/lang/Integer")                                                    \
+    V(LocaleDataClass, "libcore/icu/LocaleData")                                            \
+    V(LongClass, "java/lang/Long")                                                          \
+    V(NetlinkSocketAddressClass, "android/system/NetlinkSocketAddress")                     \
+    V(PacketSocketAddressClass, "android/system/PacketSocketAddress")                       \
+    V(VmSocketAddressClass, "android/system/VmSocketAddress")                               \
+    V(PrimitiveByteArrayClass, "[B")                                                        \
+    V(StringClass, "java/lang/String")                                                      \
+    V(StructAddrinfoClass, "android/system/StructAddrinfo")                                 \
+    V(StructCmsghdrClass, "android/system/StructCmsghdr")                                   \
+    V(StructGroupReqClass, "android/system/StructGroupReq")                                 \
+    V(StructIfaddrsClass, "android/system/StructIfaddrs")                                   \
+    V(StructLingerClass, "android/system/StructLinger")                                     \
+    V(StructMsghdrClass, "android/system/StructMsghdr")                                     \
+    V(StructPasswdClass, "android/system/StructPasswd")                                     \
+    V(StructPollfdClass, "android/system/StructPollfd")                                     \
+    V(StructStatClass, "android/system/StructStat")                                         \
+    V(StructStatVfsClass, "android/system/StructStatVfs")                                   \
+    V(StructTimevalClass, "android/system/StructTimeval")                                   \
+    V(StructTimespecClass, "android/system/StructTimespec")                                 \
+    V(StructUcredClass, "android/system/StructUcred")                                       \
+    V(StructUtsnameClass, "android/system/StructUtsname")                                   \
+    V(UnixSocketAddressClass, "android/system/UnixSocketAddress")
+
+#define DECLARE_JCLASS_CONSTANT(cppname, _) jclass g_ ## cppname;
+JCLASS_CONSTANTS_LIST(DECLARE_JCLASS_CONSTANT)
 
 // EnsureJniConstantsInitialized initializes cached constants. It should be
 // called before returning a heap object from the cache to ensure cache is
 // initialized. This pattern is only necessary because if a process finishes one
 // runtime and starts another then JNI_OnLoad may not be called.
 void EnsureJniConstantsInitialized(JNIEnv* env) {
-    if (g_constants_valid) {
-        return;
-    }
-
     std::lock_guard guard(g_constants_mutex);
     if (g_constants_valid) {
         return;
     }
 
-    booleanClass = findClass(env, "java/lang/Boolean");
-    byteBufferClass = findClass(env, "java/nio/ByteBuffer");
-    doubleClass = findClass(env, "java/lang/Double");
-    errnoExceptionClass = findClass(env, "android/system/ErrnoException");
-    fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
-    gaiExceptionClass = findClass(env, "android/system/GaiException");
-    inet6AddressClass = findClass(env, "java/net/Inet6Address");
-    inet6AddressHolderClass = findClass(env, "java/net/Inet6Address$Inet6AddressHolder");
-    inetAddressClass = findClass(env, "java/net/InetAddress");
-    inetAddressHolderClass = findClass(env, "java/net/InetAddress$InetAddressHolder");
-    inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
-    inetSocketAddressHolderClass = findClass(env, "java/net/InetSocketAddress$InetSocketAddressHolder");
-    integerClass = findClass(env, "java/lang/Integer");
-    localeDataClass = findClass(env, "libcore/icu/LocaleData");
-    longClass = findClass(env, "java/lang/Long");
-    netlinkSocketAddressClass = findClass(env, "android/system/NetlinkSocketAddress");
-    packetSocketAddressClass = findClass(env, "android/system/PacketSocketAddress");
-    vmSocketAddressClass = findClass(env, "android/system/VmSocketAddress");
-    primitiveByteArrayClass = findClass(env, "[B");
-    stringClass = findClass(env, "java/lang/String");
-    structAddrinfoClass = findClass(env, "android/system/StructAddrinfo");
-    structCmsghdrClass = findClass(env, "android/system/StructCmsghdr");
-    structGroupReqClass = findClass(env, "android/system/StructGroupReq");
-    structIfaddrsClass = findClass(env, "android/system/StructIfaddrs");
-    structLingerClass = findClass(env, "android/system/StructLinger");
-    structMsghdrClass = findClass(env, "android/system/StructMsghdr");
-    structPasswdClass = findClass(env, "android/system/StructPasswd");
-    structPollfdClass = findClass(env, "android/system/StructPollfd");
-    structStatClass = findClass(env, "android/system/StructStat");
-    structStatVfsClass = findClass(env, "android/system/StructStatVfs");
-    structTimevalClass = findClass(env, "android/system/StructTimeval");
-    structTimespecClass = findClass(env, "android/system/StructTimespec");
-    structUcredClass = findClass(env, "android/system/StructUcred");
-    structUtsnameClass = findClass(env, "android/system/StructUtsname");
-    unixSocketAddressClass = findClass(env, "android/system/UnixSocketAddress");
+#define INITIALIZE_JCLASS_CONSTANT(cppname, javaname) g_ ## cppname = findClass(env, javaname);
+JCLASS_CONSTANTS_LIST(INITIALIZE_JCLASS_CONSTANT)
 
     g_constants_valid = true;
 }
 
 }  // namespace
 
+#define CONSTANT_GETTER(cppname, _)                                                         \
+jclass JniConstants::Get ## cppname(JNIEnv* env) {                                          \
+    EnsureJniConstantsInitialized(env);                                                     \
+    return g_ ## cppname;                                                                   \
+}
+JCLASS_CONSTANTS_LIST(CONSTANT_GETTER)
+
 void JniConstants::Initialize(JNIEnv* env) {
     EnsureJniConstantsInitialized(env);
 }
@@ -152,178 +126,3 @@
     std::lock_guard guard(g_constants_mutex);
     g_constants_valid = false;
 }
-
-jclass JniConstants::GetBooleanClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return booleanClass;
-}
-
-jclass JniConstants::GetByteBufferClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return byteBufferClass;
-}
-
-jclass JniConstants::GetDoubleClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return doubleClass;
-}
-
-jclass JniConstants::GetErrnoExceptionClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return errnoExceptionClass;
-}
-
-jclass JniConstants::GetFileDescriptorClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return fileDescriptorClass;
-}
-
-jclass JniConstants::GetGaiExceptionClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return gaiExceptionClass;
-}
-
-jclass JniConstants::GetInet6AddressClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return inet6AddressClass;
-}
-
-jclass JniConstants::GetInet6AddressHolderClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return inet6AddressHolderClass;
-}
-
-jclass JniConstants::GetInetAddressClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return inetAddressClass;
-}
-
-jclass JniConstants::GetInetAddressHolderClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return inetAddressHolderClass;
-}
-
-jclass JniConstants::GetInetSocketAddressClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return inetSocketAddressClass;
-}
-
-jclass JniConstants::GetInetSocketAddressHolderClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return inetSocketAddressHolderClass;
-}
-
-jclass JniConstants::GetIntegerClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return integerClass;
-}
-
-jclass JniConstants::GetLocaleDataClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return localeDataClass;
-}
-
-jclass JniConstants::GetLongClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return longClass;
-}
-
-jclass JniConstants::GetNetlinkSocketAddressClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return netlinkSocketAddressClass;
-}
-
-jclass JniConstants::GetPacketSocketAddressClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return packetSocketAddressClass;
-}
-
-jclass JniConstants::GetVmSocketAddressClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return vmSocketAddressClass;
-}
-
-jclass JniConstants::GetPrimitiveByteArrayClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return primitiveByteArrayClass;
-}
-
-jclass JniConstants::GetStringClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return stringClass;
-}
-
-jclass JniConstants::GetStructAddrinfoClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structAddrinfoClass;
-}
-
-jclass JniConstants::GetStructCmsghdrClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structCmsghdrClass;
-}
-
-jclass JniConstants::GetStructGroupReqClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structGroupReqClass;
-}
-
-jclass JniConstants::GetStructIfaddrsClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structIfaddrsClass;
-}
-
-jclass JniConstants::GetStructLingerClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structLingerClass;
-}
-
-jclass JniConstants::GetStructMsghdrClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structMsghdrClass;
-}
-
-jclass JniConstants::GetStructPasswdClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structPasswdClass;
-}
-
-jclass JniConstants::GetStructPollfdClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structPollfdClass;
-}
-
-jclass JniConstants::GetStructStatClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structStatClass;
-}
-
-jclass JniConstants::GetStructStatVfsClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structStatVfsClass;
-}
-
-jclass JniConstants::GetStructTimespecClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structTimespecClass;
-}
-
-jclass JniConstants::GetStructTimevalClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structTimevalClass;
-}
-
-jclass JniConstants::GetStructUcredClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structUcredClass;
-}
-
-jclass JniConstants::GetStructUtsnameClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return structUtsnameClass;
-}
-
-jclass JniConstants::GetUnixSocketAddressClass(JNIEnv* env) {
-    EnsureJniConstantsInitialized(env);
-    return unixSocketAddressClass;
-}
diff --git a/luni/src/main/native/NetworkUtilities.cpp b/luni/src/main/native/NetworkUtilities.cpp
index cd695b7..47ce055 100755
--- a/luni/src/main/native/NetworkUtilities.cpp
+++ b/luni/src/main/native/NetworkUtilities.cpp
@@ -26,6 +26,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
+#include <android-base/logging.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedLocalRef.h>
 
@@ -79,19 +80,25 @@
     }
 
     ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(addressLength));
-    if (byteArray.get() == NULL) {
-        return NULL;
+    if (byteArray == nullptr) {
+        // NewByteArray aborts if the addressLength is negative, so the allocation must have failed.
+        DCHECK(env->ExceptionCheck());
+        return nullptr;
     }
+
     env->SetByteArrayRegion(byteArray.get(), 0, addressLength,
             reinterpret_cast<const jbyte*>(rawAddress));
 
-    static jmethodID getByAddressMethod = env->GetStaticMethodID(JniConstants::GetInetAddressClass(env),
-            "getByAddress", "(Ljava/lang/String;[BI)Ljava/net/InetAddress;");
-    if (getByAddressMethod == NULL) {
-        return NULL;
-    }
-    return env->CallStaticObjectMethod(JniConstants::GetInetAddressClass(env), getByAddressMethod,
-            NULL, byteArray.get(), scope_id);
+    jclass inetAddressClass = JniConstants::GetInetAddressClass(env);
+    jmethodID getByAddressMethod =
+        env->GetStaticMethodID(inetAddressClass,
+                               "getByAddress",
+                               "(Ljava/lang/String;[BI)Ljava/net/InetAddress;");
+    return env->CallStaticObjectMethod(inetAddressClass,
+                                       getByAddressMethod,
+                                       /*host*/ NULL,
+                                       /*addr*/ byteArray.get(),
+                                       /*scopeId*/ scope_id);
 }
 
 static bool inetAddressToSockaddr(JNIEnv* env, jobject inetAddress, int port, sockaddr_storage& ss, socklen_t& sa_len, bool map) {
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index d7b6c22..e8ed90e 100755
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -57,6 +57,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <log/log.h>
 #include <nativehelper/JNIPlatformHelp.h>
@@ -1638,11 +1639,9 @@
 }
 
 static jobjectArray Linux_getifaddrs(JNIEnv* env, jobject) {
-    static jmethodID ctor = env->GetMethodID(JniConstants::GetStructIfaddrsClass(env), "<init>",
+    jmethodID ctor = env->GetMethodID(JniConstants::GetStructIfaddrsClass(env), "<init>",
             "(Ljava/lang/String;ILjava/net/InetAddress;Ljava/net/InetAddress;Ljava/net/InetAddress;[B)V");
-    if (ctor == NULL) {
-        return NULL;
-    }
+    CHECK(ctor != NULL);
 
     ifaddrs* ifaddr;
     int rc = TEMP_FAILURE_RETRY(getifaddrs(&ifaddr));
@@ -1659,8 +1658,10 @@
     }
 
     // Prepare output array.
-    jobjectArray result = env->NewObjectArray(ifCount, JniConstants::GetStructIfaddrsClass(env), NULL);
+    jclass ifAddrsClass = JniConstants::GetStructIfaddrsClass(env);
+    jobjectArray result = env->NewObjectArray(ifCount, ifAddrsClass, NULL);
     if (result == NULL) {
+        DCHECK(env->ExceptionCheck());
         return NULL;
     }
 
@@ -1669,12 +1670,9 @@
     for (ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next, ++index) {
         TO_JAVA_STRING(name, ifa->ifa_name);
         jint flags = ifa->ifa_flags;
-        sockaddr_storage* interfaceAddr =
-            reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
-        sockaddr_storage* netmaskAddr =
-            reinterpret_cast<sockaddr_storage*>(ifa->ifa_netmask);
-        sockaddr_storage* broadAddr =
-            reinterpret_cast<sockaddr_storage*>(ifa->ifa_broadaddr);
+        sockaddr_storage* interfaceAddr = reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
+        sockaddr_storage* netmaskAddr = reinterpret_cast<sockaddr_storage*>(ifa->ifa_netmask);
+        sockaddr_storage* broadAddr = reinterpret_cast<sockaddr_storage*>(ifa->ifa_broadaddr);
 
         jobject addr, netmask, broad;
         jbyteArray hwaddr = NULL;
@@ -1684,14 +1682,18 @@
             case AF_INET6:
                 // IPv4 / IPv6.
                 // interfaceAddr and netmaskAddr are never null.
+                // sockaddrToInetAddress is not expected to return null.
                 if ((addr = sockaddrToInetAddress(env, *interfaceAddr, NULL)) == NULL) {
+                    DCHECK(env->ExceptionCheck());
                     return NULL;
                 }
                 if ((netmask = sockaddrToInetAddress(env, *netmaskAddr, NULL)) == NULL) {
+                    DCHECK(env->ExceptionCheck());
                     return NULL;
                 }
                 if (broadAddr != NULL && (ifa->ifa_flags & IFF_BROADCAST)) {
                     if ((broad = sockaddrToInetAddress(env, *broadAddr, NULL)) == NULL) {
+                        DCHECK(env->ExceptionCheck());
                         return NULL;
                     }
                 } else {
@@ -1713,6 +1715,7 @@
                 if (!allZero) {
                     hwaddr = env->NewByteArray(sll->sll_halen);
                     if (hwaddr == NULL) {
+                        DCHECK(env->ExceptionCheck());
                         return NULL;
                     }
                     env->SetByteArrayRegion(hwaddr, 0, sll->sll_halen,
@@ -1727,9 +1730,9 @@
             addr = netmask = broad = NULL;
         }
 
-        jobject o = env->NewObject(JniConstants::GetStructIfaddrsClass(env), ctor, name, flags,
-                                   addr, netmask, broad, hwaddr);
+        jobject o = env->NewObject(ifAddrsClass, ctor, name, flags, addr, netmask, broad, hwaddr);
         if (o == NULL) {
+            DCHECK(env->ExceptionCheck());
             return NULL;
         }
         env->SetObjectArrayElement(result, index, o);
@@ -2321,13 +2324,18 @@
         return -1;
     }
 
+    // Determine if the socket address is an internet address. We need to do this before invoking
+    // NET_FAILURE_RETRY(sendmsg) because that can throw and we can't call env->IsInstanceOf
+    // with a pending exception (b/194980932).
+    const bool isInetSocketAddressClass =
+            env->IsInstanceOf(sockAddrObj, JniConstants::GetInetSocketAddressClass(env));
+
     sockaddr* _sa = sa_len ? reinterpret_cast<sockaddr*>(&ss) : NULL;
     scopedMsghdrValue.setMsgNameAndLen(_sa, sa_len);
     rc  = NET_FAILURE_RETRY(env, ssize_t, sendmsg, javaFd, \
                                  &(scopedMsghdrValue.getObject()), flags);
 
-    if (sockAddrObj &&
-        !env->IsInstanceOf(sockAddrObj, JniConstants::GetInetSocketAddressClass(env))) {
+    if (sockAddrObj && !isInetSocketAddressClass) {
         // non InetSockAddress case, return now;
         return rc;
     }
@@ -2645,8 +2653,17 @@
 
 static jstring Linux_strerror(JNIEnv* env, jobject, jint errnum) {
     char buffer[BUFSIZ];
+#ifdef ANDROID_HOST_MUSL
+    /* musl only provides the posix version of strerror_r that returns int */
+    int ret = strerror_r(errnum, buffer, sizeof(buffer));
+    if (ret != 0) {
+      return env->NewStringUTF(android::base::StringPrintf("Unknown error %d", errnum).c_str());
+    }
+    return env->NewStringUTF(buffer);
+#else
     const char* message = strerror_r(errnum, buffer, sizeof(buffer));
     return env->NewStringUTF(message);
+#endif
 }
 
 static jstring Linux_strsignal(JNIEnv* env, jobject, jint signal) {
diff --git a/luni/src/main/native/libcore_io_Memory.cpp b/luni/src/main/native/libcore_io_Memory.cpp
index b8a8845..851cb9f 100644
--- a/luni/src/main/native/libcore_io_Memory.cpp
+++ b/luni/src/main/native/libcore_io_Memory.cpp
@@ -109,55 +109,6 @@
     return *cast<const jbyte*>(srcAddress);
 }
 
-static void Memory_peekByteArray(JNIEnv* env, jclass, jlong srcAddress, jbyteArray dst, jint dstOffset, jint byteCount) {
-    env->SetByteArrayRegion(dst, dstOffset, byteCount, cast<const jbyte*>(srcAddress));
-}
-
-// Implements the peekXArray methods:
-// - For unswapped access, we just use the JNI SetXArrayRegion functions.
-// - For swapped access, we use GetXArrayElements and our own copy-and-swap routines.
-//   GetXArrayElements is disproportionately cheap on Dalvik because it doesn't copy (as opposed
-//   to Hotspot, which always copies). The SWAP_FN copies and swaps in one pass, which is cheaper
-//   than copying and then swapping in a second pass. Depending on future VM/GC changes, the
-//   swapped case might need to be revisited.
-#define PEEKER(SCALAR_TYPE, JNI_NAME, SWAP_TYPE, SWAP_FN) { \
-    if (swap) { \
-        Scoped ## JNI_NAME ## ArrayRW elements(env, dst); \
-        if (elements.get() == NULL) { \
-            return; \
-        } \
-        const SWAP_TYPE* src = cast<const SWAP_TYPE*>(srcAddress); \
-        SWAP_FN(reinterpret_cast<SWAP_TYPE*>(elements.get()) + dstOffset, src, count); /*NOLINT*/ \
-    } else { \
-        const SCALAR_TYPE* src = cast<const SCALAR_TYPE*>(srcAddress); \
-        env->Set ## JNI_NAME ## ArrayRegion(dst, dstOffset, count, src); \
-    } \
-}
-
-static void Memory_peekCharArray(JNIEnv* env, jclass, jlong srcAddress, jcharArray dst, jint dstOffset, jint count, jboolean swap) {
-    PEEKER(jchar, Char, jshort, swapShorts);
-}
-
-static void Memory_peekDoubleArray(JNIEnv* env, jclass, jlong srcAddress, jdoubleArray dst, jint dstOffset, jint count, jboolean swap) {
-    PEEKER(jdouble, Double, jlong, swapLongs);
-}
-
-static void Memory_peekFloatArray(JNIEnv* env, jclass, jlong srcAddress, jfloatArray dst, jint dstOffset, jint count, jboolean swap) {
-    PEEKER(jfloat, Float, jint, swapInts);
-}
-
-static void Memory_peekIntArray(JNIEnv* env, jclass, jlong srcAddress, jintArray dst, jint dstOffset, jint count, jboolean swap) {
-    PEEKER(jint, Int, jint, swapInts);
-}
-
-static void Memory_peekLongArray(JNIEnv* env, jclass, jlong srcAddress, jlongArray dst, jint dstOffset, jint count, jboolean swap) {
-    PEEKER(jlong, Long, jlong, swapLongs);
-}
-
-static void Memory_peekShortArray(JNIEnv* env, jclass, jlong srcAddress, jshortArray dst, jint dstOffset, jint count, jboolean swap) {
-    PEEKER(jshort, Short, jshort, swapShorts);
-}
-
 static void Memory_pokeByte(JNIEnv*, jclass, jlong dstAddress, jbyte value) {
     *cast<jbyte*>(dstAddress) = value;
 }
@@ -290,19 +241,13 @@
     env->ReleasePrimitiveArrayCritical(srcArray, srcBytes, 0);
 }
 
+// The remaining Memory methods are contained in art/runtime/native/libcore_io_Memory.cc
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(Memory, memmove, "(Ljava/lang/Object;ILjava/lang/Object;IJ)V"),
     FAST_NATIVE_METHOD(Memory, peekByte, "(J)B"),
-    NATIVE_METHOD(Memory, peekByteArray, "(J[BII)V"),
-    NATIVE_METHOD(Memory, peekCharArray, "(J[CIIZ)V"),
-    NATIVE_METHOD(Memory, peekDoubleArray, "(J[DIIZ)V"),
-    NATIVE_METHOD(Memory, peekFloatArray, "(J[FIIZ)V"),
     FAST_NATIVE_METHOD(Memory, peekIntNative, "(J)I"),
-    NATIVE_METHOD(Memory, peekIntArray, "(J[IIIZ)V"),
     FAST_NATIVE_METHOD(Memory, peekLongNative, "(J)J"),
-    NATIVE_METHOD(Memory, peekLongArray, "(J[JIIZ)V"),
     FAST_NATIVE_METHOD(Memory, peekShortNative, "(J)S"),
-    NATIVE_METHOD(Memory, peekShortArray, "(J[SIIZ)V"),
     FAST_NATIVE_METHOD(Memory, pokeByte, "(JB)V"),
     NATIVE_METHOD(Memory, pokeByteArray, "(J[BII)V"),
     NATIVE_METHOD(Memory, pokeCharArray, "(J[CIIZ)V"),
diff --git a/luni/src/test/java/libcore/android/compat/CompatibilityTest.java b/luni/src/test/java/libcore/android/compat/CompatibilityTest.java
new file mode 100644
index 0000000..40ed9e6
--- /dev/null
+++ b/luni/src/test/java/libcore/android/compat/CompatibilityTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 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.android.compat;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.compat.Compatibility;
+import android.compat.Compatibility.BehaviorChangeDelegate;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class CompatibilityTest {
+
+    @Test
+    public void testBehaviorChangeDelegate() {
+        long changeId = 1L;
+        BehaviorChangeDelegate defaultDelegate = new BehaviorChangeDelegate() {};
+
+        // default implementation should not throw exception
+        defaultDelegate.onChangeReported(changeId);
+        assertTrue(defaultDelegate.isChangeEnabled(changeId));
+    }
+
+    @Test
+    public void testReportUnconditionalChange() {
+        long changeId = 1L;
+        BehaviorChangeDelegate delegate = mock(BehaviorChangeDelegate.class);
+        Compatibility.setBehaviorChangeDelegate(delegate);
+
+        Compatibility.reportUnconditionalChange(changeId);
+        verify(delegate).onChangeReported(changeId);
+    }
+
+    @Test
+    public void testClearBehaviorChangeDelegate() {
+        long changeId = 1L;
+        BehaviorChangeDelegate delegate = mock(BehaviorChangeDelegate.class);
+        Compatibility.setBehaviorChangeDelegate(delegate);
+
+        Compatibility.clearBehaviorChangeDelegate();
+        Compatibility.reportUnconditionalChange(changeId);
+        verify(delegate, never()).onChangeReported(anyLong());
+    }
+}
diff --git a/luni/src/test/java/libcore/android/system/OsTest.java b/luni/src/test/java/libcore/android/system/OsTest.java
index 56487a7..f3dd685 100755
--- a/luni/src/test/java/libcore/android/system/OsTest.java
+++ b/luni/src/test/java/libcore/android/system/OsTest.java
@@ -31,12 +31,14 @@
 import android.system.UnixSocketAddress;
 import android.system.VmSocketAddress;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.Inet4Address;
@@ -56,10 +58,12 @@
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import java.util.stream.Collectors;
 import libcore.io.IoUtils;
 import libcore.testing.io.TestIoUtils;
 import org.junit.Test;
@@ -822,6 +826,41 @@
         checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1"));
     }
 
+    private static short asShort(StructCmsghdr cmsg) {
+        ByteBuffer buf = ByteBuffer.wrap(cmsg.cmsg_data).order(ByteOrder.nativeOrder());
+        assertEquals(Short.BYTES, buf.capacity());
+        return buf.getShort();
+    }
+
+    private static int asInt(StructCmsghdr cmsg) {
+        ByteBuffer buf = ByteBuffer.wrap(cmsg.cmsg_data).order(ByteOrder.nativeOrder());
+        assertEquals(Integer.BYTES, buf.capacity());
+        return buf.getInt();
+    }
+
+    @Test
+    public void test_StructCmsgHdrConstructors() throws Exception {
+        final StructCmsghdr cmsg1 = new StructCmsghdr(1, 2, (short) 32005);
+        assertEquals(1, cmsg1.cmsg_level);
+        assertEquals(2, cmsg1.cmsg_type);
+        assertEquals(32005, asShort(cmsg1));
+
+        ByteBuffer buf = ByteBuffer.allocate(Short.BYTES);
+        buf.order(ByteOrder.nativeOrder());
+        buf.putShort((short) 32005);
+        assertArrayEquals(cmsg1.cmsg_data, buf.array());
+
+        buf = ByteBuffer.allocate(Integer.BYTES);
+        buf.order(ByteOrder.nativeOrder());
+        buf.putInt(1000042);
+
+        final StructCmsghdr cmsg2 = new StructCmsghdr(456789, 123456, buf.array());
+        assertEquals(456789, cmsg2.cmsg_level);
+        assertEquals(123456, cmsg2.cmsg_type);
+        assertEquals(1000042, asInt(cmsg2));
+        assertArrayEquals(buf.array(), cmsg2.cmsg_data);
+    }
+
     /*
      * Test case for sendmsg with/without GSO in loopback iface,
      * recvmsg/gro would not happen since in loopback
@@ -1530,29 +1569,31 @@
 
     @Test
     public void test_socket_setSockoptTimeval_effective() throws Exception {
-        // b/176104885 Older devices can return a few ms early, add a tolerance for them
-        long timeoutTolerance = kernelIsAtLeast(3, 18) ? 0 : 10;
-
-        int timeoutValueMillis = 250;
-        int allowedTimeoutMillis = 3000;
+        final int TIMEOUT_VALUE_MILLIS = 250;
+        final int ALLOWED_TIMEOUT_MILLIS = 3000;
+        final int ROUNDING_ERROR_MILLIS = 10;
 
         FileDescriptor fd = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
         try {
-            StructTimeval tv = StructTimeval.fromMillis(timeoutValueMillis);
+            // Configure the receive timeout.
+            StructTimeval tv = StructTimeval.fromMillis(TIMEOUT_VALUE_MILLIS);
             Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, tv);
-            Os.bind(fd, InetAddress.getByName("::1"), 0);
 
+            // Bind socket and wait for data (and timeout).
+            Os.bind(fd, InetAddress.getByName("::1"), 0);
             byte[] request = new byte[1];
             long startTime = System.nanoTime();
             expectException(() -> Os.read(fd, request, 0, request.length),
                     ErrnoException.class, EAGAIN, "Expected timeout");
             long durationMillis = Duration.ofNanos(System.nanoTime() - startTime).toMillis();
-            assertTrue("Timeout of " + timeoutValueMillis + "ms returned after "
-                    + durationMillis +"ms",
-                durationMillis >= timeoutValueMillis - timeoutTolerance);
-            assertTrue("Timeout of " + timeoutValueMillis + "ms failed to return within "
-                    + allowedTimeoutMillis  + "ms",
-                durationMillis < allowedTimeoutMillis);
+
+            // Our requested timeout may be rounded by the kernel (b/176104885, b/216667550).
+            // We allow up to 1 scheduling quantum difference (assuming HZ = 100).
+            assertTrue("Timeout of " + tv.toMillis() + "ms returned after " + durationMillis + "ms",
+                       durationMillis >= tv.toMillis() - ROUNDING_ERROR_MILLIS);
+            assertTrue("Timeout of " + TIMEOUT_VALUE_MILLIS + "ms failed to return within "
+                    + ALLOWED_TIMEOUT_MILLIS  + "ms",
+                       durationMillis < ALLOWED_TIMEOUT_MILLIS);
         } finally {
             Os.close(fd);
         }
@@ -2061,4 +2102,160 @@
         expectException(() -> Os.memfd_create("test_memfd", 0xffff), ErrnoException.class, EINVAL,
                 "memfd_create(\"test_memfd\", 0xffff)");
     }
+
+    @Test
+    public void environmentsInitiallyEqual() throws Exception {
+        assertEnvironmentsEqual();
+    }
+
+    @Test
+    public void getSetUnsetenvEnviron_Success() throws Exception {
+        String variable1 = "OSTEST_VARIABLE1";
+        String variable2 = "OSTEST_VARIABLE2";
+        String value1 = "value1";
+        String value2 = "value2";
+
+        // Initial state, the test variables should not be set anywhere
+        assertNull(System.getenv(variable1));
+        assertNull(System.getenv(variable2));
+        assertNull(Os.getenv(variable1));
+        assertNull(Os.getenv(variable2));
+
+        // Set and get
+        Os.setenv(variable1, value1, false);
+        Os.setenv(variable2, value2, false);
+        assertEquals(value1, Os.getenv(variable1));
+        assertEquals(value2, Os.getenv(variable2));
+        assertEquals(value1, System.getenv(variable1));
+        assertEquals(value2, System.getenv(variable2));
+        // Comparing environments indirectly tests Os.environ()
+        assertEnvironmentsEqual();
+
+        // Update values with overwrite flag set to false - should be a no-op
+        Os.setenv(variable1, value2, false);
+        Os.setenv(variable2, value1, false);
+        assertEquals(value1, Os.getenv(variable1));
+        assertEquals(value2, Os.getenv(variable2));
+        assertEquals(value1, System.getenv(variable1));
+        assertEquals(value2, System.getenv(variable2));
+        assertEnvironmentsEqual();
+
+        // Update values (swap value1 and value2)
+        Os.setenv(variable1, value2, true);
+        Os.setenv(variable2, value1, true);
+        assertEquals(value2, Os.getenv(variable1));
+        assertEquals(value1, Os.getenv(variable2));
+        assertEquals(value2, System.getenv(variable1));
+        assertEquals(value1, System.getenv(variable2));
+        assertEnvironmentsEqual();
+
+        // Unset
+        Os.unsetenv(variable1);
+        Os.unsetenv(variable2);
+        assertNull(System.getenv(variable1));
+        assertNull(System.getenv(variable2));
+        assertNull(Os.getenv(variable1));
+        assertNull(Os.getenv(variable2));
+        assertEnvironmentsEqual();
+    }
+
+    @Test
+    public void setenv() {
+        expectException(() -> Os.setenv(null, null, true), NullPointerException.class, null,
+            "setenv(null, null, true)");
+
+        expectException(() -> Os.setenv(null, "value", true), NullPointerException.class, null,
+            "setenv(null, value, true)");
+
+        expectException(() -> Os.setenv("a", null, true), NullPointerException.class, null,
+            "setenv(\"a\", null, true)");
+
+        expectException(() -> Os.setenv("", "value", true), ErrnoException.class, EINVAL,
+            "setenv(\"\", value, true)");
+
+        expectException(() -> Os.setenv("a=b", "value", true), ErrnoException.class, EINVAL,
+            "setenv(\"a=b\", value, true)");
+
+        expectException(() -> Os.setenv(null, null, false), NullPointerException.class, null,
+            "setenv(null, null, false)");
+
+        expectException(() -> Os.setenv(null, "value", false), NullPointerException.class, null,
+            "setenv(null, value, false)");
+
+        expectException(() -> Os.setenv("a", null, false), NullPointerException.class, null,
+            "setenv(\"a\", null, false)");
+
+        expectException(() -> Os.setenv("", "value", false), ErrnoException.class, EINVAL,
+            "setenv(\"\", value, false)");
+
+        expectException(() -> Os.setenv("a=b", "value", false), ErrnoException.class, EINVAL,
+            "setenv(\"a=b\", value, false)");
+    }
+
+    @Test
+    public void getenv() {
+        assertNotNull(Os.getenv("PATH"));
+        assertNull(Os.getenv("This can't possibly exist but is valid"));
+        assertNull(Os.getenv("so=is=this"));
+
+        expectException(() ->Os.getenv(null), NullPointerException.class, null,
+            "getenv(null)");
+    }
+
+    @Test
+    public void unsetenv() {
+        expectException(() -> Os.unsetenv(null), NullPointerException.class, null,
+            "unsetenv(null)");
+
+        expectException(() -> Os.unsetenv(""), ErrnoException.class, EINVAL,
+            "unsetenv(\"\")");
+
+        expectException(() -> Os.unsetenv("a=b"), ErrnoException.class, EINVAL,
+            "unsetenv(\"a=b\")");
+    }
+
+    /*
+     * Checks that all ways of accessing the environment are consistent by collecting:
+     * osEnvironment      - The environment returned by Os.environ()
+     * systemEnvironment  - The environment returned by System.getenv()
+     * processEnvironment - The environment that will be passed to sub-processes via
+     *                      ProcessBuilder
+     * execedEnvironment  - The actual environment passed to an execed instance of env
+     *
+     * All are converted to a sorted list of strings of the form "NAME=VALUE" for comparison.
+     */
+    private void assertEnvironmentsEqual() throws IOException {
+        List<String> osEnvironment = stringArrayToList(Os.environ());
+        List<String> systemEnvironment = stringMapToList(System.getenv());
+
+        ProcessBuilder pb = new ProcessBuilder("env");
+        List<String> processEnvironment = stringMapToList(pb.environment());
+
+        BufferedReader reader = new BufferedReader(
+            new InputStreamReader(pb.start().getInputStream()));
+
+        List<String> execedEnvironment = reader
+            .lines()
+            .sorted()
+            .collect(Collectors.toList());
+
+        assertEquals(osEnvironment, systemEnvironment);
+        assertEquals(osEnvironment, processEnvironment);
+        assertEquals(osEnvironment, execedEnvironment);
+    }
+
+    private List<String> stringMapToList(Map<String, String> stringMap) {
+        return stringMap
+            .entrySet()
+            .stream()
+            .map(e -> e.getKey() + "=" + e.getValue())
+            .sorted()
+            .collect(Collectors.toList());
+    }
+
+    private List<String> stringArrayToList(String[] stringArray) {
+        List<String> result = Arrays.asList(stringArray);
+        Collections.sort(result);
+        return result;
+    }
 }
diff --git a/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java b/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java
index 7d3b6f2..064e042 100644
--- a/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java
+++ b/luni/src/test/java/libcore/dalvik/system/BaseDexClassLoaderTest.java
@@ -17,6 +17,7 @@
 package libcore.dalvik.system;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
@@ -234,6 +235,62 @@
     }
 
     @Test
+    public void testReporting_withSharedLibraries_loaded_after() throws Exception {
+        final ClassLoader parent = ClassLoader.getSystemClassLoader();
+        final ClassLoader sharedLoaders[] = new ClassLoader[] {
+                new PathClassLoader(jar2.getPath(), /* librarySearchPath */ null, parent),
+        };
+        // Reset so we don't get load reports from creating the shared library CL
+        reporter.reset();
+
+        BaseDexClassLoader bdcl = new PathClassLoader(
+                jar.getPath(), null, parent, null, sharedLoaders);
+
+        assertEquals(1, reporter.loadedDexMapping.size());
+
+        String[] contexts = separateSystemClassLoaderContext(
+                reporter.loadedDexMapping.get(jar.getPath()));
+        // We cannot fully verify the context of the system class loader because its classpath
+        // may vary based on system properties and whether or not we are in a test environment.
+        assertTrue(contexts[1].startsWith("PCL["));
+        // Verify the context for the loaded dex files. The system class loader should be part
+        // of the shared library class loader.
+        assertEquals("PCL[]{~PCL[" + jar2.getPath() + "];" + contexts[1] + "}",
+                contexts[0]);
+    }
+
+    @Test
+    public void testReporting_withSharedLibraries_loaded_before_and_after() throws Exception {
+        final ClassLoader parent = ClassLoader.getSystemClassLoader();
+        final String sharedJarPath = resourcesMap.get("parent.jar").getAbsolutePath();
+        final String sharedJarPath2 = resourcesMap.get("child.jar").getAbsolutePath();
+        final ClassLoader sharedLoaders[] = new ClassLoader[] {
+                new PathClassLoader(sharedJarPath, /* librarySearchPath */ null, parent),
+        };
+        final ClassLoader sharedLoadersAfter[] = new ClassLoader[] {
+                new PathClassLoader(sharedJarPath2, /* librarySearchPath */ null, parent),
+        };
+        // Reset so we don't get load reports from creating the shared library CL
+        reporter.reset();
+
+        BaseDexClassLoader bdcl = new PathClassLoader(jar.getPath(), null, parent, sharedLoaders,
+                sharedLoadersAfter);
+
+        assertEquals(1, reporter.loadedDexMapping.size());
+
+        String[] contexts = separateSystemClassLoaderContext(
+                reporter.loadedDexMapping.get(jar.getPath()));
+        // We cannot fully verify the context of the system class loader because its classpath
+        // may vary based on system properties and whether or not we are in a test environment.
+        assertTrue(contexts[1].startsWith("PCL["));
+        // Verify the context for the loaded dex files. The system class loader should be part
+        // of the shared library class loader.
+        assertEquals("PCL[]{PCL[" + sharedJarPath + "];" + contexts[1]
+                        + "#~PCL[" + sharedJarPath2 + "];" + contexts[1] + "}",
+                contexts[0]);
+    }
+
+    @Test
     public void testReporting_multipleJars_withSharedLibraries() throws Exception {
         final ClassLoader parent = ClassLoader.getSystemClassLoader();
         final String sharedJarPath = resourcesMap.get("parent.jar").getAbsolutePath();
@@ -277,6 +334,49 @@
     }
 
     @Test
+    public void testReporting_multipleJars_withSharedLibraries_loaded_after() throws Exception {
+        final ClassLoader parent = ClassLoader.getSystemClassLoader();
+        final String sharedJarPath = resourcesMap.get("parent.jar").getAbsolutePath();
+        final ClassLoader sharedLoaders[] = new ClassLoader[] {
+                new PathClassLoader(sharedJarPath, /* librarySearchPath */ null, parent),
+        };
+        // Reset so we don't get load reports from creating the shared library CL
+        reporter.reset();
+
+        BaseDexClassLoader bdcl = new PathClassLoader(
+                String.join(File.pathSeparator, jar.getPath(), jar2.getPath()),
+                null, parent, null, sharedLoaders);
+
+        assertEquals(2, reporter.loadedDexMapping.size());
+
+
+        // Verify the first jar.
+        String[] contexts = separateSystemClassLoaderContext(
+                reporter.loadedDexMapping.get(jar.getPath()));
+        String contextSuffix = "{~PCL[" + sharedJarPath + "];" + contexts[1] + "}";
+
+        // We cannot fully verify the context of the system class loader because its classpath
+        // may vary based on system properties and whether or not we are in a test environment.
+        assertTrue(contexts[1].startsWith("PCL["));
+        // Verify the context for the loaded dex files.
+        assertEquals("PCL[]" + contextSuffix, contexts[0]);
+        // We cannot fully verify the context of the system class loader because its classpath
+        // may vary based on system properties and whether or not we are in a test environment.
+        assertTrue(contexts[1].startsWith("PCL["));
+
+        // Verify the second jar.
+        String[] contexts2 = separateSystemClassLoaderContext(
+                reporter.loadedDexMapping.get(jar2.getPath()));
+        String contextSuffix2 = "{~PCL[" + sharedJarPath + "];" + contexts2[1] + "}";
+
+        // Verify the context for the loaded dex files.
+        assertEquals("PCL[" + jar.getPath() + "]" + contextSuffix2, contexts2[0]);
+        // We cannot fully verify the context of the system class loader because its classpath
+        // may vary based on system properties and whether or not we are in a test environment.
+        assertTrue(contexts2[1].startsWith("PCL[")) ;
+    }
+
+    @Test
     public void testReporting_emptyPath() throws Exception {
         BaseDexClassLoader cl1 = new PathClassLoader("", ClassLoader.getSystemClassLoader());
         assertEquals(Map.<String, String>of(), reporter.loadedDexMapping);
@@ -345,6 +445,16 @@
         loader = new DelegateLastClassLoader("", null, parent, sharedLibraries);
         assertEquals("parent", readResource(loader, "resource.txt"));
         checkResources(loader);
+
+        // PCL[]{~PCL[parent.jar]#~PCL[child.jar]}
+        loader = new PathClassLoader("", null, parent, null, sharedLibraries);
+        assertEquals("parent", readResource(loader, "resource.txt"));
+        checkResources(loader);
+
+        // DLC[]{~PCL[parent.jar]#~PCL[child.jar]}
+        loader = new DelegateLastClassLoader("", null, parent, null, sharedLibraries);
+        assertEquals("parent", readResource(loader, "resource.txt"));
+        checkResources(loader);
     }
 
     @Test
@@ -370,6 +480,16 @@
         loader = new DelegateLastClassLoader("", null, parent, sharedLibraries);
         assertEquals("child", readResource(loader, "resource.txt"));
         checkResources(loader);
+
+        // PCL[]{~PCL[child.jar]#~PCL[parent.jar]}
+        loader = new PathClassLoader("", null, parent, null, sharedLibraries);
+        assertEquals("child", readResource(loader, "resource.txt"));
+        checkResources(loader);
+
+        // DLC[]{~PCL[child.jar]#~PCL[parent.jar]}
+        loader = new DelegateLastClassLoader("", null, parent, null, sharedLibraries);
+        assertEquals("child", readResource(loader, "resource.txt"));
+        checkResources(loader);
     }
 
     @Test
@@ -398,6 +518,16 @@
         loader = new DelegateLastClassLoader("", null, parent, sharedLibraryLevel1);
         assertEquals("parent", readResource(loader, "resource.txt"));
         checkResources(loader);
+
+        // PCL[]{~PCL[child.jar]{PCL[parent.jar]}}
+        loader = new PathClassLoader("", null, parent, null, sharedLibraryLevel1);
+        assertEquals("parent", readResource(loader, "resource.txt"));
+        checkResources(loader);
+
+        // DLC[]{~PCL[child.jar]{PCL[parent.jar]}}
+        loader = new DelegateLastClassLoader("", null, parent, null, sharedLibraryLevel1);
+        assertEquals("parent", readResource(loader, "resource.txt"));
+        checkResources(loader);
     }
 
     @Test
@@ -426,6 +556,16 @@
         loader = new DelegateLastClassLoader("", null, parent, sharedLibraryLevel1);
         assertEquals("child", readResource(loader, "resource.txt"));
         checkResources(loader);
+
+        // PCL[]{~PCL[parent.jar]{PCL[child.jar]}}
+        loader = new PathClassLoader("", null, parent, null, sharedLibraryLevel1);
+        assertEquals("child", readResource(loader, "resource.txt"));
+        checkResources(loader);
+
+        // DLC[]{~PCL[parent.jar]{PCL[child.jar]}}
+        loader = new DelegateLastClassLoader("", null, parent, null, sharedLibraryLevel1);
+        assertEquals("child", readResource(loader, "resource.txt"));
+        checkResources(loader);
     }
 
     @Test
@@ -448,12 +588,163 @@
         // Check that the parent was queried first.
         assertEquals("parent", readResource(pathLoader, "resource.txt"));
 
+        // PCL[]{~PCL[child.jar]};PCL[parent.jar]
+        pathLoader = new PathClassLoader("", null, parent, null, sharedLibrary);
+
+        // Check that the parent was queried first.
+        assertEquals("parent", readResource(pathLoader, "resource.txt"));
+
         // DLC[]{PCL[child.jar]};PCL[parent.jar]
         ClassLoader delegateLast = new DelegateLastClassLoader("", null, parent, sharedLibrary);
 
         // Check that the shared library was queried first.
         assertEquals("child", readResource(delegateLast, "resource.txt"));
 
+        // DLC[]{~PCL[child.jar]};PCL[parent.jar]
+        delegateLast = new DelegateLastClassLoader("", null, parent, null, sharedLibrary);
+
+        // Check that the shared library was queried first.
+        assertEquals("child", readResource(delegateLast, "resource.txt"));
+
+    }
+
+    @Test
+    public void testGetResourceSharedLibraries6() throws Exception {
+        File parentPath = resourcesMap.get("parent.jar");
+        File childPath = resourcesMap.get("child.jar");
+        assertTrue(parentPath != null);
+        assertTrue(childPath != null);
+
+        ClassLoader parent = Object.class.getClassLoader();
+
+        ClassLoader[] sharedLibrary = {
+                new PathClassLoader(childPath.getAbsolutePath(), null, parent),
+        };
+
+        // PCL[]{PCL[child.jar]};PCL[parent.jar]
+        ClassLoader pathLoader = new PathClassLoader(
+                parentPath.getAbsolutePath(), null, parent, sharedLibrary);
+
+        // Check that the parent was queried first.
+        assertEquals("child", readResource(pathLoader, "resource.txt"));
+
+        // PCL[]{~PCL[child.jar]};PCL[parent.jar]
+        pathLoader = new PathClassLoader(
+                parentPath.getAbsolutePath(), null, parent, null, sharedLibrary);
+
+        // Check that the parent was queried first.
+        assertEquals("parent", readResource(pathLoader, "resource.txt"));
+        // confirm resource from shard lib is available
+        checkResources(pathLoader);
+
+        // PCL[]{~PCL[child.jar]};PCL[]
+        pathLoader = new PathClassLoader("", null, parent, null, sharedLibrary);
+        // Check that the shared library was queried last.
+        assertEquals("child", readResource(pathLoader, "resource.txt"));
+
+        // DLC[]{PCL[child.jar]};PCL[parent.jar]
+        ClassLoader delegateLast = new DelegateLastClassLoader(
+                parentPath.getAbsolutePath(), null, parent, sharedLibrary);
+
+        // Check that the shared library was queried first.
+        assertEquals("child", readResource(delegateLast, "resource.txt"));
+
+        // DLC[]{~PCL[child.jar]};PCL[parent.jar]
+        delegateLast = new DelegateLastClassLoader(
+                parentPath.getAbsolutePath(), null, parent, null, sharedLibrary);
+
+        // Check that the shared library was queried first.
+        assertEquals("parent", readResource(delegateLast, "resource.txt"));
+        // confirm resource from shard lib is available
+        checkResources(delegateLast);
+
+        // DLC[]{~PCL[child.jar]};PCL[]
+        delegateLast = new DelegateLastClassLoader("", null, parent, null, sharedLibrary);
+        // Check that the shared library was queried last.
+        assertEquals("child", readResource(delegateLast, "resource.txt"));
+
+    }
+
+    @Test
+    public void testGetResourceSharedLibraries7() throws Exception {
+        File parentPath = resourcesMap.get("parent.jar");
+        File childPath = resourcesMap.get("child.jar");
+        assertTrue(parentPath != null);
+        assertTrue(childPath != null);
+
+        ClassLoader parent = Object.class.getClassLoader();
+
+        ClassLoader[] sharedLibrary1 = {
+                new PathClassLoader(parentPath.getAbsolutePath(), null, parent),
+        };
+
+        ClassLoader[] sharedLibrary2 = {
+                new PathClassLoader(childPath.getAbsolutePath(), null, parent),
+        };
+
+        // PCL[]{PCL[parent.jar]#~PCL[child.jar]}
+        ClassLoader loader = new PathClassLoader("", null, parent, sharedLibrary1, sharedLibrary2);
+        assertEquals("parent", readResource(loader, "resource.txt"));
+        checkResources(loader);
+
+        // PCL[]{PCL[child.jar]#~PCL[parent.jar]}
+        loader = new PathClassLoader("", null, parent, sharedLibrary2, sharedLibrary1);
+        assertEquals("child", readResource(loader, "resource.txt"));
+        checkResources(loader);
+
+        loader = new DelegateLastClassLoader("", null, parent, sharedLibrary1, sharedLibrary2);
+        assertEquals("parent", readResource(loader, "resource.txt"));
+        checkResources(loader);
+
+        // PCL[]{PCL[child.jar]#~PCL[parent.jar]}
+        loader = new DelegateLastClassLoader("", null, parent, sharedLibrary2, sharedLibrary1);
+        assertEquals("child", readResource(loader, "resource.txt"));
+        checkResources(loader);
+    }
+
+    @Test
+    public void testLookupOrder_loadClass() throws Exception {
+        File parentPath = resourcesMap.get("parent.jar");
+        File childPath = resourcesMap.get("child.jar");
+        assertTrue(parentPath != null);
+        assertTrue(childPath != null);
+
+        ClassLoader parent = Object.class.getClassLoader();
+
+        ClassLoader[] sharedLibrary1 = {
+                new PathClassLoader(parentPath.getAbsolutePath(), null, parent),
+        };
+
+        ClassLoader[] sharedLibrary2 = {
+                new PathClassLoader(childPath.getAbsolutePath(), null, parent),
+        };
+
+        // PCL[]{PCL[parent.jar]#~PCL[child.jar]}
+        ClassLoader loader = new PathClassLoader("", null, parent, sharedLibrary1, sharedLibrary2);
+        assertEquals("A_parent", callMethod(loader, "toString", sharedLibrary1[0]));
+        Class<?> parentClass = loader.loadClass("libcore.test.delegatelast.Parent");
+        assertSame(sharedLibrary1[0], parentClass.getClassLoader());
+        Class<?> childClass = loader.loadClass("libcore.test.delegatelast.Child");
+        assertSame(sharedLibrary2[0], childClass.getClassLoader());
+
+
+        // Note that the order is reversed here. "parent" is looked up before "child".
+        loader = new PathClassLoader("", null, parent, sharedLibrary2, sharedLibrary1);
+        assertEquals("A_child", callMethod(loader, "toString", sharedLibrary2[0]));
+        parentClass = loader.loadClass("libcore.test.delegatelast.Parent");
+        assertSame(sharedLibrary1[0], parentClass.getClassLoader());
+        childClass = loader.loadClass("libcore.test.delegatelast.Child");
+        assertSame(sharedLibrary2[0], childClass.getClassLoader());
+    }
+
+    private static String callMethod(ClassLoader cl, String name, ClassLoader srcofclass)
+            throws Exception {
+        Class<?> clazz = cl.loadClass("libcore.test.delegatelast.A");
+        assertSame(srcofclass, clazz.getClassLoader());
+
+        Method method = clazz.getMethod(name);
+        Object obj = clazz.newInstance();
+        return (String) method.invoke(obj);
     }
 
     @Test
diff --git a/luni/src/test/java/libcore/dalvik/system/ClassLoaderTestSupport.java b/luni/src/test/java/libcore/dalvik/system/ClassLoaderTestSupport.java
index 27f5d7c..3182aa0 100644
--- a/luni/src/test/java/libcore/dalvik/system/ClassLoaderTestSupport.java
+++ b/luni/src/test/java/libcore/dalvik/system/ClassLoaderTestSupport.java
@@ -65,7 +65,7 @@
                 if (file.isDirectory()) {
                     cleanUpDir(file);
                 } else {
-                    assertTrue(file.delete());
+                    file.delete();
                 }
             }
         }
diff --git a/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java b/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java
index c17fad7..5437ef4 100644
--- a/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java
+++ b/luni/src/test/java/libcore/dalvik/system/EmulatedStackFrameTest.java
@@ -55,6 +55,71 @@
         assertEquals("foo", reader.nextReference(String.class));
     }
 
+    public void testRandomReaderWriter_allParamTypes() {
+        EmulatedStackFrame stackFrame = EmulatedStackFrame.create(MethodType.methodType(
+                void.class,
+                new Class<?>[] { Integer.class, boolean.class, char.class, short.class, int.class,
+                        long.class, Byte.class, float.class, double.class, String.class }));
+
+        EmulatedStackFrame.StackFrameWriter writer = new EmulatedStackFrame.StackFrameWriter();
+        writer.attach(stackFrame);
+
+        writer.putNextReference(Integer.valueOf(-2), Integer.class);
+        writer.putNextBoolean(true);
+        writer.putNextChar('a');
+        writer.putNextShort((short) 42);
+        writer.putNextInt(43);
+        writer.putNextLong(56);
+        writer.putNextReference(Byte.valueOf((byte) 7), Byte.class);
+        writer.putNextFloat(42.0f);
+        writer.putNextDouble(52.0);
+        writer.putNextReference("foo", String.class);
+
+        EmulatedStackFrame.RandomOrderStackFrameReader reader =
+            new EmulatedStackFrame.RandomOrderStackFrameReader();
+        reader.attach(stackFrame);
+
+        final int parameterCount = stackFrame.getMethodType().parameterCount();
+        for (int i = 0; i < 100; ++i) {
+            int argumentIndex = (i * 13) % parameterCount;
+            reader.moveTo(argumentIndex);
+            switch (argumentIndex) {
+                case 0:
+                    assertEquals(Integer.valueOf(-2), reader.nextReference(Integer.class));
+                    break;
+                case 1:
+                    assertTrue(reader.nextBoolean());
+                    break;
+                case 2:
+                    assertEquals('a', reader.nextChar());
+                    break;
+                case 3:
+                    assertEquals((short) 42, reader.nextShort());
+                    break;
+                case 4:
+                    assertEquals(43, reader.nextInt());
+                    break;
+                case 5:
+                    assertEquals(56, reader.nextLong());
+                    break;
+                case 6:
+                    assertEquals(Byte.valueOf((byte) 7), reader.nextReference(Byte.class));
+                    break;
+                case 7:
+                    assertEquals(42.0f, reader.nextFloat());
+                    break;
+                case 8:
+                    assertEquals(52.0, reader.nextDouble());
+                    break;
+                case 9:
+                    assertEquals("foo", reader.nextReference(String.class));
+                    break;
+                default:
+                    throw new IllegalStateException("Bad index");
+            }
+        }
+    }
+
     public void testReaderWriter_allReturnTypes() {
         EmulatedStackFrame stackFrame = EmulatedStackFrame.create(
                 MethodType.methodType(boolean.class));
@@ -195,7 +260,7 @@
         } catch (IllegalArgumentException expected) {
         }
 
-        // Should succeeed.
+        // Should succeed.
         assertFalse(reader.nextBoolean());
 
         // The next attempt should fail.
@@ -215,7 +280,7 @@
         } catch (IllegalArgumentException expected) {
         }
 
-        // Should succeeed.
+        // Should succeed.
         writer.putNextBoolean(true);
 
         // The next attempt should fail.
@@ -225,4 +290,13 @@
         } catch (IllegalArgumentException expected) {
         }
     }
+
+    public void testGetSetReference() {
+        EmulatedStackFrame stackFrame = EmulatedStackFrame.create(MethodType.methodType(
+            void.class, new Class<?>[] { Integer.class, boolean.class, String.class }));
+        stackFrame.setReference(0, Integer.valueOf(-1));
+        assertEquals(Integer.valueOf(-1), stackFrame.getReference(0, Integer.class));
+        stackFrame.setReference(2, "Hello");
+        assertEquals("Hello", stackFrame.getReference(2, String.class));
+    }
 }
diff --git a/luni/src/test/java/libcore/highmemorytest/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/highmemorytest/libcore/icu/LocaleDataTest.java
deleted file mode 100644
index ab396f9..0000000
--- a/luni/src/test/java/libcore/highmemorytest/libcore/icu/LocaleDataTest.java
+++ /dev/null
@@ -1,48 +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 libcore.highmemorytest.libcore.icu;
-
-import static org.junit.Assert.assertTrue;
-
-import libcore.icu.LocaleData;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.util.Locale;
-
-@RunWith(Parameterized.class)
-public class LocaleDataTest {
-
-    @Parameterized.Parameters(name = "{0}")
-    public static Locale[] getAllLocales() {
-        return Locale.getAvailableLocales();
-    }
-
-    @Parameterized.Parameter(0)
-    public Locale locale;
-
-    @Test
-    public void testLongDateTimeFormat() {
-        LocaleData d = LocaleData.get(locale);
-        int dateLength = d.longDateFormat.length();
-        assertTrue("LocaleData.longDateFormat has zero length: " + dateLength, dateLength != 0);
-        int timeLength = d.longTimeFormat.length();
-        assertTrue("LocaleData.longTimeFormat has zero length: " + timeLength, timeLength != 0);
-    }
-}
diff --git a/luni/src/test/java/libcore/highmemorytest/libcore/icu/SimpleDateFormatDataTest.java b/luni/src/test/java/libcore/highmemorytest/libcore/icu/SimpleDateFormatDataTest.java
new file mode 100644
index 0000000..687f73e
--- /dev/null
+++ b/luni/src/test/java/libcore/highmemorytest/libcore/icu/SimpleDateFormatDataTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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 libcore.highmemorytest.libcore.icu;
+
+import static org.junit.Assert.assertNotEquals;
+
+import java.text.DateFormat;
+
+import libcore.icu.SimpleDateFormatData;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Locale;
+
+@RunWith(Parameterized.class)
+public class SimpleDateFormatDataTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Locale[] getAllLocales() {
+        return Locale.getAvailableLocales();
+    }
+
+    @Parameterized.Parameter(0)
+    public Locale locale;
+
+    @Test
+    public void testLongDateTimeFormat() {
+        SimpleDateFormatData d = SimpleDateFormatData.getInstance(locale);
+
+        assertNotEquals(0, d.getDateFormat(DateFormat.FULL).length());
+        assertNotEquals(0, d.getDateFormat(DateFormat.LONG).length());
+        assertNotEquals(0, d.getDateFormat(DateFormat.MEDIUM).length());
+        assertNotEquals(0, d.getDateFormat(DateFormat.SHORT).length());
+
+        assertNotEquals(0, d.getTimeFormat(DateFormat.FULL).length());
+        assertNotEquals(0, d.getTimeFormat(DateFormat.LONG).length());
+        assertNotEquals(0, d.getTimeFormat(DateFormat.MEDIUM).length());
+        assertNotEquals(0, d.getTimeFormat(DateFormat.SHORT).length());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/ConsoleTest.java b/luni/src/test/java/libcore/java/io/ConsoleTest.java
new file mode 100644
index 0000000..36d382f
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/ConsoleTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Console;
+import java.io.IOError;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Constructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ConsoleTest {
+
+    private Console createConsole(InputStream inStream, OutputStream outStream) throws Exception {
+        Constructor<Console> constructor =
+            Console.class.getDeclaredConstructor(InputStream.class, OutputStream.class);
+        constructor.setAccessible(true);
+        return constructor.newInstance(inStream, outStream);
+    }
+
+    private boolean isTty() {
+        // It is important for some tests to know if it is running in an environment where tty is
+        // available or not. This is because some API calls end up calling the native echo()
+        // function which throws an exception if tty is not available.
+        // The Console.isTty() method is private, however an option to check, without reflection, if
+        // tty is available is to see if console() return null or not. The function will always
+        // return an instance of Console if isTty() is true, or null otherwise.
+        return (Console.console() != null);
+    }
+
+    @Test
+    public void testReadPassword() throws Exception {
+        final byte[] bytes = "secret password\n".getBytes();
+        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        Console console = createConsole(inStream, outStream);
+        try {
+            String password = String.valueOf(console.readPassword());
+            // Due to readPassword depending on echo, which depends on having stdin as a tty, it is
+            // expected that it will throw an IOError if tty is not available
+            assertTrue("readPassword succeeded unexpectedly", isTty());
+            assertEquals("secret password", password);
+        } catch(IOError e) {
+            assertFalse("readPassword threw unexpected IOError", isTty());
+            assertTrue("readPassword exception not as expected",
+                    e.getMessage().contains("Inappropriate ioctl for device"));
+        }
+    }
+
+    @Test
+    public void testReadPasswordWithPrompt() throws Exception {
+        final byte[] bytes = "secret password\n".getBytes();
+        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        Console console = createConsole(inStream, outStream);
+        String username = "Alice";
+        try {
+            String password = String.valueOf(
+                    console.readPassword("%s, please enter your password:", username));
+            // Due to readPassword depending on echo, which depends on having stdin as a tty, it is
+            // expected that it will throw an IOError if tty is not available
+            assertTrue("readPassword succeeded unexpectedly", isTty());
+            assertEquals("secret password", password);
+            String prompt = new String(((ByteArrayOutputStream) outStream).toByteArray());
+            assertEquals("Alice, please enter your password:", prompt);
+        } catch(IOError e) {
+            assertFalse("readPassword threw unexpected IOError", isTty());
+            assertTrue("readPassword exception not as expected",
+                    e.getMessage().contains("Inappropriate ioctl for device"));
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
index 390cfd6..f4ed41d 100644
--- a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
+++ b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
@@ -72,4 +72,11 @@
       Os.close(target);
     }
   }
+
+  public void testGetSetInt$() {
+      FileDescriptor fd = new FileDescriptor();
+      assertEquals(-1, fd.getInt$());
+      fd.setInt$(42);
+      assertEquals(42, fd.getInt$());
+  }
 }
diff --git a/luni/src/test/java/libcore/java/io/FilePermissionTest.java b/luni/src/test/java/libcore/java/io/FilePermissionTest.java
new file mode 100644
index 0000000..cae7b06
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/FilePermissionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FilePermission;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FilePermissionTest {
+
+    @Test
+    public void testImplies() {
+        FilePermission permission = new FilePermission("none", null);
+        // Implementation is stubbed in Android
+        assertTrue(permission.implies(null));
+    }
+
+    @Test
+    public void testGetActions() {
+        FilePermission permission = new FilePermission("none", null);
+        // Implementation is stubbed in Android
+        assertNull(permission.getActions());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/ObjectStreamClassSuidTest.java b/luni/src/test/java/libcore/java/io/ObjectStreamClassSuidTest.java
new file mode 100644
index 0000000..28ab598
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/ObjectStreamClassSuidTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2019 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.io;
+
+import java.io.ObjectStreamClass;
+import java.io.ObjectStreamClass.DefaultSUIDCompatibilityListener;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+import libcore.junit.util.SwitchTargetSdkVersionRule;
+import libcore.junit.util.SwitchTargetSdkVersionRule.TargetSdkVersion;
+import org.junit.FixMethodOrder;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(JUnitParamsRunner.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class ObjectStreamClassSuidTest {
+
+  @Rule
+  public TestRule switchTargetSdkVersionRule = SwitchTargetSdkVersionRule.getInstance();
+
+  /**
+   * The default SUID for this should not be affected by the b/29064453 patch.
+   */
+  public static class BaseWithStaticInitializer implements Serializable {
+    static {
+      System.out.println(
+          "Static initializer for " + BaseWithoutStaticInitializer.class.getCanonicalName());
+    }
+  }
+
+  /**
+   * The default SUID for this should not be affected by the b/29064453 patch.
+   */
+  public static class BaseWithoutStaticInitializer implements Serializable {
+  }
+
+  /**
+   * The default SUID for this should not be affected by the b/29064453 patch.
+   */
+  public static class WithStaticInitializer extends BaseWithoutStaticInitializer {
+    static {
+      System.out.println(
+          "Static initializer for " + WithStaticInitializer.class.getCanonicalName());
+    }
+  }
+
+  /**
+   * The default SUID for this should not be affected by the b/29064453 patch.
+   */
+  public static class WithoutStaticInitializer extends BaseWithoutStaticInitializer {
+  }
+
+  /**
+   * The default SUID for this should be affected by the b/29064453 patch and so should differ
+   * between version <= 23 and version > 23.
+   */
+  public static class InheritStaticInitializer extends BaseWithStaticInitializer {
+  }
+
+  public static Object[][] defaultSUIDs() {
+    return new Object[][] {
+        // The default SUID for BaseWithStaticInitializer should not be affected by the b/29064453
+        // patch.
+        { BaseWithStaticInitializer.class, 1857698805282079740L, 1857698805282079740L },
+
+        // The default SUID for BaseWithoutStaticInitializer should not be affected by the
+        // b/29064453 patch.
+        { BaseWithoutStaticInitializer.class, -4805670618654058372L, -4805670618654058372L },
+
+        // The default SUID for WithStaticInitializer should not be affected by the b/29064453
+        // patch.
+        { WithStaticInitializer.class, 8758222524306909802L, 8758222524306909802L },
+
+        // The default SUID for WithStaticInitializer should not be affected by the
+        // b/29064453 patch.
+        { WithoutStaticInitializer.class, -6923417559496792279L, -6923417559496792279L },
+
+        // The default SUID for the InheritStaticInitializer should be affected by the b/29064453
+        // patch and so should differ between version <= 23 and version > 23.
+        { InheritStaticInitializer.class, 509356435664048990L, -6712883765570708525L },
+    };
+  }
+
+  @Parameters(method = "defaultSUIDs")
+  @Test
+  public void computeDefaultSUID_current(Class<?> clazz, long suid,
+      @SuppressWarnings("unused") long suid23) {
+    checkSerialVersionUID(suid, clazz, false);
+  }
+
+  @Parameters(method = "defaultSUIDs")
+  @Test
+  @TargetSdkVersion(23)
+  public void computeDefaultSUID_targetSdkVersion_23(Class<?> clazz, long suid, long suid23) {
+    // If the suid and suid23 hashes are different then a warning is expected to be logged.
+    boolean expectedWarning = suid23 != suid;
+    checkSerialVersionUID(suid23, clazz, expectedWarning);
+  }
+
+  private static void checkSerialVersionUID(
+      long expectedSUID, Class<?> clazz, boolean expectedWarning) {
+    // Use reflection to call the private static computeDefaultSUID method directly to avoid the
+    // caching performed by ObjectStreamClass.lookup(Class).
+    long defaultSUID;
+    DefaultSUIDCompatibilityListener savedListener
+        = ObjectStreamClass.suidCompatibilityListener;
+    try {
+      ObjectStreamClass.suidCompatibilityListener = (c, hash) -> {
+        // Delegate to the existing listener so that the warning is logged.
+        savedListener.warnDefaultSUIDTargetVersionDependent(clazz, hash);
+        if (expectedWarning) {
+          assertEquals(clazz, c);
+          assertEquals(expectedSUID, hash);
+        } else {
+          fail("Unexpected warning for " + c + " with defaultSUID " + hash);
+        }
+      };
+
+      Method computeDefaultSUIDMethod =
+          ObjectStreamClass.class.getDeclaredMethod("computeDefaultSUID", Class.class);
+      computeDefaultSUIDMethod.setAccessible(true);
+
+      defaultSUID = (Long) computeDefaultSUIDMethod.invoke(null, clazz);
+    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+      throw new IllegalStateException(e);
+    } finally {
+      ObjectStreamClass.suidCompatibilityListener = savedListener;
+    }
+    assertEquals(expectedSUID, defaultSUID);
+  }
+}
diff --git a/luni/src/test/java/libcore/java/io/OldFileWriterTest.java b/luni/src/test/java/libcore/java/io/OldFileWriterTest.java
index 1db9a3e..c68c92e 100644
--- a/luni/src/test/java/libcore/java/io/OldFileWriterTest.java
+++ b/luni/src/test/java/libcore/java/io/OldFileWriterTest.java
@@ -20,6 +20,7 @@
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -77,7 +78,7 @@
         }
     }
 
-    public void test_handleEarlyEOFChar_1() {
+    public void test_handleEarlyEOFChar_1() throws IOException {
         String str = "All work and no play makes Jack a dull boy\n";
         int NUMBER = 2048;
         int j = 0;
@@ -91,27 +92,23 @@
         }
         File f = null;
         FileWriter fw = null;
-        try {
-            f = File.createTempFile("ony", "by_one");
-            fw = new FileWriter(f);
-            fw.write(strChars);
-            fw.close();
-            InputStreamReader in = null;
-            FileInputStream fis = new FileInputStream(f);
-            in = new InputStreamReader(fis);
-            int b;
-            int errors = 0;
-            for (int offset = 0; offset < strChars.length; ++offset) {
-                b = in.read();
-                if (b == -1) {
-                    fail("Early EOF at offset " + offset + "\n");
-                    return;
-                }
+        f = File.createTempFile("ony", "by_one");
+        fw = new FileWriter(f);
+        fw.write(strChars);
+        fw.close();
+        InputStreamReader in = null;
+        FileInputStream fis = new FileInputStream(f);
+        in = new InputStreamReader(fis);
+        int b;
+        int errors = 0;
+        for (int offset = 0; offset < strChars.length; ++offset) {
+            b = in.read();
+            if (b == -1) {
+                fail("Early EOF at offset " + offset + "\n");
+                return;
             }
-            assertEquals(0, errors);
-        } catch (IOException e) {
-            e.printStackTrace();
         }
+        assertEquals(0, errors);
     }
 
     public void test_handleEarlyEOFChar_2() throws IOException {
@@ -141,6 +138,40 @@
         assertEquals(inputStr, outStr);
     }
 
+    public void test_handleExternalFileDescriptor() throws IOException {
+        String str = "All work and no play makes Jack a dull boy\n";
+        int NUMBER = 2048;
+        int j = 0;
+        int len = str.length() * NUMBER;
+        /* == 88064 *//* NUMBER compulsively written copies of the same string */
+        char[] strChars = new char[len];
+        for (int i = 0; i < NUMBER; ++i) {
+            for (int k = 0; k < str.length(); ++k) {
+                strChars[j++] = str.charAt(k);
+            }
+        }
+        File f = null;
+        FileWriter fw = null;
+        f = File.createTempFile("ony", "by_one");
+        FileOutputStream stream = new FileOutputStream(f);
+        fw = new FileWriter(stream.getFD());
+        fw.write(strChars);
+        fw.close();
+        InputStreamReader in = null;
+        FileInputStream fis = new FileInputStream(f);
+        in = new InputStreamReader(fis);
+        int b;
+        int errors = 0;
+        for (int offset = 0; offset < strChars.length; ++offset) {
+            b = in.read();
+            if (b == -1) {
+                fail("Early EOF at offset " + offset + "\n");
+                return;
+            }
+        }
+        assertEquals(0, errors);
+    }
+
     protected void setUp() throws Exception {
         f = File.createTempFile("writer", ".tst");
 
diff --git a/luni/src/test/java/libcore/java/io/PrintWriterTest.java b/luni/src/test/java/libcore/java/io/PrintWriterTest.java
new file mode 100644
index 0000000..cf3b86a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/PrintWriterTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class PrintWriterTest {
+
+    private class Writer extends PrintWriter {
+
+        Writer(File f) throws FileNotFoundException {
+            super(f);
+        }
+
+        public void setError() {
+            super.setError();
+        }
+
+        public void clearError() {
+            super.clearError();
+        }
+    }
+
+    @Test
+    public void testSetError() throws IOException {
+        File f = File.createTempFile("tmp", "tst");
+        Writer writer = new Writer(f);
+        assertFalse(writer.checkError());
+        writer.setError();
+        assertTrue(writer.checkError());
+        writer.clearError();
+        assertFalse(writer.checkError());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/SerializablePermissionTest.java b/luni/src/test/java/libcore/java/io/SerializablePermissionTest.java
new file mode 100644
index 0000000..29c0b96
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/SerializablePermissionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.SerializablePermission;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class SerializablePermissionTest {
+
+    @Test
+    public void testConstructorWithActions() {
+        SerializablePermission permission = new SerializablePermission("none", "no action");
+        // Implementation is stubbed in Android
+        assertEquals("", permission.getName());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/StreamCorruptedExceptionTest.java b/luni/src/test/java/libcore/java/io/StreamCorruptedExceptionTest.java
new file mode 100644
index 0000000..61307f8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/StreamCorruptedExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.StreamCorruptedException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class StreamCorruptedExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        StreamCorruptedException exception = new StreamCorruptedException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/UTFDataFormatExceptionTest.java b/luni/src/test/java/libcore/java/io/UTFDataFormatExceptionTest.java
new file mode 100644
index 0000000..f3102a2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/UTFDataFormatExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.UTFDataFormatException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class UTFDataFormatExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        UTFDataFormatException exception = new UTFDataFormatException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/UnsupportedEncodingExceptionTest.java b/luni/src/test/java/libcore/java/io/UnsupportedEncodingExceptionTest.java
new file mode 100644
index 0000000..d791167
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/UnsupportedEncodingExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.io;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.UnsupportedEncodingException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class UnsupportedEncodingExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        UnsupportedEncodingException exception = new UnsupportedEncodingException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/io/WriteAbortedExceptionTest.java b/luni/src/test/java/libcore/java/io/WriteAbortedExceptionTest.java
new file mode 100644
index 0000000..efd38f7
--- /dev/null
+++ b/luni/src/test/java/libcore/java/io/WriteAbortedExceptionTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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.io;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.WriteAbortedException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class WriteAbortedExceptionTest {
+
+    @Test
+    public void testGetCause() {
+        RuntimeException cause = new RuntimeException("test msg");
+        WriteAbortedException e = new WriteAbortedException("parent msg", cause);
+        assertEquals(cause, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/IllegalCallerExceptionTest.java b/luni/src/test/java/libcore/java/lang/IllegalCallerExceptionTest.java
new file mode 100644
index 0000000..e5250d8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/IllegalCallerExceptionTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+@RunWith(JUnit4.class)
+public class IllegalCallerExceptionTest {
+
+    @Test
+    public void constructor_noArg() {
+        IllegalCallerException exception = new IllegalCallerException();
+
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+    @Test
+    public void constructor_String() {
+        String message = "message";
+
+        IllegalCallerException exception = new IllegalCallerException(message);
+
+        assertEquals(message, exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
+    @Test
+    public void constructor_String_Throwable() {
+        String message = "message";
+        Exception cause = new Exception();
+
+        IllegalCallerException exception = new IllegalCallerException(message, cause);
+
+        assertEquals(message, exception.getMessage());
+        assertEquals(cause, exception.getCause());
+    }
+
+    @Test
+    public void constructor_Throwable() {
+        Exception cause = new Exception();
+
+        IllegalCallerException exception = new IllegalCallerException(cause);
+
+        assertEquals(cause, exception.getCause());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/lang/IntegerTest.java b/luni/src/test/java/libcore/java/lang/IntegerTest.java
index 79d1acc..4954f02 100644
--- a/luni/src/test/java/libcore/java/lang/IntegerTest.java
+++ b/luni/src/test/java/libcore/java/lang/IntegerTest.java
@@ -16,163 +16,164 @@
 
 package libcore.java.lang;
 
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import java.util.Properties;
 
-public class IntegerTest extends junit.framework.TestCase {
+@RunWith(JUnit4.class)
+public class IntegerTest {
+    static final int[] INT_VALUES = {0, 1, 23, 456, 0x7fff_ffff, 0x8000_0000, 0xffff_ffff};
 
-  public void testSystemProperties() {
-    Properties originalProperties = System.getProperties();
-    try {
-      Properties testProperties = new Properties();
-      testProperties.put("testIncInt", "notInt");
-      System.setProperties(testProperties);
-      assertNull("returned incorrect default Integer",
-        Integer.getInteger("testIncInt"));
-      assertEquals(new Integer(4), Integer.getInteger("testIncInt", 4));
-      assertEquals(new Integer(4),
-        Integer.getInteger("testIncInt", new Integer(4)));
-    } finally {
-      System.setProperties(originalProperties);
+    static final long[] LONG_VALUES = {
+        0x1_0000_0000L, (long) Integer.MIN_VALUE - 1L, Long.MIN_VALUE, Long.MAX_VALUE
+    };
+
+    @Test
+    public void testSystemProperties() {
+        Properties originalProperties = System.getProperties();
+        try {
+            Properties testProperties = new Properties();
+            testProperties.put("testIncInt", "notInt");
+            System.setProperties(testProperties);
+            assertNull("returned incorrect default Integer", Integer.getInteger("testIncInt"));
+            assertEquals(new Integer(4), Integer.getInteger("testIncInt", 4));
+            assertEquals(new Integer(4), Integer.getInteger("testIncInt", new Integer(4)));
+        } finally {
+            System.setProperties(originalProperties);
+        }
     }
-  }
 
-  public void testCompare() throws Exception {
-    final int min = Integer.MIN_VALUE;
-    final int zero = 0;
-    final int max = Integer.MAX_VALUE;
-    assertTrue(Integer.compare(max,  max)  == 0);
-    assertTrue(Integer.compare(min,  min)  == 0);
-    assertTrue(Integer.compare(zero, zero) == 0);
-    assertTrue(Integer.compare(max,  zero) > 0);
-    assertTrue(Integer.compare(max,  min)  > 0);
-    assertTrue(Integer.compare(zero, max)  < 0);
-    assertTrue(Integer.compare(zero, min)  > 0);
-    assertTrue(Integer.compare(min,  zero) < 0);
-    assertTrue(Integer.compare(min,  max)  < 0);
-  }
+    @Test
+    public void testCompare() throws Exception {
+        final int min = Integer.MIN_VALUE;
+        final int zero = 0;
+        final int max = Integer.MAX_VALUE;
+        assertTrue(Integer.compare(max, max) == 0);
+        assertTrue(Integer.compare(min, min) == 0);
+        assertTrue(Integer.compare(zero, zero) == 0);
+        assertTrue(Integer.compare(max, zero) > 0);
+        assertTrue(Integer.compare(max, min) > 0);
+        assertTrue(Integer.compare(zero, max) < 0);
+        assertTrue(Integer.compare(zero, min) > 0);
+        assertTrue(Integer.compare(min, zero) < 0);
+        assertTrue(Integer.compare(min, max) < 0);
+    }
 
-  public void testParseInt() throws Exception {
-    assertEquals(0, Integer.parseInt("+0", 10));
-    assertEquals(473, Integer.parseInt("+473", 10));
-    assertEquals(255, Integer.parseInt("+FF", 16));
-    assertEquals(102, Integer.parseInt("+1100110", 2));
-    assertEquals(2147483647, Integer.parseInt("+2147483647", 10));
-    assertEquals(411787, Integer.parseInt("Kona", 27));
-    assertEquals(411787, Integer.parseInt("+Kona", 27));
-    assertEquals(-145, Integer.parseInt("-145", 10));
+    @Test
+    public void testParseInt() throws Exception {
+        assertEquals(0, Integer.parseInt("+0", 10));
+        assertEquals(473, Integer.parseInt("+473", 10));
+        assertEquals(255, Integer.parseInt("+FF", 16));
+        assertEquals(102, Integer.parseInt("+1100110", 2));
+        assertEquals(2147483647, Integer.parseInt("+2147483647", 10));
+        assertEquals(411787, Integer.parseInt("Kona", 27));
+        assertEquals(411787, Integer.parseInt("+Kona", 27));
+        assertEquals(-145, Integer.parseInt("-145", 10));
 
-    try {
-      Integer.parseInt("--1", 10); // multiple sign chars
-      fail();
-    } catch (NumberFormatException expected) {}
+        // multiple sign chars
+        assertThrows(NumberFormatException.class, () -> Integer.parseInt("--1", 10));
+        assertThrows(NumberFormatException.class, () -> Integer.parseInt("++1", 10));
 
-    try {
-      Integer.parseInt("++1", 10); // multiple sign chars
-      fail();
-    } catch (NumberFormatException expected) {}
+        // base too small
+        assertThrows(NumberFormatException.class, () -> Integer.parseInt("Kona", 10));
+    }
 
-    try {
-      Integer.parseInt("Kona", 10); // base too small
-      fail();
-    } catch (NumberFormatException expected) {}
-  }
+    @Test
+    public void testDecodeInt() throws Exception {
+        assertEquals(0, Integer.decode("+0").intValue());
+        assertEquals(473, Integer.decode("+473").intValue());
+        assertEquals(255, Integer.decode("+0xFF").intValue());
+        assertEquals(16, Integer.decode("+020").intValue());
+        assertEquals(2147483647, Integer.decode("+2147483647").intValue());
+        assertEquals(-73, Integer.decode("-73").intValue());
+        assertEquals(-255, Integer.decode("-0xFF").intValue());
+        assertEquals(255, Integer.decode("+#FF").intValue());
+        assertEquals(-255, Integer.decode("-#FF").intValue());
 
-  public void testDecodeInt() throws Exception {
-    assertEquals(0, Integer.decode("+0").intValue());
-    assertEquals(473, Integer.decode("+473").intValue());
-    assertEquals(255, Integer.decode("+0xFF").intValue());
-    assertEquals(16, Integer.decode("+020").intValue());
-    assertEquals(2147483647, Integer.decode("+2147483647").intValue());
-    assertEquals(-73, Integer.decode("-73").intValue());
-    assertEquals(-255, Integer.decode("-0xFF").intValue());
-    assertEquals(255, Integer.decode("+#FF").intValue());
-    assertEquals(-255, Integer.decode("-#FF").intValue());
+        assertThrows(NumberFormatException.class, () -> Integer.decode("--1"));
+        assertThrows(NumberFormatException.class, () -> Integer.decode("++1"));
+        assertThrows(NumberFormatException.class, () -> Integer.decode("-+1"));
+        assertThrows(NumberFormatException.class, () -> Integer.decode("Kona"));
+    }
 
-    try {
-      Integer.decode("--1"); // multiple sign chars
-      fail();
-    } catch (NumberFormatException expected) {}
+    /*
+    public void testParsePositiveInt() throws Exception {
+      assertEquals(0, Integer.parsePositiveInt("0", 10));
+      assertEquals(473, Integer.parsePositiveInt("473", 10));
+      assertEquals(255, Integer.parsePositiveInt("FF", 16));
 
-    try {
-      Integer.decode("++1"); // multiple sign chars
-      fail();
-    } catch (NumberFormatException expected) {}
+      try {
+        Integer.parsePositiveInt("-1", 10);
+        fail();
+      } catch (NumberFormatException e) {}
 
-    try {
-      Integer.decode("-+1"); // multiple sign chars
-      fail();
-    } catch (NumberFormatException expected) {}
+      try {
+        Integer.parsePositiveInt("+1", 10);
+        fail();
+      } catch (NumberFormatException e) {}
 
-    try {
-      Integer.decode("Kona"); // invalid number
-      fail();
-    } catch (NumberFormatException expected) {}
-  }
+      try {
+        Integer.parsePositiveInt("+0", 16);
+        fail();
+      } catch (NumberFormatException e) {}
+    }
+    */
 
-  /*
-  public void testParsePositiveInt() throws Exception {
-    assertEquals(0, Integer.parsePositiveInt("0", 10));
-    assertEquals(473, Integer.parsePositiveInt("473", 10));
-    assertEquals(255, Integer.parsePositiveInt("FF", 16));
-
-    try {
-      Integer.parsePositiveInt("-1", 10);
-      fail();
-    } catch (NumberFormatException e) {}
-
-    try {
-      Integer.parsePositiveInt("+1", 10);
-      fail();
-    } catch (NumberFormatException e) {}
-
-    try {
-      Integer.parsePositiveInt("+0", 16);
-      fail();
-    } catch (NumberFormatException e) {}
-  }
-  */
-
+    @Test
     public void testStaticHashCode() {
         assertEquals(Integer.valueOf(567).hashCode(), Integer.hashCode(567));
     }
 
+    @Test
     public void testMax() {
         int a = 567;
         int b = 578;
         assertEquals(Math.max(a, b), Integer.max(a, b));
     }
 
+    @Test
     public void testMin() {
         int a = 567;
         int b = 578;
         assertEquals(Math.min(a, b), Integer.min(a, b));
     }
 
+    @Test
     public void testSum() {
         int a = 567;
         int b = 578;
         assertEquals(a + b, Integer.sum(a, b));
     }
 
+    @Test
     public void testBYTES() {
-      assertEquals(4, Integer.BYTES);
+        assertEquals(4, Integer.BYTES);
     }
 
+    @Test
     public void testCompareUnsigned() {
-        int[] ordVals = {0, 1, 23, 456, 0x7fff_ffff, 0x8000_0000, 0xffff_ffff};
-        for(int i = 0; i < ordVals.length; ++i) {
-            for(int j = 0; j < ordVals.length; ++j) {
-                assertEquals(Integer.compare(i, j),
-                             Integer.compareUnsigned(ordVals[i], ordVals[j]));
+        for (int i = 0; i < INT_VALUES.length; ++i) {
+            for (int j = 0; j < INT_VALUES.length; ++j) {
+                assertEquals(
+                        Integer.compare(i, j),
+                        Integer.compareUnsigned(INT_VALUES[i], INT_VALUES[j]));
             }
         }
     }
 
+    @Test
     public void testDivideAndRemainderUnsigned() {
         long[] vals = {1L, 23L, 456L, 0x7fff_ffffL, 0x8000_0000L, 0xffff_ffffL};
 
-        for(long dividend : vals) {
-            for(long divisor : vals) {
+        for (long dividend : vals) {
+            for (long divisor : vals) {
                 int uq = Integer.divideUnsigned((int) dividend, (int) divisor);
                 int ur = Integer.remainderUnsigned((int) dividend, (int) divisor);
                 assertEquals((int) (dividend / divisor), uq);
@@ -181,83 +182,220 @@
             }
         }
 
-        for(long dividend : vals) {
-            try {
-                Integer.divideUnsigned((int) dividend, 0);
-                fail();
-            } catch (ArithmeticException expected) { }
-            try {
-                Integer.remainderUnsigned((int) dividend, 0);
-                fail();
-            } catch (ArithmeticException expected) { }
+        for (long dividend : vals) {
+            assertThrows(
+                    ArithmeticException.class, () -> Integer.divideUnsigned((int) dividend, 0));
+            assertThrows(
+                    ArithmeticException.class, () -> Integer.remainderUnsigned((int) dividend, 0));
         }
     }
 
+    @Test
     public void testParseUnsignedInt() {
-        int[] vals = {0, 1, 23, 456, 0x7fff_ffff, 0x8000_0000, 0xffff_ffff};
-
-        for(int val : vals) {
+        for (int value : INT_VALUES) {
             // Special radices
-            assertEquals(val, Integer.parseUnsignedInt(Integer.toBinaryString(val), 2));
-            assertEquals(val, Integer.parseUnsignedInt(Integer.toOctalString(val), 8));
-            assertEquals(val, Integer.parseUnsignedInt(Integer.toUnsignedString(val)));
-            assertEquals(val, Integer.parseUnsignedInt(Integer.toHexString(val), 16));
+            assertEquals(value, Integer.parseUnsignedInt(Integer.toBinaryString(value), 2));
+            assertEquals(value, Integer.parseUnsignedInt(Integer.toOctalString(value), 8));
+            assertEquals(value, Integer.parseUnsignedInt(Integer.toUnsignedString(value)));
+            assertEquals(value, Integer.parseUnsignedInt(Integer.toHexString(value), 16));
 
-            for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
-                assertEquals(val,
-                        Integer.parseUnsignedInt(Integer.toUnsignedString(val, radix), radix));
+            for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
+                assertEquals(
+                        value,
+                        Integer.parseUnsignedInt(Integer.toUnsignedString(value, radix), radix));
             }
         }
 
-        try {
-            Integer.parseUnsignedInt("-1");
-            fail();
-        } catch (NumberFormatException expected) { }
-        try {
-            Integer.parseUnsignedInt("123", 2);
-            fail();
-        } catch (NumberFormatException expected) { }
-        try {
-            Integer.parseUnsignedInt(null);
-            fail();
-        } catch (NumberFormatException expected) { }
-        try {
-            Integer.parseUnsignedInt("0", Character.MAX_RADIX + 1);
-            fail();
-        } catch (NumberFormatException expected) { }
-        try {
-            Integer.parseUnsignedInt("0", Character.MIN_RADIX - 1);
-            fail();
-        } catch (NumberFormatException expected) { }
+        for (long longValue : LONG_VALUES) {
+            // Special radices
+            assertThrows(
+                    NumberFormatException.class,
+                    () -> Integer.parseUnsignedInt(Long.toBinaryString(longValue), 2));
+            assertThrows(
+                    NumberFormatException.class,
+                    () -> Integer.parseUnsignedInt(Long.toOctalString(longValue), 8));
+            assertThrows(
+                    NumberFormatException.class,
+                    () -> Integer.parseUnsignedInt(Long.toUnsignedString(longValue), 10));
+            assertThrows(
+                    NumberFormatException.class,
+                    () -> Integer.parseUnsignedInt(Long.toHexString(longValue), 16));
+            for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
+                final int r = radix;
+                assertThrows(
+                        NumberFormatException.class,
+                        () -> Integer.parseUnsignedInt(Long.toUnsignedString(longValue, r), r));
+            }
+        }
+
+        assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("-1"));
+        assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("123", 2));
+        assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt(null));
+        assertThrows(
+                NumberFormatException.class,
+                () -> Integer.parseUnsignedInt("0", Character.MAX_RADIX + 1));
+        assertThrows(
+                NumberFormatException.class,
+                () -> Integer.parseUnsignedInt("0", Character.MIN_RADIX - 1));
     }
 
-    public void testToUnsignedLong() {
-        int[] vals = {0, 1, 23, 456, 0x7fff_ffff, 0x8000_0000, 0xffff_ffff};
+    @Test
+    public void testParseUnsignedIntSubstring() {
+        final String LEFT = "1";
+        final String RIGHT = "0";
 
-        for(int val : vals) {
+        for (int ii = 0; ii < 8; ii = 2 * ii + 1) {
+            for (int jj = 0; jj < 8; jj = 2 * jj + 1) {
+                final int i = ii; // final for use in lambdas
+                final int j = jj; // final for use in lambdas
+                final String leftPad = LEFT.repeat(i);
+                final String rightPad = RIGHT.repeat(j);
+                for (int value : INT_VALUES) {
+                    String binary = leftPad + Integer.toBinaryString(value) + rightPad;
+                    assertEquals(
+                            value, Integer.parseUnsignedInt(binary, i, binary.length() - j, 2));
+
+                    String octal = leftPad + Integer.toOctalString(value) + rightPad;
+                    assertEquals(value, Integer.parseUnsignedInt(octal, i, octal.length() - j, 8));
+
+                    String denary = leftPad + Integer.toUnsignedString(value) + rightPad;
+                    assertEquals(
+                            value, Integer.parseUnsignedInt(denary, i, denary.length() - j, 10));
+
+                    String hex = leftPad + Integer.toHexString(value) + rightPad;
+                    assertEquals(value, Integer.parseUnsignedInt(hex, i, hex.length() - j, 16));
+
+                    for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
+                        String arb = leftPad + Integer.toUnsignedString(value, radix) + rightPad;
+                        assertEquals(
+                                value, Integer.parseUnsignedInt(arb, i, arb.length() - j, radix));
+                    }
+                }
+
+                for (long large_value : LONG_VALUES) {
+                    {
+                        final String input = leftPad + Long.toBinaryString(large_value) + rightPad;
+                        assertThrows(
+                                NumberFormatException.class,
+                                () -> Integer.parseUnsignedInt(input, i, input.length() - j, 2));
+                    }
+                    {
+                        final String input = leftPad + Long.toOctalString(large_value) + rightPad;
+                        assertThrows(
+                                NumberFormatException.class,
+                                () -> Integer.parseUnsignedInt(input, i, input.length() - j, 8));
+                    }
+                    {
+                        final String input =
+                                leftPad + Long.toUnsignedString(large_value) + rightPad;
+                        assertThrows(
+                                NumberFormatException.class,
+                                () -> Integer.parseUnsignedInt(input, i, input.length() - j, 10));
+                    }
+                    {
+                        final String input = leftPad + Long.toHexString(large_value) + rightPad;
+                        assertThrows(
+                                NumberFormatException.class,
+                                () -> Integer.parseUnsignedInt(input, i, input.length() - j, 16));
+                    }
+                    for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
+                        final int r = radix;
+                        String input =
+                                leftPad + Long.toUnsignedString(large_value, radix) + rightPad;
+                        assertThrows(
+                                NumberFormatException.class,
+                                () -> Integer.parseUnsignedInt(input, i, input.length() - j, r));
+                    }
+                }
+            }
+        }
+
+        assertThrows(
+                IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", -1, 3, 10));
+        assertThrows(
+                IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", 4, 5, 10));
+        assertThrows(
+                IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", 2, 1, 10));
+        assertThrows(
+                IndexOutOfBoundsException.class, () -> Integer.parseUnsignedInt("123", 2, 4, 10));
+        assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("-1", 0, 2, 10));
+        assertThrows(NumberFormatException.class, () -> Integer.parseUnsignedInt("123", 0, 3, 2));
+        assertThrows(
+                NumberFormatException.class,
+                () -> Integer.parseUnsignedInt("0", 0, 1, Character.MAX_RADIX + 1));
+        assertThrows(
+                NumberFormatException.class,
+                () -> Integer.parseUnsignedInt("0", 0, 1, Character.MIN_RADIX - 1));
+        assertThrows(NullPointerException.class, () -> Integer.parseUnsignedInt(null, 0, 1, 10));
+    }
+
+    @Test
+    public void testToUnsignedLong() {
+        for (int val : INT_VALUES) {
             long ul = Integer.toUnsignedLong(val);
             assertEquals(0, ul >>> Integer.BYTES * 8);
             assertEquals(val, (int) ul);
         }
     }
 
+    @Test
     public void testToUnsignedString() {
-        int[] vals = {0, 1, 23, 456, 0x7fff_ffff, 0x8000_0000, 0xffff_ffff};
-
-        for(int val : vals) {
+        for (int val : INT_VALUES) {
             // Special radices
             assertTrue(Integer.toUnsignedString(val, 2).equals(Integer.toBinaryString(val)));
             assertTrue(Integer.toUnsignedString(val, 8).equals(Integer.toOctalString(val)));
             assertTrue(Integer.toUnsignedString(val, 10).equals(Integer.toUnsignedString(val)));
             assertTrue(Integer.toUnsignedString(val, 16).equals(Integer.toHexString(val)));
 
-            for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
-                assertTrue(Integer.toUnsignedString(val, radix)
-                        .equals(Long.toString(Integer.toUnsignedLong(val), radix)));
+            for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; ++radix) {
+                assertTrue(
+                        Integer.toUnsignedString(val, radix)
+                                .equals(Long.toString(Integer.toUnsignedLong(val), radix)));
             }
 
             // Behavior is not defined by Java API specification if the radix falls outside of valid
             // range, thus we don't test for such cases.
         }
     }
+
+    @Test
+    public void testParseUnsignedIntSubstringForBackports() {
+        // Rudimentary test to register coverage on older branches where we may see backports for
+        // OpenJDK 11 methods (b/191859202). NB using Integer_parseUnsignedInt rather than
+        // Integer.parseUnsignedInt.
+        assertEquals(
+                0xaa55aa55,
+                Integer_parseUnsignedInt("left10101010010101011010101001010101right", 4, 36, 2));
+        assertEquals(8003, Integer_parseUnsignedInt("left17503right", 4, 9, 8));
+        assertEquals(0xffff_ffff, Integer_parseUnsignedInt("left4294967295right", 4, 14, 10));
+        assertEquals(0x1234_5678, Integer_parseUnsignedInt("lefty12345678righty", 5, 13, 16));
+    }
+
+    /**
+     * Parses an unsigned integer using a {@code MethodHandle} to invoke {@code
+     * Integer.parseUnsignedInt}.
+     *
+     * @param val the {@code CharSequence} to be parsed.
+     * @param start the starting index in {@code val}.
+     * @param end the ending ing index in {@code val}, exclusive.
+     * @param radix the radix to parse {@code val} with.
+     * @return the parsed unsigned integer.
+     */
+    private static int Integer_parseUnsignedInt(CharSequence val, int start, int end, int radix) {
+        try {
+            MethodType parseUnsignedIntType =
+                    MethodType.methodType(
+                            int.class, CharSequence.class, int.class, int.class, int.class);
+            MethodHandle parseUnsignedInt =
+                    MethodHandles.lookup()
+                            .findStatic(Integer.class, "parseUnsignedInt", parseUnsignedIntType);
+            return (int) parseUnsignedInt.invokeExact(val, start, end, radix);
+        } catch (IndexOutOfBoundsException | NullPointerException | NumberFormatException e) {
+            // Expected exceptions from the target method during the tests here.
+            throw e;
+        } catch (Throwable t) {
+            // Everything else.
+            throw new RuntimeException(t);
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 395209a..0a8ef78 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -34,6 +34,7 @@
 import java.util.ArrayList;
 import java.util.Locale;
 
+import java.util.stream.IntStream;
 import junit.framework.TestCase;
 
 public class StringTest extends TestCase {
@@ -170,6 +171,7 @@
         assertEquals("[104, 63]", Arrays.toString("h\ud800".getBytes(cs)));
         // A high surrogate not followed by a low surrogate is an error replaced with '?'.
         assertEquals("[104, 63, 105]", Arrays.toString("h\ud800i".getBytes(cs)));
+        assertEquals("[104, 63, -48, -128]", Arrays.toString("h\ud800\u0400".getBytes(cs)));
     }
 
     public void test_new_String_bad() throws Exception {
@@ -794,4 +796,36 @@
             Locale.setDefault(defaultLocale);
         }
     }
+
+    /**
+     * In addition to upstream tests that test whitespace characters from range [1, 0xFFFF],
+     * test *all* whitespace characters from [1, Character.MAX_CODE_POINT] to include non-BMP
+     * whitespaces.
+     */
+    public void testStrip_allWhitespaces() {
+        StringBuilder sb = new StringBuilder();
+        IntStream.range(1, Character.MAX_CODE_POINT).filter(Character::isWhitespace)
+                .forEach(c -> sb.append((char)c));
+        String whiteSpace = sb.toString();
+
+        String testString = whiteSpace + "abc" + whiteSpace;
+        assertEquals("abc", testString.strip());
+        assertEquals("abc" + whiteSpace, testString.stripLeading());
+        assertEquals(whiteSpace + "abc", testString.stripTrailing());
+    }
+
+    /**
+     * In addition to upstream tests that test whitespace characters from range [1, 0xFFFF],
+     * test *all* whitespace characters from [1, Character.MAX_CODE_POINT] to include non-BMP
+     * whitespaces.
+     */
+    public void testIsBlank_allWhitespaces() {
+        StringBuilder sb = new StringBuilder();
+        IntStream.range(1, 0xFFFF).filter(Character::isWhitespace)
+                .forEach(c -> sb.append((char)c));
+        String whiteSpace = sb.toString();
+
+        assertTrue(whiteSpace.isBlank());
+        assertFalse((whiteSpace + "abc" + whiteSpace).isBlank());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/ThreadTest.java b/luni/src/test/java/libcore/java/lang/ThreadTest.java
index 19ca2b6..29ed4a2 100644
--- a/luni/src/test/java/libcore/java/lang/ThreadTest.java
+++ b/luni/src/test/java/libcore/java/lang/ThreadTest.java
@@ -589,4 +589,29 @@
             done = true;
         }
     }
+
+    @Test
+    public void onSpinWait() throws InterruptedException {
+        SpinWaitThread t = new SpinWaitThread();
+
+        t.start();
+        Thread.sleep(1000);
+        assertFalse(t.done);
+        t.stop = true;
+        Thread.sleep(1000);
+        assertTrue(t.done);
+    }
+
+    private static class SpinWaitThread extends Thread {
+        public volatile boolean stop = false;
+        public volatile boolean done = false;
+
+        @Override public void run() {
+            done = false;
+            while (!stop) {
+                Thread.onSpinWait();
+            }
+            done = true;
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java b/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java
index 5debdcb..559eb99 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/CallSitesTest.java
@@ -31,14 +31,22 @@
 import static java.lang.invoke.MethodHandles.Lookup.*;
 
 public class CallSitesTest extends TestCase {
-    public void test_ConstantCallSite() throws Throwable {
-        final MethodType type = MethodType.methodType(int.class, int.class, int.class);
-        final MethodHandle mh =
-                MethodHandles.lookup().findStatic(CallSitesTest.class, "add2", type);
-        final ConstantCallSite site = new ConstantCallSite(mh);
-        assertEquals(mh, site.getTarget());
-        assertEquals(type, site.type());
+    public void test_ConstantCallSiteConstructorNullMethodHandle() throws Throwable {
+        try {
+            ConstantCallSite site = new ConstantCallSite((MethodHandle) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
 
+    private static MethodHandle methodHandleForAdd2() throws Throwable {
+        final MethodType mt = MethodType.methodType(int.class, int.class, int.class);
+        return MethodHandles.lookup().findStatic(CallSitesTest.class, "add2", mt);
+    }
+
+    public void test_ConstantCallSite() throws Throwable {
+        final MethodHandle mh = methodHandleForAdd2();
+        ConstantCallSite site = new ConstantCallSite(mh);
         int n = (int) site.dynamicInvoker().invokeExact(7, 37);
         assertEquals(44, n);
         try {
@@ -48,6 +56,147 @@
         }
     }
 
+    static class OurConstantCallSite extends ConstantCallSite {
+        OurConstantCallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
+            super(targetType, createTargetHook);
+        }
+
+        static MethodHandle createTargetHook(OurConstantCallSite callSite) throws Throwable {
+            final MethodType add2MethodType =
+                    MethodType.methodType(int.class, int.class, int.class);
+            return MethodHandles.lookup().findStatic(CallSitesTest.class, "add2", add2MethodType);
+        }
+    }
+
+    public void test_ConstantCallSiteWithHook() throws Throwable {
+        final MethodType targetType =
+                MethodType.methodType(int.class, int.class, int.class);
+        MethodHandle createTargetHook =
+                MethodHandles.lookup().findStatic(OurConstantCallSite.class, "createTargetHook",
+                                                  MethodType.methodType(MethodHandle.class,
+                                                                        OurConstantCallSite.class));
+        OurConstantCallSite callSite = new OurConstantCallSite(targetType, createTargetHook);
+        int x = (int) callSite.getTarget().invoke(1, 2);
+        assertEquals(3, x);
+    }
+
+    public void test_MutableCallSiteConstructorNullMethodType() throws Throwable {
+        try {
+            MutableCallSite callSite = new MutableCallSite((MethodType) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_MutableCallSiteConstructorNullMethodHandle() throws Throwable {
+        try {
+            MutableCallSite callSite = new MutableCallSite((MethodHandle) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_MutableCallsiteNoMethodHandle() throws Throwable {
+        try {
+            MutableCallSite callSite =
+                    new MutableCallSite(MethodType.methodType(int.class, int.class, int.class));
+            int result = (int) callSite.getTarget().invokeExact(1, 2);
+            fail();
+        } catch (IllegalStateException e) {
+        }
+    }
+
+    public void test_MutableCallSite() throws Throwable {
+        final MethodHandle mh = methodHandleForAdd2();
+        final MutableCallSite site = new MutableCallSite(mh);
+
+        // Invocation test
+        int n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(44, n);
+
+        // setTarget() tests
+        try {
+            final MethodType mt_add3 =
+                    MethodType.methodType(int.class, int.class, int.class, int.class);
+            final MethodHandle mh_add3 =
+                    MethodHandles.lookup().findStatic(CallSitesTest.class, "add3", mt_add3);
+
+            site.setTarget(mh_add3);
+            fail();
+        } catch (WrongMethodTypeException e) {
+        }
+        try {
+            site.setTarget(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+        final MethodHandle mh_sub2 =
+                MethodHandles.lookup().findStatic(CallSitesTest.class, "sub2",
+                                                  MethodType.methodType(int.class, int.class, int.class));
+        site.setTarget(mh_sub2);
+        n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(-30, n);
+    }
+
+    public void test_VolatileCallSiteConstructorNullMethodType() throws Throwable {
+        try {
+            VolatileCallSite vc = new VolatileCallSite((MethodType) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_VolatileCallSiteConstructorNullMethodHandle() throws Throwable {
+        try {
+            VolatileCallSite vc = new VolatileCallSite((MethodHandle) null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void test_VolatileCallsiteNoMethodHandle() throws Throwable {
+        try {
+            VolatileCallSite vc =
+                    new VolatileCallSite(MethodType.methodType(int.class, int.class, int.class));
+            int result = (int) vc.getTarget().invokeExact(1, 2);
+            fail();
+        } catch (IllegalStateException e) {
+        }
+    }
+
+    public void test_VolatileCallSite() throws Throwable {
+        final MethodHandle mh = methodHandleForAdd2();
+        final VolatileCallSite site = new VolatileCallSite(mh);
+
+        // Invocation test
+        int n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(44, n);
+
+        // setTarget() tests
+        try {
+            final MethodType mt_add3 =
+                    MethodType.methodType(int.class, int.class, int.class, int.class);
+            final MethodHandle mh_add3 =
+                    MethodHandles.lookup().findStatic(CallSitesTest.class, "add3", mt_add3);
+            site.setTarget(mh_add3);
+            fail();
+        } catch (WrongMethodTypeException e) {
+        }
+        try {
+            site.setTarget(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+
+        // One last invocation test
+        final MethodHandle mh_sub2 =
+                MethodHandles.lookup().findStatic(CallSitesTest.class, "sub2",
+                                                  MethodType.methodType(int.class, int.class, int.class));
+        site.setTarget(mh_sub2);
+        n = (int) site.getTarget().invokeExact(7, 37);
+        assertEquals(-30, n);
+    }
+
     public void test_EarlyBoundMutableCallSite() throws Throwable {
         final MethodType type = MethodType.methodType(int.class, int.class, int.class);
         final MethodHandle add2 =
@@ -97,7 +246,7 @@
     }
 
     private static void commonMutableCallSitesTest(CallSite site,
-                                                  MethodHandle firstTarget) throws Throwable{
+                                                   MethodHandle firstTarget) throws Throwable {
         site.setTarget(firstTarget);
         site.setTarget(firstTarget);
 
@@ -133,15 +282,15 @@
         assertEquals(100, (int) site.dynamicInvoker().invokeExact(147, 47));
     }
 
-    private static int add2(int x, int y) {
+    public static int add2(int x, int y) {
         return x + y;
     }
 
-    private static int add3(int x, int y, int z) {
+    public static int add3(int x, int y, int z) {
         return x + y + z;
     }
 
-    private static int sub2(int x, int y) {
+    public static int sub2(int x, int y) {
         return x - y;
     }
 }
diff --git a/luni/src/test/java/libcore/java/lang/invoke/ExplicitCastArgumentsTest.java b/luni/src/test/java/libcore/java/lang/invoke/ExplicitCastArgumentsTest.java
index abc5825..f965cda 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/ExplicitCastArgumentsTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/ExplicitCastArgumentsTest.java
@@ -5721,4 +5721,26 @@
         m.invokeExact((Double) DOUBLE_VALUES[0]);
     }
 
+    @Test
+    public void testIntegerObjectToInt() throws Throwable {
+        MethodHandle m = explicitCastArgumentToIdentity(int.class, Object.class);
+        assertEquals(3, (int) m.invokeExact((Object) Integer.valueOf(3)));
+    }
+
+    @Test
+    public void testStringObjectToInt() throws Throwable {
+        MethodHandle m = explicitCastArgumentToIdentity(int.class, Object.class);
+        try {
+            int n = (int) m.invokeExact((Object) "3");
+            fail("Expected CCE");
+        } catch (ClassCastException expected) {}
+    }
+
+    @Test
+    public void testObjectObjectToInt() throws Throwable {
+        MethodHandle m = explicitCastArgumentToIdentity(int.class, Object.class);
+        try {
+            int n = (int) m.invokeExact(new Object());
+        } catch (ClassCastException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/invoke/LambdaConversionExceptionTest.java b/luni/src/test/java/libcore/java/lang/invoke/LambdaConversionExceptionTest.java
new file mode 100644
index 0000000..06a923a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/invoke/LambdaConversionExceptionTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang.invoke;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.invoke.LambdaConversionException;
+
+@RunWith(JUnit4.class)
+public class LambdaConversionExceptionTest {
+    private static final String MESSAGE = "message";
+
+    @Test
+    public void constructor() {
+        try {
+            throw new LambdaConversionException();
+        } catch (LambdaConversionException e) {
+            assertNull(e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @Test
+    public void constructorLString() {
+        try {
+            throw new LambdaConversionException(MESSAGE);
+        } catch (LambdaConversionException e) {
+            assertEquals(MESSAGE, e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @Test
+    public void constructorLStringLThrowable() {
+        try {
+            try {
+                throw new IllegalArgumentException();
+            } catch (Throwable t) {
+                throw new LambdaConversionException(MESSAGE, t);
+            }
+        } catch (LambdaConversionException e) {
+            assertEquals(MESSAGE, e.getMessage());
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+        }
+    }
+
+    @Test
+    public void constructorLThrowable() {
+        try {
+            try {
+                throw new IllegalArgumentException();
+            } catch (Throwable t) {
+                throw new LambdaConversionException(t);
+            }
+        } catch (LambdaConversionException e) {
+            assertEquals("java.lang.IllegalArgumentException", e.getMessage());
+            assertTrue(e.getCause() instanceof IllegalArgumentException);
+        }
+
+        try {
+            throw new LambdaConversionException((Throwable) null);
+        } catch (LambdaConversionException e) {
+            assertNull(e.getMessage());
+            assertNull(e.getCause());
+        }
+    }
+
+    @Test
+    public void constructorWithSuppressionsAndWritableStackTraces() {
+        boolean trueAndFalse[] = { true, false };
+
+        for (boolean enableSuppression : trueAndFalse) {
+            for (boolean writableStackTrace : trueAndFalse) {
+                try {
+                    throw new LambdaConversionException(MESSAGE, null, enableSuppression,
+                                                        writableStackTrace);
+                } catch (LambdaConversionException e) {
+                    assertEquals(MESSAGE, e.getMessage());
+
+                    // Check if exceptions can be suppressed.
+                    e.addSuppressed(new LambdaConversionException());
+                    boolean haveSuppressed = (e.getSuppressed().length == 1);
+                    assertEquals(enableSuppression, haveSuppressed);
+
+                    // Check if stack trace is writable.
+                    boolean stackTraceHasElements = (0 != e.getStackTrace().length);
+                    assertEquals(writableStackTrace, stackTraceHasElements);
+                    if (stackTraceHasElements) {
+                        // Only a writable stack trace has elements present. Now re-write it.
+                        e.setStackTrace(new StackTraceElement[0]);
+                        boolean wroteStackTrace = (e.getStackTrace().length == 0);
+                        assertEquals(writableStackTrace, wroteStackTrace);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
index aa3e983..d5573f1 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
@@ -528,6 +528,9 @@
         {
             MethodHandle constant = MethodHandles.constant(int.class, 56);
             assertEquals(56, (int) constant.invoke());
+            assertEquals(56, (int) constant.invokeExact());
+            assertEquals(Integer.valueOf(1),
+                         (Integer) MethodHandles.constant(Integer.class, 1).invokeExact());
 
             // short constant values are converted to int.
             constant = MethodHandles.constant(int.class, (short) 52);
@@ -620,6 +623,33 @@
         }
     }
 
+    public static void testZero() throws Throwable {
+        assertEquals(false, (boolean) MethodHandles.zero(boolean.class).invokeExact());
+        assertEquals((byte) 0, (byte) MethodHandles.zero(byte.class).invokeExact());
+        assertEquals((char) 0, (char) MethodHandles.zero(char.class).invokeExact());
+        assertEquals((short) 0, (short) MethodHandles.zero(short.class).invokeExact());
+        assertEquals(0, (int) MethodHandles.zero(int.class).invokeExact());
+        assertEquals(0L, (long) MethodHandles.zero(long.class).invokeExact());
+        assertEquals(0.0f, (float) MethodHandles.zero(float.class).invokeExact());
+        assertEquals(0.0, (double) MethodHandles.zero(double.class).invokeExact());
+        assertEquals(null, MethodHandles.zero(Object.class).invokeExact());
+        assertEquals(null, (Integer) MethodHandles.zero(Integer.class).invokeExact());
+        assertEquals(null, (String) MethodHandles.zero(String.class).invokeExact());
+
+        assertEquals(Boolean.valueOf(false), (Boolean) MethodHandles.zero(boolean.class).invoke());
+        assertEquals(Byte.valueOf((byte) 0), (Byte) MethodHandles.zero(byte.class).invoke());
+        assertEquals(Character.valueOf((char) 0),
+                     (Character) MethodHandles.zero(char.class).invoke());
+        assertEquals(Short.valueOf((short) 0), (Short) MethodHandles.zero(short.class).invoke());
+        assertEquals(Integer.valueOf(0), (Integer) MethodHandles.zero(int.class).invoke());
+        assertEquals(Long.valueOf(0L), (Long) MethodHandles.zero(long.class).invoke());
+        assertEquals(Float.valueOf(0.0f), (Float) MethodHandles.zero(float.class).invoke());
+        assertEquals(Double.valueOf(0.0), (Double) MethodHandles.zero(double.class).invoke());
+        assertEquals(null, MethodHandles.zero(Object.class).invoke());
+        assertEquals(null, (Integer) MethodHandles.zero(Integer.class).invoke());
+        assertEquals(null, (String) MethodHandles.zero(String.class).invoke());
+    }
+
     public static void testBindTo() throws Throwable {
         MethodHandle stringCharAt = MethodHandles.lookup().findVirtual(
                 String.class, "charAt", MethodType.methodType(char.class, int.class));
@@ -854,11 +884,8 @@
 
         MethodHandle exactInvoker = MethodHandles.exactInvoker(target.type());
         assertEquals("barbar", (String) exactInvoker.invoke(target, "bar", "bar"));
-        try {
-            String foo = (String) exactInvoker.invoke(target, (Object) returnBar(), "bar");
-            fail();
-        } catch (WrongMethodTypeException expected) {
-        }
+        assertEquals("barbar", (String) exactInvoker.invoke(target, (Object) returnBar(), "bar"));
+
         try {
             String foo = (String) exactInvoker.invoke(target, "bar", "bar", 24);
             fail();
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java
index 12b82b0..a4e62f0 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleInfoTest.java
@@ -54,6 +54,25 @@
         }
     }
 
+    public void test_constants() {
+        final int [] REF_CONSTANTS = {
+            0,                                     // Not used
+            MethodHandleInfo.REF_getField,         // 1
+            MethodHandleInfo.REF_getStatic,        // 2
+            MethodHandleInfo.REF_putField,         // 3
+            MethodHandleInfo.REF_putStatic,        // 4
+            MethodHandleInfo.REF_invokeVirtual,    // 5
+            MethodHandleInfo.REF_invokeStatic,     // 6
+            MethodHandleInfo.REF_invokeSpecial,    // 7
+            MethodHandleInfo.REF_newInvokeSpecial, // 8
+            MethodHandleInfo.REF_invokeInterface,  // 9
+        };
+        assertEquals(10, REF_CONSTANTS.length);
+        for (int i = 0; i < REF_CONSTANTS.length; ++i) {
+            assertEquals(i, REF_CONSTANTS[i]);
+        }
+    }
+
     public void test_referenceKindToString() {
         assertEquals("getField", referenceKindToString(REF_getField));
         assertEquals("getStatic", referenceKindToString(REF_getStatic));
@@ -77,4 +96,46 @@
         } catch (IllegalArgumentException expected) {
         }
     }
+
+    public void test_refKindIsField() {
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_getField));
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_getStatic));
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_putField));
+        assertTrue(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_putStatic));
+
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeVirtual));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeStatic));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeSpecial));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_newInvokeSpecial));
+        assertFalse(MethodHandleInfo.refKindIsField(MethodHandleInfo.REF_invokeInterface));
+    }
+
+    public void test_refKindIsValid() {
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_getField));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_getStatic));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_putField));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_putStatic));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeVirtual));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeStatic));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeSpecial));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_newInvokeSpecial));
+        assertTrue(MethodHandleInfo.refKindIsValid(MethodHandleInfo.REF_invokeInterface));
+    }
+
+    public void test_refKindName() {
+        assertEquals("getField", MethodHandleInfo.refKindName(MethodHandleInfo.REF_getField));
+        assertEquals("getStatic", MethodHandleInfo.refKindName(MethodHandleInfo.REF_getStatic));
+        assertEquals("putField", MethodHandleInfo.refKindName(MethodHandleInfo.REF_putField));
+        assertEquals("putStatic", MethodHandleInfo.refKindName(MethodHandleInfo.REF_putStatic));
+        assertEquals("invokeVirtual",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeVirtual));
+        assertEquals("invokeStatic",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeStatic));
+        assertEquals("invokeSpecial",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeSpecial));
+        assertEquals("newInvokeSpecial",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_newInvokeSpecial));
+        assertEquals("invokeInterface",
+                     MethodHandleInfo.refKindName(MethodHandleInfo.REF_invokeInterface));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
index 973c994..561ac7a 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandlesTest.java
@@ -83,6 +83,42 @@
         }
     }
 
+    public void test_privateLookupIn() throws Throwable {
+        MethodHandles.Lookup defaultLookup = MethodHandles.lookup();
+
+        try {
+            MethodHandles.privateLookupIn(null, defaultLookup);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            MethodHandles.privateLookupIn(int.class, defaultLookup);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            MethodHandles.privateLookupIn(Integer[].class, defaultLookup);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        D dInstance = new D();
+
+        MethodHandles.Lookup privateLookup =
+            MethodHandles.privateLookupIn(MethodHandlesTest.D.class, defaultLookup);
+        assertNotNull(privateLookup);
+
+        MethodHandle handle = privateLookup.findVirtual(MethodHandlesTest.D.class,
+                "privateRyan", MethodType.methodType(void.class));
+        assertNotNull(handle);
+
+        dInstance.privateDCalled = false;
+        handle.invokeExact(dInstance);
+        assertTrue(dInstance.privateDCalled);
+    }
+
     public void test_findStatic() throws Exception {
         MethodHandles.Lookup defaultLookup = MethodHandles.lookup();
 
diff --git a/luni/src/test/java/libcore/java/lang/invoke/VarHandleTest.java b/luni/src/test/java/libcore/java/lang/invoke/VarHandleTest.java
new file mode 100644
index 0000000..8d373b2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/invoke/VarHandleTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.lang.invoke;
+
+import java.lang.invoke.VarHandle;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class VarHandleTest {
+    @Test
+    public void fences() {
+        // In theory, these should log coverage for these fences, but they are implemented
+        // as intrinsics in the runtime and the compiler.
+        VarHandle.acquireFence();
+        VarHandle.releaseFence();
+        VarHandle.fullFence();
+        VarHandle.loadLoadFence();
+        VarHandle.storeStoreFence();
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/invoke/WrongMethodTypeExceptionTest.java b/luni/src/test/java/libcore/java/lang/invoke/WrongMethodTypeExceptionTest.java
new file mode 100644
index 0000000..d9288d2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/invoke/WrongMethodTypeExceptionTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.lang.invoke;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+@RunWith(JUnit4.class)
+public class WrongMethodTypeExceptionTest {
+    private static final String MESSAGE = "message";
+
+    @Test
+    public void constructor() {
+        try {
+            throw new WrongMethodTypeException();
+        } catch (WrongMethodTypeException e) {
+            assertNull(e.getCause());
+            assertNull(e.getMessage());
+        }
+    }
+
+    @Test
+    public void constructorLString() {
+        try {
+            throw new WrongMethodTypeException(MESSAGE);
+        } catch (WrongMethodTypeException e) {
+            assertNull(e.getCause());
+            assertEquals(MESSAGE, e.getMessage());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/GenericSignatureFormatErrorTest.java b/luni/src/test/java/libcore/java/lang/reflect/GenericSignatureFormatErrorTest.java
new file mode 100644
index 0000000..8324aa4
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/GenericSignatureFormatErrorTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.lang.reflect;
+
+import java.lang.reflect.GenericSignatureFormatError;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class GenericSignatureFormatErrorTest {
+    private static final String MESSAGE = "message";
+
+    @Test
+    public void constructor() {
+        try {
+            throw new GenericSignatureFormatError();
+        } catch (GenericSignatureFormatError e) {
+            assertNull(e.getCause());
+            assertNull(e.getMessage());
+        }
+    }
+
+    @Test
+    public void constructorLString() {
+        try {
+            throw new GenericSignatureFormatError(MESSAGE);
+        } catch (GenericSignatureFormatError e) {
+            assertNull(e.getCause());
+            assertEquals(MESSAGE, e.getMessage());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ReflectPermissionTest.java b/luni/src/test/java/libcore/java/lang/reflect/ReflectPermissionTest.java
new file mode 100644
index 0000000..1f788fe
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/ReflectPermissionTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package libcore.java.lang.reflect;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.reflect.ReflectPermission;
+
+@RunWith(JUnit4.class)
+public class ReflectPermissionTest {
+    private static final String NAME = "message";
+    private static final String ACTIONS = "No action";
+
+    private void checkFieldsAreEmpty(ReflectPermission permission) {
+        // The super-class of ReflectPermission overrides the name and actions provided to
+        // the ReflectPermission constructors with empty strings.
+        //
+        // This is legacy code that is not intended for use.
+        assertTrue(permission.getName().isEmpty());
+        assertTrue(permission.getActions().isEmpty());
+    }
+
+    @Test
+    public void reflectPermissionWithName() {
+        ReflectPermission permission = new ReflectPermission(NAME);
+        checkFieldsAreEmpty(permission);
+    }
+
+    @Test
+    public void reflectPermissionWithNameAndActions() {
+        ReflectPermission permission = new ReflectPermission(NAME, ACTIONS);
+        checkFieldsAreEmpty(permission);
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java b/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java
index 7c47206..1cc25bf 100644
--- a/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java
+++ b/luni/src/test/java/libcore/java/net/AbstractCookiesTest.java
@@ -726,6 +726,13 @@
         assertNotEquals(createCookie("theme", "light", "a.com", "/path"), baseCookie);
     }
 
+    public void testIsHttpOnly() throws Exception {
+        HttpCookie cookie = createCookie("a", "android", "a.com", "/");
+        assertFalse(cookie.isHttpOnly());
+        cookie.setHttpOnly(true);
+        assertTrue(cookie.isHttpOnly());
+    }
+
     private static void assertNotEquals(HttpCookie one, HttpCookie two) {
         assertFalse(one.equals(two));
         assertFalse(two.equals(one));
diff --git a/luni/src/test/java/libcore/java/net/AuthenticatorTest.java b/luni/src/test/java/libcore/java/net/AuthenticatorTest.java
new file mode 100644
index 0000000..f14e127
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/AuthenticatorTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 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.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.net.Authenticator;
+import java.net.InetAddress;
+import java.net.PasswordAuthentication;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class AuthenticatorTest {
+
+    private class MockAuthenticator extends Authenticator {
+        private int requests = 0;
+        private String userName;
+        private String password;
+
+        public void setUserName(String userName) {
+            this.userName = userName;
+        }
+
+        public void setPassword(String password) {
+            this.password = password;
+        }
+
+        @Override
+        protected PasswordAuthentication getPasswordAuthentication() {
+            ++requests;
+            return new PasswordAuthentication(userName, password.toCharArray());
+        }
+
+        public int getRequests() {
+            return requests;
+        }
+
+        public InetAddress getAddr() {
+            return getRequestingSite();
+        }
+
+        public int getPort() {
+            return getRequestingPort();
+        }
+
+        public String getProtocol() {
+            return getRequestingProtocol();
+        }
+
+        public String getPrompt() {
+            return getRequestingPrompt();
+        }
+
+        public String getScheme() {
+            return getRequestingScheme();
+        }
+
+        public String getHost() {
+            return getRequestingHost();
+        }
+    }
+
+    @Test
+    public void testRequestPasswordAuthentication() throws Exception {
+        final InetAddress addr = InetAddress.getByName("localhost");
+        final String host = "www.example.com";
+        final int port = 42;
+        final String protocol = "HTTP";
+        final String prompt = "Please enter your password";
+        final String scheme = "scheme";
+        final String userName = "007";
+        final String password = "super secret";
+
+        MockAuthenticator auth = new MockAuthenticator();
+        auth.setUserName(userName);
+        auth.setPassword(password);
+        Authenticator.setDefault(auth);
+        PasswordAuthentication passAuth = Authenticator.requestPasswordAuthentication(
+                addr, port, protocol, prompt, scheme);
+
+        assertNotNull(passAuth);
+        assertEquals(userName, passAuth.getUserName());
+        assertEquals(password, String.valueOf(passAuth.getPassword()));
+
+        assertEquals(1, auth.getRequests());
+        assertEquals(addr, auth.getAddr());
+        assertEquals(port, auth.getPort());
+        assertEquals(protocol, auth.getProtocol());
+        assertEquals(prompt, auth.getPrompt());
+        assertEquals(scheme, auth.getScheme());
+
+        passAuth = Authenticator.requestPasswordAuthentication(
+                host, addr, port, protocol, prompt, scheme);
+
+        assertNotNull(passAuth);
+        assertEquals(userName, passAuth.getUserName());
+        assertEquals(password, String.valueOf(passAuth.getPassword()));
+
+        assertEquals(host, auth.getHost());
+        assertEquals(2, auth.getRequests());
+        assertEquals(addr, auth.getAddr());
+        assertEquals(port, auth.getPort());
+        assertEquals(protocol, auth.getProtocol());
+        assertEquals(prompt, auth.getPrompt());
+        assertEquals(scheme, auth.getScheme());
+    }
+
+    @Test
+    public void testRequestPasswordAuthenticationWithNullAuthenticator() throws Exception {
+        final String host = "www.example.com";
+        final InetAddress addr = InetAddress.getByName("localhost");
+        final int port = 42;
+        final String protocol = "HTTP";
+        final String prompt = "Please enter your password";
+        final String scheme = "scheme";
+
+        Authenticator.setDefault(null);
+        assertNull(Authenticator.requestPasswordAuthentication(
+                addr, port, protocol, prompt, scheme));
+
+        assertNull(Authenticator.requestPasswordAuthentication(
+                host, addr, port, protocol, prompt, scheme));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
index fabed97..f6c3a27 100644
--- a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
+++ b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.net;
 
+import java.io.FileDescriptor;
 import java.lang.reflect.Field;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
@@ -219,4 +220,19 @@
       assertSame(packetAddr, newPacketAddr);
     }
   }
+
+  public void testGetFileDescriptor$() throws Exception {
+    final int port = 9999;
+
+    try(DatagramSocket s = new DatagramSocket()) {
+        s.connect(InetAddress.getLocalHost(), port);
+
+        FileDescriptor fd = s.getFileDescriptor$();
+        assertTrue(fd.valid());
+
+        s.disconnect();
+        fd = s.getFileDescriptor$();
+        assertTrue(fd.valid());
+    }
+  }
 }
diff --git a/luni/src/test/java/libcore/java/net/InetAddressTest.java b/luni/src/test/java/libcore/java/net/InetAddressTest.java
index 7d59ec0..097e94a 100644
--- a/luni/src/test/java/libcore/java/net/InetAddressTest.java
+++ b/luni/src/test/java/libcore/java/net/InetAddressTest.java
@@ -329,6 +329,18 @@
         } catch (UnknownHostException expected) {
         }
 
+
+        try {
+            InetAddress.getByNameOnNet(invalid, 0 /* NETID_UNSET */);
+            String msg = "Invalid IP address incorrectly recognized as valid: \"" + invalid + "\"";
+            if (InetAddressUtils.parseNumericAddressNoThrowStripOptionalBrackets(invalid) == null) {
+                msg += " (it was probably unexpectedly resolved by this network's DNS)";
+            }
+            msg += ".";
+            fail(msg);
+        } catch (UnknownHostException expected) {
+        }
+
         // exercise negative cache
         try {
             InetAddress.getByName(invalid);
@@ -346,6 +358,7 @@
     @Test
     public void test_getByName_valid(String valid) throws Exception {
         InetAddress.getByName(valid);
+        InetAddress.getAllByNameOnNet(valid, 0 /* NETID_UNSET */);
 
         // exercise positive cache
         InetAddress.getByName(valid);
diff --git a/luni/src/test/java/libcore/java/net/MalformedURLExceptionTest.java b/luni/src/test/java/libcore/java/net/MalformedURLExceptionTest.java
new file mode 100644
index 0000000..b60b7b8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/MalformedURLExceptionTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.net.MalformedURLException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class MalformedURLExceptionTest {
+
+    @Test
+    public void testConstructor() {
+        MalformedURLException e = new MalformedURLException();
+        assertNull(e.getMessage());
+
+        String msg = "x:yyy is not valid URL";
+        e = new MalformedURLException(msg);
+        assertEquals(msg, e.getMessage());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/NetPermissionTest.java b/luni/src/test/java/libcore/java/net/NetPermissionTest.java
new file mode 100644
index 0000000..db774da
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/NetPermissionTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.NetPermission;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class NetPermissionTest {
+
+    @Test
+    public void testConstructor() {
+        NetPermission permission = new NetPermission("name");
+        assertEquals("", permission.getName());
+
+        permission = new NetPermission("name", "action");
+        assertEquals("", permission.getName());
+        assertEquals("", permission.getActions());
+
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
index 555654e..e57b646 100644
--- a/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
+++ b/luni/src/test/java/libcore/java/net/NetworkInterfaceTest.java
@@ -41,6 +41,7 @@
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
 import libcore.io.Os;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.IFF_LOOPBACK;
@@ -114,10 +115,13 @@
         }
     }
 
-    public void testGetHardwareAddress_returnsNull() throws Exception {
-        // Hardware addresses should be unavailable to non-system apps.
+    public void testGetByIndex() throws Exception {
         for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
-            assertNull(nif.getHardwareAddress());
+            int nifIndex = nif.getIndex();
+            if (nifIndex == -1) { // -1 means unknown interface
+                continue;
+            }
+            assertEquals(nif, NetworkInterface.getByIndex(nifIndex));
         }
     }
 
diff --git a/luni/src/test/java/libcore/java/net/PortUnreachableExceptionTest.java b/luni/src/test/java/libcore/java/net/PortUnreachableExceptionTest.java
new file mode 100644
index 0000000..a85faa1
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/PortUnreachableExceptionTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.net.PortUnreachableException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PortUnreachableExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        PortUnreachableException e = new PortUnreachableException();
+        assertNull(e.getMessage());
+    }
+
+    @Test
+    public void testConstructor_withMsg() {
+        String msg = "test message";
+        PortUnreachableException e = new PortUnreachableException(msg);
+        assertEquals(msg, e.getMessage());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/SocketPermissionTest.java b/luni/src/test/java/libcore/java/net/SocketPermissionTest.java
new file mode 100644
index 0000000..2bedbef
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/SocketPermissionTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.net.SocketPermission;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SocketPermissionTest {
+
+    @Test
+    public void testGetAction() {
+        String host = "www.example.com";
+        String action = "Connect";
+        SocketPermission permission = new SocketPermission(host, action);
+        // permission.getActions() always returns null on Android.
+        assertNull(permission.getActions());
+    }
+
+    @Test
+    public void testImplies() {
+        String host = "www.example.com";
+        String action = "Connect";
+        SocketPermission permission = new SocketPermission(host, action);
+        // permission.implies() always returns true on Android.
+        assertTrue(permission.implies(null));
+        assertTrue(permission.implies(permission));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/SocketTest.java b/luni/src/test/java/libcore/java/net/SocketTest.java
index df12a29..8bb21ee 100644
--- a/luni/src/test/java/libcore/java/net/SocketTest.java
+++ b/luni/src/test/java/libcore/java/net/SocketTest.java
@@ -32,6 +32,9 @@
 import java.net.SocketAddress;
 import java.net.SocketException;
 import java.net.SocketImpl;
+import java.net.SocketOption;
+import java.net.SocketOptions;
+import java.net.StandardSocketOptions;
 import java.net.URI;
 import java.net.UnknownHostException;
 import java.nio.channels.ServerSocketChannel;
@@ -56,6 +59,15 @@
     // This hostname is required to resolve to 127.0.0.1 and ::1 for all tests to pass.
     private static final String ALL_LOOPBACK_HOSTNAME = "loopback46.unittest.grpc.io";
 
+    private static final InetAddress[] ALL_LOOPBACK_ADDRESSES = {
+        Inet4Address.LOOPBACK,
+        Inet6Address.LOOPBACK
+    };
+
+    {
+        sortAddresses(ALL_LOOPBACK_ADDRESSES);
+    }
+
     // From net/inet_ecn.h
     private static final int INET_ECN_MASK = 0x3;
 
@@ -191,47 +203,51 @@
         assertEquals(outLocalAddress.getPort(), outLocalAddressAfterClose.getPort());
     }
 
+    private static class MySocketImpl extends SocketImpl {
+        public int option;
+        public Object value;
+
+        public boolean createCalled;
+        public boolean createStream;
+
+        public MySocketImpl() { super(); }
+        @Override protected void accept(SocketImpl arg0) throws IOException { }
+        @Override protected int available() throws IOException { return 0; }
+        @Override protected void bind(InetAddress arg0, int arg1) throws IOException { }
+        @Override protected void close() throws IOException { }
+        @Override protected void connect(String arg0, int arg1) throws IOException { }
+        @Override protected void connect(InetAddress arg0, int arg1) throws IOException { }
+        @Override protected void connect(SocketAddress arg0, int arg1) throws IOException { }
+        @Override protected InputStream getInputStream() throws IOException { return null; }
+        @Override protected OutputStream getOutputStream() throws IOException { return null; }
+        @Override protected void listen(int arg0) throws IOException { }
+        @Override protected void sendUrgentData(int arg0) throws IOException { }
+        public Object getOption(int arg0) throws SocketException { return null; }
+
+        @Override protected void create(boolean isStream) throws IOException {
+            this.createCalled = true;
+            this.createStream = isStream;
+        }
+
+        public void setOption(int option, Object value) throws SocketException {
+            this.option = option;
+            this.value = value;
+        }
+
+        public <T> void setSuperOption(SocketOption<T> option, T value) throws IOException {
+            super.setOption(option, value);
+        }
+    }
+
+    private static class MySocket extends Socket {
+        public MySocket(SocketImpl impl) throws SocketException {
+            super(impl);
+        }
+    }
+
     // SocketOptions.setOption has weird behavior for setSoLinger/SO_LINGER.
     // This test ensures we do what the RI does.
     public void test_SocketOptions_setOption() throws Exception {
-        class MySocketImpl extends SocketImpl {
-            public int option;
-            public Object value;
-
-            public boolean createCalled;
-            public boolean createStream;
-
-            public MySocketImpl() { super(); }
-            @Override protected void accept(SocketImpl arg0) throws IOException { }
-            @Override protected int available() throws IOException { return 0; }
-            @Override protected void bind(InetAddress arg0, int arg1) throws IOException { }
-            @Override protected void close() throws IOException { }
-            @Override protected void connect(String arg0, int arg1) throws IOException { }
-            @Override protected void connect(InetAddress arg0, int arg1) throws IOException { }
-            @Override protected void connect(SocketAddress arg0, int arg1) throws IOException { }
-            @Override protected InputStream getInputStream() throws IOException { return null; }
-            @Override protected OutputStream getOutputStream() throws IOException { return null; }
-            @Override protected void listen(int arg0) throws IOException { }
-            @Override protected void sendUrgentData(int arg0) throws IOException { }
-            public Object getOption(int arg0) throws SocketException { return null; }
-
-            @Override protected void create(boolean isStream) throws IOException {
-                this.createCalled = true;
-                this.createStream = isStream;
-            }
-
-            public void setOption(int option, Object value) throws SocketException {
-                this.option = option;
-                this.value = value;
-            }
-        }
-
-        class MySocket extends Socket {
-            public MySocket(SocketImpl impl) throws SocketException {
-                super(impl);
-            }
-        }
-
         MySocketImpl impl = new MySocketImpl();
         Socket s = new MySocket(impl);
 
@@ -253,6 +269,30 @@
         assertEquals(Integer.valueOf(0), (Integer) impl.value);
         s.setSoLinger(true, 1);
         assertEquals(Integer.valueOf(1), (Integer) impl.value);
+
+        // API test for SocketImpl.setOption(SocketOption, Object).
+        // The value isn't sent to the kernel, because the mock intercepts the value in this test.
+        setAndAssertOption(impl, StandardSocketOptions.SO_KEEPALIVE,
+                SocketOptions.SO_KEEPALIVE, true);
+        setAndAssertOption(impl, StandardSocketOptions.SO_SNDBUF,
+                SocketOptions.SO_SNDBUF, 1);
+        setAndAssertOption(impl, StandardSocketOptions.SO_RCVBUF,
+                SocketOptions.SO_RCVBUF, 2);
+        setAndAssertOption(impl, StandardSocketOptions.SO_REUSEADDR,
+                SocketOptions.SO_REUSEADDR, true);
+        setAndAssertOption(impl, StandardSocketOptions.SO_LINGER,
+                SocketOptions.SO_LINGER, 3);
+        setAndAssertOption(impl, StandardSocketOptions.IP_TOS,
+                SocketOptions.IP_TOS, 4);
+        setAndAssertOption(impl, StandardSocketOptions.TCP_NODELAY,
+                SocketOptions.TCP_NODELAY, true);
+    }
+
+    private static void setAndAssertOption(MySocketImpl sockImpl, SocketOption option,
+            int optionInt, Object value) throws IOException {
+        sockImpl.setSuperOption(option, value);
+        assertEquals(sockImpl.option, optionInt);
+        assertEquals(sockImpl.value, value);
     }
 
     public void test_setTrafficClass() throws Exception {
@@ -596,17 +636,15 @@
 
     // b/30007735
     public void testSocketTestAllAddresses() throws Exception {
+        checkLoopbackHost();
+
         // Socket Ctor should try all sockets.
         //
         // This test creates server sockets bound to 127.0.0.1 and ::1, and connects using a
         // hostname that resolves to both addresses. We should be able to connect to the server
         // socket in either setup.
-        final String loopbackHost = ALL_LOOPBACK_HOSTNAME;
-
-        checkLoopbackHost(loopbackHost);
-
         final int port = 9999;
-        for (InetAddress addr : new InetAddress[]{ Inet4Address.LOOPBACK, Inet6Address.LOOPBACK }) {
+        for (InetAddress addr : ALL_LOOPBACK_ADDRESSES) {
             try (ServerSocket ss = new ServerSocket(port, 0, addr)) {
                 new Thread(() -> {
                     try {
@@ -616,21 +654,51 @@
                     }
                 }).start();
 
-                assertTrue(canConnect(loopbackHost, port));
+                assertTrue(canConnect(ALL_LOOPBACK_HOSTNAME, port));
             }
         }
     }
 
+    private static int compareInetAddress(InetAddress lhs, InetAddress rhs) {
+        return Arrays.compare(lhs.getAddress(), rhs.getAddress());
+    }
+
+    private static void sortAddresses(InetAddress[] addresses) {
+        Arrays.sort(addresses, (InetAddress lhs, InetAddress rhs) -> compareInetAddress(lhs, rhs));
+    }
+
+    private static boolean allUniqueLoopbackAddresses(InetAddress[] addresses) {
+        for (InetAddress a : addresses) {
+            if (!a.isLoopbackAddress()) {
+                return false;
+            }
+        }
+        return addresses.length <= 1 || (addresses.length == 2 && addresses[0] != addresses[1]);
+    }
+
     /** Confirm the supplied hostname maps to only loopback addresses, both IPv4 and IPv6. */
-    private static void checkLoopbackHost(String host) throws UnknownHostException {
-        InetAddress[] addrArray = InetAddress.getAllByName(host);
-        final String addressesString = Arrays.toString(addrArray);
-        List<InetAddress> addrs = Arrays.asList(addrArray);
-        final String msg = ALL_LOOPBACK_HOSTNAME
-                + " must only return loopback addresses, both IPv4 and IPv6. Got: "
-                + addressesString;
-        assertTrue(msg, addrs.stream().allMatch(InetAddress::isLoopbackAddress)
-                && addrs.contains(Inet4Address.LOOPBACK) && addrs.contains(Inet6Address.LOOPBACK));
+    private static void checkLoopbackHost() throws UnknownHostException {
+        // b/202426043 retry a few times since DNS maybe prone to being dropped or slow in
+        // responding and we have no control over the query or cache timeouts here.
+        final int WAIT_MILLIS = 2000;
+        for (int triesLeft = 2; triesLeft >= 0; --triesLeft) {
+            InetAddress[] addresses = InetAddress.getAllByName(ALL_LOOPBACK_HOSTNAME);
+            sortAddresses(addresses);
+            if (Arrays.equals(ALL_LOOPBACK_ADDRESSES, addresses)) {
+                return;
+            }
+
+            if (triesLeft == 0 || addresses.length > 2 || !allUniqueLoopbackAddresses(addresses)) {
+                fail("Expected " + Arrays.toString(ALL_LOOPBACK_ADDRESSES) +
+                     ", got " + Arrays.toString(addresses));
+            }
+
+            try {
+                Thread.sleep(WAIT_MILLIS);
+            } catch (InterruptedException e) {
+                fail("Test interrupted");
+            }
+        }
     }
 
     private static boolean canConnect(String host, int port) {
diff --git a/luni/src/test/java/libcore/java/net/URLClassLoaderTest.java b/luni/src/test/java/libcore/java/net/URLClassLoaderTest.java
new file mode 100644
index 0000000..598cf6d
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/URLClassLoaderTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class URLClassLoaderTest {
+
+    @Test
+    public void testClose() throws IOException {
+        URL[] urls = new URL[] { new URL("http://www.example.com.") };
+        URLClassLoader classLoader = new URLClassLoader(urls);
+        classLoader.close();
+    }
+}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index aecc1ad..3492193 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -26,6 +26,9 @@
 import com.google.mockwebserver.RecordedRequest;
 import com.google.mockwebserver.SocketPolicy;
 
+import java.lang.reflect.Field;
+import java.net.ContentHandler;
+import java.net.ContentHandlerFactory;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -2970,6 +2973,59 @@
         connection.disconnect();
     }
 
+    @Test public void setContentHandlerFactory() throws Exception {
+        // Verify that the static ContentHandlerFactory is null
+        Field f = URLConnection.class.getDeclaredField("factory");
+        f.setAccessible(true);
+        assertNull(f.get(null));
+
+        try {
+            URLConnection.setContentHandlerFactory(new MockContentHandlerFactory());
+            String msg = "ABC";
+            server.enqueue(new MockResponse()
+                    .addHeader("Content-Type: text/plain")
+                    .setBody(msg));
+            server.enqueue(new MockResponse()
+                    .addHeader("Content-Type: " + MockContentHandlerFactory.HANDLED_MIME_TYPE)
+                    .setBody(msg));
+            server.play();
+
+            HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
+            assertEquals("text/plain", connection.getContentType());
+            assertEquals(msg, readAscii((InputStream) connection.getContent()));
+
+            connection = (HttpURLConnection) server.getUrl("/").openConnection();
+            assertEquals(MockContentHandlerFactory.HANDLED_MIME_TYPE, connection.getContentType());
+            assertEquals(MockContentHandler.CONTENT, connection.getContent());
+        } finally {
+            // reset the static ContentHandlerFactory
+            f.set(null, null);
+        }
+    }
+
+    private static class MockContentHandler extends ContentHandler {
+
+        private static final String CONTENT = "SECRET_CONTENT";
+
+        @Override
+        public Object getContent(URLConnection urlc) throws IOException {
+            return CONTENT;
+        }
+    }
+
+    private static class MockContentHandlerFactory implements ContentHandlerFactory {
+
+        private static final String HANDLED_MIME_TYPE = "text/secret";
+
+        @Override
+        public ContentHandler createContentHandler(String mimetype) {
+            if (HANDLED_MIME_TYPE.equals(mimetype)) {
+                return new MockContentHandler();
+            }
+            return null;
+        }
+    }
+
     // http://b/4361656
     @Test public void urlContainsQueryButNoPath() throws Exception {
         server.enqueue(new MockResponse().setBody("A"));
diff --git a/luni/src/test/java/libcore/java/net/UrlEncodingTest.java b/luni/src/test/java/libcore/java/net/UrlEncodingTest.java
index babecf1..71a70d7 100644
--- a/luni/src/test/java/libcore/java/net/UrlEncodingTest.java
+++ b/luni/src/test/java/libcore/java/net/UrlEncodingTest.java
@@ -106,7 +106,7 @@
 
     public void testUrlDecoderFailsOnNullCharset() throws Exception {
         try {
-            URLDecoder.decode("ab", null);
+            URLDecoder.decode("ab", (String) null);
             fail();
         } catch (IllegalCharsetNameException expected) {
         } catch (NullPointerException expected) {
@@ -124,7 +124,7 @@
 
     public void testUrlEncoderFailsOnNullCharset() throws Exception {
         try {
-            URLEncoder.encode("ab", null);
+            URLEncoder.encode("ab", (String) null);
             fail();
         } catch (IllegalCharsetNameException expected) {
         } catch (NullPointerException expected) {
@@ -148,7 +148,7 @@
         try {
             assertEquals("ab", URLDecoder.decode("ab", "no-such-charset"));
             // no fail()
-        } catch (UnsupportedCharsetException expected) {
+        } catch (UnsupportedEncodingException expected) {
         }
     }
 
diff --git a/luni/src/test/java/libcore/java/nio/BufferTest.java b/luni/src/test/java/libcore/java/nio/BufferTest.java
index f808092..e826967 100644
--- a/luni/src/test/java/libcore/java/nio/BufferTest.java
+++ b/luni/src/test/java/libcore/java/nio/BufferTest.java
@@ -251,6 +251,14 @@
         b.order(ByteOrder.LITTLE_ENDIAN);
         assertEquals(ByteOrder.BIG_ENDIAN, b.slice().order());
 
+        // alignedSlice always returns a big-endian buffer.
+        b.order(ByteOrder.BIG_ENDIAN);
+        assertEquals(ByteOrder.BIG_ENDIAN, b.alignedSlice(4).order());
+        assertEquals(0, b.alignedSlice(4).alignmentOffset(0, 4));
+        b.order(ByteOrder.LITTLE_ENDIAN);
+        assertEquals(ByteOrder.BIG_ENDIAN, b.alignedSlice(4).order());
+        assertEquals(0, b.alignedSlice(2).alignmentOffset(0, 2));
+
         // asXBuffer always returns a current-endian buffer.
         b.order(ByteOrder.BIG_ENDIAN);
         assertEquals(ByteOrder.BIG_ENDIAN, b.asCharBuffer().order());
@@ -639,6 +647,27 @@
         assertEquals(directBuffer.arrayOffset() + 1, directSlice.arrayOffset());
     }
 
+    public void testAlignedSliceOffset() throws Exception {
+        final ByteBuffer [] buffers = {
+            ByteBuffer.allocate(10),
+            ByteBuffer.allocateDirect(10),
+            ByteBuffer.wrap(new byte[10]),
+            ByteBuffer.wrap(new byte[10], 1, 8),
+        };
+
+        for (ByteBuffer buffer: buffers) {
+            for (int i = 0; i < 4; ++i) {
+                // Slicing changes the array offset.
+                ByteBuffer slice = ((ByteBuffer) buffer.duplicate().position(i)).alignedSlice(4);
+                for (int j = 0; j < 4; ++j) {
+                    assertEquals(j, slice.alignmentOffset(j, 4));
+                }
+                assertEquals(0, slice.limit() % 4);
+                assertTrue(buffer.limit() > 0);
+            }
+        }
+    }
+
     // http://code.google.com/p/android/issues/detail?id=16184
     public void testPutByteBuffer() throws Exception {
         ByteBuffer dst = ByteBuffer.allocate(10).asReadOnlyBuffer();
@@ -1441,4 +1470,41 @@
         FinalizationTester.induceFinalization();
         assertTrue(pr.isEnqueued());
     }
+
+    private void alignmentOffsetChecks(final ByteBuffer buffer) {
+
+        for (int start = 0; start < buffer.limit(); ++start) {
+            buffer.position(start);
+            final ByteBuffer bb = buffer.slice();
+            for (int unitSize = 1; unitSize <= 8; unitSize *= 2) {
+                try {
+                    bb.alignmentOffset(-1 - start, unitSize);
+                    fail();
+                } catch (IllegalArgumentException expected) {
+                }
+
+                if (unitSize > 2) {
+                    try {
+                        bb.alignmentOffset(0, unitSize - 1);
+                        fail();
+                    } catch (IllegalArgumentException expected) {
+                    }
+                }
+
+                int alignmentAtZero = bb.alignmentOffset(0, unitSize);
+                for (int i = 0; i < bb.limit(); ++i) {
+                    assertEquals((alignmentAtZero + i) % unitSize, bb.alignmentOffset(i, unitSize));
+                }
+            }
+        }
+    }
+
+    public void test_alignmentOffset() throws Exception {
+        alignmentOffsetChecks(ByteBuffer.allocateDirect(32));
+        alignmentOffsetChecks(ByteBuffer.allocate(32));
+
+        byte[] array = new byte[32];
+        alignmentOffsetChecks(ByteBuffer.wrap(array));
+        alignmentOffsetChecks(ByteBuffer.wrap(array, 1, 31));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java
index 3b072f2..43f5b7d 100644
--- a/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/AsynchronousFileChannelTest.java
@@ -27,8 +27,10 @@
 import java.nio.channels.AsynchronousFileChannel;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.CompletionHandler;
+import java.nio.channels.FileLock;
 import java.nio.channels.NonReadableChannelException;
 import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
 import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
@@ -701,4 +703,67 @@
         } catch(ClosedChannelException expected) {}
     }
 
+    static class LockHandler implements CompletionHandler<FileLock, Integer> {
+        public FileLock fileLock;
+        public Throwable exc;
+
+        private final CountDownLatch cdl = new CountDownLatch(1);
+
+        @Override
+        public void completed(FileLock fileLock, Integer attachment) {
+            this.fileLock = fileLock;
+
+            cdl.countDown();
+        }
+
+        @Override
+        public void failed(Throwable exc, Integer attachment) {
+            this.exc = exc;
+        }
+
+        public boolean awaitCompletion() throws InterruptedException {
+            return cdl.await(10, TimeUnit.SECONDS);
+        }
+    }
+
+
+    @Test
+    public void testLock() throws Exception {
+        File temp = createTemporaryFile(256);
+        assertEquals(256, temp.length());
+        AsynchronousFileChannel afc = AsynchronousFileChannel.open(temp.toPath(),
+                StandardOpenOption.WRITE);
+        LockHandler handler = new LockHandler();
+
+        afc.lock(null, handler);
+        assertTrue(handler.awaitCompletion());
+        assertNotNull(handler.fileLock);
+        assertNull(handler.exc);
+        assertTrue(handler.fileLock.isValid());
+        assertFalse(handler.fileLock.isShared());
+
+        AsynchronousFileChannel otherAfc = AsynchronousFileChannel.open(temp.toPath(),
+                StandardOpenOption.WRITE);
+        LockHandler otherHandler = new LockHandler();
+        try {
+            otherAfc.lock(null, otherHandler);
+            fail();
+        } catch (OverlappingFileLockException expected) {
+        }
+
+        handler.fileLock.release();
+
+        otherHandler = new LockHandler();
+        otherAfc.lock(null, otherHandler);
+        assertTrue(otherHandler.awaitCompletion());
+        assertNotNull(otherHandler.fileLock);
+        assertNull(otherHandler.exc);
+        assertTrue(otherHandler.fileLock.isValid());
+
+        otherHandler.fileLock.release();
+
+        afc.close();
+        otherAfc.close();
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/FileLockTest.java b/luni/src/test/java/libcore/java/nio/channels/FileLockTest.java
new file mode 100644
index 0000000..dbf72f9
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/channels/FileLockTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 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.nio.channels;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FileLockTest {
+
+    @Test
+    public void testToString() throws Exception {
+        File tmp = File.createTempFile("FileLockTest", "tmp");
+
+        try(FileOutputStream fos = new FileOutputStream(tmp)) {
+            try(FileChannel fc = fos.getChannel()) {
+                FileLock lock = fc.lock(0, 42, false);
+                String strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("exclusive"));
+                assertTrue(strLock.contains("valid"));
+                assertFalse(strLock.contains("invalid"));
+
+                lock.release();
+                strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("exclusive"));
+                assertTrue(strLock.contains("invalid"));
+            }
+        }
+
+        try(FileInputStream fis = new FileInputStream(tmp)) {
+            try(FileChannel fc = fis.getChannel()) {
+                FileLock lock = fc.lock(0, 42, true);
+                String strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("shared"));
+                assertTrue(strLock.contains("valid"));
+                assertFalse(strLock.contains("invalid"));
+
+                lock.release();
+                strLock = lock.toString();
+                assertTrue(strLock.contains("0"));
+                assertTrue(strLock.contains("42"));
+                assertTrue(strLock.contains("shared"));
+                assertTrue(strLock.contains("invalid"));
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/ClosedFileSystemExceptionTest.java b/luni/src/test/java/libcore/java/nio/file/ClosedFileSystemExceptionTest.java
new file mode 100644
index 0000000..f209899
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/ClosedFileSystemExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.nio.file;
+
+import static org.junit.Assert.assertNull;
+
+import java.nio.file.ClosedFileSystemException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ClosedFileSystemExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        ClosedFileSystemException exception = new ClosedFileSystemException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTest.java b/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTest.java
index 4d2f4cb..54d9b43 100644
--- a/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/LinuxFileSystemTest.java
@@ -17,6 +17,7 @@
 package libcore.java.nio.file;
 
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -89,10 +90,61 @@
     @Test
     public void test_getFileStores() {
         Iterable<FileStore> fileStores = fileSystem.getFileStores();
-        // Asserting if the the list has non zero number stores.
+        // The FileSystem should have at least one FileStore
         assertTrue(fileStores.iterator().hasNext());
     }
 
+    // It's difficult to make assumptions that are true across all test targets.
+    // The root FileStore may or may not be full (on devices the System image is usually
+    // 100% full and read-only, on hosts usable space will be positive).
+    // /data should *usually* exist (on devices, at least), be writable and have some
+    // usable space.
+    @Test
+    public void rootFilestore() throws Exception {
+        FileStore filestore = getFilestore("/");
+        assertEquals(0, filestore.getBlockSize() % 512);
+        assertTrue(filestore.getTotalSpace() > 0);
+        assertTrue(filestore.getUnallocatedSpace() >= 0);
+        assertTrue(filestore.getUsableSpace() >= 0);
+    }
+
+    // See explanation for rootFilestore()
+    @Test
+    public void dataFilestore() throws Exception {
+        FileStore filestore = null;
+        try {
+            filestore = getFilestore("/data");
+        } catch (IOException e) {
+            // Ignored
+        }
+        Assume.assumeNotNull(filestore);
+        assertEquals(0, filestore.getBlockSize() % 512);
+        assertTrue(filestore.getTotalSpace() > 0);
+        assertTrue(filestore.getUnallocatedSpace() > 0);
+        assertTrue(filestore.getUsableSpace() > 0);
+        assertFalse(filestore.isReadOnly());
+    }
+
+    // File.getFileStore(path) throws a SecurityException on Android, so we
+    // iterate over all file stores until we find a matching mount point.
+    private FileStore getFilestore(String mountPoint) throws IOException {
+        for (FileStore filestore : fileSystem.getFileStores()) {
+            if (mountPoint.equals(getMountPoint(filestore))) {
+                return filestore;
+            }
+        }
+        fail("Unable to find FileStore for " + mountPoint);
+        return null;
+    }
+
+    // Naturally there is no official API to get the mount point for a FileStore,
+    // so we rely on the fact that the string representation is always "<mountpoint> (<device>)"
+    private String getMountPoint(FileStore fileStore) {
+        String description = fileStore.toString();
+        int index = description.indexOf(" (");
+        return description.substring(0, index);
+    }
+
     @Test
     public void test_supportedFileAttributeViews() {
         Set<String> supportedFileAttributeViewsList = fileSystem.supportedFileAttributeViews();
diff --git a/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java b/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java
index 277db4f..480d9b4 100644
--- a/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/ProviderNotFoundExceptionTest.java
@@ -22,6 +22,12 @@
 
 public class ProviderNotFoundExceptionTest extends TestCase {
 
+    public void test_constructor$() {
+        ProviderNotFoundException exception = new ProviderNotFoundException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+
     public void test_constructor$String() {
         String message = "message";
         ProviderNotFoundException exception = new ProviderNotFoundException(message);
diff --git a/luni/src/test/java/libcore/java/nio/file/ReadOnlyFileSystemExceptionTest.java b/luni/src/test/java/libcore/java/nio/file/ReadOnlyFileSystemExceptionTest.java
new file mode 100644
index 0000000..b89eccd
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/ReadOnlyFileSystemExceptionTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.nio.file;
+
+import static org.junit.Assert.assertNull;
+
+import java.nio.file.ReadOnlyFileSystemException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ReadOnlyFileSystemExceptionTest {
+
+    @Test
+    public void testEmptyConstructor() {
+        ReadOnlyFileSystemException exception = new ReadOnlyFileSystemException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java b/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java
index 6e0ccd8..0464faf 100644
--- a/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java
+++ b/luni/src/test/java/libcore/java/nio/file/attribute/AclEntryTest.java
@@ -55,4 +55,31 @@
         assertEquals(1, flags.size());
         assertTrue(flags.contains(AclEntryFlag.INHERIT_ONLY));
     }
+
+    @Test
+    public void testBuilder() throws Exception {
+        UserPrincipal user = Files.getOwner(Paths.get("."));
+
+        AclEntry aclEntry = AclEntry.newBuilder()
+            .setType(AclEntryType.ALLOW)
+            .setPrincipal(user)
+            .setFlags(AclEntryFlag.INHERIT_ONLY)
+            .setPermissions(AclEntryPermission.READ_DATA, AclEntryPermission.READ_ATTRIBUTES)
+            .build();
+
+        AclEntry.Builder builder = AclEntry.newBuilder(aclEntry);
+        aclEntry = builder.build();
+
+        assertEquals(AclEntryType.ALLOW, aclEntry.type());
+        assertEquals(user, aclEntry.principal());
+
+        Set<AclEntryPermission> permissions = aclEntry.permissions();
+        assertEquals(2, permissions.size());
+        assertTrue(permissions.contains(AclEntryPermission.READ_DATA));
+        assertTrue(permissions.contains(AclEntryPermission.READ_ATTRIBUTES));
+
+        Set<AclEntryFlag> flags = aclEntry.flags();
+        assertEquals(1, flags.size());
+        assertTrue(flags.contains(AclEntryFlag.INHERIT_ONLY));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/file/spi/FileSystemProviderTest.java b/luni/src/test/java/libcore/java/nio/file/spi/FileSystemProviderTest.java
new file mode 100644
index 0000000..82c58a1
--- /dev/null
+++ b/luni/src/test/java/libcore/java/nio/file/spi/FileSystemProviderTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2021 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.nio.file.spi;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.AccessMode;
+import java.nio.file.CopyOption;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.LinkOption;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.FileAttributeView;
+import java.nio.file.spi.FileSystemProvider;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FileSystemProviderTest {
+
+    class MockFileSystemProvider extends FileSystemProvider {
+        @Override
+        public String getScheme() {
+            return "mock";
+        }
+
+        @Override
+        public FileSystem newFileSystem(URI uri, Map<String,?> env) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public FileSystem getFileSystem(URI uri) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Path getPath(URI uri) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public SeekableByteChannel newByteChannel(Path path,
+                Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public DirectoryStream<Path> newDirectoryStream(Path dir,
+                DirectoryStream.Filter<? super Path> filter) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void delete(Path path) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void copy(Path source, Path target, CopyOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void move(Path source, Path target, CopyOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isSameFile(Path path, Path path2) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isHidden(Path path) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public FileStore getFileStore(Path path) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void checkAccess(Path path, AccessMode... modes) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public <V extends FileAttributeView> V getFileAttributeView(
+                Path path, Class<V> type, LinkOption... options) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public <A extends BasicFileAttributes> A readAttributes(
+                Path path, Class<A> type, LinkOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Map<String,Object> readAttributes(
+                Path path, String attributes, LinkOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void setAttribute(Path path, String attribute,
+                Object value, LinkOption... options) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Test
+    public void testCreateLink() throws Exception {
+        MockFileSystemProvider provider = new MockFileSystemProvider();
+
+        Path link = Paths.get("testdir");
+        Path existing = Paths.get("testfile");
+
+        try {
+            provider.createLink(link, existing);
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException expected) {
+        }
+    }
+
+    @Test
+    public void testNewAsynchronousFileChannel() throws Exception {
+        MockFileSystemProvider provider = new MockFileSystemProvider();
+
+        Path path = Paths.get("testfile");
+        Set<OpenOption> options = new TreeSet<OpenOption>();
+
+        try {
+            provider.newAsynchronousFileChannel(path, options, null);
+            fail("Expected UnsupportedOperationException");
+        } catch(UnsupportedOperationException expected) {
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/security/spec/EdECPointTest.java b/luni/src/test/java/libcore/java/security/spec/EdECPointTest.java
new file mode 100644
index 0000000..95b3951
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/spec/EdECPointTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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.security.spec;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.security.spec.EdECPoint;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class EdECPointTest {
+
+    @Test
+    public void testConstructor() {
+        EdECPoint p = new EdECPoint(false, BigInteger.TEN);
+        assertFalse(p.isXOdd());
+        assertEquals(BigInteger.TEN, p.getY());
+
+        p = new EdECPoint(true, BigInteger.valueOf(Long.MAX_VALUE));
+        assertTrue(p.isXOdd());
+        assertEquals(BigInteger.valueOf(Long.MAX_VALUE), p.getY());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/security/spec/EdECPrivateKeySpecTest.java b/luni/src/test/java/libcore/java/security/spec/EdECPrivateKeySpecTest.java
new file mode 100644
index 0000000..f5e0604
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/spec/EdECPrivateKeySpecTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 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.security.spec;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.security.spec.EdECPrivateKeySpec;
+import java.security.spec.NamedParameterSpec;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class EdECPrivateKeySpecTest {
+
+    @Test
+    public void testConstructor() {
+        byte[] bytes = new byte[] {9, 8, 7};
+        EdECPrivateKeySpec keySpec = new EdECPrivateKeySpec(NamedParameterSpec.ED448, bytes);
+        assertEquals(NamedParameterSpec.ED448, keySpec.getParams());
+        assertArrayEquals(bytes, keySpec.getBytes());
+
+        bytes = new byte[] {1, 3, 5, 7, 9};
+        keySpec = new EdECPrivateKeySpec(NamedParameterSpec.ED25519, bytes);
+        assertEquals(NamedParameterSpec.ED25519, keySpec.getParams());
+        assertArrayEquals(bytes, keySpec.getBytes());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/security/spec/EdECPublicKeySpecTest.java b/luni/src/test/java/libcore/java/security/spec/EdECPublicKeySpecTest.java
new file mode 100644
index 0000000..cc58871
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/spec/EdECPublicKeySpecTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.security.spec;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+import java.security.spec.EdECPoint;
+import java.security.spec.EdECPublicKeySpec;
+import java.security.spec.NamedParameterSpec;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class EdECPublicKeySpecTest {
+
+    @Test
+    public void testConstructor() {
+        EdECPoint point = new EdECPoint(true, BigInteger.ONE);
+        EdECPublicKeySpec keySpec = new EdECPublicKeySpec(NamedParameterSpec.ED448, point);
+        assertEquals(NamedParameterSpec.ED448, keySpec.getParams());
+        assertEquals(point.isXOdd(), keySpec.getPoint().isXOdd());
+        assertEquals(point.getY(), keySpec.getPoint().getY());
+
+        point = new EdECPoint(false, BigInteger.TEN);
+        keySpec = new EdECPublicKeySpec(NamedParameterSpec.ED25519, point);
+        assertEquals(NamedParameterSpec.ED25519, keySpec.getParams());
+        assertEquals(point.isXOdd(), keySpec.getPoint().isXOdd());
+        assertEquals(point.getY(), keySpec.getPoint().getY());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/security/spec/XECPrivateKeySpecTest.java b/luni/src/test/java/libcore/java/security/spec/XECPrivateKeySpecTest.java
new file mode 100644
index 0000000..64b84e1
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/spec/XECPrivateKeySpecTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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.security.spec;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.XECPrivateKeySpec;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class XECPrivateKeySpecTest {
+
+    @Test
+    public void testConstructor() {
+        byte[] scalar = new byte[] {9, 8, 7};
+        XECPrivateKeySpec keySpec = new XECPrivateKeySpec(NamedParameterSpec.X25519, scalar);
+        assertEquals(NamedParameterSpec.X25519, keySpec.getParams());
+        assertArrayEquals(scalar, keySpec.getScalar());
+
+        scalar = new byte[] {1, 3, 5, 7, 9};
+        keySpec = new XECPrivateKeySpec(MGF1ParameterSpec.SHA512, scalar);
+        assertEquals(MGF1ParameterSpec.SHA512, keySpec.getParams());
+        assertArrayEquals(scalar, keySpec.getScalar());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/security/spec/XECPublicKeySpecTest.java b/luni/src/test/java/libcore/java/security/spec/XECPublicKeySpecTest.java
new file mode 100644
index 0000000..5d4f8b1
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/spec/XECPublicKeySpecTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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.security.spec;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.XECPublicKeySpec;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class XECPublicKeySpecTest {
+
+    @Test
+    public void testConstructor() {
+        XECPublicKeySpec keySpec = new XECPublicKeySpec(NamedParameterSpec.X25519, BigInteger.TEN);
+        assertEquals(NamedParameterSpec.X25519, keySpec.getParams());
+        assertEquals(BigInteger.TEN, keySpec.getU());
+
+        keySpec = new XECPublicKeySpec(MGF1ParameterSpec.SHA512, BigInteger.ONE);
+        assertEquals(MGF1ParameterSpec.SHA512, keySpec.getParams());
+        assertEquals(BigInteger.ONE, keySpec.getU());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/sql/BatchUpdateExceptionTest.java b/luni/src/test/java/libcore/java/sql/BatchUpdateExceptionTest.java
new file mode 100644
index 0000000..862a977
--- /dev/null
+++ b/luni/src/test/java/libcore/java/sql/BatchUpdateExceptionTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.sql;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import java.sql.BatchUpdateException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class BatchUpdateExceptionTest {
+
+    @Test
+    public void testConstructor() {
+        String reason = "exception reason";
+        Throwable cause = new RuntimeException();
+        int[] updateCounts = {9, 5, 6};
+        BatchUpdateException exception = new BatchUpdateException(reason, updateCounts, cause);
+        assertEquals(reason, exception.getMessage());
+        assertArrayEquals(updateCounts, exception.getUpdateCounts());
+        assertSame(cause, exception.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/sql/DriverManagerTest.java b/luni/src/test/java/libcore/java/sql/DriverManagerTest.java
new file mode 100644
index 0000000..f06da7b
--- /dev/null
+++ b/luni/src/test/java/libcore/java/sql/DriverManagerTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.sql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.sql.DriverManager;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DriverManagerTest {
+
+    @Test
+    public void testSetLoginTimeout() {
+        int originalTimeout = DriverManager.getLoginTimeout();
+
+        try {
+            int timeout = 9999;
+            DriverManager.setLoginTimeout(timeout);
+            assertEquals(timeout, DriverManager.getLoginTimeout());
+        } finally {
+            DriverManager.setLoginTimeout(originalTimeout);
+        }
+    }
+
+    @Test
+    public void testSetLogWriter() {
+        PrintWriter originalWriter = DriverManager.getLogWriter();
+
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            PrintWriter writer = new PrintWriter(baos);
+            DriverManager.setLogWriter(writer);
+            assertSame(writer, DriverManager.getLogWriter());
+            String msg = "secret message";
+            DriverManager.println(msg);
+            assertEquals(msg + "\n",  baos.toString());
+        } finally {
+            DriverManager.setLogWriter(originalWriter);
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/sql/DriverTest.java b/luni/src/test/java/libcore/java/sql/DriverTest.java
index 59d13bd..69ba859 100644
--- a/luni/src/test/java/libcore/java/sql/DriverTest.java
+++ b/luni/src/test/java/libcore/java/sql/DriverTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.sql;
 
+import java.util.Collections;
 import junit.framework.TestCase;
 
 import SQLite.JDBCDriver;
@@ -68,6 +69,15 @@
         assertFalse(getDriver().jdbcCompliant());
     }
 
+    public void testGetDrivers() {
+        for (Driver driver : Collections.list(DriverManager.getDrivers())) {
+            if (driver instanceof JDBCDriver) {
+                return;
+            }
+        }
+        fail("DriverManager.getDrivers() doesn't return a Sqlite JDBC driver.");
+    }
+
     private Driver getDriver() throws SQLException {
         Driver driver = DriverManager.getDriver(SQLITE_JDBC_URL);
         assertNotNull(driver);
diff --git a/luni/src/test/java/libcore/java/sql/SQLClientInfoExceptionTest.java b/luni/src/test/java/libcore/java/sql/SQLClientInfoExceptionTest.java
new file mode 100644
index 0000000..82da184
--- /dev/null
+++ b/luni/src/test/java/libcore/java/sql/SQLClientInfoExceptionTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.sql;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.ClientInfoStatus;
+import java.sql.SQLClientInfoException;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SQLClientInfoExceptionTest {
+
+    @Test
+    public void testConstructor() {
+        String reason = "secret reason";
+        String sqlState = "random SQL state";
+        int vendorCode = 1234;
+        Map<String, ClientInfoStatus> failedProps = new HashMap<String, ClientInfoStatus>() {{
+            put("key1", ClientInfoStatus.REASON_VALUE_TRUNCATED);
+        }};
+        SQLClientInfoException exception = new SQLClientInfoException(reason, sqlState,
+                vendorCode, failedProps);
+        assertEquals(reason, exception.getMessage());
+        assertEquals(sqlState, exception.getSQLState());
+        assertEquals(vendorCode, exception.getErrorCode());
+        assertEquals(failedProps, exception.getFailedProperties());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/sql/SQLPermissionTest.java b/luni/src/test/java/libcore/java/sql/SQLPermissionTest.java
new file mode 100644
index 0000000..0a0e812
--- /dev/null
+++ b/luni/src/test/java/libcore/java/sql/SQLPermissionTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.sql;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.SQLPermission;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SQLPermissionTest {
+
+    @Test
+    public void testConstructor() {
+        SQLPermission permission = new SQLPermission("name", "action");
+        assertEquals("", permission.getName());
+        assertEquals("", permission.getActions());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/text/DateFormatTest.java b/luni/src/test/java/libcore/java/text/DateFormatTest.java
index 8e215ab..83505e5 100644
--- a/luni/src/test/java/libcore/java/text/DateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DateFormatTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.text;
 
+import java.util.TimeZone;
 import junit.framework.TestCase;
 
 import java.text.DateFormat;
@@ -56,4 +57,12 @@
         String expectedDateString = sdf.format(current);
         assertEquals(expectedDateString, actualDateString);
     }
+
+    public void testGetTimeInstance_withLocaleExtension() {
+        Locale locale = Locale.forLanguageTag("en-u-tz-usden");
+        DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT, locale);
+        // Note: when Calendar class supports "tz" extension, it should return "America/Denver".
+        assertEquals(TimeZone.getDefault().getID(), df.getCalendar().getTimeZone().getID());
+        // assertEquals("America/Denver", df.getCalendar().getTimeZone().getID());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/text/NumberFormatTest.java b/luni/src/test/java/libcore/java/text/NumberFormatTest.java
index 547653f..599630b 100644
--- a/luni/src/test/java/libcore/java/text/NumberFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/NumberFormatTest.java
@@ -260,4 +260,14 @@
         format.setCurrency(Currency.getInstance("USD"));
         assertEquals("$10", format.format(10d));
     }
+
+    public void test_getInstance_withLocaleExtension() {
+        Locale locale = Locale.US;
+        NumberFormat numberFormat = NumberFormat.getNumberInstance(locale);
+        assertEquals("123", numberFormat.format(123));
+
+        locale = Locale.forLanguageTag("en-US-u-nu-arab");
+        numberFormat = NumberFormat.getNumberInstance(locale);
+        assertEquals("١٢٣", numberFormat.format(123));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
index 9df9e43..3e7bb98 100644
--- a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
@@ -47,7 +47,7 @@
         assertEquals(0, format.getMaximumFractionDigits());
         assertTrue(format.isParseIntegerOnly());
 
-        Locale arLocale = new Locale("ar", "AE");
+        Locale arLocale = new Locale("ar", "EG");
         format = (DecimalFormat) NumberFormat.getIntegerInstance(arLocale);
         String variant = (format.toPattern().indexOf(';') > 0) ? "#,##0;-#,##0" : "#,##0";
         assertEquals(variant, format.toPattern());
diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
index 245cd3d..4d90116 100644
--- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.text;
 
+import android.icu.util.VersionInfo;
 import libcore.util.Nullable;
 import java.text.DateFormat;
 import java.text.DateFormatSymbols;
@@ -592,7 +593,10 @@
         String timeZonePattern = "zzzz";
         int timeZoneStyle = TimeZone.LONG;
         doTestFormat(Locale.ENGLISH, timeZoneStyle, timeZonePattern, "Coordinated Universal Time");
-        doTestFormat(Locale.FRANCE, timeZoneStyle, timeZonePattern, "Temps universel coordonné");
+        doTestFormat(Locale.FRANCE, timeZoneStyle, timeZonePattern,
+            VersionInfo.ICU_VERSION.getMajor() >= 70
+                ? "temps universel coordonné"
+                : "Temps universel coordonné");
         doTestFormat(Locale.SIMPLIFIED_CHINESE, timeZoneStyle, timeZonePattern, "协调世界时");
     }
 
@@ -632,7 +636,9 @@
         doUtcParsingTest(Locale.ENGLISH, timeZonePattern, timeZoneStyle,
                 "Coordinated Universal Time");
         doUtcParsingTest(Locale.FRENCH, timeZonePattern, timeZoneStyle,
-                "Temps universel coordonné");
+            VersionInfo.ICU_VERSION.getMajor() >= 70
+                ? "temps universel coordonné"
+                : "Temps universel coordonné");
         doUtcParsingTest(Locale.SIMPLIFIED_CHINESE, timeZonePattern, timeZoneStyle,
                 "协调世界时");
     }
diff --git a/luni/src/test/java/libcore/java/time/BionicTzdbConsistencyTest.java b/luni/src/test/java/libcore/java/time/BionicTzdbConsistencyTest.java
new file mode 100644
index 0000000..7ba2518
--- /dev/null
+++ b/luni/src/test/java/libcore/java/time/BionicTzdbConsistencyTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2021 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.time;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import dalvik.system.VMRuntime;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.zone.ZoneOffsetTransition;
+import java.time.zone.ZoneRules;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TimeZone;
+
+/**
+ * Tests that bionic's interpretation of the TZDB rules on a device matches Android's java.time
+ * behavior. On Android, java.time is implemented using ICU4J, so these confirm that bionic's
+ * understanding of TZDB transitions and UTC offsets matches those of ICU4J.
+ */
+@RunWith(Parameterized.class)
+public class BionicTzdbConsistencyTest {
+
+    // The lower bound for testing.
+    private static final LocalDateTime START_DATE;
+
+    // The upper bound for testing.
+    private static final LocalDateTime END_DATE;
+
+    static {
+        // time_t is platform dependent on Linux at the moment of writing. So we can't test dates
+        // outside of the range allowed by 32-bit integer.
+        if (VMRuntime.getRuntime().is64Bit()) {
+            // Chosen because TZDB has no rules defined prior to this date.
+            START_DATE = LocalDateTime.of(1800, 1, 1, 0, 0);
+            // Chosen because it's considered to be sufficiently in the future that Android devices
+            // won't be running. Any TZDB entries affecting this date are recurring so going beyond
+            // shouldn't do anything unexpected.
+            END_DATE = LocalDateTime.of(2100, 1, 1, 0, 0);
+        } else {
+            // Date close to minimal value allowed by 32-bit integer.
+            START_DATE = LocalDateTime.of(1902, 1, 1, 0, 0);
+            // Date close to maximal value allowed by 32-bit integer.
+            END_DATE = LocalDateTime.of(2038, 1, 1, 0, 0);
+        }
+    }
+
+    // Android's DateTimeFormatter implementation formats time zone as offset only for historic
+    // dates on certain time zones, while bionic takes abbreviation from TZif file.
+    // So time zone is not included here because we know it can differ. Equality of numeric local
+    // date/time components implies that used offsets were the same in libcore and bionic.
+    private static final DateTimeFormatter FORMATTER =
+            DateTimeFormatter.ofPattern("dd MM yyyy HH:mm:ss").withLocale(Locale.US);
+
+    private static final Set<Duration> INTERESTING_OFFSETS =
+            Set.of(Duration.ZERO, Duration.ofMinutes(30), Duration.ofMinutes(-30),
+                    Duration.ofHours(1), Duration.ofHours(-1),
+                    Duration.ofHours(2), Duration.ofHours(-2),
+                    Duration.ofDays(1), Duration.ofDays(-1));
+
+    @Parameters(name = "{0}")
+    public static String[] getZoneIds() {
+        // We use java.util.TimeZone.getAvailableIDs() since that uses the IDs from TZDB, not the
+        // expanded set recognized by ICU.
+        String[] zones = TimeZone.getAvailableIDs();
+        assertNotEquals("no zones returned", 0, zones.length);
+        return zones;
+    }
+
+    static {
+        System.loadLibrary("javacoretests");
+    }
+
+    private final String timeZoneId;
+
+    public BionicTzdbConsistencyTest(String timeZoneId) {
+        this.timeZoneId = timeZoneId;
+    }
+
+    /**
+     * Compares bionic's instant formatting output (localtime()) with java.time's. If it fails,
+     * bionic's data and ICU's data have not been updated at the same time, or ICU and bionic's
+     * understanding of the same data differs.
+     */
+    @Test
+    public void compareBionicFormattingWithJavaTime() {
+        ZoneRules zoneRules = ZoneId.of(timeZoneId).getRules();
+
+        Instant start = START_DATE.atOffset(ZoneOffset.UTC).toInstant();
+        Instant stop = END_DATE.atOffset(ZoneOffset.UTC).toInstant();
+
+        ZoneOffsetTransition zoneOffsetTransition = zoneRules.nextTransition(start);
+
+        while (start.isBefore(stop)) {
+            for (Duration interestingOffset : INTERESTING_OFFSETS) {
+                Instant instantToCheck = start.plus(interestingOffset);
+                String bionicResult = formatWithBionic(instantToCheck, timeZoneId);
+                String javaResult = instantToCheck.atZone(ZoneId.of(timeZoneId)).format(FORMATTER);
+
+                String errorMessage = "Failed to format " + start + " at " + timeZoneId
+                        + " with offset=" + interestingOffset;
+                assertEquals(errorMessage, javaResult, bionicResult);
+            }
+
+            if (zoneOffsetTransition == null) {
+                break;
+            }
+
+            start = zoneOffsetTransition.getInstant();
+            zoneOffsetTransition = zoneRules.nextTransition(start);
+        }
+    }
+
+    private static String formatWithBionic(Instant instant, String timeZoneId) {
+        return formatWithBionic(instant.getEpochSecond(), timeZoneId);
+    }
+
+    private static native String formatWithBionic(long epochSeconds, String timeZoneId);
+
+}
diff --git a/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java b/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java
index a319980..d6a0de4 100644
--- a/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java
+++ b/luni/src/test/java/libcore/java/time/chrono/ChronoZonedDateTimeTest.java
@@ -16,6 +16,7 @@
 
 package libcore.java.time.chrono;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -24,14 +25,22 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.time.Instant;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
 import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.ChronoZonedDateTime;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.JapaneseDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.FormatStyle;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalUnit;
+import java.util.Locale;
 
 @RunWith(JUnit4.class)
 public class ChronoZonedDateTimeTest {
@@ -58,6 +67,21 @@
         verify(temporalUnit).isSupportedBy(chronoZonedDateTime);
     }
 
+    @Test
+    public void testFormat() {
+        JapaneseChronology chrono = JapaneseChronology.INSTANCE;
+        DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
+                .appendLocalized(FormatStyle.MEDIUM, null)
+                .toFormatter(Locale.US);
+        ZonedDateTime epochTime = ZonedDateTime.ofInstant(Instant.EPOCH, ZoneId.of("UTC"));
+
+        ChronoZonedDateTime<JapaneseDate> chronoZonedDateTime = chrono.zonedDateTime(epochTime);
+        assertEquals("Jan 1, 45 Shōwa", chronoZonedDateTime.format(dateFormatter));
+
+        ChronoLocalDateTime<JapaneseDate> chronoLocalDateTime = chrono.localDateTime(epochTime);
+        assertEquals("Jan 1, 45 Shōwa", chronoLocalDateTime.format(dateFormatter));
+    }
+
     /* Used to test default methods. */
     private static class TestChronoZonedDateTime implements ChronoZonedDateTime {
 
diff --git a/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java b/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java
index 7db90cd..452b687 100644
--- a/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java
+++ b/luni/src/test/java/libcore/java/time/format/DateTimeFormatterTest.java
@@ -106,4 +106,13 @@
         assertEquals(23, accessor.getLong(ChronoField.HOUR_OF_DAY));
         assertEquals(59, accessor.getLong(ChronoField.MINUTE_OF_HOUR));
     }
+
+    // Regression test for http://b/206566562 when ICU4J fails to load the pattern data.
+    @Test
+    public void test_format_locale_de_AT() {
+        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
+            .withLocale(new Locale("de", "AT"))
+            .withZone(ZoneOffset.UTC);
+        assertEquals("00:00", dateTimeFormatter.format(TEST_INSTANT));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/AbstractMapTest.java b/luni/src/test/java/libcore/java/util/AbstractMapTest.java
new file mode 100644
index 0000000..4b68018
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/AbstractMapTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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 static org.junit.Assert.assertEquals;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.AbstractMap;
+
+@RunWith(JUnit4.class)
+public class AbstractMapTest {
+
+
+    @Test
+    public void testSimpleEntrySetValue() {
+        AbstractMap.SimpleEntry<String, Integer> entry = new AbstractMap.SimpleEntry<>("abc", 1);
+        assertEquals(Integer.valueOf(1), entry.getValue());
+        entry.setValue(-1);
+        assertEquals(Integer.valueOf(-1), entry.getValue());
+
+        AbstractMap.SimpleImmutableEntry<String, Integer> immutableEntry =
+                new AbstractMap.SimpleImmutableEntry<>("abc", 1);
+        assertEquals(Integer.valueOf(1), immutableEntry.getValue());
+        Assert.assertThrows(UnsupportedOperationException.class, () -> immutableEntry.setValue(-1));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/ArraysTest.java b/luni/src/test/java/libcore/java/util/ArraysTest.java
index 5a2bfe2..f834b2b 100644
--- a/luni/src/test/java/libcore/java/util/ArraysTest.java
+++ b/luni/src/test/java/libcore/java/util/ArraysTest.java
@@ -921,6 +921,50 @@
         }
     }
 
+    @Test
+    public void compareLIILII() {
+        final Integer[] lhs = { Integer.valueOf(0), Integer.valueOf(1), Integer.valueOf(2) };
+        final Integer[] rhs = { Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(0) };
+        final Integer[] empty = (Integer []) null;
+
+        assertEquals(0, Arrays.compare(lhs, 0, lhs.length, lhs, 0, lhs.length));
+        assertEquals(0, Arrays.compare(lhs, 1, 3, rhs, 0, 2));
+        assertEquals(-1, Arrays.compare(lhs, 0, 2, rhs, 0, 2));
+        assertEquals(-1, Arrays.compare(lhs, 0, 2, rhs, 1, 3));
+        assertEquals(-1, Arrays.compare(lhs, 0, 3, rhs, 0, 3));
+        assertEquals(1, Arrays.compare(rhs, 0, 3, lhs, 0, 3));
+
+        for (Integer[][] arrays : new Integer[][][] { { lhs, empty }, { empty, rhs }}) {
+            try {
+                Arrays.compare(arrays[0], 1, 3, arrays[1], 0, 2);
+                fail("Expected NPE");
+            } catch (NullPointerException e) {
+                // Expected
+            }
+        }
+
+        for (int[] i : new int[][] {{3, 1, 0, 2}, {1, 3, 2, 0}}) {
+            try {
+                Arrays.compare(lhs, i[0], i[1], rhs, i[2], i[3]);
+                fail("Expected IAE");
+            } catch (IllegalArgumentException e) {
+                // Expected
+            }
+        }
+
+        for (int[] i : new int[][] { {-1, 1, 0, 1},
+                                     {0, lhs.length + 1, 0, 1},
+                                     {0, 1, -1, 1},
+                                     {0, 1, 0, rhs.length + 1}}) {
+            try {
+                Arrays.compare(lhs, i[0], i[1], rhs, i[2], i[3]);
+                fail("Expected AIOBE");
+            } catch (ArrayIndexOutOfBoundsException e) {
+                // Expected
+            }
+        }
+    }
+
     private int[] intTestArray(int size) {
         int[] array = new int[size];
         for (int i = 0; i < size; i++) {
diff --git a/luni/src/test/java/libcore/java/util/BitSetTest.java b/luni/src/test/java/libcore/java/util/BitSetTest.java
index 41d4e53..8a38fcb 100644
--- a/luni/src/test/java/libcore/java/util/BitSetTest.java
+++ b/luni/src/test/java/libcore/java/util/BitSetTest.java
@@ -204,6 +204,21 @@
         assertEquals(-1, bs.previousSetBit(-1));
     }
 
+
+    public void test_previousClearBit() {
+        BitSet bs = new BitSet();
+        assertEquals(0, bs.previousClearBit(0));
+        assertEquals(1, bs.previousClearBit(1));
+        assertEquals(5, bs.previousClearBit(5));
+
+        bs.set(0);
+        assertEquals(-1, bs.previousClearBit(0));
+        bs.set(5);
+        assertEquals(4, bs.previousClearBit(5));
+        bs.set(6);
+        assertEquals(4, bs.previousClearBit(6));
+    }
+
     private static BitSet big() {
         BitSet result = new BitSet();
         result.set(1000);
diff --git a/luni/src/test/java/libcore/java/util/CalendarTest.java b/luni/src/test/java/libcore/java/util/CalendarTest.java
index abe5ab8..6c7efc2 100644
--- a/luni/src/test/java/libcore/java/util/CalendarTest.java
+++ b/luni/src/test/java/libcore/java/util/CalendarTest.java
@@ -361,6 +361,11 @@
         } catch (UnsupportedOperationException expected) {}
     }
 
+    public void testGetCalendarType() {
+        Calendar cal = new FakeCalendar();
+        assertEquals(FakeCalendar.class.getName(), cal.getCalendarType());
+    }
+
     public static class FakeCalendar extends Calendar {
 
         private int[] subclassFields;
diff --git a/luni/src/test/java/libcore/java/util/IllformedLocaleExceptionTest.java b/luni/src/test/java/libcore/java/util/IllformedLocaleExceptionTest.java
new file mode 100644
index 0000000..ac010ae
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/IllformedLocaleExceptionTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.IllformedLocaleException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class IllformedLocaleExceptionTest {
+
+    @Test
+    public void testConstructor() {
+        IllformedLocaleException exception = new IllformedLocaleException();
+        assertNull(exception.getMessage());
+        assertEquals(-1, exception.getErrorIndex());
+    }
+
+    @Test
+    public void testGetErrorIndex() {
+        IllformedLocaleException exception = new IllformedLocaleException("message", 6);
+        assertEquals(6, exception.getErrorIndex());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/IntSummaryStatisticsTest.java b/luni/src/test/java/libcore/java/util/IntSummaryStatisticsTest.java
index 925b29a..f52b491 100644
--- a/luni/src/test/java/libcore/java/util/IntSummaryStatisticsTest.java
+++ b/luni/src/test/java/libcore/java/util/IntSummaryStatisticsTest.java
@@ -23,6 +23,41 @@
     private static final int data1[] = {2, -5, 7, -1, 1, 0, 100};
     private static final int data2[] = {1, 3, 2, 1, 7};
 
+    public void test_bad_count() {
+        try {
+            new IntSummaryStatistics(-1, 0, 0, 0);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals(e.getMessage(), "Negative count value");
+        }
+    }
+
+    public void test_bad_min_max() {
+        try {
+            new IntSummaryStatistics(2, 2, 0, 0);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals(e.getMessage(), "Minimum greater than maximum");
+        }
+    }
+
+    public void test_defaults_when_count_is_zero() {
+        IntSummaryStatistics iss = new IntSummaryStatistics(0, 1, 10, 30);
+        assertEquals(0, iss.getCount());
+        assertEquals(0, iss.getSum());
+        assertEquals(0.0d, iss.getAverage());
+        assertEquals(Integer.MAX_VALUE, iss.getMin());
+        assertEquals(Integer.MIN_VALUE, iss.getMax());
+    }
+
+    public void test_filled_constructor() {
+        IntSummaryStatistics iss = new IntSummaryStatistics(9, 1, 5, 25);
+        assertEquals(9, iss.getCount());
+        assertEquals(25, iss.getSum());
+        assertEquals(1, iss.getMin());
+        assertEquals(5, iss.getMax());
+    }
+
     public void test_empty() {
         IntSummaryStatistics iss = new IntSummaryStatistics();
         assertEquals(0, iss.getCount());
diff --git a/luni/src/test/java/libcore/java/util/LongSummaryStatisticsTest.java b/luni/src/test/java/libcore/java/util/LongSummaryStatisticsTest.java
index 300c087..55102c4 100644
--- a/luni/src/test/java/libcore/java/util/LongSummaryStatisticsTest.java
+++ b/luni/src/test/java/libcore/java/util/LongSummaryStatisticsTest.java
@@ -32,6 +32,42 @@
         assertEquals(Long.MIN_VALUE, lss.getMax());
     }
 
+    public void test_bad_count() {
+        try {
+            new LongSummaryStatistics(-1, 0, 0, 0);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals(e.getMessage(), "Negative count value");
+        }
+    }
+
+    public void test_bad_min_max() {
+        try {
+            new LongSummaryStatistics(2, 2, 0, 0);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertEquals(e.getMessage(), "Minimum greater than maximum");
+        }
+    }
+
+    public void test_defaults_when_count_is_zero() {
+        LongSummaryStatistics lss = new LongSummaryStatistics(0, 1, 10, 30);
+        assertEquals(0, lss.getCount());
+        assertEquals(0, lss.getSum());
+        assertEquals(0.0d, lss.getAverage());
+        assertEquals(Long.MAX_VALUE, lss.getMin());
+        assertEquals(Long.MIN_VALUE, lss.getMax());
+    }
+
+    public void test_filled_constructor() {
+        LongSummaryStatistics lss = new LongSummaryStatistics(9, 1, 5, 25);
+        assertEquals(9, lss.getCount());
+        assertEquals(25, lss.getSum());
+        assertEquals(1, lss.getMin());
+        assertEquals(5, lss.getMax());
+    }
+
+
     public void test_accept() {
         LongSummaryStatistics lss = new LongSummaryStatistics();
 
diff --git a/luni/src/test/java/libcore/java/util/OptionalTest.java b/luni/src/test/java/libcore/java/util/OptionalTest.java
index 3cd8f9f..b7160b5 100644
--- a/luni/src/test/java/libcore/java/util/OptionalTest.java
+++ b/luni/src/test/java/libcore/java/util/OptionalTest.java
@@ -64,6 +64,7 @@
         assertFalse(Optional.<String>ofNullable(null).isPresent());
     }
 
+    @SuppressWarnings("OptionalOfRedundantMethod")
     public void testIfPresent() {
         Optional<String> empty = Optional.empty();
         Optional<String> ofNull = Optional.ofNullable(null);
diff --git a/luni/src/test/java/libcore/java/util/ResourceBundleTest.java b/luni/src/test/java/libcore/java/util/ResourceBundleTest.java
new file mode 100644
index 0000000..d8bcc99
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ResourceBundleTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.ResourceBundle.Control;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import tests.support.resource.Support_Resources;
+
+@RunWith(JUnit4.class)
+public class ResourceBundleTest {
+
+    private static final String PROP_RESOURCE_NAME = Support_Resources.RESOURCE_PACKAGE_NAME
+            + ".hyts_resource";
+
+    @Before
+    public void setUp() {
+        // Due to http://b/231440892, clear global cache before each test
+        ResourceBundle.clearCache();
+    }
+
+    @After
+    public void tearDown() {
+        // Due to http://b/231440892, clear global cache after each test
+        ResourceBundle.clearCache();
+    }
+
+    @Test
+    public void testGetBundle_withControl() {
+        Control propControl = Control.getControl(Control.FORMAT_PROPERTIES);
+        Control classControl = Control.getControl(Control.FORMAT_CLASS);
+        ClassLoader resClassLoader = Support_Resources.class.getClassLoader();
+        Locale locale = Locale.getDefault();
+
+        // Test for getBundle(String, Control)
+        ResourceBundle bundle = ResourceBundle.getBundle(PROP_RESOURCE_NAME, propControl);
+        assertEquals("parent", bundle.getString("property"));
+        ResourceBundle.clearCache(resClassLoader);
+        try {
+            ResourceBundle.getBundle(PROP_RESOURCE_NAME, classControl);
+            fail("ResourceBundle.getBundle() is expected to throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        // clearCache() must be called after the previous lookup failure. See http://b/231440892.
+        ResourceBundle.clearCache(resClassLoader);
+        // Test for getBundle(String, Locale, Control)
+        bundle = ResourceBundle.getBundle(PROP_RESOURCE_NAME, locale, propControl);
+        assertEquals("parent", bundle.getString("property"));
+        ResourceBundle.clearCache(resClassLoader);
+        try {
+            ResourceBundle.getBundle(PROP_RESOURCE_NAME, locale, classControl);
+            fail("ResourceBundle.getBundle() is expected to throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+
+        // clearCache() must be called after the previous lookup failure. See http://b/231440892.
+        ResourceBundle.clearCache(resClassLoader);
+        // Test for getBundle(String, Locale, ClassLoader, Control)
+        bundle = ResourceBundle.getBundle(PROP_RESOURCE_NAME, locale, resClassLoader, propControl);
+        assertEquals("parent", bundle.getString("property"));
+
+        // clearCache() and clearCache(resClassLoader) should have the same effect, because the
+        // classes are in the same class loader.
+        assertEquals(resClassLoader, ResourceBundleTest.class.getClassLoader());
+        ResourceBundle.clearCache();
+        try {
+            ResourceBundle.getBundle(PROP_RESOURCE_NAME, locale, resClassLoader, classControl);
+            fail("ResourceBundle.getBundle() is expected to throw MissingResourceException");
+        } catch (MissingResourceException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testContainsKey() {
+        ResourceBundle bundle = ResourceBundle.getBundle(PROP_RESOURCE_NAME);
+        assertTrue(bundle.containsKey("property"));
+        assertFalse(bundle.containsKey("anotherProperty"));
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/ScannerTest.java b/luni/src/test/java/libcore/java/util/ScannerTest.java
new file mode 100644
index 0000000..f84dac1
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ScannerTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertEquals;
+
+import java.util.Locale;
+import java.util.Scanner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ScannerTest {
+    @Test
+    public void testReset() {
+        Scanner scanner = new Scanner("123 45");
+        Locale locale = Locale.forLanguageTag("zh");
+        scanner.useDelimiter("123");
+        scanner.useLocale(locale);
+        scanner.useRadix(8);
+        assertEquals("123", scanner.delimiter().pattern());
+        assertEquals(locale, scanner.locale());
+        assertEquals(8, scanner.radix());
+
+        scanner.reset();
+        assertEquals("\\p{javaWhitespace}+", scanner.delimiter().pattern());
+        assertEquals(Locale.getDefault(Locale.Category.FORMAT), scanner.locale());
+        assertEquals(10, scanner.radix());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java b/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
index f17eb22..4be9007 100644
--- a/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
+++ b/luni/src/test/java/libcore/java/util/ServiceLoaderTest.java
@@ -38,6 +38,17 @@
     assertFalse(it.hasNext());
   }
 
+  public void testLoadInstalled() {
+    // We need to register a service in the System or Boot class loader in order to test this
+    // properly. We only test the negative case here.
+    ServiceLoader<ServiceLoaderTestInterface> loader = ServiceLoader.loadInstalled(
+            ServiceLoaderTestInterface.class);
+    Iterator<ServiceLoaderTestInterface> it = loader.iterator();
+    // Impl1 and Impl2 are not in the System or Boot class loader.
+    // Thus, ServiceLoader.loadInstalled shouldn't load any of them.
+    assertFalse(it.hasNext());
+  }
+
   // Something like "does.not.Exist", that is a well-formed class name, but just doesn't exist.
   public void test_missingRegisteredClass() throws Exception {
     try {
diff --git a/luni/src/test/java/libcore/java/util/SpliteratorTest.java b/luni/src/test/java/libcore/java/util/SpliteratorTest.java
new file mode 100644
index 0000000..37b1d7a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/SpliteratorTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertEquals;
+
+import java.util.Spliterator.OfPrimitive;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.function.IntConsumer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SpliteratorTest {
+
+
+    /**
+     * Class used to test {@link OfPrimitive#forEachRemaining(Object)}
+     */
+    private static class PrimitiveIntegerSpliterator
+            implements OfPrimitive<Integer, IntConsumer, PrimitiveIntegerSpliterator> {
+        private int current = 1;
+        private final int size;
+
+        PrimitiveIntegerSpliterator(int size) {
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (current <= size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public long estimateSize() {
+            return size;
+        }
+
+        @Override
+        public int characteristics() {
+            return 0;
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super Integer> action) {
+            if (action instanceof IntConsumer) {
+                return tryAdvance(action);
+            } else {
+                return tryAdvance((IntConsumer) action::accept);
+            }
+        }
+
+        @Override
+        public PrimitiveIntegerSpliterator trySplit() {
+            // null implying that this spliterator cannot be split
+            return null;
+        }
+    }
+
+    @Test
+    public void testOfPrimitiveForEachRemaining() {
+        OfPrimitive<Integer, IntConsumer, PrimitiveIntegerSpliterator> spliterator =
+                new PrimitiveIntegerSpliterator(10);
+        AtomicInteger sum = new AtomicInteger();
+        IntConsumer action = (i) -> sum.addAndGet(i);
+        spliterator.forEachRemaining(action);
+
+        assertEquals(55, sum.get());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/SpliteratorsTest.java b/luni/src/test/java/libcore/java/util/SpliteratorsTest.java
index 639ebf1..5e01ee0 100644
--- a/luni/src/test/java/libcore/java/util/SpliteratorsTest.java
+++ b/luni/src/test/java/libcore/java/util/SpliteratorsTest.java
@@ -26,6 +26,10 @@
 import java.util.PrimitiveIterator;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.Spliterators.AbstractDoubleSpliterator;
+import java.util.Spliterators.AbstractIntSpliterator;
+import java.util.Spliterators.AbstractLongSpliterator;
+import java.util.Spliterators.AbstractSpliterator;
 import java.util.function.Consumer;
 import java.util.function.DoubleConsumer;
 import java.util.function.IntConsumer;
@@ -863,4 +867,302 @@
 
         assertFalse(it.hasNext());
     }
+
+    private static class IncrementalDoubleSequenceSpliterator extends AbstractDoubleSpliterator {
+        private int current = 0;
+        private final int size;
+
+        IncrementalDoubleSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(DoubleConsumer action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractDoubleSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractDoubleSpliterator spliterator = new IncrementalDoubleSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator.OfDouble resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0);
+        assertFalse(spliterator.tryAdvance((DoubleConsumer) value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(0d, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(1d, value);
+        })));
+    }
+
+    public void testAbstractDoubleSpliterator_largeSize() {
+        // AbstractDoubleSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractDoubleSpliterator spliterator = new IncrementalDoubleSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator.OfDouble resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(0d, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals(1d, value);
+        })));;
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance(((DoubleConsumer) value -> {
+            assertEquals((double) maxBatch, value);
+        })));
+
+    }
+
+    private static class IncrementalIntSequenceSpliterator extends AbstractIntSpliterator {
+        private int current = 0;
+        private final int size;
+
+        IncrementalIntSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractIntSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractIntSpliterator spliterator = new IncrementalIntSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator.OfInt resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0);
+        assertFalse(spliterator.tryAdvance((IntConsumer) value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(0, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(1, value);
+        })));
+    }
+
+    public void testAbstractIntSpliterator_largeSize() {
+        // AbstractIntSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractIntSpliterator spliterator = new IncrementalIntSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator.OfInt resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(0, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(1, value);
+        })));
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance(((IntConsumer) value -> {
+            assertEquals(maxBatch, value);
+        })));
+    }
+
+    private static class IncrementalLongSequenceSpliterator extends AbstractLongSpliterator {
+        private int current = 0;
+        private final int size;
+
+        IncrementalLongSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(LongConsumer action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractLongSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractLongSpliterator spliterator = new IncrementalLongSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator.OfLong resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0L);
+        assertFalse(spliterator.tryAdvance((LongConsumer) value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(0L, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(1L, value);
+        })));
+    }
+
+    public void testAbstractLongSpliterator_largeSize() {
+        // AbstractLongSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractLongSpliterator spliterator = new IncrementalLongSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator.OfLong resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(0, value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(1, value);
+        })));;
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance(((LongConsumer) value -> {
+            assertEquals(maxBatch, value);
+        })));
+
+    }
+
+    private static class IncrementalIntegerSequenceSpliterator extends
+            AbstractSpliterator<Integer> {
+        private int current = 0;
+        private final int size;
+
+        IncrementalIntegerSequenceSpliterator(int size, int additionalCharacteristics) {
+            super(size, additionalCharacteristics);
+            this.size = size;
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super Integer> action) {
+            if (current < size) {
+                action.accept(current++);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public void testAbstractSpliterator_smallSize() {
+        int size = 10;
+        int characteristics = Spliterator.ORDERED;
+        AbstractSpliterator<Integer> spliterator = new IncrementalIntegerSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics);
+
+        Spliterator<Integer> resultSpliterator = spliterator.trySplit();
+        // The parent spliterator should have no remaining elements
+        assertEquals(spliterator.estimateSize(), 0L);
+        assertFalse(spliterator.tryAdvance(value -> {
+            throw new IllegalArgumentException("Unexpected call with value: " + value);
+        }));
+        // The result spliterator should have the same size because the size is small.
+        assertEquals(resultSpliterator.estimateSize(), size);
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(0), value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(1), value);
+        })));
+    }
+
+    public void testAbstractSpliterator_largeSize() {
+        // AbstractSpliterator.MAX_BATCH is package-private, and so assume it's 1 << 10.
+        int maxBatch = 1 << 10;
+        int size = maxBatch * 2;
+        int characteristics = Spliterator.ORDERED | Spliterator.SIZED;
+        AbstractSpliterator<Integer> spliterator = new IncrementalIntegerSequenceSpliterator(size,
+                characteristics);
+        assertEquals(spliterator.estimateSize(), size);
+        assertEquals(spliterator.characteristics(), characteristics | Spliterator.SUBSIZED);
+
+        Spliterator<Integer> resultSpliterator = spliterator.trySplit();
+        // The total size is not changed
+        assertEquals(size, spliterator.estimateSize() + resultSpliterator.estimateSize());
+
+        // The result spliterator should have the max batch size.
+        assertEquals(resultSpliterator.estimateSize(), maxBatch);
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(0), value);
+        })));
+        assertTrue(resultSpliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(1), value);
+        })));
+
+        ;
+
+        // The parent spliterator should be able to advance.
+        assertTrue(spliterator.tryAdvance((value -> {
+            assertEquals(Integer.valueOf(maxBatch), value);
+        })));
+
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/SplittableRandomTest.java b/luni/src/test/java/libcore/java/util/SplittableRandomTest.java
new file mode 100644
index 0000000..f3f394d
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/SplittableRandomTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 static org.junit.Assert.assertEquals;
+
+import java.util.SplittableRandom;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SplittableRandomTest {
+
+    @Test
+    public void testNextBoolean() {
+        long seed = 0x1234567890L;
+        SplittableRandom random1 = new SplittableRandom(seed);
+        SplittableRandom random2 = new SplittableRandom(seed);
+        for (int i = 0; i < 1000; i++) {
+            assertEquals(random1.nextBoolean(), random2.nextBoolean());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
index 9b8ea47..145c2d1 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -16,8 +16,7 @@
 
 package libcore.java.util;
 
-import junit.framework.TestCase;
-
+import dalvik.system.RuntimeHooks;
 import java.text.SimpleDateFormat;
 import java.time.ZoneId;
 import java.util.Calendar;
@@ -25,8 +24,18 @@
 import java.util.Locale;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
+import java.util.function.Supplier;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.SwitchTargetSdkVersionRule;
+import libcore.junit.util.SwitchTargetSdkVersionRule.TargetSdkVersion;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-public class TimeZoneTest extends TestCase {
+public class TimeZoneTest extends TestCaseWithRules {
+
+    @Rule
+    public TestRule switchTargetSdkVersionRule = SwitchTargetSdkVersionRule.getInstance();
+
     // http://code.google.com/p/android/issues/detail?id=877
     public void test_useDaylightTime_Taiwan() {
         TimeZone asiaTaipei = TimeZone.getTimeZone("Asia/Taipei");
@@ -401,4 +410,42 @@
         assertEquals(canonical.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH),
                 nonCanonical.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH));
     }
+
+    // Regression test for http://b/205618822
+    public void testGetTimeZone_forNonOlsonId() throws Exception {
+        Supplier<String> originalTimeZoneSupplier = RuntimeHooks.getTimeZoneIdSupplier();
+
+        try {
+            // Must clear the supplier before setting a new supplier.
+            RuntimeHooks.clearTimeZoneIdSupplier();
+            RuntimeHooks.setTimeZoneIdSupplier(() -> "GMT-12:00");
+            TimeZone.getTimeZone("GMT+08:00");
+        } finally {
+            RuntimeHooks.clearTimeZoneIdSupplier();
+            // If the process was forked from Zygote, originalTimeZoneSupplier shouldn't be null.
+            if (originalTimeZoneSupplier != null) {
+                RuntimeHooks.setTimeZoneIdSupplier(originalTimeZoneSupplier);
+            }
+        }
+    }
+
+    // Regression test for http://b/205618822
+    @TargetSdkVersion(29)
+    public void testGetTimeZone_forNonOlsonId_targetSdkVersion29() {
+        Supplier<String> originalTimeZoneSupplier = RuntimeHooks.getTimeZoneIdSupplier();
+
+        try {
+            // Must clear the supplier before setting a new supplier.
+            RuntimeHooks.clearTimeZoneIdSupplier();
+            RuntimeHooks.setTimeZoneIdSupplier(() -> "GMT-12:00");
+            TimeZone.getTimeZone("GMT+08:00");
+        } finally {
+            RuntimeHooks.clearTimeZoneIdSupplier();
+            // If the process was forked from Zygote, originalTimeZoneSupplier shouldn't be null.
+            if (originalTimeZoneSupplier != null) {
+                RuntimeHooks.setTimeZoneIdSupplier(originalTimeZoneSupplier);
+            }
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/util/TreeSetTest.java b/luni/src/test/java/libcore/java/util/TreeSetTest.java
index 11cb708..958bdb9 100644
--- a/luni/src/test/java/libcore/java/util/TreeSetTest.java
+++ b/luni/src/test/java/libcore/java/util/TreeSetTest.java
@@ -16,7 +16,9 @@
 
 package libcore.java.util;
 
+import java.util.Arrays;
 import java.util.NavigableSet;
+import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import junit.framework.TestCase;
@@ -133,4 +135,22 @@
             }
         }.test();
     }
+
+    public void testHeadSet() {
+        TreeSet<Integer> set = new TreeSet<>();
+        for (int i = -5; i < 5; i++) {
+            set.add(i);
+            // Adding twice should make no difference to the set.
+            set.add(i);
+        }
+
+        Set<Integer> headset = set.headSet(-1, true);
+        assertTrue(headset.containsAll(Arrays.asList(-5, -4, -3, -2, -1)));
+        assertEquals(5, headset.size());
+
+
+        headset = set.headSet(-1, false);
+        assertTrue(headset.containsAll(Arrays.asList(-5, -4, -3, -2)));
+        assertEquals(4, headset.size());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ArrayBlockingQueueTest.java b/luni/src/test/java/libcore/java/util/concurrent/ArrayBlockingQueueTest.java
new file mode 100644
index 0000000..12ec722
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ArrayBlockingQueueTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.atomic.LongAdder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ArrayBlockingQueueTest {
+
+    @Test
+    public void testForEach() {
+        int capacity = 10;
+        ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(capacity);
+        for (int i = 0; i < capacity; ++i) {
+            queue.add(Integer.valueOf(i+1));
+        }
+        LongAdder adder = new LongAdder();
+        queue.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(queue.size() * (queue.size() + 1) / 2, adder.sum());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AtomicBooleanTest.java b/luni/src/test/java/libcore/java/util/concurrent/AtomicBooleanTest.java
new file mode 100644
index 0000000..7aa4c66
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AtomicBooleanTest.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicBooleanTest {
+
+    @Test
+    public void testCompareAndExchange() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        boolean expected = false;
+        boolean newValue = false;
+        assertEquals(true, val.compareAndExchange(expected, newValue));
+        assertEquals(true, val.get());
+        assertEquals(true, val.compareAndExchange(expected, newValue));
+        assertEquals(true, val.get());
+        expected = true;
+        assertEquals(true, val.compareAndExchange(expected, newValue));
+        assertEquals(false, val.get());
+        assertEquals(false, val.compareAndExchange(expected, newValue));
+        assertEquals(false, val.get());
+        expected = false;
+        newValue = true;
+        assertEquals(false, val.compareAndExchange(expected, newValue));
+        assertEquals(true, val.get());
+    }
+
+    @Test
+    public void testCompareAndExchangeAcquire() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        boolean expected = false;
+        boolean newValue = false;
+        assertEquals(true, val.compareAndExchangeAcquire(expected, newValue));
+        assertEquals(true, val.get());
+        assertEquals(true, val.compareAndExchangeAcquire(expected, newValue));
+        assertEquals(true, val.get());
+        expected = true;
+        assertEquals(true, val.compareAndExchangeAcquire(expected, newValue));
+        assertEquals(false, val.get());
+        assertEquals(false, val.compareAndExchangeAcquire(expected, newValue));
+        assertEquals(false, val.get());
+        expected = false;
+        newValue = true;
+        assertEquals(false, val.compareAndExchangeAcquire(expected, newValue));
+        assertEquals(true, val.get());
+    }
+
+    @Test
+    public void testCompareAndExchangeRelease() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        boolean expected = false;
+        boolean newValue = false;
+        assertEquals(true, val.compareAndExchangeRelease(expected, newValue));
+        assertEquals(true, val.get());
+        assertEquals(true, val.compareAndExchangeRelease(expected, newValue));
+        assertEquals(true, val.get());
+        expected = true;
+        assertEquals(true, val.compareAndExchangeRelease(expected, newValue));
+        assertEquals(false, val.get());
+        assertEquals(false, val.compareAndExchangeRelease(expected, newValue));
+        assertEquals(false, val.get());
+        expected = false;
+        newValue = true;
+        assertEquals(false, val.compareAndExchangeRelease(expected, newValue));
+        assertEquals(true, val.get());
+    }
+
+    @Test
+    public void testGetAcquire() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        assertEquals(true, val.getAcquire());
+        val.set(false);
+        assertEquals(false, val.getAcquire());
+        val.set(true);
+        assertEquals(true, val.getAcquire());
+    }
+
+    @Test
+    public void testGetOpaque() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        assertEquals(true, val.getOpaque());
+        val.set(false);
+        assertEquals(false, val.getOpaque());
+        val.set(true);
+        assertEquals(true, val.getOpaque());
+    }
+
+    @Test
+    public void testGetPlain() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        assertEquals(true, val.getPlain());
+        val.set(false);
+        assertEquals(false, val.getPlain());
+        val.set(true);
+        assertEquals(true, val.getPlain());
+    }
+
+    @Test
+    public void testSetOpaque() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        val.setOpaque(false);
+        assertEquals(false, val.get());
+        val.setOpaque(true);
+        assertEquals(true, val.get());
+        val.setOpaque(false);
+        assertEquals(false, val.get());
+    }
+
+    @Test
+    public void testSetPlain() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        val.setPlain(false);
+        assertEquals(false, val.get());
+        val.setPlain(true);
+        assertEquals(true, val.get());
+        val.setPlain(false);
+        assertEquals(false, val.get());
+    }
+
+    @Test
+    public void testSetRelease() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        val.setRelease(false);
+        assertEquals(false, val.get());
+        val.setRelease(true);
+        assertEquals(true, val.get());
+        val.setRelease(false);
+        assertEquals(false, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetAcquire() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        boolean expected = false;
+        boolean newValue = false;
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetAcquire(expected, newValue));
+            assertEquals(true, val.get());
+        }
+
+        expected = true;
+        do { } while (!val.weakCompareAndSetAcquire(expected, newValue));
+        assertEquals(false, val.get());
+
+        expected = false;
+        newValue = true;
+        do { } while (!val.weakCompareAndSetAcquire(expected, newValue));
+        assertEquals(true, val.get());
+
+        expected = true;
+        newValue = false;
+        do { } while (!val.weakCompareAndSetAcquire(expected, newValue));
+        assertEquals(false, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetPlain() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        boolean expected = false;
+        boolean newValue = false;
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetPlain(expected, newValue));
+            assertEquals(true, val.get());
+        }
+
+        expected = true;
+        do { } while (!val.weakCompareAndSetPlain(expected, newValue));
+        assertEquals(false, val.get());
+
+        expected = false;
+        newValue = true;
+        do { } while (!val.weakCompareAndSetPlain(expected, newValue));
+        assertEquals(true, val.get());
+
+        expected = true;
+        newValue = false;
+        do { } while (!val.weakCompareAndSetPlain(expected, newValue));
+        assertEquals(false, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetRelease() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        boolean expected = false;
+        boolean newValue = false;
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetRelease(expected, newValue));
+            assertEquals(true, val.get());
+        }
+
+        expected = true;
+        do { } while (!val.weakCompareAndSetRelease(expected, newValue));
+        assertEquals(false, val.get());
+
+        expected = false;
+        newValue = true;
+        do { } while (!val.weakCompareAndSetRelease(expected, newValue));
+        assertEquals(true, val.get());
+
+        expected = true;
+        newValue = false;
+        do { } while (!val.weakCompareAndSetRelease(expected, newValue));
+        assertEquals(false, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetVolatile() {
+        AtomicBoolean val = new AtomicBoolean(true);
+        boolean expected = false;
+        boolean newValue = false;
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetVolatile(expected, newValue));
+            assertEquals(true, val.get());
+        }
+
+        expected = true;
+        do { } while (!val.weakCompareAndSetVolatile(expected, newValue));
+        assertEquals(false, val.get());
+
+        expected = false;
+        newValue = true;
+        do { } while (!val.weakCompareAndSetVolatile(expected, newValue));
+        assertEquals(true, val.get());
+
+        expected = true;
+        newValue = false;
+        do { } while (!val.weakCompareAndSetVolatile(expected, newValue));
+        assertEquals(false, val.get());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AtomicIntegerArrayTest.java b/luni/src/test/java/libcore/java/util/concurrent/AtomicIntegerArrayTest.java
new file mode 100644
index 0000000..6f9fcdd
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AtomicIntegerArrayTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.concurrent.atomic.AtomicIntegerArray;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicIntegerArrayTest {
+
+    private void checkArrayAsExpected(int[] expected, AtomicIntegerArray actual) {
+        assertEquals(expected.length, actual.length());
+        for (int i = 0; i < expected.length; ++i) {
+            assertEquals(expected[i], actual.get(i));
+        }
+    }
+
+    @Test
+    public void testCompareAndExchange() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, 0, i+1));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(i+1, arr.compareAndExchange(i, i+1, -1));
+            assertEquals(-1, arr.get(i));
+            expectedArray[i] = -1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(-1, arr.compareAndExchange(i, -1, i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testCompareAndExchangeAcquire() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, 0, i+1));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(i+1, arr.compareAndExchangeAcquire(i, i+1, -1));
+            assertEquals(-1, arr.get(i));
+            expectedArray[i] = -1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(-1, arr.compareAndExchangeAcquire(i, -1, i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testCompareAndExchangeRelease() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, 0, i+1));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(i+1, arr.compareAndExchangeRelease(i, i+1, -1));
+            assertEquals(-1, arr.get(i));
+            expectedArray[i] = -1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(-1, arr.compareAndExchangeRelease(i, -1, i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testGetAcquire() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            assertEquals(expectedArray[i], arr.getAcquire(i));
+            arr.set(i, i+1);
+            assertEquals(i+1, arr.getAcquire(i));
+        }
+    }
+
+    @Test
+    public void testGetOpaque() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            assertEquals(expectedArray[i], arr.getOpaque(i));
+            arr.set(i, i+1);
+            assertEquals(i+1, arr.getOpaque(i));
+        }
+    }
+
+    @Test
+    public void testGetPlain() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            assertEquals(expectedArray[i], arr.getPlain(i));
+            arr.set(i, i+1);
+            assertEquals(i+1, arr.getPlain(i));
+        }
+    }
+
+    @Test
+    public void testSetOpaque() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            arr.setOpaque(i, i+1);
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            arr.setOpaque(i, i*2);
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testSetPlain() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            arr.setPlain(i, i+1);
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            arr.setPlain(i, i*2);
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testSetRelease() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            arr.setRelease(i, i+1);
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            arr.setRelease(i, i*2);
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetAcquire() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetAcquire(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            do { } while (!arr.weakCompareAndSetAcquire(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetAcquire(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetPlain() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetPlain(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            do { } while (!arr.weakCompareAndSetPlain(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetPlain(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetRelease() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetRelease(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            do { } while (!arr.weakCompareAndSetRelease(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetRelease(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetVolatile() {
+        int[] expectedArray = { 42, 43, 44, 45 };
+        AtomicIntegerArray arr = new AtomicIntegerArray(expectedArray);
+        for (int i = arr.length() - 1; i >= 0; --i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetVolatile(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+
+            do { } while (!arr.weakCompareAndSetVolatile(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetVolatile(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AtomicIntegerTest.java b/luni/src/test/java/libcore/java/util/concurrent/AtomicIntegerTest.java
new file mode 100644
index 0000000..54bb1ce
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AtomicIntegerTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicIntegerTest {
+
+    @Test
+    public void testCompareAndExchange() {
+        AtomicInteger val = new AtomicInteger(42);
+        assertEquals(42, val.compareAndExchange(0, 1));
+        assertEquals(42, val.get());
+        assertEquals(42, val.compareAndExchange(42, 1));
+        assertEquals(1, val.get());
+        assertEquals(1, val.compareAndExchange(1, -1));
+        assertEquals(-1, val.get());
+        assertEquals(-1, val.compareAndExchange(42, 0));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testCompareAndExchangeAcquire() {
+        AtomicInteger val = new AtomicInteger(42);
+        assertEquals(42, val.compareAndExchangeAcquire(0, 1));
+        assertEquals(42, val.get());
+        assertEquals(42, val.compareAndExchangeAcquire(42, 1));
+        assertEquals(1, val.get());
+        assertEquals(1, val.compareAndExchangeAcquire(1, -1));
+        assertEquals(-1, val.get());
+        assertEquals(-1, val.compareAndExchangeAcquire(42, 0));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testCompareAndExchangeRelease() {
+        AtomicInteger val = new AtomicInteger(42);
+        assertEquals(42, val.compareAndExchangeRelease(0, 1));
+        assertEquals(42, val.get());
+        assertEquals(42, val.compareAndExchangeRelease(42, 1));
+        assertEquals(1, val.get());
+        assertEquals(1, val.compareAndExchangeRelease(1, -1));
+        assertEquals(-1, val.get());
+        assertEquals(-1, val.compareAndExchangeRelease(42, 0));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testGetAcquire() {
+        AtomicInteger val = new AtomicInteger(42);
+        assertEquals(42, val.getAcquire());
+        val.set(0);
+        assertEquals(0, val.getAcquire());
+        val.set(5);
+        assertEquals(5, val.getAcquire());
+    }
+
+    @Test
+    public void testGetOpaque() {
+        AtomicInteger val = new AtomicInteger(42);
+        assertEquals(42, val.getOpaque());
+        val.set(0);
+        assertEquals(0, val.getOpaque());
+        val.set(5);
+        assertEquals(5, val.getOpaque());
+    }
+
+    @Test
+    public void testGetPlain() {
+        AtomicInteger val = new AtomicInteger(42);
+        assertEquals(42, val.getPlain());
+        val.set(0);
+        assertEquals(0, val.getPlain());
+        val.set(5);
+        assertEquals(5, val.getPlain());
+    }
+
+    @Test
+    public void testSetOpaque() {
+        AtomicInteger val = new AtomicInteger(42);
+        val.setOpaque(0);
+        assertEquals(0, val.get());
+        val.setOpaque(5);
+        assertEquals(5, val.get());
+        val.setOpaque(-1);
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testSetPlain() {
+        AtomicInteger val = new AtomicInteger(42);
+        val.setPlain(0);
+        assertEquals(0, val.get());
+        val.setPlain(5);
+        assertEquals(5, val.get());
+        val.setPlain(-1);
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testSetRelease() {
+        AtomicInteger val = new AtomicInteger(42);
+        val.setRelease(0);
+        assertEquals(0, val.get());
+        val.setRelease(5);
+        assertEquals(5, val.get());
+        val.setRelease(-1);
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetAcquire() {
+        AtomicInteger val = new AtomicInteger(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetAcquire(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetAcquire(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetAcquire(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetAcquire(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetPlain() {
+        AtomicInteger val = new AtomicInteger(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetPlain(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetPlain(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetPlain(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetPlain(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetRelease() {
+        AtomicInteger val = new AtomicInteger(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetRelease(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetRelease(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetRelease(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetRelease(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetVolatile() {
+        AtomicInteger val = new AtomicInteger(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetVolatile(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetVolatile(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetVolatile(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetVolatile(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AtomicLongArrayTest.java b/luni/src/test/java/libcore/java/util/concurrent/AtomicLongArrayTest.java
new file mode 100644
index 0000000..8c92dae
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AtomicLongArrayTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.concurrent.atomic.AtomicLongArray;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicLongArrayTest {
+
+    private void checkArrayAsExpected(long[] expected, AtomicLongArray actual) {
+        assertEquals(expected.length, actual.length());
+        for (int i = 0; i < expected.length; ++i) {
+            assertEquals(expected[i], actual.get(i));
+        }
+    }
+
+    @Test
+    public void testCompareAndExchange() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, 0, i+1));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(i+1, arr.compareAndExchange(i, i+1, -1));
+            assertEquals(-1, arr.get(i));
+            expectedArray[i] = -1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(-1, arr.compareAndExchange(i, -1, i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testCompareAndExchangeAcquire() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, 0, i+1));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(i+1, arr.compareAndExchangeAcquire(i, i+1, -1));
+            assertEquals(-1, arr.get(i));
+            expectedArray[i] = -1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(-1, arr.compareAndExchangeAcquire(i, -1, i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testCompareAndExchangeRelease() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, 0, i+1));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(i+1, arr.compareAndExchangeRelease(i, i+1, -1));
+            assertEquals(-1, arr.get(i));
+            expectedArray[i] = -1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(-1, arr.compareAndExchangeRelease(i, -1, i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testGetAcquire() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertEquals(expectedArray[i], arr.getAcquire(i));
+            arr.set(i, i+1);
+            assertEquals(i+1, arr.getAcquire(i));
+        }
+    }
+
+    @Test
+    public void testGetOpaque() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertEquals(expectedArray[i], arr.getOpaque(i));
+            arr.set(i, i+1);
+            assertEquals(i+1, arr.getOpaque(i));
+        }
+    }
+
+    @Test
+    public void testGetPlain() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertEquals(expectedArray[i], arr.getPlain(i));
+            arr.set(i, i+1);
+            assertEquals(i+1, arr.getPlain(i));
+        }
+    }
+
+    @Test
+    public void testSetOpaque() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            arr.setOpaque(i, i+1);
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            arr.setOpaque(i, i*2);
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testSetPlain() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            arr.setPlain(i, i+1);
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            arr.setPlain(i, i*2);
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testSetRelease() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            arr.setRelease(i, i+1);
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            arr.setRelease(i, i*2);
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetAcquire() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetAcquire(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            do { } while (!arr.weakCompareAndSetAcquire(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetAcquire(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetPlain() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetPlain(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            do { } while (!arr.weakCompareAndSetPlain(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetPlain(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetRelease() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetRelease(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            do { } while (!arr.weakCompareAndSetRelease(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetRelease(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetVolatile() {
+        long[] expectedArray = { 42, 43, 44, 45 };
+        AtomicLongArray arr = new AtomicLongArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetVolatile(i, 0, -1));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+
+            do { } while (!arr.weakCompareAndSetVolatile(i, expectedArray[i], i+1));
+            assertEquals(i+1, arr.get(i));
+            expectedArray[i] = i+1;
+            checkArrayAsExpected(expectedArray, arr);
+
+            do { } while (!arr.weakCompareAndSetVolatile(i, expectedArray[i], i*2));
+            assertEquals(i*2, arr.get(i));
+            expectedArray[i] = i*2;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AtomicLongTest.java b/luni/src/test/java/libcore/java/util/concurrent/AtomicLongTest.java
new file mode 100644
index 0000000..33a4f3a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AtomicLongTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.concurrent.atomic.AtomicLong;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicLongTest {
+
+    @Test
+    public void testCompareAndExchange() {
+        AtomicLong val = new AtomicLong(42);
+        assertEquals(42, val.compareAndExchange(0, 1));
+        assertEquals(42, val.get());
+        assertEquals(42, val.compareAndExchange(42, 1));
+        assertEquals(1, val.get());
+        assertEquals(1, val.compareAndExchange(1, -1));
+        assertEquals(-1, val.get());
+        assertEquals(-1, val.compareAndExchange(42, 0));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testCompareAndExchangeAcquire() {
+        AtomicLong val = new AtomicLong(42);
+        assertEquals(42, val.compareAndExchangeAcquire(0, 1));
+        assertEquals(42, val.get());
+        assertEquals(42, val.compareAndExchangeAcquire(42, 1));
+        assertEquals(1, val.get());
+        assertEquals(1, val.compareAndExchangeAcquire(1, -1));
+        assertEquals(-1, val.get());
+        assertEquals(-1, val.compareAndExchangeAcquire(42, 0));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testCompareAndExchangeRelease() {
+        AtomicLong val = new AtomicLong(42);
+        assertEquals(42, val.compareAndExchangeRelease(0, 1));
+        assertEquals(42, val.get());
+        assertEquals(42, val.compareAndExchangeRelease(42, 1));
+        assertEquals(1, val.get());
+        assertEquals(1, val.compareAndExchangeRelease(1, -1));
+        assertEquals(-1, val.get());
+        assertEquals(-1, val.compareAndExchangeRelease(42, 0));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testGetAcquire() {
+        AtomicLong val = new AtomicLong(42);
+        assertEquals(42, val.getAcquire());
+        val.set(0);
+        assertEquals(0, val.getAcquire());
+        val.set(5);
+        assertEquals(5, val.getAcquire());
+    }
+
+    @Test
+    public void testGetOpaque() {
+        AtomicLong val = new AtomicLong(42);
+        assertEquals(42, val.getOpaque());
+        val.set(0);
+        assertEquals(0, val.getOpaque());
+        val.set(5);
+        assertEquals(5, val.getOpaque());
+    }
+
+    @Test
+    public void testGetPlain() {
+        AtomicLong val = new AtomicLong(42);
+        assertEquals(42, val.getPlain());
+        val.set(0);
+        assertEquals(0, val.getPlain());
+        val.set(5);
+        assertEquals(5, val.getPlain());
+    }
+
+    @Test
+    public void testSetOpaque() {
+        AtomicLong val = new AtomicLong(42);
+        val.setOpaque(0);
+        assertEquals(0, val.get());
+        val.setOpaque(5);
+        assertEquals(5, val.get());
+        val.setOpaque(-1);
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testSetPlain() {
+        AtomicLong val = new AtomicLong(42);
+        val.setPlain(0);
+        assertEquals(0, val.get());
+        val.setPlain(5);
+        assertEquals(5, val.get());
+        val.setPlain(-1);
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testSetRelease() {
+        AtomicLong val = new AtomicLong(42);
+        val.setRelease(0);
+        assertEquals(0, val.get());
+        val.setRelease(5);
+        assertEquals(5, val.get());
+        val.setRelease(-1);
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetAcquire() {
+        AtomicLong val = new AtomicLong(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetAcquire(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetAcquire(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetAcquire(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetAcquire(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetPlain() {
+        AtomicLong val = new AtomicLong(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetPlain(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetPlain(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetPlain(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetPlain(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetRelease() {
+        AtomicLong val = new AtomicLong(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetRelease(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetRelease(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetRelease(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetRelease(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+    @Test
+    public void testWeakCompareAndSetVolatile() {
+        AtomicLong val = new AtomicLong(42);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetVolatile(0, -1));
+            assertEquals(42, val.get());
+        }
+        do { } while (!val.weakCompareAndSetVolatile(42, 0));
+        assertEquals(0, val.get());
+        do { } while (!val.weakCompareAndSetVolatile(0, 5));
+        assertEquals(5, val.get());
+        do { } while (!val.weakCompareAndSetVolatile(5, -1));
+        assertEquals(-1, val.get());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AtomicReferenceArrayTest.java b/luni/src/test/java/libcore/java/util/concurrent/AtomicReferenceArrayTest.java
new file mode 100644
index 0000000..2b256b0
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AtomicReferenceArrayTest.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+
+import java.util.concurrent.atomic.AtomicReferenceArray;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicReferenceArrayTest {
+
+    private void checkArrayAsExpected(Integer[] expected, AtomicReferenceArray<Integer> actual) {
+        assertEquals(expected.length, actual.length());
+        for (int i = 0; i < expected.length; ++i) {
+            assertSame(expected[i], actual.get(i));
+        }
+    }
+
+    @Test
+    public void testCompareAndExchange() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            Integer val = Integer.valueOf(i+1);
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, Integer.valueOf(0), val));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(-1);
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(-1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            assertEquals(expectedArray[i], arr.compareAndExchange(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testCompareAndExchangeAcquire() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            Integer val = Integer.valueOf(i+1);
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, Integer.valueOf(0), val));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(-1);
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(-1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            assertEquals(expectedArray[i], arr.compareAndExchangeAcquire(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testCompareAndExchangeRelease() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            Integer val = Integer.valueOf(i+1);
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, Integer.valueOf(0), val));
+            checkArrayAsExpected(expectedArray, arr);
+
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(-1);
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(-1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            assertEquals(expectedArray[i], arr.compareAndExchangeRelease(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testGetAcquire() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertSame(expectedArray[i], arr.getAcquire(i));
+            arr.set(i, Integer.valueOf(i+1));
+            assertEquals(i+1, arr.getAcquire(i).intValue());
+        }
+    }
+
+    @Test
+    public void testGetOpaque() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertSame(expectedArray[i], arr.getOpaque(i));
+            arr.set(i, Integer.valueOf(i+1));
+            assertEquals(i+1, arr.getOpaque(i).intValue());
+        }
+    }
+
+    @Test
+    public void testGetPlain() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            assertSame(expectedArray[i], arr.getPlain(i));
+            arr.set(i, Integer.valueOf(i+1));
+            assertEquals(i+1, arr.getPlain(i).intValue());
+        }
+    }
+
+    @Test
+    public void testSetOpaque() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            Integer val = Integer.valueOf(i+1);
+            arr.setOpaque(i, val);
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            arr.setOpaque(i, val);
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testSetPlain() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            Integer val = Integer.valueOf(i+1);
+            arr.setPlain(i, val);
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            arr.setPlain(i, val);
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testSetRelease() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            Integer val = Integer.valueOf(i+1);
+            arr.setRelease(i, val);
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            arr.setRelease(i, val);
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetAcquire() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetAcquire(i, Integer.valueOf(0), Integer.valueOf(-1)));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            Integer val = Integer.valueOf(i+1);
+            do { } while (!arr.weakCompareAndSetAcquire(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            do { } while (!arr.weakCompareAndSetAcquire(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetPlain() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetPlain(i, Integer.valueOf(0), Integer.valueOf(-1)));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            Integer val = Integer.valueOf(i+1);
+            do { } while (!arr.weakCompareAndSetPlain(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            do { } while (!arr.weakCompareAndSetPlain(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetRelease() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetRelease(i, Integer.valueOf(0), Integer.valueOf(-1)));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            Integer val = Integer.valueOf(i+1);
+            do { } while (!arr.weakCompareAndSetRelease(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            do { } while (!arr.weakCompareAndSetRelease(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+    @Test
+    public void testWeakCompareAndSetVolatile() {
+        Integer[] expectedArray = {
+            Integer.valueOf(42),
+            Integer.valueOf(43),
+            Integer.valueOf(44),
+            Integer.valueOf(45)
+        };
+        AtomicReferenceArray<Integer> arr = new AtomicReferenceArray(expectedArray);
+        for (int i = 0; i < arr.length(); ++i) {
+            for (int r = 0; r < 10; ++r) {
+                assertFalse(arr.weakCompareAndSetVolatile(i, Integer.valueOf(0), Integer.valueOf(-1)));
+                checkArrayAsExpected(expectedArray, arr);
+            }
+            Integer val = Integer.valueOf(i+1);
+            do { } while (!arr.weakCompareAndSetVolatile(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i+1, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+
+            val = Integer.valueOf(i*2);
+            do { } while (!arr.weakCompareAndSetVolatile(i, expectedArray[i], val));
+            assertSame(val, arr.get(i));
+            assertEquals(i*2, arr.get(i).intValue());
+            expectedArray[i] = val;
+            checkArrayAsExpected(expectedArray, arr);
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/AtomicReferenceTest.java b/luni/src/test/java/libcore/java/util/concurrent/AtomicReferenceTest.java
new file mode 100644
index 0000000..74f1f82
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/AtomicReferenceTest.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AtomicReferenceTest {
+
+    @Test
+    public void testCompareAndExchange() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+
+        Integer notCurrent = new Integer(0);
+        Integer newValue = Integer.valueOf(1);
+        Integer result = val.compareAndExchange(notCurrent, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(42, currentValue.intValue());
+
+        notCurrent = new Integer(42);
+        result = val.compareAndExchange(notCurrent, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(42, currentValue.intValue());
+
+        result = val.compareAndExchange(currentValue, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(newValue, val.get());
+        currentValue = val.get();
+        assertEquals(1, currentValue.intValue());
+
+
+        notCurrent = new Integer(42);
+        newValue = Integer.valueOf(0);
+        result = val.compareAndExchange(notCurrent, newValue);
+        assertEquals(1, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(1, currentValue.intValue());
+
+        newValue = Integer.valueOf(0);
+        result = val.compareAndExchange(currentValue, newValue);
+        assertEquals(1, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(newValue, val.get());
+        currentValue = val.get();
+        assertEquals(0, currentValue.intValue());
+    }
+
+    @Test
+    public void testCompareAndExchangeAcquire() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+
+        Integer notCurrent = new Integer(0);
+        Integer newValue = Integer.valueOf(1);
+        Integer result = val.compareAndExchangeAcquire(notCurrent, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(42, currentValue.intValue());
+
+        notCurrent = new Integer(42);
+        result = val.compareAndExchangeAcquire(notCurrent, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(42, currentValue.intValue());
+
+        result = val.compareAndExchangeAcquire(currentValue, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(newValue, val.get());
+        currentValue = val.get();
+        assertEquals(1, currentValue.intValue());
+
+
+        notCurrent = new Integer(42);
+        newValue = Integer.valueOf(0);
+        result = val.compareAndExchangeAcquire(notCurrent, newValue);
+        assertEquals(1, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(1, currentValue.intValue());
+
+        newValue = Integer.valueOf(0);
+        result = val.compareAndExchangeAcquire(currentValue, newValue);
+        assertEquals(1, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(newValue, val.get());
+        currentValue = val.get();
+        assertEquals(0, currentValue.intValue());
+    }
+
+    @Test
+    public void testCompareAndExchangeRelease() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+
+        Integer notCurrent = new Integer(0);
+        Integer newValue = Integer.valueOf(1);
+        Integer result = val.compareAndExchangeRelease(notCurrent, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(42, currentValue.intValue());
+
+        notCurrent = new Integer(42);
+        result = val.compareAndExchangeRelease(notCurrent, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(42, currentValue.intValue());
+
+        result = val.compareAndExchangeRelease(currentValue, newValue);
+        assertEquals(42, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(newValue, val.get());
+        currentValue = val.get();
+        assertEquals(1, currentValue.intValue());
+
+
+        notCurrent = new Integer(42);
+        newValue = Integer.valueOf(0);
+        result = val.compareAndExchangeRelease(notCurrent, newValue);
+        assertEquals(1, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(currentValue, val.get());
+        assertEquals(1, currentValue.intValue());
+
+        newValue = Integer.valueOf(0);
+        result = val.compareAndExchangeRelease(currentValue, newValue);
+        assertEquals(1, result.intValue());
+        assertSame(currentValue, result);
+        assertSame(newValue, val.get());
+        currentValue = val.get();
+        assertEquals(0, currentValue.intValue());
+    }
+
+    @Test
+    public void testGetAcquire() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        assertSame(currentValue, val.getAcquire());
+        assertEquals(42, val.getAcquire().intValue());
+
+        currentValue = Integer.valueOf(0);
+        val.set(currentValue);
+        assertSame(currentValue, val.getAcquire());
+        assertEquals(0, val.getAcquire().intValue());
+
+        currentValue = Integer.valueOf(5);
+        val.set(currentValue);
+        assertSame(currentValue, val.getAcquire());
+        assertEquals(5, val.getAcquire().intValue());
+    }
+
+    @Test
+    public void testGetOpaque() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        assertSame(currentValue, val.getOpaque());
+        assertEquals(42, val.getOpaque().intValue());
+
+        currentValue = Integer.valueOf(0);
+        val.set(currentValue);
+        assertSame(currentValue, val.getOpaque());
+        assertEquals(0, val.getOpaque().intValue());
+
+        currentValue = Integer.valueOf(5);
+        val.set(currentValue);
+        assertSame(currentValue, val.getOpaque());
+        assertEquals(5, val.getOpaque().intValue());
+    }
+
+    @Test
+    public void testGetPlain() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        assertSame(currentValue, val.getPlain());
+        assertEquals(42, val.getPlain().intValue());
+
+        currentValue = Integer.valueOf(0);
+        val.set(currentValue);
+        assertSame(currentValue, val.getPlain());
+        assertEquals(0, val.getPlain().intValue());
+
+        currentValue = Integer.valueOf(5);
+        val.set(currentValue);
+        assertSame(currentValue, val.getPlain());
+        assertEquals(5, val.getPlain().intValue());
+    }
+
+    @Test
+    public void testSetOpaque() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(42, val.get().intValue());
+
+        currentValue = Integer.valueOf(0);
+        val.setOpaque(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(0, val.get().intValue());
+
+        currentValue = Integer.valueOf(5);
+        val.setOpaque(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(5, val.get().intValue());
+    }
+
+    @Test
+    public void testSetPlain() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(42, val.get().intValue());
+
+        currentValue = Integer.valueOf(0);
+        val.setPlain(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(0, val.get().intValue());
+
+        currentValue = Integer.valueOf(5);
+        val.setPlain(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(5, val.get().intValue());
+    }
+
+    @Test
+    public void testSetRelease() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(42, val.get().intValue());
+
+        currentValue = Integer.valueOf(0);
+        val.setRelease(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(0, val.get().intValue());
+
+        currentValue = Integer.valueOf(5);
+        val.setRelease(currentValue);
+        assertSame(currentValue, val.get());
+        assertEquals(5, val.get().intValue());
+    }
+
+    @Test
+    public void testWeakCompareAndSetAcquire() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetAcquire(Integer.valueOf(0), Integer.valueOf(-1)));
+            assertSame(currentValue, val.get());
+            assertEquals(42, val.get().intValue());
+        }
+
+        Integer newValue = Integer.valueOf(0);
+        do { } while (!val.weakCompareAndSetAcquire(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(0, currentValue.intValue());
+
+        newValue = Integer.valueOf(5);
+        do { } while (!val.weakCompareAndSetAcquire(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(5, currentValue.intValue());
+
+        newValue = Integer.valueOf(-1);
+        do { } while (!val.weakCompareAndSetAcquire(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(-1, currentValue.intValue());
+    }
+
+    @Test
+    public void testWeakCompareAndSetPlain() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetPlain(Integer.valueOf(0), Integer.valueOf(-1)));
+            assertSame(currentValue, val.get());
+            assertEquals(42, val.get().intValue());
+        }
+
+        Integer newValue = Integer.valueOf(0);
+        do { } while (!val.weakCompareAndSetPlain(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(0, currentValue.intValue());
+
+        newValue = Integer.valueOf(5);
+        do { } while (!val.weakCompareAndSetPlain(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(5, currentValue.intValue());
+
+        newValue = Integer.valueOf(-1);
+        do { } while (!val.weakCompareAndSetPlain(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(-1, currentValue.intValue());
+    }
+
+    @Test
+    public void testWeakCompareAndSetRelease() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetRelease(Integer.valueOf(0), Integer.valueOf(-1)));
+            assertSame(currentValue, val.get());
+            assertEquals(42, val.get().intValue());
+        }
+
+        Integer newValue = Integer.valueOf(0);
+        do { } while (!val.weakCompareAndSetRelease(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(0, currentValue.intValue());
+
+        newValue = Integer.valueOf(5);
+        do { } while (!val.weakCompareAndSetRelease(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(5, currentValue.intValue());
+
+        newValue = Integer.valueOf(-1);
+        do { } while (!val.weakCompareAndSetRelease(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(-1, currentValue.intValue());
+    }
+
+    @Test
+    public void testWeakCompareAndSetVolatile() {
+        Integer currentValue = Integer.valueOf(42);
+        AtomicReference<Integer> val = new AtomicReference(currentValue);
+        for (int i = 0; i < 10; ++i) {
+            assertFalse(val.weakCompareAndSetVolatile(Integer.valueOf(0), Integer.valueOf(-1)));
+            assertSame(currentValue, val.get());
+            assertEquals(42, val.get().intValue());
+        }
+
+        Integer newValue = Integer.valueOf(0);
+        do { } while (!val.weakCompareAndSetVolatile(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(0, currentValue.intValue());
+
+        newValue = Integer.valueOf(5);
+        do { } while (!val.weakCompareAndSetVolatile(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(5, currentValue.intValue());
+
+        newValue = Integer.valueOf(-1);
+        do { } while (!val.weakCompareAndSetVolatile(currentValue, newValue));
+        currentValue = val.get();
+        assertSame(newValue, currentValue);
+        assertEquals(-1, currentValue.intValue());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentLinkedDequeTest.java b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentLinkedDequeTest.java
new file mode 100644
index 0000000..6a6f7ea
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentLinkedDequeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.atomic.LongAdder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ConcurrentLinkedDequeTest {
+
+    @Test
+    public void testForEach() {
+        int capacity = 10;
+        ConcurrentLinkedDeque<Integer> deque = new ConcurrentLinkedDeque<>();
+        for (int i = 0; i < capacity; ++i) {
+            deque.add(Integer.valueOf(i+1));
+        }
+        LongAdder adder = new LongAdder();
+        deque.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(deque.size() * (deque.size() + 1) / 2, adder.sum());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentLinkedQueueTest.java b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentLinkedQueueTest.java
new file mode 100644
index 0000000..6a1bffa
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentLinkedQueueTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.LongAdder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ConcurrentLinkedQueueTest {
+
+    @Test
+    public void testForEach() {
+        int capacity = 10;
+        ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
+        for (int i = 0; i < capacity; ++i) {
+            queue.add(Integer.valueOf(i+1));
+        }
+        LongAdder adder = new LongAdder();
+        queue.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(queue.size() * (queue.size() + 1) / 2, adder.sum());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListSetTest.java b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListSetTest.java
index bd858b0..dbbb948 100644
--- a/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListSetTest.java
+++ b/luni/src/test/java/libcore/java/util/concurrent/ConcurrentSkipListSetTest.java
@@ -22,7 +22,9 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import java.util.Arrays;
 import java.util.Iterator;
+import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentSkipListSet;
 
@@ -96,4 +98,23 @@
         assertEquals(i, size);
     }
 
+    @Test
+    public void testHeadSet() {
+        ConcurrentSkipListSet<Integer> set = new ConcurrentSkipListSet<>();
+        for (int i = -5; i < 5; i++) {
+            set.add(i);
+            // Adding twice should make no difference to the set.
+            set.add(i);
+        }
+
+        Set<Integer> headset = set.headSet(-1, true);
+        assertTrue(headset.containsAll(Arrays.asList(-5, -4, -3, -2, -1)));
+        assertEquals(5, headset.size());
+
+
+        headset = set.headSet(-1, false);
+        assertTrue(headset.containsAll(Arrays.asList(-5, -4, -3, -2)));
+        assertEquals(4, headset.size());
+    }
+
 }
diff --git a/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java b/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java
index 80005df..4a62623 100644
--- a/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java
+++ b/luni/src/test/java/libcore/java/util/concurrent/CopyOnWriteArrayListTest.java
@@ -285,7 +285,7 @@
     public void testDoesNotRetainToArray() {
         String[] strings = { "a", "b", "c" };
         List<String> asList = Arrays.asList(strings);
-        assertEquals(String[].class, asList.toArray().getClass());
+
         CopyOnWriteArrayList<Object> objects = new CopyOnWriteArrayList<Object>(asList);
         objects.add(Boolean.TRUE);
     }
@@ -434,4 +434,30 @@
         } catch (NullPointerException expected) {
         }
     }
+
+    public void test_get_returnType() {
+        List<TestBase> input = new ArrayList();
+        input.add(new TestBase());
+        input.add(new TestDerived());
+        List<TestBase> l = new CopyOnWriteArrayList(input);
+
+        assertEquals(TestBase.class, l.get(0).getClass());
+        assertEquals(TestDerived.class, l.get(1).getClass());
+    }
+
+    public void test_toArray_returnType() {
+        List<TestBase> input = new ArrayList();
+        input.add(new TestBase());
+        input.add(new TestDerived());
+        List<TestBase> l = new CopyOnWriteArrayList(input);
+
+        assertEquals(Object[].class, l.toArray().getClass());
+    }
+
+
+    private static class TestBase {
+    }
+
+    private static class TestDerived extends TestBase {
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/concurrent/ForkJoinPoolTest.java b/luni/src/test/java/libcore/java/util/concurrent/ForkJoinPoolTest.java
index 578970e..48d4170 100644
--- a/luni/src/test/java/libcore/java/util/concurrent/ForkJoinPoolTest.java
+++ b/luni/src/test/java/libcore/java/util/concurrent/ForkJoinPoolTest.java
@@ -70,4 +70,94 @@
             fail("Unexpected exception: " + t.getMessage());
         }
     }
+
+    @Test
+    public void testConstructor_withKeepAliveTime() {
+
+        try {
+            ForkJoinPool pool = new ForkJoinPool(0,
+                    ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+                    /*handler*/ null,
+                    /*asyncMode*/ false,
+                    /*corePoolSize*/ 10,
+                    /*maximumPoolSize*/ 10,
+                    /*minimumRunnable*/ 1,
+                    /*saturate*/ null,
+                    /*keepAliveTime*/ 60,
+                    /*unit*/ TimeUnit.SECONDS);
+            fail("Expected IllegalArgumentException when parallelism is 0");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            ForkJoinPool pool = new ForkJoinPool(-1,
+                    ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+                    /*handler*/ null,
+                    /*asyncMode*/ false,
+                    /*corePoolSize*/ 10,
+                    /*maximumPoolSize*/ 10,
+                    /*minimumRunnable*/ 1,
+                    /*saturate*/ null,
+                    /*keepAliveTime*/ 60,
+                    /*unit*/ TimeUnit.SECONDS);
+            fail("Expected IllegalArgumentException when parallelism is less than 0");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            ForkJoinPool pool = new ForkJoinPool(8,
+                    ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+                    /*handler*/ null,
+                    /*asyncMode*/ false,
+                    /*corePoolSize*/ 10,
+                    /*maximumPoolSize*/ 5,
+                    /*minimumRunnable*/ 1,
+                    /*saturate*/ null,
+                    /*keepAliveTime*/ 60,
+                    /*unit*/ TimeUnit.SECONDS);
+            fail("Expected IllegalArgumentException when maximumPoolSize is less than parallelism");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            ForkJoinPool pool = new ForkJoinPool(8,
+                    ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+                    /*handler*/ null,
+                    /*asyncMode*/ false,
+                    /*corePoolSize*/ 10,
+                    /*maximumPoolSize*/ 10,
+                    /*minimumRunnable*/ 1,
+                    /*saturate*/ null,
+                    /*keepAliveTime*/ 0,
+                    /*unit*/ TimeUnit.SECONDS);
+            fail("Expected IllegalArgumentException when keepAlivetime is 0");
+        } catch (IllegalArgumentException e) {
+        }
+
+        try {
+            ForkJoinPool pool = new ForkJoinPool(8,
+                    null,
+                    /*handler*/ null,
+                    /*asyncMode*/ false,
+                    /*corePoolSize*/ 10,
+                    /*maximumPoolSize*/ 10,
+                    /*minimumRunnable*/ 1,
+                    /*saturate*/ null,
+                    /*keepAliveTime*/ 60,
+                    /*unit*/ TimeUnit.SECONDS);
+            fail("Expected NullPointerException when factory is null");
+        } catch (NullPointerException e) {
+        }
+
+        ForkJoinPool pool = new ForkJoinPool(8,
+                ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+                /*handler*/ null,
+                /*asyncMode*/ false,
+                /*corePoolSize*/ 10,
+                /*maximumPoolSize*/ 10,
+                /*minimumRunnable*/ 1,
+                /*saturate*/ null,
+                /*keepAliveTime*/ 60,
+                /*unit*/ TimeUnit.SECONDS);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/concurrent/LinkedBlockingDequeTest.java b/luni/src/test/java/libcore/java/util/concurrent/LinkedBlockingDequeTest.java
new file mode 100644
index 0000000..66dd942
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/LinkedBlockingDequeTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.atomic.LongAdder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class LinkedBlockingDequeTest {
+
+    @Test
+    public void testForEach() {
+        int capacity = 10;
+        LinkedBlockingDeque<Integer> deque = new LinkedBlockingDeque<>();
+        for (int i = 0; i < capacity; ++i) {
+            deque.add(Integer.valueOf(i+1));
+        }
+        LongAdder adder = new LongAdder();
+        deque.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(deque.size() * (deque.size() + 1) / 2, adder.sum());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/LinkedBlockingQueueTest.java b/luni/src/test/java/libcore/java/util/concurrent/LinkedBlockingQueueTest.java
new file mode 100644
index 0000000..4363988
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/LinkedBlockingQueueTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.LongAdder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class LinkedBlockingQueueTest {
+
+    @Test
+    public void testForEach() {
+        int capacity = 10;
+        LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
+        for (int i = 0; i < capacity; ++i) {
+            queue.add(Integer.valueOf(i+1));
+        }
+        LongAdder adder = new LongAdder();
+        queue.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(queue.size() * (queue.size() + 1) / 2, adder.sum());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/LinkedTransferQueueTest.java b/luni/src/test/java/libcore/java/util/concurrent/LinkedTransferQueueTest.java
new file mode 100644
index 0000000..5b09284
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/LinkedTransferQueueTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.atomic.LongAdder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class LinkedTransferQueueTest {
+
+    @Test
+    public void testForEach() {
+        int capacity = 10;
+        LinkedTransferQueue<Integer> queue = new LinkedTransferQueue<>();
+        for (int i = 0; i < capacity; ++i) {
+            queue.add(Integer.valueOf(i+1));
+        }
+        LongAdder adder = new LongAdder();
+        queue.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(queue.size() * (queue.size() + 1) / 2, adder.sum());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/PriorityBlockingQueueTest.java b/luni/src/test/java/libcore/java/util/concurrent/PriorityBlockingQueueTest.java
new file mode 100644
index 0000000..ba7bc0c
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/PriorityBlockingQueueTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.atomic.LongAdder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class PriorityBlockingQueueTest {
+
+    @Test
+    public void testForEach() {
+        int capacity = 10;
+        PriorityBlockingQueue<Integer> queue = new PriorityBlockingQueue<>(capacity);
+        for (int i = 0; i < capacity; ++i) {
+            queue.add(Integer.valueOf(i+1));
+        }
+        LongAdder adder = new LongAdder();
+        queue.forEach((Integer x) -> adder.add(x.longValue()));
+        // The size is small enough for the sum not to overflow
+        assertEquals(queue.size() * (queue.size() + 1) / 2, adder.sum());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/concurrent/StampedLockTest.java b/luni/src/test/java/libcore/java/util/concurrent/StampedLockTest.java
new file mode 100644
index 0000000..efcc492
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/concurrent/StampedLockTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 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.concurrent;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.locks.StampedLock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class StampedLockTest {
+
+    @Test
+    public void testIsLockStamp() {
+        final StampedLock lock = new StampedLock();
+
+        long stamp = lock.tryConvertToReadLock(0L);
+        assertFalse(lock.isLockStamp(stamp));
+
+        stamp = lock.tryOptimisticRead();
+        stamp = lock.tryConvertToReadLock(stamp);
+        assertTrue(lock.isLockStamp(stamp));
+
+        lock.unlockRead(stamp);
+    }
+
+    @Test
+    public void testIsOptimisticReadStamp() {
+        final StampedLock lock = new StampedLock();
+
+        long stamp = lock.readLock();
+        assertFalse(lock.isOptimisticReadStamp(stamp));
+
+        stamp = lock.tryConvertToOptimisticRead(stamp);
+        assertTrue(lock.isOptimisticReadStamp(stamp));
+
+        stamp = lock.readLock();
+        lock.unlockRead(stamp);
+    }
+
+    @Test
+    public void testIsReadLockStamp() {
+        final StampedLock lock = new StampedLock();
+
+        long stamp = lock.writeLock();
+        assertFalse(lock.isReadLockStamp(stamp));
+        lock.unlockWrite(stamp);
+
+        stamp = lock.readLock();
+        assertTrue(lock.isReadLockStamp(stamp));
+        lock.unlockRead(stamp);
+    }
+
+    @Test
+    public void testIsWriteLockStamp() {
+        final StampedLock lock = new StampedLock();
+
+        long stamp = lock.readLock();
+        assertFalse(lock.isWriteLockStamp(stamp));
+        lock.unlockRead(stamp);
+
+        stamp = lock.writeLock();
+        assertTrue(lock.isWriteLockStamp(stamp));
+        lock.unlockWrite(stamp);
+    }
+
+}
diff --git a/luni/src/test/java/libcore/javax/security/auth/AuthPermissionTest.java b/luni/src/test/java/libcore/javax/security/auth/AuthPermissionTest.java
new file mode 100644
index 0000000..e4715d0
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/AuthPermissionTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.javax.security.auth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import javax.security.auth.AuthPermission;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class AuthPermissionTest {
+
+    @Test
+    public void constructorWithString() {
+        AuthPermission permission = new AuthPermission("name");
+        assertNotNull(permission);
+        assertEquals("", permission.getName());
+    }
+
+    @Test
+    public void constructorWithStringAndString() {
+        AuthPermission permission = new AuthPermission("name", "actions");
+        assertNotNull(permission);
+        assertEquals("", permission.getName());
+        assertEquals("", permission.getActions());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/security/auth/PrivateCredentialPermissionTest.java b/luni/src/test/java/libcore/javax/security/auth/PrivateCredentialPermissionTest.java
new file mode 100644
index 0000000..8ecb49b
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/PrivateCredentialPermissionTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 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.javax.security.auth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.security.AllPermission;
+import javax.security.auth.AuthPermission;
+import javax.security.auth.PrivateCredentialPermission;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class PrivateCredentialPermissionTest {
+
+    private PrivateCredentialPermission permission;
+
+    @Before
+    public void setUp() {
+        permission = new PrivateCredentialPermission("name", "actions");
+    }
+
+    @Test
+    public void constructorWithStringAndString() {
+        assertNotNull(permission);
+        assertEquals("", permission.getName());
+        assertNull(permission.getActions());
+    }
+
+    @Test
+    public void getActions() {
+        assertNull(permission.getActions());
+    }
+
+    @Test
+    public void getCredentialClass() {
+        assertNull(permission.getCredentialClass());
+    }
+
+    @Test
+    public void getPrincipals() {
+        assertNull(permission.getPrincipals());
+    }
+
+    @Test
+    public void implies() {
+        assertTrue(permission.implies(new AuthPermission("")));
+        assertTrue(permission.implies(new AllPermission()));
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/security/auth/SubjectDomainCombinerTest.java b/luni/src/test/java/libcore/javax/security/auth/SubjectDomainCombinerTest.java
new file mode 100644
index 0000000..a88670c
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/SubjectDomainCombinerTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.javax.security.auth;
+
+import static org.junit.Assert.assertNull;
+
+import javax.security.auth.Subject;
+import javax.security.auth.SubjectDomainCombiner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class SubjectDomainCombinerTest {
+
+    @Test
+    public void combine() {
+        SubjectDomainCombiner combiner = new SubjectDomainCombiner(null);
+        assertNull(combiner.combine(null, null));
+    }
+
+    @Test
+    public void getSubject() {
+        SubjectDomainCombiner combiner = new SubjectDomainCombiner(null);
+        assertNull(combiner.getSubject());
+
+        combiner = new SubjectDomainCombiner(new Subject());
+        assertNull(combiner.getSubject());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/security/auth/SubjectTest.java b/luni/src/test/java/libcore/javax/security/auth/SubjectTest.java
new file mode 100644
index 0000000..0af23fc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/security/auth/SubjectTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 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.javax.security.auth;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.security.Principal;
+import java.util.Set;
+import javax.security.auth.Subject;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import sun.security.x509.X500Name;
+
+/**
+ * Android does not support {@link java.lang.SecurityManager} and has its implementations stubbed.
+ * See comments in {@link java.lang.SecurityManager} for details.
+ *
+ * This test is added primarily for code coverage.
+ */
+@RunWith(JUnit4.class)
+public class SubjectTest {
+
+    private Set<Principal> set;
+    private Subject subject;
+
+    @Before
+    public void setUp() {
+        set = Set.of(new PrincipalImpl());
+        subject = new Subject(true, set, set, set);
+    }
+
+    @Test
+    public void getPrincipals() {
+        assertEquals(set, subject.getPrincipals());
+
+        assertEquals(set, subject.getPrincipals(PrincipalImpl.class));
+        assertEquals(set, subject.getPrincipals(Principal.class));
+        // PrincipalImpl is not a subclass of X500Name.
+        assertEquals(0, subject.getPrincipals(X500Name.class).size());
+    }
+
+    @Test
+    public void getPrivateCredentials() {
+        assertEquals(set, subject.getPrivateCredentials());
+
+        assertEquals(set, subject.getPrivateCredentials(PrincipalImpl.class));
+        assertEquals(set, subject.getPrivateCredentials(Principal.class));
+        // PrincipalImpl is not a subclass of X500Name.
+        assertEquals(0, subject.getPrivateCredentials(X500Name.class).size());
+    }
+
+    @Test
+    public void getPublicCredentials() {
+        assertEquals(set, subject.getPublicCredentials());
+
+        assertEquals(set, subject.getPublicCredentials(PrincipalImpl.class));
+        assertEquals(set, subject.getPublicCredentials(Principal.class));
+        // PrincipalImpl is not a subclass of X500Name.
+        assertEquals(0, subject.getPublicCredentials(X500Name.class).size());
+    }
+
+    @Test
+    public void isReadOnly() {
+        assertTrue(subject.isReadOnly());
+
+        subject = new Subject(false, set, set, set);
+        assertFalse(subject.isReadOnly());
+    }
+
+    @Test
+    public void setReadOnly() {
+        subject = new Subject(false, set, set, set);
+        assertFalse(subject.isReadOnly());
+
+        subject.setReadOnly();
+        assertTrue(subject.isReadOnly());
+    }
+
+    private static final class PrincipalImpl implements Principal {
+
+        @Override
+        public String getName() {
+            return "";
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java
new file mode 100644
index 0000000..3b6708d
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConfigurationExceptionTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.datatype;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DatatypeConfigurationExceptionTest {
+
+    @Test
+    public void constructor() {
+        DatatypeConfigurationException e = new DatatypeConfigurationException();
+        assertNull(e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndThrowable() {
+        Throwable t = new Throwable();
+        DatatypeConfigurationException e = new DatatypeConfigurationException("message", t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        DatatypeConfigurationException e = new DatatypeConfigurationException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConstantsTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConstantsTest.java
new file mode 100644
index 0000000..f1797d1
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeConstantsTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.datatype;
+
+import javax.xml.datatype.DatatypeConstants;
+import junit.framework.TestCase;
+
+public class DatatypeConstantsTest extends TestCase {
+
+    public void testField_getId() {
+        assertEquals(0, DatatypeConstants.YEARS.getId());
+        assertEquals(1, DatatypeConstants.MONTHS.getId());
+        assertEquals(2, DatatypeConstants.DAYS.getId());
+        assertEquals(3, DatatypeConstants.HOURS.getId());
+        assertEquals(4, DatatypeConstants.MINUTES.getId());
+        assertEquals(5, DatatypeConstants.SECONDS.getId());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java
new file mode 100644
index 0000000..d062d3c
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DatatypeFactoryTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.GregorianCalendar;
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+import junit.framework.TestCase;
+
+public class DatatypeFactoryTest extends TestCase {
+
+    private DatatypeFactory factory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        factory = new ExtendsDatatypeFactory();
+    }
+
+    public void testConstructor() {
+        DatatypeFactory f = new ExtendsDatatypeFactory();
+    }
+
+    public void testNewDuration_biiiiii() {
+        Duration duration = factory.newDuration(true, 1, 2, 3, 4, 5, 6);
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(3, duration.getDays());
+        assertEquals(4, duration.getHours());
+        assertEquals(5, duration.getMinutes());
+        assertEquals(6, duration.getSeconds());
+    }
+
+    public void testNewDurationDayTime_biiii() {
+        Duration duration = factory.newDurationDayTime(true, 3, 4, 5, 6);
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(3, duration.getDays());
+        assertEquals(4, duration.getHours());
+        assertEquals(5, duration.getMinutes());
+        assertEquals(6, duration.getSeconds());
+    }
+
+    public void testNewDurationDayTime_bBigInteger() {
+        Duration duration = factory.newDuration(true, BigInteger.valueOf(1), BigInteger.valueOf(2),
+                BigInteger.valueOf(3), BigInteger.valueOf(4), BigInteger.valueOf(5),
+                BigDecimal.valueOf(6));
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(3, duration.getDays());
+        assertEquals(4, duration.getHours());
+        assertEquals(5, duration.getMinutes());
+        assertEquals(6, duration.getSeconds());
+
+        duration = factory.newDurationDayTime(true,
+            BigInteger.valueOf(3), BigInteger.valueOf(4), BigInteger.valueOf(5),
+            BigInteger.valueOf(6));
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(3, duration.getDays());
+        assertEquals(4, duration.getHours());
+        assertEquals(5, duration.getMinutes());
+        assertEquals(6, duration.getSeconds());
+    }
+
+    public void testNewDurationDayTime_String() {
+        Duration duration = factory.newDuration("");
+        assertNull(duration);
+
+        duration = factory.newDurationDayTime("");
+        assertNull(duration);
+    }
+
+    public void testNewDurationDayTime_long() {
+        Duration duration = factory.newDuration(1000L);
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(1, duration.getSeconds());
+
+        duration = factory.newDurationDayTime(1000L);
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(1, duration.getSeconds());
+    }
+
+    public void testNewDurationYearMonth_bii() {
+        Duration duration = factory.newDurationYearMonth(true, 1, 2);
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(0, duration.getSeconds());
+    }
+
+    public void testNewDurationYearMonth_bBigInteger() {
+        Duration duration = factory.newDurationYearMonth(true, BigInteger.valueOf(1), BigInteger.valueOf(2));
+        assertEquals(1, duration.getYears());
+        assertEquals(2, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(0, duration.getSeconds());
+    }
+
+    public void testNewDurationYearMonth_String() {
+        Duration duration = factory.newDurationYearMonth("");
+        assertNull(duration);
+    }
+
+    public void testNewDurationYearMonth_long() {
+        Duration duration = factory.newDurationYearMonth(1000);
+        assertEquals(0, duration.getYears());
+        assertEquals(0, duration.getMonths());
+        assertEquals(0, duration.getDays());
+        assertEquals(0, duration.getHours());
+        assertEquals(0, duration.getMinutes());
+        assertEquals(1, duration.getSeconds());
+    }
+
+    public void testNewInstance() {
+        try {
+            DatatypeFactory.newInstance();
+            fail("Unexpectedly created new instance");
+        } catch (DatatypeConfigurationException expected) {
+            // no default implementation in Android
+        }
+    }
+
+    public void testNewInstance_customClass() {
+        try {
+            DatatypeFactory.newInstance(null, null);
+            fail("Unexpectedly created new instance");
+        } catch (DatatypeConfigurationException expected) {
+            // class loading disabled
+        }
+    }
+
+    public void testNewXMLGregorianCalendar_iiiiiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendar(
+                1, 2, 3, 4, 5, 6, 7, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarDate_iiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarDate(1, 2, 3, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarTime_iiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarTime(4, 5, 6, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarTime_iiiii() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarTime(4, 5, 6, 7, 0);
+        assertNull(calendar);
+    }
+
+    public void testNewXMLGregorianCalendarTime_BigDecimal() {
+        XMLGregorianCalendar calendar = factory.newXMLGregorianCalendarTime(4, 5, 6, BigDecimal.valueOf(7), 0);
+        assertNull(calendar);
+    }
+
+    private static class ExtendsDatatypeFactory extends DatatypeFactory {
+
+        protected ExtendsDatatypeFactory() {
+            super();
+        }
+
+        @Override
+        public Duration newDuration(String lexicalRepresentation) {
+            return null;
+        }
+
+        @Override
+        public Duration newDuration(long durationInMilliSeconds) {
+            return new DurationImpl(durationInMilliSeconds);
+        }
+
+        @Override
+        public Duration newDuration(boolean isPositive, BigInteger years,
+                BigInteger months, BigInteger days, BigInteger hours,
+                BigInteger minutes, BigDecimal seconds) {
+            int y = years == null ? DatatypeConstants.FIELD_UNDEFINED : years.intValue();
+            int m = months == null ? DatatypeConstants.FIELD_UNDEFINED : months.intValue();
+            int d = days == null ? DatatypeConstants.FIELD_UNDEFINED : days.intValue();
+            int h = hours == null ? DatatypeConstants.FIELD_UNDEFINED : hours.intValue();
+            int mn = minutes == null ? DatatypeConstants.FIELD_UNDEFINED : minutes.intValue();
+            int s = seconds == null ? DatatypeConstants.FIELD_UNDEFINED : seconds.intValue();
+            return new DurationImpl(isPositive ? 1 : -1, y, m, d, h, mn, s);
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar() {
+            return null;
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar(String lexicalRepresentation) {
+            return null;
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar(GregorianCalendar cal) {
+            return null;
+        }
+
+        @Override
+        public XMLGregorianCalendar newXMLGregorianCalendar(BigInteger year, int month,
+                int day, int hour, int minute, int second,
+                BigDecimal fractionalSecond, int timezone) {
+            return null;
+        }
+
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DurationImpl.java b/luni/src/test/java/libcore/javax/xml/datatype/DurationImpl.java
new file mode 100644
index 0000000..ae89cbc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DurationImpl.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.datatype;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeConstants.Field;
+import javax.xml.datatype.Duration;
+
+/**
+ * Avoid depending on {@link javax.xml.datatype.DatatypeFactory}, and
+ * throws {@link UnsupportedOperationException} on abstract methods,
+ * since proper implementation does not exist in Android.
+ */
+public class DurationImpl extends javax.xml.datatype.Duration {
+
+    private final int sign;
+    private final Map<Field, Number> fields;
+
+    DurationImpl(long millis) {
+        fields = new HashMap<>();
+        if (millis > 0) {
+            sign = 1;
+        } else if (millis == 0) {
+            sign = 0;
+            return;
+        } else {
+            sign = -1;
+            millis = -millis;
+        }
+        long d = millis / 86400000L;
+        millis %= 86400000L;
+        if (d > 0) {
+            fields.put(DatatypeConstants.DAYS, d);
+        }
+        long h = millis / 3600000L;
+        millis %= 3600000L;
+        if (h > 0) {
+            fields.put(DatatypeConstants.HOURS, h);
+        }
+        long m = millis / 60000L;
+        millis %= 60000L;
+        if (m > 0) {
+            fields.put(DatatypeConstants.MINUTES, m);
+        }
+        fields.put(DatatypeConstants.SECONDS, (float)millis / 1000);
+    }
+
+    DurationImpl(int sgn, int y, int months, int d, int h, int m, float s) {
+        sign = sgn;
+        fields = new HashMap<>();
+        if (y >= 0) { fields.put(DatatypeConstants.YEARS, y); }
+        if (months >= 0) { fields.put(DatatypeConstants.MONTHS, months); }
+        if (d >= 0) { fields.put(DatatypeConstants.DAYS, d); }
+        if (h >= 0) { fields.put(DatatypeConstants.HOURS, h); }
+        if (m >= 0) { fields.put(DatatypeConstants.MINUTES, m); }
+        if (s >= 0) { fields.put(DatatypeConstants.SECONDS, s); }
+    }
+
+    @Override
+    public int getSign() {
+        return sign;
+    }
+
+    @Override
+    public Number getField(Field field) {
+        return fields.get(field);
+    }
+
+    @Override
+    public boolean isSet(Field field) {
+        return fields.containsKey(field);
+    }
+
+    @Override
+    public Duration add(Duration rhs) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public void addTo(Calendar calendar) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public Duration multiply(BigDecimal factor) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public Duration negate() {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public Duration normalizeWith(Calendar startTimeInstant) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public int compare(Duration duration) {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException("Stub implementation");
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/DurationTest.java b/luni/src/test/java/libcore/javax/xml/datatype/DurationTest.java
new file mode 100644
index 0000000..ad9dba6
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/DurationTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.datatype;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.Duration;
+import junit.framework.TestCase;
+
+/**
+ * Android has no {@link Duration} implementation, so use stubbed one that throws
+ * on abstract methods. This unit test is primarily for code coverage, it barely tests
+ * the actual implementation.
+ */
+public class DurationTest extends TestCase {
+
+    private static final Duration oneSecond = new DurationImpl(1, 0, 0, 0, 0, 0, 1);
+    private static final Duration tenMinutes = new DurationImpl(1, 0, 0, 0, 0, 10, 0);
+    private static final Duration oneDay = new DurationImpl(1, 0, 0, 1, 0 , 0, 0);
+    private static final Duration fiveDays = new DurationImpl(1, 0, 0, 5, 0, 0, 0);
+    private static final Duration twoMonths = new DurationImpl(1, 0, 2, 0, 0, 0, 0);
+    private static final Duration threeYears = new DurationImpl(1, 3, 0, 0, 0, 0, 0);
+    private static final Duration y6m5d4h3m2s1 = new DurationImpl(1, 6, 5, 4, 3, 2, 1);
+
+    public void testAddTo_Date() {
+        Date date = null;
+        try {
+            oneSecond.addTo(date);
+        } catch (NullPointerException expected) {}
+
+        date = new Date(1000);
+        try {
+            oneSecond.addTo(date);
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testGetDays() {
+        assertEquals(0, oneSecond.getDays());
+        assertEquals(0, tenMinutes.getDays());
+        assertEquals(1, oneDay.getDays());
+        assertEquals(5, fiveDays.getDays());
+        assertEquals(0, twoMonths.getDays());
+        assertEquals(4, y6m5d4h3m2s1.getDays());
+    }
+
+    public void testGetHours() {
+        assertEquals(0, oneSecond.getHours());
+        assertEquals(0, tenMinutes.getHours());
+        assertEquals(0, oneDay.getHours());
+        assertEquals(0, fiveDays.getHours());
+        assertEquals(0, twoMonths.getHours());
+        assertEquals(3, y6m5d4h3m2s1.getHours());
+    }
+
+    public void testGetMinutes() {
+        assertEquals(0, oneSecond.getMinutes());
+        assertEquals(10, tenMinutes.getMinutes());
+        assertEquals(0, oneDay.getMinutes());
+        assertEquals(0, fiveDays.getMinutes());
+        assertEquals(0, twoMonths.getMinutes());
+        assertEquals(2, y6m5d4h3m2s1.getMinutes());
+    }
+
+    public void testGetMonths() {
+        assertEquals(0, oneSecond.getMonths());
+        assertEquals(0, tenMinutes.getMonths());
+        assertEquals(0, oneDay.getMonths());
+        assertEquals(0, fiveDays.getMonths());
+        assertEquals(2, twoMonths.getMonths());
+        assertEquals(0, threeYears.getMonths());
+        assertEquals(5, y6m5d4h3m2s1.getMonths());
+    }
+
+    public void testGetSeconds() {
+        assertEquals(1, oneSecond.getSeconds());
+        assertEquals(0, tenMinutes.getSeconds());
+        assertEquals(0, oneDay.getSeconds());
+        assertEquals(0, fiveDays.getSeconds());
+        assertEquals(0, twoMonths.getSeconds());
+        assertEquals(0, threeYears.getSeconds());
+        assertEquals(1, y6m5d4h3m2s1.getSeconds());
+    }
+
+    public void testGetTimeInMillis_calendar() {
+        Calendar calendar = GregorianCalendar.getInstance();
+        calendar.setTimeInMillis(1000);
+        try {
+            oneSecond.getTimeInMillis(calendar);
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testGetTimeInMillis_date() {
+        Date date = new Date(1000);
+        try {
+            oneSecond.getTimeInMillis(date);
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testGetXmlSchemaType() {
+        Duration allSet = new DurationImpl(1, 1, 1, 1, 1, 1, 1);
+        assertEquals(DatatypeConstants.DURATION, allSet.getXMLSchemaType());
+
+        Duration dayHourMinuteSecondSet = new DurationImpl(1, -1, -1, 1, 1, 1, 1);
+        assertEquals(DatatypeConstants.DURATION_DAYTIME, dayHourMinuteSecondSet.getXMLSchemaType());
+
+        Duration yearMonthSet = new DurationImpl(1, 1, 1, -1, -1, -1, -1);
+        assertEquals(DatatypeConstants.DURATION_YEARMONTH, yearMonthSet.getXMLSchemaType());
+
+        Duration noneSet = new DurationImpl(0, -1, -1, -1, -1, -1, -1);
+        try {
+            noneSet.getXMLSchemaType();
+            fail("Unexpectedly didn't throw");
+        } catch (IllegalStateException expected) {}
+    }
+
+    public void testGetYears() {
+        assertEquals(0, oneSecond.getYears());
+        assertEquals(0, tenMinutes.getYears());
+        assertEquals(0, oneDay.getYears());
+        assertEquals(0, fiveDays.getYears());
+        assertEquals(0, twoMonths.getYears());
+        assertEquals(3, threeYears.getYears());
+        assertEquals(6, y6m5d4h3m2s1.getYears());
+    }
+
+    public void testIsLongerThan() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (int i = 0; i < durations.length - 1; i++) {
+            for (int j = i + 1; j < durations.length; j++) {
+                try {
+                    assertTrue(durations[j].isLongerThan(durations[i]));
+                } catch (UnsupportedOperationException expected) {}
+            }
+        }
+    }
+
+    public void testIsShorterThan() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (int i = 0; i < durations.length - 1; i++) {
+            for (int j = i + 1; j < durations.length; j++) {
+                try {
+                    assertTrue(durations[i].isShorterThan(durations[j]));
+                } catch (UnsupportedOperationException expected) {}
+            }
+        }
+    }
+
+    public void testMultiply() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (Duration d : durations) {
+            try {
+                d.multiply(2);
+            } catch (UnsupportedOperationException expected) {}
+        }
+    }
+
+    public void testSubtract() {
+        final Duration[] durations = {
+                oneSecond, tenMinutes, oneDay, fiveDays, twoMonths, threeYears };
+        for (Duration i : durations) {
+            for (Duration j : durations) {
+                try {
+                    i.subtract(j);
+                } catch (UnsupportedOperationException expected) {}
+            }
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java b/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java
new file mode 100644
index 0000000..012facc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/datatype/XMLGregorianCalendarTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.datatype;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+import junit.framework.TestCase;
+
+public class XMLGregorianCalendarTest extends TestCase {
+
+    private XMLGregorianCalendar calendar;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        calendar = new XMLGregorianCalendarImpl();
+    }
+
+    public void testGetMillisecond() {
+        assertEquals(DatatypeConstants.FIELD_UNDEFINED, calendar.getMillisecond());
+    }
+
+    public void testSetTime_iii() {
+        calendar.setTime(1, 2, 3);
+        assertEquals(1, calendar.getHour());
+        assertEquals(2, calendar.getMinute());
+        assertEquals(3, calendar.getSecond());
+    }
+
+    public void testSetTime_iiii() {
+        calendar.setTime(1, 2, 3, 4);
+        assertEquals(1, calendar.getHour());
+        assertEquals(2, calendar.getMinute());
+        assertEquals(3, calendar.getSecond());
+        assertEquals(DatatypeConstants.FIELD_UNDEFINED, calendar.getMillisecond());
+    }
+
+    public void testSetTime_iiiBigDecimal() {
+        calendar.setTime(1, 2, 3, BigDecimal.valueOf(0.1));
+        assertEquals(1, calendar.getHour());
+        assertEquals(2, calendar.getMinute());
+        assertEquals(3, calendar.getSecond());
+        assertEquals(100, calendar.getMillisecond());
+        assertEquals(BigDecimal.valueOf(0.1), calendar.getFractionalSecond());
+    }
+
+    /**
+     * Stub implementation intended for test coverage.
+     */
+    private static final class XMLGregorianCalendarImpl extends XMLGregorianCalendar {
+
+        private int year;
+        private int month;
+        private int day;
+        private int hour;
+        private int minute;
+        private int second;
+        private int millisecond;
+        private BigDecimal fractional;
+        private int timezoneOffset;
+
+        @Override
+        public void clear() {
+            year = month = day = hour = minute = second = millisecond = timezoneOffset = 0;
+            fractional = BigDecimal.valueOf(0);
+        }
+
+        @Override
+        public void reset() {
+            year = month = day = hour = minute = second = millisecond = timezoneOffset = 0;
+            fractional = BigDecimal.valueOf(0);
+        }
+
+        @Override
+        public void setYear(BigInteger year) {
+            this.year = year.intValue();
+        }
+
+        @Override
+        public void setYear(int year) {
+            this.year = year;
+        }
+
+        @Override
+        public void setMonth(int month) {
+            this.month = month;
+        }
+
+        @Override
+        public void setDay(int day) {
+            this.day = day;
+        }
+
+        @Override
+        public void setTimezone(int offset) {
+            this.timezoneOffset = offset;
+        }
+
+        @Override
+        public void setHour(int hour) {
+            this.hour = hour;
+        }
+
+        @Override
+        public void setMinute(int minute) {
+            this.minute = minute;
+        }
+
+        @Override
+        public void setSecond(int second) {
+            this.second = second;
+        }
+
+        @Override
+        public void setMillisecond(int millisecond) {
+            this.millisecond = millisecond;
+        }
+
+        @Override
+        public void setFractionalSecond(BigDecimal fractional) {
+            this.fractional = fractional;
+        }
+
+        @Override
+        public BigInteger getEon() {
+            return null;
+        }
+
+        @Override
+        public int getYear() {
+            return year;
+        }
+
+        @Override
+        public BigInteger getEonAndYear() {
+            return null;
+        }
+
+        @Override
+        public int getMonth() {
+            return month;
+        }
+
+        @Override
+        public int getDay() {
+            return day;
+        }
+
+        @Override
+        public int getTimezone() {
+            return timezoneOffset;
+        }
+
+        @Override
+        public int getHour() {
+            return hour;
+        }
+
+        @Override
+        public int getMinute() {
+            return minute;
+        }
+
+        @Override
+        public int getSecond() {
+            return second;
+        }
+
+        @Override
+        public BigDecimal getFractionalSecond() {
+            return fractional;
+        }
+
+        @Override
+        public int compare(XMLGregorianCalendar rhs) {
+            if (year != rhs.getYear()) return year - rhs.getYear();
+            if (month != rhs.getMonth()) return month - rhs.getMonth();
+            if (day != rhs.getDay()) return day - rhs.getDay();
+            if (hour != rhs.getHour()) return hour - rhs.getHour();
+            if (minute != rhs.getMinute()) return minute - rhs.getMinute();
+            if (second != rhs.getSecond()) return second - rhs.getSecond();
+            if (millisecond != rhs.getMillisecond()) return millisecond - getMillisecond();
+            return fractional.subtract(rhs.getFractionalSecond()).intValue();
+        }
+
+        @Override
+        public XMLGregorianCalendar normalize() {
+            return null;
+        }
+
+        @Override
+        public String toXMLFormat() {
+            return null;
+        }
+
+        @Override
+        public QName getXMLSchemaType() {
+            return null;
+        }
+
+        @Override
+        public boolean isValid() {
+            return false;
+        }
+
+        @Override
+        public void add(Duration duration) {}
+
+        @Override
+        public GregorianCalendar toGregorianCalendar() {
+            return null;
+        }
+
+        @Override
+        public GregorianCalendar toGregorianCalendar(TimeZone timezone, Locale aLocale,
+                XMLGregorianCalendar defaults) {
+            return null;
+        }
+
+        @Override
+        public TimeZone getTimeZone(int defaultZoneoffset) {
+            return null;
+        }
+
+        @Override
+        public Object clone() {
+            return null;
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/namespace/QNameTest.java b/luni/src/test/java/libcore/javax/xml/namespace/QNameTest.java
new file mode 100644
index 0000000..b0afcae
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/namespace/QNameTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.namespace;
+
+import javax.xml.namespace.QName;
+import junit.framework.TestCase;
+
+public class QNameTest extends TestCase {
+
+    public void testConstructor() {
+        QName qName = new QName("hello");
+        assertEquals("", qName.getNamespaceURI());
+        assertEquals("", qName.getPrefix());
+        assertEquals("hello", qName.getLocalPart());
+    }
+
+    public void testEquals() {
+        QName qName = new QName("namespace", "local part", "prefix");
+        assertTrue(qName.equals(qName));
+        assertFalse(qName.equals(null));
+        assertFalse(qName.equals(new Object()));
+
+        QName qNameSame = new QName("namespace", "local part", "prefix");
+        assertTrue(qName.equals(qNameSame));
+        assertTrue(qNameSame.equals(qName));
+
+        // Check the namespace is considered in equality considerations.
+        QName qNameDifferentNamespace = new QName("another namespace", "local part", "prefix");
+        assertFalse(qName.equals(qNameDifferentNamespace));
+        assertFalse(qNameDifferentNamespace.equals(qName));
+
+        // Check the local part is considered in equality considerations.
+        QName qNameDifferentLocalPart = new QName("namespace", "another local part", "prefix");
+        assertFalse(qName.equals(qNameDifferentLocalPart));
+        assertFalse(qNameDifferentLocalPart.equals(qName));
+
+        // Check the prefix is not considered in equality considerations.
+        QName qNameDifferentPrefix = new QName("namespace", "local part", "another prefix");
+        assertTrue(qName.equals(qNameDifferentPrefix));
+        assertTrue(qNameDifferentPrefix.equals(qName));
+    }
+
+    public void testGetNamespaceURI() {
+        QName qName = new QName("namespace", "local part", "prefix");
+        assertEquals("namespace", qName.getNamespaceURI());
+        assertEquals("local part", qName.getLocalPart());
+        assertEquals("prefix", qName.getPrefix());
+
+        qName = new QName(null, "local part", "prefix");
+        assertEquals("", qName.getNamespaceURI());
+        assertEquals("local part", qName.getLocalPart());
+        assertEquals("prefix", qName.getPrefix());
+    }
+
+    public void testGetPrefix() {
+        QName qName = new QName("namespace", "local part", "prefix");
+        assertEquals("prefix", qName.getPrefix());
+
+        try {
+            new QName("namespace", "local part", null);
+            fail("Unexpectedly didn't throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {}
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderFactoryTest.java b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderFactoryTest.java
new file mode 100644
index 0000000..ae9a045
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderFactoryTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.parsers;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+import javax.xml.validation.ValidatorHandler;
+import junit.framework.TestCase;
+
+public class DocumentBuilderFactoryTest extends TestCase {
+
+    public void testGetSchema() {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+        try {
+            factory.getSchema();
+            fail("Unexpectedly didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testSetSchema() {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+        try {
+            factory.setSchema(new Schema() {
+                @Override
+                public Validator newValidator() { return null; }
+
+                @Override
+                public ValidatorHandler newValidatorHandler() { return null; }
+            });
+            fail("Unexpectedly didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException expected) {}
+    }
+
+    public void testNewInstance_StringClassLoader() {
+        try {
+            DocumentBuilderFactory.newInstance(null, null);
+        } catch (FactoryConfigurationError expected) {}
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java
index 646776a..e643bfd 100644
--- a/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java
+++ b/luni/src/test/java/libcore/javax/xml/parsers/DocumentBuilderTest.java
@@ -16,7 +16,17 @@
 
 package libcore.javax.xml.parsers;
 
-import static tests.support.Support_Xml.*;
+import static tests.support.Support_Xml.attrOf;
+import static tests.support.Support_Xml.domOf;
+import static tests.support.Support_Xml.firstChildTextOf;
+import static tests.support.Support_Xml.firstElementOf;
+
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
 
 public class DocumentBuilderTest extends junit.framework.TestCase {
     // http://code.google.com/p/android/issues/detail?id=2607
@@ -61,4 +71,35 @@
             // Expected.
         }
     }
+
+    public void testGetSchema() {
+        DocumentBuilder db = new DocumentBuilder() {
+            @Override
+            public Document parse(InputSource is) { return null; }
+
+            @Override
+            public boolean isNamespaceAware() { return false; }
+
+            @Override
+            public boolean isValidating() { return false; }
+
+            @Override
+            public void setEntityResolver(EntityResolver er) {}
+
+            @Override
+            public void setErrorHandler(ErrorHandler eh) {}
+
+            @Override
+            public Document newDocument() { return null; }
+
+            @Override
+            public DOMImplementation getDOMImplementation() { return null; }
+        };
+
+        try {
+            db.getSchema();
+            fail("Unexpectedly didn't throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException expected) {}
+    }
+
 }
diff --git a/luni/src/test/java/libcore/javax/xml/transform/SourceLocatorImpl.java b/luni/src/test/java/libcore/javax/xml/transform/SourceLocatorImpl.java
new file mode 100644
index 0000000..8219c31
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/SourceLocatorImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform;
+
+import javax.xml.transform.SourceLocator;
+
+public class SourceLocatorImpl implements SourceLocator {
+    @Override
+    public String getPublicId() { return null; }
+
+    @Override
+    public String getSystemId() { return null; }
+
+    @Override
+    public int getLineNumber() { return 0; }
+
+    @Override
+    public int getColumnNumber() { return 0; }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerConfigurationExceptionTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerConfigurationExceptionTest.java
new file mode 100644
index 0000000..254a586
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerConfigurationExceptionTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerConfigurationException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerConfigurationExceptionTest  {
+
+    @Test
+    public void constructor() {
+        TransformerConfigurationException e = new TransformerConfigurationException();
+        assertEquals("Configuration Error", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndThrowable() {
+        Throwable t = new Throwable();
+        TransformerConfigurationException e = new TransformerConfigurationException("message", t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndSourceLocator() {
+        SourceLocator locator = new SourceLocatorImpl();
+        TransformerConfigurationException e = new TransformerConfigurationException("message",
+                locator);
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void constructorWithStringSourceLocatorAndThrowable() {
+        SourceLocator locator = new SourceLocatorImpl();
+        Throwable t = new Throwable();
+        TransformerConfigurationException e = new TransformerConfigurationException("message",
+                locator, t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        TransformerConfigurationException e = new TransformerConfigurationException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void constructorWithString() {
+        TransformerConfigurationException e = new TransformerConfigurationException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+        assertNull(e.getLocator());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerExceptionTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerExceptionTest.java
new file mode 100644
index 0000000..83bad06
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerExceptionTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.SourceLocator;
+import javax.xml.transform.TransformerException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerExceptionTest {
+
+    @Test
+    public void constructorWithStringAndThrowable() {
+        Throwable t = new Throwable();
+        TransformerException e = new TransformerException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void constructorWithStringAndSourceLocator() {
+        SourceLocator locator = new SourceLocatorImpl();
+        TransformerException e = new TransformerException("message", locator);
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void constructorWithStringSourceLocatorAndThrowable() {
+        SourceLocator locator = new SourceLocatorImpl();
+        Throwable t = new Throwable();
+        TransformerException e = new TransformerException("message", locator, t);
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+        assertEquals(locator, e.getLocator());
+    }
+
+    @Test
+    public void getException() {
+        TransformerException e = new TransformerException("message");
+        Throwable t = e.getException();
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+
+    @Test
+    public void getMessageAndLocation() {
+        SourceLocator locator = new SourceLocatorImpl();
+        TransformerException e = new TransformerException("message", locator);
+        assertEquals("message", e.getMessageAndLocation());
+    }
+
+}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryConfigurationErrorTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryConfigurationErrorTest.java
new file mode 100644
index 0000000..ba8ab52
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryConfigurationErrorTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerFactoryConfigurationErrorTest {
+
+    @Test
+    public void constructor() {
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError();
+        assertNull(e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithException() {
+        Exception ex = new Exception("message");
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError(ex);
+        assertEquals("java.lang.Exception: message", e.getMessage());
+        assertEquals(ex, e.getException());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithExceptionAndString() {
+        Exception ex = new Exception("message");
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError(ex,
+                "another message");
+        assertEquals("another message", e.getMessage());
+        assertEquals(ex, e.getException());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithString() {
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void getException() {
+        TransformerFactoryConfigurationError e = new TransformerFactoryConfigurationError("message");
+        Throwable t = e.getException();
+        assertEquals("message", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryTest.java
new file mode 100644
index 0000000..0269e49
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerFactoryTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerFactoryTest {
+
+    @Test
+    public void newInstanceOfStringAndClassLoader() {
+        assertThrows(TransformerFactoryConfigurationError.class,
+                () -> TransformerFactory.newInstance(null, null));
+
+        try {
+            TransformerFactory.newInstance("nonexistent class", null);
+        } catch (TransformerFactoryConfigurationError expected) {
+            assertEquals(ClassNotFoundException.class, expected.getException().getClass());
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/TransformerTest.java b/luni/src/test/java/libcore/javax/xml/transform/TransformerTest.java
new file mode 100644
index 0000000..6c44a90
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/TransformerTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform;
+
+import java.util.Properties;
+import javax.xml.transform.ErrorListener;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TransformerTest {
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void reset() {
+        Transformer transformer = new TransformerImpl();
+        transformer.reset();
+    }
+
+    private static final class TransformerImpl extends Transformer {
+
+        @Override
+        public void reset() { super.reset(); }
+
+        @Override
+        public void transform(Source xmlSource, Result outputTarget) throws TransformerException {}
+
+        @Override
+        public void setParameter(String name, Object value) {}
+
+        @Override
+        public Object getParameter(String name) { return null; }
+
+        @Override
+        public void clearParameters() {}
+
+        @Override
+        public void setURIResolver(URIResolver resolver) {}
+
+        @Override
+        public URIResolver getURIResolver() { return null;  }
+
+        @Override
+        public void setOutputProperties(Properties oformat) {}
+
+        @Override
+        public Properties getOutputProperties() { return null; }
+
+        @Override
+        public void setOutputProperty(String name, String value) throws IllegalArgumentException {}
+
+        @Override
+        public String getOutputProperty(String name) throws IllegalArgumentException {
+            return null;
+        }
+
+        @Override
+        public void setErrorListener(ErrorListener listener) throws IllegalArgumentException {}
+
+        @Override
+        public ErrorListener getErrorListener() { return null; }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/dom/DOMResultTest.java b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMResultTest.java
new file mode 100644
index 0000000..6f9eacc
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMResultTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import javax.xml.transform.dom.DOMResult;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Comment;
+import org.w3c.dom.DOMConfiguration;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.Element;
+import org.w3c.dom.EntityReference;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.w3c.dom.UserDataHandler;
+import org.xml.sax.SAXException;
+
+@RunWith(JUnit4.class)
+public class DOMResultTest {
+
+    private Node node;
+    private Node documentNode;
+
+    @Before
+    public void setUp() throws SAXException, IOException {
+        node = new NodeImpl();
+        documentNode = new NodeImpl();
+    }
+
+    @Test
+    public void constructorWithNode() {
+        DOMResult result = new DOMResult(node);
+        assertNotNull(result);
+        assertEquals(node, result.getNode());
+    }
+
+    @Test
+    public void constructorWithNodeAndString() {
+        DOMResult result = new DOMResult(node, "systemId");
+        assertNotNull(result);
+        assertEquals(node, result.getNode());
+        assertEquals("systemId", result.getSystemId());
+    }
+
+    @Test
+    public void constructorWithNodeAndNode() {
+        documentNode.appendChild(node);
+        DOMResult result = new DOMResult(documentNode, node);
+        assertNotNull(result);
+        assertEquals(documentNode, result.getNode());
+        assertEquals(node, result.getNextSibling());
+    }
+
+    @Test
+    public void constructorWithNodeNodeAndString() {
+        documentNode.appendChild(node);
+        DOMResult result = new DOMResult(documentNode, node, "systemId");
+        assertNotNull(result);
+        assertEquals(documentNode, result.getNode());
+        assertEquals("systemId", result.getSystemId());
+        assertEquals(node, result.getNextSibling());
+    }
+
+    @Test
+    public void getSetSystemId() {
+        DOMResult result = new DOMResult(node);
+        assertNull(result.getSystemId());
+
+        result.setSystemId("systemId");
+        assertEquals("systemId", result.getSystemId());
+    }
+
+    @Test
+    public void getSetNextSibling() {
+        DOMResult result = new DOMResult(node);
+        assertNull(result.getNextSibling());
+
+        Node anotherNode = new NodeImpl();
+        result.setNextSibling(anotherNode);
+        assertNotEquals(node, result.getNextSibling());
+        assertEquals(anotherNode, result.getNextSibling());
+    }
+
+    private static final class NodeImpl implements Node, Document {
+
+        private final ArrayList<Node> children;
+
+        public NodeImpl() {
+            this.children = new ArrayList<>();
+        }
+
+        @Override
+        public String getNodeName() { return null; }
+
+        @Override
+        public String getNodeValue() throws DOMException { return null; }
+
+        @Override
+        public void setNodeValue(String nodeValue) throws DOMException {}
+
+        @Override
+        public short getNodeType() { return 0; }
+
+        @Override
+        public Node getParentNode() { return null; }
+
+        @Override
+        public NodeList getChildNodes() { return new NodeListImpl(children); }
+
+        @Override
+        public Node getFirstChild() { return children.get(0); }
+
+        @Override
+        public Node getLastChild() { return children.get(children.size() - 1); }
+
+        @Override
+        public Node getPreviousSibling() { return null; }
+
+        @Override
+        public Node getNextSibling() { return null; }
+
+        @Override
+        public NamedNodeMap getAttributes() { return null; }
+
+        @Override
+        public Document getOwnerDocument() { return null; }
+
+        @Override
+        public Node insertBefore(Node newChild, Node refChild) throws DOMException { return null; }
+
+        @Override
+        public Node replaceChild(Node newChild, Node oldChild) throws DOMException { return null; }
+
+        @Override
+        public Node removeChild(Node oldChild) throws DOMException { return null; }
+
+        @Override
+        public Node appendChild(Node newChild) throws DOMException { return null; }
+
+        @Override
+        public boolean hasChildNodes() { return false; }
+
+        @Override
+        public Node cloneNode(boolean deep) { return null; }
+
+        @Override
+        public void normalize() {}
+
+        @Override
+        public boolean isSupported(String feature, String version) { return false; }
+
+        @Override
+        public String getNamespaceURI() { return null; }
+
+        @Override
+        public String getPrefix() { return null; }
+
+        @Override
+        public void setPrefix(String prefix) throws DOMException {}
+
+        @Override
+        public String getLocalName() { return null; }
+
+        @Override
+        public boolean hasAttributes() { return false; }
+
+        @Override
+        public String getBaseURI() { return null; }
+
+        @Override
+        public short compareDocumentPosition(Node other) throws DOMException {
+            return DOCUMENT_POSITION_CONTAINED_BY;
+        }
+
+        @Override
+        public String getTextContent() throws DOMException { return null; }
+
+        @Override
+        public void setTextContent(String textContent) throws DOMException {}
+
+        @Override
+        public boolean isSameNode(Node other) { return false; }
+
+        @Override
+        public String lookupPrefix(String namespaceURI) { return null; }
+
+        @Override
+        public boolean isDefaultNamespace(String namespaceURI) { return false; }
+
+        @Override
+        public String lookupNamespaceURI(String prefix) { return null; }
+
+        @Override
+        public boolean isEqualNode(Node arg) { return false; }
+
+        @Override
+        public Object getFeature(String feature, String version) { return null; }
+
+        @Override
+        public Object setUserData(String key, Object data, UserDataHandler handler) { return null; }
+
+        @Override
+        public Object getUserData(String key) { return null; }
+
+        @Override
+        public DocumentType getDoctype() { return null; }
+
+        @Override
+        public DOMImplementation getImplementation() { return null; }
+
+        @Override
+        public Element getDocumentElement() { return null; }
+
+        @Override
+        public Element createElement(String tagName) throws DOMException { return null; }
+
+        @Override
+        public DocumentFragment createDocumentFragment() { return null; }
+
+        @Override
+        public Text createTextNode(String data) { return null; }
+
+        @Override
+        public Comment createComment(String data) { return null; }
+
+        @Override
+        public CDATASection createCDATASection(String data) throws DOMException { return null; }
+
+        @Override
+        public ProcessingInstruction createProcessingInstruction(String target, String data)
+                throws DOMException  { return null; }
+
+        @Override
+        public Attr createAttribute(String name) throws DOMException { return null; }
+
+        @Override
+        public EntityReference createEntityReference(String name) throws DOMException {
+            return null;
+        }
+
+        @Override
+        public NodeList getElementsByTagName(String tagname) { return null; }
+
+        @Override
+        public Node importNode(Node importedNode, boolean deep) throws DOMException  {
+            return null;
+        }
+
+        @Override
+        public Element createElementNS(String namespaceURI, String qualifiedName)
+                throws DOMException { return null; }
+
+        @Override
+        public Attr createAttributeNS(String namespaceURI, String qualifiedName)
+                throws DOMException { return null; }
+
+        @Override
+        public NodeList getElementsByTagNameNS(String namespaceURI, String localName)  {
+            return null;
+        }
+
+        @Override
+        public Element getElementById(String elementId) { return null; }
+
+        @Override
+        public String getInputEncoding() { return null; }
+
+        @Override
+        public String getXmlEncoding() { return null; }
+
+        @Override
+        public boolean getXmlStandalone() { return false; }
+
+        @Override
+        public void setXmlStandalone(boolean xmlStandalone) throws DOMException {}
+
+        @Override
+        public String getXmlVersion()  { return null; }
+
+        @Override
+        public void setXmlVersion(String xmlVersion) throws DOMException {}
+
+        @Override
+        public boolean getStrictErrorChecking() { return false; }
+
+        @Override
+        public void setStrictErrorChecking(boolean strictErrorChecking) {}
+
+        @Override
+        public String getDocumentURI() { return null;  }
+
+        @Override
+        public void setDocumentURI(String documentURI) {}
+
+        @Override
+        public Node adoptNode(Node source) throws DOMException { return null; }
+
+        @Override
+        public DOMConfiguration getDomConfig() { return null; }
+
+        @Override
+        public void normalizeDocument() {}
+
+        @Override
+        public Node renameNode(Node n, String namespaceURI, String qualifiedName)
+                throws DOMException { return null; }
+    }
+
+    private static final class NodeListImpl implements NodeList {
+
+        private final ArrayList<Node> list;
+
+        public NodeListImpl(ArrayList<Node> list) {
+            this.list = list;
+        }
+
+        @Override
+        public Node item(int index) {
+            return list.get(index);
+        }
+
+        @Override
+        public int getLength() {
+            return list.size();
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/dom/DOMSourceTest.java b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMSourceTest.java
new file mode 100644
index 0000000..2c18046
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/dom/DOMSourceTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform.dom;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.dom.DOMSource;
+import org.apache.harmony.xml.dom.CDATASectionImpl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.Node;
+
+@RunWith(JUnit4.class)
+public class DOMSourceTest {
+
+    @Test
+    public void constructor() {
+        DOMSource source = new DOMSource();
+        assertNotNull(source);
+        assertNull(source.getNode());
+        assertNull(source.getSystemId());
+    }
+
+    @Test
+    public void constructorWithNodeAndString() {
+        Node node = new CDATASectionImpl(null, "");
+        DOMSource source = new DOMSource(node, "systemId");
+        assertEquals(node, source.getNode());
+        assertEquals("systemId", source.getSystemId());
+    }
+
+    @Test
+    public void setSystemId() {
+        DOMSource source = new DOMSource();
+        assertNull(source.getSystemId());
+
+        source.setSystemId("systemId");
+        assertEquals("systemId", source.getSystemId());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/sax/SAXResultTest.java b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXResultTest.java
new file mode 100644
index 0000000..becccbb
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXResultTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform.sax;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import javax.xml.transform.sax.SAXResult;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.DefaultHandler;
+
+@RunWith(JUnit4.class)
+public class SAXResultTest {
+
+    private SAXResult result;
+
+    @Before
+    public void setUp() {
+        result = new SAXResult();
+    }
+
+    @Test
+    public void constructor() {
+        result = new SAXResult();
+        assertNull(result.getHandler());
+        assertNull(result.getLexicalHandler());
+        assertNull(result.getSystemId());
+    }
+
+    @Test
+    public void constructor_withContentHandler() {
+        ContentHandler handler = new DefaultHandler();
+        result = new SAXResult(handler);
+        assertEquals(handler, result.getHandler());
+        assertNull(result.getLexicalHandler());
+        assertNull(result.getSystemId());
+    }
+
+    @Test
+    public void getSetHandler() {
+        assertNull(result.getHandler());
+
+        ContentHandler handler = new DefaultHandler();
+        result.setHandler(handler);
+        assertEquals(handler, result.getHandler());
+
+        result.setHandler(null);
+        assertNull(result.getHandler());
+    }
+
+    @Test
+    public void getSetLexicalHandler() {
+        assertNull(result.getLexicalHandler());
+
+        LexicalHandler handler = new DefaultHandler2();
+        result.setLexicalHandler(handler);
+        assertEquals(handler, result.getLexicalHandler());
+
+        result.setLexicalHandler(null);
+        assertNull(result.getLexicalHandler());
+    }
+
+    @Test
+    public void getSetSystemId() {
+        assertNull(result.getSystemId());
+
+        String systemId = "systemId";
+        result.setSystemId(systemId);
+        assertEquals(systemId, result.getSystemId());
+
+        result.setSystemId(null);
+        assertNull(result.getSystemId());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/sax/SAXSourceTest.java b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXSourceTest.java
new file mode 100644
index 0000000..a032a36
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/sax/SAXSourceTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.transform.sax;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+
+@RunWith(JUnit4.class)
+public class SAXSourceTest {
+
+    private SAXSource source;
+
+    @Before
+    public void setUp() {
+        source = new SAXSource();
+    }
+
+    @Test
+    public void constructor() {
+        source = new SAXSource();
+        assertNull(source.getInputSource());
+        assertNull(source.getXMLReader());
+    }
+
+    @Test
+    public void constructor_withXMLReaderAndInputSource() {
+        XMLReader reader = new XMLReaderImpl();
+        InputSource is = new InputSource();
+        source = new SAXSource(reader, is);
+        assertEquals(reader, source.getXMLReader());
+        assertEquals(is, source.getInputSource());
+    }
+
+    @Test
+    public void setInputSource() {
+        InputSource is = new InputSource();
+        source.setInputSource(is);
+        assertEquals(is, source.getInputSource());
+
+        source.setInputSource(null);
+        assertNull(source.getInputSource());
+    }
+
+    @Test
+    public void setXMLReader() {
+        XMLReader reader = new XMLReaderImpl();
+        source.setXMLReader(reader);
+        assertEquals(reader, source.getXMLReader());
+
+        source.setXMLReader(null);
+        assertNull(source.getXMLReader());
+    }
+
+    @Test
+    public void sourceToInputSource() {
+        XMLReader reader = new XMLReaderImpl();
+        InputSource is = new InputSource();
+        source = new SAXSource(reader, is);
+        assertEquals(is, SAXSource.sourceToInputSource(source));
+
+        StreamSource ss = new StreamSource(new StringReader("<tag></tag>"));
+        assertNotNull(SAXSource.sourceToInputSource(ss));
+
+        assertNull(SAXSource.sourceToInputSource(new UnknownSource()));
+        assertNull(SAXSource.sourceToInputSource(null));
+    }
+
+    private static final class UnknownSource implements Source {
+        private String systemId;
+
+        public void setSystemId(String systemId) {
+            this.systemId = systemId;
+        }
+
+        public String getSystemId() {
+            return systemId;
+        }
+    }
+
+    private static final class XMLReaderImpl implements XMLReader {
+
+        @Override
+        public boolean getFeature(String name)
+                throws SAXNotRecognizedException, SAXNotSupportedException { return false; }
+
+        @Override
+        public void setFeature(String name, boolean value)
+                throws SAXNotRecognizedException, SAXNotSupportedException {}
+
+        @Override
+        public Object getProperty(String name)
+                throws SAXNotRecognizedException, SAXNotSupportedException { return null; }
+
+        @Override
+        public void setProperty(String name, Object value)
+                throws SAXNotRecognizedException, SAXNotSupportedException {}
+
+        @Override
+        public void setEntityResolver(EntityResolver resolver) {}
+
+        @Override
+        public EntityResolver getEntityResolver() { return null; }
+
+        @Override
+        public void setDTDHandler(DTDHandler handler) {}
+
+        @Override
+        public DTDHandler getDTDHandler() { return null; }
+
+        @Override
+        public void setContentHandler(ContentHandler handler) {}
+
+        @Override
+        public ContentHandler getContentHandler() { return null; }
+
+        @Override
+        public void setErrorHandler(ErrorHandler handler) {}
+
+        @Override
+        public ErrorHandler getErrorHandler() { return null; }
+
+        @Override
+        public void parse(InputSource input) throws IOException, SAXException {}
+
+        @Override
+        public void parse(String systemId) throws IOException, SAXException {}
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/stream/StreamResultTest.java b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamResultTest.java
new file mode 100644
index 0000000..c4d3be4
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamResultTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 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.javax.xml.transform.stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+
+import javax.xml.transform.stream.StreamResult;
+
+@RunWith(JUnit4.class)
+public class StreamResultTest {
+
+    @Test
+    public void constructor() {
+        StreamResult sr = new StreamResult();
+        assertNull(sr.getOutputStream());
+        assertNull(sr.getSystemId());
+        assertNull(sr.getWriter());
+    }
+
+    @Test
+    public void constructorWithFile() throws IOException {
+        final String PREFIX = "StreamResultTest52";
+        File file = File.createTempFile(PREFIX, null);
+        StreamResult sr = new StreamResult(file);
+        assertNull(sr.getOutputStream());
+        assertTrue(sr.getSystemId().contains(PREFIX));
+        assertNull(sr.getWriter());
+        if (file.exists()) {
+            file.delete();
+        }
+    }
+
+    @Test
+    public void constructorWithOutputStream() {
+        ByteArrayOutputStream os = new ByteArrayOutputStream(16);
+        StreamResult sr = new StreamResult(os);
+        assertEquals(os, sr.getOutputStream());
+        assertNull(sr.getSystemId());
+        assertNull(sr.getWriter());
+    }
+
+    @Test
+    public void constructorWithSystemId() {
+        final String ID = "System74";
+        StreamResult sr = new StreamResult(ID);
+        assertNull(sr.getOutputStream());
+        assertEquals(ID, sr.getSystemId());
+        assertNull(sr.getWriter());
+    }
+
+    @Test
+    public void constructorWithWriter() {
+        StringWriter sw = new StringWriter();
+        StreamResult sr = new StreamResult(sw);
+        assertNull(sr.getOutputStream());
+        assertNull(sr.getSystemId());
+        assertEquals(sw, sr.getWriter());
+    }
+
+    @Test
+    public void setOutputStream() {
+        StreamResult sr = new StreamResult();
+        ByteArrayOutputStream os = new ByteArrayOutputStream(16);
+        sr.setOutputStream(os);
+        assertEquals(os, sr.getOutputStream());
+    }
+
+    @Test
+    public void setSystemIdWithFile() throws IOException {
+        final String PREFIX = "StreamResultTest100";
+        StreamResult sr = new StreamResult();
+        File file = File.createTempFile(PREFIX, null);
+        sr.setSystemId(file);
+        assertTrue(sr.getSystemId().contains(PREFIX));
+        if (file.exists()) {
+            file.delete();
+        }
+    }
+
+    @Test
+    public void setSystemIdWithString() {
+        final String ID = "System112";
+        StreamResult sr = new StreamResult();
+        sr.setSystemId(ID);
+        assertEquals(ID, sr.getSystemId());
+    }
+
+    @Test
+    public void setWriter() {
+        StreamResult sr = new StreamResult();
+        StringWriter sw = new StringWriter();
+        sr.setWriter(sw);
+        assertEquals(sw, sr.getWriter());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/transform/stream/StreamSourceTest.java b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamSourceTest.java
new file mode 100644
index 0000000..58d8155
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/transform/stream/StreamSourceTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 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.javax.xml.transform.stream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamSource;
+
+@RunWith(JUnit4.class)
+public class StreamSourceTest {
+
+  @Test
+  public void constructor() {
+    StreamSource ss = new StreamSource();
+    assertNull(ss.getInputStream());
+    assertNull(ss.getPublicId());
+    assertNull(ss.getReader());
+    assertNull(ss.getSystemId());
+  }
+
+  @Test
+  public void constructorWithFile() throws IOException {
+    final String PREFIX = "StreamSourceTest";
+    File file = File.createTempFile(PREFIX, null);
+    StreamSource ss = new StreamSource(file);
+    assertNull(ss.getInputStream());
+    assertNull(ss.getPublicId());
+    assertNull(ss.getReader());
+    assertTrue("SystemId is " + ss.getSystemId(), ss.getSystemId().contains(PREFIX));
+    if (file.exists()) {
+      file.delete();
+    }
+  }
+
+  @Test
+  public void constructorWithInputStreamAndSystemId() {
+    final String SYSTEM_ID = "System 65";
+    ByteArrayInputStream is = new ByteArrayInputStream(new byte[] { (byte) 0 });
+    StreamSource ss = new StreamSource(is, SYSTEM_ID);
+    assertEquals(is, ss.getInputStream());
+    assertNull(ss.getPublicId());
+    assertNull(ss.getReader());
+    assertEquals(SYSTEM_ID, ss.getSystemId());
+  }
+
+  @Test
+  public void constructorWithSystemId() {
+    final String SYSTEM_ID = "System 76";
+    StreamSource ss = new StreamSource(SYSTEM_ID);
+    assertNull(ss.getInputStream());
+    assertNull(ss.getPublicId());
+    assertNull(ss.getReader());
+    assertEquals(SYSTEM_ID, ss.getSystemId());
+  }
+
+  @Test
+  public void constructorWithReader() {
+    StringReader sr = new StringReader("House");
+    StreamSource ss = new StreamSource(sr);
+    assertNull(ss.getInputStream());
+    assertNull(ss.getPublicId());
+    assertEquals(sr, ss.getReader());
+    assertNull(ss.getSystemId());
+  }
+
+  @Test
+  public void constructorWithReaderAndSystemId() {
+    final String SYSTEM_ID = "System 96";
+    StringReader sr = new StringReader("House");
+    StreamSource ss = new StreamSource(sr, SYSTEM_ID);
+    assertNull(ss.getInputStream());
+    assertNull(ss.getPublicId());
+    assertEquals(sr, ss.getReader());
+    assertEquals(SYSTEM_ID, ss.getSystemId());
+  }
+
+  @Test
+  public void setInputStream() {
+    StreamSource ss = new StreamSource();
+    ByteArrayInputStream is = new ByteArrayInputStream(new byte[] {(byte) 0});
+    ss.setInputStream(is);
+    assertEquals(is, ss.getInputStream());
+  }
+
+  @Test
+  public void setReader() {
+    StreamSource ss = new StreamSource();
+    StringReader sr = new StringReader("Thirteen-twenty-one");
+    ss.setReader(sr);
+    assertEquals(sr, ss.getReader());
+  }
+
+  @Test
+  public void setPublicId() {
+    final String PUBLIC_ID = "Thirteen-twenty-three";
+    StreamSource ss = new StreamSource();
+    ss.setPublicId(PUBLIC_ID);
+    assertEquals(PUBLIC_ID, ss.getPublicId());
+  }
+
+  @Test
+  public void setSystemId() {
+    final String SYSTEM_ID = "Thirteen-twenty-four";
+    StreamSource ss = new StreamSource();
+    ss.setSystemId(SYSTEM_ID);
+    assertEquals(SYSTEM_ID, ss.getSystemId());
+  }
+
+  @Test
+  public void setSystemIdWithFile() throws IOException {
+    final String PREFIX = "StreamSourceTest100";
+    StreamSource ss = new StreamSource();
+    File file = File.createTempFile(PREFIX, null);
+    ss.setSystemId(file);
+    assertTrue(ss.getSystemId().contains(PREFIX));
+    if (file.exists()) {
+      file.delete();
+    }
+  }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/validation/TypeInfoProviderTest.java b/luni/src/test/java/libcore/javax/xml/validation/TypeInfoProviderTest.java
new file mode 100644
index 0000000..619bd68
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/validation/TypeInfoProviderTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 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.javax.xml.validation;
+
+import static org.junit.Assert.assertNull;
+
+import javax.xml.validation.TypeInfoProvider;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.TypeInfo;
+
+@RunWith(JUnit4.class)
+public class TypeInfoProviderTest {
+    @Test
+    public void testConstructor() {
+        TypeInfoProvider p = new TestTypeInfoProvider();
+        assertNull(p.getElementTypeInfo() );
+
+    }
+
+    private static class TestTypeInfoProvider extends TypeInfoProvider {
+
+        @Override
+        public TypeInfo getElementTypeInfo() {
+            return null;
+        }
+
+        @Override
+        public TypeInfo getAttributeTypeInfo(int index) {
+            return null;
+        }
+
+        @Override
+        public boolean isIdAttribute(int index) {
+            return false;
+        }
+
+        @Override
+        public boolean isSpecified(int index) {
+            return false;
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/javax/xml/validation/ValidatorHandlerTest.java b/luni/src/test/java/libcore/javax/xml/validation/ValidatorHandlerTest.java
new file mode 100644
index 0000000..529340e
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/validation/ValidatorHandlerTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.validation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+import javax.xml.validation.TypeInfoProvider;
+import javax.xml.validation.ValidatorHandler;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+
+@RunWith(JUnit4.class)
+public class ValidatorHandlerTest {
+
+    private ValidatorHandler handler;
+
+    @Before
+    public void setUp() {
+        handler = new ValidatorHandlerImpl();
+    }
+
+    @Test
+    public void constructor() {
+        handler = new ValidatorHandlerImpl();
+        assertNotNull(handler);
+    }
+
+    @Test
+    public void getFeature() {
+        assertThrows(NullPointerException.class, () -> handler.getFeature(null));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getFeature("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getFeature(""));
+    }
+
+    @Test
+    public void getProperty() {
+        assertThrows(NullPointerException.class, () -> handler.getProperty(null));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getProperty("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> handler.getProperty(""));
+    }
+
+    @Test
+    public void setFeature() {
+        assertThrows(NullPointerException.class,
+                () -> handler.setFeature(null, false));
+        assertThrows(NullPointerException.class,
+                () -> handler.setFeature(null, true));
+
+        String[] features = {"", "hello", "feature"};
+        boolean[] trueAndFalse = {true, false};
+        for (String feature : features) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> handler.setFeature(feature, value));
+            }
+        }
+    }
+
+    @Test
+    public void setProperty() {
+        assertThrows(NullPointerException.class,
+                () -> handler.setProperty(null, false));
+        assertThrows(NullPointerException.class,
+                () -> handler.setProperty(null, true));
+
+        String[] properties = {"", "hello", "property"};
+        boolean[] trueAndFalse = {true, false};
+        for (String property : properties) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> handler.setProperty(property, value));
+            }
+        }
+    }
+
+    private static final class ValidatorHandlerImpl extends ValidatorHandler {
+
+        @Override
+        public ContentHandler getContentHandler() {
+            return null;
+        }
+
+        @Override
+        public void setContentHandler(ContentHandler receiver) {
+        }
+
+        @Override
+        public ErrorHandler getErrorHandler() {
+            return null;
+        }
+
+        @Override
+        public void setErrorHandler(ErrorHandler errorHandler) {
+        }
+
+        @Override
+        public LSResourceResolver getResourceResolver() {
+            return null;
+        }
+
+        @Override
+        public void setResourceResolver(LSResourceResolver resourceResolver) {
+        }
+
+        @Override
+        public TypeInfoProvider getTypeInfoProvider() {
+            return null;
+        }
+
+        @Override
+        public void setDocumentLocator(Locator locator) {
+        }
+
+        @Override
+        public void startDocument() throws SAXException {
+        }
+
+        @Override
+        public void endDocument() throws SAXException {
+        }
+
+        @Override
+        public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        }
+
+        @Override
+        public void endPrefixMapping(String prefix) throws SAXException {
+        }
+
+        @Override
+        public void startElement(String uri, String localName, String qName, Attributes atts)
+                throws SAXException {
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String qName) throws SAXException {
+        }
+
+        @Override
+        public void characters(char[] ch, int start, int length) throws SAXException {
+        }
+
+        @Override
+        public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+        }
+
+        @Override
+        public void processingInstruction(String target, String data) throws SAXException {
+        }
+
+        @Override
+        public void skippedEntity(String name) throws SAXException {
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/validation/ValidatorTest.java b/luni/src/test/java/libcore/javax/xml/validation/ValidatorTest.java
new file mode 100644
index 0000000..b7ca46a
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/validation/ValidatorTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.validation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+
+import java.io.IOException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.validation.Validator;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+
+@RunWith(JUnit4.class)
+public class ValidatorTest {
+
+    private Validator validator;
+
+    @Before
+    public void setUp() {
+        validator = new ValidatorImpl();
+    }
+
+    @Test
+    public void constructor() {
+        validator = new ValidatorImpl();
+        assertNotNull(validator);
+    }
+
+    @Test
+    public void getFeature() {
+        assertThrows(NullPointerException.class, () -> validator.getFeature(null));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getFeature("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getFeature(""));
+    }
+
+    @Test
+    public void getProperty() {
+        assertThrows(NullPointerException.class, () -> validator.getProperty(null));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getProperty("hello"));
+        assertThrows(SAXNotRecognizedException.class, () -> validator.getProperty(""));
+    }
+
+    @Test
+    public void setFeature() {
+        assertThrows(NullPointerException.class,
+                () -> validator.setFeature(null, false));
+        assertThrows(NullPointerException.class,
+                () -> validator.setFeature(null, true));
+
+        String[] features = {"", "hello", "feature"};
+        boolean[] trueAndFalse = {true, false};
+        for (String feature : features) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> validator.setFeature(feature, value));
+            }
+        }
+    }
+
+    @Test
+    public void setProperty() {
+        assertThrows(NullPointerException.class,
+                () -> validator.setProperty(null, false));
+        assertThrows(NullPointerException.class,
+                () -> validator.setProperty(null, true));
+
+        String[] properties = {"", "hello", "property"};
+        boolean[] trueAndFalse = {true, false};
+        for (String property : properties) {
+            for (boolean value : trueAndFalse) {
+                assertThrows(SAXNotRecognizedException.class,
+                        () -> validator.setProperty(property, value));
+            }
+        }
+    }
+
+    @Test
+    public void validate() throws IOException, SAXException {
+        Source source = new SAXSource();
+        validator.validate(source);
+    }
+
+    private static final class ValidatorImpl extends Validator {
+
+        @Override
+        public void reset() {
+        }
+
+        @Override
+        public void validate(Source source, Result result) throws SAXException, IOException {
+        }
+
+        @Override
+        public ErrorHandler getErrorHandler() {
+            return null;
+        }
+
+        @Override
+        public void setErrorHandler(ErrorHandler errorHandler) {
+        }
+
+        @Override
+        public LSResourceResolver getResourceResolver() {
+            return null;
+        }
+
+        @Override
+        public void setResourceResolver(LSResourceResolver resourceResolver) {
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java
new file mode 100644
index 0000000..79e4707
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathException;
+
+@RunWith(JUnit4.class)
+public class XPathExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathException e = new XPathException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathException e = new XPathException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathExpressionExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathExpressionExceptionTest.java
new file mode 100644
index 0000000..96568e0
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathExpressionExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathExpressionException;
+
+@RunWith(JUnit4.class)
+public class XPathExpressionExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathExpressionException e = new XPathExpressionException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathExpressionException e = new XPathExpressionException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryConfigurationExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryConfigurationExceptionTest.java
new file mode 100644
index 0000000..d0e5c54
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryConfigurationExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathFactoryConfigurationException;
+
+@RunWith(JUnit4.class)
+public class XPathFactoryConfigurationExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathFactoryConfigurationException e = new XPathFactoryConfigurationException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathFactoryConfigurationException e = new XPathFactoryConfigurationException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryTest.java
new file mode 100644
index 0000000..d868eea
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathFactoryTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathFactoryConfigurationException;
+import javax.xml.xpath.XPathFunctionResolver;
+import javax.xml.xpath.XPathVariableResolver;
+
+@RunWith(JUnit4.class)
+public class XPathFactoryTest {
+    public static final String SUPPORTED_URI = "http://a.b.c/d";
+    public static final String UNSUPPORTED_URI = "http://a.b.c/e";
+
+    static public class XPathFactoryForTest extends XPathFactory {
+        public XPathFactoryForTest() {}
+
+        public boolean getFeature(String name) { return true; }
+
+        public boolean isObjectModelSupported(String objectModel) {
+            return objectModel.equals(SUPPORTED_URI);
+        }
+
+        public XPath newXPath() { return null; }
+
+        public void setFeature(String name, boolean value) {}
+
+        public void setXPathFunctionResolver(XPathFunctionResolver resolver) {}
+
+        public void setXPathVariableResolver(XPathVariableResolver resolver) {}
+
+        boolean field = false;
+    }
+
+    @Test
+    public void newInstanceWithUriAndFactoryAndClassLoader() throws Throwable {
+        final ClassLoader classLoader = XPathFactoryForTest.class.getClassLoader();
+        final String factoryName = XPathFactoryForTest.class.getName();
+
+        // Happy path
+        {
+            XPathFactory factory = XPathFactory.newInstance(SUPPORTED_URI,
+                                                            factoryName,
+                                                            classLoader);
+            assertNotNull(factory);
+        }
+
+        // Bad URI
+        try {
+            XPathFactory factory = XPathFactory.newInstance(UNSUPPORTED_URI,
+                                                            factoryName,
+                                                            classLoader);
+            fail("Failed for URI " + UNSUPPORTED_URI);
+        } catch (XPathFactoryConfigurationException e) {
+        }
+
+        // Null URI
+        try {
+            XPathFactory factory = XPathFactory.newInstance(null, factoryName, classLoader);
+            fail("Expected NPE Failed for null URI");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+
+        // Bad factory name
+        try {
+            final String badFactoryName = factoryName + "Bad";
+            XPathFactory factory = XPathFactory.newInstance(SUPPORTED_URI,
+                                                            badFactoryName,
+                                                            classLoader);
+            fail("Failed for " + badFactoryName);
+        } catch (XPathFactoryConfigurationException e) {
+        }
+
+        // Null ClassLoader
+        {
+            XPathFactory factory = XPathFactory.newInstance(SUPPORTED_URI, factoryName, null);
+            assertNotNull(factory);
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/javax/xml/xpath/XPathFunctionExceptionTest.java b/luni/src/test/java/libcore/javax/xml/xpath/XPathFunctionExceptionTest.java
new file mode 100644
index 0000000..2eaac48
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/xml/xpath/XPathFunctionExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.javax.xml.xpath;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import javax.xml.xpath.XPathFunctionException;
+
+@RunWith(JUnit4.class)
+public class XPathFunctionExceptionTest {
+    @Test
+    public void constructorWithString() {
+        XPathFunctionException e = new XPathFunctionException("message");
+        assertEquals("message", e.getMessage());
+        assertNull(e.getCause());
+    }
+
+    @Test
+    public void constructorWithThrowable() {
+        Throwable t = new Throwable();
+        XPathFunctionException e = new XPathFunctionException(t);
+        assertEquals("java.lang.Throwable", e.getMessage());
+        assertEquals(t, e.getCause());
+    }
+}
diff --git a/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java
index da41559..c4fcfa0 100644
--- a/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java
@@ -20,6 +20,7 @@
 import android.icu.util.TimeZone;
 import android.icu.util.ULocale;
 
+import android.icu.util.VersionInfo;
 import java.util.function.BiFunction;
 
 import static android.icu.util.TimeZone.GMT_ZONE;
@@ -36,6 +37,10 @@
 
   // These are the old CTS tests for DateIntervalFormat.formatDateRange.
   public void test_formatDateInterval() throws Exception {
+    // Require min ICU version 70 to provide the expected locale data.
+    if (VersionInfo.ICU_VERSION.getMajor() < 70) {
+      return;
+    }
     TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 
     Calendar c = Calendar.getInstance(tz, ULocale.US);
@@ -97,9 +102,9 @@
     assertEquals("19/1/2009–9/2/2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
 
     assertEquals("19/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + HOUR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
-    assertEquals("19/1/2009–22/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
-    assertEquals("19/1/2009–22/4/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
-    assertEquals("19/1/2009–9/2/2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 22/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 22/4/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 9/2/2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
 
     // These are some random other test cases I came up with.
 
@@ -138,36 +143,36 @@
     // The same tests but for es_US.
 
     assertEquals("19–22 de enero de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, 0));
-    assertEquals("19–22 de ene. de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
-    assertEquals("lun, 19 de ene. – jue, 22 de ene. de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
-    assertEquals("lunes, 19 de enero–jueves, 22 de enero de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
+    assertEquals("19–22 de ene de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("lun, 19 de ene – jue, 22 de ene de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("lunes, 19 de enero – jueves, 22 de enero de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
 
-    assertEquals("19 de enero–22 de abril de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, 0));
-    assertEquals("19 de ene. – 22 de abr. 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
-    assertEquals("lun, 19 de ene. – mié, 22 de abr. de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("19 de enero – 22 de abril de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, 0));
+    assertEquals("19 de ene – 22 de abr 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("lun, 19 de ene – mié, 22 de abr de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
     assertEquals("enero–abril de 2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY));
 
-    assertEquals("19 de ene. de 2009 – 9 de feb. de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
-    assertEquals("ene. de 2009 – feb. de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
-    assertEquals("19 de enero de 2009–9 de febrero de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, 0));
-    assertEquals("lunes, 19 de enero de 2009–jueves, 9 de febrero de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
+    assertEquals("19 de ene de 2009 – 9 de feb de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("ene de 2009 – feb de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+    assertEquals("19 de enero de 2009 – 9 de febrero de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, 0));
+    assertEquals("lunes, 19 de enero de 2009 – jueves, 9 de febrero de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
 
     // The same tests but for es_ES.
 
     assertEquals("19–22 de enero de 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, 0));
     assertEquals("19–22 ene 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
     assertEquals("lun, 19 ene – jue, 22 ene 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
-    assertEquals("lunes, 19 de enero–jueves, 22 de enero de 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
+    assertEquals("lunes, 19 de enero – jueves, 22 de enero de 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
 
-    assertEquals("19 de enero–22 de abril de 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, 0));
+    assertEquals("19 de enero – 22 de abril de 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, 0));
     assertEquals("19 ene – 22 abr 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
     assertEquals("lun, 19 ene – mié, 22 abr 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
     assertEquals("enero–abril de 2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY));
 
     assertEquals("19 ene 2009 – 9 feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
     assertEquals("ene 2009 – feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
-    assertEquals("19 de enero de 2009–9 de febrero de 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, 0));
-    assertEquals("lunes, 19 de enero de 2009–jueves, 9 de febrero de 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
+    assertEquals("19 de enero de 2009 – 9 de febrero de 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, 0));
+    assertEquals("lunes, 19 de enero de 2009 – jueves, 9 de febrero de 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
   }
 
   // http://b/8862241 - we should be able to format dates past 2038.
diff --git a/luni/src/test/java/libcore/libcore/icu/DecimalFormatDataTest.java b/luni/src/test/java/libcore/libcore/icu/DecimalFormatDataTest.java
new file mode 100644
index 0000000..1e3edf0
--- /dev/null
+++ b/luni/src/test/java/libcore/libcore/icu/DecimalFormatDataTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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 libcore.libcore.icu;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Locale;
+import libcore.icu.DecimalFormatData;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DecimalFormatDataTest {
+
+    // http://code.google.com/p/android/issues/detail?id=38844
+    @Test
+    public void testDecimalFormatSymbols_es() {
+        DecimalFormatData es = DecimalFormatData.getInstance(new Locale("es"));
+        assertEquals(',', es.getDecimalSeparator());
+        assertEquals('.', es.getGroupingSeparator());
+
+        DecimalFormatData es_419 = DecimalFormatData.getInstance(new Locale("es", "419"));
+        assertEquals('.', es_419.getDecimalSeparator());
+        assertEquals(',', es_419.getGroupingSeparator());
+
+        DecimalFormatData es_US = DecimalFormatData.getInstance(new Locale("es", "US"));
+        assertEquals('.', es_US.getDecimalSeparator());
+        assertEquals(',', es_US.getGroupingSeparator());
+
+        DecimalFormatData es_MX = DecimalFormatData.getInstance(new Locale("es", "MX"));
+        assertEquals('.', es_MX.getDecimalSeparator());
+        assertEquals(',', es_MX.getGroupingSeparator());
+
+        DecimalFormatData es_AR = DecimalFormatData.getInstance(new Locale("es", "AR"));
+        assertEquals(',', es_AR.getDecimalSeparator());
+        assertEquals('.', es_AR.getGroupingSeparator());
+    }
+}
diff --git a/luni/src/test/java/libcore/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/libcore/icu/ICUTest.java
index a5577a5..ba09855 100644
--- a/luni/src/test/java/libcore/libcore/icu/ICUTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/ICUTest.java
@@ -250,12 +250,11 @@
     assertTransformIcuDateTimePattern("b H:mm", "H:mm");
     assertTransformIcuDateTimePattern("B H:mm:ss, E", "H:mm:ss, E");
 
-    // Examples with no effect
-    assertTransformIcuDateTimePattern("hh:mm b", "hh:mm b"); // No change for 12-hour format
-    assertTransformIcuDateTimePattern("hh:mm B", "hh:mm B"); // No change for 12-hour format
-    assertTransformIcuDateTimePattern("B h:mm:ss, E", "B h:mm:ss, E");
-    // No change when no hour is specified
-    assertTransformIcuDateTimePattern("dd-MM-yy B", "dd-MM-yy B");
+    // Examples with 'h' 12-hour format
+    assertTransformIcuDateTimePattern("hh:mm a", "hh:mm a");
+    assertTransformIcuDateTimePattern("hh:mm a", "hh:mm a");
+    assertTransformIcuDateTimePattern("a h:mm:ss, E", "a h:mm:ss, E");
+    assertTransformIcuDateTimePattern("dd-MM-yy a", "dd-MM-yy a");
   }
 
   private static void assertTransformIcuDateTimePattern(String input, String expectedOutput) {
diff --git a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
index b524483..9b7ecae 100644
--- a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
@@ -18,12 +18,10 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 
 import android.icu.text.DateTimePatternGenerator;
 
-import java.text.DateFormat;
+import android.icu.util.VersionInfo;
 import java.text.DateFormatSymbols;
 import java.text.DecimalFormatSymbols;
 import java.text.SimpleDateFormat;
@@ -32,9 +30,11 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
+import libcore.icu.DecimalFormatData;
 import libcore.icu.LocaleData;
 import libcore.junit.util.SwitchTargetSdkVersionRule;
 
+import org.junit.Assume;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestRule;
@@ -87,11 +87,12 @@
 
   @Test
   public void test_ru_RU() throws Exception {
+    Assume.assumeTrue("Require min ICU version 70", VersionInfo.ICU_VERSION.getMajor() >= 70);
     LocaleData l = LocaleData.get(new Locale("ru", "RU"));
 
     assertEquals("воскресенье", l.longWeekdayNames[1]);
     assertEquals("вс", l.shortWeekdayNames[1]);
-    assertEquals("вс", l.tinyWeekdayNames[1]);
+    assertEquals("В", l.tinyWeekdayNames[1]);
 
     // Russian stand-alone weekday names have no initial capital since CLDR 28/ICU 56.
     assertEquals("воскресенье", l.longStandAloneWeekdayNames[1]);
@@ -99,58 +100,6 @@
     assertEquals("В", l.tinyStandAloneWeekdayNames[1]);
   }
 
-  // http://code.google.com/p/android/issues/detail?id=38844
-  @Test
-  public void testDecimalFormatSymbols_es() throws Exception {
-    LocaleData es = LocaleData.get(new Locale("es"));
-    assertEquals(',', es.decimalSeparator);
-    assertEquals('.', es.groupingSeparator);
-
-    LocaleData es_419 = LocaleData.get(new Locale("es", "419"));
-    assertEquals('.', es_419.decimalSeparator);
-    assertEquals(',', es_419.groupingSeparator);
-
-    LocaleData es_US = LocaleData.get(new Locale("es", "US"));
-    assertEquals('.', es_US.decimalSeparator);
-    assertEquals(',', es_US.groupingSeparator);
-
-    LocaleData es_MX = LocaleData.get(new Locale("es", "MX"));
-    assertEquals('.', es_MX.decimalSeparator);
-    assertEquals(',', es_MX.groupingSeparator);
-
-    LocaleData es_AR = LocaleData.get(new Locale("es", "AR"));
-    assertEquals(',', es_AR.decimalSeparator);
-    assertEquals('.', es_AR.groupingSeparator);
-  }
-
-  // http://b/7924970
-  @Test
-  public void testTimeFormat12And24() {
-    Boolean originalSetting = DateFormat.is24Hour;
-    try {
-      LocaleData en_US = LocaleData.get(Locale.US);
-      DateFormat.is24Hour = false;
-      assertEquals("h:mm a", en_US.getTimeFormat(DateFormat.SHORT));
-      DateFormat.is24Hour = true;
-      assertEquals("HH:mm", en_US.getTimeFormat(DateFormat.SHORT));
-
-      LocaleData ja_JP = LocaleData.get(Locale.JAPAN);
-      DateFormat.is24Hour = false;
-      assertEquals("aK:mm", ja_JP.getTimeFormat(DateFormat.SHORT));
-      DateFormat.is24Hour = true;
-      assertEquals("H:mm", ja_JP.getTimeFormat(DateFormat.SHORT));
-    } finally {
-      DateFormat.is24Hour = originalSetting;
-    }
-  }
-
-  // http://b/26397197
-  @Test
-  public void testPatternWithOverride() throws Exception {
-    LocaleData haw = LocaleData.get(new Locale("haw"));
-    assertFalse(haw.shortDateFormat.isEmpty());
-  }
-
   /**
    * Check that LocaleData.get() does not throw when the input locale is invalid.
    * http://b/129070579
@@ -193,6 +142,7 @@
 
   private static void assertRootDataEqualsToTargetLocaleData(Locale targetLocale) {
     LocaleData localeData = LocaleData.get(Locale.ROOT);
+    DecimalFormatData decimalFormatData = DecimalFormatData.getInstance(Locale.ROOT);
     Calendar calendar = Calendar.getInstance(Locale.ROOT);
     android.icu.util.Calendar icuCalendar = android.icu.util.Calendar.getInstance(targetLocale);
     DateFormatSymbols dateFormatSymbols = DateFormatSymbols.getInstance(Locale.ROOT);
@@ -238,7 +188,7 @@
 
     // ICU DecimalFormatSymbols has data slightly different from LocaleData, but infinity is known
     // to be the same, but caused the bug b/68318492 in old Android version.
-    assertEquals(localeData.infinity, icuDecimalFormatSymbols.getInfinity());
+    assertEquals(decimalFormatData.getInfinity(), icuDecimalFormatSymbols.getInfinity());
     assertEquals(decimalFormatSymbols.getInfinity(), icuDecimalFormatSymbols.getInfinity());
 
     // Explicitly test Calendar and DateFormatSymbols here because they are known to
diff --git a/luni/src/test/java/libcore/libcore/icu/SimpleDateFormatDataTest.java b/luni/src/test/java/libcore/libcore/icu/SimpleDateFormatDataTest.java
new file mode 100644
index 0000000..ec5059e
--- /dev/null
+++ b/luni/src/test/java/libcore/libcore/icu/SimpleDateFormatDataTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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 libcore.libcore.icu;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.text.DateFormat;
+import java.util.Locale;
+import libcore.icu.LocaleData;
+import libcore.icu.SimpleDateFormatData;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SimpleDateFormatDataTest {
+
+    // http://b/7924970
+    @Test
+    public void testTimeFormat12And24() {
+        Boolean originalSetting = DateFormat.is24Hour;
+        try {
+            SimpleDateFormatData en_US = SimpleDateFormatData.getInstance(Locale.US);
+            DateFormat.is24Hour = false;
+            assertEquals("h:mm a", en_US.getTimeFormat(DateFormat.SHORT));
+            DateFormat.is24Hour = true;
+            assertEquals("HH:mm", en_US.getTimeFormat(DateFormat.SHORT));
+
+            SimpleDateFormatData ja_JP = SimpleDateFormatData.getInstance(Locale.JAPAN);
+            DateFormat.is24Hour = false;
+            assertEquals("aK:mm", ja_JP.getTimeFormat(DateFormat.SHORT));
+            DateFormat.is24Hour = true;
+            assertEquals("H:mm", ja_JP.getTimeFormat(DateFormat.SHORT));
+        } finally {
+            DateFormat.is24Hour = originalSetting;
+        }
+    }
+
+    // http://b/26397197
+    @Test
+    public void testPatternWithOverride() throws Exception {
+        SimpleDateFormatData haw = SimpleDateFormatData.getInstance(new Locale("haw"));
+        assertFalse(haw.getDateFormat(DateFormat.SHORT).isEmpty());
+    }
+
+}
diff --git a/luni/src/test/java/libcore/libcore/io/MemoryTest.java b/luni/src/test/java/libcore/libcore/io/MemoryTest.java
index 80ff4ea..4047e3c 100644
--- a/luni/src/test/java/libcore/libcore/io/MemoryTest.java
+++ b/luni/src/test/java/libcore/libcore/io/MemoryTest.java
@@ -143,4 +143,54 @@
             assertEquals(expectedValues[i], Memory.peekShort(ptr + Short.BYTES * i, swap));
         }
     }
+
+    public void testMemmove() {
+        final int size = 100;
+        checkPartialMemmove(size, 0, 0, size);
+        checkPartialMemmove(size, 0, 0, size / 2);
+        checkPartialMemmove(size, size / 2, size / 2, size - size / 2);
+        checkPartialMemmove(size, 10, 20, 20);
+
+        checkOverlappingMemmove(size, 0, 0, size);
+        checkOverlappingMemmove(size, 10, 20, 30);
+        checkOverlappingMemmove(size, 20, 10, 30);
+    }
+
+    private void checkPartialMemmove(int size, int offsetDst, int offsetSrc, int count) {
+        byte[] src = new byte[size];
+        for (int i = 0; i < size; ++i) {
+            src[i] = (byte)i;
+        }
+        byte[] dst = new byte[size];
+        Arrays.fill(dst, (byte)-1);
+
+        assertTrue(offsetSrc + count <= size);
+        assertTrue(offsetDst + count <= size);
+        Memory.memmove(dst, offsetDst, src, offsetSrc, count);
+        for (int i = 0; i < size; ++i) {
+            if (i >= offsetDst && i < offsetDst + count) {
+                assertEquals(src[i + (offsetSrc - offsetDst)], dst[i]);
+            } else {
+                assertEquals((byte)-1, dst[i]);
+            }
+        }
+    }
+
+    private void checkOverlappingMemmove(int size, int offsetDst, int offsetSrc, int count) {
+        byte[] buf = new byte[size];
+        for (int i = 0; i < size; ++i) {
+            buf[i] = (byte)i;
+        }
+
+        assertTrue(offsetSrc + count <= size);
+        assertTrue(offsetDst + count <= size);
+        Memory.memmove(buf, offsetDst, buf, offsetSrc, count);
+        for (int i = 0; i < size; ++i) {
+            if (i >= offsetDst && i < offsetDst + count) {
+                assertEquals(i + (offsetSrc - offsetDst), buf[i]);
+            } else {
+                assertEquals((byte)i, buf[i]);
+            }
+        }
+    }
 }
diff --git a/luni/src/test/java/libcore/libcore/io/StreamsTest.java b/luni/src/test/java/libcore/libcore/io/StreamsTest.java
new file mode 100644
index 0000000..2b0e627
--- /dev/null
+++ b/luni/src/test/java/libcore/libcore/io/StreamsTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 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.libcore.io;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+import libcore.io.Streams;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class StreamsTest {
+
+    @Test
+    public void testReadFully() throws Exception {
+        final byte[] bytes = "0123456789".getBytes();
+        ByteArrayInputStream inStream = new ByteArrayInputStream(bytes);
+        byte[] dst = new byte[bytes.length - 1];
+
+        Arrays.fill(dst, (byte)-1);
+        Streams.readFully(inStream, dst);
+        for (int i = 0; i < dst.length; ++i) {
+            assertEquals(bytes[i], dst[i]);
+        }
+    }
+}
diff --git a/luni/src/test/java/libcore/sun/misc/UnsafeTest.java b/luni/src/test/java/libcore/sun/misc/UnsafeTest.java
index 483398b..994f6bb 100644
--- a/luni/src/test/java/libcore/sun/misc/UnsafeTest.java
+++ b/luni/src/test/java/libcore/sun/misc/UnsafeTest.java
@@ -16,6 +16,8 @@
 
 package libcore.sun.misc;
 
+import static org.junit.Assert.assertEquals;
+
 import junit.framework.TestCase;
 
 import java.lang.reflect.Field;
@@ -72,4 +74,230 @@
         assertEquals(null, i.s);
         assertEquals(i, i.getThis());
     }
+
+    public void test_copyMemory() throws Exception {
+        Unsafe unsafe = getUnsafe();
+
+        // Source buffer.
+        byte[] msg = "All your base are belong to us.".getBytes();
+        long srcBuf = unsafe.allocateMemory(msg.length);
+        {
+            long srcPtr = srcBuf;
+            for (byte b : msg){
+                unsafe.putByte(srcPtr++, b);
+            }
+        }
+
+        // Destination buffer.
+        long dstBuf = getUnsafe().allocateMemory(msg.length);
+        unsafe.copyMemory(srcBuf, dstBuf, msg.length);
+
+        // Compare buffers.
+        long srcPtr = srcBuf;
+        long dstPtr = dstBuf;
+        for (int i = 0; i < msg.length; ++i) {
+            byte srcByte = unsafe.getByte(srcPtr++);
+            byte dstByte = unsafe.getByte(dstPtr++);
+            assertEquals(String.format("Content mismatch at offset %d: src = '%c', dst = '%c'",
+                            i, srcByte, dstByte),
+                    srcByte, dstByte);
+        }
+
+        // Clean up.
+        unsafe.freeMemory(dstBuf);
+        unsafe.freeMemory(srcBuf);
+    }
+
+    private class TestFixture {
+        public boolean booleanVar = true;
+        public byte byteVar = 42;
+        public int intVar = 2046;
+        public long longVar = 123456789;
+        public float floatVar = 1.618f;
+        public double doubleVar = 3.141;
+        public Object objectVar = new Object();
+    }
+
+    public void test_getBoolean_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field booleanField = TestFixture.class.getDeclaredField("booleanVar");
+        long booleanFieldOffset = unsafe.objectFieldOffset(booleanField);
+        boolean booleanValue = unsafe.getBoolean(tf, booleanFieldOffset);
+        assertEquals(tf.booleanVar, booleanValue);
+    }
+
+    public void test_getByte_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field byteField = TestFixture.class.getDeclaredField("byteVar");
+        long byteFieldOffset = unsafe.objectFieldOffset(byteField);
+        byte byteValue = unsafe.getByte(tf, byteFieldOffset);
+        assertEquals(tf.byteVar, byteValue);
+    }
+
+    public void test_getInt_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field intField = TestFixture.class.getDeclaredField("intVar");
+        long intFieldOffset = unsafe.objectFieldOffset(intField);
+        int intValue = unsafe.getInt(tf, intFieldOffset);
+        assertEquals(tf.intVar, intValue);
+    }
+
+    public void test_getLong_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field longField = TestFixture.class.getDeclaredField("longVar");
+        long longFieldOffset = unsafe.objectFieldOffset(longField);
+        long longValue = unsafe.getLong(tf, longFieldOffset);
+        assertEquals(tf.longVar, longValue);
+    }
+
+    public void test_getFloat_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field floatField = TestFixture.class.getDeclaredField("floatVar");
+        long floatFieldOffset = unsafe.objectFieldOffset(floatField);
+        float floatValue = unsafe.getFloat(tf, floatFieldOffset);
+        assertEquals(tf.floatVar, floatValue);
+    }
+
+    public void test_getDouble_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field doubleField = TestFixture.class.getDeclaredField("doubleVar");
+        long doubleFieldOffset = unsafe.objectFieldOffset(doubleField);
+        double doubleValue = unsafe.getDouble(tf, doubleFieldOffset);
+        assertEquals(tf.doubleVar, doubleValue);
+    }
+
+    public void test_getObject_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field objectField = TestFixture.class.getDeclaredField("objectVar");
+        long objectFieldOffset = unsafe.objectFieldOffset(objectField);
+        Object objectValue = unsafe.getObject(tf, objectFieldOffset);
+        assertEquals(tf.objectVar, objectValue);
+    }
+
+    public void test_putBoolean_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field booleanField = TestFixture.class.getDeclaredField("booleanVar");
+        long booleanFieldOffset = unsafe.objectFieldOffset(booleanField);
+        boolean booleanValue = false;
+        unsafe.putBoolean(tf, booleanFieldOffset, booleanValue);
+        assertEquals(booleanValue, tf.booleanVar);
+    }
+
+    public void test_putByte_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field byteField = TestFixture.class.getDeclaredField("byteVar");
+        long byteFieldOffset = unsafe.objectFieldOffset(byteField);
+        byte byteValue = 83;
+        unsafe.putByte(tf, byteFieldOffset, byteValue);
+        assertEquals(byteValue, tf.byteVar);
+    }
+
+    public void test_putInt_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field intField = TestFixture.class.getDeclaredField("intVar");
+        long intFieldOffset = unsafe.objectFieldOffset(intField);
+        int intValue = 3000;
+        unsafe.putInt(tf, intFieldOffset, intValue);
+        assertEquals(intValue, tf.intVar);
+    }
+
+    public void test_putLong_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field longField = TestFixture.class.getDeclaredField("longVar");
+        long longFieldOffset = unsafe.objectFieldOffset(longField);
+        long longValue = 9000;
+        unsafe.putLong(tf, longFieldOffset, longValue);
+        assertEquals(longValue, tf.longVar);
+    }
+
+    public void test_putFloat_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field floatField = TestFixture.class.getDeclaredField("floatVar");
+        long floatFieldOffset = unsafe.objectFieldOffset(floatField);
+        float floatValue = 0.987f;
+        unsafe.putFloat(tf, floatFieldOffset, floatValue);
+        assertEquals(floatValue, tf.floatVar);
+    }
+
+    public void test_putDouble_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field doubleField = TestFixture.class.getDeclaredField("doubleVar");
+        long doubleFieldOffset = unsafe.objectFieldOffset(doubleField);
+        double doubleValue = 0.123;
+        unsafe.putDouble(tf, doubleFieldOffset, doubleValue);
+        assertEquals(doubleValue, tf.doubleVar);
+    }
+
+    public void test_putObject_Relative() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        TestFixture tf = new TestFixture();
+        Field objectField = TestFixture.class.getDeclaredField("objectVar");
+        long objectFieldOffset = unsafe.objectFieldOffset(objectField);
+        Object objectValue = new Object();
+        unsafe.putObject(tf, objectFieldOffset, objectValue);
+        assertEquals(objectValue, tf.objectVar);
+    }
+
+    public void test_putByte_getByte_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Byte.BYTES);
+        byte byteValue1 = 51;
+        unsafe.putByte(buffer, byteValue1);
+        byte byteValue2 = unsafe.getByte(buffer);
+        assertEquals(byteValue2, byteValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putInt_getInt_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Integer.BYTES);
+        int intValue1 = 2047;
+        unsafe.putInt(buffer, intValue1);
+        int intValue2 = unsafe.getInt(buffer);
+        assertEquals(intValue2, intValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putLong_getLong_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Long.BYTES);
+        long longValue1 = 987654321;
+        unsafe.putLong(buffer, longValue1);
+        long longValue2 = unsafe.getLong(buffer);
+        assertEquals(longValue2, longValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putFloat_getFloat_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Float.BYTES);
+        float floatValue1 = 2.718f;
+        unsafe.putFloat(buffer, floatValue1);
+        float floatValue2 = unsafe.getFloat(buffer);
+        assertEquals(floatValue2, floatValue1);
+        unsafe.freeMemory(buffer);
+    }
+
+    public void test_putDouble_getDouble_Absolute() throws Exception {
+        Unsafe unsafe = getUnsafe();
+        long buffer = unsafe.allocateMemory(Double.BYTES);
+        double doubleValue1 = 6.283;
+        unsafe.putDouble(buffer, doubleValue1);
+        double doubleValue2 = unsafe.getDouble(buffer);
+        assertEquals(doubleValue2, doubleValue1);
+        unsafe.freeMemory(buffer);
+    }
 }
diff --git a/luni/src/test/java/libcore/sun/security/jca/ProvidersTest.java b/luni/src/test/java/libcore/sun/security/jca/ProvidersTest.java
deleted file mode 100644
index 45c857f..0000000
--- a/luni/src/test/java/libcore/sun/security/jca/ProvidersTest.java
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sun.security.jca;
-
-import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import dalvik.system.VMRuntime;
-
-import java.lang.reflect.Method;
-import java.security.AlgorithmParameters;
-import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
-import java.security.KeyPairGenerator;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Provider;
-import java.security.Security;
-import java.security.Signature;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-import javax.crypto.Cipher;
-import javax.crypto.KeyAgreement;
-import javax.crypto.KeyGenerator;
-import javax.crypto.Mac;
-import javax.crypto.SecretKeyFactory;
-
-import sun.security.jca.Providers;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-/**
- * Tests that the deprecation of algorithms from the BC provider works as expected.  Requests
- * from an application targeting an API level before the deprecation should receive them,
- * but those targeting an API level after the deprecation should cause an exception.  Tests
- * a representative sample of services and algorithms and various ways of naming them.
- */
-@RunWith(JUnit4.class)
-public class ProvidersTest {
-
-    /**
-     * An object that can be called to call an appropriate getInstance method.  Since
-     * each type of object has its own class that the method should be called on,
-     * it's either this or reflection, and this seems more straightforward.
-     */
-    private interface Algorithm {
-        Object getInstance() throws GeneralSecurityException;
-    }
-
-    // getInstance calls that result in requests to BC
-    private static final List<Algorithm> BC_ALGORITHMS = new ArrayList<>();
-    // getInstance calls that result in requests to Conscrypt
-    private static final List<Algorithm> CONSCRYPT_ALGORITHMS = new ArrayList<>();
-    static {
-        // All the same algorithms as for BC, but with no provider, which should produce
-        // the Conscrypt implementation
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                return Signature.getInstance("sha224withrsa");
-            }
-        });
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                return KeyFactory.getInstance("EC");
-            }
-        });
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                return Signature.getInstance("MD5withRSAEncryption");
-            }
-        });
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                return KeyGenerator.getInstance("HMAC-MD5");
-            }
-        });
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                return Mac.getInstance("Hmac/sha256");
-            }
-        });
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                return Signature.getInstance("SHA384/rsA");
-            }
-        });
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                // OID for SHA-256
-                return MessageDigest.getInstance("2.16.840.1.101.3.4.2.1");
-            }
-        });
-        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
-            @Override
-            public Object getInstance() throws GeneralSecurityException {
-                // OID for AES-128
-                return AlgorithmParameters.getInstance("2.16.840.1.101.3.4.1.2");
-            }
-        });
-    }
-
-    private static final Set<String> REMOVED_BC_ALGORITHMS = new HashSet<String>();
-    static {
-        REMOVED_BC_ALGORITHMS.addAll(Arrays.asList(
-                "ALGORITHMPARAMETERS.1.2.840.113549.3.7",
-                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.2",
-                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.22",
-                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.26",
-                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.42",
-                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.46",
-                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.6",
-                "ALGORITHMPARAMETERS.AES",
-                "ALGORITHMPARAMETERS.DESEDE",
-                "ALGORITHMPARAMETERS.EC",
-                "ALGORITHMPARAMETERS.GCM",
-                "ALGORITHMPARAMETERS.OAEP",
-                "ALGORITHMPARAMETERS.TDEA",
-                "CERTIFICATEFACTORY.X.509",
-                "CERTIFICATEFACTORY.X509",
-                // List of Ciphers produced by ProviderOverlap:
-                "CIPHER.1.2.840.113549.3.4",
-                "CIPHER.2.16.840.1.101.3.4.1.26",
-                "CIPHER.2.16.840.1.101.3.4.1.46",
-                "CIPHER.2.16.840.1.101.3.4.1.6",
-                "CIPHER.AES/GCM/NOPADDING",
-                "CIPHER.ARC4",
-                "CIPHER.ARCFOUR",
-                "CIPHER.OID.1.2.840.113549.3.4",
-                "CIPHER.RC4",
-                // End of Ciphers produced by ProviderOverlap
-                // Additional ciphers transformations that will resolve to the same things as
-                // the automatically-produced overlap due to the Cipher transformation rules.
-                // These have been added manually.
-                "CIPHER.ARC4/ECB/NOPADDING",
-                "CIPHER.ARC4/NONE/NOPADDING",
-                "CIPHER.ARCFOUR/ECB/NOPADDING",
-                "CIPHER.ARCFOUR/NONE/NOPADDING",
-                "CIPHER.RC4/ECB/NOPADDING",
-                "CIPHER.RC4/NONE/NOPADDING",
-                // End of additional Ciphers
-                "KEYAGREEMENT.ECDH",
-                "KEYFACTORY.1.2.840.10045.2.1",
-                "KEYFACTORY.1.2.840.113549.1.1.1",
-                "KEYFACTORY.1.2.840.113549.1.1.7",
-                "KEYFACTORY.1.3.133.16.840.63.0.2",
-                "KEYFACTORY.2.5.8.1.1",
-                "KEYFACTORY.EC",
-                "KEYGENERATOR.1.2.840.113549.2.10",
-                "KEYGENERATOR.1.2.840.113549.2.11",
-                "KEYGENERATOR.1.2.840.113549.2.7",
-                "KEYGENERATOR.1.2.840.113549.2.8",
-                "KEYGENERATOR.1.2.840.113549.2.9",
-                "KEYGENERATOR.1.3.6.1.5.5.8.1.1",
-                "KEYGENERATOR.1.3.6.1.5.5.8.1.2",
-                "KEYGENERATOR.2.16.840.1.101.3.4.2.1",
-                "KEYGENERATOR.AES",
-                "KEYGENERATOR.DESEDE",
-                "KEYGENERATOR.HMAC-MD5",
-                "KEYGENERATOR.HMAC-SHA1",
-                "KEYGENERATOR.HMAC-SHA224",
-                "KEYGENERATOR.HMAC-SHA256",
-                "KEYGENERATOR.HMAC-SHA384",
-                "KEYGENERATOR.HMAC-SHA512",
-                "KEYGENERATOR.HMAC/MD5",
-                "KEYGENERATOR.HMAC/SHA1",
-                "KEYGENERATOR.HMAC/SHA224",
-                "KEYGENERATOR.HMAC/SHA256",
-                "KEYGENERATOR.HMAC/SHA384",
-                "KEYGENERATOR.HMAC/SHA512",
-                "KEYGENERATOR.HMACMD5",
-                "KEYGENERATOR.HMACSHA1",
-                "KEYGENERATOR.HMACSHA224",
-                "KEYGENERATOR.HMACSHA256",
-                "KEYGENERATOR.HMACSHA384",
-                "KEYGENERATOR.HMACSHA512",
-                "KEYGENERATOR.TDEA",
-                "KEYPAIRGENERATOR.1.2.840.10045.2.1",
-                "KEYPAIRGENERATOR.1.2.840.113549.1.1.1",
-                "KEYPAIRGENERATOR.1.2.840.113549.1.1.7",
-                "KEYPAIRGENERATOR.1.3.133.16.840.63.0.2",
-                "KEYPAIRGENERATOR.2.5.8.1.1",
-                "KEYPAIRGENERATOR.EC",
-                "KEYPAIRGENERATOR.RSA",
-                "MAC.1.2.840.113549.2.10",
-                "MAC.1.2.840.113549.2.11",
-                "MAC.1.2.840.113549.2.7",
-                "MAC.1.2.840.113549.2.8",
-                "MAC.1.2.840.113549.2.9",
-                "MAC.1.3.6.1.5.5.8.1.1",
-                "MAC.1.3.6.1.5.5.8.1.2",
-                "MAC.2.16.840.1.101.3.4.2.1",
-                "MAC.HMAC-MD5",
-                "MAC.HMAC-SHA1",
-                "MAC.HMAC-SHA224",
-                "MAC.HMAC-SHA256",
-                "MAC.HMAC-SHA384",
-                "MAC.HMAC-SHA512",
-                "MAC.HMAC/MD5",
-                "MAC.HMAC/SHA1",
-                "MAC.HMAC/SHA224",
-                "MAC.HMAC/SHA256",
-                "MAC.HMAC/SHA384",
-                "MAC.HMAC/SHA512",
-                "MAC.HMACMD5",
-                "MAC.HMACSHA1",
-                "MAC.HMACSHA224",
-                "MAC.HMACSHA256",
-                "MAC.HMACSHA384",
-                "MAC.HMACSHA512",
-                "MAC.PBEWITHHMACSHA224",
-                "MAC.PBEWITHHMACSHA256",
-                "MAC.PBEWITHHMACSHA384",
-                "MAC.PBEWITHHMACSHA512",
-                "MESSAGEDIGEST.1.2.840.113549.2.5",
-                "MESSAGEDIGEST.1.3.14.3.2.26",
-                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.1",
-                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.2",
-                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.3",
-                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.4",
-                "MESSAGEDIGEST.MD5",
-                "MESSAGEDIGEST.SHA",
-                "MESSAGEDIGEST.SHA-1",
-                "MESSAGEDIGEST.SHA-224",
-                "MESSAGEDIGEST.SHA-256",
-                "MESSAGEDIGEST.SHA-384",
-                "MESSAGEDIGEST.SHA-512",
-                "MESSAGEDIGEST.SHA1",
-                "MESSAGEDIGEST.SHA224",
-                "MESSAGEDIGEST.SHA256",
-                "MESSAGEDIGEST.SHA384",
-                "MESSAGEDIGEST.SHA512",
-                "SECRETKEYFACTORY.DESEDE",
-                "SECRETKEYFACTORY.TDEA",
-                "SIGNATURE.1.2.840.10045.4.1",
-                "SIGNATURE.1.2.840.10045.4.3.1",
-                "SIGNATURE.1.2.840.10045.4.3.2",
-                "SIGNATURE.1.2.840.10045.4.3.3",
-                "SIGNATURE.1.2.840.10045.4.3.4",
-                "SIGNATURE.1.2.840.113549.1.1.11",
-                "SIGNATURE.1.2.840.113549.1.1.12",
-                "SIGNATURE.1.2.840.113549.1.1.13",
-                "SIGNATURE.1.2.840.113549.1.1.14",
-                "SIGNATURE.1.2.840.113549.1.1.4",
-                "SIGNATURE.1.2.840.113549.1.1.5",
-                "SIGNATURE.1.3.14.3.2.29",
-                "SIGNATURE.ECDSA",
-                "SIGNATURE.ECDSAWITHSHA1",
-                "SIGNATURE.MD5/RSA",
-                "SIGNATURE.MD5WITHRSA",
-                "SIGNATURE.MD5WITHRSAENCRYPTION",
-                "SIGNATURE.NONEWITHECDSA",
-                "SIGNATURE.OID.1.2.840.10045.4.3.1",
-                "SIGNATURE.OID.1.2.840.10045.4.3.2",
-                "SIGNATURE.OID.1.2.840.10045.4.3.3",
-                "SIGNATURE.OID.1.2.840.10045.4.3.4",
-                "SIGNATURE.OID.1.2.840.113549.1.1.11",
-                "SIGNATURE.OID.1.2.840.113549.1.1.12",
-                "SIGNATURE.OID.1.2.840.113549.1.1.13",
-                "SIGNATURE.OID.1.2.840.113549.1.1.14",
-                "SIGNATURE.OID.1.2.840.113549.1.1.4",
-                "SIGNATURE.OID.1.2.840.113549.1.1.5",
-                "SIGNATURE.OID.1.3.14.3.2.29",
-                "SIGNATURE.SHA1/RSA",
-                "SIGNATURE.SHA1WITHECDSA",
-                "SIGNATURE.SHA1WITHRSA",
-                "SIGNATURE.SHA1WITHRSAENCRYPTION",
-                "SIGNATURE.SHA224/ECDSA",
-                "SIGNATURE.SHA224/RSA",
-                "SIGNATURE.SHA224WITHECDSA",
-                "SIGNATURE.SHA224WITHRSA",
-                "SIGNATURE.SHA224WITHRSAENCRYPTION",
-                "SIGNATURE.SHA256/ECDSA",
-                "SIGNATURE.SHA256/RSA",
-                "SIGNATURE.SHA256WITHECDSA",
-                "SIGNATURE.SHA256WITHRSA",
-                "SIGNATURE.SHA256WITHRSAENCRYPTION",
-                "SIGNATURE.SHA384/ECDSA",
-                "SIGNATURE.SHA384/RSA",
-                "SIGNATURE.SHA384WITHECDSA",
-                "SIGNATURE.SHA384WITHRSA",
-                "SIGNATURE.SHA384WITHRSAENCRYPTION",
-                "SIGNATURE.SHA512/ECDSA",
-                "SIGNATURE.SHA512/RSA",
-                "SIGNATURE.SHA512WITHECDSA",
-                "SIGNATURE.SHA512WITHRSA",
-                "SIGNATURE.SHA512WITHRSAENCRYPTION"
-        ));
-    }
-
-    private static Provider getProvider(Object object) throws Exception {
-        // Every JCA object has a getProvider() method
-        Method m = object.getClass().getMethod("getProvider");
-        return (Provider) m.invoke(object);
-    }
-
-    @Test
-    public void testBeforeLimit() throws Exception {
-        // When we're before the limit of the target API, all calls should succeed
-        try {
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    VMRuntime.getRuntime().getTargetSdkVersion() + 1);
-            for (Algorithm a : BC_ALGORITHMS) {
-                Object result = a.getInstance();
-                assertEquals("BC", getProvider(result).getName());
-            }
-            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
-                Object result = a.getInstance();
-                assertEquals("AndroidOpenSSL", getProvider(result).getName());
-            }
-        } finally {
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        }
-    }
-
-    @Test
-    public void testAtLimit() throws Exception {
-        // When we're at the limit of the target API, all calls should still succeed
-        try {
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    VMRuntime.getRuntime().getTargetSdkVersion());
-            for (Algorithm a : BC_ALGORITHMS) {
-                Object result = a.getInstance();
-                assertEquals("BC", getProvider(result).getName());
-            }
-            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
-                Object result = a.getInstance();
-                assertEquals("AndroidOpenSSL", getProvider(result).getName());
-            }
-        } finally {
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        }
-    }
-
-    @Test
-    public void testPastLimit() throws Exception {
-        // When we're beyond the limit of the target API, the Conscrypt calls should succeed
-        // but the BC calls should throw NoSuchAlgorithmException
-        try {
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    VMRuntime.getRuntime().getTargetSdkVersion() - 1);
-            for (Algorithm a : BC_ALGORITHMS) {
-                try {
-                    a.getInstance();
-                    fail("getInstance should have thrown");
-                } catch (NoSuchAlgorithmException expected) {
-                }
-            }
-            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
-                Object result = a.getInstance();
-                assertEquals("AndroidOpenSSL", getProvider(result).getName());
-            }
-        } finally {
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        }
-    }
-
-    @Test
-    public void testCustomProvider() throws Exception {
-        // When we install our own separate instance of Bouncy Castle, the system should
-        // respect that and allow us to use its implementation.
-        Provider originalBouncyCastle = null;
-        int originalBouncyCastleIndex = -1;
-        for (int i = 0; i < Security.getProviders().length; i++) {
-            if (Security.getProviders()[i].getName().equals("BC")) {
-                originalBouncyCastle = Security.getProviders()[i];
-                originalBouncyCastleIndex = i;
-                break;
-            }
-        }
-        assertNotNull(originalBouncyCastle);
-        Provider newBouncyCastle = new BouncyCastleProvider();
-        assertEquals("BC", newBouncyCastle.getName());
-        try {
-            // Remove the existing BC provider and replace it with a different one
-            Security.removeProvider("BC");
-            Security.insertProviderAt(newBouncyCastle, originalBouncyCastleIndex);
-            // Set the target API limit such that the BC algorithms are disallowed
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    VMRuntime.getRuntime().getTargetSdkVersion() - 1);
-            for (Algorithm a : BC_ALGORITHMS) {
-                Object result = a.getInstance();
-                assertEquals("BC", getProvider(result).getName());
-            }
-            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
-                Object result = a.getInstance();
-                assertEquals("AndroidOpenSSL", getProvider(result).getName());
-            }
-        } finally {
-            Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-            Security.removeProvider("BC");
-            Security.insertProviderAt(originalBouncyCastle, originalBouncyCastleIndex);
-        }
-    }
-    
-    @Test
-    public void testRemovedBCAlgorithms() throws Exception {
-        for (String fullAlgorithm : REMOVED_BC_ALGORITHMS) {
-            String[] parts = fullAlgorithm.split("\\.", 2);
-            assertEquals("Algortihm names are expected to be of format Type.Name",
-                2, parts.length);
-
-            Provider bcProvider = Security.getProvider("BC");
-            String type = parts[0];
-            String algorithm = parts[1];
-            try {
-                switch (parts[0]) {
-                    case "ALGORITHMPARAMETERS":
-                        AlgorithmParameters.getInstance(algorithm, bcProvider);
-                    case "CERTIFICATEFACTORY":
-                        CertificateFactory.getInstance(algorithm, bcProvider);
-                    case "CIPHER":
-                        Cipher.getInstance(algorithm, bcProvider);
-                    case "KEYAGREEMENT":
-                        KeyAgreement.getInstance(algorithm, bcProvider);
-                    case "KEYFACTORY":
-                        KeyFactory.getInstance(algorithm, bcProvider);
-                    case "KEYGENERATOR":
-                        KeyGenerator.getInstance(algorithm, bcProvider);
-                    case "KEYPAIRGENERATOR":
-                        KeyPairGenerator.getInstance(algorithm, bcProvider);
-                    case "MAC":
-                        Mac.getInstance(algorithm, bcProvider);
-                    case "MESSAGEDIGEST":
-                        MessageDigest.getInstance(algorithm, bcProvider);
-                    case "SECRETKEYFACTORY":
-                        SecretKeyFactory.getInstance(algorithm, bcProvider);
-                    case "SIGNATURE":
-                        Signature.getInstance(algorithm, bcProvider);
-                    default:
-                        fail("unhandled algorithm type " + parts[0]);
-                }
-                fail("getInstance should have thrown for type: " + parts[0] + ", name: " + algorithm);
-            } catch(CertificateException | NoSuchAlgorithmException expected) {
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/luni/src/test/java/libcore/xml/XmlToSax2DriverTest.java b/luni/src/test/java/libcore/xml/XmlToSax2DriverTest.java
new file mode 100644
index 0000000..b8ad8bd
--- /dev/null
+++ b/luni/src/test/java/libcore/xml/XmlToSax2DriverTest.java
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2021 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.xml;
+
+import static org.junit.Assert.assertThrows;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import junit.framework.TestCase;
+import org.junit.Assert;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.sax2.Driver;
+
+public class XmlToSax2DriverTest extends TestCase {
+
+    private static final String XML =
+            "<note type=\"email\" foo=\"bar\">"
+            + "<to>John</to>"
+            + "<from>Smith</from>"
+            + "<heading>Lunch today</heading>"
+            + "<body>Hi, shall we go to lunch at 12?</body>"
+            + "</note>";
+
+    private Driver driver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        driver = new Driver();
+    }
+
+    public void testConstructor() {
+        Driver driver = null;
+        try {
+            driver = new Driver();
+        } catch (XmlPullParserException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+
+        assertEquals(0, driver.getLength());
+        assertEquals(1, driver.getColumnNumber());
+        assertEquals(1, driver.getLineNumber());
+    }
+
+    public void testConstructor_parametrized() {
+        XmlPullParserFactory factory;
+        XmlPullParser parser = null;
+
+        try {
+            factory = XmlPullParserFactory.newInstance(null, null);
+            parser = factory.newPullParser();
+        } catch (XmlPullParserException e) {
+            fail("Couldn't create factory and parser");
+        }
+        Driver driver = null;
+
+        try {
+             driver = new Driver(parser);
+        } catch (XmlPullParserException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+
+        assertEquals(0, driver.getLength());
+        assertEquals(1, driver.getColumnNumber());
+        assertEquals(1, driver.getLineNumber());
+    }
+
+    public void testGetColumnNumber() {
+        assertEquals(driver.getColumnNumber(), 1);
+    }
+
+    public void testSetProperty() throws Exception {
+        assertThrows(SAXNotSupportedException.class , () -> driver.setProperty(
+                "http://xml.org/sax/properties/declaration-handler", // DECLARATION_HANDLER_PROPERTY
+                ""));
+
+        assertThrows(SAXNotSupportedException.class ,() -> driver.setProperty(
+                "http://xml.org/sax/properties/lexical-handler", // LEXICAL_HANDLER_PROPERTY
+                ""));
+
+        // This may be the only key accpeted by the KXmlParser.
+        String key = "http://xmlpull.org/v1/doc/properties.html#location";
+        driver.setProperty(key, "123");
+        assertEquals("123", driver.getProperty(key));
+
+        assertThrows(SAXNotSupportedException.class ,() -> driver.setProperty("abc", ""));
+    }
+
+    public void testGetSetContentHandler() throws XmlPullParserException {
+        assertTrue(driver.getContentHandler() instanceof DefaultHandler);
+
+        ContentHandler handler = new DefaultHandler();
+        driver.setContentHandler(handler);
+        assertEquals(driver.getContentHandler(), handler);
+
+        driver.setContentHandler(null);
+        assertNull(driver.getContentHandler());
+    }
+
+    public void testGetSetDTDHandler() {
+        assertNull(driver.getDTDHandler());
+
+        driver.setDTDHandler(new DefaultHandler());
+        assertNull(driver.getDTDHandler());
+
+        driver.setDTDHandler(null);
+        assertNull(driver.getDTDHandler());
+    }
+
+    public void testGetSetEntityResolver() {
+        assertNull(driver.getEntityResolver());
+
+        driver.setEntityResolver(new DefaultHandler());
+        assertNull(driver.getEntityResolver());
+
+        driver.setEntityResolver((publicId, systemId) -> null);
+        assertNull(driver.getEntityResolver());
+
+        driver.setEntityResolver(null);
+        assertNull(driver.getEntityResolver());
+    }
+
+    public void testGetSetErrorHandler() {
+        assertTrue(driver.getContentHandler() instanceof DefaultHandler);
+
+        ErrorHandler handler = new DefaultHandler();
+        driver.setErrorHandler(handler);
+        assertEquals(handler, driver.getErrorHandler());
+
+        driver.setErrorHandler(null);
+        assertNull(driver.getErrorHandler());
+    }
+
+    public void testGetSetFeature() throws SAXNotSupportedException, SAXNotRecognizedException {
+        final String NAMESPACES_FEATURE = "http://xml.org/sax/features/namespaces";
+        final String NAMESPACE_PREFIXES_FEATURE = "http://xml.org/sax/features/namespace-prefixes";
+        final String VALIDATION_FEATURE = "http://xml.org/sax/features/validation";
+        final String PROCESS_DOCDECL_FEATURE =
+                "http://xmlpull.org/v1/doc/features.html#process-docdecl";
+        final String REPORT_NAMESPACE_ATTRIBUTES_FEATURE =
+                "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";
+        final String RELAXED_FEATURE = "http://xmlpull.org/v1/doc/features.html#relaxed";
+
+        final Object[][] expectations = {
+                {NAMESPACE_PREFIXES_FEATURE, false},
+                {VALIDATION_FEATURE, false},
+                {PROCESS_DOCDECL_FEATURE, false},
+                {REPORT_NAMESPACE_ATTRIBUTES_FEATURE, false},
+                {NAMESPACES_FEATURE, true},
+        };
+
+        for (Object[] f : expectations) {
+            final String feature = (String) f[0];
+            final boolean result = (boolean) f[1];
+            try {
+                assertEquals(result, driver.getFeature(feature));
+            } catch (SAXNotSupportedException | SAXNotRecognizedException e) {
+                fail("Unexpected exception: " + e.getMessage());
+            }
+        }
+
+        final String[] settable = {
+                NAMESPACES_FEATURE,
+                PROCESS_DOCDECL_FEATURE,
+                RELAXED_FEATURE,
+        };
+        for (String feature : settable) {
+            for (boolean value : new boolean[]{ false, true }) {
+                driver.setFeature(feature, value);
+                assertEquals(feature, value, driver.getFeature(feature));
+            }
+        }
+    }
+
+    public void testGetIndex() throws NoSuchFieldException, IllegalAccessException {
+        assertEquals(-1, driver.getIndex("hello"));
+        assertEquals(-1, driver.getIndex("encoding"));
+        assertEquals(-1, driver.getIndex("version"));
+    }
+
+    public void testGetIndex_namespaced() {
+        assertEquals(-1, driver.getIndex("", "version"));
+    }
+
+    public void testGetLength() {
+        assertEquals(0, driver.getLength());
+    }
+
+    public void testGetLineNumber() {
+        assertEquals(1, driver.getLineNumber());
+    }
+
+    public void testGetLocalName() {
+        try {
+            driver.getLocalName(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testGetProperty() {
+        try {
+            driver.getProperty("");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        } catch (SAXNotSupportedException | SAXNotRecognizedException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+    }
+
+    public void testGetPublicId() {
+        assertNull(driver.getPublicId());
+    }
+
+    public void testGetQName() {
+        try {
+            driver.getQName(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testGetSystemId() {
+        assertNull(driver.getSystemId());
+    }
+
+    public void testGetType() {
+        assertEquals("CDATA", driver.getType(0));
+        assertNull(driver.getType("value"));
+        assertNull(driver.getType("", "value"));
+    }
+
+    public void testGetUri() {
+        try {
+            driver.getURI(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testGetValue() {
+        try {
+            driver.getValue(0);
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertNull("CDATA", driver.getValue("value"));
+        assertNull("CDATA", driver.getValue("", "value"));
+    }
+
+    public void testParse_String() {
+        try {
+            driver.parse("systemId");
+        } catch (SAXException | IOException e) {
+            // expected
+        }
+
+        String systemId = null;
+        try {
+            driver.parse(systemId);
+        } catch (SAXException | IOException e) {
+            // expected
+        }
+    }
+
+    public void testParse_InputSource() throws IOException, SAXException {
+        InputSource source = new InputSource();
+        source.setCharacterStream(new StringReader(XML));
+        source.setSystemId("systemId");
+
+        final int[] errors = {0, 0, 0};
+        driver.setErrorHandler(new ErrorHandler() {
+            @Override
+            public void warning(SAXParseException exception) throws SAXException {
+                errors[0]++;
+            }
+
+            @Override
+            public void error(SAXParseException exception) throws SAXException {
+                errors[1]++;
+            }
+
+            @Override
+            public void fatalError(SAXParseException exception) throws SAXException {
+                errors[2]++;
+            }
+        });
+
+        // Four events counter: { "startDocument", "endDocument", "startElement", "endElement" }
+        final int[] events = {0, 0, 0, 0};
+        final ArrayList<String> tagsEncountered = new ArrayList<>();
+        final ArrayList<String> textsEncountered = new ArrayList<>();
+        driver.setContentHandler(new DefaultHandler() {
+            @Override
+            public void startDocument() throws SAXException {
+                super.startDocument();
+                events[0]++;
+            }
+
+            @Override
+            public void endDocument() throws SAXException {
+                super.endDocument();
+                events[1]++;
+            }
+
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                super.startElement(uri, localName, qName, attributes);
+                events[2]++;
+                tagsEncountered.add(localName);
+                if ("note".equals(localName)) {
+                    assertEquals(2, attributes.getLength());
+                    assertEquals("type", attributes.getLocalName(0));
+                    assertEquals("email", attributes.getValue(0));
+                    assertEquals("foo", attributes.getLocalName(1));
+                    assertEquals("bar", attributes.getValue(1));
+                }
+            }
+
+            @Override
+            public void characters(char[] ch, int start, int length) throws SAXException {
+                super.characters(ch, start, length);
+                textsEncountered.add(StringFactory.newStringFromChars(ch, start, length));
+            }
+
+            @Override
+            public void endElement(String uri, String localName, String qName) throws SAXException {
+                super.endElement(uri, localName, qName);
+                events[3]++;
+            }
+        });
+        driver.parse(source);
+
+        assertEquals("systemId", driver.getSystemId());
+        Assert.assertArrayEquals(new int[]{0, 0, 0}, errors);
+        Assert.assertArrayEquals(new int[]{1, 1, 5, 5}, events);
+        Assert.assertArrayEquals(new String[]{"note", "to", "from", "heading", "body"},
+                tagsEncountered.toArray());
+        Assert.assertArrayEquals(new String[]{
+                "John", "Smith", "Lunch today", "Hi, shall we go to lunch at 12?"
+        }, textsEncountered.toArray());
+    }
+
+    public void testParseSubtree() throws XmlPullParserException, IOException {
+        XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+        parser.setInput(new StringReader(XML));
+
+        final int[] errors = {0, 0, 0};
+        driver.setErrorHandler(new ErrorHandler() {
+            @Override
+            public void warning(SAXParseException exception) throws SAXException {
+                errors[0]++;
+            }
+
+            @Override
+            public void error(SAXParseException exception) throws SAXException {
+                errors[1]++;
+            }
+
+            @Override
+            public void fatalError(SAXParseException exception) throws SAXException {
+                errors[2]++;
+            }
+        });
+
+        // Four events counter: { "startDocument", "endDocument", "startElement", "endElement" }
+        final int[] events = {0, 0, 0, 0};
+        final ArrayList<String> tagsEncountered = new ArrayList<>();
+        final ArrayList<String> textsEncountered = new ArrayList<>();
+        driver.setContentHandler(new DefaultHandler() {
+            @Override
+            public void startDocument() throws SAXException {
+                super.startDocument();
+                events[0]++;
+            }
+
+            @Override
+            public void endDocument() throws SAXException {
+                super.endDocument();
+                events[1]++;
+            }
+
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                super.startElement(uri, localName, qName, attributes);
+                events[2]++;
+                tagsEncountered.add(localName);
+                if ("note".equals(localName)) {
+                    assertEquals(2, attributes.getLength());
+                    assertEquals("type", attributes.getLocalName(0));
+                    assertEquals("email", attributes.getValue(0));
+                    assertEquals("foo", attributes.getLocalName(1));
+                    assertEquals("bar", attributes.getValue(1));
+                }
+            }
+
+            @Override
+            public void characters(char[] ch, int start, int length) throws SAXException {
+                super.characters(ch, start, length);
+                textsEncountered.add(StringFactory.newStringFromChars(ch, start, length));
+            }
+
+            @Override
+            public void endElement(String uri, String localName, String qName) throws SAXException {
+                super.endElement(uri, localName, qName);
+                events[3]++;
+            }
+        });
+
+        try {
+            driver.parseSubTree(parser);
+        } catch (SAXException e) {
+            // expected, as START_TAG should have been read already
+        } catch (IOException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+        assertEquals(XmlPullParser.START_TAG, parser.next());
+        try {
+            driver.parseSubTree(parser);
+        } catch (SAXException | IOException e) {
+            fail("Unexpected exception: " + e.getMessage());
+        }
+
+        Assert.assertArrayEquals(new int[]{0, 0, 0}, errors);
+        Assert.assertArrayEquals(new int[]{0, 0, 5, 5}, events);
+        Assert.assertArrayEquals(new String[]{"note", "to", "from", "heading", "body"},
+                tagsEncountered.toArray());
+        Assert.assertArrayEquals(new String[]{
+                "John", "Smith", "Lunch today", "Hi, shall we go to lunch at 12?"
+        }, textsEncountered.toArray());
+    }
+
+    public void testStartElement() throws XmlPullParserException, IOException, SAXException {
+        boolean[] called = {false};
+        ContentHandler handler = new DefaultHandler() {
+            @Override
+            public void startElement(String uri, String localName, String qName,
+                    Attributes attributes) throws SAXException {
+                super.startElement(uri, localName, qName, attributes);
+                called[0] = true;
+            }
+        };
+        ExtendsDriver d = new ExtendsDriver(handler);
+        d.setContentHandler(handler);
+        d.parse(new InputSource(new StringReader(XML)));
+
+        assertTrue(called[0]);
+    }
+
+    private static class ExtendsDriver extends Driver {
+
+        private final ContentHandler handler;
+
+        public ExtendsDriver(ContentHandler handler) throws XmlPullParserException {
+            this.handler = handler;
+        }
+
+        @Override
+        protected void startElement(String namespace, String localName, String qName)
+                throws SAXException {
+            super.startElement(namespace, localName, qName);
+            handler.startElement(namespace, localName, qName, this);
+        }
+    }
+}
diff --git a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java
index aa2d9ca..6270838 100644
--- a/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java
+++ b/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLEncoderTest.java
@@ -61,8 +61,7 @@
         try {
             URLEncoder.encode(null, "harmony");
             fail("NullPointerException expected");
-        } catch (NullPointerException expected) {
-        } catch (UnsupportedCharsetException expected) {
+        } catch (UnsupportedEncodingException expected) {
         }
     }
 
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 6fbe9cf..f813be4 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
@@ -37,6 +37,7 @@
     assertTrue(s.contains("Foo"));
     assertTrue(s.contains("Bar"));
     assertTrue(s.contains("0"));
+    assertTrue(s.contains("^"));
 
     // No description specified
     e = new PatternSyntaxException(null, "Bar", 0);
@@ -48,6 +49,7 @@
     assertFalse(s.contains("Foo"));
     assertTrue(s.contains("Bar"));
     assertTrue(s.contains("0"));
+    assertTrue(s.contains("^"));
 
     // No pattern specified
     e = new PatternSyntaxException("Foo", null, 0);
@@ -84,7 +86,6 @@
     assertEquals(0, e.getIndex());
 
     s = e.getMessage();
-    assertTrue(s.contains("^"));
     assertTrue(s.contains("null"));
   }
 
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
index 2cbf1ce..b21b265 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
@@ -31,7 +31,7 @@
 import java.security.cert.X509Certificate;
 import org.apache.harmony.security.tests.java.security.IdentityScope2Test.IdentityScopeSubclass;
 
-@SuppressWarnings("deprecation")
+@SuppressWarnings("removal")
 public class Identity2Test extends junit.framework.TestCase {
 
     private static PublicKey PUB_KEY;
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/IdentityScope2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/IdentityScope2Test.java
index f68e030..449b9b7 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/IdentityScope2Test.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/IdentityScope2Test.java
@@ -27,7 +27,7 @@
 
 import org.apache.harmony.security.tests.java.security.Identity2Test.IdentitySubclass;
 
-@SuppressWarnings("deprecation")
+@SuppressWarnings("removal")
 public class IdentityScope2Test extends junit.framework.TestCase {
 
     private static PublicKey PUB_KEY;
@@ -38,6 +38,7 @@
         return PUB_KEY;
     }
 
+    @SuppressWarnings("removal")
     public static class IdentityScopeSubclass extends IdentityScope {
         private static final long serialVersionUID = 1L;
         Hashtable<Identity, Identity> identities;
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreBuilderTest.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreBuilderTest.java
index d14cf23..d423abe 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreBuilderTest.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreBuilderTest.java
@@ -92,14 +92,14 @@
         // exceptions verification
 
         try {
-            KeyStore.Builder.newInstance(null, null);
+            KeyStore.Builder.newInstance((KeyStore) null, null);
             fail("NullPointerException must be thrown");
         } catch (NullPointerException e) {
             // expected
         }
 
         try {
-            KeyStore.Builder.newInstance(null, protPass);
+            KeyStore.Builder.newInstance((KeyStore) null, protPass);
             fail("NullPointerException must be thrown");
         } catch (NullPointerException e) {
             // expected
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java
index 494ba65..d80965c 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreSpiTest.java
@@ -220,6 +220,22 @@
         } catch (UnsupportedOperationException expected) {
         }
     }
+
+    public void test_engineProbe() throws IOException {
+        KeyStoreSpi ksSpi = new MyKeyStoreSpi();
+        try {
+            ksSpi.engineProbe(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        InputStream inputStream = new InputStream() {
+            @Override
+            public int read() throws IOException {
+                return 0;
+            }
+        };
+        assertFalse(ksSpi.engineProbe(inputStream));
+    }
 }
 
 // These are "Bad" because they are not expected inner subclasses of the KeyStore class.
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SignerTest.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SignerTest.java
index 254b467..14d7fb1 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/SignerTest.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/SignerTest.java
@@ -43,7 +43,7 @@
  * tests for class Signer
  *
  */
-@SuppressWarnings("deprecation")
+@SuppressWarnings("removal")
 public class SignerTest extends TestCase {
 
     public static class MySecurityManager extends SecurityManager {
diff --git a/luni/src/test/java/tests/java/lang/ClassLoaderTest.java b/luni/src/test/java/tests/java/lang/ClassLoaderTest.java
new file mode 100644
index 0000000..717a562
--- /dev/null
+++ b/luni/src/test/java/tests/java/lang/ClassLoaderTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 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 tests.java.lang;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.Before;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ClassLoaderTest {
+
+    class TestClassLoader extends ClassLoader {
+        public Class<?> findSystemClassWrapper(String s) throws ClassNotFoundException {
+            return findSystemClass(s);
+        }
+
+        public Class<?> defineClassWrapper(String name, byte[] b, int off, int len)
+                throws ClassFormatError {
+            return defineClass(name, b, off, len);
+        }
+
+        public void setSignersWrapper(Class<?> c, Object[] signers) {
+            setSigners(c, signers);
+        }
+    }
+
+    private TestClassLoader loader;
+
+    @Before
+    public void setUp() throws Exception {
+        loader = new TestClassLoader();
+    }
+
+    @Test
+    public void test_findSystemClass() {
+        try {
+            loader.findSystemClassWrapper("java.lang.String");
+        } catch (ClassNotFoundException cnfe) {
+            throw new RuntimeException(cnfe);
+        }
+        try {
+            loader.findSystemClassWrapper("nonexistentclass");
+            fail("Expected ClassNotFoundException");
+        } catch (ClassNotFoundException cnfe) {
+        }
+    }
+
+    @Test
+    public void test_defineClass() {
+        try {
+            byte b[] = new byte[1];
+            loader.defineClassWrapper("java.lang.String", b, 0, 0);
+            fail();
+        } catch (UnsupportedOperationException e) {
+            assertEquals(e.getMessage(), "can't load this type of class file");
+        }
+    }
+
+    // setSigners does nothing
+    @Test
+    public void test_setSigners() {
+        Object[] signers = new Object[] { null };
+        loader.setSignersWrapper(Object.class, signers);
+    }
+}
\ No newline at end of file
diff --git a/luni/src/test/java/tests/java/security/IdentityTest.java b/luni/src/test/java/tests/java/security/IdentityTest.java
index 6610350..dc84fb8 100644
--- a/luni/src/test/java/tests/java/security/IdentityTest.java
+++ b/luni/src/test/java/tests/java/security/IdentityTest.java
@@ -41,7 +41,7 @@
  * Tests for class Identity
  *
  */
-@SuppressWarnings("deprecation")
+@SuppressWarnings("removal")
 public class IdentityTest extends TestCase {
 
     public static class MySecurityManager extends SecurityManager {
diff --git a/luni/src/test/java/tests/security/acl/AclNotFoundException2Test.java b/luni/src/test/java/tests/security/acl/AclNotFoundException2Test.java
index d3b7735..b9ff209 100644
--- a/luni/src/test/java/tests/security/acl/AclNotFoundException2Test.java
+++ b/luni/src/test/java/tests/security/acl/AclNotFoundException2Test.java
@@ -26,6 +26,7 @@
     /**
      * java.security.acl.AclNotFoundException#AclNotFoundException()
      */
+    @SuppressWarnings("removal")
     public void test_Constructor() {
         // Test for method java.security.acl.AclNotFoundException()
         try {
diff --git a/luni/src/test/java/tests/security/acl/AclNotFoundExceptionTest.java b/luni/src/test/java/tests/security/acl/AclNotFoundExceptionTest.java
index a4c389e..e371051 100644
--- a/luni/src/test/java/tests/security/acl/AclNotFoundExceptionTest.java
+++ b/luni/src/test/java/tests/security/acl/AclNotFoundExceptionTest.java
@@ -34,6 +34,7 @@
     /**
      * check default constructor
      */
+    @SuppressWarnings("removal")
     public void testAclNotFoundException() {
         assertNotNull(new AclNotFoundException());
         assertNull(new AclNotFoundException().getMessage());
diff --git a/luni/src/test/java/tests/security/acl/LastOwnerException2Test.java b/luni/src/test/java/tests/security/acl/LastOwnerException2Test.java
index 8b7d9a1..c73bcdd 100644
--- a/luni/src/test/java/tests/security/acl/LastOwnerException2Test.java
+++ b/luni/src/test/java/tests/security/acl/LastOwnerException2Test.java
@@ -26,6 +26,7 @@
     /**
      * java.security.acl.LastOwnerException#LastOwnerException()
      */
+    @SuppressWarnings("removal")
     public void test_Constructor() {
         // Test for method java.security.acl.LastOwnerException()
         try {
diff --git a/luni/src/test/java/tests/security/acl/LastOwnerExceptionTest.java b/luni/src/test/java/tests/security/acl/LastOwnerExceptionTest.java
index 6caca20..bc22c4d 100644
--- a/luni/src/test/java/tests/security/acl/LastOwnerExceptionTest.java
+++ b/luni/src/test/java/tests/security/acl/LastOwnerExceptionTest.java
@@ -31,6 +31,7 @@
  *
  */
 public class LastOwnerExceptionTest extends TestCase {
+    @SuppressWarnings("removal")
     public void testLastOwnerException() {
         assertNotNull(new LastOwnerException());
         assertNull(new LastOwnerException().getMessage());
diff --git a/luni/src/test/java/tests/security/acl/NotOwnerException2Test.java b/luni/src/test/java/tests/security/acl/NotOwnerException2Test.java
index 5632ec7..c787ed9 100644
--- a/luni/src/test/java/tests/security/acl/NotOwnerException2Test.java
+++ b/luni/src/test/java/tests/security/acl/NotOwnerException2Test.java
@@ -26,6 +26,7 @@
     /**
      * java.security.acl.NotOwnerException#NotOwnerException()
      */
+    @SuppressWarnings("removal")
     public void test_Constructor() {
         // Test for method java.security.acl.NotOwnerException()
         try {
diff --git a/luni/src/test/java/tests/security/acl/NotOwnerExceptionTest.java b/luni/src/test/java/tests/security/acl/NotOwnerExceptionTest.java
index 80b7823..dd89b05 100644
--- a/luni/src/test/java/tests/security/acl/NotOwnerExceptionTest.java
+++ b/luni/src/test/java/tests/security/acl/NotOwnerExceptionTest.java
@@ -31,6 +31,7 @@
  *
  */
 public class NotOwnerExceptionTest extends TestCase {
+    @SuppressWarnings("removal")
     public void testNotOwnerException() {
         assertNotNull(new NotOwnerException());
         assertNull(new NotOwnerException().getMessage());
diff --git a/luni/src/test/java/tests/targets/security/KeyStoreTest.java b/luni/src/test/java/tests/targets/security/KeyStoreTest.java
index e5bbb62..1b13e57 100644
--- a/luni/src/test/java/tests/targets/security/KeyStoreTest.java
+++ b/luni/src/test/java/tests/targets/security/KeyStoreTest.java
@@ -76,6 +76,14 @@
     }
 
     public void testKeyStoreCreate() {
+        createAndTest("the secret password", algorithmName);
+    }
+
+    public void testKeyStoreCreateNullPassword() {
+        createAndTest(null, "BKS");
+    }
+
+    private void createAndTest(String password, String algorithmName) {
         KeyStore keyStore = null;
         try {
             keyStore = KeyStore.getInstance(algorithmName);
@@ -83,8 +91,10 @@
             fail(e.getMessage());
         }
 
+        char[] passwordCharArray = (password == null) ? null : password.toCharArray();
+
         try {
-            keyStore.load(null, "the secret password".toCharArray());
+            keyStore.load(null, passwordCharArray);
         } catch (NoSuchAlgorithmException e) {
             fail(e.getMessage());
         } catch (CertificateException e) {
@@ -124,7 +134,7 @@
 
         try {
             keyStore.setEntry("aPrivateKey", privateKeyEntry,
-                    new PasswordProtection("the key password".toCharArray()));
+                    new PasswordProtection(passwordCharArray));
         } catch (KeyStoreException e) {
             fail(e.getMessage());
         }
@@ -137,8 +147,7 @@
 
         try {
             PrivateKeyEntry entry = (PrivateKeyEntry) keyStore.getEntry(
-                    "aPrivateKey", new PasswordProtection("the key password"
-                            .toCharArray()));
+                    "aPrivateKey", new PasswordProtection(passwordCharArray));
             PrivateKey privateKey = entry.getPrivateKey();
             assertEquals(keyPair.getPrivate(), privateKey);
         } catch (NoSuchAlgorithmException e) {
@@ -151,7 +160,7 @@
 
         try {
             ByteArrayOutputStream stream = new ByteArrayOutputStream();
-            keyStore.store(stream, "the keystore password".toCharArray());
+            keyStore.store(stream, passwordCharArray);
             assertTrue("keystore not written", stream.size() > 0);
         } catch (KeyStoreException e) {
             fail(e.getMessage());
diff --git a/luni/src/test/java11language/Android.bp b/luni/src/test/java11language/Android.bp
new file mode 100644
index 0000000..dc53d3f
--- /dev/null
+++ b/luni/src/test/java11language/Android.bp
@@ -0,0 +1,83 @@
+// Copyright (C) 2021 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.
+
+// Android tests related to Java 11 language features.
+
+// Use jarjar to repackage Java11LanguageFeatures, to be used in tests below.
+package {
+    // http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // the below license kinds from "libcore_luni_license":
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["libcore_luni_license"],
+}
+
+java_library {
+    name: "core-java-11-language-features-repackaged-for-test",
+    hostdex: true,
+
+    srcs: [":core-java-11-language-features-source"],
+    jarjar_rules: "jarjar_rules_java11_language_features.txt",
+    java_version: "11",
+
+    sdk_version: "none",
+    system_modules: "core-all-system-modules",
+    patch_module: "java.base",
+
+    visibility: ["//visibility:private"],
+}
+
+// Generate a clone of Java11LanguageFeaturesTest which uses a version of
+// Java11LanguageFeatures repackaged by jarjar. This ensures that jarjar is able
+// to handle a class file which must be at least v55 and includes bytecode
+// compiled from Java 11 language features.
+filegroup {
+    name: "core-rewrite-java-11-test-for-jarjar-sed-script",
+    srcs: ["rewrite-test-for-jarjar.sed"],
+    visibility: ["//visibility:private"],
+}
+
+filegroup {
+    name: "core-java-11-language-features-test-src",
+    srcs: ["java/libcore/libcore/internal/Java11LanguageFeaturesTest.java"],
+    visibility: ["//visibility:private"],
+}
+
+genrule {
+    name: "core-gen-test-repackaged-java-11-language-features",
+    srcs: [
+        ":core-rewrite-java-11-test-for-jarjar-sed-script",
+        ":core-java-11-language-features-test-src",
+    ],
+    out: ["libcore/libcore/internal/Java11LanguageFeaturesJarjarTest.java"],
+    cmd: "sed -r -f $(location :core-rewrite-java-11-test-for-jarjar-sed-script) $(location :core-java-11-language-features-test-src) > $(out)",
+    visibility: ["//visibility:private"],
+}
+
+java_library {
+    name: "core-java-11-language-tests",
+    hostdex: true,
+    srcs: [
+        "java/**/*.java",
+        ":core-gen-test-repackaged-java-11-language-features",
+    ],
+    sdk_version: "none",
+    system_modules: "core-all-system-modules",
+    static_libs: [
+        "core-java-11-language-features-repackaged-for-test",
+        "junit",
+    ],
+    visibility: ["//libcore"],
+    java_version: "11",
+}
diff --git a/luni/src/test/java11language/jarjar_rules_java11_language_features.txt b/luni/src/test/java11language/jarjar_rules_java11_language_features.txt
new file mode 100644
index 0000000..dee72bc
--- /dev/null
+++ b/luni/src/test/java11language/jarjar_rules_java11_language_features.txt
@@ -0,0 +1 @@
+rule libcore.internal.** libcore.internal.repackaged.@1
diff --git a/luni/src/test/java11language/java/libcore/libcore/internal/Java11LanguageFeaturesTest.java b/luni/src/test/java11language/java/libcore/libcore/internal/Java11LanguageFeaturesTest.java
new file mode 100644
index 0000000..055f19b
--- /dev/null
+++ b/luni/src/test/java11language/java/libcore/libcore/internal/Java11LanguageFeaturesTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 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.libcore.internal;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import libcore.internal.Java11LanguageFeatures;
+
+import org.junit.Test;
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class Java11LanguageFeaturesTest {
+
+    @Test
+    public void testVarForLambda() {
+        assertEquals("ONE TWO THREE",
+                Java11LanguageFeatures.collectUpperCaseStrings(
+                        Arrays.asList("one", "two", "three")));
+    }
+
+    @Test
+    public void testLocalVariableTypeInference() {
+        assertEquals("", Java11LanguageFeatures.guessTheString("42"));
+        assertEquals("The answer to the universe, life and everything",
+                Java11LanguageFeatures.guessTheString(
+                        "The answer to the universe, life and everything"));
+    }
+
+    @Test
+    @Ignore("b/210843415")
+    public void testReflectionOnPrivateNestmate() throws Throwable {
+        Java11LanguageFeatures.Person person = new Java11LanguageFeatures.Person("R2D2");
+        assertEquals("Hello R2D2", person.greet());
+    }
+}
diff --git a/luni/src/test/java11language/rewrite-test-for-jarjar.sed b/luni/src/test/java11language/rewrite-test-for-jarjar.sed
new file mode 100644
index 0000000..eb350b1
--- /dev/null
+++ b/luni/src/test/java11language/rewrite-test-for-jarjar.sed
@@ -0,0 +1,21 @@
+# Copyright (C) 2021 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.
+
+# This is a sed script that modifies Java source code in two ways.
+
+# Replace libcore.internal with libcore.internal.repackaged in imports:
+s/import libcore.internal/import libcore.internal.repackaged/
+
+# Replace Test with JarjarTest in class declarations.
+s/class ([A-Za-z0-9_]+)Test/class \1JarjarTest/
diff --git a/luni/src/test/java9compatibility/Android.bp b/luni/src/test/java9compatibility/Android.bp
new file mode 100644
index 0000000..a329cd5
--- /dev/null
+++ b/luni/src/test/java9compatibility/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2019 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.
+
+// Android tests related to compatibility with pre-Java 11 language features.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "libcore_luni_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["libcore_luni_license"],
+}
+
+java_library {
+    name: "core-java-9-compatibility-tests",
+    hostdex: true,
+    srcs: [
+        "java/**/*.java",
+    ],
+    java_version: "1.9",
+    sdk_version: "none",
+    system_modules: "core-all-system-modules",
+    static_libs: [
+        "core-test-rules",
+        "junit",
+        "junit-params",
+    ],
+    visibility: ["//libcore"],
+}
diff --git a/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java b/luni/src/test/java9compatibility/java/libcore/java/io/ObjectStreamClassTest.java
similarity index 100%
rename from luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java
rename to luni/src/test/java9compatibility/java/libcore/java/io/ObjectStreamClassTest.java
diff --git a/luni/src/test/native/libcore_java_io_FileTest.cpp b/luni/src/test/native/libcore_java_io_FileTest.cpp
index 7cc6568..759d808 100644
--- a/luni/src/test/native/libcore_java_io_FileTest.cpp
+++ b/luni/src/test/native/libcore_java_io_FileTest.cpp
@@ -37,18 +37,22 @@
   int ret = stat(subDir.c_str(), &sb);
   if (ret == -1) {
       jniThrowIOException(env, errno);
+      return;
   }
   if (!S_ISDIR(sb.st_mode)) {
       jniThrowException(env, "java/lang/IllegalStateException", "expected dir");
+      return;
   }
 
   ret = stat(subFile.c_str(), &sb);
   if (ret == -1) {
       jniThrowIOException(env, errno);
+      return;
   }
 
   if (!S_ISREG(sb.st_mode)) {
       jniThrowException(env, "java/lang/IllegalStateException", "expected file");
+      return;
   }
 }
 
diff --git a/luni/src/test/native/libcore_java_time_BionicTzdbConsistencyTest.cpp b/luni/src/test/native/libcore_java_time_BionicTzdbConsistencyTest.cpp
new file mode 100644
index 0000000..be7e164
--- /dev/null
+++ b/luni/src/test/native/libcore_java_time_BionicTzdbConsistencyTest.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 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 <locale.h>
+#include <time.h>
+#include <stdlib.h>
+#include <jni.h>
+
+extern "C"
+JNIEXPORT jstring JNICALL Java_libcore_java_time_BionicTzdbConsistencyTest_formatWithBionic(
+    JNIEnv* env, jclass, jlong epochSeconds, jstring timeZoneId) {
+
+  const char* oldTimeZone = getenv("TZ");
+  const char* oldLocale = setlocale(LC_ALL, NULL);
+
+  const char* nativeTimeZone = env->GetStringUTFChars(timeZoneId, 0);
+  setenv("TZ", nativeTimeZone, /* overwrite */ 1);
+  env->ReleaseStringUTFChars(timeZoneId, nativeTimeZone);
+
+  setlocale(LC_ALL, "en_US");
+
+  // Formatted string should fit into this buffer
+  char buf[32];
+  time_t t = epochSeconds;
+  strftime(buf, 32, "%d %m %Y %H:%M:%S", localtime(&t));
+
+  if (oldTimeZone) {
+    setenv("TZ", oldTimeZone, /* overwrite */ 1);
+  } else {
+    unsetenv("TZ");
+  }
+
+  setlocale(LC_ALL, oldLocale);
+
+  return env->NewStringUTF(buf);
+}
diff --git a/luni/src/test/resources/libcore/java/nio/charset/encodings_ISO-8859-1.txt b/luni/src/test/resources/libcore/java/nio/charset/encodings_ISO-8859-1.txt
index ded4590..432d7d6 100644
--- a/luni/src/test/resources/libcore/java/nio/charset/encodings_ISO-8859-1.txt
+++ b/luni/src/test/resources/libcore/java/nio/charset/encodings_ISO-8859-1.txt
@@ -6160,7 +6160,9 @@
 6156:true:
 6157:true:
 6158:true:
-6159:false:
+# Disable the test U+180F as the property change
+# U+180F Mongolian Nonspacing Mark
+# 6159:true:
 6160:false:
 6161:false:
 6162:false:
diff --git a/luni/src/test/resources/libcore/java/nio/charset/encodings_US-ASCII.txt b/luni/src/test/resources/libcore/java/nio/charset/encodings_US-ASCII.txt
index 9901420..9862932 100644
--- a/luni/src/test/resources/libcore/java/nio/charset/encodings_US-ASCII.txt
+++ b/luni/src/test/resources/libcore/java/nio/charset/encodings_US-ASCII.txt
@@ -6160,7 +6160,9 @@
 6156:true:
 6157:true:
 6158:true:
-6159:false:
+# Disable the test U+180F as the property change
+# U+180F Mongolian Nonspacing Mark
+# 6159:true:
 6160:false:
 6161:false:
 6162:false:
diff --git a/mmodules/core_platform_api/Android.bp b/mmodules/core_platform_api/Android.bp
deleted file mode 100644
index 7036aba..0000000
--- a/mmodules/core_platform_api/Android.bp
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (C) 2018 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.
-
-// Generates stub source files for the core platform API of the ART module.
-// i.e. every class/member that is either in the public API or annotated with
-// @CorePlatformApi.
-//
-// The API specification .txt files managed by this only contain the additional
-// classes/members that are in the intra-core API but which are not in the public
-// API.
-//
-// There are two versions of the API surface. The "stable" version contains the
-// APIs which are considered stable, and is indicated in source with the
-// annotation @CorePlatformApi(status = CorePlatformApi.Status.STABLE). The
-// "legacy" version also includes those which have not been audited for stability
-// or which are deprecated (which have the default status of LEGACY_ONLY).
-//
-// TODO(b/161973015): Remove the legacy/stable distinction once no longer useful.
-
-package {
-    // http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // the below license kinds from "libcore_license":
-    //   SPDX-license-identifier-Apache-2.0
-    //   SPDX-license-identifier-GPL
-    //   SPDX-license-identifier-GPL-2.0
-    //   SPDX-license-identifier-LGPL
-    //   SPDX-license-identifier-MIT
-    //   SPDX-license-identifier-W3C
-    default_applicable_licenses: ["libcore_license"],
-}
-
-// Ideally this should be a restricted allowlist but there are hundreds of modules that depend on
-// this.
-// TODO(http://b/134561230) - limit the number of dependents on this.
-core_platform_visibility = ["//visibility:public"]
-
-// Libraries containing the core platform API stubs for the core libraries.
-//
-// Although this stubs library is primarily used by the Java compiler / build to indicate
-// the core platform API surface area, compile_dex: true is used so that the Core Platform
-// API annotations are available to the dex tools that enable enforcement of runtime
-// accessibility. b/119068555
-java_library {
-    name: "legacy.core.platform.api.stubs",
-    visibility: core_platform_visibility,
-    hostdex: true,
-    compile_dex: true,
-
-    sdk_version: "none",
-    system_modules: "none",
-    static_libs: [
-        "art.module.public.api.stubs.module_lib",
-        "conscrypt.module.platform.api.stubs",
-        "legacy.i18n.module.platform.api.stubs",
-    ],
-    patch_module: "java.base",
-}
-
-java_library {
-    name: "stable.core.platform.api.stubs",
-    visibility: core_platform_visibility,
-    hostdex: true,
-    compile_dex: true,
-
-    sdk_version: "none",
-    system_modules: "none",
-    static_libs: [
-        "art.module.public.api.stubs.module_lib",
-        // conscrypt only has a stable version, so it is okay to depend on it here:
-        "conscrypt.module.platform.api.stubs",
-        "stable.i18n.module.platform.api.stubs",
-    ],
-    patch_module: "java.base",
-}
-
-// Used when compiling higher-level code against *.core.platform.api.stubs.
-java_system_modules {
-    name: "legacy-core-platform-api-stubs-system-modules",
-    visibility: core_platform_visibility,
-    libs: [
-        "legacy.core.platform.api.stubs",
-        // This one is not on device but it's needed when javac compiles code
-        // containing lambdas.
-        "core-lambda-stubs-for-system-modules",
-        // This one is not on device but it's needed when javac compiles code
-        // containing @Generated annotations produced by some code generation
-        // tools.
-        // See http://b/123891440.
-        "core-generated-annotation-stubs",
-    ],
-}
-
-java_system_modules {
-    name: "stable-core-platform-api-stubs-system-modules",
-    visibility: core_platform_visibility,
-    libs: [
-        "stable.core.platform.api.stubs",
-        // This one is not on device but it's needed when javac compiles code
-        // containing lambdas.
-        "core-lambda-stubs-for-system-modules",
-        // This one is not on device but it's needed when javac compiles code
-        // containing @Generated annotations produced by some code generation
-        // tools.
-        // See http://b/123891440.
-        "core-generated-annotation-stubs",
-    ],
-}
diff --git a/mmodules/core_platform_api/api/legacy_platform/current.txt b/mmodules/core_platform_api/api/legacy_platform/current.txt
deleted file mode 100644
index 15741a7..0000000
--- a/mmodules/core_platform_api/api/legacy_platform/current.txt
+++ /dev/null
@@ -1,865 +0,0 @@
-// Signature format: 2.0
-package android.compat {
-
-  public final class Compatibility {
-    method public static void clearBehaviorChangeDelegate();
-    method public static void clearOverrides();
-    method public static boolean isChangeEnabled(long);
-    method public static void reportUnconditionalChange(long);
-    method public static void setBehaviorChangeDelegate(android.compat.Compatibility.BehaviorChangeDelegate);
-    method public static void setOverrides(android.compat.Compatibility.ChangeConfig);
-  }
-
-  public static interface Compatibility.BehaviorChangeDelegate {
-    method public default boolean isChangeEnabled(long);
-    method public default void onChangeReported(long);
-  }
-
-  public static final class Compatibility.ChangeConfig {
-    ctor public Compatibility.ChangeConfig(@NonNull java.util.Set<java.lang.Long>, @NonNull java.util.Set<java.lang.Long>);
-    method @NonNull public long[] getDisabledChangesArray();
-    method @NonNull public java.util.Set<java.lang.Long> getDisabledSet();
-    method @NonNull public long[] getEnabledChangesArray();
-    method @NonNull public java.util.Set<java.lang.Long> getEnabledSet();
-    method public boolean isEmpty();
-    method public boolean isForceDisabled(long);
-    method public boolean isForceEnabled(long);
-  }
-
-}
-
-package android.system {
-
-  public final class NetlinkSocketAddress extends java.net.SocketAddress {
-    ctor public NetlinkSocketAddress(int, int);
-    method public int getGroupsMask();
-    method public int getPortId();
-  }
-
-  public final class Os {
-    method @Nullable public static android.system.StructCapUserData[] capget(@NonNull android.system.StructCapUserHeader) throws android.system.ErrnoException;
-    method public static void capset(@NonNull android.system.StructCapUserHeader, @NonNull android.system.StructCapUserData[]) throws android.system.ErrnoException;
-    method public static int getpgid(int) throws android.system.ErrnoException;
-    method @Nullable public static android.system.StructRlimit getrlimit(int) throws android.system.ErrnoException;
-    method public static int getsockoptInt(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
-    method @Nullable public static android.system.StructLinger getsockoptLinger(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
-    method public static int ioctlInt(@NonNull java.io.FileDescriptor, int) throws android.system.ErrnoException;
-    method @Nullable public static java.io.FileDescriptor[] pipe2(int) throws android.system.ErrnoException;
-    method @Nullable public static String realpath(@Nullable String) throws android.system.ErrnoException;
-    method public static void setpgid(int, int) throws android.system.ErrnoException;
-    method public static void setregid(int, int) throws android.system.ErrnoException;
-    method public static void setreuid(int, int) throws android.system.ErrnoException;
-    method public static void setsockoptIfreq(@NonNull java.io.FileDescriptor, int, int, @Nullable String) throws android.system.ErrnoException;
-    method public static void setsockoptLinger(@NonNull java.io.FileDescriptor, int, int, @NonNull android.system.StructLinger) throws android.system.ErrnoException;
-    method public static long splice(@NonNull java.io.FileDescriptor, @Nullable android.system.Int64Ref, @NonNull java.io.FileDescriptor, @Nullable android.system.Int64Ref, long, int) throws android.system.ErrnoException;
-    method public static void unlink(@Nullable String) throws android.system.ErrnoException;
-  }
-
-  public final class OsConstants {
-    method public static int CAP_TO_INDEX(int);
-    method public static int CAP_TO_MASK(int);
-    field public static final int ARPHRD_LOOPBACK;
-    field public static final int EUSERS;
-    field public static final int MAP_POPULATE;
-    field public static final int O_DIRECT;
-    field public static final int PR_CAP_AMBIENT;
-    field public static final int PR_CAP_AMBIENT_RAISE;
-    field public static final int RLIMIT_NOFILE;
-    field public static final int RTMGRP_IPV4_IFADDR;
-    field public static final int SPLICE_F_MORE;
-    field public static final int SPLICE_F_MOVE;
-    field public static final int TIOCOUTQ;
-    field public static final int UDP_ENCAP;
-    field public static final int UDP_ENCAP_ESPINUDP;
-    field public static final int XATTR_CREATE;
-    field public static final int XATTR_REPLACE;
-    field public static final int _LINUX_CAPABILITY_VERSION_3;
-  }
-
-  public final class PacketSocketAddress extends java.net.SocketAddress {
-    ctor public PacketSocketAddress(int, int, byte[]);
-  }
-
-  public final class StructCapUserData {
-    ctor public StructCapUserData(int, int, int);
-    field public final int effective;
-    field public final int inheritable;
-    field public final int permitted;
-  }
-
-  public final class StructCapUserHeader {
-    ctor public StructCapUserHeader(int, int);
-  }
-
-  public final class StructLinger {
-    ctor public StructLinger(int, int);
-    method public boolean isOn();
-    field public final int l_linger;
-  }
-
-  public final class StructRlimit {
-    field public final long rlim_cur;
-  }
-
-  public final class UnixSocketAddress extends java.net.SocketAddress {
-    method public static android.system.UnixSocketAddress createFileSystem(String);
-  }
-
-  public final class VmSocketAddress extends java.net.SocketAddress {
-    ctor public VmSocketAddress(int, int);
-    method public int getSvmCid();
-    method public int getSvmPort();
-  }
-
-}
-
-package com.android.okhttp.internalandroidapi {
-
-  public final class AndroidResponseCacheAdapter {
-    ctor public AndroidResponseCacheAdapter(@NonNull com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder);
-    method public void close() throws java.io.IOException;
-    method public void delete() throws java.io.IOException;
-    method public void flush() throws java.io.IOException;
-    method @Nullable public java.net.CacheResponse get(@NonNull java.net.URI, @NonNull String, @Nullable java.util.Map<java.lang.String,java.util.List<java.lang.String>>) throws java.io.IOException;
-    method @NonNull public com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder getCacheHolder();
-    method public int getHitCount();
-    method public long getMaxSize();
-    method public int getNetworkCount();
-    method public int getRequestCount();
-    method public long getSize() throws java.io.IOException;
-    method @Nullable public java.net.CacheRequest put(@NonNull java.net.URI, @NonNull java.net.URLConnection) throws java.io.IOException;
-  }
-
-  public interface HasCacheHolder {
-    method @NonNull public com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder getCacheHolder();
-  }
-
-  public static final class HasCacheHolder.CacheHolder {
-    method @NonNull public static com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder create(@NonNull java.io.File, long);
-    method public boolean isEquivalent(@NonNull java.io.File, long);
-  }
-
-}
-
-package dalvik.annotation.codegen {
-
-  @java.lang.annotation.Repeatable(CovariantReturnType.CovariantReturnTypes.class) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface CovariantReturnType {
-    method public abstract int presentAfter();
-    method public abstract Class<?> returnType();
-  }
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public static @interface CovariantReturnType.CovariantReturnTypes {
-    method public abstract dalvik.annotation.codegen.CovariantReturnType[] value();
-  }
-
-}
-
-package dalvik.annotation.optimization {
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface CriticalNative {
-  }
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface FastNative {
-  }
-
-}
-
-package dalvik.system {
-
-  public final class AnnotatedStackTraceElement {
-    method @Nullable public Object getBlockedOn();
-    method @Nullable public Object[] getHeldLocks();
-    method @NonNull public StackTraceElement getStackTraceElement();
-  }
-
-  public class AppSpecializationHooks {
-    method public static void handleCompatChangesBeforeBindingApplication();
-  }
-
-  public class BaseDexClassLoader extends java.lang.ClassLoader {
-    method public void addDexPath(@Nullable String);
-    method public void addNativePath(@NonNull java.util.Collection<java.lang.String>);
-    method @NonNull public String getLdLibraryPath();
-    method public void reportClassLoaderChain();
-    method public static void setReporter(@Nullable dalvik.system.BaseDexClassLoader.Reporter);
-  }
-
-  public static interface BaseDexClassLoader.Reporter {
-    method public void report(@NonNull java.util.Map<java.lang.String,java.lang.String>);
-  }
-
-  public final class BlockGuard {
-    method @NonNull public static dalvik.system.BlockGuard.Policy getThreadPolicy();
-    method @NonNull public static dalvik.system.BlockGuard.VmPolicy getVmPolicy();
-    method public static void setThreadPolicy(@NonNull dalvik.system.BlockGuard.Policy);
-    method public static void setVmPolicy(@NonNull dalvik.system.BlockGuard.VmPolicy);
-    field public static final dalvik.system.BlockGuard.Policy LAX_POLICY;
-    field public static final dalvik.system.BlockGuard.VmPolicy LAX_VM_POLICY;
-  }
-
-  public static interface BlockGuard.Policy {
-    method public int getPolicyMask();
-    method public void onReadFromDisk();
-    method public void onUnbufferedIO();
-    method public void onWriteToDisk();
-  }
-
-  public static interface BlockGuard.VmPolicy {
-    method public void onPathAccess(@NonNull String);
-  }
-
-  public final class CloseGuard {
-    method public void close();
-    method public static dalvik.system.CloseGuard get();
-    method public static dalvik.system.CloseGuard.Reporter getReporter();
-    method public void open(String);
-    method public void openWithCallSite(String, String);
-    method public static void setEnabled(boolean);
-    method public static void setReporter(dalvik.system.CloseGuard.Reporter);
-    method public void warnIfOpen();
-  }
-
-  public static interface CloseGuard.Reporter {
-    method public void report(String, Throwable);
-    method public default void report(String);
-  }
-
-  public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
-    ctor public DelegateLastClassLoader(String, String, ClassLoader, ClassLoader[]);
-  }
-
-  @Deprecated public final class DexFile {
-    method @Deprecated @NonNull public static dalvik.system.DexFile.OptimizationInfo getDexFileOptimizationInfo(@NonNull String, @NonNull String) throws java.io.FileNotFoundException;
-    method @Deprecated @Nullable public static String[] getDexFileOutputPaths(@NonNull String, @NonNull String) throws java.io.FileNotFoundException;
-    method @Deprecated public static int getDexOptNeeded(@NonNull String, @NonNull String, @NonNull String, @Nullable String, boolean, boolean) throws java.io.FileNotFoundException, java.io.IOException;
-    method @Deprecated @NonNull public static String getSafeModeCompilerFilter(@NonNull String);
-    method @Deprecated public static boolean isProfileGuidedCompilerFilter(@NonNull String);
-    method @Deprecated public static boolean isValidCompilerFilter(@NonNull String);
-    field @Deprecated public static final int DEX2OAT_FOR_FILTER = 3; // 0x3
-    field @Deprecated public static final int NO_DEXOPT_NEEDED = 0; // 0x0
-  }
-
-  @Deprecated public static final class DexFile.OptimizationInfo {
-    method @Deprecated @NonNull public String getReason();
-    method @Deprecated @NonNull public String getStatus();
-  }
-
-  public class PathClassLoader extends dalvik.system.BaseDexClassLoader {
-    ctor public PathClassLoader(@NonNull String, @Nullable String, @Nullable ClassLoader, @Nullable ClassLoader[]);
-  }
-
-  public final class RuntimeHooks {
-    method public static void setTimeZoneIdSupplier(@NonNull java.util.function.Supplier<java.lang.String>);
-    method public static void setUncaughtExceptionPreHandler(@Nullable java.lang.Thread.UncaughtExceptionHandler);
-  }
-
-  public abstract class SocketTagger {
-    ctor public SocketTagger();
-    method public static dalvik.system.SocketTagger get();
-    method public static void set(dalvik.system.SocketTagger);
-    method public abstract void tag(java.io.FileDescriptor) throws java.net.SocketException;
-    method public final void tag(java.net.Socket) throws java.net.SocketException;
-    method public final void tag(java.net.DatagramSocket) throws java.net.SocketException;
-    method public abstract void untag(java.io.FileDescriptor) throws java.net.SocketException;
-    method public final void untag(java.net.Socket) throws java.net.SocketException;
-    method public final void untag(java.net.DatagramSocket) throws java.net.SocketException;
-  }
-
-  public final class VMDebug {
-    method public static void attachAgent(String, ClassLoader) throws java.io.IOException;
-    method public static long countInstancesOfClass(Class, boolean);
-    method public static long[] countInstancesOfClasses(Class[], boolean);
-    method public static void dumpHprofData(String) throws java.io.IOException;
-    method public static void dumpHprofData(String, java.io.FileDescriptor) throws java.io.IOException;
-    method public static void dumpHprofDataDdms();
-    method public static void dumpReferenceTables();
-    method public static int getAllocCount(int);
-    method @dalvik.annotation.optimization.FastNative public static int getLoadedClassCount();
-    method public static int getMethodTracingMode();
-    method public static String getRuntimeStat(String);
-    method public static java.util.Map<java.lang.String,java.lang.String> getRuntimeStats();
-    method public static String[] getVmFeatureList();
-    method @dalvik.annotation.optimization.FastNative public static boolean isDebuggerConnected();
-    method @dalvik.annotation.optimization.FastNative public static boolean isDebuggingEnabled();
-    method @dalvik.annotation.optimization.FastNative public static long lastDebuggerActivity();
-    method @dalvik.annotation.optimization.FastNative public static void printLoadedClasses(int);
-    method public static void resetAllocCount(int);
-    method public static void setAllocTrackerStackDepth(int);
-    method public static void startAllocCounting();
-    method public static void startMethodTracing(String, int, int, boolean, int);
-    method public static void startMethodTracing(String, java.io.FileDescriptor, int, int, boolean, int, boolean);
-    method public static void startMethodTracingDdms(int, int, boolean, int);
-    method public static void stopAllocCounting();
-    method public static void stopMethodTracing();
-    method @dalvik.annotation.optimization.FastNative public static long threadCpuTimeNanos();
-    field public static final int KIND_ALL_COUNTS = -1; // 0xffffffff
-    field public static final int KIND_GLOBAL_ALLOCATED_BYTES = 2; // 0x2
-    field public static final int KIND_GLOBAL_ALLOCATED_OBJECTS = 1; // 0x1
-    field public static final int KIND_GLOBAL_CLASS_INIT_COUNT = 32; // 0x20
-    field public static final int KIND_GLOBAL_CLASS_INIT_TIME = 64; // 0x40
-    field public static final int KIND_GLOBAL_FREED_BYTES = 8; // 0x8
-    field public static final int KIND_GLOBAL_FREED_OBJECTS = 4; // 0x4
-    field public static final int KIND_GLOBAL_GC_INVOCATIONS = 16; // 0x10
-    field public static final int KIND_THREAD_ALLOCATED_BYTES = 131072; // 0x20000
-    field public static final int KIND_THREAD_ALLOCATED_OBJECTS = 65536; // 0x10000
-    field public static final int KIND_THREAD_GC_INVOCATIONS = 1048576; // 0x100000
-    field public static final int TRACE_COUNT_ALLOCS = 1; // 0x1
-  }
-
-  public final class VMRuntime {
-    method @dalvik.annotation.optimization.FastNative public long addressOf(Object);
-    method public static void bootCompleted();
-    method public void clampGrowthLimit();
-    method public void clearGrowthLimit();
-    method public static String getCurrentInstructionSet();
-    method public static String getInstructionSet(String);
-    method public static dalvik.system.VMRuntime getRuntime();
-    method public int getTargetSdkVersion();
-    method @dalvik.annotation.optimization.FastNative public boolean is64Bit();
-    method public static boolean is64BitAbi(String);
-    method public static boolean is64BitInstructionSet(String);
-    method @dalvik.annotation.optimization.FastNative public boolean isCheckJniEnabled();
-    method @dalvik.annotation.optimization.FastNative public boolean isNativeDebuggable();
-    method public static boolean isValidClassLoaderContext(String);
-    method @dalvik.annotation.optimization.FastNative public Object newNonMovableArray(Class<?>, int);
-    method @dalvik.annotation.optimization.FastNative public Object newUnpaddedArray(Class<?>, int);
-    method public void notifyStartupCompleted();
-    method public void preloadDexCaches();
-    method public static void registerAppInfo(String, String, String, String[], int);
-    method public void registerNativeAllocation(long);
-    method @Deprecated public void registerNativeAllocation(int);
-    method public void registerNativeFree(long);
-    method @Deprecated public void registerNativeFree(int);
-    method public static void registerSensitiveThread();
-    method public void requestConcurrentGC();
-    method public static void resetJitCounters();
-    method public static void setDedupeHiddenApiWarnings(boolean);
-    method public void setDisabledCompatChanges(long[]);
-    method public void setHiddenApiAccessLogSamplingRate(int);
-    method public void setHiddenApiExemptions(String[]);
-    method public static void setHiddenApiUsageLogger(dalvik.system.VMRuntime.HiddenApiUsageLogger);
-    method public static void setNonSdkApiUsageConsumer(java.util.function.Consumer<java.lang.String>);
-    method public static void setProcessDataDirectory(String);
-    method public static void setProcessPackageName(String);
-    method public void setTargetSdkVersion(int);
-    method public void updateProcessState(int);
-    method public String vmInstructionSet();
-    method public String vmLibrary();
-    field public static final int CODE_PATH_TYPE_PRIMARY_APK = 1; // 0x1
-    field public static final int CODE_PATH_TYPE_SECONDARY_DEX = 4; // 0x4
-    field public static final int CODE_PATH_TYPE_SPLIT_APK = 2; // 0x2
-    field public static final int SDK_VERSION_CUR_DEVELOPMENT = 10000; // 0x2710
-  }
-
-  public static interface VMRuntime.HiddenApiUsageLogger {
-    method public void hiddenApiUsed(int, String, String, int, boolean);
-    field public static final int ACCESS_METHOD_JNI = 2; // 0x2
-    field public static final int ACCESS_METHOD_LINKING = 3; // 0x3
-    field public static final int ACCESS_METHOD_NONE = 0; // 0x0
-    field public static final int ACCESS_METHOD_REFLECTION = 1; // 0x1
-  }
-
-  public final class VMStack {
-    method @Nullable @dalvik.annotation.optimization.FastNative public static dalvik.system.AnnotatedStackTraceElement[] getAnnotatedThreadStackTrace(Thread);
-  }
-
-  public final class ZygoteHooks {
-    method public static void gcAndFinalize();
-    method public static boolean isIndefiniteThreadSuspensionSafe();
-    method public static void onBeginPreload();
-    method public static void onEndPreload();
-    method public static void postForkChild(int, boolean, boolean, String);
-    method public static void postForkCommon();
-    method public static void postForkSystemServer(int);
-    method public static void preFork();
-    method public static void startZygoteNoThreadCreation();
-    method public static void stopZygoteNoThreadCreation();
-  }
-
-}
-
-package java.io {
-
-  public final class FileDescriptor {
-    method public int getInt$();
-    method public void setInt$(int);
-  }
-
-  public class FileInputStream extends java.io.InputStream {
-    ctor public FileInputStream(java.io.FileDescriptor, boolean);
-  }
-
-}
-
-package java.lang {
-
-  public class Thread implements java.lang.Runnable {
-    method public static java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionPreHandler();
-    method public static void setUncaughtExceptionPreHandler(java.lang.Thread.UncaughtExceptionHandler);
-  }
-
-}
-
-package java.net {
-
-  public class DatagramSocket implements java.io.Closeable {
-    method public java.io.FileDescriptor getFileDescriptor$();
-  }
-
-  public final class Inet4Address extends java.net.InetAddress {
-    field public static final java.net.InetAddress ALL;
-    field public static final java.net.InetAddress ANY;
-    field public static final java.net.InetAddress LOOPBACK;
-  }
-
-  public final class Inet6Address extends java.net.InetAddress {
-    field public static final java.net.InetAddress ANY;
-    field public static final java.net.InetAddress LOOPBACK;
-  }
-
-  public class InetAddress implements java.io.Serializable {
-    method public static void clearDnsCache();
-    method @NonNull public static java.net.InetAddress[] getAllByNameOnNet(@Nullable String, int) throws java.net.UnknownHostException;
-    method @NonNull public static java.net.InetAddress getByNameOnNet(@Nullable String, int) throws java.net.UnknownHostException;
-    method @Deprecated public static boolean isNumeric(String);
-    method @Deprecated public static java.net.InetAddress parseNumericAddress(String);
-  }
-
-  public class InetSocketAddress extends java.net.SocketAddress {
-    ctor public InetSocketAddress();
-  }
-
-  public class ServerSocket implements java.io.Closeable {
-    method public java.net.SocketImpl getImpl() throws java.net.SocketException;
-  }
-
-  public class Socket implements java.io.Closeable {
-    method public java.io.FileDescriptor getFileDescriptor$();
-  }
-
-  public abstract class SocketImpl implements java.net.SocketOptions {
-    method public java.io.FileDescriptor getFD$();
-  }
-
-}
-
-package java.nio {
-
-  public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable<java.nio.ByteBuffer> {
-    method public void setAccessible(boolean);
-  }
-
-  public class DirectByteBuffer extends java.nio.MappedByteBuffer {
-    ctor public DirectByteBuffer(int, long, java.io.FileDescriptor, Runnable, boolean);
-    method public final long address();
-    method public final void setAccessible(boolean);
-  }
-
-  public final class NIOAccess {
-    method public static Object getBaseArray(java.nio.Buffer);
-    method public static int getBaseArrayOffset(java.nio.Buffer);
-  }
-
-  public final class NioUtils {
-    method public static void freeDirectBuffer(java.nio.ByteBuffer);
-    method public static byte[] unsafeArray(java.nio.ByteBuffer);
-    method public static int unsafeArrayOffset(java.nio.ByteBuffer);
-  }
-
-}
-
-package java.security {
-
-  public abstract class Provider extends java.util.Properties {
-    method public void warmUpServiceProvision();
-  }
-
-  public abstract class Signature extends java.security.SignatureSpi {
-    method public java.security.SignatureSpi getCurrentSpi();
-  }
-
-}
-
-package java.text {
-
-  public abstract class DateFormat extends java.text.Format {
-    method public static final void set24HourTimePref(Boolean);
-  }
-
-}
-
-package java.util {
-
-  public class LinkedHashMap<K, V> extends java.util.HashMap<K,V> implements java.util.Map<K,V> {
-    method public java.util.Map.Entry<K,V> eldest();
-  }
-
-}
-
-package java.util.zip {
-
-  public class ZipEntry implements java.lang.Cloneable {
-    method public long getDataOffset();
-  }
-
-}
-
-package javax.crypto {
-
-  public class Cipher {
-    method public javax.crypto.CipherSpi getCurrentSpi();
-  }
-
-  public class Mac implements java.lang.Cloneable {
-    method public javax.crypto.MacSpi getCurrentSpi();
-  }
-
-}
-
-package javax.net.ssl {
-
-  public abstract class HttpsURLConnection extends java.net.HttpURLConnection {
-    method public static javax.net.ssl.HostnameVerifier getStrictHostnameVerifier();
-  }
-
-}
-
-package libcore.content.type {
-
-  public final class MimeMap {
-    method @NonNull public libcore.content.type.MimeMap.Builder buildUpon();
-    method @NonNull public static libcore.content.type.MimeMap.Builder builder();
-    method @NonNull public java.util.Set<java.lang.String> extensions();
-    method @NonNull public static libcore.content.type.MimeMap getDefault();
-    method @Nullable public String guessExtensionFromMimeType(@Nullable String);
-    method @Nullable public String guessMimeTypeFromExtension(@Nullable String);
-    method public boolean hasExtension(@Nullable String);
-    method public boolean hasMimeType(@Nullable String);
-    method @NonNull public java.util.Set<java.lang.String> mimeTypes();
-    method public static void setDefaultSupplier(@NonNull java.util.function.Supplier<libcore.content.type.MimeMap>);
-  }
-
-  public static final class MimeMap.Builder {
-    method @NonNull public libcore.content.type.MimeMap.Builder addMimeMapping(@NonNull String, @NonNull java.util.List<java.lang.String>);
-    method @NonNull public libcore.content.type.MimeMap build();
-  }
-
-}
-
-package libcore.io {
-
-  public class ForwardingOs implements libcore.io.Os {
-    ctor protected ForwardingOs(@NonNull libcore.io.Os);
-    method public boolean access(@Nullable String, int) throws android.system.ErrnoException;
-    method public java.io.FileDescriptor open(@Nullable String, int, int) throws android.system.ErrnoException;
-    method public void remove(@Nullable String) throws android.system.ErrnoException;
-    method public void rename(@Nullable String, @Nullable String) throws android.system.ErrnoException;
-    method @Nullable public android.system.StructStat stat(@Nullable String) throws android.system.ErrnoException;
-    method public void unlink(@Nullable String) throws android.system.ErrnoException;
-  }
-
-  public final class IoBridge {
-    method public static void closeAndSignalBlockedThreads(@NonNull java.io.FileDescriptor) throws java.io.IOException;
-    method @NonNull public static java.io.FileDescriptor open(@NonNull String, int) throws java.io.FileNotFoundException;
-    method public static int read(@NonNull java.io.FileDescriptor, @NonNull byte[], int, int) throws java.io.IOException;
-    method public static void write(@NonNull java.io.FileDescriptor, @NonNull byte[], int, int) throws java.io.IOException;
-  }
-
-  public final class IoUtils {
-    method public static int acquireRawFd(@NonNull java.io.FileDescriptor);
-    method public static void close(@Nullable java.io.FileDescriptor) throws java.io.IOException;
-    method public static void closeQuietly(@Nullable AutoCloseable);
-    method public static void closeQuietly(@Nullable java.io.FileDescriptor);
-    method public static void closeQuietly(@Nullable java.net.Socket);
-    method @NonNull public static byte[] readFileAsByteArray(@NonNull String) throws java.io.IOException;
-    method @NonNull public static String readFileAsString(@NonNull String) throws java.io.IOException;
-    method public static void setBlocking(@NonNull java.io.FileDescriptor, boolean) throws java.io.IOException;
-    method public static void setFdOwner(@NonNull java.io.FileDescriptor, @NonNull Object);
-  }
-
-  public final class Memory {
-    method public static void memmove(@NonNull Object, int, @NonNull Object, int, long);
-    method public static int peekInt(@NonNull byte[], int, @NonNull java.nio.ByteOrder);
-    method public static short peekShort(@NonNull byte[], int, @NonNull java.nio.ByteOrder);
-    method public static void pokeInt(@NonNull byte[], int, int, @NonNull java.nio.ByteOrder);
-    method public static void pokeLong(@NonNull byte[], int, long, @NonNull java.nio.ByteOrder);
-    method public static void pokeShort(@NonNull byte[], int, short, @NonNull java.nio.ByteOrder);
-  }
-
-  public interface Os {
-    method public static boolean compareAndSetDefault(libcore.io.Os, libcore.io.Os);
-    method public static libcore.io.Os getDefault();
-  }
-
-  public final class Streams {
-    method public static int copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream) throws java.io.IOException;
-    method public static void readFully(@NonNull java.io.InputStream, @NonNull byte[]) throws java.io.IOException;
-    method @NonNull public static byte[] readFully(@NonNull java.io.InputStream) throws java.io.IOException;
-    method @NonNull public static String readFully(@NonNull java.io.Reader) throws java.io.IOException;
-    method @NonNull public static byte[] readFullyNoClose(@NonNull java.io.InputStream) throws java.io.IOException;
-    method public static int readSingleByte(@NonNull java.io.InputStream) throws java.io.IOException;
-    method public static long skipByReading(@NonNull java.io.InputStream, long) throws java.io.IOException;
-    method public static void writeSingleByte(@NonNull java.io.OutputStream, int) throws java.io.IOException;
-  }
-
-}
-
-package libcore.net {
-
-  public class InetAddressUtils {
-    method public static boolean isNumericAddress(String);
-    method public static java.net.InetAddress parseNumericAddress(String);
-  }
-
-  public abstract class NetworkSecurityPolicy {
-    ctor public NetworkSecurityPolicy();
-    method public static libcore.net.NetworkSecurityPolicy getInstance();
-    method public abstract boolean isCertificateTransparencyVerificationRequired(String);
-    method public abstract boolean isCleartextTrafficPermitted();
-    method public abstract boolean isCleartextTrafficPermitted(String);
-    method public static void setInstance(libcore.net.NetworkSecurityPolicy);
-  }
-
-}
-
-package libcore.net.event {
-
-  public final class NetworkEventDispatcher {
-    method public void dispatchNetworkConfigurationChange();
-    method public static libcore.net.event.NetworkEventDispatcher getInstance();
-  }
-
-}
-
-package libcore.net.http {
-
-  public interface Dns {
-    method @NonNull public java.util.List<java.net.InetAddress> lookup(@Nullable String) throws java.net.UnknownHostException;
-  }
-
-  public class HttpURLConnectionFactory {
-    method @NonNull public static libcore.net.http.HttpURLConnectionFactory createInstance();
-    method public java.net.URLConnection openConnection(@NonNull java.net.URL, @NonNull javax.net.SocketFactory, @NonNull java.net.Proxy) throws java.io.IOException;
-    method public void setDns(@NonNull libcore.net.http.Dns);
-    method public void setNewConnectionPool(int, long, @NonNull java.util.concurrent.TimeUnit);
-  }
-
-}
-
-package libcore.util {
-
-  public final class EmptyArray {
-    field @NonNull public static final boolean[] BOOLEAN;
-    field @NonNull public static final byte[] BYTE;
-    field @NonNull public static final float[] FLOAT;
-    field @NonNull public static final int[] INT;
-    field @NonNull public static final long[] LONG;
-    field @NonNull public static final Object[] OBJECT;
-    field @NonNull public static final String[] STRING;
-  }
-
-  public final class FP16 {
-    method public static short ceil(short);
-    method public static int compare(short, short);
-    method public static boolean equals(short, short);
-    method public static short floor(short);
-    method public static boolean greater(short, short);
-    method public static boolean greaterEquals(short, short);
-    method public static boolean isInfinite(short);
-    method public static boolean isNaN(short);
-    method public static boolean isNormalized(short);
-    method public static boolean less(short, short);
-    method public static boolean lessEquals(short, short);
-    method public static short max(short, short);
-    method public static short min(short, short);
-    method public static short rint(short);
-    method public static float toFloat(short);
-    method public static short toHalf(float);
-    method public static String toHexString(short);
-    method public static short trunc(short);
-    field public static final short EPSILON = 5120; // 0x1400
-    field public static final int EXPONENT_BIAS = 15; // 0xf
-    field public static final int EXPONENT_SHIFT = 10; // 0xa
-    field public static final int EXPONENT_SIGNIFICAND_MASK = 32767; // 0x7fff
-    field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
-    field public static final int MAX_EXPONENT = 15; // 0xf
-    field public static final short MAX_VALUE = 31743; // 0x7bff
-    field public static final int MIN_EXPONENT = -14; // 0xfffffff2
-    field public static final short MIN_NORMAL = 1024; // 0x400
-    field public static final short MIN_VALUE = 1; // 0x1
-    field public static final short NEGATIVE_INFINITY = -1024; // 0xfffffc00
-    field public static final short NEGATIVE_ZERO = -32768; // 0xffff8000
-    field public static final short NaN = 32256; // 0x7e00
-    field public static final short POSITIVE_INFINITY = 31744; // 0x7c00
-    field public static final short POSITIVE_ZERO = 0; // 0x0
-    field public static final int SHIFTED_EXPONENT_MASK = 31; // 0x1f
-    field public static final int SIGNIFICAND_MASK = 1023; // 0x3ff
-    field public static final int SIGN_MASK = 32768; // 0x8000
-    field public static final int SIGN_SHIFT = 15; // 0xf
-    field public static final int SIZE = 16; // 0x10
-  }
-
-  public class HexEncoding {
-    method public static byte[] decode(String) throws java.lang.IllegalArgumentException;
-    method public static byte[] decode(String, boolean) throws java.lang.IllegalArgumentException;
-    method public static byte[] decode(char[]) throws java.lang.IllegalArgumentException;
-    method public static byte[] decode(char[], boolean) throws java.lang.IllegalArgumentException;
-    method public static char[] encode(byte[]);
-    method public static char[] encode(byte[], boolean);
-    method public static char[] encode(byte[], int, int);
-    method public static String encodeToString(byte, boolean);
-    method public static String encodeToString(byte[]);
-    method public static String encodeToString(byte[], boolean);
-  }
-
-  public class NativeAllocationRegistry {
-    ctor public NativeAllocationRegistry(@NonNull ClassLoader, long, long);
-    method public static void applyFreeFunction(long, long);
-    method public static libcore.util.NativeAllocationRegistry createMalloced(@NonNull ClassLoader, long, long);
-    method public static libcore.util.NativeAllocationRegistry createMalloced(@NonNull ClassLoader, long);
-    method public static libcore.util.NativeAllocationRegistry createNonmalloced(@NonNull ClassLoader, long, long);
-    method @NonNull public Runnable registerNativeAllocation(@NonNull Object, long);
-  }
-
-  public class SneakyThrow {
-    method public static void sneakyThrow(@NonNull Throwable);
-  }
-
-  public class XmlObjectFactory {
-    method @NonNull public static org.xml.sax.XMLReader newXMLReader();
-    method @NonNull public static org.xmlpull.v1.XmlPullParser newXmlPullParser();
-    method @NonNull public static org.xmlpull.v1.XmlSerializer newXmlSerializer();
-  }
-
-}
-
-package org.apache.harmony.dalvik.ddmc {
-
-  public class Chunk {
-    ctor public Chunk(int, byte[], int, int);
-    ctor public Chunk(int, java.nio.ByteBuffer);
-    field public int type;
-  }
-
-  public abstract class ChunkHandler {
-    ctor public ChunkHandler();
-    method public static org.apache.harmony.dalvik.ddmc.Chunk createFailChunk(int, String);
-    method public abstract org.apache.harmony.dalvik.ddmc.Chunk handleChunk(org.apache.harmony.dalvik.ddmc.Chunk);
-    method public static String name(int);
-    method public abstract void onConnected();
-    method public abstract void onDisconnected();
-    method public static int type(String);
-    method public static java.nio.ByteBuffer wrapChunk(org.apache.harmony.dalvik.ddmc.Chunk);
-    field public static final java.nio.ByteOrder CHUNK_ORDER;
-  }
-
-  public final class DdmServer {
-    method public static void registerHandler(int, org.apache.harmony.dalvik.ddmc.ChunkHandler);
-    method public static void registrationComplete();
-    method public static void sendChunk(org.apache.harmony.dalvik.ddmc.Chunk);
-    method public static org.apache.harmony.dalvik.ddmc.ChunkHandler unregisterHandler(int);
-  }
-
-  public final class DdmVmInternal {
-    method public static void setRecentAllocationsTrackingEnabled(boolean);
-    method public static void setThreadNotifyEnabled(boolean);
-  }
-
-}
-
-package org.json {
-
-  public class JSONObject {
-    method @NonNull public java.util.Set<java.lang.String> keySet();
-  }
-
-}
-
-package sun.misc {
-
-  public class Cleaner extends java.lang.ref.PhantomReference<java.lang.Object> {
-    method public void clean();
-    method public static sun.misc.Cleaner create(Object, Runnable);
-  }
-
-  public final class Unsafe {
-    method public int arrayBaseOffset(Class);
-    method public int arrayIndexScale(Class);
-    method @dalvik.annotation.optimization.FastNative public void copyMemory(long, long, long);
-    method @dalvik.annotation.optimization.FastNative public boolean getBoolean(Object, long);
-    method @dalvik.annotation.optimization.FastNative public byte getByte(Object, long);
-    method @dalvik.annotation.optimization.FastNative public byte getByte(long);
-    method @dalvik.annotation.optimization.FastNative public double getDouble(Object, long);
-    method @dalvik.annotation.optimization.FastNative public double getDouble(long);
-    method @dalvik.annotation.optimization.FastNative public float getFloat(Object, long);
-    method @dalvik.annotation.optimization.FastNative public float getFloat(long);
-    method @dalvik.annotation.optimization.FastNative public int getInt(Object, long);
-    method @dalvik.annotation.optimization.FastNative public int getInt(long);
-    method @dalvik.annotation.optimization.FastNative public long getLong(Object, long);
-    method @dalvik.annotation.optimization.FastNative public long getLong(long);
-    method @dalvik.annotation.optimization.FastNative public Object getObject(Object, long);
-    method public static sun.misc.Unsafe getUnsafe();
-    method public long objectFieldOffset(java.lang.reflect.Field);
-    method @dalvik.annotation.optimization.FastNative public void putBoolean(Object, long, boolean);
-    method @dalvik.annotation.optimization.FastNative public void putByte(Object, long, byte);
-    method @dalvik.annotation.optimization.FastNative public void putByte(long, byte);
-    method @dalvik.annotation.optimization.FastNative public void putDouble(Object, long, double);
-    method @dalvik.annotation.optimization.FastNative public void putDouble(long, double);
-    method @dalvik.annotation.optimization.FastNative public void putFloat(Object, long, float);
-    method @dalvik.annotation.optimization.FastNative public void putFloat(long, float);
-    method @dalvik.annotation.optimization.FastNative public void putInt(Object, long, int);
-    method @dalvik.annotation.optimization.FastNative public void putInt(long, int);
-    method @dalvik.annotation.optimization.FastNative public void putLong(Object, long, long);
-    method @dalvik.annotation.optimization.FastNative public void putLong(long, long);
-    method @dalvik.annotation.optimization.FastNative public void putObject(Object, long, Object);
-  }
-
-}
-
-package sun.security.jca {
-
-  public class Providers {
-    method public static Object startJarVerification();
-    method public static void stopJarVerification(Object);
-  }
-
-}
-
-package sun.security.pkcs {
-
-  public class PKCS7 {
-    ctor public PKCS7(java.io.InputStream) throws java.io.IOException, sun.security.pkcs.ParsingException;
-    ctor public PKCS7(byte[]) throws sun.security.pkcs.ParsingException;
-    method public java.security.cert.X509Certificate[] getCertificates();
-    method public sun.security.pkcs.SignerInfo[] getSignerInfos();
-    method public sun.security.pkcs.SignerInfo verify(sun.security.pkcs.SignerInfo, java.io.InputStream) throws java.io.IOException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
-    method public sun.security.pkcs.SignerInfo[] verify(byte[]) throws java.security.NoSuchAlgorithmException, java.security.SignatureException;
-  }
-
-  public class ParsingException extends java.io.IOException {
-  }
-
-  public class SignerInfo {
-    ctor public SignerInfo();
-    method public java.util.ArrayList<java.security.cert.X509Certificate> getCertificateChain(sun.security.pkcs.PKCS7) throws java.io.IOException;
-  }
-
-}
-
-package sun.security.util {
-
-  public final class ObjectIdentifier implements java.io.Serializable {
-    ctor public ObjectIdentifier(String) throws java.io.IOException;
-  }
-
-}
-
-package sun.security.x509 {
-
-  public class AlgorithmId implements java.io.Serializable {
-    ctor public AlgorithmId(sun.security.util.ObjectIdentifier);
-    method public String getName();
-  }
-
-}
-
diff --git a/mmodules/core_platform_api/api/legacy_platform/last-incompatibilities.txt b/mmodules/core_platform_api/api/legacy_platform/last-incompatibilities.txt
deleted file mode 100644
index e69de29..0000000
--- a/mmodules/core_platform_api/api/legacy_platform/last-incompatibilities.txt
+++ /dev/null
diff --git a/mmodules/core_platform_api/api/legacy_platform/last-removed.txt b/mmodules/core_platform_api/api/legacy_platform/last-removed.txt
deleted file mode 100644
index e69de29..0000000
--- a/mmodules/core_platform_api/api/legacy_platform/last-removed.txt
+++ /dev/null
diff --git a/mmodules/core_platform_api/api/legacy_platform/removed.txt b/mmodules/core_platform_api/api/legacy_platform/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/mmodules/core_platform_api/api/legacy_platform/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/mmodules/core_platform_api/api/stable_platform/current.txt b/mmodules/core_platform_api/api/stable_platform/current.txt
deleted file mode 100644
index 15741a7..0000000
--- a/mmodules/core_platform_api/api/stable_platform/current.txt
+++ /dev/null
@@ -1,865 +0,0 @@
-// Signature format: 2.0
-package android.compat {
-
-  public final class Compatibility {
-    method public static void clearBehaviorChangeDelegate();
-    method public static void clearOverrides();
-    method public static boolean isChangeEnabled(long);
-    method public static void reportUnconditionalChange(long);
-    method public static void setBehaviorChangeDelegate(android.compat.Compatibility.BehaviorChangeDelegate);
-    method public static void setOverrides(android.compat.Compatibility.ChangeConfig);
-  }
-
-  public static interface Compatibility.BehaviorChangeDelegate {
-    method public default boolean isChangeEnabled(long);
-    method public default void onChangeReported(long);
-  }
-
-  public static final class Compatibility.ChangeConfig {
-    ctor public Compatibility.ChangeConfig(@NonNull java.util.Set<java.lang.Long>, @NonNull java.util.Set<java.lang.Long>);
-    method @NonNull public long[] getDisabledChangesArray();
-    method @NonNull public java.util.Set<java.lang.Long> getDisabledSet();
-    method @NonNull public long[] getEnabledChangesArray();
-    method @NonNull public java.util.Set<java.lang.Long> getEnabledSet();
-    method public boolean isEmpty();
-    method public boolean isForceDisabled(long);
-    method public boolean isForceEnabled(long);
-  }
-
-}
-
-package android.system {
-
-  public final class NetlinkSocketAddress extends java.net.SocketAddress {
-    ctor public NetlinkSocketAddress(int, int);
-    method public int getGroupsMask();
-    method public int getPortId();
-  }
-
-  public final class Os {
-    method @Nullable public static android.system.StructCapUserData[] capget(@NonNull android.system.StructCapUserHeader) throws android.system.ErrnoException;
-    method public static void capset(@NonNull android.system.StructCapUserHeader, @NonNull android.system.StructCapUserData[]) throws android.system.ErrnoException;
-    method public static int getpgid(int) throws android.system.ErrnoException;
-    method @Nullable public static android.system.StructRlimit getrlimit(int) throws android.system.ErrnoException;
-    method public static int getsockoptInt(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
-    method @Nullable public static android.system.StructLinger getsockoptLinger(@NonNull java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
-    method public static int ioctlInt(@NonNull java.io.FileDescriptor, int) throws android.system.ErrnoException;
-    method @Nullable public static java.io.FileDescriptor[] pipe2(int) throws android.system.ErrnoException;
-    method @Nullable public static String realpath(@Nullable String) throws android.system.ErrnoException;
-    method public static void setpgid(int, int) throws android.system.ErrnoException;
-    method public static void setregid(int, int) throws android.system.ErrnoException;
-    method public static void setreuid(int, int) throws android.system.ErrnoException;
-    method public static void setsockoptIfreq(@NonNull java.io.FileDescriptor, int, int, @Nullable String) throws android.system.ErrnoException;
-    method public static void setsockoptLinger(@NonNull java.io.FileDescriptor, int, int, @NonNull android.system.StructLinger) throws android.system.ErrnoException;
-    method public static long splice(@NonNull java.io.FileDescriptor, @Nullable android.system.Int64Ref, @NonNull java.io.FileDescriptor, @Nullable android.system.Int64Ref, long, int) throws android.system.ErrnoException;
-    method public static void unlink(@Nullable String) throws android.system.ErrnoException;
-  }
-
-  public final class OsConstants {
-    method public static int CAP_TO_INDEX(int);
-    method public static int CAP_TO_MASK(int);
-    field public static final int ARPHRD_LOOPBACK;
-    field public static final int EUSERS;
-    field public static final int MAP_POPULATE;
-    field public static final int O_DIRECT;
-    field public static final int PR_CAP_AMBIENT;
-    field public static final int PR_CAP_AMBIENT_RAISE;
-    field public static final int RLIMIT_NOFILE;
-    field public static final int RTMGRP_IPV4_IFADDR;
-    field public static final int SPLICE_F_MORE;
-    field public static final int SPLICE_F_MOVE;
-    field public static final int TIOCOUTQ;
-    field public static final int UDP_ENCAP;
-    field public static final int UDP_ENCAP_ESPINUDP;
-    field public static final int XATTR_CREATE;
-    field public static final int XATTR_REPLACE;
-    field public static final int _LINUX_CAPABILITY_VERSION_3;
-  }
-
-  public final class PacketSocketAddress extends java.net.SocketAddress {
-    ctor public PacketSocketAddress(int, int, byte[]);
-  }
-
-  public final class StructCapUserData {
-    ctor public StructCapUserData(int, int, int);
-    field public final int effective;
-    field public final int inheritable;
-    field public final int permitted;
-  }
-
-  public final class StructCapUserHeader {
-    ctor public StructCapUserHeader(int, int);
-  }
-
-  public final class StructLinger {
-    ctor public StructLinger(int, int);
-    method public boolean isOn();
-    field public final int l_linger;
-  }
-
-  public final class StructRlimit {
-    field public final long rlim_cur;
-  }
-
-  public final class UnixSocketAddress extends java.net.SocketAddress {
-    method public static android.system.UnixSocketAddress createFileSystem(String);
-  }
-
-  public final class VmSocketAddress extends java.net.SocketAddress {
-    ctor public VmSocketAddress(int, int);
-    method public int getSvmCid();
-    method public int getSvmPort();
-  }
-
-}
-
-package com.android.okhttp.internalandroidapi {
-
-  public final class AndroidResponseCacheAdapter {
-    ctor public AndroidResponseCacheAdapter(@NonNull com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder);
-    method public void close() throws java.io.IOException;
-    method public void delete() throws java.io.IOException;
-    method public void flush() throws java.io.IOException;
-    method @Nullable public java.net.CacheResponse get(@NonNull java.net.URI, @NonNull String, @Nullable java.util.Map<java.lang.String,java.util.List<java.lang.String>>) throws java.io.IOException;
-    method @NonNull public com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder getCacheHolder();
-    method public int getHitCount();
-    method public long getMaxSize();
-    method public int getNetworkCount();
-    method public int getRequestCount();
-    method public long getSize() throws java.io.IOException;
-    method @Nullable public java.net.CacheRequest put(@NonNull java.net.URI, @NonNull java.net.URLConnection) throws java.io.IOException;
-  }
-
-  public interface HasCacheHolder {
-    method @NonNull public com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder getCacheHolder();
-  }
-
-  public static final class HasCacheHolder.CacheHolder {
-    method @NonNull public static com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder create(@NonNull java.io.File, long);
-    method public boolean isEquivalent(@NonNull java.io.File, long);
-  }
-
-}
-
-package dalvik.annotation.codegen {
-
-  @java.lang.annotation.Repeatable(CovariantReturnType.CovariantReturnTypes.class) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public @interface CovariantReturnType {
-    method public abstract int presentAfter();
-    method public abstract Class<?> returnType();
-  }
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD}) public static @interface CovariantReturnType.CovariantReturnTypes {
-    method public abstract dalvik.annotation.codegen.CovariantReturnType[] value();
-  }
-
-}
-
-package dalvik.annotation.optimization {
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface CriticalNative {
-  }
-
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface FastNative {
-  }
-
-}
-
-package dalvik.system {
-
-  public final class AnnotatedStackTraceElement {
-    method @Nullable public Object getBlockedOn();
-    method @Nullable public Object[] getHeldLocks();
-    method @NonNull public StackTraceElement getStackTraceElement();
-  }
-
-  public class AppSpecializationHooks {
-    method public static void handleCompatChangesBeforeBindingApplication();
-  }
-
-  public class BaseDexClassLoader extends java.lang.ClassLoader {
-    method public void addDexPath(@Nullable String);
-    method public void addNativePath(@NonNull java.util.Collection<java.lang.String>);
-    method @NonNull public String getLdLibraryPath();
-    method public void reportClassLoaderChain();
-    method public static void setReporter(@Nullable dalvik.system.BaseDexClassLoader.Reporter);
-  }
-
-  public static interface BaseDexClassLoader.Reporter {
-    method public void report(@NonNull java.util.Map<java.lang.String,java.lang.String>);
-  }
-
-  public final class BlockGuard {
-    method @NonNull public static dalvik.system.BlockGuard.Policy getThreadPolicy();
-    method @NonNull public static dalvik.system.BlockGuard.VmPolicy getVmPolicy();
-    method public static void setThreadPolicy(@NonNull dalvik.system.BlockGuard.Policy);
-    method public static void setVmPolicy(@NonNull dalvik.system.BlockGuard.VmPolicy);
-    field public static final dalvik.system.BlockGuard.Policy LAX_POLICY;
-    field public static final dalvik.system.BlockGuard.VmPolicy LAX_VM_POLICY;
-  }
-
-  public static interface BlockGuard.Policy {
-    method public int getPolicyMask();
-    method public void onReadFromDisk();
-    method public void onUnbufferedIO();
-    method public void onWriteToDisk();
-  }
-
-  public static interface BlockGuard.VmPolicy {
-    method public void onPathAccess(@NonNull String);
-  }
-
-  public final class CloseGuard {
-    method public void close();
-    method public static dalvik.system.CloseGuard get();
-    method public static dalvik.system.CloseGuard.Reporter getReporter();
-    method public void open(String);
-    method public void openWithCallSite(String, String);
-    method public static void setEnabled(boolean);
-    method public static void setReporter(dalvik.system.CloseGuard.Reporter);
-    method public void warnIfOpen();
-  }
-
-  public static interface CloseGuard.Reporter {
-    method public void report(String, Throwable);
-    method public default void report(String);
-  }
-
-  public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
-    ctor public DelegateLastClassLoader(String, String, ClassLoader, ClassLoader[]);
-  }
-
-  @Deprecated public final class DexFile {
-    method @Deprecated @NonNull public static dalvik.system.DexFile.OptimizationInfo getDexFileOptimizationInfo(@NonNull String, @NonNull String) throws java.io.FileNotFoundException;
-    method @Deprecated @Nullable public static String[] getDexFileOutputPaths(@NonNull String, @NonNull String) throws java.io.FileNotFoundException;
-    method @Deprecated public static int getDexOptNeeded(@NonNull String, @NonNull String, @NonNull String, @Nullable String, boolean, boolean) throws java.io.FileNotFoundException, java.io.IOException;
-    method @Deprecated @NonNull public static String getSafeModeCompilerFilter(@NonNull String);
-    method @Deprecated public static boolean isProfileGuidedCompilerFilter(@NonNull String);
-    method @Deprecated public static boolean isValidCompilerFilter(@NonNull String);
-    field @Deprecated public static final int DEX2OAT_FOR_FILTER = 3; // 0x3
-    field @Deprecated public static final int NO_DEXOPT_NEEDED = 0; // 0x0
-  }
-
-  @Deprecated public static final class DexFile.OptimizationInfo {
-    method @Deprecated @NonNull public String getReason();
-    method @Deprecated @NonNull public String getStatus();
-  }
-
-  public class PathClassLoader extends dalvik.system.BaseDexClassLoader {
-    ctor public PathClassLoader(@NonNull String, @Nullable String, @Nullable ClassLoader, @Nullable ClassLoader[]);
-  }
-
-  public final class RuntimeHooks {
-    method public static void setTimeZoneIdSupplier(@NonNull java.util.function.Supplier<java.lang.String>);
-    method public static void setUncaughtExceptionPreHandler(@Nullable java.lang.Thread.UncaughtExceptionHandler);
-  }
-
-  public abstract class SocketTagger {
-    ctor public SocketTagger();
-    method public static dalvik.system.SocketTagger get();
-    method public static void set(dalvik.system.SocketTagger);
-    method public abstract void tag(java.io.FileDescriptor) throws java.net.SocketException;
-    method public final void tag(java.net.Socket) throws java.net.SocketException;
-    method public final void tag(java.net.DatagramSocket) throws java.net.SocketException;
-    method public abstract void untag(java.io.FileDescriptor) throws java.net.SocketException;
-    method public final void untag(java.net.Socket) throws java.net.SocketException;
-    method public final void untag(java.net.DatagramSocket) throws java.net.SocketException;
-  }
-
-  public final class VMDebug {
-    method public static void attachAgent(String, ClassLoader) throws java.io.IOException;
-    method public static long countInstancesOfClass(Class, boolean);
-    method public static long[] countInstancesOfClasses(Class[], boolean);
-    method public static void dumpHprofData(String) throws java.io.IOException;
-    method public static void dumpHprofData(String, java.io.FileDescriptor) throws java.io.IOException;
-    method public static void dumpHprofDataDdms();
-    method public static void dumpReferenceTables();
-    method public static int getAllocCount(int);
-    method @dalvik.annotation.optimization.FastNative public static int getLoadedClassCount();
-    method public static int getMethodTracingMode();
-    method public static String getRuntimeStat(String);
-    method public static java.util.Map<java.lang.String,java.lang.String> getRuntimeStats();
-    method public static String[] getVmFeatureList();
-    method @dalvik.annotation.optimization.FastNative public static boolean isDebuggerConnected();
-    method @dalvik.annotation.optimization.FastNative public static boolean isDebuggingEnabled();
-    method @dalvik.annotation.optimization.FastNative public static long lastDebuggerActivity();
-    method @dalvik.annotation.optimization.FastNative public static void printLoadedClasses(int);
-    method public static void resetAllocCount(int);
-    method public static void setAllocTrackerStackDepth(int);
-    method public static void startAllocCounting();
-    method public static void startMethodTracing(String, int, int, boolean, int);
-    method public static void startMethodTracing(String, java.io.FileDescriptor, int, int, boolean, int, boolean);
-    method public static void startMethodTracingDdms(int, int, boolean, int);
-    method public static void stopAllocCounting();
-    method public static void stopMethodTracing();
-    method @dalvik.annotation.optimization.FastNative public static long threadCpuTimeNanos();
-    field public static final int KIND_ALL_COUNTS = -1; // 0xffffffff
-    field public static final int KIND_GLOBAL_ALLOCATED_BYTES = 2; // 0x2
-    field public static final int KIND_GLOBAL_ALLOCATED_OBJECTS = 1; // 0x1
-    field public static final int KIND_GLOBAL_CLASS_INIT_COUNT = 32; // 0x20
-    field public static final int KIND_GLOBAL_CLASS_INIT_TIME = 64; // 0x40
-    field public static final int KIND_GLOBAL_FREED_BYTES = 8; // 0x8
-    field public static final int KIND_GLOBAL_FREED_OBJECTS = 4; // 0x4
-    field public static final int KIND_GLOBAL_GC_INVOCATIONS = 16; // 0x10
-    field public static final int KIND_THREAD_ALLOCATED_BYTES = 131072; // 0x20000
-    field public static final int KIND_THREAD_ALLOCATED_OBJECTS = 65536; // 0x10000
-    field public static final int KIND_THREAD_GC_INVOCATIONS = 1048576; // 0x100000
-    field public static final int TRACE_COUNT_ALLOCS = 1; // 0x1
-  }
-
-  public final class VMRuntime {
-    method @dalvik.annotation.optimization.FastNative public long addressOf(Object);
-    method public static void bootCompleted();
-    method public void clampGrowthLimit();
-    method public void clearGrowthLimit();
-    method public static String getCurrentInstructionSet();
-    method public static String getInstructionSet(String);
-    method public static dalvik.system.VMRuntime getRuntime();
-    method public int getTargetSdkVersion();
-    method @dalvik.annotation.optimization.FastNative public boolean is64Bit();
-    method public static boolean is64BitAbi(String);
-    method public static boolean is64BitInstructionSet(String);
-    method @dalvik.annotation.optimization.FastNative public boolean isCheckJniEnabled();
-    method @dalvik.annotation.optimization.FastNative public boolean isNativeDebuggable();
-    method public static boolean isValidClassLoaderContext(String);
-    method @dalvik.annotation.optimization.FastNative public Object newNonMovableArray(Class<?>, int);
-    method @dalvik.annotation.optimization.FastNative public Object newUnpaddedArray(Class<?>, int);
-    method public void notifyStartupCompleted();
-    method public void preloadDexCaches();
-    method public static void registerAppInfo(String, String, String, String[], int);
-    method public void registerNativeAllocation(long);
-    method @Deprecated public void registerNativeAllocation(int);
-    method public void registerNativeFree(long);
-    method @Deprecated public void registerNativeFree(int);
-    method public static void registerSensitiveThread();
-    method public void requestConcurrentGC();
-    method public static void resetJitCounters();
-    method public static void setDedupeHiddenApiWarnings(boolean);
-    method public void setDisabledCompatChanges(long[]);
-    method public void setHiddenApiAccessLogSamplingRate(int);
-    method public void setHiddenApiExemptions(String[]);
-    method public static void setHiddenApiUsageLogger(dalvik.system.VMRuntime.HiddenApiUsageLogger);
-    method public static void setNonSdkApiUsageConsumer(java.util.function.Consumer<java.lang.String>);
-    method public static void setProcessDataDirectory(String);
-    method public static void setProcessPackageName(String);
-    method public void setTargetSdkVersion(int);
-    method public void updateProcessState(int);
-    method public String vmInstructionSet();
-    method public String vmLibrary();
-    field public static final int CODE_PATH_TYPE_PRIMARY_APK = 1; // 0x1
-    field public static final int CODE_PATH_TYPE_SECONDARY_DEX = 4; // 0x4
-    field public static final int CODE_PATH_TYPE_SPLIT_APK = 2; // 0x2
-    field public static final int SDK_VERSION_CUR_DEVELOPMENT = 10000; // 0x2710
-  }
-
-  public static interface VMRuntime.HiddenApiUsageLogger {
-    method public void hiddenApiUsed(int, String, String, int, boolean);
-    field public static final int ACCESS_METHOD_JNI = 2; // 0x2
-    field public static final int ACCESS_METHOD_LINKING = 3; // 0x3
-    field public static final int ACCESS_METHOD_NONE = 0; // 0x0
-    field public static final int ACCESS_METHOD_REFLECTION = 1; // 0x1
-  }
-
-  public final class VMStack {
-    method @Nullable @dalvik.annotation.optimization.FastNative public static dalvik.system.AnnotatedStackTraceElement[] getAnnotatedThreadStackTrace(Thread);
-  }
-
-  public final class ZygoteHooks {
-    method public static void gcAndFinalize();
-    method public static boolean isIndefiniteThreadSuspensionSafe();
-    method public static void onBeginPreload();
-    method public static void onEndPreload();
-    method public static void postForkChild(int, boolean, boolean, String);
-    method public static void postForkCommon();
-    method public static void postForkSystemServer(int);
-    method public static void preFork();
-    method public static void startZygoteNoThreadCreation();
-    method public static void stopZygoteNoThreadCreation();
-  }
-
-}
-
-package java.io {
-
-  public final class FileDescriptor {
-    method public int getInt$();
-    method public void setInt$(int);
-  }
-
-  public class FileInputStream extends java.io.InputStream {
-    ctor public FileInputStream(java.io.FileDescriptor, boolean);
-  }
-
-}
-
-package java.lang {
-
-  public class Thread implements java.lang.Runnable {
-    method public static java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionPreHandler();
-    method public static void setUncaughtExceptionPreHandler(java.lang.Thread.UncaughtExceptionHandler);
-  }
-
-}
-
-package java.net {
-
-  public class DatagramSocket implements java.io.Closeable {
-    method public java.io.FileDescriptor getFileDescriptor$();
-  }
-
-  public final class Inet4Address extends java.net.InetAddress {
-    field public static final java.net.InetAddress ALL;
-    field public static final java.net.InetAddress ANY;
-    field public static final java.net.InetAddress LOOPBACK;
-  }
-
-  public final class Inet6Address extends java.net.InetAddress {
-    field public static final java.net.InetAddress ANY;
-    field public static final java.net.InetAddress LOOPBACK;
-  }
-
-  public class InetAddress implements java.io.Serializable {
-    method public static void clearDnsCache();
-    method @NonNull public static java.net.InetAddress[] getAllByNameOnNet(@Nullable String, int) throws java.net.UnknownHostException;
-    method @NonNull public static java.net.InetAddress getByNameOnNet(@Nullable String, int) throws java.net.UnknownHostException;
-    method @Deprecated public static boolean isNumeric(String);
-    method @Deprecated public static java.net.InetAddress parseNumericAddress(String);
-  }
-
-  public class InetSocketAddress extends java.net.SocketAddress {
-    ctor public InetSocketAddress();
-  }
-
-  public class ServerSocket implements java.io.Closeable {
-    method public java.net.SocketImpl getImpl() throws java.net.SocketException;
-  }
-
-  public class Socket implements java.io.Closeable {
-    method public java.io.FileDescriptor getFileDescriptor$();
-  }
-
-  public abstract class SocketImpl implements java.net.SocketOptions {
-    method public java.io.FileDescriptor getFD$();
-  }
-
-}
-
-package java.nio {
-
-  public abstract class ByteBuffer extends java.nio.Buffer implements java.lang.Comparable<java.nio.ByteBuffer> {
-    method public void setAccessible(boolean);
-  }
-
-  public class DirectByteBuffer extends java.nio.MappedByteBuffer {
-    ctor public DirectByteBuffer(int, long, java.io.FileDescriptor, Runnable, boolean);
-    method public final long address();
-    method public final void setAccessible(boolean);
-  }
-
-  public final class NIOAccess {
-    method public static Object getBaseArray(java.nio.Buffer);
-    method public static int getBaseArrayOffset(java.nio.Buffer);
-  }
-
-  public final class NioUtils {
-    method public static void freeDirectBuffer(java.nio.ByteBuffer);
-    method public static byte[] unsafeArray(java.nio.ByteBuffer);
-    method public static int unsafeArrayOffset(java.nio.ByteBuffer);
-  }
-
-}
-
-package java.security {
-
-  public abstract class Provider extends java.util.Properties {
-    method public void warmUpServiceProvision();
-  }
-
-  public abstract class Signature extends java.security.SignatureSpi {
-    method public java.security.SignatureSpi getCurrentSpi();
-  }
-
-}
-
-package java.text {
-
-  public abstract class DateFormat extends java.text.Format {
-    method public static final void set24HourTimePref(Boolean);
-  }
-
-}
-
-package java.util {
-
-  public class LinkedHashMap<K, V> extends java.util.HashMap<K,V> implements java.util.Map<K,V> {
-    method public java.util.Map.Entry<K,V> eldest();
-  }
-
-}
-
-package java.util.zip {
-
-  public class ZipEntry implements java.lang.Cloneable {
-    method public long getDataOffset();
-  }
-
-}
-
-package javax.crypto {
-
-  public class Cipher {
-    method public javax.crypto.CipherSpi getCurrentSpi();
-  }
-
-  public class Mac implements java.lang.Cloneable {
-    method public javax.crypto.MacSpi getCurrentSpi();
-  }
-
-}
-
-package javax.net.ssl {
-
-  public abstract class HttpsURLConnection extends java.net.HttpURLConnection {
-    method public static javax.net.ssl.HostnameVerifier getStrictHostnameVerifier();
-  }
-
-}
-
-package libcore.content.type {
-
-  public final class MimeMap {
-    method @NonNull public libcore.content.type.MimeMap.Builder buildUpon();
-    method @NonNull public static libcore.content.type.MimeMap.Builder builder();
-    method @NonNull public java.util.Set<java.lang.String> extensions();
-    method @NonNull public static libcore.content.type.MimeMap getDefault();
-    method @Nullable public String guessExtensionFromMimeType(@Nullable String);
-    method @Nullable public String guessMimeTypeFromExtension(@Nullable String);
-    method public boolean hasExtension(@Nullable String);
-    method public boolean hasMimeType(@Nullable String);
-    method @NonNull public java.util.Set<java.lang.String> mimeTypes();
-    method public static void setDefaultSupplier(@NonNull java.util.function.Supplier<libcore.content.type.MimeMap>);
-  }
-
-  public static final class MimeMap.Builder {
-    method @NonNull public libcore.content.type.MimeMap.Builder addMimeMapping(@NonNull String, @NonNull java.util.List<java.lang.String>);
-    method @NonNull public libcore.content.type.MimeMap build();
-  }
-
-}
-
-package libcore.io {
-
-  public class ForwardingOs implements libcore.io.Os {
-    ctor protected ForwardingOs(@NonNull libcore.io.Os);
-    method public boolean access(@Nullable String, int) throws android.system.ErrnoException;
-    method public java.io.FileDescriptor open(@Nullable String, int, int) throws android.system.ErrnoException;
-    method public void remove(@Nullable String) throws android.system.ErrnoException;
-    method public void rename(@Nullable String, @Nullable String) throws android.system.ErrnoException;
-    method @Nullable public android.system.StructStat stat(@Nullable String) throws android.system.ErrnoException;
-    method public void unlink(@Nullable String) throws android.system.ErrnoException;
-  }
-
-  public final class IoBridge {
-    method public static void closeAndSignalBlockedThreads(@NonNull java.io.FileDescriptor) throws java.io.IOException;
-    method @NonNull public static java.io.FileDescriptor open(@NonNull String, int) throws java.io.FileNotFoundException;
-    method public static int read(@NonNull java.io.FileDescriptor, @NonNull byte[], int, int) throws java.io.IOException;
-    method public static void write(@NonNull java.io.FileDescriptor, @NonNull byte[], int, int) throws java.io.IOException;
-  }
-
-  public final class IoUtils {
-    method public static int acquireRawFd(@NonNull java.io.FileDescriptor);
-    method public static void close(@Nullable java.io.FileDescriptor) throws java.io.IOException;
-    method public static void closeQuietly(@Nullable AutoCloseable);
-    method public static void closeQuietly(@Nullable java.io.FileDescriptor);
-    method public static void closeQuietly(@Nullable java.net.Socket);
-    method @NonNull public static byte[] readFileAsByteArray(@NonNull String) throws java.io.IOException;
-    method @NonNull public static String readFileAsString(@NonNull String) throws java.io.IOException;
-    method public static void setBlocking(@NonNull java.io.FileDescriptor, boolean) throws java.io.IOException;
-    method public static void setFdOwner(@NonNull java.io.FileDescriptor, @NonNull Object);
-  }
-
-  public final class Memory {
-    method public static void memmove(@NonNull Object, int, @NonNull Object, int, long);
-    method public static int peekInt(@NonNull byte[], int, @NonNull java.nio.ByteOrder);
-    method public static short peekShort(@NonNull byte[], int, @NonNull java.nio.ByteOrder);
-    method public static void pokeInt(@NonNull byte[], int, int, @NonNull java.nio.ByteOrder);
-    method public static void pokeLong(@NonNull byte[], int, long, @NonNull java.nio.ByteOrder);
-    method public static void pokeShort(@NonNull byte[], int, short, @NonNull java.nio.ByteOrder);
-  }
-
-  public interface Os {
-    method public static boolean compareAndSetDefault(libcore.io.Os, libcore.io.Os);
-    method public static libcore.io.Os getDefault();
-  }
-
-  public final class Streams {
-    method public static int copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream) throws java.io.IOException;
-    method public static void readFully(@NonNull java.io.InputStream, @NonNull byte[]) throws java.io.IOException;
-    method @NonNull public static byte[] readFully(@NonNull java.io.InputStream) throws java.io.IOException;
-    method @NonNull public static String readFully(@NonNull java.io.Reader) throws java.io.IOException;
-    method @NonNull public static byte[] readFullyNoClose(@NonNull java.io.InputStream) throws java.io.IOException;
-    method public static int readSingleByte(@NonNull java.io.InputStream) throws java.io.IOException;
-    method public static long skipByReading(@NonNull java.io.InputStream, long) throws java.io.IOException;
-    method public static void writeSingleByte(@NonNull java.io.OutputStream, int) throws java.io.IOException;
-  }
-
-}
-
-package libcore.net {
-
-  public class InetAddressUtils {
-    method public static boolean isNumericAddress(String);
-    method public static java.net.InetAddress parseNumericAddress(String);
-  }
-
-  public abstract class NetworkSecurityPolicy {
-    ctor public NetworkSecurityPolicy();
-    method public static libcore.net.NetworkSecurityPolicy getInstance();
-    method public abstract boolean isCertificateTransparencyVerificationRequired(String);
-    method public abstract boolean isCleartextTrafficPermitted();
-    method public abstract boolean isCleartextTrafficPermitted(String);
-    method public static void setInstance(libcore.net.NetworkSecurityPolicy);
-  }
-
-}
-
-package libcore.net.event {
-
-  public final class NetworkEventDispatcher {
-    method public void dispatchNetworkConfigurationChange();
-    method public static libcore.net.event.NetworkEventDispatcher getInstance();
-  }
-
-}
-
-package libcore.net.http {
-
-  public interface Dns {
-    method @NonNull public java.util.List<java.net.InetAddress> lookup(@Nullable String) throws java.net.UnknownHostException;
-  }
-
-  public class HttpURLConnectionFactory {
-    method @NonNull public static libcore.net.http.HttpURLConnectionFactory createInstance();
-    method public java.net.URLConnection openConnection(@NonNull java.net.URL, @NonNull javax.net.SocketFactory, @NonNull java.net.Proxy) throws java.io.IOException;
-    method public void setDns(@NonNull libcore.net.http.Dns);
-    method public void setNewConnectionPool(int, long, @NonNull java.util.concurrent.TimeUnit);
-  }
-
-}
-
-package libcore.util {
-
-  public final class EmptyArray {
-    field @NonNull public static final boolean[] BOOLEAN;
-    field @NonNull public static final byte[] BYTE;
-    field @NonNull public static final float[] FLOAT;
-    field @NonNull public static final int[] INT;
-    field @NonNull public static final long[] LONG;
-    field @NonNull public static final Object[] OBJECT;
-    field @NonNull public static final String[] STRING;
-  }
-
-  public final class FP16 {
-    method public static short ceil(short);
-    method public static int compare(short, short);
-    method public static boolean equals(short, short);
-    method public static short floor(short);
-    method public static boolean greater(short, short);
-    method public static boolean greaterEquals(short, short);
-    method public static boolean isInfinite(short);
-    method public static boolean isNaN(short);
-    method public static boolean isNormalized(short);
-    method public static boolean less(short, short);
-    method public static boolean lessEquals(short, short);
-    method public static short max(short, short);
-    method public static short min(short, short);
-    method public static short rint(short);
-    method public static float toFloat(short);
-    method public static short toHalf(float);
-    method public static String toHexString(short);
-    method public static short trunc(short);
-    field public static final short EPSILON = 5120; // 0x1400
-    field public static final int EXPONENT_BIAS = 15; // 0xf
-    field public static final int EXPONENT_SHIFT = 10; // 0xa
-    field public static final int EXPONENT_SIGNIFICAND_MASK = 32767; // 0x7fff
-    field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
-    field public static final int MAX_EXPONENT = 15; // 0xf
-    field public static final short MAX_VALUE = 31743; // 0x7bff
-    field public static final int MIN_EXPONENT = -14; // 0xfffffff2
-    field public static final short MIN_NORMAL = 1024; // 0x400
-    field public static final short MIN_VALUE = 1; // 0x1
-    field public static final short NEGATIVE_INFINITY = -1024; // 0xfffffc00
-    field public static final short NEGATIVE_ZERO = -32768; // 0xffff8000
-    field public static final short NaN = 32256; // 0x7e00
-    field public static final short POSITIVE_INFINITY = 31744; // 0x7c00
-    field public static final short POSITIVE_ZERO = 0; // 0x0
-    field public static final int SHIFTED_EXPONENT_MASK = 31; // 0x1f
-    field public static final int SIGNIFICAND_MASK = 1023; // 0x3ff
-    field public static final int SIGN_MASK = 32768; // 0x8000
-    field public static final int SIGN_SHIFT = 15; // 0xf
-    field public static final int SIZE = 16; // 0x10
-  }
-
-  public class HexEncoding {
-    method public static byte[] decode(String) throws java.lang.IllegalArgumentException;
-    method public static byte[] decode(String, boolean) throws java.lang.IllegalArgumentException;
-    method public static byte[] decode(char[]) throws java.lang.IllegalArgumentException;
-    method public static byte[] decode(char[], boolean) throws java.lang.IllegalArgumentException;
-    method public static char[] encode(byte[]);
-    method public static char[] encode(byte[], boolean);
-    method public static char[] encode(byte[], int, int);
-    method public static String encodeToString(byte, boolean);
-    method public static String encodeToString(byte[]);
-    method public static String encodeToString(byte[], boolean);
-  }
-
-  public class NativeAllocationRegistry {
-    ctor public NativeAllocationRegistry(@NonNull ClassLoader, long, long);
-    method public static void applyFreeFunction(long, long);
-    method public static libcore.util.NativeAllocationRegistry createMalloced(@NonNull ClassLoader, long, long);
-    method public static libcore.util.NativeAllocationRegistry createMalloced(@NonNull ClassLoader, long);
-    method public static libcore.util.NativeAllocationRegistry createNonmalloced(@NonNull ClassLoader, long, long);
-    method @NonNull public Runnable registerNativeAllocation(@NonNull Object, long);
-  }
-
-  public class SneakyThrow {
-    method public static void sneakyThrow(@NonNull Throwable);
-  }
-
-  public class XmlObjectFactory {
-    method @NonNull public static org.xml.sax.XMLReader newXMLReader();
-    method @NonNull public static org.xmlpull.v1.XmlPullParser newXmlPullParser();
-    method @NonNull public static org.xmlpull.v1.XmlSerializer newXmlSerializer();
-  }
-
-}
-
-package org.apache.harmony.dalvik.ddmc {
-
-  public class Chunk {
-    ctor public Chunk(int, byte[], int, int);
-    ctor public Chunk(int, java.nio.ByteBuffer);
-    field public int type;
-  }
-
-  public abstract class ChunkHandler {
-    ctor public ChunkHandler();
-    method public static org.apache.harmony.dalvik.ddmc.Chunk createFailChunk(int, String);
-    method public abstract org.apache.harmony.dalvik.ddmc.Chunk handleChunk(org.apache.harmony.dalvik.ddmc.Chunk);
-    method public static String name(int);
-    method public abstract void onConnected();
-    method public abstract void onDisconnected();
-    method public static int type(String);
-    method public static java.nio.ByteBuffer wrapChunk(org.apache.harmony.dalvik.ddmc.Chunk);
-    field public static final java.nio.ByteOrder CHUNK_ORDER;
-  }
-
-  public final class DdmServer {
-    method public static void registerHandler(int, org.apache.harmony.dalvik.ddmc.ChunkHandler);
-    method public static void registrationComplete();
-    method public static void sendChunk(org.apache.harmony.dalvik.ddmc.Chunk);
-    method public static org.apache.harmony.dalvik.ddmc.ChunkHandler unregisterHandler(int);
-  }
-
-  public final class DdmVmInternal {
-    method public static void setRecentAllocationsTrackingEnabled(boolean);
-    method public static void setThreadNotifyEnabled(boolean);
-  }
-
-}
-
-package org.json {
-
-  public class JSONObject {
-    method @NonNull public java.util.Set<java.lang.String> keySet();
-  }
-
-}
-
-package sun.misc {
-
-  public class Cleaner extends java.lang.ref.PhantomReference<java.lang.Object> {
-    method public void clean();
-    method public static sun.misc.Cleaner create(Object, Runnable);
-  }
-
-  public final class Unsafe {
-    method public int arrayBaseOffset(Class);
-    method public int arrayIndexScale(Class);
-    method @dalvik.annotation.optimization.FastNative public void copyMemory(long, long, long);
-    method @dalvik.annotation.optimization.FastNative public boolean getBoolean(Object, long);
-    method @dalvik.annotation.optimization.FastNative public byte getByte(Object, long);
-    method @dalvik.annotation.optimization.FastNative public byte getByte(long);
-    method @dalvik.annotation.optimization.FastNative public double getDouble(Object, long);
-    method @dalvik.annotation.optimization.FastNative public double getDouble(long);
-    method @dalvik.annotation.optimization.FastNative public float getFloat(Object, long);
-    method @dalvik.annotation.optimization.FastNative public float getFloat(long);
-    method @dalvik.annotation.optimization.FastNative public int getInt(Object, long);
-    method @dalvik.annotation.optimization.FastNative public int getInt(long);
-    method @dalvik.annotation.optimization.FastNative public long getLong(Object, long);
-    method @dalvik.annotation.optimization.FastNative public long getLong(long);
-    method @dalvik.annotation.optimization.FastNative public Object getObject(Object, long);
-    method public static sun.misc.Unsafe getUnsafe();
-    method public long objectFieldOffset(java.lang.reflect.Field);
-    method @dalvik.annotation.optimization.FastNative public void putBoolean(Object, long, boolean);
-    method @dalvik.annotation.optimization.FastNative public void putByte(Object, long, byte);
-    method @dalvik.annotation.optimization.FastNative public void putByte(long, byte);
-    method @dalvik.annotation.optimization.FastNative public void putDouble(Object, long, double);
-    method @dalvik.annotation.optimization.FastNative public void putDouble(long, double);
-    method @dalvik.annotation.optimization.FastNative public void putFloat(Object, long, float);
-    method @dalvik.annotation.optimization.FastNative public void putFloat(long, float);
-    method @dalvik.annotation.optimization.FastNative public void putInt(Object, long, int);
-    method @dalvik.annotation.optimization.FastNative public void putInt(long, int);
-    method @dalvik.annotation.optimization.FastNative public void putLong(Object, long, long);
-    method @dalvik.annotation.optimization.FastNative public void putLong(long, long);
-    method @dalvik.annotation.optimization.FastNative public void putObject(Object, long, Object);
-  }
-
-}
-
-package sun.security.jca {
-
-  public class Providers {
-    method public static Object startJarVerification();
-    method public static void stopJarVerification(Object);
-  }
-
-}
-
-package sun.security.pkcs {
-
-  public class PKCS7 {
-    ctor public PKCS7(java.io.InputStream) throws java.io.IOException, sun.security.pkcs.ParsingException;
-    ctor public PKCS7(byte[]) throws sun.security.pkcs.ParsingException;
-    method public java.security.cert.X509Certificate[] getCertificates();
-    method public sun.security.pkcs.SignerInfo[] getSignerInfos();
-    method public sun.security.pkcs.SignerInfo verify(sun.security.pkcs.SignerInfo, java.io.InputStream) throws java.io.IOException, java.security.NoSuchAlgorithmException, java.security.SignatureException;
-    method public sun.security.pkcs.SignerInfo[] verify(byte[]) throws java.security.NoSuchAlgorithmException, java.security.SignatureException;
-  }
-
-  public class ParsingException extends java.io.IOException {
-  }
-
-  public class SignerInfo {
-    ctor public SignerInfo();
-    method public java.util.ArrayList<java.security.cert.X509Certificate> getCertificateChain(sun.security.pkcs.PKCS7) throws java.io.IOException;
-  }
-
-}
-
-package sun.security.util {
-
-  public final class ObjectIdentifier implements java.io.Serializable {
-    ctor public ObjectIdentifier(String) throws java.io.IOException;
-  }
-
-}
-
-package sun.security.x509 {
-
-  public class AlgorithmId implements java.io.Serializable {
-    ctor public AlgorithmId(sun.security.util.ObjectIdentifier);
-    method public String getName();
-  }
-
-}
-
diff --git a/mmodules/core_platform_api/api/stable_platform/last-api.txt b/mmodules/core_platform_api/api/stable_platform/last-api.txt
deleted file mode 100644
index e69de29..0000000
--- a/mmodules/core_platform_api/api/stable_platform/last-api.txt
+++ /dev/null
diff --git a/mmodules/core_platform_api/api/stable_platform/last-incompatibilities.txt b/mmodules/core_platform_api/api/stable_platform/last-incompatibilities.txt
deleted file mode 100644
index e69de29..0000000
--- a/mmodules/core_platform_api/api/stable_platform/last-incompatibilities.txt
+++ /dev/null
diff --git a/mmodules/core_platform_api/api/stable_platform/last-removed.txt b/mmodules/core_platform_api/api/stable_platform/last-removed.txt
deleted file mode 100644
index e69de29..0000000
--- a/mmodules/core_platform_api/api/stable_platform/last-removed.txt
+++ /dev/null
diff --git a/mmodules/core_platform_api/api/stable_platform/removed.txt b/mmodules/core_platform_api/api/stable_platform/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/mmodules/core_platform_api/api/stable_platform/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/mmodules/intracoreapi/Android.bp b/mmodules/intracoreapi/Android.bp
index 513b044..34c6f1c 100644
--- a/mmodules/intracoreapi/Android.bp
+++ b/mmodules/intracoreapi/Android.bp
@@ -68,7 +68,6 @@
     droiddoc_options: [
         "--hide-annotation libcore.api.Hide",
         "--show-single-annotation libcore.api.IntraCoreApi",
-        "--skip-annotation-instance-methods=false",
     ],
     merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"],
 
diff --git a/mmodules/intracoreapi/api/intra/current.txt b/mmodules/intracoreapi/api/intra/current.txt
index 7e813f9..e58fb13 100644
--- a/mmodules/intracoreapi/api/intra/current.txt
+++ b/mmodules/intracoreapi/api/intra/current.txt
@@ -1,20 +1,20 @@
 // Signature format: 2.0
 package android.compat {
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public final class Compatibility {
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static boolean isChangeEnabled(long);
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static void reportUnconditionalChange(long);
+  @libcore.api.IntraCoreApi public final class Compatibility {
+    method @libcore.api.IntraCoreApi public static boolean isChangeEnabled(long);
+    method @libcore.api.IntraCoreApi public static void reportUnconditionalChange(long);
   }
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static final class Compatibility.ChangeConfig {
-    ctor @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public Compatibility.ChangeConfig(@NonNull java.util.Set<java.lang.Long>, @NonNull java.util.Set<java.lang.Long>);
-    method @NonNull @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public long[] getDisabledChangesArray();
-    method @NonNull @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public java.util.Set<java.lang.Long> getDisabledSet();
-    method @NonNull @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public long[] getEnabledChangesArray();
-    method @NonNull @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public java.util.Set<java.lang.Long> getEnabledSet();
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public boolean isEmpty();
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public boolean isForceDisabled(long);
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public boolean isForceEnabled(long);
+  @libcore.api.IntraCoreApi public static final class Compatibility.ChangeConfig {
+    ctor @libcore.api.IntraCoreApi public Compatibility.ChangeConfig(@NonNull java.util.Set<java.lang.Long>, @NonNull java.util.Set<java.lang.Long>);
+    method @NonNull @libcore.api.IntraCoreApi public long[] getDisabledChangesArray();
+    method @NonNull @libcore.api.IntraCoreApi public java.util.Set<java.lang.Long> getDisabledSet();
+    method @NonNull @libcore.api.IntraCoreApi public long[] getEnabledChangesArray();
+    method @NonNull @libcore.api.IntraCoreApi public java.util.Set<java.lang.Long> getEnabledSet();
+    method @libcore.api.IntraCoreApi public boolean isEmpty();
+    method @libcore.api.IntraCoreApi public boolean isForceDisabled(long);
+    method @libcore.api.IntraCoreApi public boolean isForceEnabled(long);
   }
 
 }
@@ -22,7 +22,7 @@
 package android.system {
 
   public final class Os {
-    method @Nullable @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static String realpath(@Nullable String) throws android.system.ErrnoException;
+    method @Nullable @libcore.api.IntraCoreApi public static String realpath(@Nullable String) throws android.system.ErrnoException;
   }
 
 }
@@ -36,13 +36,15 @@
     field @libcore.api.IntraCoreApi public static final int Q = 29; // 0x1d
     field @libcore.api.IntraCoreApi public static final int R = 30; // 0x1e
     field @libcore.api.IntraCoreApi public static final int S = 31; // 0x1f
+    field @libcore.api.IntraCoreApi public static final int S_V2 = 32; // 0x20
+    field @libcore.api.IntraCoreApi public static final int TIRAMISU = 33; // 0x21
   }
 
 }
 
 package dalvik.annotation.optimization {
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public @interface FastNative {
+  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) @libcore.api.IntraCoreApi public @interface FastNative {
   }
 
   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @libcore.api.IntraCoreApi public @interface ReachabilitySensitive {
@@ -52,25 +54,25 @@
 
 package dalvik.system {
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public final class BlockGuard {
-    method @NonNull @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static dalvik.system.BlockGuard.Policy getThreadPolicy();
+  @libcore.api.IntraCoreApi public final class BlockGuard {
+    method @NonNull @libcore.api.IntraCoreApi public static dalvik.system.BlockGuard.Policy getThreadPolicy();
   }
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static interface BlockGuard.Policy {
+  @libcore.api.IntraCoreApi public static interface BlockGuard.Policy {
     method @libcore.api.IntraCoreApi public void onNetwork();
   }
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public final class CloseGuard {
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public void close();
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static dalvik.system.CloseGuard get();
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public void open(String);
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public void warnIfOpen();
+  @libcore.api.IntraCoreApi public final class CloseGuard {
+    method @libcore.api.IntraCoreApi public void close();
+    method @libcore.api.IntraCoreApi public static dalvik.system.CloseGuard get();
+    method @libcore.api.IntraCoreApi public void open(String);
+    method @libcore.api.IntraCoreApi public void warnIfOpen();
   }
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public final class VMRuntime {
-    method @dalvik.annotation.optimization.FastNative @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public long addressOf(Object);
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static dalvik.system.VMRuntime getRuntime();
-    method @dalvik.annotation.optimization.FastNative @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public Object newNonMovableArray(Class<?>, int);
+  @libcore.api.IntraCoreApi public final class VMRuntime {
+    method @dalvik.annotation.optimization.FastNative @libcore.api.IntraCoreApi public long addressOf(Object);
+    method @libcore.api.IntraCoreApi public static dalvik.system.VMRuntime getRuntime();
+    method @dalvik.annotation.optimization.FastNative @libcore.api.IntraCoreApi public Object newNonMovableArray(Class<?>, int);
   }
 
 }
@@ -126,19 +128,19 @@
 
 package libcore.net {
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public abstract class NetworkSecurityPolicy {
-    ctor @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public NetworkSecurityPolicy();
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static libcore.net.NetworkSecurityPolicy getInstance();
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public abstract boolean isCertificateTransparencyVerificationRequired(String);
+  @libcore.api.IntraCoreApi public abstract class NetworkSecurityPolicy {
+    ctor @libcore.api.IntraCoreApi public NetworkSecurityPolicy();
+    method @libcore.api.IntraCoreApi public static libcore.net.NetworkSecurityPolicy getInstance();
+    method @libcore.api.IntraCoreApi public abstract boolean isCertificateTransparencyVerificationRequired(String);
   }
 
 }
 
 package libcore.util {
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public class NativeAllocationRegistry {
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public static libcore.util.NativeAllocationRegistry createMalloced(@NonNull ClassLoader, long);
-    method @NonNull @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public Runnable registerNativeAllocation(@NonNull Object, long);
+  @libcore.api.IntraCoreApi public class NativeAllocationRegistry {
+    method @libcore.api.IntraCoreApi public static libcore.util.NativeAllocationRegistry createMalloced(@NonNull ClassLoader, long);
+    method @NonNull @libcore.api.IntraCoreApi public Runnable registerNativeAllocation(@NonNull Object, long);
   }
 
   @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.TYPE_USE}) @libcore.api.IntraCoreApi public @interface NonNull {
@@ -159,10 +161,10 @@
 
 package sun.security.x509 {
 
-  @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public class AlgorithmId implements sun.security.util.DerEncoder java.io.Serializable {
+  @libcore.api.IntraCoreApi public class AlgorithmId implements sun.security.util.DerEncoder java.io.Serializable {
     method @libcore.api.IntraCoreApi public void derEncode(java.io.OutputStream) throws java.io.IOException;
     method @libcore.api.IntraCoreApi public static sun.security.x509.AlgorithmId get(String) throws java.security.NoSuchAlgorithmException;
-    method @libcore.api.CorePlatformApi(status=libcore.api.CorePlatformApi.Status.STABLE) @libcore.api.IntraCoreApi public String getName();
+    method @libcore.api.IntraCoreApi public String getName();
   }
 
 }
diff --git a/non_openjdk_java_files.bp b/non_openjdk_java_files.bp
index 59a78e3..5e32adb 100755
--- a/non_openjdk_java_files.bp
+++ b/non_openjdk_java_files.bp
@@ -28,6 +28,7 @@
         "dalvik/src/main/java/dalvik/annotation/optimization/CriticalNative.java",
         "dalvik/src/main/java/dalvik/annotation/optimization/DeadReferenceSafe.java",
         "dalvik/src/main/java/dalvik/annotation/optimization/FastNative.java",
+        "dalvik/src/main/java/dalvik/annotation/optimization/NeverCompile.java",
         "dalvik/src/main/java/dalvik/annotation/optimization/ReachabilitySensitive.java",
         "dalvik/src/main/java/dalvik/bytecode/OpcodeInfo.java",
         "dalvik/src/main/java/dalvik/bytecode/Opcodes.java",
@@ -90,6 +91,7 @@
         "libart/src/main/java/java/lang/invoke/ByteArrayViewVarHandle.java",
         "libart/src/main/java/java/lang/invoke/ByteBufferViewVarHandle.java",
         "libart/src/main/java/java/lang/invoke/FieldVarHandle.java",
+        "libart/src/main/java/java/lang/invoke/StaticFieldVarHandle.java",
     ],
     path: "libart/src/main",
     visibility: ["//visibility:private"],
@@ -154,6 +156,7 @@
         "luni/src/main/java/android/system/StructTimeval.java",
         "luni/src/main/java/android/system/StructUcred.java",
         "luni/src/main/java/android/system/StructUtsname.java",
+        "luni/src/main/java/android/system/SystemCleaner.java",
         "luni/src/main/java/android/system/UnixSocketAddress.java",
         "luni/src/main/java/android/system/VmSocketAddress.java",
         "luni/src/main/java/java/lang/FindBugsSuppressWarnings.java",
@@ -221,8 +224,10 @@
         "luni/src/main/java/javax/xml/xpath/XPathVariableResolver.java",
         "luni/src/main/java/libcore/content/type/MimeMap.java",
         "luni/src/main/java/libcore/icu/DateIntervalFormat.java",
+        "luni/src/main/java/libcore/icu/DecimalFormatData.java",
         "luni/src/main/java/libcore/icu/ICU.java",
         "luni/src/main/java/libcore/icu/LocaleData.java",
+        "luni/src/main/java/libcore/icu/SimpleDateFormatData.java",
         "luni/src/main/java/libcore/icu/TimeZoneNames.java",
         "luni/src/main/java/libcore/io/AsynchronousCloseMonitor.java",
         "luni/src/main/java/libcore/io/ForwardingOs.java",
@@ -351,6 +356,7 @@
         "luni/src/main/java/java/net/AddressCache.java",
         "luni/src/main/java/libcore/icu/CollationKeyICU.java",
         "luni/src/main/java/libcore/icu/DateUtilsBridge.java",
+        "luni/src/main/java/libcore/internal/Java11LanguageFeatures.java",
         "luni/src/main/java/libcore/internal/Java9LanguageFeatures.java",
         "luni/src/main/java/libcore/internal/StringPool.java",
         "luni/src/main/java/libcore/io/ClassPathURLStreamHandler.java",
diff --git a/nullability_annotated_classes.txt b/nullability_annotated_classes.txt
index e241e0b..f72c856 100644
--- a/nullability_annotated_classes.txt
+++ b/nullability_annotated_classes.txt
@@ -2,5 +2,4 @@
 # which should be validated for correctness and completeness. (N.B. Classes
 # with annotations in stub files under ojluni/annotations/sdk/nullability/
 # should also be validated, but are not listed here.)
-java.math.BigInteger
 org.json.JSONObject
diff --git a/ojluni/annotations/README b/ojluni/annotations/README
index 15d9738..ebc4390 100644
--- a/ojluni/annotations/README
+++ b/ojluni/annotations/README
@@ -16,7 +16,7 @@
    will cause the annotations to be validated for correctness and completeness.
  - To add some new files under this directory:
    1. make openjdk-sdk-stubs-no-javadoc
-   2. for FILE in your/package/and/Class.java another/package/AnotherClass.java; do mkdir -p libcore/ojluni/annotations/sdk/nullability/$(dirname ${FILE}) && cp out/soong/.intermediates/libcore/openjdk-sdk-stubs-no-javadoc/android_common/stubsDir/${FILE} libcore/ojluni/annotations/sdk/nullability/${FILE/%.java/.annotated.java}; done
+   2. for FILE in your/package/and/Class.java another/package/AnotherClass.java; do unzip out/soong/.intermediates/libcore/openjdk-sdk-stubs-no-javadoc/android_common/metalava/openjdk-sdk-stubs-no-javadoc-stubs.srcjar ${FILE} -d libcore/ojluni/annotations/sdk/nullability/ && mv libcore/ojluni/annotations/sdk/nullability/$FILE libcore/ojluni/annotations/sdk/nullability/${FILE/%.java/.annotated.java}; done
    3. Add nullability annotations to the new files.
  - To see the effect of the files under this directory:
    1. make api-stubs-docs
@@ -33,7 +33,7 @@
    2. make openjdk-mmodule-stubs-no-javadoc
    3. FILES="your/package/and/Class.java another/package/AnotherClass.java"; for FILE in $FILES; do mkdir -p libcore/ojluni/annotations/mmodule/$(dirname ${FILE}) && unzip out/soong/.intermediates/libcore/openjdk-mmodule-stubs-no-javadoc/android_common/metalava/openjdk-mmodule-stubs-no-javadoc-stubs.srcjar ${FILE} && mv ${FILE} libcore/ojluni/annotations/mmodule/${FILE/%.java/.annotated.java}; done
    4. Add @libcore.api.Hide to each class, methods and fields in the new files. This will prevent it from being added to the public API. A JavaDoc @hide tag will not work as metalava will ignore javadoc from the stub files.
-   5. Add @libcore.api.CorePlatformApi and @libcore.api.IntraCoreApi as desired
+   5. Add @android.annotation.SystemApi(client = MODULE_LIBRARIES) and @libcore.api.IntraCoreApi as desired
       to the classes and members.
  - To see the effect of the files under this directory:
    1. make make core-platform-api-stubs core-intra-stubs
diff --git a/ojluni/annotations/hiddenapi/java/lang/String.java b/ojluni/annotations/hiddenapi/java/lang/String.java
index e3a264b..6fed412 100644
--- a/ojluni/annotations/hiddenapi/java/lang/String.java
+++ b/ojluni/annotations/hiddenapi/java/lang/String.java
@@ -383,6 +383,16 @@
         throw new RuntimeException("Stub!");
     }
 
+    public java.lang.String strip() { throw new RuntimeException("Stub!"); }
+
+    public java.lang.String stripLeading() { throw new RuntimeException("Stub!"); }
+
+    public java.lang.String stripTrailing() { throw new RuntimeException("Stub!"); }
+
+    public boolean isBlank() { throw new RuntimeException("Stub!"); }
+
+    public java.util.stream.Stream<String> lines() { throw new RuntimeException("Stub!"); }
+
     public java.lang.String toString() {
         throw new RuntimeException("Stub!");
     }
diff --git a/ojluni/annotations/mmodule/java/io/FileDescriptor.annotated.java b/ojluni/annotations/mmodule/java/io/FileDescriptor.annotated.java
index cc16cd6..af283d9 100644
--- a/ojluni/annotations/mmodule/java/io/FileDescriptor.annotated.java
+++ b/ojluni/annotations/mmodule/java/io/FileDescriptor.annotated.java
@@ -37,11 +37,9 @@
 public native void sync() throws java.io.SyncFailedException;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public int getInt$() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public void setInt$(int fd) { throw new RuntimeException("Stub!"); }
 
 public long getOwnerId$() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/io/FileInputStream.annotated.java b/ojluni/annotations/mmodule/java/io/FileInputStream.annotated.java
index ac26aeb..7c10ad7 100644
--- a/ojluni/annotations/mmodule/java/io/FileInputStream.annotated.java
+++ b/ojluni/annotations/mmodule/java/io/FileInputStream.annotated.java
@@ -39,7 +39,6 @@
 public FileInputStream(java.io.FileDescriptor fdObj) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public FileInputStream(java.io.FileDescriptor fdObj, boolean isFdOwner) { throw new RuntimeException("Stub!"); }
 
 public int read() throws java.io.IOException { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/lang/Thread.annotated.java b/ojluni/annotations/mmodule/java/lang/Thread.annotated.java
index 8308a99..3b1ebe4 100644
--- a/ojluni/annotations/mmodule/java/lang/Thread.annotated.java
+++ b/ojluni/annotations/mmodule/java/lang/Thread.annotated.java
@@ -142,11 +142,9 @@
 public static java.lang.Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static void setUncaughtExceptionPreHandler(UncaughtExceptionHandler eh) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static UncaughtExceptionHandler getUncaughtExceptionPreHandler() { throw new RuntimeException("Stub!"); }
 
 public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/net/DatagramSocket.annotated.java b/ojluni/annotations/mmodule/java/net/DatagramSocket.annotated.java
index 52b5bff..4d4e8e4 100644
--- a/ojluni/annotations/mmodule/java/net/DatagramSocket.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/DatagramSocket.annotated.java
@@ -104,7 +104,6 @@
 public static synchronized void setDatagramSocketImplFactory(java.net.DatagramSocketImplFactory fac) throws java.io.IOException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public java.io.FileDescriptor getFileDescriptor$() { throw new RuntimeException("Stub!"); }
 }
 
diff --git a/ojluni/annotations/mmodule/java/net/Inet4Address.annotated.java b/ojluni/annotations/mmodule/java/net/Inet4Address.annotated.java
index 4692b1f..bf01c2a 100644
--- a/ojluni/annotations/mmodule/java/net/Inet4Address.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/Inet4Address.annotated.java
@@ -63,17 +63,14 @@
 public boolean equals(java.lang.Object obj) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static final java.net.InetAddress ALL;
 static { ALL = null; }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static final java.net.InetAddress ANY;
 static { ANY = null; }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static final java.net.InetAddress LOOPBACK;
 static { LOOPBACK = null; }
 }
diff --git a/ojluni/annotations/mmodule/java/net/Inet6Address.annotated.java b/ojluni/annotations/mmodule/java/net/Inet6Address.annotated.java
index 567d877..04a66cf 100644
--- a/ojluni/annotations/mmodule/java/net/Inet6Address.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/Inet6Address.annotated.java
@@ -72,12 +72,10 @@
 public boolean isIPv4CompatibleAddress() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static final java.net.InetAddress ANY;
 static { ANY = null; }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static final java.net.InetAddress LOOPBACK;
 static { LOOPBACK = null; }
 }
diff --git a/ojluni/annotations/mmodule/java/net/InetAddress.annotated.java b/ojluni/annotations/mmodule/java/net/InetAddress.annotated.java
index 6229cc9..443541b 100644
--- a/ojluni/annotations/mmodule/java/net/InetAddress.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/InetAddress.annotated.java
@@ -88,23 +88,18 @@
 public static java.net.InetAddress getLocalHost() throws java.net.UnknownHostException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static boolean isNumeric(java.lang.String address) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static java.net.InetAddress parseNumericAddress(java.lang.String numericAddress) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static void clearDnsCache() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static java.net.InetAddress getByNameOnNet(java.lang.String host, int netId) throws java.net.UnknownHostException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static java.net.InetAddress[] getAllByNameOnNet(java.lang.String host, int netId) throws java.net.UnknownHostException { throw new RuntimeException("Stub!"); }
 }
 
diff --git a/ojluni/annotations/mmodule/java/net/InetSocketAddress.annotated.java b/ojluni/annotations/mmodule/java/net/InetSocketAddress.annotated.java
index b2bf439..e121099 100644
--- a/ojluni/annotations/mmodule/java/net/InetSocketAddress.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/InetSocketAddress.annotated.java
@@ -31,7 +31,6 @@
 public class InetSocketAddress extends java.net.SocketAddress {
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public InetSocketAddress() { throw new RuntimeException("Stub!"); }
 
 public InetSocketAddress(int port) { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/net/ServerSocket.annotated.java b/ojluni/annotations/mmodule/java/net/ServerSocket.annotated.java
index 0bf1fe7..fd09926 100644
--- a/ojluni/annotations/mmodule/java/net/ServerSocket.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/ServerSocket.annotated.java
@@ -53,7 +53,6 @@
 public java.net.Socket accept() throws java.io.IOException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public SocketImpl getImpl() throws SocketException { throw new RuntimeException("Stub!"); }
 
 protected final void implAccept(java.net.Socket s) throws java.io.IOException { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/net/Socket.annotated.java b/ojluni/annotations/mmodule/java/net/Socket.annotated.java
index 61014de..4924f10 100644
--- a/ojluni/annotations/mmodule/java/net/Socket.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/Socket.annotated.java
@@ -140,7 +140,6 @@
 public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 public java.io.FileDescriptor getFileDescriptor$() { throw new RuntimeException("Stub!"); }
 }
diff --git a/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java b/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java
index a29ed76..c7e345e 100644
--- a/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java
+++ b/ojluni/annotations/mmodule/java/net/SocketImpl.annotated.java
@@ -63,7 +63,6 @@
 protected java.io.FileDescriptor getFileDescriptor() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public java.io.FileDescriptor getFD$() { throw new RuntimeException("Stub!"); }
 
 protected java.net.InetAddress getInetAddress() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/nio/ByteBuffer.annotated.java b/ojluni/annotations/mmodule/java/nio/ByteBuffer.annotated.java
index 369d0a5..0fbe4d0 100644
--- a/ojluni/annotations/mmodule/java/nio/ByteBuffer.annotated.java
+++ b/ojluni/annotations/mmodule/java/nio/ByteBuffer.annotated.java
@@ -152,7 +152,6 @@
 public boolean isAccessible() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public void setAccessible(boolean value) { throw new RuntimeException("Stub!"); }
 }
 
diff --git a/ojluni/annotations/mmodule/java/nio/DirectByteBuffer.annotated.java b/ojluni/annotations/mmodule/java/nio/DirectByteBuffer.annotated.java
index 8031e93..220b7dd 100644
--- a/ojluni/annotations/mmodule/java/nio/DirectByteBuffer.annotated.java
+++ b/ojluni/annotations/mmodule/java/nio/DirectByteBuffer.annotated.java
@@ -30,13 +30,11 @@
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public class DirectByteBuffer extends java.nio.MappedByteBuffer implements sun.nio.ch.DirectBuffer {
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public DirectByteBuffer(int cap, long addr, java.io.FileDescriptor fd, java.lang.Runnable unmapper, boolean isReadOnly) { super(0, 0, 0, 0); throw new RuntimeException("Stub!"); }
 
 @libcore.api.Hide
@@ -56,7 +54,6 @@
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final long address() { throw new RuntimeException("Stub!"); }
 
 @libcore.api.Hide
@@ -184,7 +181,6 @@
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public final void setAccessible(boolean value) { throw new RuntimeException("Stub!"); }
 }
 
diff --git a/ojluni/annotations/mmodule/java/security/Provider.annotated.java b/ojluni/annotations/mmodule/java/security/Provider.annotated.java
index 3ffe654..6662ec0 100644
--- a/ojluni/annotations/mmodule/java/security/Provider.annotated.java
+++ b/ojluni/annotations/mmodule/java/security/Provider.annotated.java
@@ -107,7 +107,6 @@
 public boolean isRegistered() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public synchronized void warmUpServiceProvision() { throw new RuntimeException("Stub!"); }
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public static class Service {
diff --git a/ojluni/annotations/mmodule/java/security/Signature.annotated.java b/ojluni/annotations/mmodule/java/security/Signature.annotated.java
index 8aaf5c4..cec7abb 100644
--- a/ojluni/annotations/mmodule/java/security/Signature.annotated.java
+++ b/ojluni/annotations/mmodule/java/security/Signature.annotated.java
@@ -87,7 +87,6 @@
 public java.lang.Object clone() throws java.lang.CloneNotSupportedException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public java.security.SignatureSpi getCurrentSpi() { throw new RuntimeException("Stub!"); }
 
 protected static final int SIGN = 2; // 0x2
diff --git a/ojluni/annotations/mmodule/java/text/DateFormat.annotated.java b/ojluni/annotations/mmodule/java/text/DateFormat.annotated.java
index 12a850e..49272d2 100644
--- a/ojluni/annotations/mmodule/java/text/DateFormat.annotated.java
+++ b/ojluni/annotations/mmodule/java/text/DateFormat.annotated.java
@@ -84,7 +84,6 @@
 public static final java.text.DateFormat getInstance() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static final void set24HourTimePref(java.lang.Boolean is24Hour) { throw new RuntimeException("Stub!"); }
 
 public static java.util.Locale[] getAvailableLocales() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/time/Clock.annotated.java b/ojluni/annotations/mmodule/java/time/Clock.annotated.java
new file mode 100644
index 0000000..a7ec571
--- /dev/null
+++ b/ojluni/annotations/mmodule/java/time/Clock.annotated.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package java.time;
+
+import libcore.api.Hide;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public abstract class Clock {
+
+protected Clock() { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock systemUTC() { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock systemDefaultZone() { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock system(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public static java.time.Clock tickMillis(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock tickSeconds(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock tickMinutes(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock tick(java.time.Clock baseClock, java.time.Duration tickDuration) { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock fixed(java.time.Instant fixedInstant, java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.Clock offset(java.time.Clock baseClock, java.time.Duration offsetDuration) { throw new RuntimeException("Stub!"); }
+
+public abstract java.time.ZoneId getZone();
+
+public abstract java.time.Clock withZone(java.time.ZoneId zone);
+
+public long millis() { throw new RuntimeException("Stub!"); }
+
+public abstract java.time.Instant instant();
+
+public boolean equals(java.lang.Object obj) { throw new RuntimeException("Stub!"); }
+
+public int hashCode() { throw new RuntimeException("Stub!"); }
+}
+
diff --git a/ojluni/annotations/mmodule/java/time/LocalDate.annotated.java b/ojluni/annotations/mmodule/java/time/LocalDate.annotated.java
new file mode 100644
index 0000000..1f74bb9
--- /dev/null
+++ b/ojluni/annotations/mmodule/java/time/LocalDate.annotated.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package java.time;
+
+import libcore.api.Hide;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class LocalDate implements java.time.temporal.Temporal, java.time.temporal.TemporalAdjuster, java.time.chrono.ChronoLocalDate, java.io.Serializable {
+
+private LocalDate() { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate now() { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate now(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate now(java.time.Clock clock) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate of(int year, java.time.Month month, int dayOfMonth) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate of(int year, int month, int dayOfMonth) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate ofYearDay(int year, int dayOfYear) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public static java.time.LocalDate ofInstant(java.time.Instant instant, java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate ofEpochDay(long epochDay) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate from(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate parse(java.lang.CharSequence text) { throw new RuntimeException("Stub!"); }
+
+public static java.time.LocalDate parse(java.lang.CharSequence text, java.time.format.DateTimeFormatter formatter) { throw new RuntimeException("Stub!"); }
+
+public boolean isSupported(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public boolean isSupported(java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.ValueRange range(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public int get(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public long getLong(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.IsoChronology getChronology() { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.Era getEra() { throw new RuntimeException("Stub!"); }
+
+public int getYear() { throw new RuntimeException("Stub!"); }
+
+public int getMonthValue() { throw new RuntimeException("Stub!"); }
+
+public java.time.Month getMonth() { throw new RuntimeException("Stub!"); }
+
+public int getDayOfMonth() { throw new RuntimeException("Stub!"); }
+
+public int getDayOfYear() { throw new RuntimeException("Stub!"); }
+
+public java.time.DayOfWeek getDayOfWeek() { throw new RuntimeException("Stub!"); }
+
+public boolean isLeapYear() { throw new RuntimeException("Stub!"); }
+
+public int lengthOfMonth() { throw new RuntimeException("Stub!"); }
+
+public int lengthOfYear() { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate with(java.time.temporal.TemporalAdjuster adjuster) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate with(java.time.temporal.TemporalField field, long newValue) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate withYear(int year) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate withMonth(int month) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate withDayOfMonth(int dayOfMonth) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate withDayOfYear(int dayOfYear) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate plus(java.time.temporal.TemporalAmount amountToAdd) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate plus(long amountToAdd, java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate plusYears(long yearsToAdd) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate plusMonths(long monthsToAdd) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate plusWeeks(long weeksToAdd) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate plusDays(long daysToAdd) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate minus(java.time.temporal.TemporalAmount amountToSubtract) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate minus(long amountToSubtract, java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate minusYears(long yearsToSubtract) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate minusMonths(long monthsToSubtract) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate minusWeeks(long weeksToSubtract) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate minusDays(long daysToSubtract) { throw new RuntimeException("Stub!"); }
+
+public <R> R query(java.time.temporal.TemporalQuery<R> query) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal temporal) { throw new RuntimeException("Stub!"); }
+
+public long until(java.time.temporal.Temporal endExclusive, java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.Period until(java.time.chrono.ChronoLocalDate endDateExclusive) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public java.util.stream.Stream<java.time.LocalDate> datesUntil(java.time.LocalDate endExclusive) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public java.util.stream.Stream<java.time.LocalDate> datesUntil(java.time.LocalDate endExclusive, java.time.Period step) { throw new RuntimeException("Stub!"); }
+
+public java.lang.String format(java.time.format.DateTimeFormatter formatter) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDateTime atTime(java.time.LocalTime time) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDateTime atTime(int hour, int minute) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDateTime atTime(int hour, int minute, int second) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetDateTime atTime(java.time.OffsetTime time) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDateTime atStartOfDay() { throw new RuntimeException("Stub!"); }
+
+public java.time.ZonedDateTime atStartOfDay(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public long toEpochDay() { throw new RuntimeException("Stub!"); }
+
+@Hide
+public long toEpochSecond(java.time.LocalTime time, java.time.ZoneOffset offset) { throw new RuntimeException("Stub!"); }
+
+public int compareTo(java.time.chrono.ChronoLocalDate other) { throw new RuntimeException("Stub!"); }
+
+public boolean isAfter(java.time.chrono.ChronoLocalDate other) { throw new RuntimeException("Stub!"); }
+
+public boolean isBefore(java.time.chrono.ChronoLocalDate other) { throw new RuntimeException("Stub!"); }
+
+public boolean isEqual(java.time.chrono.ChronoLocalDate other) { throw new RuntimeException("Stub!"); }
+
+public boolean equals(java.lang.Object obj) { throw new RuntimeException("Stub!"); }
+
+public int hashCode() { throw new RuntimeException("Stub!"); }
+
+public java.lang.String toString() { throw new RuntimeException("Stub!"); }
+
+@Hide
+public static final java.time.LocalDate EPOCH;
+static { EPOCH = null; }
+
+public static final java.time.LocalDate MAX;
+static { MAX = null; }
+
+public static final java.time.LocalDate MIN;
+static { MIN = null; }
+}
+
diff --git a/ojluni/annotations/mmodule/java/time/OffsetTime.annotated.java b/ojluni/annotations/mmodule/java/time/OffsetTime.annotated.java
new file mode 100644
index 0000000..6707851
--- /dev/null
+++ b/ojluni/annotations/mmodule/java/time/OffsetTime.annotated.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package java.time;
+
+import libcore.api.Hide;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class OffsetTime implements java.time.temporal.Temporal, java.time.temporal.TemporalAdjuster, java.lang.Comparable<java.time.OffsetTime>, java.io.Serializable {
+
+private OffsetTime() { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime now() { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime now(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime now(java.time.Clock clock) { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime of(java.time.LocalTime time, java.time.ZoneOffset offset) { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime of(int hour, int minute, int second, int nanoOfSecond, java.time.ZoneOffset offset) { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime ofInstant(java.time.Instant instant, java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime from(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime parse(java.lang.CharSequence text) { throw new RuntimeException("Stub!"); }
+
+public static java.time.OffsetTime parse(java.lang.CharSequence text, java.time.format.DateTimeFormatter formatter) { throw new RuntimeException("Stub!"); }
+
+public boolean isSupported(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public boolean isSupported(java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.ValueRange range(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public int get(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public long getLong(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public java.time.ZoneOffset getOffset() { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime withOffsetSameLocal(java.time.ZoneOffset offset) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime withOffsetSameInstant(java.time.ZoneOffset offset) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalTime toLocalTime() { throw new RuntimeException("Stub!"); }
+
+public int getHour() { throw new RuntimeException("Stub!"); }
+
+public int getMinute() { throw new RuntimeException("Stub!"); }
+
+public int getSecond() { throw new RuntimeException("Stub!"); }
+
+public int getNano() { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime with(java.time.temporal.TemporalAdjuster adjuster) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime with(java.time.temporal.TemporalField field, long newValue) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime withHour(int hour) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime withMinute(int minute) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime withSecond(int second) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime withNano(int nanoOfSecond) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime truncatedTo(java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime plus(java.time.temporal.TemporalAmount amountToAdd) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime plus(long amountToAdd, java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime plusHours(long hours) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime plusMinutes(long minutes) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime plusSeconds(long seconds) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime plusNanos(long nanos) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime minus(java.time.temporal.TemporalAmount amountToSubtract) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime minus(long amountToSubtract, java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime minusHours(long hours) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime minusMinutes(long minutes) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime minusSeconds(long seconds) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetTime minusNanos(long nanos) { throw new RuntimeException("Stub!"); }
+
+public <R> R query(java.time.temporal.TemporalQuery<R> query) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.Temporal adjustInto(java.time.temporal.Temporal temporal) { throw new RuntimeException("Stub!"); }
+
+public long until(java.time.temporal.Temporal endExclusive, java.time.temporal.TemporalUnit unit) { throw new RuntimeException("Stub!"); }
+
+public java.lang.String format(java.time.format.DateTimeFormatter formatter) { throw new RuntimeException("Stub!"); }
+
+public java.time.OffsetDateTime atDate(java.time.LocalDate date) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public long toEpochSecond(java.time.LocalDate date) { throw new RuntimeException("Stub!"); }
+
+public int compareTo(java.time.OffsetTime other) { throw new RuntimeException("Stub!"); }
+
+public boolean isAfter(java.time.OffsetTime other) { throw new RuntimeException("Stub!"); }
+
+public boolean isBefore(java.time.OffsetTime other) { throw new RuntimeException("Stub!"); }
+
+public boolean isEqual(java.time.OffsetTime other) { throw new RuntimeException("Stub!"); }
+
+public boolean equals(java.lang.Object obj) { throw new RuntimeException("Stub!"); }
+
+public int hashCode() { throw new RuntimeException("Stub!"); }
+
+public java.lang.String toString() { throw new RuntimeException("Stub!"); }
+
+public static final java.time.OffsetTime MAX;
+static { MAX = null; }
+
+public static final java.time.OffsetTime MIN;
+static { MIN = null; }
+}
+
diff --git a/ojluni/annotations/mmodule/java/time/chrono/Chronology.annotated.java b/ojluni/annotations/mmodule/java/time/chrono/Chronology.annotated.java
new file mode 100644
index 0000000..1d5e367
--- /dev/null
+++ b/ojluni/annotations/mmodule/java/time/chrono/Chronology.annotated.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package java.time.chrono;
+
+import libcore.api.Hide;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public interface Chronology extends java.lang.Comparable<java.time.chrono.Chronology> {
+
+public static java.time.chrono.Chronology from(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public static java.time.chrono.Chronology ofLocale(java.util.Locale locale) { throw new RuntimeException("Stub!"); }
+
+public static java.time.chrono.Chronology of(java.lang.String id) { throw new RuntimeException("Stub!"); }
+
+public static java.util.Set<java.time.chrono.Chronology> getAvailableChronologies() { throw new RuntimeException("Stub!"); }
+
+public java.lang.String getId();
+
+public java.lang.String getCalendarType();
+
+public default java.time.chrono.ChronoLocalDate date(java.time.chrono.Era era, int yearOfEra, int month, int dayOfMonth) { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth);
+
+public default java.time.chrono.ChronoLocalDate dateYearDay(java.time.chrono.Era era, int yearOfEra, int dayOfYear) { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear);
+
+public java.time.chrono.ChronoLocalDate dateEpochDay(long epochDay);
+
+public default java.time.chrono.ChronoLocalDate dateNow() { throw new RuntimeException("Stub!"); }
+
+public default java.time.chrono.ChronoLocalDate dateNow(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public default java.time.chrono.ChronoLocalDate dateNow(java.time.Clock clock) { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.ChronoLocalDate date(java.time.temporal.TemporalAccessor temporal);
+
+public default java.time.chrono.ChronoLocalDateTime<? extends java.time.chrono.ChronoLocalDate> localDateTime(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public default java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate> zonedDateTime(java.time.Instant instant, java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public boolean isLeapYear(long prolepticYear);
+
+public int prolepticYear(java.time.chrono.Era era, int yearOfEra);
+
+public java.time.chrono.Era eraOf(int eraValue);
+
+public java.util.List<java.time.chrono.Era> eras();
+
+public java.time.temporal.ValueRange range(java.time.temporal.ChronoField field);
+
+public default java.lang.String getDisplayName(java.time.format.TextStyle style, java.util.Locale locale) { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.ChronoLocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField,java.lang.Long> fieldValues, java.time.format.ResolverStyle resolverStyle);
+
+public default java.time.chrono.ChronoPeriod period(int years, int months, int days) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public default long epochSecond(int prolepticYear, int month, int dayOfMonth, int hour, int minute, int second, java.time.ZoneOffset zoneOffset) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public default long epochSecond(java.time.chrono.Era era, int yearOfEra, int month, int dayOfMonth, int hour, int minute, int second, java.time.ZoneOffset zoneOffset) { throw new RuntimeException("Stub!"); }
+
+public int compareTo(java.time.chrono.Chronology other);
+
+public boolean equals(java.lang.Object obj);
+
+public int hashCode();
+
+public java.lang.String toString();
+}
+
diff --git a/ojluni/annotations/mmodule/java/time/chrono/IsoChronology.annotated.java b/ojluni/annotations/mmodule/java/time/chrono/IsoChronology.annotated.java
new file mode 100644
index 0000000..a5a515e
--- /dev/null
+++ b/ojluni/annotations/mmodule/java/time/chrono/IsoChronology.annotated.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package java.time.chrono;
+
+import libcore.api.Hide;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class IsoChronology extends java.time.chrono.AbstractChronology implements java.io.Serializable {
+
+private IsoChronology() { throw new RuntimeException("Stub!"); }
+
+public java.lang.String getId() { throw new RuntimeException("Stub!"); }
+
+public java.lang.String getCalendarType() { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate date(java.time.chrono.Era era, int yearOfEra, int month, int dayOfMonth) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate date(int prolepticYear, int month, int dayOfMonth) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate dateYearDay(java.time.chrono.Era era, int yearOfEra, int dayOfYear) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate dateYearDay(int prolepticYear, int dayOfYear) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate dateEpochDay(long epochDay) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate date(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public long epochSecond(int prolepticYear, int month, int dayOfMonth, int hour, int minute, int second, java.time.ZoneOffset zoneOffset) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDateTime localDateTime(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public java.time.ZonedDateTime zonedDateTime(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public java.time.ZonedDateTime zonedDateTime(java.time.Instant instant, java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate dateNow() { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate dateNow(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate dateNow(java.time.Clock clock) { throw new RuntimeException("Stub!"); }
+
+public boolean isLeapYear(long prolepticYear) { throw new RuntimeException("Stub!"); }
+
+public int prolepticYear(java.time.chrono.Era era, int yearOfEra) { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.IsoEra eraOf(int eraValue) { throw new RuntimeException("Stub!"); }
+
+public java.util.List<java.time.chrono.Era> eras() { throw new RuntimeException("Stub!"); }
+
+public java.time.LocalDate resolveDate(java.util.Map<java.time.temporal.TemporalField,java.lang.Long> fieldValues, java.time.format.ResolverStyle resolverStyle) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.ValueRange range(java.time.temporal.ChronoField field) { throw new RuntimeException("Stub!"); }
+
+public java.time.Period period(int years, int months, int days) { throw new RuntimeException("Stub!"); }
+
+public static final java.time.chrono.IsoChronology INSTANCE;
+static { INSTANCE = null; }
+}
+
diff --git a/ojluni/annotations/mmodule/java/time/format/DateTimeFormatter.annotated.java b/ojluni/annotations/mmodule/java/time/format/DateTimeFormatter.annotated.java
new file mode 100644
index 0000000..2334429
--- /dev/null
+++ b/ojluni/annotations/mmodule/java/time/format/DateTimeFormatter.annotated.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package java.time.format;
+
+import libcore.api.Hide;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class DateTimeFormatter {
+
+DateTimeFormatter() { throw new RuntimeException("Stub!"); }
+
+public static java.time.format.DateTimeFormatter ofPattern(java.lang.String pattern) { throw new RuntimeException("Stub!"); }
+
+public static java.time.format.DateTimeFormatter ofPattern(java.lang.String pattern, java.util.Locale locale) { throw new RuntimeException("Stub!"); }
+
+public static java.time.format.DateTimeFormatter ofLocalizedDate(java.time.format.FormatStyle dateStyle) { throw new RuntimeException("Stub!"); }
+
+public static java.time.format.DateTimeFormatter ofLocalizedTime(java.time.format.FormatStyle timeStyle) { throw new RuntimeException("Stub!"); }
+
+public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle dateTimeStyle) { throw new RuntimeException("Stub!"); }
+
+public static java.time.format.DateTimeFormatter ofLocalizedDateTime(java.time.format.FormatStyle dateStyle, java.time.format.FormatStyle timeStyle) { throw new RuntimeException("Stub!"); }
+
+public static java.time.temporal.TemporalQuery<java.time.Period> parsedExcessDays() { throw new RuntimeException("Stub!"); }
+
+public static java.time.temporal.TemporalQuery<java.lang.Boolean> parsedLeapSecond() { throw new RuntimeException("Stub!"); }
+
+public java.util.Locale getLocale() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter withLocale(java.util.Locale locale) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public java.time.format.DateTimeFormatter localizedBy(java.util.Locale locale) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DecimalStyle getDecimalStyle() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter withDecimalStyle(java.time.format.DecimalStyle decimalStyle) { throw new RuntimeException("Stub!"); }
+
+public java.time.chrono.Chronology getChronology() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter withChronology(java.time.chrono.Chronology chrono) { throw new RuntimeException("Stub!"); }
+
+public java.time.ZoneId getZone() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter withZone(java.time.ZoneId zone) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.ResolverStyle getResolverStyle() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter withResolverStyle(java.time.format.ResolverStyle resolverStyle) { throw new RuntimeException("Stub!"); }
+
+public java.util.Set<java.time.temporal.TemporalField> getResolverFields() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter withResolverFields(java.time.temporal.TemporalField... resolverFields) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter withResolverFields(java.util.Set<java.time.temporal.TemporalField> resolverFields) { throw new RuntimeException("Stub!"); }
+
+public java.lang.String format(java.time.temporal.TemporalAccessor temporal) { throw new RuntimeException("Stub!"); }
+
+public void formatTo(java.time.temporal.TemporalAccessor temporal, java.lang.Appendable appendable) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence text) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.TemporalAccessor parse(java.lang.CharSequence text, java.text.ParsePosition position) { throw new RuntimeException("Stub!"); }
+
+public <T> T parse(java.lang.CharSequence text, java.time.temporal.TemporalQuery<T> query) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.TemporalAccessor parseBest(java.lang.CharSequence text, java.time.temporal.TemporalQuery<?>... queries) { throw new RuntimeException("Stub!"); }
+
+public java.time.temporal.TemporalAccessor parseUnresolved(java.lang.CharSequence text, java.text.ParsePosition position) { throw new RuntimeException("Stub!"); }
+
+public java.text.Format toFormat() { throw new RuntimeException("Stub!"); }
+
+public java.text.Format toFormat(java.time.temporal.TemporalQuery<?> parseQuery) { throw new RuntimeException("Stub!"); }
+
+public java.lang.String toString() { throw new RuntimeException("Stub!"); }
+
+public static final java.time.format.DateTimeFormatter BASIC_ISO_DATE;
+static { BASIC_ISO_DATE = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_DATE;
+static { ISO_DATE = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_DATE_TIME;
+static { ISO_DATE_TIME = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_INSTANT;
+static { ISO_INSTANT = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE;
+static { ISO_LOCAL_DATE = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_LOCAL_DATE_TIME;
+static { ISO_LOCAL_DATE_TIME = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_LOCAL_TIME;
+static { ISO_LOCAL_TIME = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE;
+static { ISO_OFFSET_DATE = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_OFFSET_DATE_TIME;
+static { ISO_OFFSET_DATE_TIME = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_OFFSET_TIME;
+static { ISO_OFFSET_TIME = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_ORDINAL_DATE;
+static { ISO_ORDINAL_DATE = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_TIME;
+static { ISO_TIME = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_WEEK_DATE;
+static { ISO_WEEK_DATE = null; }
+
+public static final java.time.format.DateTimeFormatter ISO_ZONED_DATE_TIME;
+static { ISO_ZONED_DATE_TIME = null; }
+
+public static final java.time.format.DateTimeFormatter RFC_1123_DATE_TIME;
+static { RFC_1123_DATE_TIME = null; }
+}
+
diff --git a/ojluni/annotations/mmodule/java/time/format/DateTimeFormatterBuilder.annotated.java b/ojluni/annotations/mmodule/java/time/format/DateTimeFormatterBuilder.annotated.java
new file mode 100644
index 0000000..6b6873c
--- /dev/null
+++ b/ojluni/annotations/mmodule/java/time/format/DateTimeFormatterBuilder.annotated.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package java.time.format;
+
+import libcore.api.Hide;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class DateTimeFormatterBuilder {
+
+public DateTimeFormatterBuilder() { throw new RuntimeException("Stub!"); }
+
+public static java.lang.String getLocalizedDateTimePattern(java.time.format.FormatStyle dateStyle, java.time.format.FormatStyle timeStyle, java.time.chrono.Chronology chrono, java.util.Locale locale) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder parseCaseSensitive() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder parseCaseInsensitive() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder parseStrict() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder parseLenient() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder parseDefaulting(java.time.temporal.TemporalField field, long value) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField field, int width) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendValue(java.time.temporal.TemporalField field, int minWidth, int maxWidth, java.time.format.SignStyle signStyle) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField field, int width, int maxWidth, int baseValue) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendValueReduced(java.time.temporal.TemporalField field, int width, int maxWidth, java.time.chrono.ChronoLocalDate baseDate) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendFraction(java.time.temporal.TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField field) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField field, java.time.format.TextStyle textStyle) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendText(java.time.temporal.TemporalField field, java.util.Map<java.lang.Long,java.lang.String> textLookup) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendInstant() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendInstant(int fractionalDigits) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendOffsetId() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendOffset(java.lang.String pattern, java.lang.String noOffsetText) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendLocalizedOffset(java.time.format.TextStyle style) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendZoneId() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendZoneRegionId() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendZoneOrOffsetId() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle textStyle) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendZoneText(java.time.format.TextStyle textStyle, java.util.Set<java.time.ZoneId> preferredZones) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public java.time.format.DateTimeFormatterBuilder appendGenericZoneText(java.time.format.TextStyle textStyle) { throw new RuntimeException("Stub!"); }
+
+@Hide
+public java.time.format.DateTimeFormatterBuilder appendGenericZoneText(java.time.format.TextStyle textStyle, java.util.Set<java.time.ZoneId> preferredZones) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendChronologyId() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendChronologyText(java.time.format.TextStyle textStyle) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendLocalized(java.time.format.FormatStyle dateStyle, java.time.format.FormatStyle timeStyle) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendLiteral(char literal) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendLiteral(java.lang.String literal) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder append(java.time.format.DateTimeFormatter formatter) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendOptional(java.time.format.DateTimeFormatter formatter) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder appendPattern(java.lang.String pattern) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder padNext(int padWidth) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder padNext(int padWidth, char padChar) { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder optionalStart() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatterBuilder optionalEnd() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter toFormatter() { throw new RuntimeException("Stub!"); }
+
+public java.time.format.DateTimeFormatter toFormatter(java.util.Locale locale) { throw new RuntimeException("Stub!"); }
+}
+
diff --git a/ojluni/annotations/mmodule/java/util/LinkedHashMap.annotated.java b/ojluni/annotations/mmodule/java/util/LinkedHashMap.annotated.java
index ada21b1..ef28749 100644
--- a/ojluni/annotations/mmodule/java/util/LinkedHashMap.annotated.java
+++ b/ojluni/annotations/mmodule/java/util/LinkedHashMap.annotated.java
@@ -49,7 +49,6 @@
 public void clear() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public java.util.Map.Entry<K,V> eldest() { throw new RuntimeException("Stub!"); }
 
 protected boolean removeEldestEntry(java.util.Map.Entry<K,V> eldest) { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/java/util/zip/ZipEntry.annotated.java b/ojluni/annotations/mmodule/java/util/zip/ZipEntry.annotated.java
index 6c840f7..db001eb 100644
--- a/ojluni/annotations/mmodule/java/util/zip/ZipEntry.annotated.java
+++ b/ojluni/annotations/mmodule/java/util/zip/ZipEntry.annotated.java
@@ -39,7 +39,6 @@
 public ZipEntry(java.util.zip.ZipEntry e) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public long getDataOffset() { throw new RuntimeException("Stub!"); }
 
 public java.lang.String getName() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/javax/crypto/Cipher.annotated.java b/ojluni/annotations/mmodule/javax/crypto/Cipher.annotated.java
index 220eef6..ac3167a 100644
--- a/ojluni/annotations/mmodule/javax/crypto/Cipher.annotated.java
+++ b/ojluni/annotations/mmodule/javax/crypto/Cipher.annotated.java
@@ -120,7 +120,6 @@
 
 public final void updateAAD(java.nio.ByteBuffer src) { throw new RuntimeException("Stub!"); }
 
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @SystemApi(client = MODULE_LIBRARIES)
 public javax.crypto.CipherSpi getCurrentSpi() { throw new RuntimeException("Stub!"); }
 
diff --git a/ojluni/annotations/mmodule/javax/crypto/Mac.annotated.java b/ojluni/annotations/mmodule/javax/crypto/Mac.annotated.java
index 26bbeff..02dedec 100644
--- a/ojluni/annotations/mmodule/javax/crypto/Mac.annotated.java
+++ b/ojluni/annotations/mmodule/javax/crypto/Mac.annotated.java
@@ -76,7 +76,6 @@
 
 public final java.lang.Object clone() throws java.lang.CloneNotSupportedException { throw new RuntimeException("Stub!"); }
 
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @SystemApi(client = MODULE_LIBRARIES)
 public javax.crypto.MacSpi getCurrentSpi() { throw new RuntimeException("Stub!"); }
 }
diff --git a/ojluni/annotations/mmodule/javax/net/ssl/HttpsURLConnection.annotated.java b/ojluni/annotations/mmodule/javax/net/ssl/HttpsURLConnection.annotated.java
index 5177ba3..5b65388 100644
--- a/ojluni/annotations/mmodule/javax/net/ssl/HttpsURLConnection.annotated.java
+++ b/ojluni/annotations/mmodule/javax/net/ssl/HttpsURLConnection.annotated.java
@@ -44,7 +44,6 @@
     public void setHostnameVerifier(javax.net.ssl.HostnameVerifier v) { throw new RuntimeException("Stub!"); }
 
     @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public static javax.net.ssl.HostnameVerifier getStrictHostnameVerifier() { throw new RuntimeException("Stub!"); }
 
     public javax.net.ssl.HostnameVerifier getHostnameVerifier() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/mmodule/sun/misc/Cleaner.annotated.java b/ojluni/annotations/mmodule/sun/misc/Cleaner.annotated.java
index 06dddd4..6085df7 100644
--- a/ojluni/annotations/mmodule/sun/misc/Cleaner.annotated.java
+++ b/ojluni/annotations/mmodule/sun/misc/Cleaner.annotated.java
@@ -29,7 +29,6 @@
 import java.lang.ref.*;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public class Cleaner extends java.lang.ref.PhantomReference<java.lang.Object> {
@@ -39,11 +38,9 @@
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public static sun.misc.Cleaner create(java.lang.Object ob, java.lang.Runnable thunk) { throw new RuntimeException("Stub!"); }
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public void clean() { throw new RuntimeException("Stub!"); }
 }
diff --git a/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java
index f6e755e..2b83e0f 100644
--- a/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java
+++ b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java
@@ -27,7 +27,6 @@
 package sun.misc;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public final class Unsafe {
@@ -35,23 +34,19 @@
 private Unsafe() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public static sun.misc.Unsafe getUnsafe() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public long objectFieldOffset(java.lang.reflect.Field field) { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public int arrayBaseOffset(java.lang.Class clazz) { throw new RuntimeException("Stub!"); }
 
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public int arrayIndexScale(java.lang.Class clazz) { throw new RuntimeException("Stub!"); }
 
@@ -83,12 +78,10 @@
 public native java.lang.Object getObjectVolatile(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native int getInt(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putInt(java.lang.Object obj, long offset, int newValue);
 
@@ -96,12 +89,10 @@
 public native void putOrderedInt(java.lang.Object obj, long offset, int newValue);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native long getLong(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putLong(java.lang.Object obj, long offset, long newValue);
 
@@ -109,12 +100,10 @@
 public native void putOrderedLong(java.lang.Object obj, long offset, long newValue);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native java.lang.Object getObject(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putObject(java.lang.Object obj, long offset, java.lang.Object newValue);
 
@@ -122,22 +111,18 @@
 public native void putOrderedObject(java.lang.Object obj, long offset, java.lang.Object newValue);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native boolean getBoolean(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putBoolean(java.lang.Object obj, long offset, boolean newValue);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native byte getByte(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putByte(java.lang.Object obj, long offset, byte newValue);
 
@@ -154,22 +139,18 @@
 public native void putShort(java.lang.Object obj, long offset, short newValue);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native float getFloat(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putFloat(java.lang.Object obj, long offset, float newValue);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native double getDouble(java.lang.Object obj, long offset);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putDouble(java.lang.Object obj, long offset, double newValue);
 
@@ -198,12 +179,10 @@
 public native void setMemory(long address, long bytes, byte value);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native byte getByte(long address);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putByte(long address, byte x);
 
@@ -220,42 +199,34 @@
 public native void putChar(long address, char x);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native int getInt(long address);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putInt(long address, int x);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native long getLong(long address);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putLong(long address, long x);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native float getFloat(long address);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putFloat(long address, float x);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native double getDouble(long address);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void putDouble(long address, double x);
 
@@ -266,7 +237,6 @@
 public native void copyMemoryFromPrimitiveArray(java.lang.Object src, long srcOffset, long dstAddr, long bytes);
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public native void copyMemory(long srcAddr, long dstAddr, long bytes);
 
diff --git a/ojluni/annotations/mmodule/sun/security/jca/Providers.annotated.java b/ojluni/annotations/mmodule/sun/security/jca/Providers.annotated.java
index 476ebb5..cba2a22 100644
--- a/ojluni/annotations/mmodule/sun/security/jca/Providers.annotated.java
+++ b/ojluni/annotations/mmodule/sun/security/jca/Providers.annotated.java
@@ -32,7 +32,6 @@
 import java.security.NoSuchAlgorithmException;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public class Providers {
@@ -44,12 +43,10 @@
 public static java.security.Provider getSunProvider() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public static java.lang.Object startJarVerification() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public static void stopJarVerification(java.lang.Object obj) { throw new RuntimeException("Stub!"); }
 
diff --git a/ojluni/annotations/mmodule/sun/security/pkcs/PKCS7.annotated.java b/ojluni/annotations/mmodule/sun/security/pkcs/PKCS7.annotated.java
index 3bb1a66..79143ee 100644
--- a/ojluni/annotations/mmodule/sun/security/pkcs/PKCS7.annotated.java
+++ b/ojluni/annotations/mmodule/sun/security/pkcs/PKCS7.annotated.java
@@ -36,13 +36,11 @@
 import sun.security.x509.X500Name;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public class PKCS7 {
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public PKCS7(java.io.InputStream in) throws java.io.IOException, sun.security.pkcs.ParsingException { throw new RuntimeException("Stub!"); }
 
@@ -51,7 +49,6 @@
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public PKCS7(byte[] bytes) throws sun.security.pkcs.ParsingException { throw new RuntimeException("Stub!"); }
 
 @libcore.api.Hide
@@ -70,12 +67,10 @@
 public sun.security.pkcs.SignerInfo verify(sun.security.pkcs.SignerInfo info, byte[] bytes) throws java.security.NoSuchAlgorithmException, java.security.SignatureException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public sun.security.pkcs.SignerInfo verify(sun.security.pkcs.SignerInfo info, java.io.InputStream dataInputStream) throws java.io.IOException, java.security.NoSuchAlgorithmException, java.security.SignatureException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public sun.security.pkcs.SignerInfo[] verify(byte[] bytes) throws java.security.NoSuchAlgorithmException, java.security.SignatureException { throw new RuntimeException("Stub!"); }
 
@@ -93,14 +88,12 @@
 
 @libcore.api.Hide
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public java.security.cert.X509Certificate[] getCertificates() { throw new RuntimeException("Stub!"); }
 
 @libcore.api.Hide
 public java.security.cert.X509CRL[] getCRLs() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public sun.security.pkcs.SignerInfo[] getSignerInfos() { throw new RuntimeException("Stub!"); }
 
diff --git a/ojluni/annotations/mmodule/sun/security/pkcs/ParsingException.annotated.java b/ojluni/annotations/mmodule/sun/security/pkcs/ParsingException.annotated.java
index bdc70dc..a93d39c 100644
--- a/ojluni/annotations/mmodule/sun/security/pkcs/ParsingException.annotated.java
+++ b/ojluni/annotations/mmodule/sun/security/pkcs/ParsingException.annotated.java
@@ -33,7 +33,6 @@
 package sun.security.pkcs;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public class ParsingException extends java.io.IOException {
diff --git a/ojluni/annotations/mmodule/sun/security/pkcs/SignerInfo.annotated.java b/ojluni/annotations/mmodule/sun/security/pkcs/SignerInfo.annotated.java
index 6a85427..46b89c3 100644
--- a/ojluni/annotations/mmodule/sun/security/pkcs/SignerInfo.annotated.java
+++ b/ojluni/annotations/mmodule/sun/security/pkcs/SignerInfo.annotated.java
@@ -33,13 +33,11 @@
 import java.io.IOException;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public class SignerInfo implements sun.security.util.DerEncoder {
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public SignerInfo() { throw new RuntimeException("Stub!"); }
 
@@ -65,7 +63,6 @@
 public java.security.cert.X509Certificate getCertificate(sun.security.pkcs.PKCS7 block) throws java.io.IOException { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public java.util.ArrayList<java.security.cert.X509Certificate> getCertificateChain(sun.security.pkcs.PKCS7 block) throws java.io.IOException { throw new RuntimeException("Stub!"); }
 
diff --git a/ojluni/annotations/mmodule/sun/security/util/ObjectIdentifier.annotated.java b/ojluni/annotations/mmodule/sun/security/util/ObjectIdentifier.annotated.java
index 2892b72..b0a2994 100644
--- a/ojluni/annotations/mmodule/sun/security/util/ObjectIdentifier.annotated.java
+++ b/ojluni/annotations/mmodule/sun/security/util/ObjectIdentifier.annotated.java
@@ -27,13 +27,11 @@
 package sun.security.util;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public final class ObjectIdentifier implements java.io.Serializable {
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public ObjectIdentifier(java.lang.String oid) throws java.io.IOException { throw new RuntimeException("Stub!"); }
 
diff --git a/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java b/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java
index 0399caa..f403a1b 100644
--- a/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java
+++ b/ojluni/annotations/mmodule/sun/security/x509/AlgorithmId.annotated.java
@@ -28,7 +28,6 @@
 package sun.security.x509;
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 @libcore.api.Hide
 @SuppressWarnings({"unchecked", "deprecation", "all"})
@@ -39,7 +38,6 @@
 public AlgorithmId() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.Hide
 public AlgorithmId(sun.security.util.ObjectIdentifier oid) { throw new RuntimeException("Stub!"); }
 
@@ -63,7 +61,6 @@
 public final sun.security.util.ObjectIdentifier getOID() { throw new RuntimeException("Stub!"); }
 
 @android.annotation.SystemApi(client = android.annotation.SystemApi.Client.MODULE_LIBRARIES)
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 @libcore.api.IntraCoreApi
 @libcore.api.Hide
 public java.lang.String getName() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/sdk/nullability/java/io/ByteArrayOutputStream.annotated.java b/ojluni/annotations/sdk/nullability/java/io/ByteArrayOutputStream.annotated.java
index 3fdca11..a642f85 100644
--- a/ojluni/annotations/sdk/nullability/java/io/ByteArrayOutputStream.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/io/ByteArrayOutputStream.annotated.java
@@ -50,6 +50,8 @@
 
 @libcore.util.NonNull public synchronized java.lang.String toString(@libcore.util.NonNull java.lang.String charsetName) throws java.io.UnsupportedEncodingException { throw new RuntimeException("Stub!"); }
 
+@libcore.util.NonNull public synchronized java.lang.String toString(@libcore.util.NonNull java.nio.charset.Charset charset) { throw new RuntimeException("Stub!"); }
+
 @Deprecated
 @libcore.util.NonNull public synchronized java.lang.String toString(int hibyte) { throw new RuntimeException("Stub!"); }
 
diff --git a/ojluni/annotations/sdk/nullability/java/io/PrintWriter.annotated.java b/ojluni/annotations/sdk/nullability/java/io/PrintWriter.annotated.java
index 531dfb0..9c3a936 100644
--- a/ojluni/annotations/sdk/nullability/java/io/PrintWriter.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/io/PrintWriter.annotated.java
@@ -41,12 +41,18 @@
 
 public PrintWriter(@libcore.util.NonNull java.io.OutputStream out, boolean autoFlush) { throw new RuntimeException("Stub!"); }
 
+public PrintWriter(@libcore.util.NonNull java.io.OutputStream out, boolean autoFlush, @libcore.util.NonNull java.nio.charset.Charset charset) { throw new RuntimeException("Stub!"); }
+
 public PrintWriter(@libcore.util.NonNull java.lang.String fileName) throws java.io.FileNotFoundException { throw new RuntimeException("Stub!"); }
 
 public PrintWriter(@libcore.util.NonNull java.lang.String fileName, @libcore.util.NonNull java.lang.String csn) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException { throw new RuntimeException("Stub!"); }
 
+public PrintWriter(@libcore.util.NonNull java.lang.String fileName, @libcore.util.NonNull java.nio.charset.Charset charset) throws java.io.IOException { throw new RuntimeException("Stub!"); }
+
 public PrintWriter(@libcore.util.NonNull java.io.File file) throws java.io.FileNotFoundException { throw new RuntimeException("Stub!"); }
 
+public PrintWriter(@libcore.util.NonNull java.io.File file, @libcore.util.NonNull java.nio.charset.Charset charset) throws java.io.IOException { throw new RuntimeException("Stub!"); }
+
 public PrintWriter(@libcore.util.NonNull java.io.File file, @libcore.util.NonNull java.lang.String csn) throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException { throw new RuntimeException("Stub!"); }
 
 public void flush() { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/sdk/nullability/java/lang/Integer.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/Integer.annotated.java
index d3f6753..f06aa0b 100644
--- a/ojluni/annotations/sdk/nullability/java/lang/Integer.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/lang/Integer.annotated.java
@@ -53,10 +53,14 @@
 
 public static int parseInt(@libcore.util.NonNull java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
+public static int parseInt(@libcore.util.NonNull java.lang.CharSequence s, int beginIndex, int endIndex, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
+
 public static int parseUnsignedInt(@libcore.util.NonNull java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
 public static int parseUnsignedInt(@libcore.util.NonNull java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
+public static int parseUnsignedInt(@libcore.util.NonNull java.lang.CharSequence s, int beginIndex, int endIndex, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
+
 @libcore.util.NonNull public static java.lang.Integer valueOf(@libcore.util.NonNull java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
 @libcore.util.NonNull public static java.lang.Integer valueOf(@libcore.util.NonNull java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/sdk/nullability/java/lang/Long.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/Long.annotated.java
index b077ef5..7e9e6f5 100644
--- a/ojluni/annotations/sdk/nullability/java/lang/Long.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/lang/Long.annotated.java
@@ -54,10 +54,14 @@
 
 public static long parseLong(@libcore.util.NonNull java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
+public static long parseLong(@libcore.util.NonNull java.lang.CharSequence s, int beginIndex, int endIndex, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
+
 public static long parseUnsignedLong(@libcore.util.NonNull java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
 public static long parseUnsignedLong(@libcore.util.NonNull java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
+public static long parseUnsignedLong(@libcore.util.NonNull java.lang.CharSequence s, int beginIndex, int endIndex, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
+
 @libcore.util.NonNull public static java.lang.Long valueOf(@libcore.util.NonNull java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
 
 @libcore.util.NonNull public static java.lang.Long valueOf(@libcore.util.NonNull java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
diff --git a/ojluni/annotations/sdk/nullability/java/lang/String.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/String.annotated.java
index a8cf1de..28415ff 100644
--- a/ojluni/annotations/sdk/nullability/java/lang/String.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/lang/String.annotated.java
@@ -35,6 +35,7 @@
 import java.util.Locale;
 import java.util.Formatter;
 import java.util.Comparator;
+import java.util.stream.Stream;
 
 @SuppressWarnings({"unchecked", "deprecation", "all"})
 public final class String implements java.io.Serializable, java.lang.Comparable<java.lang.String>, java.lang.CharSequence {
@@ -171,6 +172,16 @@
 
 @libcore.util.NonNull public java.lang.String trim() { throw new RuntimeException("Stub!"); }
 
+@libcore.util.NonNull public java.lang.String strip() { throw new RuntimeException("Stub!"); }
+
+@libcore.util.NonNull public java.lang.String stripLeading() { throw new RuntimeException("Stub!"); }
+
+@libcore.util.NonNull public java.lang.String stripTrailing() { throw new RuntimeException("Stub!"); }
+
+public boolean isBlank() { throw new RuntimeException("Stub!"); }
+
+@libcore.util.NonNull public java.util.stream.Stream<String> lines() { throw new RuntimeException("Stub!"); }
+
 @libcore.util.NonNull public java.lang.String toString() { throw new RuntimeException("Stub!"); }
 
 public native char[] toCharArray();
@@ -203,6 +214,8 @@
 
 @libcore.util.NonNull public native java.lang.String intern();
 
+@libcore.util.NonNull public java.lang.String repeat(int count) { throw new RuntimeException("Stub!"); }
+
 public static final java.util.Comparator<java.lang.String> CASE_INSENSITIVE_ORDER;
 static { CASE_INSENSITIVE_ORDER = null; }
 }
diff --git a/ojluni/annotations/sdk/nullability/java/lang/Thread.annotated.java b/ojluni/annotations/sdk/nullability/java/lang/Thread.annotated.java
index 6b21f17..e43882a 100644
--- a/ojluni/annotations/sdk/nullability/java/lang/Thread.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/lang/Thread.annotated.java
@@ -53,6 +53,8 @@
 
 public Thread(@libcore.util.Nullable java.lang.ThreadGroup group, @libcore.util.Nullable java.lang.Runnable target, @libcore.util.NonNull java.lang.String name, long stackSize) { throw new RuntimeException("Stub!"); }
 
+public Thread(@libcore.util.Nullable java.lang.ThreadGroup group, @libcore.util.Nullable java.lang.Runnable target, @libcore.util.NonNull java.lang.String name, long stackSize, boolean inheritThreadLocals) { throw new RuntimeException("Stub!"); }
+
 @libcore.util.NonNull public static native java.lang.Thread currentThread();
 
 public static native void yield();
diff --git a/ojluni/annotations/sdk/nullability/java/math/BigInteger.annotated.java b/ojluni/annotations/sdk/nullability/java/math/BigInteger.annotated.java
new file mode 100644
index 0000000..e8f71c4
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/math/BigInteger.annotated.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.math;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public class BigInteger extends java.lang.Number implements java.lang.Comparable<java.math.BigInteger> {
+
+    public BigInteger(byte[] val, int off, int len) { throw new RuntimeException("Stub!"); }
+
+    public BigInteger(byte[] val) { throw new RuntimeException("Stub!"); }
+
+    public BigInteger(int signum, byte[] magnitude, int off, int len) { throw new RuntimeException("Stub!"); }
+
+    public BigInteger(int signum, byte[] magnitude) { throw new RuntimeException("Stub!"); }
+
+    public BigInteger(@libcore.util.NonNull java.lang.String val, int radix) { throw new RuntimeException("Stub!"); }
+
+    public BigInteger(@libcore.util.NonNull java.lang.String val) { throw new RuntimeException("Stub!"); }
+
+    public BigInteger(int numBits, @libcore.util.NonNull java.util.Random rnd) { throw new RuntimeException("Stub!"); }
+
+    public BigInteger(int bitLength, int certainty, @libcore.util.NonNull java.util.Random rnd) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public static BigInteger probablePrime(int bitLength, @libcore.util.NonNull java.util.Random rnd) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger nextProbablePrime() { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull private static BigInteger lucasLehmerSequence(int z, @libcore.util.NonNull BigInteger k, @libcore.util.NonNull BigInteger n) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public static BigInteger valueOf(long val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public static final BigInteger ZERO = null;
+
+    @libcore.util.NonNull public static final BigInteger ONE = null;
+
+    @libcore.util.NonNull public static final java.math.BigInteger TWO = null;
+
+    @libcore.util.NonNull public static final BigInteger TEN = null;
+
+    @libcore.util.NonNull public BigInteger add(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger subtract(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger multiply(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger divide(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger[] divideAndRemainder(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger remainder(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger pow(int exponent) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger gcd(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger abs() { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger negate() { throw new RuntimeException("Stub!"); }
+
+    public int signum() { return 0; }
+
+    @libcore.util.NonNull public BigInteger sqrt() { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger[] sqrtAndRemainder() { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger mod(@libcore.util.NonNull BigInteger m) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger modPow(@libcore.util.NonNull BigInteger exponent, @libcore.util.NonNull BigInteger m) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger modInverse(@libcore.util.NonNull BigInteger m) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger shiftLeft(int n) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger shiftRight(int n) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger and(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger or(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger xor(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger not() { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger andNot(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    public boolean testBit(int n) { return 0; }
+
+    @libcore.util.NonNull public BigInteger setBit(int n) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger clearBit(int n) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger flipBit(int n) { throw new RuntimeException("Stub!"); }
+
+    public int getLowestSetBit() { return 0; }
+
+    public int bitLength() { return 0; }
+
+    public int bitCount() { return 0; }
+
+    public boolean isProbablePrime(int certainty) { return false; }
+
+    public int compareTo(@libcore.util.NonNull BigInteger val) { return 0; }
+
+    public boolean equals(@libcore.util.NonNull Object x) { return false; }
+
+    @libcore.util.NonNull public BigInteger min(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public BigInteger max(@libcore.util.NonNull BigInteger val) { throw new RuntimeException("Stub!"); }
+
+    public int hashCode() { return 0; }
+
+    @libcore.util.NonNull public java.lang.String toString(int radix) { throw new RuntimeException("Stub!"); }
+
+    @libcore.util.NonNull public java.lang.String toString() { throw new RuntimeException("Stub!"); }
+
+    public byte[] toByteArray() { return null; }
+
+    public int intValue() { return 0; }
+
+    public long longValue() { return 0L; }
+
+    public float floatValue() { return 0.0f; }
+
+    public double doubleValue() { return 0.0; }
+
+    public long longValueExact() { return 0L; }
+
+    public int intValueExact() { return 0; }
+
+    public short shortValueExact() { return 0; }
+
+    public byte byteValueExact() { return 0; }
+}
diff --git a/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java b/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java
index 30c82ec..adea368 100644
--- a/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/nio/ByteBuffer.annotated.java
@@ -100,6 +100,8 @@
 
 @libcore.util.NonNull public final java.nio.ByteBuffer order(@libcore.util.NonNull java.nio.ByteOrder bo) { throw new RuntimeException("Stub!"); }
 
+@libcore.util.NonNull public final java.nio.ByteBuffer alignedSlice(int unitSize) { throw new RuntimeException("Stub!"); }
+
 public abstract char getChar();
 
 @libcore.util.NonNull public abstract java.nio.ByteBuffer putChar(char value);
diff --git a/ojluni/annotations/sdk/nullability/java/security/spec/EdECPoint.annotated.java b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPoint.annotated.java
new file mode 100644
index 0000000..6f38c4e
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPoint.annotated.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Objects;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class EdECPoint {
+
+    public EdECPoint(boolean xOdd, @libcore.util.NonNull BigInteger y) { throw new RuntimeException("Stub!"); }
+    public boolean isXOdd(){ throw new RuntimeException("Stub!"); }
+    public @libcore.util.NonNull BigInteger getY(){ throw new RuntimeException("Stub!"); }
+}
diff --git a/ojluni/annotations/sdk/nullability/java/security/spec/EdECPrivateKeySpec.annotated.java b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPrivateKeySpec.annotated.java
new file mode 100644
index 0000000..2dbeefb
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPrivateKeySpec.annotated.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+public final class EdECPrivateKeySpec implements KeySpec {
+    public EdECPrivateKeySpec(@libcore.util.NonNull NamedParameterSpec params, @libcore.util.NonNull byte[] bytes) { throw new RuntimeException("Stub!"); }
+    public @libcore.util.NonNull NamedParameterSpec getParams(){ throw new RuntimeException("Stub!"); }
+    public @libcore.util.NonNull byte[] getBytes() { throw new RuntimeException("Stub!"); }
+}
diff --git a/ojluni/annotations/sdk/nullability/java/security/spec/EdECPublicKeySpec.annotated.java b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPublicKeySpec.annotated.java
new file mode 100644
index 0000000..0f6401b
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/security/spec/EdECPublicKeySpec.annotated.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+public final class EdECPublicKeySpec implements KeySpec {
+    public EdECPublicKeySpec(@libcore.util.NonNull NamedParameterSpec params, @libcore.util.NonNull EdECPoint point) { throw new RuntimeException("Stub!"); }
+    public @libcore.util.NonNull NamedParameterSpec getParams() { throw new RuntimeException("Stub!"); }
+    public @libcore.util.NonNull EdECPoint getPoint() { throw new RuntimeException("Stub!"); }
+}
diff --git a/ojluni/annotations/sdk/nullability/java/security/spec/NamedParameterSpec.annotated.java b/ojluni/annotations/sdk/nullability/java/security/spec/NamedParameterSpec.annotated.java
new file mode 100644
index 0000000..ad9bcae
--- /dev/null
+++ b/ojluni/annotations/sdk/nullability/java/security/spec/NamedParameterSpec.annotated.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public class NamedParameterSpec implements java.security.spec.AlgorithmParameterSpec {
+
+public NamedParameterSpec(@libcore.util.NonNull java.lang.String stdName) { throw new RuntimeException("Stub!"); }
+
+public @libcore.util.NonNull java.lang.String getName() { throw new RuntimeException("Stub!"); }
+
+public static final java.security.spec.NamedParameterSpec X25519;
+static { X25519 = null; }
+
+public static final java.security.spec.NamedParameterSpec X448;
+static { X448 = null; }
+}
+
diff --git a/ojluni/annotations/sdk/nullability/java/util/Arrays.annotated.java b/ojluni/annotations/sdk/nullability/java/util/Arrays.annotated.java
index 99dec24..891f9b9 100644
--- a/ojluni/annotations/sdk/nullability/java/util/Arrays.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/util/Arrays.annotated.java
@@ -169,22 +169,44 @@
 
 public static boolean equals(long @libcore.util.Nullable [] a, long @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(long @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, long @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(int @libcore.util.Nullable [] a, int @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(int @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, int @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(short @libcore.util.Nullable [] a, short @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(short @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, short @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(char @libcore.util.Nullable [] a, char @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(char @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, char @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(byte @libcore.util.Nullable [] a, byte @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(byte @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, byte @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(boolean @libcore.util.Nullable [] a, boolean @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(boolean @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, boolean @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(double @libcore.util.Nullable [] a, double @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(double @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, double @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(float @libcore.util.Nullable [] a, float @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(float @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, float @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
 public static boolean equals(java.lang.@libcore.util.Nullable Object @libcore.util.Nullable [] a, java.lang.@libcore.util.Nullable Object @libcore.util.Nullable [] a2) { throw new RuntimeException("Stub!"); }
 
+public static boolean equals(java.lang.@libcore.util.Nullable java.lang.Object @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, java.lang.@libcore.util.Nullable java.lang.Object @libcore.util.NonNull[] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static <T> boolean equals(T @libcore.util.Nullable[] a, T @libcore.util.Nullable [] a2, @libcore.util.NonNull java.util.Comparator<? super T> cmp) { throw new RuntimeException("Stub!"); }
+
+public static <T> boolean equals(T @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, T @libcore.util.NonNull [] b, int bFromIndex, int bToIndex, @libcore.util.NonNull java.util.Comparator<? super T> cmp) { throw new RuntimeException("Stub!"); }
+
 public static void fill(long @libcore.util.NonNull [] a, long val) { throw new RuntimeException("Stub!"); }
 
 public static void fill(long @libcore.util.NonNull [] a, int fromIndex, int toIndex, long val) { throw new RuntimeException("Stub!"); }
@@ -353,4 +375,100 @@
 @libcore.util.NonNull public static java.util.stream.DoubleStream stream(double @libcore.util.NonNull [] array) { throw new RuntimeException("Stub!"); }
 
 @libcore.util.NonNull public static java.util.stream.DoubleStream stream(double @libcore.util.NonNull [] array, int startInclusive, int endExclusive) { throw new RuntimeException("Stub!"); }
+
+public static int compare(boolean @libcore.util.Nullable [] a, boolean @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(boolean @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, boolean @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compare(byte @libcore.util.Nullable [] a, byte @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(byte @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, byte @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(byte @libcore.util.Nullable [] a, byte @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(byte @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, byte @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compare(short @libcore.util.Nullable [] a, short @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(short @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, short @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(short @libcore.util.Nullable [] a, short @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(short @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, short @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compare(char @libcore.util.Nullable [] a, char @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(char @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, char @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compare(int @libcore.util.Nullable [] a, int @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(int @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, int @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(int @libcore.util.Nullable [] a, int @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(int @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, int @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compare(long @libcore.util.Nullable [] a, long @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(long @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, long @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(long @libcore.util.Nullable [] a, long @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compareUnsigned(long @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, long @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compare(float @libcore.util.Nullable [] a, float @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(float @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, float @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int compare(double @libcore.util.Nullable [] a, double @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static int compare(double @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, double @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static <T extends java.lang.Comparable<? super T>> int compare(T @libcore.util.Nullable [] a, T @libcore.util.Nullable [] b) { throw new RuntimeException("Stub!"); }
+
+public static <T extends java.lang.Comparable<? super T>> int compare(T @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, T @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static <T> int compare(T @libcore.util.Nullable [] a, T @libcore.utill.Nullable [] b, @libcore.util.NonNull java.util.Comparator<? super T> cmp) { throw new RuntimeException("Stub!"); }
+
+public static <T> int compare(T @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, T @libcore.util.NonNull [] b, int bFromIndex, int bToIndex, @libcore.util.NonNull java.util.Comparator<? super T> cmp) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(boolean @libcore.util.NonNull [] a, boolean @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(boolean @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, boolean @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(byte @libcore.util.NonNull [] a, byte @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(char @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, char @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(char @libcore.util.NonNull [] a, char @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(char @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, char @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(short @libcore.util.NonNull [] a, short @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(short @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, short @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(int @libcore.util.NonNull [] a, int @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(int @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, int @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(long @libcore.util.NonNull [] a, long @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(long @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, long @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(float @libcore.util.NonNull [] a, float @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(float @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, float @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(double @libcore.util.NonNull [] a, double @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(double @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, double @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(java.lang.Object @libcore.util.NonNull [] a, java.lang.Object @libcore.util.NonNull [] b) { throw new RuntimeException("Stub!"); }
+
+public static int mismatch(java.lang.Object @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, java.lang.Object @libcore.util.NonNull [] b, int bFromIndex, int bToIndex) { throw new RuntimeException("Stub!"); }
+
+public static <T> int mismatch(T @libcore.util.NonNull [] a, T @libcore.util.NonNull [] b, @libcore.util.NonNull java.util.Comparator<? super T> cmp) { throw new RuntimeException("Stub!"); }
+
+public static <T> int mismatch(T @libcore.util.NonNull [] a, int aFromIndex, int aToIndex, T @libcore.util.NonNull [] b, int bFromIndex, int bToIndex, @libcore.util.NonNull java.util.Comparator<? super T> cmp) { throw new RuntimeException("Stub!"); }
 }
diff --git a/ojluni/annotations/sdk/nullability/java/util/Collection.annotated.java b/ojluni/annotations/sdk/nullability/java/util/Collection.annotated.java
index d2f425f..d58d9a4 100644
--- a/ojluni/annotations/sdk/nullability/java/util/Collection.annotated.java
+++ b/ojluni/annotations/sdk/nullability/java/util/Collection.annotated.java
@@ -44,6 +44,8 @@
 
 public <T> T @libcore.util.NonNull [] toArray(T @libcore.util.NonNull [] a);
 
+@libcore.util.NonNull public default <T> T @libcore.util.NonNull [] toArray(@libcore.util.NonNull java.util.function.IntFunction<@libcore.util.NullFromTypeParam T @libcore.util.NonNull []> g);
+
 public boolean add(@libcore.util.NullFromTypeParam E e);
 
 public boolean remove(@libcore.util.Nullable java.lang.Object o);
diff --git a/ojluni/src/main/java/java/io/BufferedOutputStream.java b/ojluni/src/main/java/java/io/BufferedOutputStream.java
index 0579704..f114485 100644
--- a/ojluni/src/main/java/java/io/BufferedOutputStream.java
+++ b/ojluni/src/main/java/java/io/BufferedOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,10 +32,9 @@
  * system for each byte written.
  *
  * @author  Arthur van Hoff
- * @since   JDK1.0
+ * @since   1.0
  */
-public
-class BufferedOutputStream extends FilterOutputStream {
+public class BufferedOutputStream extends FilterOutputStream {
     /**
      * The internal buffer where data is stored.
      */
@@ -43,8 +42,8 @@
 
     /**
      * The number of valid bytes in the buffer. This value is always
-     * in the range <tt>0</tt> through <tt>buf.length</tt>; elements
-     * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid
+     * in the range {@code 0} through {@code buf.length}; elements
+     * {@code buf[0]} through {@code buf[count-1]} contain valid
      * byte data.
      */
     protected int count;
@@ -90,6 +89,7 @@
      * @param      b   the byte to be written.
      * @exception  IOException  if an I/O error occurs.
      */
+    @Override
     public synchronized void write(int b) throws IOException {
         if (count >= buf.length) {
             flushBuffer();
diff --git a/ojluni/src/main/java/java/io/BufferedReader.java b/ojluni/src/main/java/java/io/BufferedReader.java
index fb814b1..384b286 100644
--- a/ojluni/src/main/java/java/io/BufferedReader.java
+++ b/ojluni/src/main/java/java/io/BufferedReader.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,7 @@
  * @see java.nio.file.Files#newBufferedReader
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class BufferedReader extends Reader {
@@ -283,6 +283,7 @@
      *             stream has been reached
      *
      * @exception  IOException  If an I/O error occurs
+     * @exception  IndexOutOfBoundsException {@inheritDoc}
      */
     public int read(char cbuf[], int off, int len) throws IOException {
         synchronized (lock) {
@@ -307,21 +308,22 @@
 
     /**
      * Reads a line of text.  A line is considered to be terminated by any one
-     * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
-     * followed immediately by a linefeed.
+     * of a line feed ('\n'), a carriage return ('\r'), a carriage return
+     * followed immediately by a line feed, or by reaching the end-of-file
+     * (EOF).
      *
      * @param      ignoreLF  If true, the next '\n' will be skipped
      *
      * @return     A String containing the contents of the line, not including
      *             any line-termination characters, or null if the end of the
-     *             stream has been reached
+     *             stream has been reached without reading any characters
      *
      * @see        java.io.LineNumberReader#readLine()
      *
      * @exception  IOException  If an I/O error occurs
      */
     String readLine(boolean ignoreLF) throws IOException {
-        StringBuffer s = null;
+        StringBuilder s = null;
         int startChar;
 
         synchronized (lock) {
@@ -377,7 +379,7 @@
                 }
 
                 if (s == null)
-                    s = new StringBuffer(defaultExpectedLineLength);
+                    s = new StringBuilder(defaultExpectedLineLength);
                 s.append(cb, startChar, i - startChar);
             }
         }
@@ -385,12 +387,13 @@
 
     /**
      * Reads a line of text.  A line is considered to be terminated by any one
-     * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
-     * followed immediately by a linefeed.
+     * of a line feed ('\n'), a carriage return ('\r'), a carriage return
+     * followed immediately by a line feed, or by reaching the end-of-file
+     * (EOF).
      *
      * @return     A String containing the contents of the line, not including
      *             any line-termination characters, or null if the end of the
-     *             stream has been reached
+     *             stream has been reached without reading any characters
      *
      * @exception  IOException  If an I/O error occurs
      *
@@ -570,7 +573,7 @@
      * @since 1.8
      */
     public Stream<String> lines() {
-        Iterator<String> iter = new Iterator<String>() {
+        Iterator<String> iter = new Iterator<>() {
             String nextLine = null;
 
             @Override
diff --git a/ojluni/src/main/java/java/io/BufferedWriter.java b/ojluni/src/main/java/java/io/BufferedWriter.java
index a5d810a..3d8e1ee 100644
--- a/ojluni/src/main/java/java/io/BufferedWriter.java
+++ b/ojluni/src/main/java/java/io/BufferedWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
  * The default is large enough for most purposes.
  *
  * <p> A newLine() method is provided, which uses the platform's own notion of
- * line separator as defined by the system property <tt>line.separator</tt>.
+ * line separator as defined by the system property {@code line.separator}.
  * Not all platforms use the newline character ('\n') to terminate lines.
  * Calling this method to terminate each output line is therefore preferred to
  * writing a newline character directly.
@@ -60,7 +60,7 @@
  * @see java.nio.file.Files#newBufferedWriter
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class BufferedWriter extends Writer {
@@ -73,12 +73,6 @@
     private static int defaultCharBufferSize = 8192;
 
     /**
-     * Line separator string.  This is the value of the line.separator
-     * property at the moment that the stream was created.
-     */
-    private String lineSeparator;
-
-    /**
      * Creates a buffered character-output stream that uses a default-sized
      * output buffer.
      *
@@ -105,9 +99,6 @@
         cb = new char[sz];
         nChars = sz;
         nextChar = 0;
-
-        lineSeparator = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetPropertyAction("line.separator"));
     }
 
     /** Checks to make sure that the stream has not been closed */
@@ -162,13 +153,18 @@
      * needed.  If the requested length is at least as large as the buffer,
      * however, then this method will flush the buffer and write the characters
      * directly to the underlying stream.  Thus redundant
-     * <code>BufferedWriter</code>s will not copy data unnecessarily.
+     * {@code BufferedWriter}s will not copy data unnecessarily.
      *
      * @param  cbuf  A character array
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to write
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         synchronized (lock) {
@@ -204,17 +200,24 @@
     /**
      * Writes a portion of a String.
      *
-     * <p> If the value of the <tt>len</tt> parameter is negative then no
-     * characters are written.  This is contrary to the specification of this
-     * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int)
-     * superclass}, which requires that an {@link IndexOutOfBoundsException} be
-     * thrown.
+     * @implSpec
+     * While the specification of this method in the
+     * {@linkplain java.io.Writer#write(java.lang.String,int,int) superclass}
+     * recommends that an {@link IndexOutOfBoundsException} be thrown
+     * if {@code len} is negative or {@code off + len} is negative,
+     * the implementation in this class does not throw such an exception in
+     * these cases but instead simply writes no characters.
      *
      * @param  s     String to be written
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative,
+     *          or {@code off + len} is greater than the length
+     *          of the given string
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String s, int off, int len) throws IOException {
         synchronized (lock) {
@@ -234,13 +237,13 @@
 
     /**
      * Writes a line separator.  The line separator string is defined by the
-     * system property <tt>line.separator</tt>, and is not necessarily a single
+     * system property {@code line.separator}, and is not necessarily a single
      * newline ('\n') character.
      *
      * @exception  IOException  If an I/O error occurs
      */
     public void newLine() throws IOException {
-        write(lineSeparator);
+        write(System.lineSeparator());
     }
 
     /**
diff --git a/ojluni/src/main/java/java/io/ByteArrayInputStream.java b/ojluni/src/main/java/java/io/ByteArrayInputStream.java
index d07f074..cb20f8c 100644
--- a/ojluni/src/main/java/java/io/ByteArrayInputStream.java
+++ b/ojluni/src/main/java/java/io/ByteArrayInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,30 +25,32 @@
 
 package java.io;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 /**
- * A <code>ByteArrayInputStream</code> contains
+ * A {@code ByteArrayInputStream} contains
  * an internal buffer that contains bytes that
  * may be read from the stream. An internal
  * counter keeps track of the next byte to
- * be supplied by the <code>read</code> method.
+ * be supplied by the {@code read} method.
  * <p>
- * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
+ * Closing a {@code ByteArrayInputStream} has no effect. The methods in
  * this class can be called after the stream has been closed without
- * generating an <tt>IOException</tt>.
+ * generating an {@code IOException}.
  *
  * @author  Arthur van Hoff
  * @see     java.io.StringBufferInputStream
- * @since   JDK1.0
+ * @since   1.0
  */
-public
-class ByteArrayInputStream extends InputStream {
+public class ByteArrayInputStream extends InputStream {
 
     /**
      * An array of bytes that was provided
-     * by the creator of the stream. Elements <code>buf[0]</code>
-     * through <code>buf[count-1]</code> are the
+     * by the creator of the stream. Elements {@code buf[0]}
+     * through {@code buf[count-1]} are the
      * only bytes that can ever be read from the
-     * stream;  element <code>buf[pos]</code> is
+     * stream;  element {@code buf[pos]} is
      * the next byte to be read.
      */
     protected byte buf[];
@@ -56,9 +58,9 @@
     /**
      * The index of the next character to read from the input stream buffer.
      * This value should always be nonnegative
-     * and not larger than the value of <code>count</code>.
+     * and not larger than the value of {@code count}.
      * The next byte to be read from the input stream buffer
-     * will be <code>buf[pos]</code>.
+     * will be {@code buf[pos]}.
      */
     protected int pos;
 
@@ -66,14 +68,14 @@
      * The currently marked position in the stream.
      * ByteArrayInputStream objects are marked at position zero by
      * default when constructed.  They may be marked at another
-     * position within the buffer by the <code>mark()</code> method.
+     * position within the buffer by the {@code mark()} method.
      * The current buffer position is set to this point by the
-     * <code>reset()</code> method.
+     * {@code reset()} method.
      * <p>
      * If no mark has been set, then the value of mark is the offset
      * passed to the constructor (or 0 if the offset was not supplied).
      *
-     * @since   JDK1.1
+     * @since   1.1
      */
     protected int mark = 0;
 
@@ -81,22 +83,22 @@
      * The index one greater than the last valid character in the input
      * stream buffer.
      * This value should always be nonnegative
-     * and not larger than the length of <code>buf</code>.
+     * and not larger than the length of {@code buf}.
      * It  is one greater than the position of
-     * the last byte within <code>buf</code> that
+     * the last byte within {@code buf} that
      * can ever be read  from the input stream buffer.
      */
     protected int count;
 
     /**
-     * Creates a <code>ByteArrayInputStream</code>
-     * so that it  uses <code>buf</code> as its
+     * Creates a {@code ByteArrayInputStream}
+     * so that it  uses {@code buf} as its
      * buffer array.
      * The buffer array is not copied.
-     * The initial value of <code>pos</code>
-     * is <code>0</code> and the initial value
-     * of  <code>count</code> is the length of
-     * <code>buf</code>.
+     * The initial value of {@code pos}
+     * is {@code 0} and the initial value
+     * of  {@code count} is the length of
+     * {@code buf}.
      *
      * @param   buf   the input buffer.
      */
@@ -107,12 +109,12 @@
     }
 
     /**
-     * Creates <code>ByteArrayInputStream</code>
-     * that uses <code>buf</code> as its
-     * buffer array. The initial value of <code>pos</code>
-     * is <code>offset</code> and the initial value
-     * of <code>count</code> is the minimum of <code>offset+length</code>
-     * and <code>buf.length</code>.
+     * Creates {@code ByteArrayInputStream}
+     * that uses {@code buf} as its
+     * buffer array. The initial value of {@code pos}
+     * is {@code offset} and the initial value
+     * of {@code count} is the minimum of {@code offset+length}
+     * and {@code buf.length}.
      * The buffer array is not copied. The buffer's mark is
      * set to the specified offset.
      *
@@ -129,15 +131,15 @@
 
     /**
      * Reads the next byte of data from this input stream. The value
-     * byte is returned as an <code>int</code> in the range
-     * <code>0</code> to <code>255</code>. If no byte is available
+     * byte is returned as an {@code int} in the range
+     * {@code 0} to {@code 255}. If no byte is available
      * because the end of the stream has been reached, the value
-     * <code>-1</code> is returned.
+     * {@code -1} is returned.
      * <p>
-     * This <code>read</code> method
+     * This {@code read} method
      * cannot block.
      *
-     * @return  the next byte of data, or <code>-1</code> if the end of the
+     * @return  the next byte of data, or {@code -1} if the end of the
      *          stream has been reached.
      */
     public synchronized int read() {
@@ -145,40 +147,30 @@
     }
 
     /**
-     * Reads up to <code>len</code> bytes of data into an array of bytes
-     * from this input stream.
-     * If <code>pos</code> equals <code>count</code>,
-     * then <code>-1</code> is returned to indicate
-     * end of file. Otherwise, the  number <code>k</code>
-     * of bytes read is equal to the smaller of
-     * <code>len</code> and <code>count-pos</code>.
-     * If <code>k</code> is positive, then bytes
-     * <code>buf[pos]</code> through <code>buf[pos+k-1]</code>
-     * are copied into <code>b[off]</code>  through
-     * <code>b[off+k-1]</code> in the manner performed
-     * by <code>System.arraycopy</code>. The
-     * value <code>k</code> is added into <code>pos</code>
-     * and <code>k</code> is returned.
+     * Reads up to {@code len} bytes of data into an array of bytes from this
+     * input stream.  If {@code pos} equals {@code count}, then {@code -1} is
+     * returned to indicate end of file.  Otherwise, the  number {@code k} of
+     * bytes read is equal to the smaller of {@code len} and {@code count-pos}.
+     * If {@code k} is positive, then bytes {@code buf[pos]} through
+     * {@code buf[pos+k-1]} are copied into {@code b[off]} through
+     * {@code b[off+k-1]} in the manner performed by {@code System.arraycopy}.
+     * The value {@code k} is added into {@code pos} and {@code k} is returned.
      * <p>
-     * This <code>read</code> method cannot block.
+     * This {@code read} method cannot block.
      *
      * @param   b     the buffer into which the data is read.
-     * @param   off   the start offset in the destination array <code>b</code>
+     * @param   off   the start offset in the destination array {@code b}
      * @param   len   the maximum number of bytes read.
      * @return  the total number of bytes read into the buffer, or
-     *          <code>-1</code> if there is no more data because the end of
+     *          {@code -1} if there is no more data because the end of
      *          the stream has been reached.
-     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
-     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
-     * <code>len</code> is negative, or <code>len</code> is greater than
-     * <code>b.length - off</code>
+     * @throws  NullPointerException If {@code b} is {@code null}.
+     * @throws  IndexOutOfBoundsException If {@code off} is negative,
+     * {@code len} is negative, or {@code len} is greater than
+     * {@code b.length - off}
      */
     public synchronized int read(byte b[], int off, int len) {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        }
+        Objects.checkFromIndexSize(off, len, b.length);
 
         if (pos >= count) {
             return -1;
@@ -196,14 +188,32 @@
         return len;
     }
 
+    public synchronized byte[] readAllBytes() {
+        byte[] result = Arrays.copyOfRange(buf, pos, count);
+        pos = count;
+        return result;
+    }
+
+    public int readNBytes(byte[] b, int off, int len) {
+        int n = read(b, off, len);
+        return n == -1 ? 0 : n;
+    }
+
+    public synchronized long transferTo(OutputStream out) throws IOException {
+        int len = count - pos;
+        out.write(buf, pos, len);
+        pos = count;
+        return len;
+    }
+
     /**
-     * Skips <code>n</code> bytes of input from this input stream. Fewer
+     * Skips {@code n} bytes of input from this input stream. Fewer
      * bytes might be skipped if the end of the input stream is reached.
-     * The actual number <code>k</code>
+     * The actual number {@code k}
      * of bytes to be skipped is equal to the smaller
-     * of <code>n</code> and  <code>count-pos</code>.
-     * The value <code>k</code> is added into <code>pos</code>
-     * and <code>k</code> is returned.
+     * of {@code n} and  {@code count-pos}.
+     * The value {@code k} is added into {@code pos}
+     * and {@code k} is returned.
      *
      * @param   n   the number of bytes to be skipped.
      * @return  the actual number of bytes skipped.
@@ -222,7 +232,7 @@
      * Returns the number of remaining bytes that can be read (or skipped over)
      * from this input stream.
      * <p>
-     * The value returned is <code>count&nbsp;- pos</code>,
+     * The value returned is {@code count - pos},
      * which is the number of bytes remaining to be read from the input buffer.
      *
      * @return  the number of remaining bytes that can be read (or skipped
@@ -233,11 +243,11 @@
     }
 
     /**
-     * Tests if this <code>InputStream</code> supports mark/reset. The
-     * <code>markSupported</code> method of <code>ByteArrayInputStream</code>
-     * always returns <code>true</code>.
+     * Tests if this {@code InputStream} supports mark/reset. The
+     * {@code markSupported} method of {@code ByteArrayInputStream}
+     * always returns {@code true}.
      *
-     * @since   JDK1.1
+     * @since   1.1
      */
     public boolean markSupported() {
         return true;
@@ -253,10 +263,10 @@
      * offset passed to the constructor (or 0 if the offset was not
      * supplied).
      *
-     * <p> Note: The <code>readAheadLimit</code> for this class
+     * <p> Note: The {@code readAheadLimit} for this class
      *  has no meaning.
      *
-     * @since   JDK1.1
+     * @since   1.1
      */
     public void mark(int readAheadLimit) {
         mark = pos;
@@ -272,9 +282,9 @@
     }
 
     /**
-     * Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
+     * Closing a {@code ByteArrayInputStream} has no effect. The methods in
      * this class can be called after the stream has been closed without
-     * generating an <tt>IOException</tt>.
+     * generating an {@code IOException}.
      */
     public void close() throws IOException {
     }
diff --git a/ojluni/src/main/java/java/io/ByteArrayOutputStream.java b/ojluni/src/main/java/java/io/ByteArrayOutputStream.java
index f1d429b..df2fdd0 100644
--- a/ojluni/src/main/java/java/io/ByteArrayOutputStream.java
+++ b/ojluni/src/main/java/java/io/ByteArrayOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,21 +25,23 @@
 
 package java.io;
 
+import java.nio.charset.Charset;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * This class implements an output stream in which the data is
  * written into a byte array. The buffer automatically grows as data
  * is written to it.
- * The data can be retrieved using <code>toByteArray()</code> and
- * <code>toString()</code>.
+ * The data can be retrieved using {@code toByteArray()} and
+ * {@code toString()}.
  * <p>
- * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
+ * Closing a {@code ByteArrayOutputStream} has no effect. The methods in
  * this class can be called after the stream has been closed without
- * generating an <tt>IOException</tt>.
+ * generating an {@code IOException}.
  *
  * @author  Arthur van Hoff
- * @since   JDK1.0
+ * @since   1.0
  */
 
 public class ByteArrayOutputStream extends OutputStream {
@@ -55,7 +57,7 @@
     protected int count;
 
     /**
-     * Creates a new byte array output stream. The buffer capacity is
+     * Creates a new {@code ByteArrayOutputStream}. The buffer capacity is
      * initially 32 bytes, though its size increases if necessary.
      */
     public ByteArrayOutputStream() {
@@ -63,11 +65,11 @@
     }
 
     /**
-     * Creates a new byte array output stream, with a buffer capacity of
+     * Creates a new {@code ByteArrayOutputStream}, with a buffer capacity of
      * the specified size, in bytes.
      *
-     * @param   size   the initial size.
-     * @exception  IllegalArgumentException if size is negative.
+     * @param  size   the initial size.
+     * @throws IllegalArgumentException if size is negative.
      */
     public ByteArrayOutputStream(int size) {
         if (size < 0) {
@@ -82,7 +84,7 @@
      * at least the number of elements specified by the minimum
      * capacity argument.
      *
-     * @param minCapacity the desired minimum capacity
+     * @param  minCapacity the desired minimum capacity
      * @throws OutOfMemoryError if {@code minCapacity < 0}.  This is
      * interpreted as a request for the unsatisfiably large capacity
      * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.
@@ -127,7 +129,7 @@
     }
 
     /**
-     * Writes the specified byte to this byte array output stream.
+     * Writes the specified byte to this {@code ByteArrayOutputStream}.
      *
      * @param   b   the byte to be written.
      */
@@ -138,38 +140,56 @@
     }
 
     /**
-     * Writes <code>len</code> bytes from the specified byte array
-     * starting at offset <code>off</code> to this byte array output stream.
+     * Writes {@code len} bytes from the specified byte array
+     * starting at offset {@code off} to this {@code ByteArrayOutputStream}.
      *
      * @param   b     the data.
      * @param   off   the start offset in the data.
      * @param   len   the number of bytes to write.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  IndexOutOfBoundsException if {@code off} is negative,
+     * {@code len} is negative, or {@code len} is greater than
+     * {@code b.length - off}
      */
     public synchronized void write(byte b[], int off, int len) {
-        if ((off < 0) || (off > b.length) || (len < 0) ||
-            ((off + len) - b.length > 0)) {
-            throw new IndexOutOfBoundsException();
-        }
+        Objects.checkFromIndexSize(off, len, b.length);
         ensureCapacity(count + len);
         System.arraycopy(b, off, buf, count, len);
         count += len;
     }
 
     /**
-     * Writes the complete contents of this byte array output stream to
-     * the specified output stream argument, as if by calling the output
-     * stream's write method using <code>out.write(buf, 0, count)</code>.
+     * Writes the complete contents of the specified byte array
+     * to this {@code ByteArrayOutputStream}.
      *
-     * @param      out   the output stream to which to write the data.
-     * @exception  IOException  if an I/O error occurs.
+     * @apiNote
+     * This method is equivalent to {@link #write(byte[],int,int)
+     * write(b, 0, b.length)}.
+     *
+     * @param   b     the data.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @since   11
+     */
+    public void writeBytes(byte b[]) {
+        write(b, 0, b.length);
+    }
+
+    /**
+     * Writes the complete contents of this {@code ByteArrayOutputStream} to
+     * the specified output stream argument, as if by calling the output
+     * stream's write method using {@code out.write(buf, 0, count)}.
+     *
+     * @param   out   the output stream to which to write the data.
+     * @throws  NullPointerException if {@code out} is {@code null}.
+     * @throws  IOException if an I/O error occurs.
      */
     public synchronized void writeTo(OutputStream out) throws IOException {
         out.write(buf, 0, count);
     }
 
     /**
-     * Resets the <code>count</code> field of this byte array output
-     * stream to zero, so that all currently accumulated output in the
+     * Resets the {@code count} field of this {@code ByteArrayOutputStream}
+     * to zero, so that all currently accumulated output in the
      * output stream is discarded. The output stream can be used again,
      * reusing the already allocated buffer space.
      *
@@ -187,14 +207,14 @@
      * @return  the current contents of this output stream, as a byte array.
      * @see     java.io.ByteArrayOutputStream#size()
      */
-    public synchronized byte toByteArray()[] {
+    public synchronized byte[] toByteArray() {
         return Arrays.copyOf(buf, count);
     }
 
     /**
      * Returns the current size of the buffer.
      *
-     * @return  the value of the <code>count</code> field, which is the number
+     * @return  the value of the {@code count} field, which is the number
      *          of valid bytes in this output stream.
      * @see     java.io.ByteArrayOutputStream#count
      */
@@ -204,7 +224,7 @@
 
     /**
      * Converts the buffer's contents into a string decoding bytes using the
-     * platform's default character set. The length of the new <tt>String</tt>
+     * platform's default character set. The length of the new {@code String}
      * is a function of the character set, and hence may not be equal to the
      * size of the buffer.
      *
@@ -215,7 +235,7 @@
      * required.
      *
      * @return String decoded from the buffer's contents.
-     * @since  JDK1.1
+     * @since  1.1
      */
     public synchronized String toString() {
         return new String(buf, 0, count);
@@ -223,21 +243,34 @@
 
     /**
      * Converts the buffer's contents into a string by decoding the bytes using
-     * the named {@link java.nio.charset.Charset charset}. The length of the new
-     * <tt>String</tt> is a function of the charset, and hence may not be equal
-     * to the length of the byte array.
+     * the named {@link java.nio.charset.Charset charset}.
      *
-     * <p> This method always replaces malformed-input and unmappable-character
-     * sequences with this charset's default replacement string. The {@link
-     * java.nio.charset.CharsetDecoder} class should be used when more control
-     * over the decoding process is required.
+     * <p> This method is equivalent to {@code #toString(charset)} that takes a
+     * {@link java.nio.charset.Charset charset}.
      *
-     * @param      charsetName  the name of a supported
-     *             {@link java.nio.charset.Charset charset}
-     * @return     String decoded from the buffer's contents.
-     * @exception  UnsupportedEncodingException
-     *             If the named charset is not supported
-     * @since      JDK1.1
+     * <p> An invocation of this method of the form
+     *
+     * <pre> {@code
+     *      ByteArrayOutputStream b = ...
+     *      b.toString("UTF-8")
+     *      }
+     * </pre>
+     *
+     * behaves in exactly the same way as the expression
+     *
+     * <pre> {@code
+     *      ByteArrayOutputStream b = ...
+     *      b.toString(StandardCharsets.UTF_8)
+     *      }
+     * </pre>
+     *
+     *
+     * @param  charsetName  the name of a supported
+     *         {@link java.nio.charset.Charset charset}
+     * @return String decoded from the buffer's contents.
+     * @throws UnsupportedEncodingException
+     *         If the named charset is not supported
+     * @since  1.1
      */
     public synchronized String toString(String charsetName)
         throws UnsupportedEncodingException
@@ -246,20 +279,41 @@
     }
 
     /**
+     * Converts the buffer's contents into a string by decoding the bytes using
+     * the specified {@link java.nio.charset.Charset charset}. The length of the new
+     * {@code String} is a function of the charset, and hence may not be equal
+     * to the length of the byte array.
+     *
+     * <p> This method always replaces malformed-input and unmappable-character
+     * sequences with the charset's default replacement string. The {@link
+     * java.nio.charset.CharsetDecoder} class should be used when more control
+     * over the decoding process is required.
+     *
+     * @param      charset  the {@linkplain java.nio.charset.Charset charset}
+     *             to be used to decode the {@code bytes}
+     * @return     String decoded from the buffer's contents.
+     * @since      10
+     */
+    public synchronized String toString(Charset charset) {
+        return new String(buf, 0, count, charset);
+    }
+
+    /**
      * Creates a newly allocated string. Its size is the current size of
      * the output stream and the valid contents of the buffer have been
      * copied into it. Each character <i>c</i> in the resulting string is
      * constructed from the corresponding element <i>b</i> in the byte
      * array such that:
-     * <blockquote><pre>
-     *     c == (char)(((hibyte &amp; 0xff) &lt;&lt; 8) | (b &amp; 0xff))
-     * </pre></blockquote>
+     * <blockquote><pre>{@code
+     *     c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))
+     * }</pre></blockquote>
      *
      * @deprecated This method does not properly convert bytes into characters.
      * As of JDK&nbsp;1.1, the preferred way to do this is via the
-     * <code>toString(String enc)</code> method, which takes an encoding-name
-     * argument, or the <code>toString()</code> method, which uses the
-     * platform's default character encoding.
+     * {@link #toString(String charsetName)} or {@link #toString(Charset charset)}
+     * method, which takes an encoding-name or charset argument,
+     * or the {@code toString()} method, which uses the platform's default
+     * character encoding.
      *
      * @param      hibyte    the high byte of each resulting Unicode character.
      * @return     the current contents of the output stream, as a string.
@@ -273,9 +327,9 @@
     }
 
     /**
-     * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
+     * Closing a {@code ByteArrayOutputStream} has no effect. The methods in
      * this class can be called after the stream has been closed without
-     * generating an <tt>IOException</tt>.
+     * generating an {@code IOException}.
      */
     public void close() throws IOException {
     }
diff --git a/ojluni/src/main/java/java/io/CharArrayReader.java b/ojluni/src/main/java/java/io/CharArrayReader.java
index 4140976..08b1381 100644
--- a/ojluni/src/main/java/java/io/CharArrayReader.java
+++ b/ojluni/src/main/java/java/io/CharArrayReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  * character-input stream.
  *
  * @author      Herb Jellinek
- * @since       JDK1.1
+ * @since       1.1
  */
 public class CharArrayReader extends Reader {
     /** The character buffer. */
@@ -62,13 +62,13 @@
      * Creates a CharArrayReader from the specified array of chars.
      *
      * <p> The resulting reader will start reading at the given
-     * <tt>offset</tt>.  The total number of <tt>char</tt> values that can be
-     * read from this reader will be either <tt>length</tt> or
-     * <tt>buf.length-offset</tt>, whichever is smaller.
+     * {@code offset}.  The total number of {@code char} values that can be
+     * read from this reader will be either {@code length} or
+     * {@code buf.length-offset}, whichever is smaller.
      *
      * @throws IllegalArgumentException
-     *         If <tt>offset</tt> is negative or greater than
-     *         <tt>buf.length</tt>, or if <tt>length</tt> is negative, or if
+     *         If {@code offset} is negative or greater than
+     *         {@code buf.length}, or if {@code length} is negative, or if
      *         the sum of these two values is negative.
      *
      * @param buf       Input buffer (not copied)
@@ -116,6 +116,7 @@
      *          the end of the stream has been reached
      *
      * @exception   IOException  If an I/O error occurs
+     * @exception   IndexOutOfBoundsException {@inheritDoc}
      */
     public int read(char b[], int off, int len) throws IOException {
         synchronized (lock) {
@@ -130,12 +131,11 @@
             if (pos >= count) {
                 return -1;
             }
-            // BEGIN Android-changed: Backport of OpenJDK 9b132 fix to avoid integer overflow.
+
             int avail = count - pos;
             if (len > avail) {
                 len = avail;
             }
-            // END Android-changed: Backport of OpenJDK 9b132 fix to avoid integer overflow.
             if (len <= 0) {
                 return 0;
             }
@@ -160,12 +160,11 @@
     public long skip(long n) throws IOException {
         synchronized (lock) {
             ensureOpen();
-            // BEGIN Android-changed: Backport of OpenJDK 9b132 fix to avoid integer overflow.
+
             long avail = count - pos;
             if (n > avail) {
                 n = avail;
             }
-            // END Android-changed: Backport of OpenJDK 9b132 fix to avoid integer overflow.
             if (n < 0) {
                 return 0;
             }
@@ -230,9 +229,12 @@
      * Closes the stream and releases any system resources associated with
      * it.  Once the stream has been closed, further read(), ready(),
      * mark(), reset(), or skip() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      */
     public void close() {
-        buf = null;
+        synchronized (lock) {
+            buf = null;
+        }
     }
 }
diff --git a/ojluni/src/main/java/java/io/CharArrayWriter.java b/ojluni/src/main/java/java/io/CharArrayWriter.java
index 56a5821..e8bf2c3 100644
--- a/ojluni/src/main/java/java/io/CharArrayWriter.java
+++ b/ojluni/src/main/java/java/io/CharArrayWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
  * without generating an IOException.
  *
  * @author      Herb Jellinek
- * @since       JDK1.1
+ * @since       1.1
  */
 public
 class CharArrayWriter extends Writer {
@@ -91,6 +91,11 @@
      * @param c the data to be written
      * @param off       the start offset in the data
      * @param len       the number of chars that are written
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
      */
     public void write(char c[], int off, int len) {
         if ((off < 0) || (off > c.length) || (len < 0) ||
@@ -114,6 +119,11 @@
      * @param  str  String to be written from
      * @param  off  Offset from which to start reading characters
      * @param  len  Number of characters to be written
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
      */
     public void write(String str, int off, int len) {
         synchronized (lock) {
@@ -141,21 +151,21 @@
     /**
      * Appends the specified character sequence to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
+     * <p> An invocation of this method of the form {@code out.append(csq)}
      * behaves in exactly the same way as the invocation
      *
      * <pre>
      *     out.write(csq.toString()) </pre>
      *
-     * <p> Depending on the specification of <tt>toString</tt> for the
-     * character sequence <tt>csq</tt>, the entire sequence may not be
-     * appended. For instance, invoking the <tt>toString</tt> method of a
+     * <p> Depending on the specification of {@code toString} for the
+     * character sequence {@code csq}, the entire sequence may not be
+     * appended. For instance, invoking the {@code toString} method of a
      * character buffer will return a subsequence whose content depends upon
      * the buffer's position and limit.
      *
      * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         The character sequence to append.  If {@code csq} is
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this writer.
      *
      * @return  This writer
@@ -163,7 +173,7 @@
      * @since  1.5
      */
     public CharArrayWriter append(CharSequence csq) {
-        String s = (csq == null ? "null" : csq.toString());
+        String s = String.valueOf(csq);
         write(s, 0, s.length());
         return this;
     }
@@ -171,8 +181,9 @@
     /**
      * Appends a subsequence of the specified character sequence to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
+     * <p> An invocation of this method of the form
+     * {@code out.append(csq, start, end)} when
+     * {@code csq} is not {@code null}, behaves in
      * exactly the same way as the invocation
      *
      * <pre>
@@ -180,9 +191,9 @@
      *
      * @param  csq
      *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
+     *         appended.  If {@code csq} is {@code null}, then characters
+     *         will be appended as if {@code csq} contained the four
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -194,22 +205,21 @@
      * @return  This writer
      *
      * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
+     *          If {@code start} or {@code end} are negative, {@code start}
+     *          is greater than {@code end}, or {@code end} is greater than
+     *          {@code csq.length()}
      *
      * @since  1.5
      */
     public CharArrayWriter append(CharSequence csq, int start, int end) {
-        String s = (csq == null ? "null" : csq).subSequence(start, end).toString();
-        write(s, 0, s.length());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
      * Appends the specified character to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
+     * <p> An invocation of this method of the form {@code out.append(c)}
      * behaves in exactly the same way as the invocation
      *
      * <pre>
@@ -240,7 +250,7 @@
      *
      * @return an array of chars copied from the input data.
      */
-    public char toCharArray()[] {
+    public char[] toCharArray() {
         synchronized (lock) {
             return Arrays.copyOf(buf, count);
         }
diff --git a/ojluni/src/main/java/java/io/CharConversionException.java b/ojluni/src/main/java/java/io/CharConversionException.java
index ba79fe3..832dc49 100644
--- a/ojluni/src/main/java/java/io/CharConversionException.java
+++ b/ojluni/src/main/java/java/io/CharConversionException.java
@@ -28,7 +28,7 @@
  * Base class for character conversion exceptions.
  *
  * @author      Asmus Freytag
- * @since       JDK1.1
+ * @since       1.1
  */
 public class CharConversionException
     extends java.io.IOException
diff --git a/ojluni/src/main/java/java/io/DataInput.java b/ojluni/src/main/java/java/io/DataInput.java
index 3e0f0dd..86d8d3e 100644
--- a/ojluni/src/main/java/java/io/DataInput.java
+++ b/ojluni/src/main/java/java/io/DataInput.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,87 +48,96 @@
  * may be thrown if the input stream has been
  * closed.
  *
- * <h3><a name="modified-utf-8">Modified UTF-8</a></h3>
+ * <h3><a id="modified-utf-8">Modified UTF-8</a></h3>
  * <p>
  * Implementations of the DataInput and DataOutput interfaces represent
  * Unicode strings in a format that is a slight modification of UTF-8.
  * (For information regarding the standard UTF-8 format, see section
  * <i>3.9 Unicode Encoding Forms</i> of <i>The Unicode Standard, Version
- * 4.0</i>).
- * Note that in the following table, the most significant bit appears in the
- * far left-hand column.
+ * 4.0</i>)
  *
- * <blockquote>
- *   <table border="1" cellspacing="0" cellpadding="8"
- *          summary="Bit values and bytes">
- *     <tr>
- *       <th colspan="9"><span style="font-weight:normal">
- *         All characters in the range {@code '\u005Cu0001'} to
- *         {@code '\u005Cu007F'} are represented by a single byte:</span></th>
- *     </tr>
- *     <tr>
- *       <td></td>
- *       <th colspan="8" id="bit_a">Bit Values</th>
- *     </tr>
- *     <tr>
- *       <th id="byte1_a">Byte 1</th>
- *       <td><center>0</center>
- *       <td colspan="7"><center>bits 6-0</center>
- *     </tr>
- *     <tr>
- *       <th colspan="9"><span style="font-weight:normal">
- *         The null character {@code '\u005Cu0000'} and characters
+ * <ul>
+ * <li>Characters in the range {@code '\u005Cu0001'} to
+ *         {@code '\u005Cu007F'} are represented by a single byte.
+ * <li>The null character {@code '\u005Cu0000'} and characters
  *         in the range {@code '\u005Cu0080'} to {@code '\u005Cu07FF'} are
- *         represented by a pair of bytes:</span></th>
+ *         represented by a pair of bytes.
+ * <li>Characters in the range {@code '\u005Cu0800'}
+ *         to {@code '\u005CuFFFF'} are represented by three bytes.
+ * </ul>
+ *
+ *   <table class="plain" style="margin-left:2em;">
+ *     <caption>Encoding of UTF-8 values</caption>
+ *     <thead>
+ *     <tr>
+ *       <th scope="col" rowspan="2">Value</th>
+ *       <th scope="col" rowspan="2">Byte</th>
+ *       <th scope="col" colspan="8" id="bit_a">Bit Values</th>
  *     </tr>
  *     <tr>
- *       <td></td>
- *       <th colspan="8" id="bit_b">Bit Values</th>
+ *       <!-- Value -->
+ *       <!-- Byte -->
+ *       <th scope="col" style="width:3em"> 7 </th>
+ *       <th scope="col" style="width:3em"> 6 </th>
+ *       <th scope="col" style="width:3em"> 5 </th>
+ *       <th scope="col" style="width:3em"> 4 </th>
+ *       <th scope="col" style="width:3em"> 3 </th>
+ *       <th scope="col" style="width:3em"> 2 </th>
+ *       <th scope="col" style="width:3em"> 1 </th>
+ *       <th scope="col" style="width:3em"> 0 </th>
+ *     </thead>
+ *     <tbody>
+ *     <tr>
+ *       <th scope="row" style="text-align:left; font-weight:normal">
+ *         {@code \u005Cu0001} to {@code \u005Cu007F} </th>
+ *       <th scope="row" style="font-weight:normal; text-align:center"> 1 </th>
+ *       <td style="text-align:center">0
+ *       <td colspan="7" style="text-align:right; padding-right:6em">bits 6-0
  *     </tr>
  *     <tr>
- *       <th id="byte1_b">Byte 1</th>
- *       <td><center>1</center>
- *       <td><center>1</center>
- *       <td><center>0</center>
- *       <td colspan="5"><center>bits 10-6</center>
+ *       <th scope="row" rowspan="2" style="text-align:left; font-weight:normal">
+ *           {@code \u005Cu0000},<br>
+ *           {@code \u005Cu0080} to {@code \u005Cu07FF} </th>
+ *       <th scope="row" style="font-weight:normal; text-align:center"> 1 </th>
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">0
+ *       <td colspan="5" style="text-align:right; padding-right:6em">bits 10-6
  *     </tr>
  *     <tr>
- *       <th id="byte2_a">Byte 2</th>
- *       <td><center>1</center>
- *       <td><center>0</center>
- *       <td colspan="6"><center>bits 5-0</center>
+ *       <!-- (value) -->
+ *       <th scope="row" style="font-weight:normal; text-align:center"> 2 </th>
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">0
+ *       <td colspan="6" style="text-align:right; padding-right:6em">bits 5-0
  *     </tr>
  *     <tr>
- *       <th colspan="9"><span style="font-weight:normal">
- *         {@code char} values in the range {@code '\u005Cu0800'}
- *         to {@code '\u005CuFFFF'} are represented by three bytes:</span></th>
+ *       <th scope="row" rowspan="3" style="text-align:left; font-weight:normal">
+ *         {@code \u005Cu0800} to {@code \u005CuFFFF} </th>
+ *       <th scope="row" style="font-weight:normal; text-align:center"> 1 </th>
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">0
+ *       <td colspan="4" style="text-align:right; padding-right:6em">bits 15-12
  *     </tr>
  *     <tr>
- *       <td></td>
- *       <th colspan="8"id="bit_c">Bit Values</th>
+ *       <!-- (value) -->
+ *       <th scope="row" style="font-weight:normal; text-align:center"> 2 </th>
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">0
+ *       <td colspan="6" style="text-align:right; padding-right:6em">bits 11-6
  *     </tr>
  *     <tr>
- *       <th id="byte1_c">Byte 1</th>
- *       <td><center>1</center>
- *       <td><center>1</center>
- *       <td><center>1</center>
- *       <td><center>0</center>
- *       <td colspan="4"><center>bits 15-12</center>
+ *       <!-- (value) -->
+ *       <th scope="row" style="font-weight:normal; text-align:center"> 3 </th>
+ *       <td style="text-align:center">1
+ *       <td style="text-align:center">0
+ *       <td colspan="6" style="text-align:right; padding-right:6em">bits 5-0
  *     </tr>
- *     <tr>
- *       <th id="byte2_b">Byte 2</th>
- *       <td><center>1</center>
- *       <td><center>0</center>
- *       <td colspan="6"><center>bits 11-6</center>
- *     </tr>
- *     <tr>
- *       <th id="byte3">Byte 3</th>
- *       <td><center>1</center>
- *       <td><center>0</center>
- *       <td colspan="6"><center>bits 5-0</center>
- *     </tr>
+ *     </tbody>
  *   </table>
- * </blockquote>
+ *
  * <p>
  * The differences between this format and the
  * standard UTF-8 format are the following:
@@ -143,7 +152,7 @@
  * @author  Frank Yellin
  * @see     java.io.DataInputStream
  * @see     java.io.DataOutput
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 interface DataInput {
@@ -182,10 +191,11 @@
      * not all bytes of {@code b} have been
      * updated with data from the input stream.
      *
-     * @param     b   the buffer into which the data is read.
-     * @exception  EOFException  if this stream reaches the end before reading
-     *               all the bytes.
-     * @exception  IOException   if an I/O error occurs.
+     * @param   b   the buffer into which the data is read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  EOFException  if this stream reaches the end before reading
+     *          all the bytes.
+     * @throws  IOException   if an I/O error occurs.
      */
     void readFully(byte b[]) throws IOException;
 
@@ -226,12 +236,16 @@
      * and so on. The number of bytes read is,
      * at most, equal to {@code len}.
      *
-     * @param     b   the buffer into which the data is read.
-     * @param off  an int specifying the offset into the data.
-     * @param len  an int specifying the number of bytes to read.
-     * @exception  EOFException  if this stream reaches the end before reading
-     *               all the bytes.
-     * @exception  IOException   if an I/O error occurs.
+     * @param   b    the buffer into which the data is read.
+     * @param   off  an int specifying the offset in the data array {@code b}.
+     * @param   len  an int specifying the number of bytes to read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  IndexOutOfBoundsException if {@code off} is negative,
+     *          {@code len} is negative, or {@code len} is greater than
+     *          {@code b.length - off}.
+     * @throws  EOFException  if this stream reaches the end before reading
+     *          all the bytes.
+     * @throws  IOException   if an I/O error occurs.
      */
     void readFully(byte b[], int off, int len) throws IOException;
 
diff --git a/ojluni/src/main/java/java/io/DataInputStream.java b/ojluni/src/main/java/java/io/DataInputStream.java
index 19d4067..2098344 100644
--- a/ojluni/src/main/java/java/io/DataInputStream.java
+++ b/ojluni/src/main/java/java/io/DataInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@
  *
  * @author  Arthur van Hoff
  * @see     java.io.DataOutputStream
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class DataInputStream extends FilterInputStream implements DataInput {
@@ -153,38 +153,43 @@
     }
 
     /**
-     * See the general contract of the <code>readFully</code>
-     * method of <code>DataInput</code>.
+     * See the general contract of the {@code readFully}
+     * method of {@code DataInput}.
      * <p>
      * Bytes
      * for this operation are read from the contained
      * input stream.
      *
-     * @param      b   the buffer into which the data is read.
-     * @exception  EOFException  if this input stream reaches the end before
-     *             reading all the bytes.
-     * @exception  IOException   the stream has been closed and the contained
-     *             input stream does not support reading after close, or
-     *             another I/O error occurs.
-     * @see        java.io.FilterInputStream#in
+     * @param   b   the buffer into which the data is read.
+     * @throws  NullPointerException if {@code b} is {@code null}.
+     * @throws  EOFException  if this input stream reaches the end before
+     *          reading all the bytes.
+     * @throws  IOException   the stream has been closed and the contained
+     *          input stream does not support reading after close, or
+     *          another I/O error occurs.
+     * @see     java.io.FilterInputStream#in
      */
     public final void readFully(byte b[]) throws IOException {
         readFully(b, 0, b.length);
     }
 
     /**
-     * See the general contract of the <code>readFully</code>
-     * method of <code>DataInput</code>.
+     * See the general contract of the {@code readFully}
+     * method of {@code DataInput}.
      * <p>
      * Bytes
      * for this operation are read from the contained
      * input stream.
      *
      * @param      b     the buffer into which the data is read.
-     * @param      off   the start offset of the data.
+     * @param      off   the start offset in the data array {@code b}.
      * @param      len   the number of bytes to read.
+     * @exception  NullPointerException if {@code b} is {@code null}.
+     * @exception  IndexOutOfBoundsException if {@code off} is negative,
+     *             {@code len} is negative, or {@code len} is greater than
+     *             {@code b.length - off}.
      * @exception  EOFException  if this input stream reaches the end before
-     *               reading all the bytes.
+     *             reading all the bytes.
      * @exception  IOException   the stream has been closed and the contained
      *             input stream does not support reading after close, or
      *             another I/O error occurs.
@@ -582,7 +587,7 @@
      *               valid modified UTF-8 encoding of a Unicode string.
      * @see        java.io.DataInputStream#readUnsignedShort()
      */
-    public final static String readUTF(DataInput in) throws IOException {
+    public static final String readUTF(DataInput in) throws IOException {
         int utflen = in.readUnsignedShort();
         byte[] bytearr = null;
         char[] chararr = null;
diff --git a/ojluni/src/main/java/java/io/DataOutput.java b/ojluni/src/main/java/java/io/DataOutput.java
index c6692a6..50de041 100644
--- a/ojluni/src/main/java/java/io/DataOutput.java
+++ b/ojluni/src/main/java/java/io/DataOutput.java
@@ -44,7 +44,7 @@
  * @author  Frank Yellin
  * @see     java.io.DataInput
  * @see     java.io.DataOutputStream
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 interface DataOutput {
diff --git a/ojluni/src/main/java/java/io/DataOutputStream.java b/ojluni/src/main/java/java/io/DataOutputStream.java
index 99fafed..392abba 100644
--- a/ojluni/src/main/java/java/io/DataOutputStream.java
+++ b/ojluni/src/main/java/java/io/DataOutputStream.java
@@ -32,7 +32,7 @@
  *
  * @author  unascribed
  * @see     java.io.DataInputStream
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class DataOutputStream extends FilterOutputStream implements DataOutput {
diff --git a/ojluni/src/main/java/java/io/EOFException.java b/ojluni/src/main/java/java/io/EOFException.java
index 536669f..446373e 100644
--- a/ojluni/src/main/java/java/io/EOFException.java
+++ b/ojluni/src/main/java/java/io/EOFException.java
@@ -36,7 +36,7 @@
  * @author  Frank Yellin
  * @see     java.io.DataInputStream
  * @see     java.io.IOException
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class EOFException extends IOException {
diff --git a/ojluni/src/main/java/java/io/Externalizable.java b/ojluni/src/main/java/java/io/Externalizable.java
index f9e88fe..f5f3f9a 100644
--- a/ojluni/src/main/java/java/io/Externalizable.java
+++ b/ojluni/src/main/java/java/io/Externalizable.java
@@ -61,7 +61,7 @@
  * @see java.io.ObjectOutput
  * @see java.io.ObjectInput
  * @see java.io.Serializable
- * @since   JDK1.1
+ * @since   1.1
  */
 public interface Externalizable extends java.io.Serializable {
     /**
diff --git a/ojluni/src/main/java/java/io/FileInputStream.java b/ojluni/src/main/java/java/io/FileInputStream.java
index 9ce75ff..edba2f4 100755
--- a/ojluni/src/main/java/java/io/FileInputStream.java
+++ b/ojluni/src/main/java/java/io/FileInputStream.java
@@ -317,7 +317,7 @@
         }
 
         // Android-added: Tracking of unbuffered I/O.
-        tracker.trackIo(len);
+        tracker.trackIo(len, IoTracker.Mode.READ);
 
         // Android-changed: Use IoBridge instead of calling native method.
         return IoBridge.read(fd, b, off, len);
diff --git a/ojluni/src/main/java/java/io/FileNotFoundException.java b/ojluni/src/main/java/java/io/FileNotFoundException.java
index 278fa1d..898a9b79 100644
--- a/ojluni/src/main/java/java/io/FileNotFoundException.java
+++ b/ojluni/src/main/java/java/io/FileNotFoundException.java
@@ -37,7 +37,7 @@
  * example when an attempt is made to open a read-only file for writing.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 
 public class FileNotFoundException extends IOException {
diff --git a/ojluni/src/main/java/java/io/FileOutputStream.java b/ojluni/src/main/java/java/io/FileOutputStream.java
index 66f4c05..6cf7155 100755
--- a/ojluni/src/main/java/java/io/FileOutputStream.java
+++ b/ojluni/src/main/java/java/io/FileOutputStream.java
@@ -395,7 +395,7 @@
         }
 
         // Android-added: Tracking of unbuffered I/O.
-        tracker.trackIo(len);
+        tracker.trackIo(len, IoTracker.Mode.WRITE);
 
         // Android-changed: Use IoBridge instead of calling native method.
         IoBridge.write(fd, b, off, len);
diff --git a/ojluni/src/main/java/java/io/FileReader.java b/ojluni/src/main/java/java/io/FileReader.java
index acc3a19..d37cd8c 100644
--- a/ojluni/src/main/java/java/io/FileReader.java
+++ b/ojluni/src/main/java/java/io/FileReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,30 +25,32 @@
 
 package java.io;
 
+import java.nio.charset.Charset;
 
 /**
- * Convenience class for reading character files.  The constructors of this
- * class assume that the default character encoding and the default byte-buffer
- * size are appropriate.  To specify these values yourself, construct an
- * InputStreamReader on a FileInputStream.
+ * Reads text from character files using a default buffer size. Decoding from bytes
+ * to characters uses either a specified {@linkplain java.nio.charset.Charset charset}
+ * or the platform's
+ * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
  *
- * <p><code>FileReader</code> is meant for reading streams of characters.
- * For reading streams of raw bytes, consider using a
- * <code>FileInputStream</code>.
+ * <p>
+ * The {@code FileReader} is meant for reading streams of characters. For reading
+ * streams of raw bytes, consider using a {@code FileInputStream}.
  *
  * @see InputStreamReader
  * @see FileInputStream
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 public class FileReader extends InputStreamReader {
 
    /**
-    * Creates a new <tt>FileReader</tt>, given the name of the
-    * file to read from.
+    * Creates a new {@code FileReader}, given the name of the file to read,
+    * using the platform's
+    * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
     *
-    * @param fileName the name of the file to read from
+    * @param fileName the name of the file to read
     * @exception  FileNotFoundException  if the named file does not exist,
     *                   is a directory rather than a regular file,
     *                   or for some other reason cannot be opened for
@@ -59,10 +61,11 @@
     }
 
    /**
-    * Creates a new <tt>FileReader</tt>, given the <tt>File</tt>
-    * to read from.
+    * Creates a new {@code FileReader}, given the {@code File} to read,
+    * using the platform's
+    * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
     *
-    * @param file the <tt>File</tt> to read from
+    * @param file the {@code File} to read
     * @exception  FileNotFoundException  if the file does not exist,
     *                   is a directory rather than a regular file,
     *                   or for some other reason cannot be opened for
@@ -73,13 +76,47 @@
     }
 
    /**
-    * Creates a new <tt>FileReader</tt>, given the
-    * <tt>FileDescriptor</tt> to read from.
+    * Creates a new {@code FileReader}, given the {@code FileDescriptor} to read,
+    * using the platform's
+    * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
     *
-    * @param fd the FileDescriptor to read from
+    * @param fd the {@code FileDescriptor} to read
     */
     public FileReader(FileDescriptor fd) {
         super(new FileInputStream(fd));
     }
 
+   /**
+    * Creates a new {@code FileReader}, given the name of the file to read
+    * and the {@linkplain java.nio.charset.Charset charset}.
+    *
+    * @param fileName the name of the file to read
+    * @param charset the {@linkplain java.nio.charset.Charset charset}
+    * @exception  IOException  if the named file does not exist,
+    *                   is a directory rather than a regular file,
+    *                   or for some other reason cannot be opened for
+    *                   reading.
+    *
+    * @since 11
+    */
+    public FileReader(String fileName, Charset charset) throws IOException {
+        super(new FileInputStream(fileName), charset);
+    }
+
+   /**
+    * Creates a new {@code FileReader}, given the {@code File} to read and
+    * the {@linkplain java.nio.charset.Charset charset}.
+    *
+    * @param file the {@code File} to read
+    * @param charset the {@linkplain java.nio.charset.Charset charset}
+    * @exception  IOException  if the file does not exist,
+    *                   is a directory rather than a regular file,
+    *                   or for some other reason cannot be opened for
+    *                   reading.
+    *
+    * @since 11
+    */
+    public FileReader(File file, Charset charset) throws IOException {
+        super(new FileInputStream(file), charset);
+    }
 }
diff --git a/ojluni/src/main/java/java/io/FileWriter.java b/ojluni/src/main/java/java/io/FileWriter.java
index 7475ea4..e49b316 100644
--- a/ojluni/src/main/java/java/io/FileWriter.java
+++ b/ojluni/src/main/java/java/io/FileWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,34 +25,37 @@
 
 package java.io;
 
+import java.nio.charset.Charset;
 
 /**
- * Convenience class for writing character files.  The constructors of this
- * class assume that the default character encoding and the default byte-buffer
- * size are acceptable.  To specify these values yourself, construct an
- * OutputStreamWriter on a FileOutputStream.
+ * Writes text to character files using a default buffer size. Encoding from characters
+ * to bytes uses either a specified {@linkplain java.nio.charset.Charset charset}
+ * or the platform's
+ * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
  *
- * <p>Whether or not a file is available or may be created depends upon the
+ * <p>
+ * Whether or not a file is available or may be created depends upon the
  * underlying platform.  Some platforms, in particular, allow a file to be
- * opened for writing by only one <tt>FileWriter</tt> (or other file-writing
+ * opened for writing by only one {@code FileWriter} (or other file-writing
  * object) at a time.  In such situations the constructors in this class
  * will fail if the file involved is already open.
  *
- * <p><code>FileWriter</code> is meant for writing streams of characters.
- * For writing streams of raw bytes, consider using a
- * <code>FileOutputStream</code>.
+ * <p>
+ * The {@code FileWriter} is meant for writing streams of characters. For writing
+ * streams of raw bytes, consider using a {@code FileOutputStream}.
  *
  * @see OutputStreamWriter
  * @see FileOutputStream
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class FileWriter extends OutputStreamWriter {
 
     /**
-     * Constructs a FileWriter object given a file name.
+     * Constructs a {@code FileWriter} given a file name, using the platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}
      *
      * @param fileName  String The system-dependent filename.
      * @throws IOException  if the named file exists but is a directory rather
@@ -64,11 +67,12 @@
     }
 
     /**
-     * Constructs a FileWriter object given a file name with a boolean
-     * indicating whether or not to append the data written.
+     * Constructs a {@code FileWriter} given a file name and a boolean indicating
+     * whether to append the data written, using the platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
      *
      * @param fileName  String The system-dependent filename.
-     * @param append    boolean if <code>true</code>, then data will be written
+     * @param append    boolean if {@code true}, then data will be written
      *                  to the end of the file rather than the beginning.
      * @throws IOException  if the named file exists but is a directory rather
      *                  than a regular file, does not exist but cannot be
@@ -79,9 +83,11 @@
     }
 
     /**
-     * Constructs a FileWriter object given a File object.
+     * Constructs a {@code FileWriter} given the {@code File} to write,
+     * using the platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}
      *
-     * @param file  a File object to write to.
+     * @param file  the {@code File} to write.
      * @throws IOException  if the file exists but is a directory rather than
      *                  a regular file, does not exist but cannot be created,
      *                  or cannot be opened for any other reason
@@ -91,12 +97,12 @@
     }
 
     /**
-     * Constructs a FileWriter object given a File object. If the second
-     * argument is <code>true</code>, then bytes will be written to the end
-     * of the file rather than the beginning.
+     * Constructs a {@code FileWriter} given the {@code File} to write and
+     * a boolean indicating whether to append the data written, using the platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
      *
-     * @param file  a File object to write to
-     * @param     append    if <code>true</code>, then bytes will be written
+     * @param file  the {@code File} to write
+     * @param     append    if {@code true}, then bytes will be written
      *                      to the end of the file rather than the beginning
      * @throws IOException  if the file exists but is a directory rather than
      *                  a regular file, does not exist but cannot be created,
@@ -108,12 +114,83 @@
     }
 
     /**
-     * Constructs a FileWriter object associated with a file descriptor.
+     * Constructs a {@code FileWriter} given a file descriptor,
+     * using the platform's
+     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
      *
-     * @param fd  FileDescriptor object to write to.
+     * @param fd  the {@code FileDescriptor} to write.
      */
     public FileWriter(FileDescriptor fd) {
         super(new FileOutputStream(fd));
     }
 
+
+    /**
+     * Constructs a {@code FileWriter} given a file name and
+     * {@linkplain java.nio.charset.Charset charset}.
+     *
+     * @param fileName  the name of the file to write
+     * @param charset the {@linkplain java.nio.charset.Charset charset}
+     * @throws IOException  if the named file exists but is a directory rather
+     *                  than a regular file, does not exist but cannot be
+     *                  created, or cannot be opened for any other reason
+     *
+     * @since 11
+     */
+    public FileWriter(String fileName, Charset charset) throws IOException {
+        super(new FileOutputStream(fileName), charset);
+    }
+
+    /**
+     * Constructs a {@code FileWriter} given a file name,
+     * {@linkplain java.nio.charset.Charset charset} and a boolean indicating
+     * whether to append the data written.
+     *
+     * @param fileName  the name of the file to write
+     * @param charset the {@linkplain java.nio.charset.Charset charset}
+     * @param append    a boolean. If {@code true}, the writer will write the data
+     *                  to the end of the file rather than the beginning.
+     * @throws IOException  if the named file exists but is a directory rather
+     *                  than a regular file, does not exist but cannot be
+     *                  created, or cannot be opened for any other reason
+     *
+     * @since 11
+     */
+    public FileWriter(String fileName, Charset charset, boolean append) throws IOException {
+        super(new FileOutputStream(fileName, append), charset);
+    }
+
+    /**
+     * Constructs a {@code FileWriter} given the {@code File} to write and
+     * {@linkplain java.nio.charset.Charset charset}.
+     *
+     * @param file  the {@code File} to write
+     * @param charset the {@linkplain java.nio.charset.Charset charset}
+     * @throws IOException  if the file exists but is a directory rather than
+     *                  a regular file, does not exist but cannot be created,
+     *                  or cannot be opened for any other reason
+     *
+     * @since 11
+     */
+    public FileWriter(File file, Charset charset) throws IOException {
+        super(new FileOutputStream(file), charset);
+    }
+
+    /**
+     * Constructs a {@code FileWriter} given the {@code File} to write,
+     * {@linkplain java.nio.charset.Charset charset} and a boolean indicating
+     * whether to append the data written.
+     *
+     * @param file  the {@code File} to write
+     * @param charset the {@linkplain java.nio.charset.Charset charset}
+     * @param append    a boolean. If {@code true}, the writer will write the data
+     *                  to the end of the file rather than the beginning.
+     * @throws IOException  if the file exists but is a directory rather than
+     *                  a regular file, does not exist but cannot be created,
+     *                  or cannot be opened for any other reason
+     * @since 11
+     */
+    public FileWriter(File file, Charset charset, boolean append) throws IOException {
+        super(new FileOutputStream(file, append), charset);
+    }
 }
diff --git a/ojluni/src/main/java/java/io/FilenameFilter.java b/ojluni/src/main/java/java/io/FilenameFilter.java
index 25d866b..2af02e8 100644
--- a/ojluni/src/main/java/java/io/FilenameFilter.java
+++ b/ojluni/src/main/java/java/io/FilenameFilter.java
@@ -38,7 +38,7 @@
  * @author  Jonathan Payne
  * @see     java.io.File
  * @see     java.io.File#list(java.io.FilenameFilter)
- * @since   JDK1.0
+ * @since   1.0
  */
 @FunctionalInterface
 public interface FilenameFilter {
diff --git a/ojluni/src/main/java/java/io/FilterInputStream.java b/ojluni/src/main/java/java/io/FilterInputStream.java
index 10beaea..05ab5fa 100644
--- a/ojluni/src/main/java/java/io/FilterInputStream.java
+++ b/ojluni/src/main/java/java/io/FilterInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@
  * and fields.
  *
  * @author  Jonathan Payne
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class FilterInputStream extends InputStream {
@@ -84,7 +84,7 @@
     }
 
     /**
-     * Reads up to <code>byte.length</code> bytes of data from this
+     * Reads up to <code>b.length</code> bytes of data from this
      * input stream into an array of bytes. This method blocks until some
      * input is available.
      * <p>
@@ -144,8 +144,7 @@
      *
      * @param      n   the number of bytes to be skipped.
      * @return     the actual number of bytes skipped.
-     * @exception  IOException  if the stream does not support seek,
-     *                          or if some other I/O error occurs.
+     * @throws     IOException  if {@code in.skip(n)} throws an IOException.
      */
     public long skip(long n) throws IOException {
         return in.skip(n);
diff --git a/ojluni/src/main/java/java/io/FilterOutputStream.java b/ojluni/src/main/java/java/io/FilterOutputStream.java
index 89f5ef5..55abe73 100644
--- a/ojluni/src/main/java/java/io/FilterOutputStream.java
+++ b/ojluni/src/main/java/java/io/FilterOutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,27 +39,30 @@
  * methods as well as provide additional methods and fields.
  *
  * @author  Jonathan Payne
- * @since   JDK1.0
+ * @since   1.0
  */
-public
-class FilterOutputStream extends OutputStream {
+public class FilterOutputStream extends OutputStream {
     /**
      * The underlying output stream to be filtered.
      */
     protected OutputStream out;
 
-    // Android-added: Integrate OpenJDK 9 fix for double-close. http://b/122733269.
     /**
      * Whether the stream is closed; implicitly initialized to false.
      */
-    private boolean closed;
+    private volatile boolean closed;
+
+    /**
+     * Object used to prevent a race on the 'closed' instance variable.
+     */
+    private final Object closeLock = new Object();
 
     /**
      * Creates an output stream filter built on top of the specified
      * underlying output stream.
      *
      * @param   out   the underlying output stream to be assigned to
-     *                the field <tt>this.out</tt> for later use, or
+     *                the field {@code this.out} for later use, or
      *                <code>null</code> if this instance is to be
      *                created without an underlying stream.
      */
@@ -72,13 +75,14 @@
      * <p>
      * The <code>write</code> method of <code>FilterOutputStream</code>
      * calls the <code>write</code> method of its underlying output stream,
-     * that is, it performs <tt>out.write(b)</tt>.
+     * that is, it performs {@code out.write(b)}.
      * <p>
-     * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
+     * Implements the abstract {@code write} method of {@code OutputStream}.
      *
      * @param      b   the <code>byte</code>.
      * @exception  IOException  if an I/O error occurs.
      */
+    @Override
     public void write(int b) throws IOException {
         out.write(b);
     }
@@ -92,13 +96,14 @@
      * <code>b.length</code>.
      * <p>
      * Note that this method does not call the one-argument
-     * <code>write</code> method of its underlying stream with the single
-     * argument <code>b</code>.
+     * <code>write</code> method of its underlying output stream with
+     * the single argument <code>b</code>.
      *
      * @param      b   the data to be written.
      * @exception  IOException  if an I/O error occurs.
      * @see        java.io.FilterOutputStream#write(byte[], int, int)
      */
+    @Override
     public void write(byte b[]) throws IOException {
         write(b, 0, b.length);
     }
@@ -113,7 +118,7 @@
      * <code>byte</code> to output.
      * <p>
      * Note that this method does not call the <code>write</code> method
-     * of its underlying input stream with the same arguments. Subclasses
+     * of its underlying output stream with the same arguments. Subclasses
      * of <code>FilterOutputStream</code> should provide a more efficient
      * implementation of this method.
      *
@@ -123,6 +128,7 @@
      * @exception  IOException  if an I/O error occurs.
      * @see        java.io.FilterOutputStream#write(int)
      */
+    @Override
     public void write(byte b[], int off, int len) throws IOException {
         if ((off | len | (b.length - (len + off)) | (off + len)) < 0)
             throw new IndexOutOfBoundsException();
@@ -142,6 +148,7 @@
      * @exception  IOException  if an I/O error occurs.
      * @see        java.io.FilterOutputStream#out
      */
+    @Override
     public void flush() throws IOException {
         out.flush();
     }
@@ -158,21 +165,17 @@
      * @see        java.io.FilterOutputStream#flush()
      * @see        java.io.FilterOutputStream#out
      */
-    // BEGIN Android-changed: Integrate OpenJDK 9 fix for double-close. http://b/122733269.
-    /*
-    @SuppressWarnings("try")
-    public void close() throws IOException {
-        try (OutputStream ostream = out) {
-            flush();
-        }
-    }
-    */
     @Override
     public void close() throws IOException {
         if (closed) {
             return;
         }
-        closed = true;
+        synchronized (closeLock) {
+            if (closed) {
+                return;
+            }
+            closed = true;
+        }
 
         Throwable flushException = null;
         try {
@@ -203,5 +206,4 @@
             }
         }
     }
-    // END Android-changed: Integrate OpenJDK 9 fix for double-close. http://b/122733269.
 }
diff --git a/ojluni/src/main/java/java/io/FilterReader.java b/ojluni/src/main/java/java/io/FilterReader.java
index 0826230..60f748f 100644
--- a/ojluni/src/main/java/java/io/FilterReader.java
+++ b/ojluni/src/main/java/java/io/FilterReader.java
@@ -35,7 +35,7 @@
  * additional methods and fields.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public abstract class FilterReader extends Reader {
@@ -69,6 +69,7 @@
      * Reads characters into a portion of an array.
      *
      * @exception  IOException  If an I/O error occurs
+     * @exception  IndexOutOfBoundsException {@inheritDoc}
      */
     public int read(char cbuf[], int off, int len) throws IOException {
         return in.read(cbuf, off, len);
diff --git a/ojluni/src/main/java/java/io/FilterWriter.java b/ojluni/src/main/java/java/io/FilterWriter.java
index fb307d5..8272b3c 100644
--- a/ojluni/src/main/java/java/io/FilterWriter.java
+++ b/ojluni/src/main/java/java/io/FilterWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@
  * provide additional methods and fields.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public abstract class FilterWriter extends Writer {
@@ -72,7 +72,12 @@
      * @param  off   Offset from which to start reading characters
      * @param  len   Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(char cbuf[], int off, int len) throws IOException {
         out.write(cbuf, off, len);
@@ -85,7 +90,12 @@
      * @param  off  Offset from which to start reading characters
      * @param  len  Number of characters to be written
      *
-     * @exception  IOException  If an I/O error occurs
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
+     *
+     * @throws  IOException  If an I/O error occurs
      */
     public void write(String str, int off, int len) throws IOException {
         out.write(str, off, len);
diff --git a/ojluni/src/main/java/java/io/Flushable.java b/ojluni/src/main/java/java/io/Flushable.java
index fe90fbd..9bdc56e 100644
--- a/ojluni/src/main/java/java/io/Flushable.java
+++ b/ojluni/src/main/java/java/io/Flushable.java
@@ -28,7 +28,7 @@
 import java.io.IOException;
 
 /**
- * A <tt>Flushable</tt> is a destination of data that can be flushed.  The
+ * A {@code Flushable} is a destination of data that can be flushed.  The
  * flush method is invoked to write any buffered output to the underlying
  * stream.
  *
diff --git a/ojluni/src/main/java/java/io/IOError.java b/ojluni/src/main/java/java/io/IOError.java
index f9626cd..ea9ec0f 100644
--- a/ojluni/src/main/java/java/io/IOError.java
+++ b/ojluni/src/main/java/java/io/IOError.java
@@ -35,11 +35,11 @@
     /**
      * Constructs a new instance of IOError with the specified cause. The
      * IOError is created with the detail message of
-     * <tt>(cause==null ? null : cause.toString())</tt> (which typically
+     * {@code (cause==null ? null : cause.toString())} (which typically
      * contains the class and detail message of cause).
      *
      * @param  cause
-     *         The cause of this error, or <tt>null</tt> if the cause
+     *         The cause of this error, or {@code null} if the cause
      *         is not known
      */
     public IOError(Throwable cause) {
diff --git a/ojluni/src/main/java/java/io/IOException.java b/ojluni/src/main/java/java/io/IOException.java
index 745b579..c0d6ea5 100644
--- a/ojluni/src/main/java/java/io/IOException.java
+++ b/ojluni/src/main/java/java/io/IOException.java
@@ -33,7 +33,7 @@
  * @author  unascribed
  * @see     java.io.InputStream
  * @see     java.io.OutputStream
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class IOException extends Exception {
diff --git a/ojluni/src/main/java/java/io/InputStream.java b/ojluni/src/main/java/java/io/InputStream.java
index 6c46a40..7bccfaf 100644
--- a/ojluni/src/main/java/java/io/InputStream.java
+++ b/ojluni/src/main/java/java/io/InputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,11 @@
 
 package java.io;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
 /**
  * This abstract class is the superclass of all classes representing
  * an input stream of bytes.
@@ -40,7 +45,7 @@
  * @see     java.io.InputStream#read()
  * @see     java.io.OutputStream
  * @see     java.io.PushbackInputStream
- * @since   JDK1.0
+ * @since   1.0
  */
 public abstract class InputStream implements Closeable {
 
@@ -48,6 +53,105 @@
     // use when skipping.
     private static final int MAX_SKIP_BUFFER_SIZE = 2048;
 
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+    /**
+     * Returns a new {@code InputStream} that reads no bytes. The returned
+     * stream is initially open.  The stream is closed by calling the
+     * {@code close()} method.  Subsequent calls to {@code close()} have no
+     * effect.
+     *
+     * <p> While the stream is open, the {@code available()}, {@code read()},
+     * {@code read(byte[])}, {@code read(byte[], int, int)},
+     * {@code readAllBytes()}, {@code readNBytes(byte[], int, int)},
+     * {@code readNBytes(int)}, {@code skip(long)}, and
+     * {@code transferTo()} methods all behave as if end of stream has been
+     * reached.  After the stream has been closed, these methods all throw
+     * {@code IOException}.
+     *
+     * <p> The {@code markSupported()} method returns {@code false}.  The
+     * {@code mark()} method does nothing, and the {@code reset()} method
+     * throws {@code IOException}.
+     *
+     * @return an {@code InputStream} which contains no bytes
+     *
+     * @since 11
+     */
+    public static InputStream nullInputStream() {
+        return new InputStream() {
+            private volatile boolean closed;
+
+            private void ensureOpen() throws IOException {
+                if (closed) {
+                    throw new IOException("Stream closed");
+                }
+            }
+
+            @Override
+            public int available () throws IOException {
+                ensureOpen();
+                return 0;
+            }
+
+            @Override
+            public int read() throws IOException {
+                ensureOpen();
+                return -1;
+            }
+
+            @Override
+            public int read(byte[] b, int off, int len) throws IOException {
+                Objects.checkFromIndexSize(off, len, b.length);
+                if (len == 0) {
+                    return 0;
+                }
+                ensureOpen();
+                return -1;
+            }
+
+            @Override
+            public byte[] readAllBytes() throws IOException {
+                ensureOpen();
+                return new byte[0];
+            }
+
+            @Override
+            public int readNBytes(byte[] b, int off, int len)
+                throws IOException {
+                Objects.checkFromIndexSize(off, len, b.length);
+                ensureOpen();
+                return 0;
+            }
+
+            @Override
+            public byte[] readNBytes(int len) throws IOException {
+                if (len < 0) {
+                    throw new IllegalArgumentException("len < 0");
+                }
+                ensureOpen();
+                return new byte[0];
+            }
+
+            @Override
+            public long skip(long n) throws IOException {
+                ensureOpen();
+                return 0L;
+            }
+
+            @Override
+            public long transferTo(OutputStream out) throws IOException {
+                Objects.requireNonNull(out);
+                ensureOpen();
+                return 0L;
+            }
+
+            @Override
+            public void close() throws IOException {
+                closed = true;
+            }
+        };
+    }
+
     /**
      * Reads the next byte of data from the input stream. The value byte is
      * returned as an <code>int</code> in the range <code>0</code> to
@@ -139,8 +243,8 @@
      * <code>b</code> and the number of bytes read before the exception
      * occurred is returned. The default implementation of this method blocks
      * until the requested amount of input data <code>len</code> has been read,
-     * end of file is detected, or an exception is thrown. Subclasses are encouraged
-     * to provide a more efficient implementation of this method.
+     * end of file is detected, or an exception is thrown. Subclasses are
+     * encouraged to provide a more efficient implementation of this method.
      *
      * @param      b     the buffer into which the data is read.
      * @param      off   the start offset in array <code>b</code>
@@ -159,11 +263,8 @@
      * @see        java.io.InputStream#read()
      */
     public int read(byte b[], int off, int len) throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
+        Objects.checkFromIndexSize(off, len, b.length);
+        if (len == 0) {
             return 0;
         }
 
@@ -188,6 +289,213 @@
     }
 
     /**
+     * The maximum size of array to allocate.
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
+     */
+    private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
+
+    /**
+     * Reads all remaining bytes from the input stream. This method blocks until
+     * all remaining bytes have been read and end of stream is detected, or an
+     * exception is thrown. This method does not close the input stream.
+     *
+     * <p> When this stream reaches end of stream, further invocations of this
+     * method will return an empty byte array.
+     *
+     * <p> Note that this method is intended for simple cases where it is
+     * convenient to read all bytes into a byte array. It is not intended for
+     * reading input streams with large amounts of data.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes have been read. Consequently the input
+     * stream may not be at end of stream and may be in an inconsistent state.
+     * It is strongly recommended that the stream be promptly closed if an I/O
+     * error occurs.
+     *
+     * @implSpec
+     * This method invokes {@link #readNBytes(int)} with a length of
+     * {@link Integer#MAX_VALUE}.
+     *
+     * @return a byte array containing the bytes read from this input stream
+     * @throws IOException if an I/O error occurs
+     * @throws OutOfMemoryError if an array of the required size cannot be
+     *         allocated.
+     *
+     * @since 9
+     */
+    public byte[] readAllBytes() throws IOException {
+        return readNBytes(Integer.MAX_VALUE);
+    }
+
+    /**
+     * Reads up to a specified number of bytes from the input stream. This
+     * method blocks until the requested number of bytes have been read, end
+     * of stream is detected, or an exception is thrown. This method does not
+     * close the input stream.
+     *
+     * <p> The length of the returned array equals the number of bytes read
+     * from the stream. If {@code len} is zero, then no bytes are read and
+     * an empty byte array is returned. Otherwise, up to {@code len} bytes
+     * are read from the stream. Fewer than {@code len} bytes may be read if
+     * end of stream is encountered.
+     *
+     * <p> When this stream reaches end of stream, further invocations of this
+     * method will return an empty byte array.
+     *
+     * <p> Note that this method is intended for simple cases where it is
+     * convenient to read the specified number of bytes into a byte array. The
+     * total amount of memory allocated by this method is proportional to the
+     * number of bytes read from the stream which is bounded by {@code len}.
+     * Therefore, the method may be safely called with very large values of
+     * {@code len} provided sufficient memory is available.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes have been read. Consequently the input
+     * stream may not be at end of stream and may be in an inconsistent state.
+     * It is strongly recommended that the stream be promptly closed if an I/O
+     * error occurs.
+     *
+     * @implNote
+     * The number of bytes allocated to read data from this stream and return
+     * the result is bounded by {@code 2*(long)len}, inclusive.
+     *
+     * @param len the maximum number of bytes to read
+     * @return a byte array containing the bytes read from this input stream
+     * @throws IllegalArgumentException if {@code length} is negative
+     * @throws IOException if an I/O error occurs
+     * @throws OutOfMemoryError if an array of the required size cannot be
+     *         allocated.
+     *
+     * @since 11
+     */
+    public byte[] readNBytes(int len) throws IOException {
+        if (len < 0) {
+            throw new IllegalArgumentException("len < 0");
+        }
+
+        List<byte[]> bufs = null;
+        byte[] result = null;
+        int total = 0;
+        int remaining = len;
+        int n;
+        do {
+            byte[] buf = new byte[Math.min(remaining, DEFAULT_BUFFER_SIZE)];
+            int nread = 0;
+
+            // read to EOF which may read more or less than buffer size
+            while ((n = read(buf, nread,
+                    Math.min(buf.length - nread, remaining))) > 0) {
+                nread += n;
+                remaining -= n;
+            }
+
+            if (nread > 0) {
+                if (MAX_BUFFER_SIZE - total < nread) {
+                    throw new OutOfMemoryError("Required array size too large");
+                }
+                total += nread;
+                if (result == null) {
+                    result = buf;
+                } else {
+                    if (bufs == null) {
+                        bufs = new ArrayList<>();
+                        bufs.add(result);
+                    }
+                    bufs.add(buf);
+                }
+            }
+            // if the last call to read returned -1 or the number of bytes
+            // requested have been read then break
+        } while (n >= 0 && remaining > 0);
+
+        if (bufs == null) {
+            if (result == null) {
+                return new byte[0];
+            }
+            return result.length == total ?
+                result : Arrays.copyOf(result, total);
+        }
+
+        result = new byte[total];
+        int offset = 0;
+        remaining = total;
+        for (byte[] b : bufs) {
+            int count = Math.min(b.length, remaining);
+            System.arraycopy(b, 0, result, offset, count);
+            offset += count;
+            remaining -= count;
+        }
+
+        return result;
+    }
+
+    /**
+     * Reads the requested number of bytes from the input stream into the given
+     * byte array. This method blocks until {@code len} bytes of input data have
+     * been read, end of stream is detected, or an exception is thrown. The
+     * number of bytes actually read, possibly zero, is returned. This method
+     * does not close the input stream.
+     *
+     * <p> In the case where end of stream is reached before {@code len} bytes
+     * have been read, then the actual number of bytes read will be returned.
+     * When this stream reaches end of stream, further invocations of this
+     * method will return zero.
+     *
+     * <p> If {@code len} is zero, then no bytes are read and {@code 0} is
+     * returned; otherwise, there is an attempt to read up to {@code len} bytes.
+     *
+     * <p> The first byte read is stored into element {@code b[off]}, the next
+     * one in to {@code b[off+1]}, and so on. The number of bytes read is, at
+     * most, equal to {@code len}. Let <i>k</i> be the number of bytes actually
+     * read; these bytes will be stored in elements {@code b[off]} through
+     * {@code b[off+}<i>k</i>{@code -1]}, leaving elements {@code b[off+}<i>k</i>
+     * {@code ]} through {@code b[off+len-1]} unaffected.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes of {@code b} have been updated with
+     * data from the input stream. Consequently the input stream and {@code b}
+     * may be in an inconsistent state. It is strongly recommended that the
+     * stream be promptly closed if an I/O error occurs.
+     *
+     * @param  b the byte array into which the data is read
+     * @param  off the start offset in {@code b} at which the data is written
+     * @param  len the maximum number of bytes to read
+     * @return the actual number of bytes read into the buffer
+     * @throws IOException if an I/O error occurs
+     * @throws NullPointerException if {@code b} is {@code null}
+     * @throws IndexOutOfBoundsException If {@code off} is negative, {@code len}
+     *         is negative, or {@code len} is greater than {@code b.length - off}
+     *
+     * @since 9
+     */
+    public int readNBytes(byte[] b, int off, int len) throws IOException {
+        Objects.checkFromIndexSize(off, len, b.length);
+
+        int n = 0;
+        while (n < len) {
+            int count = read(b, off + n, len - n);
+            if (count < 0)
+                break;
+            n += count;
+        }
+        return n;
+    }
+
+    /**
      * Skips over and discards <code>n</code> bytes of data from this input
      * stream. The <code>skip</code> method may, for a variety of reasons, end
      * up skipping over some smaller number of bytes, possibly <code>0</code>.
@@ -198,7 +506,7 @@
      * returns 0, and no bytes are skipped. Subclasses may handle the negative
      * value differently.
      *
-     * <p> The <code>skip</code> method of this class creates a
+     * <p> The <code>skip</code> method implementation of this class creates a
      * byte array and then repeatedly reads into it until <code>n</code> bytes
      * have been read or the end of the stream has been reached. Subclasses are
      * encouraged to provide a more efficient implementation of this method.
@@ -206,8 +514,7 @@
      *
      * @param      n   the number of bytes to be skipped.
      * @return     the actual number of bytes skipped.
-     * @exception  IOException  if the stream does not support seek,
-     *                          or if some other I/O error occurs.
+     * @throws     IOException  if an I/O error occurs.
      */
     public long skip(long n) throws IOException {
 
@@ -232,29 +539,29 @@
     }
 
     /**
-     * Returns an estimate of the number of bytes that can be read (or
-     * skipped over) from this input stream without blocking by the next
-     * invocation of a method for this input stream. The next invocation
-     * might be the same thread or another thread.  A single read or skip of this
-     * many bytes will not block, but may read or skip fewer bytes.
+     * Returns an estimate of the number of bytes that can be read (or skipped
+     * over) from this input stream without blocking, which may be 0, or 0 when
+     * end of stream is detected.  The read might be on the same thread or
+     * another thread.  A single read or skip of this many bytes will not block,
+     * but may read or skip fewer bytes.
      *
-     * <p> Note that while some implementations of {@code InputStream} will return
-     * the total number of bytes in the stream, many will not.  It is
+     * <p> Note that while some implementations of {@code InputStream} will
+     * return the total number of bytes in the stream, many will not.  It is
      * never correct to use the return value of this method to allocate
      * a buffer intended to hold all data in this stream.
      *
-     * <p> A subclass' implementation of this method may choose to throw an
-     * {@link IOException} if this input stream has been closed by
-     * invoking the {@link #close()} method.
+     * <p> A subclass's implementation of this method may choose to throw an
+     * {@link IOException} if this input stream has been closed by invoking the
+     * {@link #close()} method.
      *
-     * <p> The {@code available} method for class {@code InputStream} always
-     * returns {@code 0}.
+     * <p> The {@code available} method of {@code InputStream} always returns
+     * {@code 0}.
      *
      * <p> This method should be overridden by subclasses.
      *
-     * @return     an estimate of the number of bytes that can be read (or skipped
-     *             over) from this input stream without blocking or {@code 0} when
-     *             it reaches the end of the input stream.
+     * @return     an estimate of the number of bytes that can be read (or
+     *             skipped over) from this input stream without blocking or
+     *             {@code 0} when it reaches the end of the input stream.
      * @exception  IOException if an I/O error occurs.
      */
     public int available() throws IOException {
@@ -364,4 +671,40 @@
         return false;
     }
 
+    /**
+     * Reads all bytes from this input stream and writes the bytes to the
+     * given output stream in the order that they are read. On return, this
+     * input stream will be at end of stream. This method does not close either
+     * stream.
+     * <p>
+     * This method may block indefinitely reading from the input stream, or
+     * writing to the output stream. The behavior for the case where the input
+     * and/or output stream is <i>asynchronously closed</i>, or the thread
+     * interrupted during the transfer, is highly input and output stream
+     * specific, and therefore not specified.
+     * <p>
+     * If an I/O error occurs reading from the input stream or writing to the
+     * output stream, then it may do so after some bytes have been read or
+     * written. Consequently the input stream may not be at end of stream and
+     * one, or both, streams may be in an inconsistent state. It is strongly
+     * recommended that both streams be promptly closed if an I/O error occurs.
+     *
+     * @param  out the output stream, non-null
+     * @return the number of bytes transferred
+     * @throws IOException if an I/O error occurs when reading or writing
+     * @throws NullPointerException if {@code out} is {@code null}
+     *
+     * @since 9
+     */
+    public long transferTo(OutputStream out) throws IOException {
+        Objects.requireNonNull(out, "out");
+        long transferred = 0;
+        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+        int read;
+        while ((read = this.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) {
+            out.write(buffer, 0, read);
+            transferred += read;
+        }
+        return transferred;
+    }
 }
diff --git a/ojluni/src/main/java/java/io/InputStreamReader.java b/ojluni/src/main/java/java/io/InputStreamReader.java
index e131dca..bb76cdc 100644
--- a/ojluni/src/main/java/java/io/InputStreamReader.java
+++ b/ojluni/src/main/java/java/io/InputStreamReader.java
@@ -56,7 +56,7 @@
  * @see java.nio.charset.Charset
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class InputStreamReader extends Reader {
@@ -70,12 +70,8 @@
      */
     public InputStreamReader(InputStream in) {
         super(in);
-        try {
-            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
-        } catch (UnsupportedEncodingException e) {
-            // The default encoding should always be available
-            throw new Error(e);
-        }
+        sd = StreamDecoder.forInputStreamReader(in, this,
+                Charset.defaultCharset()); // ## check lock object
     }
 
     /**
diff --git a/ojluni/src/main/java/java/io/InvalidClassException.java b/ojluni/src/main/java/java/io/InvalidClassException.java
index 77f0a5a..3d78c6b 100644
--- a/ojluni/src/main/java/java/io/InvalidClassException.java
+++ b/ojluni/src/main/java/java/io/InvalidClassException.java
@@ -36,7 +36,7 @@
  * </UL>
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class InvalidClassException extends ObjectStreamException {
 
diff --git a/ojluni/src/main/java/java/io/InvalidObjectException.java b/ojluni/src/main/java/java/io/InvalidObjectException.java
index fbe1108..5853911 100644
--- a/ojluni/src/main/java/java/io/InvalidObjectException.java
+++ b/ojluni/src/main/java/java/io/InvalidObjectException.java
@@ -30,10 +30,10 @@
  * tests.  The argument should provide the reason for the failure.
  *
  * @see ObjectInputValidation
- * @since JDK1.1
+ * @since 1.1
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class InvalidObjectException extends ObjectStreamException {
 
diff --git a/ojluni/src/main/java/java/io/LineNumberInputStream.java b/ojluni/src/main/java/java/io/LineNumberInputStream.java
index 1f37a98..2235a2b 100644
--- a/ojluni/src/main/java/java/io/LineNumberInputStream.java
+++ b/ojluni/src/main/java/java/io/LineNumberInputStream.java
@@ -40,7 +40,7 @@
  *
  * @author     Arthur van Hoff
  * @see        java.io.LineNumberReader
- * @since      JDK1.0
+ * @since      1.0
  * @deprecated This class incorrectly assumes that bytes adequately represent
  *             characters.  As of JDK&nbsp;1.1, the preferred way to operate on
  *             character streams is via the new character-stream classes, which
diff --git a/ojluni/src/main/java/java/io/LineNumberReader.java b/ojluni/src/main/java/java/io/LineNumberReader.java
index 29884fd..bffda6e 100644
--- a/ojluni/src/main/java/java/io/LineNumberReader.java
+++ b/ojluni/src/main/java/java/io/LineNumberReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,17 +34,17 @@
  *
  * <p> By default, line numbering begins at 0. This number increments at every
  * <a href="#lt">line terminator</a> as the data is read, and can be changed
- * with a call to <tt>setLineNumber(int)</tt>.  Note however, that
- * <tt>setLineNumber(int)</tt> does not actually change the current position in
+ * with a call to {@code setLineNumber(int)}.  Note however, that
+ * {@code setLineNumber(int)} does not actually change the current position in
  * the stream; it only changes the value that will be returned by
- * <tt>getLineNumber()</tt>.
+ * {@code getLineNumber()}.
  *
- * <p> A line is considered to be <a name="lt">terminated</a> by any one of a
+ * <p> A line is considered to be <a id="lt">terminated</a> by any one of a
  * line feed ('\n'), a carriage return ('\r'), or a carriage return followed
  * immediately by a linefeed.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class LineNumberReader extends BufferedReader {
@@ -159,6 +159,8 @@
      *
      * @throws  IOException
      *          If an I/O error occurs
+     *
+     * @throws  IndexOutOfBoundsException {@inheritDoc}
      */
     @SuppressWarnings("fallthrough")
     public int read(char cbuf[], int off, int len) throws IOException {
@@ -191,7 +193,7 @@
      *
      * @return  A String containing the contents of the line, not including
      *          any <a href="#lt">line termination characters</a>, or
-     *          <tt>null</tt> if the end of the stream has been reached
+     *          {@code null} if the end of the stream has been reached
      *
      * @throws  IOException
      *          If an I/O error occurs
@@ -224,7 +226,7 @@
      *          If an I/O error occurs
      *
      * @throws  IllegalArgumentException
-     *          If <tt>n</tt> is negative
+     *          If {@code n} is negative
      */
     public long skip(long n) throws IOException {
         if (n < 0)
@@ -259,6 +261,11 @@
      */
     public void mark(int readAheadLimit) throws IOException {
         synchronized (lock) {
+            // If the most recently read character is '\r', then increment the
+            // read ahead limit as in this case if the next character is '\n',
+            // two characters would actually be read by the next read().
+            if (skipLF)
+                readAheadLimit++;
             super.mark(readAheadLimit);
             markedLineNumber = lineNumber;
             markedSkipLF     = skipLF;
diff --git a/ojluni/src/main/java/java/io/NotActiveException.java b/ojluni/src/main/java/java/io/NotActiveException.java
index 13291e6..231598c 100644
--- a/ojluni/src/main/java/java/io/NotActiveException.java
+++ b/ojluni/src/main/java/java/io/NotActiveException.java
@@ -29,7 +29,7 @@
  * Thrown when serialization or deserialization is not active.
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class NotActiveException extends ObjectStreamException {
 
diff --git a/ojluni/src/main/java/java/io/NotSerializableException.java b/ojluni/src/main/java/java/io/NotSerializableException.java
index 70e4f57..43dbc1a 100644
--- a/ojluni/src/main/java/java/io/NotSerializableException.java
+++ b/ojluni/src/main/java/java/io/NotSerializableException.java
@@ -31,7 +31,7 @@
  * this exception. The argument should be the name of the class.
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class NotSerializableException extends ObjectStreamException {
 
diff --git a/ojluni/src/main/java/java/io/ObjectInput.java b/ojluni/src/main/java/java/io/ObjectInput.java
index bc7c26b..92d3b70 100644
--- a/ojluni/src/main/java/java/io/ObjectInput.java
+++ b/ojluni/src/main/java/java/io/ObjectInput.java
@@ -34,7 +34,7 @@
  * @see java.io.InputStream
  * @see java.io.ObjectOutputStream
  * @see java.io.ObjectInputStream
- * @since   JDK1.1
+ * @since   1.1
  */
 public interface ObjectInput extends DataInput, AutoCloseable {
     /**
diff --git a/ojluni/src/main/java/java/io/ObjectInputStream.java b/ojluni/src/main/java/java/io/ObjectInputStream.java
index 8369a59..b8c4c76 100644
--- a/ojluni/src/main/java/java/io/ObjectInputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectInputStream.java
@@ -44,6 +44,7 @@
 import static java.io.ObjectStreamClass.processQueue;
 import sun.reflect.misc.ReflectUtil;
 import dalvik.system.VMStack;
+import jdk.internal.misc.SharedSecrets;
 
 /**
  * An ObjectInputStream deserializes primitive data and objects previously
@@ -239,7 +240,7 @@
             new ReferenceQueue<>();
     }
 
-    // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+    // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
     /*
     static {
         /* Setup access so sun.misc can invoke package private functions. *
@@ -281,10 +282,10 @@
     /** validation callback list */
     private final ValidationList vlist;
     /** recursion depth */
-    // Android-changed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+    // Android-changed: ObjectInputFilter logic not available on Android. http://b/110252929
     // private long depth;
     private int depth;
-    // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+    // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
     // /** Total number of references to any type of object, class, enum, proxy, etc. */
     // private long totalObjectRefs;
     /** whether stream is closed */
@@ -312,7 +313,7 @@
      */
     private SerialCallbackContext curContext;
 
-    // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+    // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
     /**
      * Filter of class descriptors and classes read from the stream;
      * may be null.
@@ -347,7 +348,7 @@
         bin = new BlockDataInputStream(in);
         handles = new HandleTable(10);
         vlist = new ValidationList();
-        // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
         // serialFilter = ObjectInputFilter.Config.getSerialFilter();
         enableOverride = false;
         readStreamHeader();
@@ -379,7 +380,7 @@
         bin = null;
         handles = null;
         vlist = null;
-        // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
         // serialFilter = ObjectInputFilter.Config.getSerialFilter();
         enableOverride = true;
     }
@@ -1129,10 +1130,37 @@
         return bin.readUTF();
     }
 
-    // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+    // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
     // Removed ObjectInputFilter related methods.
 
     /**
+     * Checks the given array type and length to ensure that creation of such
+     * an array is permitted by this ObjectInputStream. The arrayType argument
+     * must represent an actual array type.
+     *
+     * This private method is called via SharedSecrets.
+     *
+     * @param arrayType the array type
+     * @param arrayLength the array length
+     * @throws NullPointerException if arrayType is null
+     * @throws IllegalArgumentException if arrayType isn't actually an array type
+     * @throws NegativeArraySizeException if arrayLength is negative
+     * @throws InvalidClassException if the filter rejects creation
+     */
+    private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {
+        if (! arrayType.isArray()) {
+            throw new IllegalArgumentException("not an array type");
+        }
+
+        if (arrayLength < 0) {
+            throw new NegativeArraySizeException();
+        }
+
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
+        // filterCheck(arrayType, arrayLength);
+    }
+
+    /**
      * Provide access to the persistent fields read from the input stream.
      */
     public static abstract class GetField {
@@ -1381,7 +1409,7 @@
         }
 
         depth++;
-        // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
         // totalObjectRefs++;
         try {
             switch (tc) {
@@ -1459,7 +1487,7 @@
         }
         Object rep = resolveObject(obj);
         if (rep != obj) {
-            // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+            // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
             /*
             // The type of the original object has been filtered but resolveObject
             // may have replaced it;  filter the replacement's type
@@ -1541,7 +1569,7 @@
             throw new InvalidObjectException(
                 "cannot read back reference to unshared object");
         }
-        // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
         // filterCheck(null, -1);       // just a check for number of references, depth, no class
         return obj;
     }
@@ -1597,7 +1625,7 @@
                 throw new StreamCorruptedException(
                     String.format("invalid type code: %02X", tc));
         }
-        // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
         // if (descriptor != null) {
         //     validateDescriptor(descriptor);
         // }
@@ -1648,7 +1676,7 @@
                 ReflectUtil.checkProxyPackageAccess(
                         getClass().getClassLoader(),
                         cl.getInterfaces());
-                // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+                // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
                 // // Filter the interfaces
                 // for (Class<?> clazz : cl.getInterfaces()) {
                 //     filterCheck(clazz, -1);
@@ -1661,7 +1689,7 @@
 
         desc.initProxy(cl, resolveEx, readClassDesc(false));
 
-        // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
         // // Call filterCheck on the definition
         // filterCheck(desc.forClass(), -1);
 
@@ -1759,7 +1787,7 @@
         ObjectStreamClass desc = readClassDesc(false);
         int len = bin.readInt();
 
-        // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+        // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
         // filterCheck(desc.forClass(), len);
 
         Object array = null;
@@ -1910,7 +1938,7 @@
                 rep = cloneArray(rep);
             }
             if (rep != obj) {
-                // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+                // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
                 /*
                 // Filter the replacement object
                 if (rep != null) {
@@ -2399,7 +2427,7 @@
         }
     }
 
-    // Android-removed: ObjectInputFilter logic, to be reconsidered. http://b/110252929
+    // Android-removed: ObjectInputFilter logic not available on Android. http://b/110252929
     // Removed FilterValues class.
 
     /**
@@ -3709,8 +3737,8 @@
     private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
         ois.validator = validator;
     }
-    static {
-        SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
-    }
     */
+    static {
+        SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::checkArray);
+    }
 }
diff --git a/ojluni/src/main/java/java/io/ObjectInputValidation.java b/ojluni/src/main/java/java/io/ObjectInputValidation.java
index dc6f842..09ee8a6 100644
--- a/ojluni/src/main/java/java/io/ObjectInputValidation.java
+++ b/ojluni/src/main/java/java/io/ObjectInputValidation.java
@@ -33,7 +33,7 @@
  * @author  unascribed
  * @see     ObjectInputStream
  * @see     ObjectInputStream#registerValidation(java.io.ObjectInputValidation, int)
- * @since   JDK1.1
+ * @since   1.1
  */
 public interface ObjectInputValidation {
     /**
diff --git a/ojluni/src/main/java/java/io/ObjectOutput.java b/ojluni/src/main/java/java/io/ObjectOutput.java
index 7c2cbeb..720d198 100644
--- a/ojluni/src/main/java/java/io/ObjectOutput.java
+++ b/ojluni/src/main/java/java/io/ObjectOutput.java
@@ -34,7 +34,7 @@
  * @see java.io.InputStream
  * @see java.io.ObjectOutputStream
  * @see java.io.ObjectInputStream
- * @since   JDK1.1
+ * @since   1.1
  */
 public interface ObjectOutput extends DataOutput, AutoCloseable {
     /**
diff --git a/ojluni/src/main/java/java/io/ObjectStreamException.java b/ojluni/src/main/java/java/io/ObjectStreamException.java
index 889cad3..94fc560 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamException.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamException.java
@@ -29,7 +29,7 @@
  * Superclass of all exceptions specific to Object Stream classes.
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public abstract class ObjectStreamException extends IOException {
 
@@ -38,10 +38,10 @@
     /**
      * Create an ObjectStreamException with the specified argument.
      *
-     * @param classname the detailed message for the exception
+     * @param message the detailed message for the exception
      */
-    protected ObjectStreamException(String classname) {
-        super(classname);
+    protected ObjectStreamException(String message) {
+        super(message);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/io/OptionalDataException.java b/ojluni/src/main/java/java/io/OptionalDataException.java
index 91283fd..f51e0ac 100644
--- a/ojluni/src/main/java/java/io/OptionalDataException.java
+++ b/ojluni/src/main/java/java/io/OptionalDataException.java
@@ -43,7 +43,7 @@
  * </ul>
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class OptionalDataException extends ObjectStreamException {
 
diff --git a/ojluni/src/main/java/java/io/OutputStream.java b/ojluni/src/main/java/java/io/OutputStream.java
index c6dd7de..556e7e0 100644
--- a/ojluni/src/main/java/java/io/OutputStream.java
+++ b/ojluni/src/main/java/java/io/OutputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package java.io;
 
+import java.util.Objects;
+
 /**
  * This abstract class is the superclass of all classes representing
  * an output stream of bytes. An output stream accepts output bytes
@@ -41,10 +43,55 @@
  * @see     java.io.FilterOutputStream
  * @see     java.io.InputStream
  * @see     java.io.OutputStream#write(int)
- * @since   JDK1.0
+ * @since   1.0
  */
 public abstract class OutputStream implements Closeable, Flushable {
     /**
+     * Returns a new {@code OutputStream} which discards all bytes.  The
+     * returned stream is initially open.  The stream is closed by calling
+     * the {@code close()} method.  Subsequent calls to {@code close()} have
+     * no effect.
+     *
+     * <p> While the stream is open, the {@code write(int)}, {@code
+     * write(byte[])}, and {@code write(byte[], int, int)} methods do nothing.
+     * After the stream has been closed, these methods all throw {@code
+     * IOException}.
+     *
+     * <p> The {@code flush()} method does nothing.
+     *
+     * @return an {@code OutputStream} which discards all bytes
+     *
+     * @since 11
+     */
+    public static OutputStream nullOutputStream() {
+        return new OutputStream() {
+            private volatile boolean closed;
+
+            private void ensureOpen() throws IOException {
+                if (closed) {
+                    throw new IOException("Stream closed");
+                }
+            }
+
+            @Override
+            public void write(int b) throws IOException {
+                ensureOpen();
+            }
+
+            @Override
+            public void write(byte b[], int off, int len) throws IOException {
+                Objects.checkFromIndexSize(off, len, b.length);
+                ensureOpen();
+            }
+
+            @Override
+            public void close() {
+                closed = true;
+            }
+        };
+    }
+
+    /**
      * Writes the specified byte to this output stream. The general
      * contract for <code>write</code> is that one byte is written
      * to the output stream. The byte to be written is the eight
@@ -94,7 +141,7 @@
      * <p>
      * If <code>off</code> is negative, or <code>len</code> is negative, or
      * <code>off+len</code> is greater than the length of the array
-     * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
+     * {@code b}, then an {@code IndexOutOfBoundsException} is thrown.
      *
      * @param      b     the data.
      * @param      off   the start offset in the data.
@@ -104,14 +151,8 @@
      *             stream is closed.
      */
     public void write(byte b[], int off, int len) throws IOException {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if ((off < 0) || (off > b.length) || (len < 0) ||
-                   ((off + len) > b.length) || ((off + len) < 0)) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0) {
-            return;
-        }
+        Objects.checkFromIndexSize(off, len, b.length);
+        // len == 0 condition implicitly handled by loop bounds
         for (int i = 0 ; i < len ; i++) {
             write(b[off + i]);
         }
diff --git a/ojluni/src/main/java/java/io/PipedInputStream.java b/ojluni/src/main/java/java/io/PipedInputStream.java
index b79bcbd..b1be6b4 100644
--- a/ojluni/src/main/java/java/io/PipedInputStream.java
+++ b/ojluni/src/main/java/java/io/PipedInputStream.java
@@ -42,18 +42,18 @@
  * The piped input stream contains a buffer,
  * decoupling read operations from write operations,
  * within limits.
- * A pipe is said to be <a name="BROKEN"> <i>broken</i> </a> if a
+ * A pipe is said to be <a id="BROKEN"> <i>broken</i> </a> if a
  * thread that was providing data bytes to the connected
  * piped output stream is no longer alive.
  *
  * @author  James Gosling
  * @see     java.io.PipedOutputStream
- * @since   JDK1.0
+ * @since   1.0
  */
 public class PipedInputStream extends InputStream {
-    boolean closedByWriter = false;
-    volatile boolean closedByReader = false;
-    boolean connected = false;
+    boolean closedByWriter;
+    volatile boolean closedByReader;
+    boolean connected;
 
         /* REMIND: identification of the read and write sides needs to be
            more sophisticated.  Either using thread groups (but what about
@@ -66,7 +66,7 @@
 
     /**
      * The default size of the pipe's circular input buffer.
-     * @since   JDK1.1
+     * @since   1.1
      */
     // This used to be a constant before the pipe size was allowed
     // to change. This field will continue to be maintained
@@ -75,7 +75,7 @@
 
     /**
      * The circular buffer into which incoming data is placed.
-     * @since   JDK1.1
+     * @since   1.1
      */
     protected byte buffer[];
 
@@ -84,14 +84,14 @@
      * next byte of data will be stored when received from the connected
      * piped output stream. <code>in&lt;0</code> implies the buffer is empty,
      * <code>in==out</code> implies the buffer is full
-     * @since   JDK1.1
+     * @since   1.1
      */
     protected int in = -1;
 
     /**
      * The index of the position in the circular buffer at which the next
      * byte of data will be read by this piped input stream.
-     * @since   JDK1.1
+     * @since   1.1
      */
     protected int out = 0;
 
@@ -198,7 +198,7 @@
      * @exception IOException If the pipe is <a href="#BROKEN"> <code>broken</code></a>,
      *          {@link #connect(java.io.PipedOutputStream) unconnected},
      *          closed, or if an I/O error occurs.
-     * @since     JDK1.1
+     * @since     1.1
      */
     protected synchronized void receive(int b) throws IOException {
         checkStateForReceive();
@@ -428,7 +428,7 @@
      *          <a href="#BROKEN"> <code>broken</code></a>.
      *
      * @exception  IOException  if an I/O error occurs.
-     * @since   JDK1.0.2
+     * @since   1.0.2
      */
     public synchronized int available() throws IOException {
         if(in < 0)
diff --git a/ojluni/src/main/java/java/io/PipedOutputStream.java b/ojluni/src/main/java/java/io/PipedOutputStream.java
index feed73a..79ffd38 100644
--- a/ojluni/src/main/java/java/io/PipedOutputStream.java
+++ b/ojluni/src/main/java/java/io/PipedOutputStream.java
@@ -35,13 +35,13 @@
  * read from the connected <code>PipedInputStream</code> by some
  * other thread. Attempting to use both objects from a single thread
  * is not recommended as it may deadlock the thread.
- * The pipe is said to be <a name=BROKEN> <i>broken</i> </a> if a
+ * The pipe is said to be <a id=BROKEN> <i>broken</i> </a> if a
  * thread that was reading data bytes from the connected piped input
  * stream is no longer alive.
  *
  * @author  James Gosling
  * @see     java.io.PipedInputStream
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class PipedOutputStream extends OutputStream {
diff --git a/ojluni/src/main/java/java/io/PipedReader.java b/ojluni/src/main/java/java/io/PipedReader.java
index d72e1e5..fe6b0ea 100644
--- a/ojluni/src/main/java/java/io/PipedReader.java
+++ b/ojluni/src/main/java/java/io/PipedReader.java
@@ -32,7 +32,7 @@
  * Piped character-input streams.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class PipedReader extends Reader {
@@ -292,6 +292,7 @@
      *                  <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
      *                  {@link #connect(java.io.PipedWriter) unconnected}, closed,
      *                  or an I/O error occurs.
+     * @exception  IndexOutOfBoundsException {@inheritDoc}
      */
     public synchronized int read(char cbuf[], int off, int len)  throws IOException {
         if (!connected) {
diff --git a/ojluni/src/main/java/java/io/PipedWriter.java b/ojluni/src/main/java/java/io/PipedWriter.java
index 46e1455..a4534b8 100644
--- a/ojluni/src/main/java/java/io/PipedWriter.java
+++ b/ojluni/src/main/java/java/io/PipedWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  * Piped character-output streams.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class PipedWriter extends Writer {
@@ -125,19 +125,25 @@
     }
 
     /**
-     * Writes <code>len</code> characters from the specified character array
-     * starting at offset <code>off</code> to this piped output stream.
+     * Writes {@code len} characters from the specified character array
+     * starting at offset {@code off} to this piped output stream.
      * This method blocks until all the characters are written to the output
      * stream.
      * If a thread was reading data characters from the connected piped input
      * stream, but the thread is no longer alive, then an
-     * <code>IOException</code> is thrown.
+     * {@code IOException} is thrown.
      *
      * @param      cbuf  the data.
      * @param      off   the start offset in the data.
      * @param      len   the number of characters to write.
-     * @exception  IOException  if the pipe is
-     *          <a href=PipedOutputStream.html#BROKEN> <code>broken</code></a>,
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
+     * @throws  IOException  if the pipe is
+     *          <a href=PipedOutputStream.html#BROKEN><code>broken</code></a>,
      *          {@link #connect(java.io.PipedReader) unconnected}, closed
      *          or an I/O error occurs.
      */
diff --git a/ojluni/src/main/java/java/io/PrintStream.java b/ojluni/src/main/java/java/io/PrintStream.java
index 809d39b..7df8353 100644
--- a/ojluni/src/main/java/java/io/PrintStream.java
+++ b/ojluni/src/main/java/java/io/PrintStream.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,26 +33,32 @@
 import java.nio.charset.UnsupportedCharsetException;
 
 /**
- * A <code>PrintStream</code> adds functionality to another output stream,
+ * A {@code PrintStream} adds functionality to another output stream,
  * namely the ability to print representations of various data values
  * conveniently.  Two other features are provided as well.  Unlike other output
- * streams, a <code>PrintStream</code> never throws an
- * <code>IOException</code>; instead, exceptional situations merely set an
- * internal flag that can be tested via the <code>checkError</code> method.
- * Optionally, a <code>PrintStream</code> can be created so as to flush
- * automatically; this means that the <code>flush</code> method is
+ * streams, a {@code PrintStream} never throws an
+ * {@code IOException}; instead, exceptional situations merely set an
+ * internal flag that can be tested via the {@code checkError} method.
+ * Optionally, a {@code PrintStream} can be created so as to flush
+ * automatically; this means that the {@code flush} method is
  * automatically invoked after a byte array is written, one of the
- * <code>println</code> methods is invoked, or a newline character or byte
- * (<code>'\n'</code>) is written.
+ * {@code println} methods is invoked, or a newline character or byte
+ * ({@code '\n'}) is written.
  *
- * <p> All characters printed by a <code>PrintStream</code> are converted into
- * bytes using the platform's default character encoding.  The <code>{@link
- * PrintWriter}</code> class should be used in situations that require writing
- * characters rather than bytes.
+ * <p> All characters printed by a {@code PrintStream} are converted into
+ * bytes using the given encoding or charset, or platform's default character
+ * encoding if not specified.
+ * The {@link PrintWriter} class should be used in situations that require
+ *  writing characters rather than bytes.
+ *
+ * <p> This class always replaces malformed and unmappable character sequences with
+ * the charset's default replacement string.
+ * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more
+ * control over the encoding process is required.
  *
  * @author     Frank Yellin
  * @author     Mark Reinhold
- * @since      JDK1.0
+ * @since      1.0
  */
 
 public class PrintStream extends FilterOutputStream
@@ -110,24 +116,13 @@
         // this.textOut = new BufferedWriter(charOut);
     }
 
-    private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {
-        super(out);
-        this.autoFlush = autoFlush;
-        // Android-changed: Lazy initialization of charOut and textOut.
-        // this.charOut = new OutputStreamWriter(this, charset);
-        // this.textOut = new BufferedWriter(charOut);
-        this.charset = charset;
-    }
-
     /* Variant of the private constructor so that the given charset name
      * can be verified before evaluating the OutputStream argument. Used
      * by constructors creating a FileOutputStream that also take a
      * charset name.
      */
-    private PrintStream(boolean autoFlush, Charset charset, OutputStream out)
-        throws UnsupportedEncodingException
-    {
-        this(autoFlush, out, charset);
+    private PrintStream(boolean autoFlush, Charset charset, OutputStream out) {
+        this(out, autoFlush, charset);
     }
 
     /**
@@ -149,8 +144,8 @@
      *                    printed
      * @param  autoFlush  A boolean; if true, the output buffer will be flushed
      *                    whenever a byte array is written, one of the
-     *                    <code>println</code> methods is invoked, or a newline
-     *                    character or byte (<code>'\n'</code>) is written
+     *                    {@code println} methods is invoked, or a newline
+     *                    character or byte ({@code '\n'}) is written
      *
      * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean)
      */
@@ -165,8 +160,8 @@
      *                    printed
      * @param  autoFlush  A boolean; if true, the output buffer will be flushed
      *                    whenever a byte array is written, one of the
-     *                    <code>println</code> methods is invoked, or a newline
-     *                    character or byte (<code>'\n'</code>) is written
+     *                    {@code println} methods is invoked, or a newline
+     *                    character or byte ({@code '\n'}) is written
      * @param  encoding   The name of a supported
      *                    <a href="../lang/package-summary.html#charenc">
      *                    character encoding</a>
@@ -179,9 +174,30 @@
     public PrintStream(OutputStream out, boolean autoFlush, String encoding)
         throws UnsupportedEncodingException
     {
-        this(autoFlush,
-             requireNonNull(out, "Null output stream"),
-             toCharset(encoding));
+        this(requireNonNull(out, "Null output stream"), autoFlush, toCharset(encoding));
+    }
+
+    /**
+     * Creates a new print stream, with the specified OutputStream, automatic line
+     * flushing and charset.  This convenience constructor creates the necessary
+     * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
+     * which will encode characters using the provided charset.
+     *
+     * @param  out        The output stream to which values and objects will be
+     *                    printed
+     * @param  autoFlush  A boolean; if true, the output buffer will be flushed
+     *                    whenever a byte array is written, one of the
+     *                    {@code println} methods is invoked, or a newline
+     *                    character or byte ({@code '\n'}) is written
+     * @param  charset    A {@linkplain java.nio.charset.Charset charset}
+     *
+     * @since  10
+     */
+    public PrintStream(OutputStream out, boolean autoFlush, Charset charset) {
+        super(out);
+        this.autoFlush = autoFlush;
+        this.charOut = new OutputStreamWriter(this, charset);
+        this.textOut = new BufferedWriter(charOut);
     }
 
     /**
@@ -257,6 +273,36 @@
 
     /**
      * Creates a new print stream, without automatic line flushing, with the
+     * specified file name and charset.  This convenience constructor creates
+     * the necessary intermediate {@link java.io.OutputStreamWriter
+     * OutputStreamWriter}, which will encode characters using the provided
+     * charset.
+     *
+     * @param  fileName
+     *         The name of the file to use as the destination of this print
+     *         stream.  If the file exists, then it will be truncated to
+     *         zero size; otherwise, a new file will be created.  The output
+     *         will be written to the file and is buffered.
+     *
+     * @param  charset
+     *         A {@linkplain java.nio.charset.Charset charset}
+     *
+     * @throws  IOException
+     *          if an I/O error occurs while opening or creating the file
+     *
+     * @throws  SecurityException
+     *          If a security manager is present and {@link
+     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
+     *          access to the file
+     *
+     * @since  10
+     */
+    public PrintStream(String fileName, Charset charset) throws IOException {
+        this(false, requireNonNull(charset, "charset"), new FileOutputStream(fileName));
+    }
+
+    /**
+     * Creates a new print stream, without automatic line flushing, with the
      * specified file.  This convenience constructor creates the necessary
      * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
      * which will encode characters using the {@linkplain
@@ -326,6 +372,37 @@
         this(false, toCharset(csn), new FileOutputStream(file));
     }
 
+
+    /**
+     * Creates a new print stream, without automatic line flushing, with the
+     * specified file and charset.  This convenience constructor creates
+     * the necessary intermediate {@link java.io.OutputStreamWriter
+     * OutputStreamWriter}, which will encode characters using the provided
+     * charset.
+     *
+     * @param  file
+     *         The file to use as the destination of this print stream.  If the
+     *         file exists, then it will be truncated to zero size; otherwise,
+     *         a new file will be created.  The output will be written to the
+     *         file and is buffered.
+     *
+     * @param  charset
+     *         A {@linkplain java.nio.charset.Charset charset}
+     *
+     * @throws  IOException
+     *          if an I/O error occurs while opening or creating the file
+     *
+     * @throws  SecurityException
+     *          If a security manager is present and {@link
+     *          SecurityManager#checkWrite checkWrite(file.getPath())}
+     *          denies write access to the file
+     *
+     * @since  10
+     */
+    public PrintStream(File file, Charset charset) throws IOException {
+        this(false, requireNonNull(charset, "charset"), new FileOutputStream(file));
+    }
+
     /** Check to make sure that the stream has not been closed */
     private void ensureOpen() throws IOException {
         if (out == null)
@@ -394,21 +471,21 @@
 
     /**
      * Flushes the stream and checks its error state. The internal error state
-     * is set to <code>true</code> when the underlying output stream throws an
-     * <code>IOException</code> other than <code>InterruptedIOException</code>,
-     * and when the <code>setError</code> method is invoked.  If an operation
+     * is set to {@code true} when the underlying output stream throws an
+     * {@code IOException} other than {@code InterruptedIOException},
+     * and when the {@code setError} method is invoked.  If an operation
      * on the underlying output stream throws an
-     * <code>InterruptedIOException</code>, then the <code>PrintStream</code>
+     * {@code InterruptedIOException}, then the {@code PrintStream}
      * converts the exception back into an interrupt by doing:
-     * <pre>
+     * <pre>{@code
      *     Thread.currentThread().interrupt();
-     * </pre>
+     * }</pre>
      * or the equivalent.
      *
-     * @return <code>true</code> if and only if this stream has encountered an
-     *         <code>IOException</code> other than
-     *         <code>InterruptedIOException</code>, or the
-     *         <code>setError</code> method has been invoked
+     * @return {@code true} if and only if this stream has encountered an
+     *         {@code IOException} other than
+     *         {@code InterruptedIOException}, or the
+     *         {@code setError} method has been invoked
      */
     public boolean checkError() {
         if (out != null)
@@ -421,13 +498,13 @@
     }
 
     /**
-     * Sets the error state of the stream to <code>true</code>.
+     * Sets the error state of the stream to {@code true}.
      *
      * <p> This method will cause subsequent invocations of {@link
-     * #checkError()} to return <tt>true</tt> until {@link
-     * #clearError()} is invoked.
+     * #checkError()} to return {@code true} until
+     * {@link #clearError()} is invoked.
      *
-     * @since JDK1.1
+     * @since 1.1
      */
     protected void setError() {
         trouble = true;
@@ -437,7 +514,7 @@
      * Clears the internal error state of this stream.
      *
      * <p> This method will cause subsequent invocations of {@link
-     * #checkError()} to return <tt>false</tt> until another write
+     * #checkError()} to return {@code false} until another write
      * operation fails and invokes {@link #setError()}.
      *
      * @since 1.6
@@ -453,12 +530,12 @@
 
     /**
      * Writes the specified byte to this stream.  If the byte is a newline and
-     * automatic flushing is enabled then the <code>flush</code> method will be
+     * automatic flushing is enabled then the {@code flush} method will be
      * invoked.
      *
      * <p> Note that the byte is written as given; to write a character that
      * will be translated according to the platform's default character
-     * encoding, use the <code>print(char)</code> or <code>println(char)</code>
+     * encoding, use the {@code print(char)} or {@code println(char)}
      * methods.
      *
      * @param  b  The byte to be written
@@ -483,13 +560,13 @@
     }
 
     /**
-     * Writes <code>len</code> bytes from the specified byte array starting at
-     * offset <code>off</code> to this stream.  If automatic flushing is
-     * enabled then the <code>flush</code> method will be invoked.
+     * Writes {@code len} bytes from the specified byte array starting at
+     * offset {@code off} to this stream.  If automatic flushing is
+     * enabled then the {@code flush} method will be invoked.
      *
      * <p> Note that the bytes will be written as given; to write characters
      * that will be translated according to the platform's default character
-     * encoding, use the <code>print(char)</code> or <code>println(char)</code>
+     * encoding, use the {@code print(char)} or {@code println(char)}
      * methods.
      *
      * @param  buf   A byte array
@@ -588,38 +665,38 @@
     /* Methods that do not terminate lines */
 
     /**
-     * Prints a boolean value.  The string produced by <code>{@link
-     * java.lang.String#valueOf(boolean)}</code> is translated into bytes
+     * Prints a boolean value.  The string produced by {@link
+     * java.lang.String#valueOf(boolean)} is translated into bytes
      * according to the platform's default character encoding, and these bytes
      * are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      b   The <code>boolean</code> to be printed
+     * @param      b   The {@code boolean} to be printed
      */
     public void print(boolean b) {
-        write(b ? "true" : "false");
+        write(String.valueOf(b));
     }
 
     /**
      * Prints a character.  The character is translated into one or more bytes
      * according to the platform's default character encoding, and these bytes
      * are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      c   The <code>char</code> to be printed
+     * @param      c   The {@code char} to be printed
      */
     public void print(char c) {
         write(String.valueOf(c));
     }
 
     /**
-     * Prints an integer.  The string produced by <code>{@link
-     * java.lang.String#valueOf(int)}</code> is translated into bytes
+     * Prints an integer.  The string produced by {@link
+     * java.lang.String#valueOf(int)} is translated into bytes
      * according to the platform's default character encoding, and these bytes
      * are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      i   The <code>int</code> to be printed
+     * @param      i   The {@code int} to be printed
      * @see        java.lang.Integer#toString(int)
      */
     public void print(int i) {
@@ -627,13 +704,13 @@
     }
 
     /**
-     * Prints a long integer.  The string produced by <code>{@link
-     * java.lang.String#valueOf(long)}</code> is translated into bytes
+     * Prints a long integer.  The string produced by {@link
+     * java.lang.String#valueOf(long)} is translated into bytes
      * according to the platform's default character encoding, and these bytes
      * are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      l   The <code>long</code> to be printed
+     * @param      l   The {@code long} to be printed
      * @see        java.lang.Long#toString(long)
      */
     public void print(long l) {
@@ -641,13 +718,13 @@
     }
 
     /**
-     * Prints a floating-point number.  The string produced by <code>{@link
-     * java.lang.String#valueOf(float)}</code> is translated into bytes
+     * Prints a floating-point number.  The string produced by {@link
+     * java.lang.String#valueOf(float)} is translated into bytes
      * according to the platform's default character encoding, and these bytes
      * are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      f   The <code>float</code> to be printed
+     * @param      f   The {@code float} to be printed
      * @see        java.lang.Float#toString(float)
      */
     public void print(float f) {
@@ -656,12 +733,12 @@
 
     /**
      * Prints a double-precision floating-point number.  The string produced by
-     * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
+     * {@link java.lang.String#valueOf(double)} is translated into
      * bytes according to the platform's default character encoding, and these
-     * bytes are written in exactly the manner of the <code>{@link
-     * #write(int)}</code> method.
+     * bytes are written in exactly the manner of the {@link
+     * #write(int)} method.
      *
-     * @param      d   The <code>double</code> to be printed
+     * @param      d   The {@code double} to be printed
      * @see        java.lang.Double#toString(double)
      */
     public void print(double d) {
@@ -672,40 +749,37 @@
      * Prints an array of characters.  The characters are converted into bytes
      * according to the platform's default character encoding, and these bytes
      * are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
      * @param      s   The array of chars to be printed
      *
-     * @throws  NullPointerException  If <code>s</code> is <code>null</code>
+     * @throws  NullPointerException  If {@code s} is {@code null}
      */
     public void print(char s[]) {
         write(s);
     }
 
     /**
-     * Prints a string.  If the argument is <code>null</code> then the string
-     * <code>"null"</code> is printed.  Otherwise, the string's characters are
+     * Prints a string.  If the argument is {@code null} then the string
+     * {@code "null"} is printed.  Otherwise, the string's characters are
      * converted into bytes according to the platform's default character
      * encoding, and these bytes are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      s   The <code>String</code> to be printed
+     * @param      s   The {@code String} to be printed
      */
     public void print(String s) {
-        if (s == null) {
-            s = "null";
-        }
-        write(s);
+        write(String.valueOf(s));
     }
 
     /**
-     * Prints an object.  The string produced by the <code>{@link
-     * java.lang.String#valueOf(Object)}</code> method is translated into bytes
+     * Prints an object.  The string produced by the {@link
+     * java.lang.String#valueOf(Object)} method is translated into bytes
      * according to the platform's default character encoding, and these bytes
      * are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      obj   The <code>Object</code> to be printed
+     * @param      obj   The {@code Object} to be printed
      * @see        java.lang.Object#toString()
      */
     public void print(Object obj) {
@@ -718,8 +792,8 @@
     /**
      * Terminates the current line by writing the line separator string.  The
      * line separator string is defined by the system property
-     * <code>line.separator</code>, and is not necessarily a single newline
-     * character (<code>'\n'</code>).
+     * {@code line.separator}, and is not necessarily a single newline
+     * character ({@code '\n'}).
      */
     public void println() {
         newLine();
@@ -727,10 +801,10 @@
 
     /**
      * Prints a boolean and then terminate the line.  This method behaves as
-     * though it invokes <code>{@link #print(boolean)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(boolean)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>boolean</code> to be printed
+     * @param x  The {@code boolean} to be printed
      */
     public void println(boolean x) {
         synchronized (this) {
@@ -741,10 +815,10 @@
 
     /**
      * Prints a character and then terminate the line.  This method behaves as
-     * though it invokes <code>{@link #print(char)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(char)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>char</code> to be printed.
+     * @param x  The {@code char} to be printed.
      */
     public void println(char x) {
         synchronized (this) {
@@ -755,10 +829,10 @@
 
     /**
      * Prints an integer and then terminate the line.  This method behaves as
-     * though it invokes <code>{@link #print(int)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(int)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>int</code> to be printed.
+     * @param x  The {@code int} to be printed.
      */
     public void println(int x) {
         synchronized (this) {
@@ -769,10 +843,10 @@
 
     /**
      * Prints a long and then terminate the line.  This method behaves as
-     * though it invokes <code>{@link #print(long)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(long)} and then
+     * {@link #println()}.
      *
-     * @param x  a The <code>long</code> to be printed.
+     * @param x  a The {@code long} to be printed.
      */
     public void println(long x) {
         synchronized (this) {
@@ -783,10 +857,10 @@
 
     /**
      * Prints a float and then terminate the line.  This method behaves as
-     * though it invokes <code>{@link #print(float)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(float)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>float</code> to be printed.
+     * @param x  The {@code float} to be printed.
      */
     public void println(float x) {
         synchronized (this) {
@@ -797,10 +871,10 @@
 
     /**
      * Prints a double and then terminate the line.  This method behaves as
-     * though it invokes <code>{@link #print(double)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(double)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>double</code> to be printed.
+     * @param x  The {@code double} to be printed.
      */
     public void println(double x) {
         synchronized (this) {
@@ -811,8 +885,8 @@
 
     /**
      * Prints an array of characters and then terminate the line.  This method
-     * behaves as though it invokes <code>{@link #print(char[])}</code> and
-     * then <code>{@link #println()}</code>.
+     * behaves as though it invokes {@link #print(char[])} and
+     * then {@link #println()}.
      *
      * @param x  an array of chars to print.
      */
@@ -825,10 +899,10 @@
 
     /**
      * Prints a String and then terminate the line.  This method behaves as
-     * though it invokes <code>{@link #print(String)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(String)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>String</code> to be printed.
+     * @param x  The {@code String} to be printed.
      */
     public void println(String x) {
         synchronized (this) {
@@ -841,10 +915,10 @@
      * Prints an Object and then terminate the line.  This method calls
      * at first String.valueOf(x) to get the printed object's string value,
      * then behaves as
-     * though it invokes <code>{@link #print(String)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(String)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>Object</code> to be printed.
+     * @param x  The {@code Object} to be printed.
      */
     public void println(Object x) {
         String s = String.valueOf(x);
@@ -859,11 +933,13 @@
      * A convenience method to write a formatted string to this output stream
      * using the specified format string and arguments.
      *
-     * <p> An invocation of this method of the form <tt>out.printf(format,
-     * args)</tt> behaves in exactly the same way as the invocation
+     * <p> An invocation of this method of the form
+     * {@code out.printf(format, args)} behaves
+     * in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.format(format, args) </pre>
+     * <pre>{@code
+     *     out.format(format, args)
+     * }</pre>
      *
      * @param  format
      *         A format string as described in <a
@@ -877,7 +953,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -890,7 +966,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This output stream
      *
@@ -904,15 +980,17 @@
      * A convenience method to write a formatted string to this output stream
      * using the specified format string and arguments.
      *
-     * <p> An invocation of this method of the form <tt>out.printf(l, format,
-     * args)</tt> behaves in exactly the same way as the invocation
+     * <p> An invocation of this method of the form
+     * {@code out.printf(l, format, args)} behaves
+     * in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.format(l, format, args) </pre>
+     * <pre>{@code
+     *     out.format(l, format, args)
+     * }</pre>
      *
      * @param  l
      *         The {@linkplain java.util.Locale locale} to apply during
-     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
+     *         formatting.  If {@code l} is {@code null} then no localization
      *         is applied.
      *
      * @param  format
@@ -927,7 +1005,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -940,7 +1018,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This output stream
      *
@@ -955,8 +1033,10 @@
      * format string and arguments.
      *
      * <p> The locale always used is the one returned by {@link
-     * java.util.Locale#getDefault() Locale.getDefault()}, regardless of any
-     * previous invocations of other formatting methods on this object.
+     * java.util.Locale#getDefault(Locale.Category)} with
+     * {@link java.util.Locale.Category#FORMAT FORMAT} category specified,
+     * regardless of any previous invocations of other formatting methods on
+     * this object.
      *
      * @param  format
      *         A format string as described in <a
@@ -970,7 +1050,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -983,7 +1063,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This output stream
      *
@@ -994,9 +1074,11 @@
             synchronized (this) {
                 ensureOpen();
                 if ((formatter == null)
-                    || (formatter.locale() != Locale.getDefault()))
+                    || (formatter.locale() !=
+                        Locale.getDefault(Locale.Category.FORMAT)))
                     formatter = new Formatter((Appendable) this);
-                formatter.format(Locale.getDefault(), format, args);
+                formatter.format(Locale.getDefault(Locale.Category.FORMAT),
+                                 format, args);
             }
         } catch (InterruptedIOException x) {
             Thread.currentThread().interrupt();
@@ -1012,7 +1094,7 @@
      *
      * @param  l
      *         The {@linkplain java.util.Locale locale} to apply during
-     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
+     *         formatting.  If {@code l} is {@code null} then no localization
      *         is applied.
      *
      * @param  format
@@ -1027,7 +1109,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -1040,7 +1122,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This output stream
      *
@@ -1066,21 +1148,22 @@
     /**
      * Appends the specified character sequence to this output stream.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
+     * <p> An invocation of this method of the form {@code out.append(csq)}
      * behaves in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.print(csq.toString()) </pre>
+     * <pre>{@code
+     *     out.print(csq.toString())
+     * }</pre>
      *
-     * <p> Depending on the specification of <tt>toString</tt> for the
-     * character sequence <tt>csq</tt>, the entire sequence may not be
-     * appended.  For instance, invoking then <tt>toString</tt> method of a
+     * <p> Depending on the specification of {@code toString} for the
+     * character sequence {@code csq}, the entire sequence may not be
+     * appended.  For instance, invoking then {@code toString} method of a
      * character buffer will return a subsequence whose content depends upon
      * the buffer's position and limit.
      *
      * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         The character sequence to append.  If {@code csq} is
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this output stream.
      *
      * @return  This output stream
@@ -1088,10 +1171,7 @@
      * @since  1.5
      */
     public PrintStream append(CharSequence csq) {
-        if (csq == null)
-            print("null");
-        else
-            print(csq.toString());
+        print(String.valueOf(csq));
         return this;
     }
 
@@ -1099,18 +1179,20 @@
      * Appends a subsequence of the specified character sequence to this output
      * stream.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
+     * <p> An invocation of this method of the form
+     * {@code out.append(csq, start, end)} when
+     * {@code csq} is not {@code null}, behaves in
      * exactly the same way as the invocation
      *
-     * <pre>
-     *     out.print(csq.subSequence(start, end).toString()) </pre>
+     * <pre>{@code
+     *     out.print(csq.subSequence(start, end).toString())
+     * }</pre>
      *
      * @param  csq
      *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
+     *         appended.  If {@code csq} is {@code null}, then characters
+     *         will be appended as if {@code csq} contained the four
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -1122,26 +1204,26 @@
      * @return  This output stream
      *
      * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
+     *          If {@code start} or {@code end} are negative, {@code start}
+     *          is greater than {@code end}, or {@code end} is greater than
+     *          {@code csq.length()}
      *
      * @since  1.5
      */
     public PrintStream append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
      * Appends the specified character to this output stream.
      *
-     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
+     * <p> An invocation of this method of the form {@code out.append(c)}
      * behaves in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.print(c) </pre>
+     * <pre>{@code
+     *     out.print(c)
+     * }</pre>
      *
      * @param  c
      *         The 16-bit character to append
diff --git a/ojluni/src/main/java/java/io/PrintWriter.java b/ojluni/src/main/java/java/io/PrintWriter.java
index 9287a19..37d4200 100644
--- a/ojluni/src/main/java/java/io/PrintWriter.java
+++ b/ojluni/src/main/java/java/io/PrintWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,13 +34,13 @@
 
 /**
  * Prints formatted representations of objects to a text-output stream.  This
- * class implements all of the <tt>print</tt> methods found in {@link
+ * class implements all of the {@code print} methods found in {@link
  * PrintStream}.  It does not contain methods for writing raw bytes, for which
  * a program should use unencoded byte streams.
  *
  * <p> Unlike the {@link PrintStream} class, if automatic flushing is enabled
- * it will be done only when one of the <tt>println</tt>, <tt>printf</tt>, or
- * <tt>format</tt> methods is invoked, rather than whenever a newline character
+ * it will be done only when one of the {@code println}, {@code printf}, or
+ * {@code format} methods is invoked, rather than whenever a newline character
  * happens to be output.  These methods use the platform's own notion of line
  * separator rather than the newline character.
  *
@@ -48,16 +48,21 @@
  * constructors may.  The client may inquire as to whether any errors have
  * occurred by invoking {@link #checkError checkError()}.
  *
+ * <p> This class always replaces malformed and unmappable character sequences with
+ * the charset's default replacement string.
+ * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more
+ * control over the encoding process is required.
+ *
  * @author      Frank Yellin
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class PrintWriter extends Writer {
 
     /**
      * The underlying character-output stream of this
-     * <code>PrintWriter</code>.
+     * {@code PrintWriter}.
      *
      * @since 1.2
      */
@@ -69,12 +74,6 @@
     private PrintStream psOut = null;
 
     /**
-     * Line separator string.  This is the value of the line.separator
-     * property at the moment that the stream was created.
-     */
-    private final String lineSeparator;
-
-    /**
      * Returns a charset object for the given charset name.
      * @throws NullPointerException          is csn is null
      * @throws UnsupportedEncodingException  if the charset is not supported
@@ -113,8 +112,6 @@
         super(out);
         this.out = out;
         this.autoFlush = autoFlush;
-        lineSeparator = java.security.AccessController.doPrivileged(
-            new sun.security.action.GetPropertyAction("line.separator"));
     }
 
     /**
@@ -138,14 +135,33 @@
      * default character encoding.
      *
      * @param  out        An output stream
-     * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
-     *                    <tt>printf</tt>, or <tt>format</tt> methods will
+     * @param  autoFlush  A boolean; if true, the {@code println},
+     *                    {@code printf}, or {@code format} methods will
      *                    flush the output buffer
      *
      * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
      */
     public PrintWriter(OutputStream out, boolean autoFlush) {
-        this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);
+        this(out, autoFlush, Charset.defaultCharset());
+    }
+
+    /**
+     * Creates a new PrintWriter from an existing OutputStream.  This
+     * convenience constructor creates the necessary intermediate
+     * OutputStreamWriter, which will convert characters into bytes using the
+     * specified charset.
+     *
+     * @param  out        An output stream
+     * @param  autoFlush  A boolean; if true, the {@code println},
+     *                    {@code printf}, or {@code format} methods will
+     *                    flush the output buffer
+     * @param  charset
+     *         A {@linkplain java.nio.charset.Charset charset}
+     *
+     * @since 10
+     */
+    public PrintWriter(OutputStream out, boolean autoFlush, Charset charset) {
+        this(new BufferedWriter(new OutputStreamWriter(out, charset)), autoFlush);
 
         // save print stream for error propagation
         if (out instanceof java.io.PrintStream) {
@@ -234,6 +250,36 @@
 
     /**
      * Creates a new PrintWriter, without automatic line flushing, with the
+     * specified file name and charset.  This convenience constructor creates
+     * the necessary intermediate {@link java.io.OutputStreamWriter
+     * OutputStreamWriter}, which will encode characters using the provided
+     * charset.
+     *
+     * @param  fileName
+     *         The name of the file to use as the destination of this writer.
+     *         If the file exists then it will be truncated to zero size;
+     *         otherwise, a new file will be created.  The output will be
+     *         written to the file and is buffered.
+     *
+     * @param  charset
+     *         A {@linkplain java.nio.charset.Charset charset}
+     *
+     * @throws  IOException
+     *          if an I/O error occurs while opening or creating the file
+     *
+     * @throws  SecurityException
+     *          If a security manager is present and {@link
+     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
+     *          access to the file
+     *
+     * @since  10
+     */
+    public PrintWriter(String fileName, Charset charset) throws IOException {
+        this(Objects.requireNonNull(charset, "charset"), new File(fileName));
+    }
+
+    /**
+     * Creates a new PrintWriter, without automatic line flushing, with the
      * specified file.  This convenience constructor creates the necessary
      * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
      * which will encode characters using the {@linkplain
@@ -303,6 +349,36 @@
         this(toCharset(csn), file);
     }
 
+    /**
+     * Creates a new PrintWriter, without automatic line flushing, with the
+     * specified file and charset.  This convenience constructor creates the
+     * necessary intermediate {@link java.io.OutputStreamWriter
+     * OutputStreamWriter}, which will encode characters using the provided
+     * charset.
+     *
+     * @param  file
+     *         The file to use as the destination of this writer.  If the file
+     *         exists then it will be truncated to zero size; otherwise, a new
+     *         file will be created.  The output will be written to the file
+     *         and is buffered.
+     *
+     * @param  charset
+     *         A {@linkplain java.nio.charset.Charset charset}
+     *
+     * @throws  IOException
+     *          if an I/O error occurs while opening or creating the file
+     *
+     * @throws  SecurityException
+     *          If a security manager is present and {@link
+     *          SecurityManager#checkWrite checkWrite(file.getPath())}
+     *          denies write access to the file
+     *
+     * @since  10
+     */
+    public PrintWriter(File file, Charset charset) throws IOException {
+        this(Objects.requireNonNull(charset, "charset"), file);
+    }
+
     /** Checks to make sure that the stream has not been closed */
     private void ensureOpen() throws IOException {
         if (out == null)
@@ -348,7 +424,7 @@
     /**
      * Flushes the stream if it's not closed and checks its error state.
      *
-     * @return <code>true</code> if the print stream has encountered an error,
+     * @return {@code true} if the print stream has encountered an error,
      *          either on the underlying output stream or during a format
      *          conversion.
      */
@@ -369,7 +445,7 @@
      * Indicates that an error has occurred.
      *
      * <p> This method will cause subsequent invocations of {@link
-     * #checkError()} to return <tt>true</tt> until {@link
+     * #checkError()} to return {@code true} until {@link
      * #clearError()} is invoked.
      */
     protected void setError() {
@@ -380,7 +456,7 @@
      * Clears the error state of this stream.
      *
      * <p> This method will cause subsequent invocations of {@link
-     * #checkError()} to return <tt>false</tt> until another write
+     * #checkError()} to return {@code false} until another write
      * operation fails and invokes {@link #setError()}.
      *
      * @since 1.6
@@ -418,6 +494,11 @@
      * @param buf Array of characters
      * @param off Offset from which to start writing characters
      * @param len Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
      */
     public void write(char buf[], int off, int len) {
         try {
@@ -448,6 +529,11 @@
      * @param s A String
      * @param off Offset from which to start writing characters
      * @param len Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the values of the {@code off} and {@code len} parameters
+     *          cause the corresponding method of the underlying {@code Writer}
+     *          to throw an {@code IndexOutOfBoundsException}
      */
     public void write(String s, int off, int len) {
         try {
@@ -477,7 +563,7 @@
         try {
             synchronized (lock) {
                 ensureOpen();
-                out.write(lineSeparator);
+                out.write(System.lineSeparator());
                 if (autoFlush)
                     out.flush();
             }
@@ -493,38 +579,38 @@
     /* Methods that do not terminate lines */
 
     /**
-     * Prints a boolean value.  The string produced by <code>{@link
-     * java.lang.String#valueOf(boolean)}</code> is translated into bytes
+     * Prints a boolean value.  The string produced by {@link
+     * java.lang.String#valueOf(boolean)} is translated into bytes
      * according to the platform's default character encoding, and these bytes
-     * are written in exactly the manner of the <code>{@link
-     * #write(int)}</code> method.
+     * are written in exactly the manner of the {@link
+     * #write(int)} method.
      *
-     * @param      b   The <code>boolean</code> to be printed
+     * @param      b   The {@code boolean} to be printed
      */
     public void print(boolean b) {
-        write(b ? "true" : "false");
+        write(String.valueOf(b));
     }
 
     /**
      * Prints a character.  The character is translated into one or more bytes
      * according to the platform's default character encoding, and these bytes
-     * are written in exactly the manner of the <code>{@link
-     * #write(int)}</code> method.
+     * are written in exactly the manner of the {@link
+     * #write(int)} method.
      *
-     * @param      c   The <code>char</code> to be printed
+     * @param      c   The {@code char} to be printed
      */
     public void print(char c) {
         write(c);
     }
 
     /**
-     * Prints an integer.  The string produced by <code>{@link
-     * java.lang.String#valueOf(int)}</code> is translated into bytes according
+     * Prints an integer.  The string produced by {@link
+     * java.lang.String#valueOf(int)} is translated into bytes according
      * to the platform's default character encoding, and these bytes are
-     * written in exactly the manner of the <code>{@link #write(int)}</code>
+     * written in exactly the manner of the {@link #write(int)}
      * method.
      *
-     * @param      i   The <code>int</code> to be printed
+     * @param      i   The {@code int} to be printed
      * @see        java.lang.Integer#toString(int)
      */
     public void print(int i) {
@@ -532,13 +618,13 @@
     }
 
     /**
-     * Prints a long integer.  The string produced by <code>{@link
-     * java.lang.String#valueOf(long)}</code> is translated into bytes
+     * Prints a long integer.  The string produced by {@link
+     * java.lang.String#valueOf(long)} is translated into bytes
      * according to the platform's default character encoding, and these bytes
-     * are written in exactly the manner of the <code>{@link #write(int)}</code>
+     * are written in exactly the manner of the {@link #write(int)}
      * method.
      *
-     * @param      l   The <code>long</code> to be printed
+     * @param      l   The {@code long} to be printed
      * @see        java.lang.Long#toString(long)
      */
     public void print(long l) {
@@ -546,13 +632,13 @@
     }
 
     /**
-     * Prints a floating-point number.  The string produced by <code>{@link
-     * java.lang.String#valueOf(float)}</code> is translated into bytes
+     * Prints a floating-point number.  The string produced by {@link
+     * java.lang.String#valueOf(float)} is translated into bytes
      * according to the platform's default character encoding, and these bytes
-     * are written in exactly the manner of the <code>{@link #write(int)}</code>
+     * are written in exactly the manner of the {@link #write(int)}
      * method.
      *
-     * @param      f   The <code>float</code> to be printed
+     * @param      f   The {@code float} to be printed
      * @see        java.lang.Float#toString(float)
      */
     public void print(float f) {
@@ -561,12 +647,12 @@
 
     /**
      * Prints a double-precision floating-point number.  The string produced by
-     * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
+     * {@link java.lang.String#valueOf(double)} is translated into
      * bytes according to the platform's default character encoding, and these
-     * bytes are written in exactly the manner of the <code>{@link
-     * #write(int)}</code> method.
+     * bytes are written in exactly the manner of the {@link
+     * #write(int)} method.
      *
-     * @param      d   The <code>double</code> to be printed
+     * @param      d   The {@code double} to be printed
      * @see        java.lang.Double#toString(double)
      */
     public void print(double d) {
@@ -576,41 +662,38 @@
     /**
      * Prints an array of characters.  The characters are converted into bytes
      * according to the platform's default character encoding, and these bytes
-     * are written in exactly the manner of the <code>{@link #write(int)}</code>
+     * are written in exactly the manner of the {@link #write(int)}
      * method.
      *
      * @param      s   The array of chars to be printed
      *
-     * @throws  NullPointerException  If <code>s</code> is <code>null</code>
+     * @throws  NullPointerException  If {@code s} is {@code null}
      */
     public void print(char s[]) {
         write(s);
     }
 
     /**
-     * Prints a string.  If the argument is <code>null</code> then the string
-     * <code>"null"</code> is printed.  Otherwise, the string's characters are
+     * Prints a string.  If the argument is {@code null} then the string
+     * {@code "null"} is printed.  Otherwise, the string's characters are
      * converted into bytes according to the platform's default character
      * encoding, and these bytes are written in exactly the manner of the
-     * <code>{@link #write(int)}</code> method.
+     * {@link #write(int)} method.
      *
-     * @param      s   The <code>String</code> to be printed
+     * @param      s   The {@code String} to be printed
      */
     public void print(String s) {
-        if (s == null) {
-            s = "null";
-        }
-        write(s);
+        write(String.valueOf(s));
     }
 
     /**
-     * Prints an object.  The string produced by the <code>{@link
-     * java.lang.String#valueOf(Object)}</code> method is translated into bytes
+     * Prints an object.  The string produced by the {@link
+     * java.lang.String#valueOf(Object)} method is translated into bytes
      * according to the platform's default character encoding, and these bytes
-     * are written in exactly the manner of the <code>{@link #write(int)}</code>
+     * are written in exactly the manner of the {@link #write(int)}
      * method.
      *
-     * @param      obj   The <code>Object</code> to be printed
+     * @param      obj   The {@code Object} to be printed
      * @see        java.lang.Object#toString()
      */
     public void print(Object obj) {
@@ -622,8 +705,8 @@
     /**
      * Terminates the current line by writing the line separator string.  The
      * line separator string is defined by the system property
-     * <code>line.separator</code>, and is not necessarily a single newline
-     * character (<code>'\n'</code>).
+     * {@code line.separator}, and is not necessarily a single newline
+     * character ({@code '\n'}).
      */
     public void println() {
         newLine();
@@ -631,10 +714,10 @@
 
     /**
      * Prints a boolean value and then terminates the line.  This method behaves
-     * as though it invokes <code>{@link #print(boolean)}</code> and then
-     * <code>{@link #println()}</code>.
+     * as though it invokes {@link #print(boolean)} and then
+     * {@link #println()}.
      *
-     * @param x the <code>boolean</code> value to be printed
+     * @param x the {@code boolean} value to be printed
      */
     public void println(boolean x) {
         synchronized (lock) {
@@ -645,10 +728,10 @@
 
     /**
      * Prints a character and then terminates the line.  This method behaves as
-     * though it invokes <code>{@link #print(char)}</code> and then <code>{@link
-     * #println()}</code>.
+     * though it invokes {@link #print(char)} and then {@link
+     * #println()}.
      *
-     * @param x the <code>char</code> value to be printed
+     * @param x the {@code char} value to be printed
      */
     public void println(char x) {
         synchronized (lock) {
@@ -659,10 +742,10 @@
 
     /**
      * Prints an integer and then terminates the line.  This method behaves as
-     * though it invokes <code>{@link #print(int)}</code> and then <code>{@link
-     * #println()}</code>.
+     * though it invokes {@link #print(int)} and then {@link
+     * #println()}.
      *
-     * @param x the <code>int</code> value to be printed
+     * @param x the {@code int} value to be printed
      */
     public void println(int x) {
         synchronized (lock) {
@@ -673,10 +756,10 @@
 
     /**
      * Prints a long integer and then terminates the line.  This method behaves
-     * as though it invokes <code>{@link #print(long)}</code> and then
-     * <code>{@link #println()}</code>.
+     * as though it invokes {@link #print(long)} and then
+     * {@link #println()}.
      *
-     * @param x the <code>long</code> value to be printed
+     * @param x the {@code long} value to be printed
      */
     public void println(long x) {
         synchronized (lock) {
@@ -687,10 +770,10 @@
 
     /**
      * Prints a floating-point number and then terminates the line.  This method
-     * behaves as though it invokes <code>{@link #print(float)}</code> and then
-     * <code>{@link #println()}</code>.
+     * behaves as though it invokes {@link #print(float)} and then
+     * {@link #println()}.
      *
-     * @param x the <code>float</code> value to be printed
+     * @param x the {@code float} value to be printed
      */
     public void println(float x) {
         synchronized (lock) {
@@ -701,10 +784,10 @@
 
     /**
      * Prints a double-precision floating-point number and then terminates the
-     * line.  This method behaves as though it invokes <code>{@link
-     * #print(double)}</code> and then <code>{@link #println()}</code>.
+     * line.  This method behaves as though it invokes {@link
+     * #print(double)} and then {@link #println()}.
      *
-     * @param x the <code>double</code> value to be printed
+     * @param x the {@code double} value to be printed
      */
     public void println(double x) {
         synchronized (lock) {
@@ -715,10 +798,10 @@
 
     /**
      * Prints an array of characters and then terminates the line.  This method
-     * behaves as though it invokes <code>{@link #print(char[])}</code> and then
-     * <code>{@link #println()}</code>.
+     * behaves as though it invokes {@link #print(char[])} and then
+     * {@link #println()}.
      *
-     * @param x the array of <code>char</code> values to be printed
+     * @param x the array of {@code char} values to be printed
      */
     public void println(char x[]) {
         synchronized (lock) {
@@ -729,10 +812,10 @@
 
     /**
      * Prints a String and then terminates the line.  This method behaves as
-     * though it invokes <code>{@link #print(String)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(String)} and then
+     * {@link #println()}.
      *
-     * @param x the <code>String</code> value to be printed
+     * @param x the {@code String} value to be printed
      */
     public void println(String x) {
         synchronized (lock) {
@@ -745,10 +828,10 @@
      * Prints an Object and then terminates the line.  This method calls
      * at first String.valueOf(x) to get the printed object's string value,
      * then behaves as
-     * though it invokes <code>{@link #print(String)}</code> and then
-     * <code>{@link #println()}</code>.
+     * though it invokes {@link #print(String)} and then
+     * {@link #println()}.
      *
-     * @param x  The <code>Object</code> to be printed.
+     * @param x  The {@code Object} to be printed.
      */
     public void println(Object x) {
         String s = String.valueOf(x);
@@ -763,11 +846,13 @@
      * the specified format string and arguments.  If automatic flushing is
      * enabled, calls to this method will flush the output buffer.
      *
-     * <p> An invocation of this method of the form <tt>out.printf(format,
-     * args)</tt> behaves in exactly the same way as the invocation
+     * <p> An invocation of this method of the form
+     * {@code out.printf(format, args)}
+     * behaves in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.format(format, args) </pre>
+     * <pre>{@code
+     *     out.format(format, args)
+     * }</pre>
      *
      * @param  format
      *         A format string as described in <a
@@ -781,7 +866,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -794,7 +879,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This writer
      *
@@ -809,15 +894,17 @@
      * the specified format string and arguments.  If automatic flushing is
      * enabled, calls to this method will flush the output buffer.
      *
-     * <p> An invocation of this method of the form <tt>out.printf(l, format,
-     * args)</tt> behaves in exactly the same way as the invocation
+     * <p> An invocation of this method of the form
+     * {@code out.printf(l, format, args)}
+     * behaves in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.format(l, format, args) </pre>
+     * <pre>{@code
+     *     out.format(l, format, args)
+     * }</pre>
      *
      * @param  l
      *         The {@linkplain java.util.Locale locale} to apply during
-     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
+     *         formatting.  If {@code l} is {@code null} then no localization
      *         is applied.
      *
      * @param  format
@@ -832,7 +919,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -845,7 +932,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This writer
      *
@@ -876,7 +963,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -889,7 +976,7 @@
      *          Formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This writer
      *
@@ -921,7 +1008,7 @@
      *
      * @param  l
      *         The {@linkplain java.util.Locale locale} to apply during
-     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
+     *         formatting.  If {@code l} is {@code null} then no localization
      *         is applied.
      *
      * @param  format
@@ -936,7 +1023,7 @@
      *         limited by the maximum dimension of a Java array as defined by
      *         <cite>The Java&trade; Virtual Machine Specification</cite>.
      *         The behaviour on a
-     *         <tt>null</tt> argument depends on the <a
+     *         {@code null} argument depends on the <a
      *         href="../util/Formatter.html#syntax">conversion</a>.
      *
      * @throws  java.util.IllegalFormatException
@@ -949,7 +1036,7 @@
      *          formatter class specification.
      *
      * @throws  NullPointerException
-     *          If the <tt>format</tt> is <tt>null</tt>
+     *          If the {@code format} is {@code null}
      *
      * @return  This writer
      *
@@ -976,21 +1063,22 @@
     /**
      * Appends the specified character sequence to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
+     * <p> An invocation of this method of the form {@code out.append(csq)}
      * behaves in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.write(csq.toString()) </pre>
+     * <pre>{@code
+     *     out.write(csq.toString())
+     * }</pre>
      *
-     * <p> Depending on the specification of <tt>toString</tt> for the
-     * character sequence <tt>csq</tt>, the entire sequence may not be
-     * appended. For instance, invoking the <tt>toString</tt> method of a
+     * <p> Depending on the specification of {@code toString} for the
+     * character sequence {@code csq}, the entire sequence may not be
+     * appended. For instance, invoking the {@code toString} method of a
      * character buffer will return a subsequence whose content depends upon
      * the buffer's position and limit.
      *
      * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         The character sequence to append.  If {@code csq} is
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this writer.
      *
      * @return  This writer
@@ -998,28 +1086,27 @@
      * @since  1.5
      */
     public PrintWriter append(CharSequence csq) {
-        if (csq == null)
-            write("null");
-        else
-            write(csq.toString());
+        write(String.valueOf(csq));
         return this;
     }
 
     /**
      * Appends a subsequence of the specified character sequence to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
+     * <p> An invocation of this method of the form
+     * {@code out.append(csq, start, end)}
+     * when {@code csq} is not {@code null}, behaves in
      * exactly the same way as the invocation
      *
-     * <pre>
-     *     out.write(csq.subSequence(start, end).toString()) </pre>
+     * <pre>{@code
+     *     out.write(csq.subSequence(start, end).toString())
+     * }</pre>
      *
      * @param  csq
      *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
+     *         appended.  If {@code csq} is {@code null}, then characters
+     *         will be appended as if {@code csq} contained the four
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -1031,26 +1118,26 @@
      * @return  This writer
      *
      * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
+     *          If {@code start} or {@code end} are negative, {@code start}
+     *          is greater than {@code end}, or {@code end} is greater than
+     *          {@code csq.length()}
      *
      * @since  1.5
      */
     public PrintWriter append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
      * Appends the specified character to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
+     * <p> An invocation of this method of the form {@code out.append(c)}
      * behaves in exactly the same way as the invocation
      *
-     * <pre>
-     *     out.write(c) </pre>
+     * <pre>{@code
+     *     out.write(c)
+     * }</pre>
      *
      * @param  c
      *         The 16-bit character to append
diff --git a/ojluni/src/main/java/java/io/PushbackInputStream.java b/ojluni/src/main/java/java/io/PushbackInputStream.java
index b44848d..d9905c8 100644
--- a/ojluni/src/main/java/java/io/PushbackInputStream.java
+++ b/ojluni/src/main/java/java/io/PushbackInputStream.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,9 +28,10 @@
 /**
  * A <code>PushbackInputStream</code> adds
  * functionality to another input stream, namely
- * the  ability to "push back" or "unread"
- * one byte. This is useful in situations where
- * it is  convenient for a fragment of code
+ * the  ability to "push back" or "unread" bytes,
+ * by storing pushed-back bytes in an internal buffer.
+ * This is useful in situations where
+ * it is convenient for a fragment of code
  * to read an indefinite number of data bytes
  * that  are delimited by a particular byte
  * value; after reading the terminating byte,
@@ -46,13 +47,13 @@
  *
  * @author  David Connelly
  * @author  Jonathan Payne
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class PushbackInputStream extends FilterInputStream {
     /**
      * The pushback buffer.
-     * @since   JDK1.1
+     * @since   1.1
      */
     protected byte[] buf;
 
@@ -62,7 +63,7 @@
      * <code>buf.length</code>; when the buffer is full, <code>pos</code> is
      * equal to zero.
      *
-     * @since   JDK1.1
+     * @since   1.1
      */
     protected int pos;
 
@@ -77,16 +78,14 @@
     /**
      * Creates a <code>PushbackInputStream</code>
      * with a pushback buffer of the specified <code>size</code>,
-     * and saves its  argument, the input stream
+     * and saves its argument, the input stream
      * <code>in</code>, for later use. Initially,
-     * there is no pushed-back byte  (the field
-     * <code>pushBack</code> is initialized to
-     * <code>-1</code>).
+     * the pushback buffer is empty.
      *
      * @param  in    the input stream from which bytes will be read.
      * @param  size  the size of the pushback buffer.
      * @exception IllegalArgumentException if {@code size <= 0}
-     * @since  JDK1.1
+     * @since  1.1
      */
     public PushbackInputStream(InputStream in, int size) {
         super(in);
@@ -99,11 +98,9 @@
 
     /**
      * Creates a <code>PushbackInputStream</code>
-     * and saves its  argument, the input stream
+     * with a 1-byte pushback buffer, and saves its argument, the input stream
      * <code>in</code>, for later use. Initially,
-     * there is no pushed-back byte  (the field
-     * <code>pushBack</code> is initialized to
-     * <code>-1</code>).
+     * the pushback buffer is empty.
      *
      * @param   in   the input stream from which bytes will be read.
      */
@@ -224,7 +221,7 @@
      *            buffer for the specified number of bytes,
      *            or this input stream has been closed by
      *            invoking its {@link #close()} method.
-     * @since     JDK1.1
+     * @since     1.1
      */
     public void unread(byte[] b, int off, int len) throws IOException {
         ensureOpen();
@@ -246,7 +243,7 @@
      *            buffer for the specified number of bytes,
      *            or this input stream has been closed by
      *            invoking its {@link #close()} method.
-     * @since     JDK1.1
+     * @since     1.1
      */
     public void unread(byte[] b) throws IOException {
         unread(b, 0, b.length);
@@ -294,10 +291,10 @@
      *
      * @param      n  {@inheritDoc}
      * @return     {@inheritDoc}
-     * @exception  IOException  if the stream does not support seek,
-     *            or the stream has been closed by
-     *            invoking its {@link #close()} method,
-     *            or an I/O error occurs.
+     * @throws     IOException  if the stream has been closed by
+     *             invoking its {@link #close()} method,
+     *             {@code in.skip(n)} throws an IOException,
+     *             or an I/O error occurs.
      * @see        java.io.FilterInputStream#in
      * @see        java.io.InputStream#skip(long n)
      * @since      1.2
diff --git a/ojluni/src/main/java/java/io/PushbackReader.java b/ojluni/src/main/java/java/io/PushbackReader.java
index f918621..85b1854 100644
--- a/ojluni/src/main/java/java/io/PushbackReader.java
+++ b/ojluni/src/main/java/java/io/PushbackReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
  * stream.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class PushbackReader extends FilterReader {
@@ -102,6 +102,7 @@
      *             stream has been reached
      *
      * @exception  IOException  If an I/O error occurs
+     * @exception  IndexOutOfBoundsException {@inheritDoc}
      */
     public int read(char cbuf[], int off, int len) throws IOException {
         synchronized (lock) {
@@ -240,13 +241,16 @@
      * Closes the stream and releases any system resources associated with
      * it. Once the stream has been closed, further read(),
      * unread(), ready(), or skip() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      *
      * @exception  IOException  If an I/O error occurs
      */
     public void close() throws IOException {
-        super.close();
-        buf = null;
+        synchronized (lock) {
+            super.close();
+            buf = null;
+        }
     }
 
     /**
diff --git a/ojluni/src/main/java/java/io/Reader.java b/ojluni/src/main/java/java/io/Reader.java
index 1c9cca6..fd3a87f 100644
--- a/ojluni/src/main/java/java/io/Reader.java
+++ b/ojluni/src/main/java/java/io/Reader.java
@@ -26,6 +26,9 @@
 package java.io;
 
 
+import java.nio.CharBuffer;
+import java.util.Objects;
+
 /**
  * Abstract class for reading character streams.  The only methods that a
  * subclass must implement are read(char[], int, int) and close().  Most
@@ -45,16 +48,102 @@
  * @see Writer
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public abstract class Reader implements Readable, Closeable {
 
+    private static final int TRANSFER_BUFFER_SIZE = 8192;
+
+    /**
+     * Returns a new {@code Reader} that reads no characters. The returned
+     * stream is initially open.  The stream is closed by calling the
+     * {@code close()} method.  Subsequent calls to {@code close()} have no
+     * effect.
+     *
+     * <p> While the stream is open, the {@code read()}, {@code read(char[])},
+     * {@code read(char[], int, int)}, {@code read(Charbuffer)}, {@code
+     * ready()}, {@code skip(long)}, and {@code transferTo()} methods all
+     * behave as if end of stream has been reached. After the stream has been
+     * closed, these methods all throw {@code IOException}.
+     *
+     * <p> The {@code markSupported()} method returns {@code false}.  The
+     * {@code mark()} and {@code reset()} methods throw an {@code IOException}.
+     *
+     * <p> The {@link #lock object} used to synchronize operations on the
+     * returned {@code Reader} is not specified.
+     *
+     * @return a {@code Reader} which reads no characters
+     *
+     * @since 11
+     */
+    public static Reader nullReader() {
+        return new Reader() {
+            private volatile boolean closed;
+
+            private void ensureOpen() throws IOException {
+                if (closed) {
+                    throw new IOException("Stream closed");
+                }
+            }
+
+            @Override
+            public int read() throws IOException {
+                ensureOpen();
+                return -1;
+            }
+
+            @Override
+            public int read(char[] cbuf, int off, int len) throws IOException {
+                Objects.checkFromIndexSize(off, len, cbuf.length);
+                ensureOpen();
+                if (len == 0) {
+                    return 0;
+                }
+                return -1;
+            }
+
+            @Override
+            public int read(CharBuffer target) throws IOException {
+                Objects.requireNonNull(target);
+                ensureOpen();
+                if (target.hasRemaining()) {
+                    return -1;
+                }
+                return 0;
+            }
+
+            @Override
+            public boolean ready() throws IOException {
+                ensureOpen();
+                return false;
+            }
+
+            @Override
+            public long skip(long n) throws IOException {
+                ensureOpen();
+                return 0L;
+            }
+
+            @Override
+            public long transferTo(Writer out) throws IOException {
+                Objects.requireNonNull(out);
+                ensureOpen();
+                return 0L;
+            }
+
+            @Override
+            public void close() {
+                closed = true;
+            }
+        };
+    }
+
     /**
      * The object used to synchronize operations on this stream.  For
      * efficiency, a character-stream object may use an object other than
      * itself to protect critical sections.  A subclass should therefore use
-     * the object in this field rather than <tt>this</tt> or a synchronized
+     * the object in this field rather than {@code this} or a synchronized
      * method.
      */
     protected Object lock;
@@ -111,7 +200,7 @@
      * should override this method.
      *
      * @return     The character read, as an integer in the range 0 to 65535
-     *             (<tt>0x00-0xffff</tt>), or -1 if the end of the stream has
+     *             ({@code 0x00-0xffff}), or -1 if the end of the stream has
      *             been reached
      *
      * @exception  IOException  If an I/O error occurs
@@ -153,8 +242,11 @@
      *             stream has been reached
      *
      * @exception  IOException  If an I/O error occurs
+     * @exception  IndexOutOfBoundsException
+     *             If {@code off} is negative, or {@code len} is negative,
+     *             or {@code len} is greater than {@code cbuf.length - off}
      */
-    abstract public int read(char cbuf[], int off, int len) throws IOException;
+    public abstract int read(char cbuf[], int off, int len) throws IOException;
 
     /** Maximum skip-buffer size */
     private static final int maxSkipBufferSize = 8192;
@@ -257,6 +349,43 @@
      *
      * @exception  IOException  If an I/O error occurs
      */
-     abstract public void close() throws IOException;
+     public abstract void close() throws IOException;
+
+    /**
+     * Reads all characters from this reader and writes the characters to the
+     * given writer in the order that they are read. On return, this reader
+     * will be at end of the stream. This method does not close either reader
+     * or writer.
+     * <p>
+     * This method may block indefinitely reading from the reader, or
+     * writing to the writer. The behavior for the case where the reader
+     * and/or writer is <i>asynchronously closed</i>, or the thread
+     * interrupted during the transfer, is highly reader and writer
+     * specific, and therefore not specified.
+     * <p>
+     * If an I/O error occurs reading from the reader or writing to the
+     * writer, then it may do so after some characters have been read or
+     * written. Consequently the reader may not be at end of the stream and
+     * one, or both, streams may be in an inconsistent state. It is strongly
+     * recommended that both streams be promptly closed if an I/O error occurs.
+     *
+     * @param  out the writer, non-null
+     * @return the number of characters transferred
+     * @throws IOException if an I/O error occurs when reading or writing
+     * @throws NullPointerException if {@code out} is {@code null}
+     *
+     * @since 10
+     */
+    public long transferTo(Writer out) throws IOException {
+        Objects.requireNonNull(out, "out");
+        long transferred = 0;
+        char[] buffer = new char[TRANSFER_BUFFER_SIZE];
+        int nRead;
+        while ((nRead = read(buffer, 0, TRANSFER_BUFFER_SIZE)) >= 0) {
+            out.write(buffer, 0, nRead);
+            transferred += nRead;
+        }
+        return transferred;
+    }
 
 }
diff --git a/ojluni/src/main/java/java/io/Serializable.java b/ojluni/src/main/java/java/io/Serializable.java
index 496aef7..eb245cc 100644
--- a/ojluni/src/main/java/java/io/Serializable.java
+++ b/ojluni/src/main/java/java/io/Serializable.java
@@ -26,9 +26,16 @@
 package java.io;
 
 // Android-added: Notes about serialVersionUID, using serialization judiciously, JSON.
+// Android-removed: External links to serialization guidelinenes.
 /**
  * Serializability of a class is enabled by the class implementing the
- * java.io.Serializable interface. Classes that do not implement this
+ * java.io.Serializable interface.
+ *
+ * <p><strong>Warning: Deserialization of untrusted data is inherently dangerous
+ * and should be avoided. Untrusted data should be carefully validated.
+ * </strong></p>
+ *
+ * Classes that do not implement this
  * interface will not have any of their state serialized or
  * deserialized.  All subtypes of a serializable class are themselves
  * serializable.  The serialization interface has no methods or fields
@@ -85,9 +92,9 @@
  * correspondingly named fields in the current object.  This handles the case
  * when the class has evolved to add new fields. The method does not need to
  * concern itself with the state belonging to its superclasses or subclasses.
- * State is saved by writing the individual fields to the
- * ObjectOutputStream using the writeObject method or by using the
- * methods for primitive data types supported by DataOutput.
+ * State is restored by reading data from the ObjectInputStream for
+ * the individual fields and making assignments to the appropriate fields
+ * of the object. Reading primitive data types is supported by DataInput.
  *
  * <p>The readObjectNoData method is responsible for initializing the state of
  * the object for its particular class in the event that the serialization
@@ -183,7 +190,7 @@
  * @see java.io.ObjectOutput
  * @see java.io.ObjectInput
  * @see java.io.Externalizable
- * @since   JDK1.1
+ * @since   1.1
  */
 public interface Serializable {
 }
diff --git a/ojluni/src/main/java/java/io/StreamCorruptedException.java b/ojluni/src/main/java/java/io/StreamCorruptedException.java
index 57af82c..22e2216 100644
--- a/ojluni/src/main/java/java/io/StreamCorruptedException.java
+++ b/ojluni/src/main/java/java/io/StreamCorruptedException.java
@@ -30,7 +30,7 @@
  * violates internal consistency checks.
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class StreamCorruptedException extends ObjectStreamException {
 
diff --git a/ojluni/src/main/java/java/io/StreamTokenizer.java b/ojluni/src/main/java/java/io/StreamTokenizer.java
index 3c7c7cc..9de1405 100644
--- a/ojluni/src/main/java/java/io/StreamTokenizer.java
+++ b/ojluni/src/main/java/java/io/StreamTokenizer.java
@@ -59,7 +59,7 @@
  * @author  James Gosling
  * @see     java.io.StreamTokenizer#nextToken()
  * @see     java.io.StreamTokenizer#TT_EOF
- * @since   JDK1.0
+ * @since   1.0
  */
 
 public class StreamTokenizer {
@@ -240,7 +240,7 @@
      * Create a tokenizer that parses the given character stream.
      *
      * @param r  a Reader object providing the input stream.
-     * @since   JDK1.1
+     * @since   1.1
      */
     public StreamTokenizer(Reader r) {
         this();
diff --git a/ojluni/src/main/java/java/io/StringBufferInputStream.java b/ojluni/src/main/java/java/io/StringBufferInputStream.java
index 90c5d4d..f54b725 100644
--- a/ojluni/src/main/java/java/io/StringBufferInputStream.java
+++ b/ojluni/src/main/java/java/io/StringBufferInputStream.java
@@ -37,7 +37,7 @@
  * @author     Arthur van Hoff
  * @see        java.io.ByteArrayInputStream
  * @see        java.io.StringReader
- * @since      JDK1.0
+ * @since      1.0
  * @deprecated This class does not properly convert characters into bytes.  As
  *             of JDK&nbsp;1.1, the preferred way to create a stream from a
  *             string is via the <code>StringReader</code> class.
@@ -108,6 +108,7 @@
      *             <code>-1</code> if there is no more data because the end of
      *             the stream has been reached.
      */
+    @SuppressWarnings("deprecation")
     public synchronized int read(byte b[], int off, int len) {
         if (b == null) {
             throw new NullPointerException();
@@ -127,12 +128,8 @@
         if (len <= 0) {
             return 0;
         }
-        String  s = buffer;
-        int cnt = len;
-        while (--cnt >= 0) {
-            b[off++] = (byte)s.charAt(pos++);
-        }
-
+        buffer.getBytes(pos, pos + len, b, off);
+        pos += len;
         return len;
     }
 
diff --git a/ojluni/src/main/java/java/io/StringReader.java b/ojluni/src/main/java/java/io/StringReader.java
index ce9ff60..9cfe541 100644
--- a/ojluni/src/main/java/java/io/StringReader.java
+++ b/ojluni/src/main/java/java/io/StringReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  * A character stream whose source is a string.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class StringReader extends Reader {
@@ -84,6 +84,7 @@
      *             stream has been reached
      *
      * @exception  IOException  If an I/O error occurs
+     * @exception  IndexOutOfBoundsException {@inheritDoc}
      */
     public int read(char cbuf[], int off, int len) throws IOException {
         synchronized (lock) {
@@ -141,8 +142,8 @@
      */
     public boolean ready() throws IOException {
         synchronized (lock) {
-        ensureOpen();
-        return true;
+            ensureOpen();
+            return true;
         }
     }
 
@@ -193,9 +194,12 @@
      * Closes the stream and releases any system resources associated with
      * it. Once the stream has been closed, further read(),
      * ready(), mark(), or reset() invocations will throw an IOException.
-     * Closing a previously closed stream has no effect.
+     * Closing a previously closed stream has no effect. This method will block
+     * while there is another thread blocking on the reader.
      */
     public void close() {
-        str = null;
+        synchronized (lock) {
+            str = null;
+        }
     }
 }
diff --git a/ojluni/src/main/java/java/io/StringWriter.java b/ojluni/src/main/java/java/io/StringWriter.java
index c4e5d40..16eed62 100644
--- a/ojluni/src/main/java/java/io/StringWriter.java
+++ b/ojluni/src/main/java/java/io/StringWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,12 +30,12 @@
  * A character stream that collects its output in a string buffer, which can
  * then be used to construct a string.
  * <p>
- * Closing a <tt>StringWriter</tt> has no effect. The methods in this class
+ * Closing a {@code StringWriter} has no effect. The methods in this class
  * can be called after the stream has been closed without generating an
- * <tt>IOException</tt>.
+ * {@code IOException}.
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public class StringWriter extends Writer {
@@ -56,11 +56,11 @@
      * size.
      *
      * @param initialSize
-     *        The number of <tt>char</tt> values that will fit into this buffer
+     *        The number of {@code char} values that will fit into this buffer
      *        before it is automatically expanded
      *
      * @throws IllegalArgumentException
-     *         If <tt>initialSize</tt> is negative
+     *         If {@code initialSize} is negative
      */
     public StringWriter(int initialSize) {
         if (initialSize < 0) {
@@ -83,6 +83,11 @@
      * @param  cbuf  Array of characters
      * @param  off   Offset from which to start writing characters
      * @param  len   Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
      */
     public void write(char cbuf[], int off, int len) {
         if ((off < 0) || (off > cbuf.length) || (len < 0) ||
@@ -107,29 +112,34 @@
      * @param  str  String to be written
      * @param  off  Offset from which to start writing characters
      * @param  len  Number of characters to write
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given string
      */
     public void write(String str, int off, int len)  {
-        buf.append(str.substring(off, off + len));
+        buf.append(str, off, off + len);
     }
 
     /**
      * Appends the specified character sequence to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
+     * <p> An invocation of this method of the form {@code out.append(csq)}
      * behaves in exactly the same way as the invocation
      *
      * <pre>
      *     out.write(csq.toString()) </pre>
      *
-     * <p> Depending on the specification of <tt>toString</tt> for the
-     * character sequence <tt>csq</tt>, the entire sequence may not be
-     * appended. For instance, invoking the <tt>toString</tt> method of a
+     * <p> Depending on the specification of {@code toString} for the
+     * character sequence {@code csq}, the entire sequence may not be
+     * appended. For instance, invoking the {@code toString} method of a
      * character buffer will return a subsequence whose content depends upon
      * the buffer's position and limit.
      *
      * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         The character sequence to append.  If {@code csq} is
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this writer.
      *
      * @return  This writer
@@ -137,28 +147,27 @@
      * @since  1.5
      */
     public StringWriter append(CharSequence csq) {
-        if (csq == null)
-            write("null");
-        else
-            write(csq.toString());
+        write(String.valueOf(csq));
         return this;
     }
 
     /**
      * Appends a subsequence of the specified character sequence to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
+     * <p> An invocation of this method of the form
+     * {@code out.append(csq, start, end)} when {@code csq}
+     * is not {@code null}, behaves in
      * exactly the same way as the invocation
      *
-     * <pre>
-     *     out.write(csq.subSequence(start, end).toString()) </pre>
+     * <pre>{@code
+     *     out.write(csq.subSequence(start, end).toString())
+     * }</pre>
      *
      * @param  csq
      *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
+     *         appended.  If {@code csq} is {@code null}, then characters
+     *         will be appended as if {@code csq} contained the four
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -170,22 +179,21 @@
      * @return  This writer
      *
      * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
+     *          If {@code start} or {@code end} are negative, {@code start}
+     *          is greater than {@code end}, or {@code end} is greater than
+     *          {@code csq.length()}
      *
      * @since  1.5
      */
     public StringWriter append(CharSequence csq, int start, int end) {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
      * Appends the specified character to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
+     * <p> An invocation of this method of the form {@code out.append(c)}
      * behaves in exactly the same way as the invocation
      *
      * <pre>
@@ -226,9 +234,9 @@
     }
 
     /**
-     * Closing a <tt>StringWriter</tt> has no effect. The methods in this
+     * Closing a {@code StringWriter} has no effect. The methods in this
      * class can be called after the stream has been closed without generating
-     * an <tt>IOException</tt>.
+     * an {@code IOException}.
      */
     public void close() throws IOException {
     }
diff --git a/ojluni/src/main/java/java/io/SyncFailedException.java b/ojluni/src/main/java/java/io/SyncFailedException.java
index 7e553a7..dc1228ad 100644
--- a/ojluni/src/main/java/java/io/SyncFailedException.java
+++ b/ojluni/src/main/java/java/io/SyncFailedException.java
@@ -31,7 +31,7 @@
  * @author  Ken Arnold
  * @see     java.io.FileDescriptor#sync
  * @see     java.io.IOException
- * @since   JDK1.1
+ * @since   1.1
  */
 public class SyncFailedException extends IOException {
     private static final long serialVersionUID = -2353342684412443330L;
diff --git a/ojluni/src/main/java/java/io/UTFDataFormatException.java b/ojluni/src/main/java/java/io/UTFDataFormatException.java
index 422d28b..88a1cf7 100644
--- a/ojluni/src/main/java/java/io/UTFDataFormatException.java
+++ b/ojluni/src/main/java/java/io/UTFDataFormatException.java
@@ -40,7 +40,7 @@
  * @see     java.io.DataInput
  * @see     java.io.DataInputStream#readUTF(java.io.DataInput)
  * @see     java.io.IOException
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class UTFDataFormatException extends IOException {
diff --git a/ojluni/src/main/java/java/io/UnsupportedEncodingException.java b/ojluni/src/main/java/java/io/UnsupportedEncodingException.java
index b59f9c3..48b2224 100644
--- a/ojluni/src/main/java/java/io/UnsupportedEncodingException.java
+++ b/ojluni/src/main/java/java/io/UnsupportedEncodingException.java
@@ -28,7 +28,7 @@
  * The Character Encoding is not supported.
  *
  * @author  Asmus Freytag
- * @since   JDK1.1
+ * @since   1.1
  */
 public class UnsupportedEncodingException
     extends IOException
diff --git a/ojluni/src/main/java/java/io/WriteAbortedException.java b/ojluni/src/main/java/java/io/WriteAbortedException.java
index c39950d..202575c 100644
--- a/ojluni/src/main/java/java/io/WriteAbortedException.java
+++ b/ojluni/src/main/java/java/io/WriteAbortedException.java
@@ -41,7 +41,7 @@
  * method, as well as the aforementioned "legacy field."
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class WriteAbortedException extends ObjectStreamException {
     private static final long serialVersionUID = -3326426625597282442L;
diff --git a/ojluni/src/main/java/java/io/Writer.java b/ojluni/src/main/java/java/io/Writer.java
index 8747a13..f83a618 100644
--- a/ojluni/src/main/java/java/io/Writer.java
+++ b/ojluni/src/main/java/java/io/Writer.java
@@ -26,25 +26,26 @@
 package java.io;
 
 
+import java.util.Objects;
+
 /**
  * Abstract class for writing to character streams.  The only methods that a
  * subclass must implement are write(char[], int, int), flush(), and close().
  * Most subclasses, however, will override some of the methods defined here in
  * order to provide higher efficiency, additional functionality, or both.
  *
- * @see Writer
  * @see   BufferedWriter
  * @see   CharArrayWriter
  * @see   FilterWriter
  * @see   OutputStreamWriter
- * @see     FileWriter
+ * @see   FileWriter
  * @see   PipedWriter
  * @see   PrintWriter
  * @see   StringWriter
  * @see Reader
  *
  * @author      Mark Reinhold
- * @since       JDK1.1
+ * @since       1.1
  */
 
 public abstract class Writer implements Appendable, Closeable, Flushable {
@@ -60,10 +61,95 @@
     private static final int WRITE_BUFFER_SIZE = 1024;
 
     /**
+     * Returns a new {@code Writer} which discards all characters.  The
+     * returned stream is initially open.  The stream is closed by calling
+     * the {@code close()} method.  Subsequent calls to {@code close()} have
+     * no effect.
+     *
+     * <p> While the stream is open, the {@code append(char)}, {@code
+     * append(CharSequence)}, {@code append(CharSequence, int, int)},
+     * {@code flush()}, {@code write(int)}, {@code write(char[])}, and
+     * {@code write(char[], int, int)} methods do nothing. After the stream
+     * has been closed, these methods all throw {@code IOException}.
+     *
+     * <p> The {@link #lock object} used to synchronize operations on the
+     * returned {@code Writer} is not specified.
+     *
+     * @return a {@code Writer} which discards all characters
+     *
+     * @since 11
+     */
+    public static Writer nullWriter() {
+        return new Writer() {
+            private volatile boolean closed;
+
+            private void ensureOpen() throws IOException {
+                if (closed) {
+                    throw new IOException("Stream closed");
+                }
+            }
+
+            @Override
+            public Writer append(char c) throws IOException {
+                ensureOpen();
+                return this;
+            }
+
+            @Override
+            public Writer append(CharSequence csq) throws IOException {
+                ensureOpen();
+                return this;
+            }
+
+            @Override
+            public Writer append(CharSequence csq, int start, int end) throws IOException {
+                ensureOpen();
+                if (csq != null) {
+                    Objects.checkFromToIndex(start, end, csq.length());
+                }
+                return this;
+            }
+
+            @Override
+            public void write(int c) throws IOException {
+                ensureOpen();
+            }
+
+            @Override
+            public void write(char[] cbuf, int off, int len) throws IOException {
+                Objects.checkFromIndexSize(off, len, cbuf.length);
+                ensureOpen();
+            }
+
+            @Override
+            public void write(String str) throws IOException {
+                Objects.requireNonNull(str);
+                ensureOpen();
+            }
+
+            @Override
+            public void write(String str, int off, int len) throws IOException {
+                Objects.checkFromIndexSize(off, len, str.length());
+                ensureOpen();
+            }
+
+            @Override
+            public void flush() throws IOException {
+                ensureOpen();
+            }
+
+            @Override
+            public void close() throws IOException {
+                closed = true;
+            }
+        };
+    }
+
+    /**
      * The object used to synchronize operations on this stream.  For
      * efficiency, a character-stream object may use an object other than
      * itself to protect critical sections.  A subclass should therefore use
-     * the object in this field rather than <tt>this</tt> or a synchronized
+     * the object in this field rather than {@code this} or a synchronized
      * method.
      */
     protected Object lock;
@@ -139,10 +225,16 @@
      * @param  len
      *         Number of characters to write
      *
+     * @throws  IndexOutOfBoundsException
+     *          Implementations should throw this exception
+     *          if {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
+     *          of the given array
+     *
      * @throws  IOException
      *          If an I/O error occurs
      */
-    abstract public void write(char cbuf[], int off, int len) throws IOException;
+    public abstract void write(char cbuf[], int off, int len) throws IOException;
 
     /**
      * Writes a string.
@@ -160,6 +252,11 @@
     /**
      * Writes a portion of a string.
      *
+     * @implSpec
+     * The implementation in this class throws an
+     * {@code IndexOutOfBoundsException} for the indicated conditions;
+     * overriding methods may choose to do otherwise.
+     *
      * @param  str
      *         A String
      *
@@ -170,8 +267,9 @@
      *         Number of characters to write
      *
      * @throws  IndexOutOfBoundsException
-     *          If <tt>off</tt> is negative, or <tt>len</tt> is negative,
-     *          or <tt>off+len</tt> is negative or greater than the length
+     *          Implementations should throw this exception
+     *          if {@code off} is negative, or {@code len} is negative,
+     *          or {@code off + len} is negative or greater than the length
      *          of the given string
      *
      * @throws  IOException
@@ -196,21 +294,21 @@
     /**
      * Appends the specified character sequence to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
+     * <p> An invocation of this method of the form {@code out.append(csq)}
      * behaves in exactly the same way as the invocation
      *
      * <pre>
      *     out.write(csq.toString()) </pre>
      *
-     * <p> Depending on the specification of <tt>toString</tt> for the
-     * character sequence <tt>csq</tt>, the entire sequence may not be
-     * appended. For instance, invoking the <tt>toString</tt> method of a
+     * <p> Depending on the specification of {@code toString} for the
+     * character sequence {@code csq}, the entire sequence may not be
+     * appended. For instance, invoking the {@code toString} method of a
      * character buffer will return a subsequence whose content depends upon
      * the buffer's position and limit.
      *
      * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         The character sequence to append.  If {@code csq} is
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this writer.
      *
      * @return  This writer
@@ -221,29 +319,28 @@
      * @since  1.5
      */
     public Writer append(CharSequence csq) throws IOException {
-        if (csq == null)
-            write("null");
-        else
-            write(csq.toString());
+        write(String.valueOf(csq));
         return this;
     }
 
     /**
      * Appends a subsequence of the specified character sequence to this writer.
-     * <tt>Appendable</tt>.
+     * {@code Appendable}.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt> behaves in exactly the
+     * <p> An invocation of this method of the form
+     * {@code out.append(csq, start, end)} when {@code csq}
+     * is not {@code null} behaves in exactly the
      * same way as the invocation
      *
-     * <pre>
-     *     out.write(csq.subSequence(start, end).toString()) </pre>
+     * <pre>{@code
+     *     out.write(csq.subSequence(start, end).toString())
+     * }</pre>
      *
      * @param  csq
      *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
+     *         appended.  If {@code csq} is {@code null}, then characters
+     *         will be appended as if {@code csq} contained the four
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -255,9 +352,9 @@
      * @return  This writer
      *
      * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
+     *          If {@code start} or {@code end} are negative, {@code start}
+     *          is greater than {@code end}, or {@code end} is greater than
+     *          {@code csq.length()}
      *
      * @throws  IOException
      *          If an I/O error occurs
@@ -265,15 +362,14 @@
      * @since  1.5
      */
     public Writer append(CharSequence csq, int start, int end) throws IOException {
-        CharSequence cs = (csq == null ? "null" : csq);
-        write(cs.subSequence(start, end).toString());
-        return this;
+        if (csq == null) csq = "null";
+        return append(csq.subSequence(start, end));
     }
 
     /**
      * Appends the specified character to this writer.
      *
-     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
+     * <p> An invocation of this method of the form {@code out.append(c)}
      * behaves in exactly the same way as the invocation
      *
      * <pre>
@@ -310,7 +406,7 @@
      * @throws  IOException
      *          If an I/O error occurs
      */
-    abstract public void flush() throws IOException;
+    public abstract void flush() throws IOException;
 
     /**
      * Closes the stream, flushing it first. Once the stream has been closed,
@@ -320,6 +416,6 @@
      * @throws  IOException
      *          If an I/O error occurs
      */
-    abstract public void close() throws IOException;
+    public abstract void close() throws IOException;
 
 }
diff --git a/ojluni/src/main/java/java/lang/AbstractMethodError.java b/ojluni/src/main/java/java/lang/AbstractMethodError.java
index e266107..af02ba8 100644
--- a/ojluni/src/main/java/java/lang/AbstractMethodError.java
+++ b/ojluni/src/main/java/java/lang/AbstractMethodError.java
@@ -33,7 +33,7 @@
  * compiled.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class AbstractMethodError extends IncompatibleClassChangeError {
diff --git a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
index 4c31e23..6739605 100644
--- a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -25,7 +25,7 @@
 
 package java.lang;
 
-import sun.misc.FloatingDecimal;
+import jdk.internal.math.FloatingDecimal;
 import java.util.Arrays;
 
 /**
@@ -45,6 +45,7 @@
  * @since       1.5
  */
 abstract class AbstractStringBuilder implements Appendable, CharSequence {
+    // TODO: remove java.lang.Integer.getChars(int, int, char[]) once updated to byte[] from 11.
     /**
      * The value is used for character storage.
      */
diff --git a/ojluni/src/main/java/java/lang/Appendable.java b/ojluni/src/main/java/java/lang/Appendable.java
index 46fd78d..0113d6f 100644
--- a/ojluni/src/main/java/java/lang/Appendable.java
+++ b/ojluni/src/main/java/java/lang/Appendable.java
@@ -28,15 +28,15 @@
 import java.io.IOException;
 
 /**
- * An object to which <tt>char</tt> sequences and values can be appended.  The
- * <tt>Appendable</tt> interface must be implemented by any class whose
+ * An object to which {@code char} sequences and values can be appended.  The
+ * {@code Appendable} interface must be implemented by any class whose
  * instances are intended to receive formatted output from a {@link
  * java.util.Formatter}.
  *
  * <p> The characters to be appended should be valid Unicode characters as
  * described in <a href="Character.html#unicode">Unicode Character
  * Representation</a>.  Note that supplementary characters may be composed of
- * multiple 16-bit <tt>char</tt> values.
+ * multiple 16-bit {@code char} values.
  *
  * <p> Appendables are not necessarily safe for multithreaded access.  Thread
  * safety is the responsibility of classes that extend and implement this
@@ -51,19 +51,19 @@
 public interface Appendable {
 
     /**
-     * Appends the specified character sequence to this <tt>Appendable</tt>.
+     * Appends the specified character sequence to this {@code Appendable}.
      *
      * <p> Depending on which class implements the character sequence
-     * <tt>csq</tt>, the entire sequence may not be appended.  For
-     * instance, if <tt>csq</tt> is a {@link java.nio.CharBuffer} then
+     * {@code csq}, the entire sequence may not be appended.  For
+     * instance, if {@code csq} is a {@link java.nio.CharBuffer} then
      * the subsequence to append is defined by the buffer's position and limit.
      *
      * @param  csq
-     *         The character sequence to append.  If <tt>csq</tt> is
-     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
+     *         The character sequence to append.  If {@code csq} is
+     *         {@code null}, then the four characters {@code "null"} are
      *         appended to this Appendable.
      *
-     * @return  A reference to this <tt>Appendable</tt>
+     * @return  A reference to this {@code Appendable}
      *
      * @throws  IOException
      *          If an I/O error occurs
@@ -72,10 +72,10 @@
 
     /**
      * Appends a subsequence of the specified character sequence to this
-     * <tt>Appendable</tt>.
+     * {@code Appendable}.
      *
-     * <p> An invocation of this method of the form <tt>out.append(csq, start,
-     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
+     * <p> An invocation of this method of the form {@code out.append(csq, start, end)}
+     * when {@code csq} is not {@code null}, behaves in
      * exactly the same way as the invocation
      *
      * <pre>
@@ -83,9 +83,9 @@
      *
      * @param  csq
      *         The character sequence from which a subsequence will be
-     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
-     *         will be appended as if <tt>csq</tt> contained the four
-     *         characters <tt>"null"</tt>.
+     *         appended.  If {@code csq} is {@code null}, then characters
+     *         will be appended as if {@code csq} contained the four
+     *         characters {@code "null"}.
      *
      * @param  start
      *         The index of the first character in the subsequence
@@ -94,12 +94,12 @@
      *         The index of the character following the last character in the
      *         subsequence
      *
-     * @return  A reference to this <tt>Appendable</tt>
+     * @return  A reference to this {@code Appendable}
      *
      * @throws  IndexOutOfBoundsException
-     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
-     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
-     *          <tt>csq.length()</tt>
+     *          If {@code start} or {@code end} are negative, {@code start}
+     *          is greater than {@code end}, or {@code end} is greater than
+     *          {@code csq.length()}
      *
      * @throws  IOException
      *          If an I/O error occurs
@@ -107,12 +107,12 @@
     Appendable append(CharSequence csq, int start, int end) throws IOException;
 
     /**
-     * Appends the specified character to this <tt>Appendable</tt>.
+     * Appends the specified character to this {@code Appendable}.
      *
      * @param  c
      *         The character to append
      *
-     * @return  A reference to this <tt>Appendable</tt>
+     * @return  A reference to this {@code Appendable}
      *
      * @throws  IOException
      *          If an I/O error occurs
diff --git a/ojluni/src/main/java/java/lang/ArithmeticException.java b/ojluni/src/main/java/java/lang/ArithmeticException.java
index af00777..7c48f7c 100644
--- a/ojluni/src/main/java/java/lang/ArithmeticException.java
+++ b/ojluni/src/main/java/java/lang/ArithmeticException.java
@@ -36,7 +36,7 @@
  * stack trace was not writable}.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public class ArithmeticException extends RuntimeException {
     private static final long serialVersionUID = 2256477558314496007L;
diff --git a/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
index d07a4b2..3630e0e 100644
--- a/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
+++ b/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,42 +27,42 @@
 package java.lang;
 
 /**
- * Thrown to indicate that an array has been accessed with an
- * illegal index. The index is either negative or greater than or
- * equal to the size of the array.
+ * Thrown to indicate that an array has been accessed with an illegal index. The
+ * index is either negative or greater than or equal to the size of the array.
  *
- * @author  unascribed
- * @since   JDK1.0
+ * @since 1.0
  */
-public
-class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
+public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
     private static final long serialVersionUID = -5116101128118950844L;
 
     /**
-     * Constructs an <code>ArrayIndexOutOfBoundsException</code> with no
-     * detail message.
+     * Constructs an {@code ArrayIndexOutOfBoundsException} with no detail
+     * message.
      */
     public ArrayIndexOutOfBoundsException() {
         super();
     }
 
     /**
-     * Constructs a new <code>ArrayIndexOutOfBoundsException</code>
-     * class with an argument indicating the illegal index.
+     * Constructs an {@code ArrayIndexOutOfBoundsException} class with the
+     * specified detail message.
      *
-     * @param   index   the illegal index.
-     */
-    public ArrayIndexOutOfBoundsException(int index) {
-        super("Array index out of range: " + index);
-    }
-
-    /**
-     * Constructs an <code>ArrayIndexOutOfBoundsException</code> class
-     * with the specified detail message.
-     *
-     * @param   s   the detail message.
+     * @param s the detail message.
      */
     public ArrayIndexOutOfBoundsException(String s) {
         super(s);
     }
+
+    /**
+     * Constructs a new {@code ArrayIndexOutOfBoundsException} class with an
+     * argument indicating the illegal index.
+     *
+     * <p>The index is included in this exception's detail message.  The
+     * exact presentation format of the detail message is unspecified.
+     *
+     * @param index the illegal index.
+     */
+    public ArrayIndexOutOfBoundsException(int index) {
+        super("Array index out of range: " + index);
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/ArrayStoreException.java b/ojluni/src/main/java/java/lang/ArrayStoreException.java
index 5ea0aa9..04696ac 100644
--- a/ojluni/src/main/java/java/lang/ArrayStoreException.java
+++ b/ojluni/src/main/java/java/lang/ArrayStoreException.java
@@ -35,7 +35,7 @@
  * </pre></blockquote>
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class ArrayStoreException extends RuntimeException {
diff --git a/ojluni/src/main/java/java/lang/Boolean.java b/ojluni/src/main/java/java/lang/Boolean.java
index a9293ba..c600a06 100644
--- a/ojluni/src/main/java/java/lang/Boolean.java
+++ b/ojluni/src/main/java/java/lang/Boolean.java
@@ -25,6 +25,8 @@
 
 package java.lang;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+
 /**
  * The Boolean class wraps a value of the primitive type
  * {@code boolean} in an object. An object of type
@@ -38,7 +40,7 @@
  * {@code boolean}.
  *
  * @author  Arthur van Hoff
- * @since   JDK1.0
+ * @since   1.0
  */
 public final class Boolean implements java.io.Serializable,
                                       Comparable<Boolean>
@@ -58,7 +60,7 @@
     /**
      * The Class object representing the primitive type boolean.
      *
-     * @since   JDK1.1
+     * @since   1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Boolean> TYPE = (Class<Boolean>) Class.getPrimitiveClass("boolean");
@@ -77,13 +79,16 @@
      * Allocates a {@code Boolean} object representing the
      * {@code value} argument.
      *
-     * <p><b>Note: It is rarely appropriate to use this constructor.
-     * Unless a <i>new</i> instance is required, the static factory
-     * {@link #valueOf(boolean)} is generally a better choice. It is
-     * likely to yield significantly better space and time performance.</b>
-     *
      * @param   value   the value of the {@code Boolean}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(boolean)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
+     * Also consider using the final fields {@link #TRUE} and {@link #FALSE}
+     * if possible.
      */
+    @Deprecated(since="9")
     public Boolean(boolean value) {
         this.value = value;
     }
@@ -92,15 +97,18 @@
      * Allocates a {@code Boolean} object representing the value
      * {@code true} if the string argument is not {@code null}
      * and is equal, ignoring case, to the string {@code "true"}.
-     * Otherwise, allocate a {@code Boolean} object representing the
-     * value {@code false}. Examples:<p>
-     * {@code new Boolean("True")} produces a {@code Boolean} object
-     * that represents {@code true}.<br>
-     * {@code new Boolean("yes")} produces a {@code Boolean} object
-     * that represents {@code false}.
+     * Otherwise, allocates a {@code Boolean} object representing the
+     * value {@code false}.
      *
      * @param   s   the string to be converted to a {@code Boolean}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseBoolean(String)} to convert a string to a
+     * {@code boolean} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Boolean} object.
      */
+    @Deprecated(since="9")
     public Boolean(String s) {
         this(parseBoolean(s));
     }
@@ -109,7 +117,9 @@
      * Parses the string argument as a boolean.  The {@code boolean}
      * returned represents the value {@code true} if the string argument
      * is not {@code null} and is equal, ignoring case, to the string
-     * {@code "true"}. <p>
+     * {@code "true"}.
+     * Otherwise, a false value is returned, including for a null
+     * argument.<p>
      * Example: {@code Boolean.parseBoolean("True")} returns {@code true}.<br>
      * Example: {@code Boolean.parseBoolean("yes")} returns {@code false}.
      *
@@ -119,7 +129,7 @@
      * @since 1.5
      */
     public static boolean parseBoolean(String s) {
-        return ((s != null) && s.equalsIgnoreCase("true"));
+        return "true".equalsIgnoreCase(s);
     }
 
     /**
@@ -128,6 +138,7 @@
      *
      * @return  the primitive {@code boolean} value of this object.
      */
+    @HotSpotIntrinsicCandidate
     public boolean booleanValue() {
         return value;
     }
@@ -146,6 +157,7 @@
      * @return a {@code Boolean} instance representing {@code b}.
      * @since  1.4
      */
+    @HotSpotIntrinsicCandidate
     public static Boolean valueOf(boolean b) {
         return (b ? TRUE : FALSE);
     }
@@ -155,6 +167,8 @@
      * specified string.  The {@code Boolean} returned represents a
      * true value if the string argument is not {@code null}
      * and is equal, ignoring case, to the string {@code "true"}.
+     * Otherwise, a false value is returned, including for a null
+     * argument.
      *
      * @param   s   a string.
      * @return  the {@code Boolean} value represented by the string.
@@ -230,16 +244,13 @@
     }
 
     /**
-     * Returns {@code true} if and only if the system property
-     * named by the argument exists and is equal to the string
-     * {@code "true"}. (Beginning with version 1.0.2 of the
-     * Java<small><sup>TM</sup></small> platform, the test of
-     * this string is case insensitive.) A system property is accessible
-     * through {@code getProperty}, a method defined by the
-     * {@code System} class.
-     * <p>
-     * If there is no property with the specified name, or if the specified
-     * name is empty or null, then {@code false} is returned.
+     * Returns {@code true} if and only if the system property named
+     * by the argument exists and is equal to, ignoring case, the
+     * string {@code "true"}.
+     * A system property is accessible through {@code getProperty}, a
+     * method defined by the {@code System} class.  <p> If there is no
+     * property with the specified name, or if the specified name is
+     * empty or null, then {@code false} is returned.
      *
      * @param   name   the system property name.
      * @return  the {@code boolean} value of the system property.
diff --git a/ojluni/src/main/java/java/lang/BootstrapMethodError.java b/ojluni/src/main/java/java/lang/BootstrapMethodError.java
index a1509a0..8ffe2ca 100644
--- a/ojluni/src/main/java/java/lang/BootstrapMethodError.java
+++ b/ojluni/src/main/java/java/lang/BootstrapMethodError.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,15 @@
 package java.lang;
 
 /**
- * Thrown to indicate that an {@code invokedynamic} instruction has
- * failed to find its bootstrap method,
- * or the bootstrap method has failed to provide a
- * {@linkplain java.lang.invoke.CallSite call site} with a {@linkplain java.lang.invoke.CallSite#getTarget target}
- * of the correct {@linkplain java.lang.invoke.MethodHandle#type method type}.
+ * Thrown to indicate that an {@code invokedynamic} instruction or a dynamic
+ * constant failed to resolve its bootstrap method and arguments,
+ * or for {@code invokedynamic} instruction the bootstrap method has failed to
+ * provide a
+ * {@linkplain java.lang.invoke.CallSite call site} with a
+ * {@linkplain java.lang.invoke.CallSite#getTarget target}
+ * of the correct {@linkplain java.lang.invoke.MethodHandle#type() method type},
+ * or for a dynamic constant the bootstrap method has failed to provide a
+ * constant value of the required type.
  *
  * @author John Rose, JSR 292 EG
  * @since 1.7
diff --git a/ojluni/src/main/java/java/lang/Byte.java b/ojluni/src/main/java/java/lang/Byte.java
index bc397f9..9988333 100644
--- a/ojluni/src/main/java/java/lang/Byte.java
+++ b/ojluni/src/main/java/java/lang/Byte.java
@@ -25,8 +25,7 @@
 
 package java.lang;
 
-// Android-removed: Unsupported @HotSpotIntrinsicCandidate annotation.
-// import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.HotSpotIntrinsicCandidate;
 import libcore.util.HexEncoding;
 
 /**
@@ -102,8 +101,7 @@
      * @return a {@code Byte} instance representing {@code b}.
      * @since  1.5
      */
-    // Android-removed: Unsupported @HotSpotIntrinsicCandidate annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public static Byte valueOf(byte b) {
         final int offset = 128;
         return ByteCache.cache[(int)b + offset];
@@ -338,8 +336,7 @@
      * Returns the value of this {@code Byte} as a
      * {@code byte}.
      */
-    // Android-removed: Unsupported @HotSpotIntrinsicCandidate annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public byte byteValue() {
         return value;
     }
diff --git a/ojluni/src/main/java/java/lang/Class.java b/ojluni/src/main/java/java/lang/Class.java
index 7925408..722968c 100644
--- a/ojluni/src/main/java/java/lang/Class.java
+++ b/ojluni/src/main/java/java/lang/Class.java
@@ -2396,6 +2396,8 @@
      * assertion status that was (or will be) associated with the specified
      * class when it was (or will be) initialized.
      *
+     * Android-note: AssertionStatuses are unsupported. This method will always return false.
+     *
      * @return the desired assertion status of the specified class.
      * @see    java.lang.ClassLoader#setClassAssertionStatus
      * @see    java.lang.ClassLoader#setPackageAssertionStatus
diff --git a/ojluni/src/main/java/java/lang/ClassCastException.java b/ojluni/src/main/java/java/lang/ClassCastException.java
index e4ca76c..d7abe40 100644
--- a/ojluni/src/main/java/java/lang/ClassCastException.java
+++ b/ojluni/src/main/java/java/lang/ClassCastException.java
@@ -35,7 +35,7 @@
  * </pre></blockquote>
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class ClassCastException extends RuntimeException {
diff --git a/ojluni/src/main/java/java/lang/ClassCircularityError.java b/ojluni/src/main/java/java/lang/ClassCircularityError.java
index 64e5361..76f2aaf 100644
--- a/ojluni/src/main/java/java/lang/ClassCircularityError.java
+++ b/ojluni/src/main/java/java/lang/ClassCircularityError.java
@@ -30,7 +30,7 @@
  * superclass hierarchy of a class being loaded.
  *
  * @author     unascribed
- * @since      JDK1.0
+ * @since      1.0
  */
 public class ClassCircularityError extends LinkageError {
     private static final long serialVersionUID = 1054362542914539689L;
diff --git a/ojluni/src/main/java/java/lang/ClassFormatError.java b/ojluni/src/main/java/java/lang/ClassFormatError.java
index 2dc81db..d06cac0 100644
--- a/ojluni/src/main/java/java/lang/ClassFormatError.java
+++ b/ojluni/src/main/java/java/lang/ClassFormatError.java
@@ -31,7 +31,7 @@
  * be interpreted as a class file.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class ClassFormatError extends LinkageError {
diff --git a/ojluni/src/main/java/java/lang/ClassLoader.java b/ojluni/src/main/java/java/lang/ClassLoader.java
index 0a8b08a..6c01ffa 100644
--- a/ojluni/src/main/java/java/lang/ClassLoader.java
+++ b/ojluni/src/main/java/java/lang/ClassLoader.java
@@ -1242,6 +1242,8 @@
      * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
      * #setClassAssertionStatus(String, boolean)}.
      *
+     * Android-note: AssertionStatuses are unsupported. This method is a no-op.
+     *
      * @param  enabled
      *         <tt>true</tt> if classes loaded by this class loader will
      *         henceforth have assertions enabled by default, <tt>false</tt>
@@ -1274,6 +1276,8 @@
      * assertion status, and may be overridden on a per-class basis by invoking
      * {@link #setClassAssertionStatus(String, boolean)}.  </p>
      *
+     * Android-note: AssertionStatuses are unsupported. This method is a no-op.
+     *
      * @param  packageName
      *         The name of the package whose package default assertion status
      *         is to be set. A <tt>null</tt> value indicates the unnamed
@@ -1304,6 +1308,8 @@
      * <p> If the named class is not a top-level class, this invocation will
      * have no effect on the actual assertion status of any class. </p>
      *
+     * Android-note: AssertionStatuses are unsupported. This method is a no-op.
+     *
      * @param  className
      *         The fully qualified class name of the top-level class whose
      *         assertion status is to be set.
@@ -1325,6 +1331,8 @@
      * provided so that class loaders can be made to ignore any command line or
      * persistent assertion status settings and "start with a clean slate."
      *
+     * Android-note: AssertionStatuses are unsupported. This method is a no-op.
+     *
      * @since  1.4
      */
     public void clearAssertionStatus() {
diff --git a/ojluni/src/main/java/java/lang/ClassNotFoundException.java b/ojluni/src/main/java/java/lang/ClassNotFoundException.java
index 1211e9f..2f20dce 100644
--- a/ojluni/src/main/java/java/lang/ClassNotFoundException.java
+++ b/ojluni/src/main/java/java/lang/ClassNotFoundException.java
@@ -48,7 +48,7 @@
  * @see     java.lang.Class#forName(java.lang.String)
  * @see     java.lang.ClassLoader#findSystemClass(java.lang.String)
  * @see     java.lang.ClassLoader#loadClass(java.lang.String, boolean)
- * @since   JDK1.0
+ * @since   1.0
  */
 public class ClassNotFoundException extends ReflectiveOperationException {
     /**
@@ -98,7 +98,7 @@
 
     /**
      * Returns the exception that was raised if an error occurred while
-     * attempting to load the class. Otherwise, returns <tt>null</tt>.
+     * attempting to load the class. Otherwise, returns {@code null}.
      *
      * <p>This method predates the general-purpose exception chaining facility.
      * The {@link Throwable#getCause()} method is now the preferred means of
@@ -114,7 +114,7 @@
     /**
      * Returns the cause of this exception (the exception that was raised
      * if an error occurred while attempting to load the class; otherwise
-     * <tt>null</tt>).
+     * {@code null}).
      *
      * @return  the cause of this exception.
      * @since   1.4
diff --git a/ojluni/src/main/java/java/lang/CloneNotSupportedException.java b/ojluni/src/main/java/java/lang/CloneNotSupportedException.java
index e43901c..fdc0147 100644
--- a/ojluni/src/main/java/java/lang/CloneNotSupportedException.java
+++ b/ojluni/src/main/java/java/lang/CloneNotSupportedException.java
@@ -38,7 +38,7 @@
  * @author  unascribed
  * @see     java.lang.Cloneable
  * @see     java.lang.Object#clone()
- * @since   JDK1.0
+ * @since   1.0
  */
 
 public
diff --git a/ojluni/src/main/java/java/lang/Cloneable.java b/ojluni/src/main/java/java/lang/Cloneable.java
index 14cf2a9..f1bec05 100644
--- a/ojluni/src/main/java/java/lang/Cloneable.java
+++ b/ojluni/src/main/java/java/lang/Cloneable.java
@@ -36,11 +36,11 @@
  * <code>CloneNotSupportedException</code> being thrown.
  * <p>
  * By convention, classes that implement this interface should override
- * <tt>Object.clone</tt> (which is protected) with a public method.
+ * {@code Object.clone} (which is protected) with a public method.
  * See {@link java.lang.Object#clone()} for details on overriding this
  * method.
  * <p>
- * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
+ * Note that this interface does <i>not</i> contain the {@code clone} method.
  * Therefore, it is not possible to clone an object merely by virtue of the
  * fact that it implements this interface.  Even if the clone method is invoked
  * reflectively, there is no guarantee that it will succeed.
@@ -48,7 +48,7 @@
  * @author  unascribed
  * @see     java.lang.CloneNotSupportedException
  * @see     java.lang.Object#clone()
- * @since   JDK1.0
+ * @since   1.0
  */
 public interface Cloneable {
 }
diff --git a/ojluni/src/main/java/java/lang/Comparable.java b/ojluni/src/main/java/java/lang/Comparable.java
index f0e4b38..75289ab 100644
--- a/ojluni/src/main/java/java/lang/Comparable.java
+++ b/ojluni/src/main/java/java/lang/Comparable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
 /**
  * This interface imposes a total ordering on the objects of each class that
  * implements it.  This ordering is referred to as the class's <i>natural
- * ordering</i>, and the class's <tt>compareTo</tt> method is referred to as
+ * ordering</i>, and the class's {@code compareTo} method is referred to as
  * its <i>natural comparison method</i>.<p>
  *
  * Lists (and arrays) of objects that implement this interface can be sorted
@@ -39,52 +39,52 @@
  * elements in a {@linkplain SortedSet sorted set}, without the need to
  * specify a {@linkplain Comparator comparator}.<p>
  *
- * The natural ordering for a class <tt>C</tt> is said to be <i>consistent
- * with equals</i> if and only if <tt>e1.compareTo(e2) == 0</tt> has
- * the same boolean value as <tt>e1.equals(e2)</tt> for every
- * <tt>e1</tt> and <tt>e2</tt> of class <tt>C</tt>.  Note that <tt>null</tt>
- * is not an instance of any class, and <tt>e.compareTo(null)</tt> should
- * throw a <tt>NullPointerException</tt> even though <tt>e.equals(null)</tt>
- * returns <tt>false</tt>.<p>
+ * The natural ordering for a class {@code C} is said to be <i>consistent
+ * with equals</i> if and only if {@code e1.compareTo(e2) == 0} has
+ * the same boolean value as {@code e1.equals(e2)} for every
+ * {@code e1} and {@code e2} of class {@code C}.  Note that {@code null}
+ * is not an instance of any class, and {@code e.compareTo(null)} should
+ * throw a {@code NullPointerException} even though {@code e.equals(null)}
+ * returns {@code false}.<p>
  *
  * It is strongly recommended (though not required) that natural orderings be
  * consistent with equals.  This is so because sorted sets (and sorted maps)
  * without explicit comparators behave "strangely" when they are used with
  * elements (or keys) whose natural ordering is inconsistent with equals.  In
  * particular, such a sorted set (or sorted map) violates the general contract
- * for set (or map), which is defined in terms of the <tt>equals</tt>
+ * for set (or map), which is defined in terms of the {@code equals}
  * method.<p>
  *
- * For example, if one adds two keys <tt>a</tt> and <tt>b</tt> such that
+ * For example, if one adds two keys {@code a} and {@code b} such that
  * {@code (!a.equals(b) && a.compareTo(b) == 0)} to a sorted
- * set that does not use an explicit comparator, the second <tt>add</tt>
+ * set that does not use an explicit comparator, the second {@code add}
  * operation returns false (and the size of the sorted set does not increase)
- * because <tt>a</tt> and <tt>b</tt> are equivalent from the sorted set's
+ * because {@code a} and {@code b} are equivalent from the sorted set's
  * perspective.<p>
  *
- * Virtually all Java core classes that implement <tt>Comparable</tt> have natural
+ * Virtually all Java core classes that implement {@code Comparable} have natural
  * orderings that are consistent with equals.  One exception is
- * <tt>java.math.BigDecimal</tt>, whose natural ordering equates
- * <tt>BigDecimal</tt> objects with equal values and different precisions
+ * {@code java.math.BigDecimal}, whose natural ordering equates
+ * {@code BigDecimal} objects with equal values and different precisions
  * (such as 4.0 and 4.00).<p>
  *
  * For the mathematically inclined, the <i>relation</i> that defines
- * the natural ordering on a given class C is:<pre>
- *       {(x, y) such that x.compareTo(y) &lt;= 0}.
- * </pre> The <i>quotient</i> for this total order is: <pre>
+ * the natural ordering on a given class C is:<pre>{@code
+ *       {(x, y) such that x.compareTo(y) <= 0}.
+ * }</pre> The <i>quotient</i> for this total order is: <pre>{@code
  *       {(x, y) such that x.compareTo(y) == 0}.
- * </pre>
+ * }</pre>
  *
- * It follows immediately from the contract for <tt>compareTo</tt> that the
- * quotient is an <i>equivalence relation</i> on <tt>C</tt>, and that the
- * natural ordering is a <i>total order</i> on <tt>C</tt>.  When we say that a
+ * It follows immediately from the contract for {@code compareTo} that the
+ * quotient is an <i>equivalence relation</i> on {@code C}, and that the
+ * natural ordering is a <i>total order</i> on {@code C}.  When we say that a
  * class's natural ordering is <i>consistent with equals</i>, we mean that the
  * quotient for the natural ordering is the equivalence relation defined by
  * the class's {@link Object#equals(Object) equals(Object)} method:<pre>
  *     {(x, y) such that x.equals(y)}. </pre><p>
  *
  * This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @param <T> the type of objects that this object may be compared to
@@ -99,31 +99,32 @@
      * negative integer, zero, or a positive integer as this object is less
      * than, equal to, or greater than the specified object.
      *
-     * <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
-     * -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
-     * implies that <tt>x.compareTo(y)</tt> must throw an exception iff
-     * <tt>y.compareTo(x)</tt> throws an exception.)
+     * <p>The implementor must ensure
+     * {@code sgn(x.compareTo(y)) == -sgn(y.compareTo(x))}
+     * for all {@code x} and {@code y}.  (This
+     * implies that {@code x.compareTo(y)} must throw an exception iff
+     * {@code y.compareTo(x)} throws an exception.)
      *
      * <p>The implementor must also ensure that the relation is transitive:
-     * <tt>(x.compareTo(y)&gt;0 &amp;&amp; y.compareTo(z)&gt;0)</tt> implies
-     * <tt>x.compareTo(z)&gt;0</tt>.
+     * {@code (x.compareTo(y) > 0 && y.compareTo(z) > 0)} implies
+     * {@code x.compareTo(z) > 0}.
      *
-     * <p>Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
-     * implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
-     * all <tt>z</tt>.
+     * <p>Finally, the implementor must ensure that {@code x.compareTo(y)==0}
+     * implies that {@code sgn(x.compareTo(z)) == sgn(y.compareTo(z))}, for
+     * all {@code z}.
      *
      * <p>It is strongly recommended, but <i>not</i> strictly required that
-     * <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>.  Generally speaking, any
-     * class that implements the <tt>Comparable</tt> interface and violates
+     * {@code (x.compareTo(y)==0) == (x.equals(y))}.  Generally speaking, any
+     * class that implements the {@code Comparable} interface and violates
      * this condition should clearly indicate this fact.  The recommended
      * language is "Note: this class has a natural ordering that is
      * inconsistent with equals."
      *
      * <p>In the foregoing description, the notation
-     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
-     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
-     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
-     * <i>expression</i> is negative, zero or positive.
+     * {@code sgn(}<i>expression</i>{@code )} designates the mathematical
+     * <i>signum</i> function, which is defined to return one of {@code -1},
+     * {@code 0}, or {@code 1} according to whether the value of
+     * <i>expression</i> is negative, zero, or positive, respectively.
      *
      * @param   o the object to be compared.
      * @return  a negative integer, zero, or a positive integer as this object
diff --git a/ojluni/src/main/java/java/lang/Double.java b/ojluni/src/main/java/java/lang/Double.java
index 690ca6a..52bf32c 100644
--- a/ojluni/src/main/java/java/lang/Double.java
+++ b/ojluni/src/main/java/java/lang/Double.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,9 @@
 
 package java.lang;
 
-import sun.misc.FloatingDecimal;
-import sun.misc.FpUtils;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
  * The {@code Double} class wraps a value of the primitive type
@@ -44,7 +44,7 @@
  * @author  Lee Boynton
  * @author  Arthur van Hoff
  * @author  Joseph D. Darcy
- * @since JDK1.0
+ * @since 1.0
  */
 public final class Double extends Number implements Comparable<Double> {
     /**
@@ -133,7 +133,7 @@
      * The {@code Class} instance representing the primitive type
      * {@code double}.
      *
-     * @since JDK1.1
+     * @since 1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Double>   TYPE = (Class<Double>) Class.getPrimitiveClass("double");
@@ -255,23 +255,27 @@
      *
      * </ul>
      *
-     * <table border>
+     * <table class="striped">
      * <caption>Examples</caption>
-     * <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
-     * <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
-     * <tr><td>{@code -1.0}</td>        <td>{@code -0x1.0p0}</td>
-     * <tr><td>{@code 2.0}</td> <td>{@code 0x1.0p1}</td>
-     * <tr><td>{@code 3.0}</td> <td>{@code 0x1.8p1}</td>
-     * <tr><td>{@code 0.5}</td> <td>{@code 0x1.0p-1}</td>
-     * <tr><td>{@code 0.25}</td>        <td>{@code 0x1.0p-2}</td>
-     * <tr><td>{@code Double.MAX_VALUE}</td>
+     * <thead>
+     * <tr><th scope="col">Floating-point Value</th><th scope="col">Hexadecimal String</th>
+     * </thead>
+     * <tbody style="text-align:right">
+     * <tr><th scope="row">{@code 1.0}</th> <td>{@code 0x1.0p0}</td>
+     * <tr><th scope="row">{@code -1.0}</th>        <td>{@code -0x1.0p0}</td>
+     * <tr><th scope="row">{@code 2.0}</th> <td>{@code 0x1.0p1}</td>
+     * <tr><th scope="row">{@code 3.0}</th> <td>{@code 0x1.8p1}</td>
+     * <tr><th scope="row">{@code 0.5}</th> <td>{@code 0x1.0p-1}</td>
+     * <tr><th scope="row">{@code 0.25}</th>        <td>{@code 0x1.0p-2}</td>
+     * <tr><th scope="row">{@code Double.MAX_VALUE}</th>
      *     <td>{@code 0x1.fffffffffffffp1023}</td>
-     * <tr><td>{@code Minimum Normal Value}</td>
+     * <tr><th scope="row">{@code Minimum Normal Value}</th>
      *     <td>{@code 0x1.0p-1022}</td>
-     * <tr><td>{@code Maximum Subnormal Value}</td>
+     * <tr><th scope="row">{@code Maximum Subnormal Value}</th>
      *     <td>{@code 0x0.fffffffffffffp-1022}</td>
-     * <tr><td>{@code Double.MIN_VALUE}</td>
+     * <tr><th scope="row">{@code Double.MIN_VALUE}</th>
      *     <td>{@code 0x0.0000000000001p-1022}</td>
+     * </tbody>
      * </table>
      * @param   d   the {@code double} to be converted.
      * @return a hex string representation of the argument.
@@ -301,7 +305,7 @@
             if(d == 0.0) {
                 answer.append("0.0p0");
             } else {
-                boolean subnormal = (d < DoubleConsts.MIN_NORMAL);
+                boolean subnormal = (d < Double.MIN_NORMAL);
 
                 // Isolate significand bits and OR in a high-order bit
                 // so that the string representation has a known
@@ -329,7 +333,7 @@
                 // exponent (the representation of a subnormal uses
                 // E_min -1).
                 answer.append(subnormal ?
-                              DoubleConsts.MIN_EXPONENT:
+                              Double.MIN_EXPONENT:
                               Math.getExponent(d));
             }
             return answer.toString();
@@ -515,6 +519,7 @@
      * @return a {@code Double} instance representing {@code d}.
      * @since  1.5
      */
+    @HotSpotIntrinsicCandidate
     public static Double valueOf(double d) {
         return new Double(d);
     }
@@ -573,7 +578,7 @@
      * @since 1.8
      */
     public static boolean isFinite(double d) {
-        return Math.abs(d) <= DoubleConsts.MAX_VALUE;
+        return Math.abs(d) <= Double.MAX_VALUE;
     }
 
     /**
@@ -588,7 +593,13 @@
      * represents the primitive {@code double} argument.
      *
      * @param   value   the value to be represented by the {@code Double}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(double)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Double(double value) {
         this.value = value;
     }
@@ -600,10 +611,16 @@
      * {@code double} value as if by the {@code valueOf} method.
      *
      * @param  s  a string to be converted to a {@code Double}.
-     * @throws    NumberFormatException  if the string does not contain a
+     * @throws    NumberFormatException if the string does not contain a
      *            parsable number.
-     * @see       java.lang.Double#valueOf(java.lang.String)
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseDouble(String)} to convert a string to a
+     * {@code double} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Double} object.
      */
+    @Deprecated(since="9")
     public Double(String s) throws NumberFormatException {
         value = parseDouble(s);
     }
@@ -651,7 +668,7 @@
      * @return  the {@code double} value represented by this object
      *          converted to type {@code byte}
      * @jls 5.1.3 Narrowing Primitive Conversions
-     * @since JDK1.1
+     * @since 1.1
      */
     public byte byteValue() {
         return (byte)value;
@@ -664,7 +681,7 @@
      * @return  the {@code double} value represented by this object
      *          converted to type {@code short}
      * @jls 5.1.3 Narrowing Primitive Conversions
-     * @since JDK1.1
+     * @since 1.1
      */
     public short shortValue() {
         return (short)value;
@@ -701,7 +718,7 @@
      * @return  the {@code double} value represented by this object
      *          converted to type {@code float}
      * @jls 5.1.3 Narrowing Primitive Conversions
-     * @since JDK1.0
+     * @since 1.0
      */
     public float floatValue() {
         return (float)value;
@@ -712,6 +729,7 @@
      *
      * @return the {@code double} value represented by this object
      */
+    @HotSpotIntrinsicCandidate
     public double doubleValue() {
         return value;
     }
@@ -832,15 +850,12 @@
      * @param   value   a {@code double} precision floating-point number.
      * @return the bits that represent the floating-point number.
      */
+    @HotSpotIntrinsicCandidate
     public static long doubleToLongBits(double value) {
-        long result = doubleToRawLongBits(value);
-        // Check for NaN based on values of bit fields, maximum
-        // exponent and nonzero significand.
-        if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
-              DoubleConsts.EXP_BIT_MASK) &&
-             (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
-            result = 0x7ff8000000000000L;
-        return result;
+        if (!isNaN(value)) {
+            return doubleToRawLongBits(value);
+        }
+        return 0x7ff8000000000000L;
     }
 
     /**
@@ -879,6 +894,7 @@
      * @return the bits that represent the floating-point number.
      * @since 1.3
      */
+    @HotSpotIntrinsicCandidate
     public static native long doubleToRawLongBits(double value);
 
     /**
@@ -942,6 +958,7 @@
      * @return  the {@code double} floating-point value with the same
      *          bit pattern.
      */
+    @HotSpotIntrinsicCandidate
     public static native double longBitsToDouble(long bits);
 
     /**
diff --git a/ojluni/src/main/java/java/lang/Enum.java b/ojluni/src/main/java/java/lang/Enum.java
index 6b37aea..2824725 100644
--- a/ojluni/src/main/java/java/lang/Enum.java
+++ b/ojluni/src/main/java/java/lang/Enum.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,8 @@
  * @see     java.util.EnumMap
  * @since   1.5
  */
+@SuppressWarnings("serial") // No serialVersionUID needed due to
+                            // special-casing of enum types.
 public abstract class Enum<E extends Enum<E>>
         implements Comparable<E>, Serializable {
     /**
@@ -293,6 +295,7 @@
     /**
      * enum classes cannot have finalize methods.
      */
+    @SuppressWarnings("deprecation")
     protected final void finalize() { }
 
     /**
diff --git a/ojluni/src/main/java/java/lang/EnumConstantNotPresentException.java b/ojluni/src/main/java/java/lang/EnumConstantNotPresentException.java
index 1773160..78aeb20 100644
--- a/ojluni/src/main/java/java/lang/EnumConstantNotPresentException.java
+++ b/ojluni/src/main/java/java/lang/EnumConstantNotPresentException.java
@@ -51,7 +51,7 @@
     private String constantName;
 
     /**
-     * Constructs an <tt>EnumConstantNotPresentException</tt> for the
+     * Constructs an {@code EnumConstantNotPresentException} for the
      * specified constant.
      *
      * @param enumType the type of the missing enum constant
diff --git a/ojluni/src/main/java/java/lang/Error.java b/ojluni/src/main/java/java/lang/Error.java
index d18c15f..e2012a5 100644
--- a/ojluni/src/main/java/java/lang/Error.java
+++ b/ojluni/src/main/java/java/lang/Error.java
@@ -44,7 +44,7 @@
  * @author  Frank Yellin
  * @see     java.lang.ThreadDeath
  * @jls 11.2 Compile-Time Checking of Exceptions
- * @since   JDK1.0
+ * @since   1.0
  */
 public class Error extends Throwable {
     static final long serialVersionUID = 4980196508277280342L;
diff --git a/ojluni/src/main/java/java/lang/Exception.java b/ojluni/src/main/java/java/lang/Exception.java
index 0bcbf9c..d81048e 100644
--- a/ojluni/src/main/java/java/lang/Exception.java
+++ b/ojluni/src/main/java/java/lang/Exception.java
@@ -40,7 +40,7 @@
  * @author  Frank Yellin
  * @see     java.lang.Error
  * @jls 11.2 Compile-Time Checking of Exceptions
- * @since   JDK1.0
+ * @since   1.0
  */
 public class Exception extends Throwable {
     static final long serialVersionUID = -3387516993124229948L;
@@ -75,7 +75,7 @@
      * @param  message the detail message (which is saved for later retrieval
      *         by the {@link #getMessage()} method).
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link #getCause()} method).  (A <tt>null</tt> value is
+     *         {@link #getCause()} method).  (A {@code null} value is
      *         permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since  1.4
@@ -86,14 +86,14 @@
 
     /**
      * Constructs a new exception with the specified cause and a detail
-     * message of <tt>(cause==null ? null : cause.toString())</tt> (which
-     * typically contains the class and detail message of <tt>cause</tt>).
+     * message of {@code (cause==null ? null : cause.toString())} (which
+     * typically contains the class and detail message of {@code cause}).
      * This constructor is useful for exceptions that are little more than
      * wrappers for other throwables (for example, {@link
      * java.security.PrivilegedActionException}).
      *
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link #getCause()} method).  (A <tt>null</tt> value is
+     *         {@link #getCause()} method).  (A {@code null} value is
      *         permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since  1.4
diff --git a/ojluni/src/main/java/java/lang/ExceptionInInitializerError.java b/ojluni/src/main/java/java/lang/ExceptionInInitializerError.java
index 0259766..d5d0bb3 100644
--- a/ojluni/src/main/java/java/lang/ExceptionInInitializerError.java
+++ b/ojluni/src/main/java/java/lang/ExceptionInInitializerError.java
@@ -39,7 +39,7 @@
  * as the aforementioned "legacy method."
  *
  * @author  Frank Yellin
- * @since   JDK1.1
+ * @since   1.1
  */
 public class ExceptionInInitializerError extends LinkageError {
     /**
diff --git a/ojluni/src/main/java/java/lang/Float.java b/ojluni/src/main/java/java/lang/Float.java
index 5cc28f9..52cb2c0 100644
--- a/ojluni/src/main/java/java/lang/Float.java
+++ b/ojluni/src/main/java/java/lang/Float.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,8 @@
 
 package java.lang;
 
-import sun.misc.FloatingDecimal;
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
  * The {@code Float} class wraps a value of primitive type
@@ -44,7 +43,7 @@
  * @author  Lee Boynton
  * @author  Arthur van Hoff
  * @author  Joseph D. Darcy
- * @since JDK1.0
+ * @since 1.0
  */
 public final class Float extends Number implements Comparable<Float> {
     /**
@@ -131,7 +130,7 @@
      * The {@code Class} instance representing the primitive type
      * {@code float}.
      *
-     * @since JDK1.1
+     * @since 1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Float> TYPE = (Class<Float>) Class.getPrimitiveClass("float");
@@ -257,23 +256,27 @@
      *
      * </ul>
      *
-     * <table border>
+     * <table class="striped">
      * <caption>Examples</caption>
-     * <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
-     * <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
-     * <tr><td>{@code -1.0}</td>        <td>{@code -0x1.0p0}</td>
-     * <tr><td>{@code 2.0}</td> <td>{@code 0x1.0p1}</td>
-     * <tr><td>{@code 3.0}</td> <td>{@code 0x1.8p1}</td>
-     * <tr><td>{@code 0.5}</td> <td>{@code 0x1.0p-1}</td>
-     * <tr><td>{@code 0.25}</td>        <td>{@code 0x1.0p-2}</td>
-     * <tr><td>{@code Float.MAX_VALUE}</td>
+     * <thead>
+     * <tr><th scope="col">Floating-point Value</th><th scope="col">Hexadecimal String</th>
+     * </thead>
+     * <tbody>
+     * <tr><th scope="row">{@code 1.0}</th> <td>{@code 0x1.0p0}</td>
+     * <tr><th scope="row">{@code -1.0}</th>        <td>{@code -0x1.0p0}</td>
+     * <tr><th scope="row">{@code 2.0}</th> <td>{@code 0x1.0p1}</td>
+     * <tr><th scope="row">{@code 3.0}</th> <td>{@code 0x1.8p1}</td>
+     * <tr><th scope="row">{@code 0.5}</th> <td>{@code 0x1.0p-1}</td>
+     * <tr><th scope="row">{@code 0.25}</th>        <td>{@code 0x1.0p-2}</td>
+     * <tr><th scope="row">{@code Float.MAX_VALUE}</th>
      *     <td>{@code 0x1.fffffep127}</td>
-     * <tr><td>{@code Minimum Normal Value}</td>
+     * <tr><th scope="row">{@code Minimum Normal Value}</th>
      *     <td>{@code 0x1.0p-126}</td>
-     * <tr><td>{@code Maximum Subnormal Value}</td>
+     * <tr><th scope="row">{@code Maximum Subnormal Value}</th>
      *     <td>{@code 0x0.fffffep-126}</td>
-     * <tr><td>{@code Float.MIN_VALUE}</td>
+     * <tr><th scope="row">{@code Float.MIN_VALUE}</th>
      *     <td>{@code 0x0.000002p-126}</td>
+     * </tbody>
      * </table>
      * @param   f   the {@code float} to be converted.
      * @return a hex string representation of the argument.
@@ -281,15 +284,15 @@
      * @author Joseph D. Darcy
      */
     public static String toHexString(float f) {
-        if (Math.abs(f) < FloatConsts.MIN_NORMAL
+        if (Math.abs(f) < Float.MIN_NORMAL
             &&  f != 0.0f ) {// float subnormal
             // Adjust exponent to create subnormal double, then
             // replace subnormal double exponent with subnormal float
             // exponent
             String s = Double.toHexString(Math.scalb((double)f,
                                                      /* -1022+126 */
-                                                     DoubleConsts.MIN_EXPONENT-
-                                                     FloatConsts.MIN_EXPONENT));
+                                                     Double.MIN_EXPONENT-
+                                                     Float.MIN_EXPONENT));
             return s.replaceFirst("p-1022$", "p-126");
         }
         else // double string will be the same as float string
@@ -429,6 +432,7 @@
      * @return a {@code Float} instance representing {@code f}.
      * @since  1.5
      */
+    @HotSpotIntrinsicCandidate
     public static Float valueOf(float f) {
         return new Float(f);
     }
@@ -487,7 +491,7 @@
      * @since 1.8
      */
      public static boolean isFinite(float f) {
-        return Math.abs(f) <= FloatConsts.MAX_VALUE;
+        return Math.abs(f) <= Float.MAX_VALUE;
     }
 
     /**
@@ -502,7 +506,13 @@
      * represents the primitive {@code float} argument.
      *
      * @param   value   the value to be represented by the {@code Float}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(float)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Float(float value) {
         this.value = value;
     }
@@ -512,7 +522,13 @@
      * represents the argument converted to type {@code float}.
      *
      * @param   value   the value to be represented by the {@code Float}.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. Instead, use the
+     * static factory method {@link #valueOf(float)} method as follows:
+     * {@code Float.valueOf((float)value)}.
      */
+    @Deprecated(since="9")
     public Float(double value) {
         this.value = (float)value;
     }
@@ -523,11 +539,17 @@
      * represented by the string. The string is converted to a
      * {@code float} value as if by the {@code valueOf} method.
      *
-     * @param      s   a string to be converted to a {@code Float}.
-     * @throws  NumberFormatException  if the string does not contain a
-     *               parsable number.
-     * @see        java.lang.Float#valueOf(java.lang.String)
+     * @param   s   a string to be converted to a {@code Float}.
+     * @throws      NumberFormatException if the string does not contain a
+     *              parsable number.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseFloat(String)} to convert a string to a
+     * {@code float} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Float} object.
      */
+    @Deprecated(since="9")
     public Float(String s) throws NumberFormatException {
         value = parseFloat(s);
     }
@@ -587,7 +609,7 @@
      * @return  the {@code float} value represented by this object
      *          converted to type {@code short}
      * @jls 5.1.3 Narrowing Primitive Conversions
-     * @since JDK1.1
+     * @since 1.1
      */
     public short shortValue() {
         return (short)value;
@@ -622,6 +644,7 @@
      *
      * @return the {@code float} value represented by this object
      */
+    @HotSpotIntrinsicCandidate
     public float floatValue() {
         return value;
     }
@@ -740,15 +763,12 @@
      * @param   value   a floating-point number.
      * @return the bits that represent the floating-point number.
      */
+    @HotSpotIntrinsicCandidate
     public static int floatToIntBits(float value) {
-        int result = floatToRawIntBits(value);
-        // Check for NaN based on values of bit fields, maximum
-        // exponent and nonzero significand.
-        if ( ((result & FloatConsts.EXP_BIT_MASK) ==
-              FloatConsts.EXP_BIT_MASK) &&
-             (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
-            result = 0x7fc00000;
-        return result;
+        if (!isNaN(value)) {
+            return floatToRawIntBits(value);
+        }
+        return 0x7fc00000;
     }
 
     /**
@@ -786,6 +806,7 @@
      * @return the bits that represent the floating-point number.
      * @since 1.3
      */
+    @HotSpotIntrinsicCandidate
     public static native int floatToRawIntBits(float value);
 
     /**
@@ -847,6 +868,7 @@
      * @return  the {@code float} floating-point value with the same bit
      *          pattern.
      */
+    @HotSpotIntrinsicCandidate
     public static native float intBitsToFloat(int bits);
 
     /**
diff --git a/ojluni/src/main/java/java/lang/FunctionalInterface.java b/ojluni/src/main/java/java/lang/FunctionalInterface.java
index a93ed51..72ecca6 100644
--- a/ojluni/src/main/java/java/lang/FunctionalInterface.java
+++ b/ojluni/src/main/java/java/lang/FunctionalInterface.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,6 +60,7 @@
  * @jls 4.3.2. The Class Object
  * @jls 9.8 Functional Interfaces
  * @jls 9.4.3 Interface Method Body
+ * @jls 9.6.4.9 @FunctionalInterface
  * @since 1.8
  */
 @Documented
diff --git a/ojluni/src/main/java/java/lang/IllegalAccessError.java b/ojluni/src/main/java/java/lang/IllegalAccessError.java
index ce045cd..b2a50a5 100644
--- a/ojluni/src/main/java/java/lang/IllegalAccessError.java
+++ b/ojluni/src/main/java/java/lang/IllegalAccessError.java
@@ -34,7 +34,7 @@
  * incompatibly changed.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public class IllegalAccessError extends IncompatibleClassChangeError {
     private static final long serialVersionUID = -8988904074992417891L;
diff --git a/ojluni/src/main/java/java/lang/IllegalAccessException.java b/ojluni/src/main/java/java/lang/IllegalAccessException.java
index c7b1df8..b0e039a 100644
--- a/ojluni/src/main/java/java/lang/IllegalAccessException.java
+++ b/ojluni/src/main/java/java/lang/IllegalAccessException.java
@@ -54,7 +54,7 @@
  * @see     java.lang.reflect.Field#getDouble(Object)
  * @see     java.lang.reflect.Method#invoke(Object, Object[])
  * @see     java.lang.reflect.Constructor#newInstance(Object[])
- * @since   JDK1.0
+ * @since   1.0
  */
 public class IllegalAccessException extends ReflectiveOperationException {
     private static final long serialVersionUID = 6616958222490762034L;
diff --git a/ojluni/src/main/java/java/lang/IllegalArgumentException.java b/ojluni/src/main/java/java/lang/IllegalArgumentException.java
index c29a9d5..67559f8 100644
--- a/ojluni/src/main/java/java/lang/IllegalArgumentException.java
+++ b/ojluni/src/main/java/java/lang/IllegalArgumentException.java
@@ -30,7 +30,7 @@
  * inappropriate argument.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class IllegalArgumentException extends RuntimeException {
@@ -63,7 +63,7 @@
      * @param  message the detail message (which is saved for later retrieval
      *         by the {@link Throwable#getMessage()} method).
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link Throwable#getCause()} method).  (A <tt>null</tt> value
+     *         {@link Throwable#getCause()} method).  (A {@code null} value
      *         is permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since 1.5
@@ -74,14 +74,14 @@
 
     /**
      * Constructs a new exception with the specified cause and a detail
-     * message of <tt>(cause==null ? null : cause.toString())</tt> (which
-     * typically contains the class and detail message of <tt>cause</tt>).
+     * message of {@code (cause==null ? null : cause.toString())} (which
+     * typically contains the class and detail message of {@code cause}).
      * This constructor is useful for exceptions that are little more than
      * wrappers for other throwables (for example, {@link
      * java.security.PrivilegedActionException}).
      *
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link Throwable#getCause()} method).  (A <tt>null</tt> value is
+     *         {@link Throwable#getCause()} method).  (A {@code null} value is
      *         permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since  1.5
diff --git a/ojluni/src/main/java/java/lang/IllegalCallerException.java b/ojluni/src/main/java/java/lang/IllegalCallerException.java
new file mode 100644
index 0000000..edb3896
--- /dev/null
+++ b/ojluni/src/main/java/java/lang/IllegalCallerException.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * Thrown to indicate that a method has been called by an inappropriate caller.
+ *
+ * @since 9
+ * @spec JPMS
+ * @see StackWalker#getCallerClass
+ */
+ // Android-changed: hide while StackWalker is not available
+ /** @hide */
+public class IllegalCallerException extends RuntimeException {
+    /**
+     * Constructs an IllegalCallerException with no detail message.
+     */
+    public IllegalCallerException() {
+        super();
+    }
+
+    /**
+     * Constructs an IllegalCallerException with the specified detail
+     * message.
+     *
+     * @param s the String that contains a detailed message (can be null)
+     */
+    public IllegalCallerException(String s) {
+        super(s);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and
+     * cause.
+     *
+     * @param  message the detail message (can be null)
+     * @param  cause the cause (can be null)
+     */
+    public IllegalCallerException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified cause and a detail
+     * message of {@code (cause==null ? null : cause.toString())} (which
+     * typically contains the class and detail message of {@code cause}).
+     *
+     * @param  cause the cause (can be null)
+     */
+    public IllegalCallerException(Throwable cause) {
+        super(cause);
+    }
+
+    static final long serialVersionUID = -2349421918363102232L;
+}
diff --git a/ojluni/src/main/java/java/lang/IllegalMonitorStateException.java b/ojluni/src/main/java/java/lang/IllegalMonitorStateException.java
index 3985066..b2be5c0 100644
--- a/ojluni/src/main/java/java/lang/IllegalMonitorStateException.java
+++ b/ojluni/src/main/java/java/lang/IllegalMonitorStateException.java
@@ -36,7 +36,7 @@
  * @see     java.lang.Object#wait()
  * @see     java.lang.Object#wait(long)
  * @see     java.lang.Object#wait(long, int)
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class IllegalMonitorStateException extends RuntimeException {
diff --git a/ojluni/src/main/java/java/lang/IllegalStateException.java b/ojluni/src/main/java/java/lang/IllegalStateException.java
index 9c0c06a..7cef7a1 100644
--- a/ojluni/src/main/java/java/lang/IllegalStateException.java
+++ b/ojluni/src/main/java/java/lang/IllegalStateException.java
@@ -32,7 +32,7 @@
  * operation.
  *
  * @author  Jonni Kanerva
- * @since   JDK1.1
+ * @since   1.1
  */
 public
 class IllegalStateException extends RuntimeException {
@@ -66,7 +66,7 @@
      * @param  message the detail message (which is saved for later retrieval
      *         by the {@link Throwable#getMessage()} method).
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link Throwable#getCause()} method).  (A <tt>null</tt> value
+     *         {@link Throwable#getCause()} method).  (A {@code null} value
      *         is permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since 1.5
@@ -77,14 +77,14 @@
 
     /**
      * Constructs a new exception with the specified cause and a detail
-     * message of <tt>(cause==null ? null : cause.toString())</tt> (which
-     * typically contains the class and detail message of <tt>cause</tt>).
+     * message of {@code (cause==null ? null : cause.toString())} (which
+     * typically contains the class and detail message of {@code cause}).
      * This constructor is useful for exceptions that are little more than
      * wrappers for other throwables (for example, {@link
      * java.security.PrivilegedActionException}).
      *
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link Throwable#getCause()} method).  (A <tt>null</tt> value is
+     *         {@link Throwable#getCause()} method).  (A {@code null} value is
      *         permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since  1.5
diff --git a/ojluni/src/main/java/java/lang/IllegalThreadStateException.java b/ojluni/src/main/java/java/lang/IllegalThreadStateException.java
index c59ab59..c926bea 100644
--- a/ojluni/src/main/java/java/lang/IllegalThreadStateException.java
+++ b/ojluni/src/main/java/java/lang/IllegalThreadStateException.java
@@ -34,7 +34,7 @@
  * @author  unascribed
  * @see     java.lang.Thread#resume()
  * @see     java.lang.Thread#suspend()
- * @since   JDK1.0
+ * @since   1.0
  */
 public class IllegalThreadStateException extends IllegalArgumentException {
     private static final long serialVersionUID = -7626246362397460174L;
diff --git a/ojluni/src/main/java/java/lang/IncompatibleClassChangeError.java b/ojluni/src/main/java/java/lang/IncompatibleClassChangeError.java
index edffaee..03ca3f3 100644
--- a/ojluni/src/main/java/java/lang/IncompatibleClassChangeError.java
+++ b/ojluni/src/main/java/java/lang/IncompatibleClassChangeError.java
@@ -31,7 +31,7 @@
  * executing method depends, has since changed.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class IncompatibleClassChangeError extends LinkageError {
diff --git a/ojluni/src/main/java/java/lang/IndexOutOfBoundsException.java b/ojluni/src/main/java/java/lang/IndexOutOfBoundsException.java
index 4dc7948..4da92e1 100644
--- a/ojluni/src/main/java/java/lang/IndexOutOfBoundsException.java
+++ b/ojluni/src/main/java/java/lang/IndexOutOfBoundsException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,28 +31,40 @@
  * <p>
  * Applications can subclass this class to indicate similar exceptions.
  *
- * @author  Frank Yellin
- * @since   JDK1.0
+ * @author Frank Yellin
+ * @since 1.0
  */
-public
-class IndexOutOfBoundsException extends RuntimeException {
+public class IndexOutOfBoundsException extends RuntimeException {
     private static final long serialVersionUID = 234122996006267687L;
 
     /**
-     * Constructs an <code>IndexOutOfBoundsException</code> with no
-     * detail message.
+     * Constructs an {@code IndexOutOfBoundsException} with no detail message.
      */
     public IndexOutOfBoundsException() {
         super();
     }
 
     /**
-     * Constructs an <code>IndexOutOfBoundsException</code> with the
-     * specified detail message.
+     * Constructs an {@code IndexOutOfBoundsException} with the specified detail
+     * message.
      *
-     * @param   s   the detail message.
+     * @param s the detail message
      */
     public IndexOutOfBoundsException(String s) {
         super(s);
     }
+
+    /**
+     * Constructs a new {@code IndexOutOfBoundsException} class with an
+     * argument indicating the illegal index.
+     *
+     * <p>The index is included in this exception's detail message.  The
+     * exact presentation format of the detail message is unspecified.
+     *
+     * @param index the illegal index.
+     * @since 9
+     */
+    public IndexOutOfBoundsException(int index) {
+        super("Index out of range: " + index);
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/InheritableThreadLocal.java b/ojluni/src/main/java/java/lang/InheritableThreadLocal.java
index 935c5f1..23f395c 100644
--- a/ojluni/src/main/java/java/lang/InheritableThreadLocal.java
+++ b/ojluni/src/main/java/java/lang/InheritableThreadLocal.java
@@ -27,12 +27,12 @@
 import java.lang.ref.*;
 
 /**
- * This class extends <tt>ThreadLocal</tt> to provide inheritance of values
+ * This class extends {@code ThreadLocal} to provide inheritance of values
  * from parent thread to child thread: when a child thread is created, the
  * child receives initial values for all inheritable thread-local variables
  * for which the parent has values.  Normally the child's values will be
  * identical to the parent's; however, the child's value can be made an
- * arbitrary function of the parent's by overriding the <tt>childValue</tt>
+ * arbitrary function of the parent's by overriding the {@code childValue}
  * method in this class.
  *
  * <p>Inheritable thread-local variables are used in preference to
@@ -40,6 +40,11 @@
  * maintained in the variable (e.g., User ID, Transaction ID) must be
  * automatically transmitted to any child threads that are created.
  *
+ * <p>Note: During the creation of a new {@link
+ * Thread#Thread(ThreadGroup,Runnable,String,long,boolean) thread}, it is
+ * possible to <i>opt out</i> of receiving initial values for inheritable
+ * thread-local variables.
+ *
  * @author  Josh Bloch and Doug Lea
  * @see     ThreadLocal
  * @since   1.2
diff --git a/ojluni/src/main/java/java/lang/InstantiationError.java b/ojluni/src/main/java/java/lang/InstantiationError.java
index 89c10b3..1410fa7 100644
--- a/ojluni/src/main/java/java/lang/InstantiationError.java
+++ b/ojluni/src/main/java/java/lang/InstantiationError.java
@@ -34,7 +34,7 @@
  * incompatibly changed.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 
 
diff --git a/ojluni/src/main/java/java/lang/InstantiationException.java b/ojluni/src/main/java/java/lang/InstantiationException.java
index afeeb17..877812b 100644
--- a/ojluni/src/main/java/java/lang/InstantiationException.java
+++ b/ojluni/src/main/java/java/lang/InstantiationException.java
@@ -40,7 +40,7 @@
  *
  * @author  unascribed
  * @see     java.lang.Class#newInstance()
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class InstantiationException extends ReflectiveOperationException {
diff --git a/ojluni/src/main/java/java/lang/Integer.java b/ojluni/src/main/java/java/lang/Integer.java
index 93ae24c..5d47b9a 100644
--- a/ojluni/src/main/java/java/lang/Integer.java
+++ b/ojluni/src/main/java/java/lang/Integer.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,9 @@
 package java.lang;
 
 import java.lang.annotation.Native;
+import java.util.Objects;
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.VM;
 
 /**
  * The {@code Integer} class wraps a value of the primitive type
@@ -48,7 +51,7 @@
  * @author  Arthur van Hoff
  * @author  Josh Bloch
  * @author  Joseph D. Darcy
- * @since JDK1.0
+ * @since 1.0
  */
 public final class Integer extends Number implements Comparable<Integer> {
     /**
@@ -67,7 +70,7 @@
      * The {@code Class} instance representing the primitive type
      * {@code int}.
      *
-     * @since   JDK1.1
+     * @since   1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int");
@@ -75,7 +78,7 @@
     /**
      * All possible chars for representing a number as a String
      */
-    final static char[] digits = {
+    static final char[] digits = {
         '0' , '1' , '2' , '3' , '4' , '5' ,
         '6' , '7' , '8' , '9' , 'a' , 'b' ,
         'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
@@ -137,26 +140,59 @@
             return toString(i);
         }
 
-        char buf[] = new char[33];
+        // BEGIN Android-changed: Use single-byte chars.
+        /*
+        if (COMPACT_STRINGS) {
+         */
+            byte[] buf = new byte[33];
+            boolean negative = (i < 0);
+            int charPos = 32;
+
+            if (!negative) {
+                i = -i;
+            }
+
+            while (i <= -radix) {
+                buf[charPos--] = (byte)digits[-(i % radix)];
+                i = i / radix;
+            }
+            buf[charPos] = (byte)digits[-i];
+
+            if (negative) {
+                buf[--charPos] = '-';
+            }
+
+        /*
+            return StringLatin1.newString(buf, charPos, (33 - charPos));
+        }
+        return toStringUTF16(i, radix);
+         */
+        return new String(buf, charPos, (33 - charPos));
+        // END Android-changed: Use single-byte chars.
+    }
+
+    // BEGIN Android-removed: UTF16 version of toString.
+    /*
+    private static String toStringUTF16(int i, int radix) {
+        byte[] buf = new byte[33 * 2];
         boolean negative = (i < 0);
         int charPos = 32;
-
         if (!negative) {
             i = -i;
         }
-
         while (i <= -radix) {
-            buf[charPos--] = digits[-(i % radix)];
+            StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
             i = i / radix;
         }
-        buf[charPos] = digits[-i];
+        StringUTF16.putChar(buf, charPos, digits[-i]);
 
         if (negative) {
-            buf[--charPos] = '-';
+            StringUTF16.putChar(buf, --charPos, '-');
         }
-
-        return new String(buf, charPos, (33 - charPos));
+        return StringUTF16.newString(buf, charPos, (33 - charPos));
     }
+     */
+    // END Android-removed: UTF16 version of toString.
 
     /**
      * Returns a string representation of the first argument as an
@@ -228,7 +264,7 @@
      *          represented by the argument in hexadecimal (base&nbsp;16).
      * @see #parseUnsignedInt(String, int)
      * @see #toUnsignedString(int, int)
-     * @since   JDK1.0.2
+     * @since   1.0.2
      */
     public static String toHexString(int i) {
         return toUnsignedString0(i, 4);
@@ -266,7 +302,7 @@
      *          represented by the argument in octal (base&nbsp;8).
      * @see #parseUnsignedInt(String, int)
      * @see #toUnsignedString(int, int)
-     * @since   JDK1.0.2
+     * @since   1.0.2
      */
     public static String toOctalString(int i) {
         return toUnsignedString0(i, 3);
@@ -298,7 +334,7 @@
      *          represented by the argument in binary (base&nbsp;2).
      * @see #parseUnsignedInt(String, int)
      * @see #toUnsignedString(int, int)
-     * @since   JDK1.0.2
+     * @since   1.0.2
      */
     public static String toBinaryString(int i) {
         return toUnsignedString0(i, 1);
@@ -311,42 +347,82 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-        char[] buf = new char[chars];
 
-        formatUnsignedInt(val, shift, buf, 0, chars);
 
-        // Android-changed: Use regular constructor instead of one which takes over "buf".
-        // return new String(buf, true);
+        // BEGIN Android-changed: Use single-byte chars.
+        /*
+        if (COMPACT_STRINGS) {
+         */
+            byte[] buf = new byte[chars];
+            formatUnsignedInt(val, shift, buf, 0, chars);
+        /*
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[chars * 2];
+            formatUnsignedIntUTF16(val, shift, buf, 0, chars);
+            return new String(buf, UTF16);
+        }
+         */
         return new String(buf);
+        // END Android-changed: Use single-byte chars.
     }
 
     /**
-     * Format a long (treated as unsigned) into a character buffer.
+     * Format an {@code int} (treated as unsigned) into a character buffer. If
+     * {@code len} exceeds the formatted ASCII representation of {@code val},
+     * {@code buf} will be padded with leading zeroes.
+     *
      * @param val the unsigned int to format
      * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary)
      * @param buf the character buffer to write to
      * @param offset the offset in the destination buffer to start at
      * @param len the number of characters to write
-     * @return the lowest character  location used
      */
-     static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
-        int charPos = len;
+    static void formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
+        // assert shift > 0 && shift <=5 : "Illegal shift value";
+        // assert offset >= 0 && offset < buf.length : "illegal offset";
+        // assert len > 0 && (offset + len) <= buf.length : "illegal length";
+        int charPos = offset + len;
         int radix = 1 << shift;
         int mask = radix - 1;
         do {
-            buf[offset + --charPos] = Integer.digits[val & mask];
+            buf[--charPos] = Integer.digits[val & mask];
             val >>>= shift;
-        } while (val != 0 && charPos > 0);
-
-        return charPos;
+        } while (charPos > offset);
     }
 
+    /** byte[]/LATIN1 version    */
+    static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            buf[--charPos] = (byte)Integer.digits[val & mask];
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+
+    // BEGIN Android-removed: UTF16 version of formatUnsignedInt().
+    /*
+    /** byte[]/UTF16 version    *
+    private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+     */
+    // END Android-removed: UTF16 version of formatUnsignedInt().
+
     // BEGIN Android-changed: Cache the toString() result for small values.
     private static final String[] SMALL_NEG_VALUES  = new String[100];
     private static final String[] SMALL_NONNEG_VALUES = new String[100];
     // END Android-changed: Cache the toString() result for small values.
 
-    final static char [] DigitTens = {
+    static final byte[] DigitTens = {
         '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
         '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
         '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
@@ -359,7 +435,7 @@
         '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
         } ;
 
-    final static char [] DigitOnes = {
+    static final byte[] DigitOnes = {
         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
@@ -372,24 +448,6 @@
         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
         } ;
 
-        // I use the "invariant division by multiplication" trick to
-        // accelerate Integer.toString.  In particular we want to
-        // avoid division by 10.
-        //
-        // The "trick" has roughly the same performance characteristics
-        // as the "classic" Integer.toString code on a non-JIT VM.
-        // The trick avoids .rem and .div calls but has a longer code
-        // path and is thus dominated by dispatch overhead.  In the
-        // JIT case the dispatch overhead doesn't exist and the
-        // "trick" is considerably faster than the classic code.
-        //
-        // TODO-FIXME: convert (x * 52429) into the equiv shift-add
-        // sequence.
-        //
-        // RE:  Division by Invariant Integers using Multiplication
-        //      T Gralund, P Montgomery
-        //      ACM PLDI 1994
-        //
 
     /**
      * Returns a {@code String} object representing the
@@ -401,12 +459,9 @@
      * @param   i   an integer to be converted.
      * @return  a string representation of the argument in base&nbsp;10.
      */
+    @HotSpotIntrinsicCandidate
     public static String toString(int i) {
-        if (i == Integer.MIN_VALUE)
-            return "-2147483648";
-
         // BEGIN Android-changed: Cache the String for small values.
-        // int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
         boolean negative = i < 0;
         boolean small = negative ? i > -100 : i < 100;
         if (small) {
@@ -416,25 +471,37 @@
                 i = -i;
                 if (smallValues[i] == null) {
                     smallValues[i] =
-                        i < 10 ? new String(new char[]{'-', DigitOnes[i]})
-                               : new String(new char[]{'-', DigitTens[i], DigitOnes[i]});
+                        i < 10 ? new String(new byte[]{'-', DigitOnes[i]})
+                               : new String(new byte[]{'-', DigitTens[i], DigitOnes[i]});
                 }
             } else {
                 if (smallValues[i] == null) {
                     smallValues[i] =
-                        i < 10 ? new String(new char[]{DigitOnes[i]})
-                               : new String(new char[]{DigitTens[i], DigitOnes[i]});
+                        i < 10 ? new String(new byte[]{DigitOnes[i]})
+                               : new String(new byte[]{DigitTens[i], DigitOnes[i]});
                 }
             }
             return smallValues[i];
         }
-        int size = negative ? stringSize(-i) + 1 : stringSize(i);
         // END Android-changed: Cache the String for small values.
-        char[] buf = new char[size];
-        getChars(i, size, buf);
-        // Android-changed: Use regular constructor instead of one which takes over "buf".
-        // return new String(buf, true);
+        int size = stringSize(i);
+
+        // BEGIN Android-changed: Use single-byte chars.
+        /*
+        if (COMPACT_STRINGS) {
+         */
+            byte[] buf = new byte[size];
+            getChars(i, size, buf);
+        /*
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[size * 2];
+            StringUTF16.getChars(i, size, buf);
+            return new String(buf, UTF16);
+        }
+         */
         return new String(buf);
+        // END Android-changed: Use single-byte chars.
     }
 
     /**
@@ -462,50 +529,115 @@
      * digit at the specified index (exclusive), and working
      * backwards from there.
      *
-     * Will fail if i == Integer.MIN_VALUE
+     * @implNote This method converts positive inputs into negative
+     * values, to cover the Integer.MIN_VALUE case. Converting otherwise
+     * (negative to positive) will expose -Integer.MIN_VALUE that overflows
+     * integer.
+     *
+     * @param i     value to convert
+     * @param index next index, after the least significant digit
+     * @param buf   target buffer, Latin1-encoded
+     * @return index of the most significant digit or minus sign, if present
      */
-    static void getChars(int i, int index, char[] buf) {
+    static int getChars(int i, int index, byte[] buf) {
         int q, r;
         int charPos = index;
-        char sign = 0;
 
-        if (i < 0) {
-            sign = '-';
+        boolean negative = i < 0;
+        if (!negative) {
             i = -i;
         }
 
         // Generate two digits per iteration
-        while (i >= 65536) {
+        while (i <= -100) {
             q = i / 100;
-        // really: r = i - (q * 100);
-            r = i - ((q << 6) + (q << 5) + (q << 2));
+            r = (q * 100) - i;
             i = q;
-            buf [--charPos] = DigitOnes[r];
-            buf [--charPos] = DigitTens[r];
+            buf[--charPos] = DigitOnes[r];
+            buf[--charPos] = DigitTens[r];
         }
 
-        // Fall thru to fast mode for smaller numbers
-        // assert(i <= 65536, i);
-        for (;;) {
-            q = (i * 52429) >>> (16+3);
-            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
-            buf [--charPos] = digits [r];
-            i = q;
-            if (i == 0) break;
+        // We know there are at most two digits left at this point.
+        q = i / 10;
+        r = (q * 10) - i;
+        buf[--charPos] = (byte)('0' + r);
+
+        // Whatever left is the remaining digit.
+        if (q < 0) {
+            buf[--charPos] = (byte)('0' - q);
         }
-        if (sign != 0) {
-            buf [--charPos] = sign;
+
+        if (negative) {
+            buf[--charPos] = (byte)'-';
         }
+        return charPos;
     }
 
-    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
+    // BEGIN Android-added: char version of getChars(int i, int index, byte[] buf).
+    // for java.lang.AbstractStringBuilder#append(int).
+    static int getChars(int i, int index, char[] buf) {
+        int q, r;
+        int charPos = index;
+
+        boolean negative = i < 0;
+        if (!negative) {
+            i = -i;
+        }
+
+        // Generate two digits per iteration
+        while (i <= -100) {
+            q = i / 100;
+            r = (q * 100) - i;
+            i = q;
+            buf[--charPos] = (char)DigitOnes[r];
+            buf[--charPos] = (char)DigitTens[r];
+        }
+
+        // We know there are at most two digits left at this point.
+        q = i / 10;
+        r = (q * 10) - i;
+        buf[--charPos] = (char)('0' + r);
+
+        // Whatever left is the remaining digit.
+        if (q < 0) {
+            buf[--charPos] = (char)('0' - q);
+        }
+
+        if (negative) {
+            buf[--charPos] = (byte)'-';
+        }
+        return charPos;
+    }
+    // END Android-added: char version of getChars(int i, int index, byte[] buf).
+
+    // Left here for compatibility reasons, see JDK-8143900.
+    static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                       99999999, 999999999, Integer.MAX_VALUE };
 
-    // Requires positive x
+    /**
+     * Returns the string representation size for a given int value.
+     *
+     * @param x int value
+     * @return string size
+     *
+     * @implNote There are other ways to compute this: e.g. binary search,
+     * but values are biased heavily towards zero, and therefore linear search
+     * wins. The iteration results are also routinely inlined in the generated
+     * code after loop unrolling.
+     */
     static int stringSize(int x) {
-        for (int i=0; ; i++)
-            if (x <= sizeTable[i])
-                return i+1;
+        int d = 1;
+        if (x >= 0) {
+            d = 0;
+            x = -x;
+        }
+        int p = -10;
+        for (int i = 1; i < 10; i++) {
+            if (x > p)
+                return i + d;
+            p = 10 * p;
+        }
+        return 10 + d;
     }
 
     /**
@@ -587,12 +719,9 @@
                                             " greater than Character.MAX_RADIX");
         }
 
-        int result = 0;
         boolean negative = false;
         int i = 0, len = s.length();
         int limit = -Integer.MAX_VALUE;
-        int multmin;
-        int digit;
 
         if (len > 0) {
             char firstChar = s.charAt(0);
@@ -600,21 +729,21 @@
                 if (firstChar == '-') {
                     negative = true;
                     limit = Integer.MIN_VALUE;
-                } else if (firstChar != '+')
-                    throw NumberFormatException.forInputString(s);
-
-                if (len == 1) // Cannot have lone "+" or "-"
-                    throw NumberFormatException.forInputString(s);
-                i++;
-            }
-            multmin = limit / radix;
-            while (i < len) {
-                // Accumulating negatively avoids surprises near MAX_VALUE
-                digit = Character.digit(s.charAt(i++),radix);
-                if (digit < 0) {
+                } else if (firstChar != '+') {
                     throw NumberFormatException.forInputString(s);
                 }
-                if (result < multmin) {
+
+                if (len == 1) { // Cannot have lone "+" or "-"
+                    throw NumberFormatException.forInputString(s);
+                }
+                i++;
+            }
+            int multmin = limit / radix;
+            int result = 0;
+            while (i < len) {
+                // Accumulating negatively avoids surprises near MAX_VALUE
+                int digit = Character.digit(s.charAt(i++), radix);
+                if (digit < 0 || result < multmin) {
                     throw NumberFormatException.forInputString(s);
                 }
                 result *= radix;
@@ -623,10 +752,96 @@
                 }
                 result -= digit;
             }
+            return negative ? result : -result;
         } else {
             throw NumberFormatException.forInputString(s);
         }
-        return negative ? result : -result;
+    }
+
+    /**
+     * Parses the {@link CharSequence} argument as a signed {@code int} in the
+     * specified {@code radix}, beginning at the specified {@code beginIndex}
+     * and extending to {@code endIndex - 1}.
+     *
+     * <p>The method does not take steps to guard against the
+     * {@code CharSequence} being mutated while parsing.
+     *
+     * @param      s   the {@code CharSequence} containing the {@code int}
+     *                  representation to be parsed
+     * @param      beginIndex   the beginning index, inclusive.
+     * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
+     * @return     the signed {@code int} represented by the subsequence in
+     *             the specified radix.
+     * @throws     NullPointerException  if {@code s} is null.
+     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
+     *             negative, or if {@code beginIndex} is greater than
+     *             {@code endIndex} or if {@code endIndex} is greater than
+     *             {@code s.length()}.
+     * @throws     NumberFormatException  if the {@code CharSequence} does not
+     *             contain a parsable {@code int} in the specified
+     *             {@code radix}, or if {@code radix} is either smaller than
+     *             {@link java.lang.Character#MIN_RADIX} or larger than
+     *             {@link java.lang.Character#MAX_RADIX}.
+     * @since  9
+     */
+    public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
+                throws NumberFormatException {
+        s = Objects.requireNonNull(s);
+
+        if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (radix < Character.MIN_RADIX) {
+            throw new NumberFormatException("radix " + radix +
+                                            " less than Character.MIN_RADIX");
+        }
+        if (radix > Character.MAX_RADIX) {
+            throw new NumberFormatException("radix " + radix +
+                                            " greater than Character.MAX_RADIX");
+        }
+
+        boolean negative = false;
+        int i = beginIndex;
+        int limit = -Integer.MAX_VALUE;
+
+        if (i < endIndex) {
+            char firstChar = s.charAt(i);
+            if (firstChar < '0') { // Possible leading "+" or "-"
+                if (firstChar == '-') {
+                    negative = true;
+                    limit = Integer.MIN_VALUE;
+                } else if (firstChar != '+') {
+                    throw NumberFormatException.forCharSequence(s, beginIndex,
+                            endIndex, i);
+                }
+                i++;
+                if (i == endIndex) { // Cannot have lone "+" or "-"
+                    throw NumberFormatException.forCharSequence(s, beginIndex,
+                            endIndex, i);
+                }
+            }
+            int multmin = limit / radix;
+            int result = 0;
+            while (i < endIndex) {
+                // Accumulating negatively avoids surprises near MAX_VALUE
+                int digit = Character.digit(s.charAt(i), radix);
+                if (digit < 0 || result < multmin) {
+                    throw NumberFormatException.forCharSequence(s, beginIndex,
+                            endIndex, i);
+                }
+                result *= radix;
+                if (result < limit + digit) {
+                    throw NumberFormatException.forCharSequence(s, beginIndex,
+                            endIndex, i);
+                }
+                i++;
+                result -= digit;
+            }
+            return negative ? result : -result;
+        } else {
+            throw NumberFormatException.forInputString("");
+        }
     }
 
     /**
@@ -727,9 +942,71 @@
     }
 
     /**
+     * Parses the {@link CharSequence} argument as an unsigned {@code int} in
+     * the specified {@code radix}, beginning at the specified
+     * {@code beginIndex} and extending to {@code endIndex - 1}.
+     *
+     * <p>The method does not take steps to guard against the
+     * {@code CharSequence} being mutated while parsing.
+     *
+     * @param      s   the {@code CharSequence} containing the unsigned
+     *                 {@code int} representation to be parsed
+     * @param      beginIndex   the beginning index, inclusive.
+     * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
+     * @return     the unsigned {@code int} represented by the subsequence in
+     *             the specified radix.
+     * @throws     NullPointerException  if {@code s} is null.
+     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
+     *             negative, or if {@code beginIndex} is greater than
+     *             {@code endIndex} or if {@code endIndex} is greater than
+     *             {@code s.length()}.
+     * @throws     NumberFormatException  if the {@code CharSequence} does not
+     *             contain a parsable unsigned {@code int} in the specified
+     *             {@code radix}, or if {@code radix} is either smaller than
+     *             {@link java.lang.Character#MIN_RADIX} or larger than
+     *             {@link java.lang.Character#MAX_RADIX}.
+     * @since  9
+     */
+    public static int parseUnsignedInt(CharSequence s, int beginIndex, int endIndex, int radix)
+                throws NumberFormatException {
+        s = Objects.requireNonNull(s);
+
+        if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+        int start = beginIndex, len = endIndex - beginIndex;
+
+        if (len > 0) {
+            char firstChar = s.charAt(start);
+            if (firstChar == '-') {
+                throw new
+                    NumberFormatException(String.format("Illegal leading minus sign " +
+                                                       "on unsigned string %s.", s));
+            } else {
+                if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
+                        (radix == 10 && len <= 9)) { // Integer.MAX_VALUE in base 10 is 10 digits
+                    return parseInt(s, start, start + len, radix);
+                } else {
+                    long ell = Long.parseLong(s, start, start + len, radix);
+                    if ((ell & 0xffff_ffff_0000_0000L) == 0) {
+                        return (int) ell;
+                    } else {
+                        throw new
+                            NumberFormatException(String.format("String value %s exceeds " +
+                                                                "range of unsigned int.", s));
+                    }
+                }
+            }
+        } else {
+            throw new NumberFormatException("");
+        }
+    }
+
+    /**
      * Parses the string argument as an unsigned decimal integer. The
      * characters in the string must all be decimal digits, except
-     * that the first character may be an an ASCII plus sign {@code
+     * that the first character may be an ASCII plus sign {@code
      * '+'} ({@code '\u005Cu002B'}). The resulting integer value
      * is returned, exactly as if the argument and the radix 10 were
      * given as arguments to the {@link
@@ -809,19 +1086,20 @@
      * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
      * During VM initialization, java.lang.Integer.IntegerCache.high property
      * may be set and saved in the private system properties in the
-     * sun.misc.VM class.
+     * jdk.internal.misc.VM class.
      */
 
     private static class IntegerCache {
         static final int low = -128;
         static final int high;
-        static final Integer cache[];
+        static final Integer[] cache;
+        static Integer[] archivedCache;
 
         static {
             // high value may be configured by property
             int h = 127;
             String integerCacheHighPropValue =
-                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
+                VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
             if (integerCacheHighPropValue != null) {
                 try {
                     int i = parseInt(integerCacheHighPropValue);
@@ -834,11 +1112,20 @@
             }
             high = h;
 
-            cache = new Integer[(high - low) + 1];
-            int j = low;
-            for(int k = 0; k < cache.length; k++)
-                cache[k] = new Integer(j++);
+            // Load IntegerCache.archivedCache from archive, if possible
+            // Android-removed: VM.initializeFromArchive isn't supported yet.
+            // VM.initializeFromArchive(IntegerCache.class);
+            int size = (high - low) + 1;
 
+            // Use the archived cache if it exists and is large enough
+            if (archivedCache == null || size > archivedCache.length) {
+                Integer[] c = new Integer[size];
+                int j = low;
+                for(int k = 0; k < c.length; k++)
+                    c[k] = new Integer(j++);
+                archivedCache = c;
+            }
+            cache = archivedCache;
             // range [-128, 127] must be interned (JLS7 5.1.7)
             assert IntegerCache.high >= 127;
         }
@@ -861,6 +1148,7 @@
      * @return an {@code Integer} instance representing {@code i}.
      * @since  1.5
      */
+    @HotSpotIntrinsicCandidate
     public static Integer valueOf(int i) {
         if (i >= IntegerCache.low && i <= IntegerCache.high)
             return IntegerCache.cache[i + (-IntegerCache.low)];
@@ -880,7 +1168,13 @@
      *
      * @param   value   the value to be represented by the
      *                  {@code Integer} object.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(int)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Integer(int value) {
         this.value = value;
     }
@@ -892,12 +1186,17 @@
      * {@code int} value in exactly the manner used by the
      * {@code parseInt} method for radix 10.
      *
-     * @param      s   the {@code String} to be converted to an
-     *                 {@code Integer}.
-     * @exception  NumberFormatException  if the {@code String} does not
-     *               contain a parsable integer.
-     * @see        java.lang.Integer#parseInt(java.lang.String, int)
+     * @param   s   the {@code String} to be converted to an {@code Integer}.
+     * @throws      NumberFormatException if the {@code String} does not
+     *              contain a parsable integer.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseInt(String)} to convert a string to a
+     * {@code int} primitive, or use {@link #valueOf(String)}
+     * to convert a string to an {@code Integer} object.
      */
+    @Deprecated(since="9")
     public Integer(String s) throws NumberFormatException {
         this.value = parseInt(s, 10);
     }
@@ -924,6 +1223,7 @@
      * Returns the value of this {@code Integer} as an
      * {@code int}.
      */
+    @HotSpotIntrinsicCandidate
     public int intValue() {
         return value;
     }
@@ -983,13 +1283,13 @@
     }
 
     /**
-     * Returns a hash code for a {@code int} value; compatible with
+     * Returns a hash code for an {@code int} value; compatible with
      * {@code Integer.hashCode()}.
      *
      * @param value the value to hash
      * @since 1.8
      *
-     * @return a hash code value for a {@code int} value.
+     * @return a hash code value for an {@code int} value.
      */
     public static int hashCode(int value) {
         return value;
@@ -1193,7 +1493,7 @@
         boolean negative = false;
         Integer result;
 
-        if (nm.length() == 0)
+        if (nm.isEmpty())
             throw new NumberFormatException("Zero length string");
         char firstChar = nm.charAt(0);
         // Handle sign, if present
@@ -1358,7 +1658,7 @@
     @Native public static final int SIZE = 32;
 
     /**
-     * The number of bytes used to represent a {@code int} value in two's
+     * The number of bytes used to represent an {@code int} value in two's
      * complement binary form.
      *
      * @since 1.8
@@ -1379,13 +1679,7 @@
      * @since 1.5
      */
     public static int highestOneBit(int i) {
-        // HD, Figure 3-1
-        i |= (i >>  1);
-        i |= (i >>  2);
-        i |= (i >>  4);
-        i |= (i >>  8);
-        i |= (i >> 16);
-        return i - (i >>> 1);
+        return i & (MIN_VALUE >>> numberOfLeadingZeros(i));
     }
 
     /**
@@ -1427,17 +1721,17 @@
      *     is equal to zero.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static int numberOfLeadingZeros(int i) {
-        // HD, Figure 5-6
-        if (i == 0)
-            return 32;
-        int n = 1;
-        if (i >>> 16 == 0) { n += 16; i <<= 16; }
-        if (i >>> 24 == 0) { n +=  8; i <<=  8; }
-        if (i >>> 28 == 0) { n +=  4; i <<=  4; }
-        if (i >>> 30 == 0) { n +=  2; i <<=  2; }
-        n -= i >>> 31;
-        return n;
+        // HD, Count leading 0's
+        if (i <= 0)
+            return i == 0 ? 32 : 0;
+        int n = 31;
+        if (i >= 1 << 16) { n -= 16; i >>>= 16; }
+        if (i >= 1 <<  8) { n -=  8; i >>>=  8; }
+        if (i >= 1 <<  4) { n -=  4; i >>>=  4; }
+        if (i >= 1 <<  2) { n -=  2; i >>>=  2; }
+        return n - (i >>> 1);
     }
 
     /**
@@ -1454,6 +1748,7 @@
      *     to zero.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static int numberOfTrailingZeros(int i) {
         // HD, Figure 5-14
         int y;
@@ -1476,6 +1771,7 @@
      *     representation of the specified {@code int} value.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static int bitCount(int i) {
         // HD, Figure 5-2
         i = i - ((i >>> 1) & 0x55555555);
@@ -1549,9 +1845,8 @@
         i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
         i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
         i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
-        i = (i << 24) | ((i & 0xff00) << 8) |
-            ((i >>> 8) & 0xff00) | (i >>> 24);
-        return i;
+
+        return reverseBytes(i);
     }
 
     /**
@@ -1577,11 +1872,12 @@
      *     {@code int} value.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static int reverseBytes(int i) {
-        return ((i >>> 24)           ) |
-               ((i >>   8) &   0xFF00) |
-               ((i <<   8) & 0xFF0000) |
-               ((i << 24));
+        return (i << 24)            |
+               ((i & 0xff00) << 8)  |
+               ((i >>> 8) & 0xff00) |
+               (i >>> 24);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/lang/InternalError.java b/ojluni/src/main/java/java/lang/InternalError.java
index 8d33821..69ce7f7 100644
--- a/ojluni/src/main/java/java/lang/InternalError.java
+++ b/ojluni/src/main/java/java/lang/InternalError.java
@@ -30,7 +30,7 @@
  * the Java Virtual Machine.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public class InternalError extends VirtualMachineError {
     private static final long serialVersionUID = -9062593416125562365L;
diff --git a/ojluni/src/main/java/java/lang/InterruptedException.java b/ojluni/src/main/java/java/lang/InterruptedException.java
index 27bc5a8..2c649bd 100644
--- a/ojluni/src/main/java/java/lang/InterruptedException.java
+++ b/ojluni/src/main/java/java/lang/InterruptedException.java
@@ -44,7 +44,7 @@
  * @see     java.lang.Thread#sleep(long)
  * @see     java.lang.Thread#interrupt()
  * @see     java.lang.Thread#interrupted()
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class InterruptedException extends Exception {
diff --git a/ojluni/src/main/java/java/lang/Iterable.java b/ojluni/src/main/java/java/lang/Iterable.java
index 0928c81..a58faa4 100644
--- a/ojluni/src/main/java/java/lang/Iterable.java
+++ b/ojluni/src/main/java/java/lang/Iterable.java
@@ -31,16 +31,13 @@
 import java.util.function.Consumer;
 
 /**
- * Implementing this interface allows an object to be the target of
- * the "for-each loop" statement. See
- * <strong>
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/language/foreach.html">For-each Loop</a>
- * </strong>
+ * Implementing this interface allows an object to be the target of the enhanced
+ * {@code for} statement (sometimes called the "for-each loop" statement).
  *
  * @param <T> the type of elements returned by the iterator
  *
  * @since 1.5
- * @jls 14.14.2 The enhanced for statement
+ * @jls 14.14.2 The enhanced {@code for} statement
  */
 public interface Iterable<T> {
     /**
@@ -53,10 +50,13 @@
     /**
      * Performs the given action for each element of the {@code Iterable}
      * until all elements have been processed or the action throws an
-     * exception.  Unless otherwise specified by the implementing class,
-     * actions are performed in the order of iteration (if an iteration order
-     * is specified).  Exceptions thrown by the action are relayed to the
+     * exception.  Actions are performed in the order of iteration, if that
+     * order is specified.  Exceptions thrown by the action are relayed to the
      * caller.
+     * <p>
+     * The behavior of this method is unspecified if the action performs
+     * side-effects that modify the underlying source of elements, unless an
+     * overriding class has specified a concurrent modification policy.
      *
      * @implSpec
      * <p>The default implementation behaves as if:
@@ -82,7 +82,7 @@
      *
      * @implSpec
      * The default implementation creates an
-     * <em><a href="Spliterator.html#binding">early-binding</a></em>
+     * <em><a href="../util/Spliterator.html#binding">early-binding</a></em>
      * spliterator from the iterable's {@code Iterator}.  The spliterator
      * inherits the <em>fail-fast</em> properties of the iterable's iterator.
      *
diff --git a/ojluni/src/main/java/java/lang/LinkageError.java b/ojluni/src/main/java/java/lang/LinkageError.java
index 6b5f060..4dbc784 100644
--- a/ojluni/src/main/java/java/lang/LinkageError.java
+++ b/ojluni/src/main/java/java/lang/LinkageError.java
@@ -32,7 +32,7 @@
  *
  *
  * @author  Frank Yellin
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class LinkageError extends Error {
diff --git a/ojluni/src/main/java/java/lang/Long.java b/ojluni/src/main/java/java/lang/Long.java
index 0047125..74c10a0 100644
--- a/ojluni/src/main/java/java/lang/Long.java
+++ b/ojluni/src/main/java/java/lang/Long.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
 
 import java.lang.annotation.Native;
 import java.math.*;
+import java.util.Objects;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 
 /**
@@ -50,7 +52,7 @@
  * @author  Arthur van Hoff
  * @author  Josh Bloch
  * @author  Joseph D. Darcy
- * @since   JDK1.0
+ * @since   1.0
  */
 public final class Long extends Number implements Comparable<Long> {
     /**
@@ -69,7 +71,7 @@
      * The {@code Class} instance representing the primitive type
      * {@code long}.
      *
-     * @since   JDK1.1
+     * @since   1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Long>     TYPE = (Class<Long>) Class.getPrimitiveClass("long");
@@ -123,26 +125,58 @@
             radix = 10;
         if (radix == 10)
             return toString(i);
-        char[] buf = new char[65];
+
+        // BEGIN Android-changed: Use single-byte chars.
+        /*
+        if (COMPACT_STRINGS) {
+         */
+            byte[] buf = new byte[65];
+            int charPos = 64;
+            boolean negative = (i < 0);
+
+            if (!negative) {
+                i = -i;
+            }
+
+            while (i <= -radix) {
+                buf[charPos--] = (byte)Integer.digits[(int)(-(i % radix))];
+                i = i / radix;
+            }
+            buf[charPos] = (byte)Integer.digits[(int)(-i)];
+
+            if (negative) {
+                buf[--charPos] = '-';
+            }
+        /*
+            return StringLatin1.newString(buf, charPos, (65 - charPos));
+        }
+        return toStringUTF16(i, radix);
+         */
+        return new String(buf, charPos, (65 - charPos));
+        // END Android-changed: Use single-byte chars.
+    }
+
+    // BEGIN Android-removed: UTF16 version of toString(long i, int radix).
+    /*
+    private static String toStringUTF16(long i, int radix) {
+        byte[] buf = new byte[65 * 2];
         int charPos = 64;
         boolean negative = (i < 0);
-
         if (!negative) {
             i = -i;
         }
-
         while (i <= -radix) {
-            buf[charPos--] = Integer.digits[(int)(-(i % radix))];
+            StringUTF16.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]);
             i = i / radix;
         }
-        buf[charPos] = Integer.digits[(int)(-i)];
-
+        StringUTF16.putChar(buf, charPos, Integer.digits[(int)(-i)]);
         if (negative) {
-            buf[--charPos] = '-';
+            StringUTF16.putChar(buf, --charPos, '-');
         }
-
-        return new String(buf, charPos, (65 - charPos));
+        return StringUTF16.newString(buf, charPos, (65 - charPos));
     }
+     */
+    // END Android-removed: UTF16 version of toString(long i, int radix).
 
     /**
      * Returns a string representation of the first argument as an
@@ -267,7 +301,7 @@
      *          (base&nbsp;16).
      * @see #parseUnsignedLong(String, int)
      * @see #toUnsignedString(long, int)
-     * @since   JDK 1.0.2
+     * @since   1.0.2
      */
     public static String toHexString(long i) {
         return toUnsignedString0(i, 4);
@@ -306,7 +340,7 @@
      *          value represented by the argument in octal (base&nbsp;8).
      * @see #parseUnsignedLong(String, int)
      * @see #toUnsignedString(long, int)
-     * @since   JDK 1.0.2
+     * @since   1.0.2
      */
     public static String toOctalString(long i) {
         return toUnsignedString0(i, 3);
@@ -339,7 +373,7 @@
      *          value represented by the argument in binary (base&nbsp;2).
      * @see #parseUnsignedLong(String, int)
      * @see #toUnsignedString(long, int)
-     * @since   JDK 1.0.2
+     * @since   1.0.2
      */
     public static String toBinaryString(long i) {
         return toUnsignedString0(i, 1);
@@ -354,35 +388,63 @@
         // assert shift > 0 && shift <=5 : "Illegal shift value";
         int mag = Long.SIZE - Long.numberOfLeadingZeros(val);
         int chars = Math.max(((mag + (shift - 1)) / shift), 1);
-        char[] buf = new char[chars];
 
-        formatUnsignedLong(val, shift, buf, 0, chars);
-        // Android-changed: Use regular constructor instead of one which takes over "buf".
-        // return new String(buf, true);
+        // BEGIN Android-changed: Use single-byte chars.
+        /*
+        if (COMPACT_STRINGS) {
+         */
+            byte[] buf = new byte[chars];
+            formatUnsignedLong0(val, shift, buf, 0, chars);
+        /*
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[chars * 2];
+            formatUnsignedLong0UTF16(val, shift, buf, 0, chars);
+            return new String(buf, UTF16);
+        }
+        */
         return new String(buf);
+        // END Android-changed: Use single-byte chars.
     }
 
     /**
-     * Format a long (treated as unsigned) into a character buffer.
+     * Format a long (treated as unsigned) into a character buffer. If
+     * {@code len} exceeds the formatted ASCII representation of {@code val},
+     * {@code buf} will be padded with leading zeroes.
+     *
      * @param val the unsigned long to format
      * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary)
      * @param buf the character buffer to write to
      * @param offset the offset in the destination buffer to start at
      * @param len the number of characters to write
-     * @return the lowest character location used
      */
-     static int formatUnsignedLong(long val, int shift, char[] buf, int offset, int len) {
-        int charPos = len;
+
+    /** byte[]/LATIN1 version    */
+    static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
         int radix = 1 << shift;
         int mask = radix - 1;
         do {
-            buf[offset + --charPos] = Integer.digits[((int) val) & mask];
+            buf[--charPos] = (byte)Integer.digits[((int) val) & mask];
             val >>>= shift;
-        } while (val != 0 && charPos > 0);
-
-        return charPos;
+        } while (charPos > offset);
     }
 
+    // BEGIN Android-removed: UTF16 version of formatUnsignedLong0().
+    /*
+    /** byte[]/UTF16 version    *
+    private static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
+        int charPos = offset + len;
+        int radix = 1 << shift;
+        int mask = radix - 1;
+        do {
+            StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]);
+            val >>>= shift;
+        } while (charPos > offset);
+    }
+     */
+    // END Android-removed: UTF16 version of formatUnsignedLong0().
+
     /**
      * Returns a {@code String} object representing the specified
      * {@code long}.  The argument is converted to signed decimal
@@ -394,14 +456,23 @@
      * @return  a string representation of the argument in base&nbsp;10.
      */
     public static String toString(long i) {
-        if (i == Long.MIN_VALUE)
-            return "-9223372036854775808";
-        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-        char[] buf = new char[size];
-        getChars(i, size, buf);
-        // Android-changed: Use regular constructor instead of one which takes over "buf".
-        // return new String(buf, true);
+        int size = stringSize(i);
+        // BEGIN Android-changed: Always use single-byte buffer.
+        /*
+        if (COMPACT_STRINGS) {
+         */
+            byte[] buf = new byte[size];
+            getChars(i, size, buf);
+        /*
+            return new String(buf, LATIN1);
+        } else {
+            byte[] buf = new byte[size * 2];
+            StringUTF16.getChars(i, size, buf);
+            return new String(buf, UTF16);
+        }
+         */
         return new String(buf);
+        // END Android-changed: Always use single-byte buffer.
     }
 
     /**
@@ -423,30 +494,36 @@
     }
 
     /**
-     * Places characters representing the integer i into the
+     * Places characters representing the long i into the
      * character array buf. The characters are placed into
      * the buffer backwards starting with the least significant
      * digit at the specified index (exclusive), and working
      * backwards from there.
      *
-     * Will fail if i == Long.MIN_VALUE
+     * @implNote This method converts positive inputs into negative
+     * values, to cover the Long.MIN_VALUE case. Converting otherwise
+     * (negative to positive) will expose -Long.MIN_VALUE that overflows
+     * long.
+     *
+     * @param i     value to convert
+     * @param index next index, after the least significant digit
+     * @param buf   target buffer, Latin1-encoded
+     * @return index of the most significant digit or minus sign, if present
      */
-    static void getChars(long i, int index, char[] buf) {
+    static int getChars(long i, int index, byte[] buf) {
         long q;
         int r;
         int charPos = index;
-        char sign = 0;
 
-        if (i < 0) {
-            sign = '-';
+        boolean negative = (i < 0);
+        if (!negative) {
             i = -i;
         }
 
         // Get 2 digits/iteration using longs until quotient fits into an int
-        while (i > Integer.MAX_VALUE) {
+        while (i <= Integer.MIN_VALUE) {
             q = i / 100;
-            // really: r = i - (q * 100);
-            r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
+            r = (int)((q * 100) - i);
             i = q;
             buf[--charPos] = Integer.DigitOnes[r];
             buf[--charPos] = Integer.DigitTens[r];
@@ -455,38 +532,103 @@
         // Get 2 digits/iteration using ints
         int q2;
         int i2 = (int)i;
-        while (i2 >= 65536) {
+        while (i2 <= -100) {
             q2 = i2 / 100;
-            // really: r = i2 - (q * 100);
-            r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
+            r  = (q2 * 100) - i2;
             i2 = q2;
             buf[--charPos] = Integer.DigitOnes[r];
             buf[--charPos] = Integer.DigitTens[r];
         }
 
-        // Fall thru to fast mode for smaller numbers
-        // assert(i2 <= 65536, i2);
-        for (;;) {
-            q2 = (i2 * 52429) >>> (16+3);
-            r = i2 - ((q2 << 3) + (q2 << 1));  // r = i2-(q2*10) ...
-            buf[--charPos] = Integer.digits[r];
-            i2 = q2;
-            if (i2 == 0) break;
+        // We know there are at most two digits left at this point.
+        q2 = i2 / 10;
+        r  = (q2 * 10) - i2;
+        buf[--charPos] = (byte)('0' + r);
+
+        // Whatever left is the remaining digit.
+        if (q2 < 0) {
+            buf[--charPos] = (byte)('0' - q2);
         }
-        if (sign != 0) {
-            buf[--charPos] = sign;
+
+        if (negative) {
+            buf[--charPos] = (byte)'-';
         }
+        return charPos;
     }
 
-    // Requires positive x
-    static int stringSize(long x) {
-        long p = 10;
-        for (int i=1; i<19; i++) {
-            if (x < p)
-                return i;
-            p = 10*p;
+    // BEGIN Android-added: char version of getChars(long i, int index, byte[] buf).
+    // for java.lang.AbstractStringBuilder#append(int).
+    static int getChars(long i, int index, char[] buf) {
+        long q;
+        int r;
+        int charPos = index;
+
+        boolean negative = (i < 0);
+        if (!negative) {
+            i = -i;
         }
-        return 19;
+
+        // Get 2 digits/iteration using longs until quotient fits into an int
+        while (i <= Integer.MIN_VALUE) {
+            q = i / 100;
+            r = (int)((q * 100) - i);
+            i = q;
+            buf[--charPos] = (char)Integer.DigitOnes[r];
+            buf[--charPos] = (char)Integer.DigitTens[r];
+        }
+
+        // Get 2 digits/iteration using ints
+        int q2;
+        int i2 = (int)i;
+        while (i2 <= -100) {
+            q2 = i2 / 100;
+            r  = (q2 * 100) - i2;
+            i2 = q2;
+            buf[--charPos] = (char)Integer.DigitOnes[r];
+            buf[--charPos] = (char)Integer.DigitTens[r];
+        }
+
+        // We know there are at most two digits left at this point.
+        q2 = i2 / 10;
+        r  = (q2 * 10) - i2;
+        buf[--charPos] = (char)('0' + r);
+
+        // Whatever left is the remaining digit.
+        if (q2 < 0) {
+            buf[--charPos] = (char)('0' - q2);
+        }
+
+        if (negative) {
+            buf[--charPos] = (byte)'-';
+        }
+        return charPos;
+    }
+    // END Android-added: char version of getChars(long i, int index, byte[] buf).
+
+    /**
+     * Returns the string representation size for a given long value.
+     *
+     * @param x long value
+     * @return string size
+     *
+     * @implNote There are other ways to compute this: e.g. binary search,
+     * but values are biased heavily towards zero, and therefore linear search
+     * wins. The iteration results are also routinely inlined in the generated
+     * code after loop unrolling.
+     */
+    static int stringSize(long x) {
+        int d = 1;
+        if (x >= 0) {
+            d = 0;
+            x = -x;
+        }
+        long p = -10;
+        for (int i = 1; i < 19; i++) {
+            if (x > p)
+                return i + d;
+            p = 10 * p;
+        }
+        return 19 + d;
     }
 
     /**
@@ -566,12 +708,9 @@
                                             " greater than Character.MAX_RADIX");
         }
 
-        long result = 0;
         boolean negative = false;
         int i = 0, len = s.length();
         long limit = -Long.MAX_VALUE;
-        long multmin;
-        int digit;
 
         if (len > 0) {
             char firstChar = s.charAt(0);
@@ -579,21 +718,21 @@
                 if (firstChar == '-') {
                     negative = true;
                     limit = Long.MIN_VALUE;
-                } else if (firstChar != '+')
-                    throw NumberFormatException.forInputString(s);
-
-                if (len == 1) // Cannot have lone "+" or "-"
-                    throw NumberFormatException.forInputString(s);
-                i++;
-            }
-            multmin = limit / radix;
-            while (i < len) {
-                // Accumulating negatively avoids surprises near MAX_VALUE
-                digit = Character.digit(s.charAt(i++),radix);
-                if (digit < 0) {
+                } else if (firstChar != '+') {
                     throw NumberFormatException.forInputString(s);
                 }
-                if (result < multmin) {
+
+                if (len == 1) { // Cannot have lone "+" or "-"
+                    throw NumberFormatException.forInputString(s);
+                }
+                i++;
+            }
+            long multmin = limit / radix;
+            long result = 0;
+            while (i < len) {
+                // Accumulating negatively avoids surprises near MAX_VALUE
+                int digit = Character.digit(s.charAt(i++),radix);
+                if (digit < 0 || result < multmin) {
                     throw NumberFormatException.forInputString(s);
                 }
                 result *= radix;
@@ -602,10 +741,96 @@
                 }
                 result -= digit;
             }
+            return negative ? result : -result;
         } else {
             throw NumberFormatException.forInputString(s);
         }
-        return negative ? result : -result;
+    }
+
+    /**
+     * Parses the {@link CharSequence} argument as a signed {@code long} in
+     * the specified {@code radix}, beginning at the specified
+     * {@code beginIndex} and extending to {@code endIndex - 1}.
+     *
+     * <p>The method does not take steps to guard against the
+     * {@code CharSequence} being mutated while parsing.
+     *
+     * @param      s   the {@code CharSequence} containing the {@code long}
+     *                  representation to be parsed
+     * @param      beginIndex   the beginning index, inclusive.
+     * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
+     * @return     the signed {@code long} represented by the subsequence in
+     *             the specified radix.
+     * @throws     NullPointerException  if {@code s} is null.
+     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
+     *             negative, or if {@code beginIndex} is greater than
+     *             {@code endIndex} or if {@code endIndex} is greater than
+     *             {@code s.length()}.
+     * @throws     NumberFormatException  if the {@code CharSequence} does not
+     *             contain a parsable {@code int} in the specified
+     *             {@code radix}, or if {@code radix} is either smaller than
+     *             {@link java.lang.Character#MIN_RADIX} or larger than
+     *             {@link java.lang.Character#MAX_RADIX}.
+     * @since  9
+     */
+    public static long parseLong(CharSequence s, int beginIndex, int endIndex, int radix)
+                throws NumberFormatException {
+        s = Objects.requireNonNull(s);
+
+        if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (radix < Character.MIN_RADIX) {
+            throw new NumberFormatException("radix " + radix +
+                    " less than Character.MIN_RADIX");
+        }
+        if (radix > Character.MAX_RADIX) {
+            throw new NumberFormatException("radix " + radix +
+                    " greater than Character.MAX_RADIX");
+        }
+
+        boolean negative = false;
+        int i = beginIndex;
+        long limit = -Long.MAX_VALUE;
+
+        if (i < endIndex) {
+            char firstChar = s.charAt(i);
+            if (firstChar < '0') { // Possible leading "+" or "-"
+                if (firstChar == '-') {
+                    negative = true;
+                    limit = Long.MIN_VALUE;
+                } else if (firstChar != '+') {
+                    throw NumberFormatException.forCharSequence(s, beginIndex,
+                            endIndex, i);
+                }
+                i++;
+            }
+            if (i >= endIndex) { // Cannot have lone "+", "-" or ""
+                throw NumberFormatException.forCharSequence(s, beginIndex,
+                        endIndex, i);
+            }
+            long multmin = limit / radix;
+            long result = 0;
+            while (i < endIndex) {
+                // Accumulating negatively avoids surprises near MAX_VALUE
+                int digit = Character.digit(s.charAt(i), radix);
+                if (digit < 0 || result < multmin) {
+                    throw NumberFormatException.forCharSequence(s, beginIndex,
+                            endIndex, i);
+                }
+                result *= radix;
+                if (result < limit + digit) {
+                    throw NumberFormatException.forCharSequence(s, beginIndex,
+                            endIndex, i);
+                }
+                i++;
+                result -= digit;
+            }
+            return negative ? result : -result;
+        } else {
+            throw new NumberFormatException("");
+        }
     }
 
     /**
@@ -699,27 +924,64 @@
                 }
 
                 // No need for range checks on len due to testing above.
-                long first = parseLong(s.substring(0, len - 1), radix);
+                long first = parseLong(s, 0, len - 1, radix);
                 int second = Character.digit(s.charAt(len - 1), radix);
                 if (second < 0) {
                     throw new NumberFormatException("Bad digit at end of " + s);
                 }
                 long result = first * radix + second;
-                if (compareUnsigned(result, first) < 0) {
+
+                /*
+                 * Test leftmost bits of multiprecision extension of first*radix
+                 * for overflow. The number of bits needed is defined by
+                 * GUARD_BIT = ceil(log2(Character.MAX_RADIX)) + 1 = 7. Then
+                 * int guard = radix*(int)(first >>> (64 - GUARD_BIT)) and
+                 * overflow is tested by splitting guard in the ranges
+                 * guard < 92, 92 <= guard < 128, and 128 <= guard, where
+                 * 92 = 128 - Character.MAX_RADIX. Note that guard cannot take
+                 * on a value which does not include a prime factor in the legal
+                 * radix range.
+                 */
+                int guard = radix * (int) (first >>> 57);
+                if (guard >= 128 ||
+                    (result >= 0 && guard >= 128 - Character.MAX_RADIX)) {
                     /*
-                     * The maximum unsigned value, (2^64)-1, takes at
-                     * most one more digit to represent than the
-                     * maximum signed value, (2^63)-1.  Therefore,
-                     * parsing (len - 1) digits will be appropriately
-                     * in-range of the signed parsing.  In other
-                     * words, if parsing (len -1) digits overflows
-                     * signed parsing, parsing len digits will
-                     * certainly overflow unsigned parsing.
+                     * For purposes of exposition, the programmatic statements
+                     * below should be taken to be multi-precision, i.e., not
+                     * subject to overflow.
                      *
-                     * The compareUnsigned check above catches
-                     * situations where an unsigned overflow occurs
-                     * incorporating the contribution of the final
-                     * digit.
+                     * A) Condition guard >= 128:
+                     * If guard >= 128 then first*radix >= 2^7 * 2^57 = 2^64
+                     * hence always overflow.
+                     *
+                     * B) Condition guard < 92:
+                     * Define left7 = first >>> 57.
+                     * Given first = (left7 * 2^57) + (first & (2^57 - 1)) then
+                     * result <= (radix*left7)*2^57 + radix*(2^57 - 1) + second.
+                     * Thus if radix*left7 < 92, radix <= 36, and second < 36,
+                     * then result < 92*2^57 + 36*(2^57 - 1) + 36 = 2^64 hence
+                     * never overflow.
+                     *
+                     * C) Condition 92 <= guard < 128:
+                     * first*radix + second >= radix*left7*2^57 + second
+                     * so that first*radix + second >= 92*2^57 + 0 > 2^63
+                     *
+                     * D) Condition guard < 128:
+                     * radix*first <= (radix*left7) * 2^57 + radix*(2^57 - 1)
+                     * so
+                     * radix*first + second <= (radix*left7) * 2^57 + radix*(2^57 - 1) + 36
+                     * thus
+                     * radix*first + second < 128 * 2^57 + 36*2^57 - radix + 36
+                     * whence
+                     * radix*first + second < 2^64 + 2^6*2^57 = 2^64 + 2^63
+                     *
+                     * E) Conditions C, D, and result >= 0:
+                     * C and D combined imply the mathematical result
+                     * 2^63 < first*radix + second < 2^64 + 2^63. The lower
+                     * bound is therefore negative as a signed long, but the
+                     * upper bound is too small to overflow again after the
+                     * signed long overflows to positive above 2^64 - 1. Hence
+                     * result >= 0 implies overflow given C and D.
                      */
                     throw new NumberFormatException(String.format("String value %s exceeds " +
                                                                   "range of unsigned long.", s));
@@ -732,9 +994,127 @@
     }
 
     /**
+     * Parses the {@link CharSequence} argument as an unsigned {@code long} in
+     * the specified {@code radix}, beginning at the specified
+     * {@code beginIndex} and extending to {@code endIndex - 1}.
+     *
+     * <p>The method does not take steps to guard against the
+     * {@code CharSequence} being mutated while parsing.
+     *
+     * @param      s   the {@code CharSequence} containing the unsigned
+     *                 {@code long} representation to be parsed
+     * @param      beginIndex   the beginning index, inclusive.
+     * @param      endIndex     the ending index, exclusive.
+     * @param      radix   the radix to be used while parsing {@code s}.
+     * @return     the unsigned {@code long} represented by the subsequence in
+     *             the specified radix.
+     * @throws     NullPointerException  if {@code s} is null.
+     * @throws     IndexOutOfBoundsException  if {@code beginIndex} is
+     *             negative, or if {@code beginIndex} is greater than
+     *             {@code endIndex} or if {@code endIndex} is greater than
+     *             {@code s.length()}.
+     * @throws     NumberFormatException  if the {@code CharSequence} does not
+     *             contain a parsable unsigned {@code long} in the specified
+     *             {@code radix}, or if {@code radix} is either smaller than
+     *             {@link java.lang.Character#MIN_RADIX} or larger than
+     *             {@link java.lang.Character#MAX_RADIX}.
+     * @since  9
+     */
+    public static long parseUnsignedLong(CharSequence s, int beginIndex, int endIndex, int radix)
+                throws NumberFormatException {
+        s = Objects.requireNonNull(s);
+
+        if (beginIndex < 0 || beginIndex > endIndex || endIndex > s.length()) {
+            throw new IndexOutOfBoundsException();
+        }
+        int start = beginIndex, len = endIndex - beginIndex;
+
+        if (len > 0) {
+            char firstChar = s.charAt(start);
+            if (firstChar == '-') {
+                throw new NumberFormatException(String.format("Illegal leading minus sign " +
+                        "on unsigned string %s.", s.subSequence(start, start + len)));
+            } else {
+                if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
+                    (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits
+                    return parseLong(s, start, start + len, radix);
+                }
+
+                // No need for range checks on end due to testing above.
+                long first = parseLong(s, start, start + len - 1, radix);
+                int second = Character.digit(s.charAt(start + len - 1), radix);
+                if (second < 0) {
+                    throw new NumberFormatException("Bad digit at end of " +
+                            s.subSequence(start, start + len));
+                }
+                long result = first * radix + second;
+
+                /*
+                 * Test leftmost bits of multiprecision extension of first*radix
+                 * for overflow. The number of bits needed is defined by
+                 * GUARD_BIT = ceil(log2(Character.MAX_RADIX)) + 1 = 7. Then
+                 * int guard = radix*(int)(first >>> (64 - GUARD_BIT)) and
+                 * overflow is tested by splitting guard in the ranges
+                 * guard < 92, 92 <= guard < 128, and 128 <= guard, where
+                 * 92 = 128 - Character.MAX_RADIX. Note that guard cannot take
+                 * on a value which does not include a prime factor in the legal
+                 * radix range.
+                 */
+                int guard = radix * (int) (first >>> 57);
+                if (guard >= 128 ||
+                        (result >= 0 && guard >= 128 - Character.MAX_RADIX)) {
+                    /*
+                     * For purposes of exposition, the programmatic statements
+                     * below should be taken to be multi-precision, i.e., not
+                     * subject to overflow.
+                     *
+                     * A) Condition guard >= 128:
+                     * If guard >= 128 then first*radix >= 2^7 * 2^57 = 2^64
+                     * hence always overflow.
+                     *
+                     * B) Condition guard < 92:
+                     * Define left7 = first >>> 57.
+                     * Given first = (left7 * 2^57) + (first & (2^57 - 1)) then
+                     * result <= (radix*left7)*2^57 + radix*(2^57 - 1) + second.
+                     * Thus if radix*left7 < 92, radix <= 36, and second < 36,
+                     * then result < 92*2^57 + 36*(2^57 - 1) + 36 = 2^64 hence
+                     * never overflow.
+                     *
+                     * C) Condition 92 <= guard < 128:
+                     * first*radix + second >= radix*left7*2^57 + second
+                     * so that first*radix + second >= 92*2^57 + 0 > 2^63
+                     *
+                     * D) Condition guard < 128:
+                     * radix*first <= (radix*left7) * 2^57 + radix*(2^57 - 1)
+                     * so
+                     * radix*first + second <= (radix*left7) * 2^57 + radix*(2^57 - 1) + 36
+                     * thus
+                     * radix*first + second < 128 * 2^57 + 36*2^57 - radix + 36
+                     * whence
+                     * radix*first + second < 2^64 + 2^6*2^57 = 2^64 + 2^63
+                     *
+                     * E) Conditions C, D, and result >= 0:
+                     * C and D combined imply the mathematical result
+                     * 2^63 < first*radix + second < 2^64 + 2^63. The lower
+                     * bound is therefore negative as a signed long, but the
+                     * upper bound is too small to overflow again after the
+                     * signed long overflows to positive above 2^64 - 1. Hence
+                     * result >= 0 implies overflow given C and D.
+                     */
+                    throw new NumberFormatException(String.format("String value %s exceeds " +
+                            "range of unsigned long.", s.subSequence(start, start + len)));
+                }
+                return result;
+            }
+        } else {
+            throw NumberFormatException.forInputString("");
+        }
+    }
+
+    /**
      * Parses the string argument as an unsigned decimal {@code long}. The
      * characters in the string must all be decimal digits, except
-     * that the first character may be an an ASCII plus sign {@code
+     * that the first character may be an ASCII plus sign {@code
      * '+'} ({@code '\u005Cu002B'}). The resulting integer value
      * is returned, exactly as if the argument and the radix 10 were
      * given as arguments to the {@link
@@ -828,15 +1208,14 @@
      * significantly better space and time performance by caching
      * frequently requested values.
      *
-     * Note that unlike the {@linkplain Integer#valueOf(int)
-     * corresponding method} in the {@code Integer} class, this method
-     * is <em>not</em> required to cache values within a particular
-     * range.
+     * This method will always cache values in the range -128 to 127,
+     * inclusive, and may cache other values outside of this range.
      *
      * @param  l a long value.
      * @return a {@code Long} instance representing {@code l}.
      * @since  1.5
      */
+    @HotSpotIntrinsicCandidate
     public static Long valueOf(long l) {
         final int offset = 128;
         if (l >= -128 && l <= 127) { // will cache
@@ -894,7 +1273,7 @@
         boolean negative = false;
         Long result;
 
-        if (nm.length() == 0)
+        if (nm.isEmpty())
             throw new NumberFormatException("Zero length string");
         char firstChar = nm.charAt(0);
         // Handle sign, if present
@@ -948,7 +1327,13 @@
      *
      * @param   value   the value to be represented by the
      *          {@code Long} object.
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor. The static factory
+     * {@link #valueOf(long)} is generally a better choice, as it is
+     * likely to yield significantly better space and time performance.
      */
+    @Deprecated(since="9")
     public Long(long value) {
         this.value = value;
     }
@@ -964,8 +1349,14 @@
      *             {@code Long}.
      * @throws     NumberFormatException  if the {@code String} does not
      *             contain a parsable {@code long}.
-     * @see        java.lang.Long#parseLong(java.lang.String, int)
+     *
+     * @deprecated
+     * It is rarely appropriate to use this constructor.
+     * Use {@link #parseLong(String)} to convert a string to a
+     * {@code long} primitive, or use {@link #valueOf(String)}
+     * to convert a string to a {@code Long} object.
      */
+    @Deprecated(since="9")
     public Long(String s) throws NumberFormatException {
         this.value = parseLong(s, 10);
     }
@@ -1001,6 +1392,7 @@
      * Returns the value of this {@code Long} as a
      * {@code long} value.
      */
+    @HotSpotIntrinsicCandidate
     public long longValue() {
         return value;
     }
@@ -1369,14 +1761,7 @@
      * @since 1.5
      */
     public static long highestOneBit(long i) {
-        // HD, Figure 3-1
-        i |= (i >>  1);
-        i |= (i >>  2);
-        i |= (i >>  4);
-        i |= (i >>  8);
-        i |= (i >> 16);
-        i |= (i >> 32);
-        return i - (i >>> 1);
+        return i & (MIN_VALUE >>> numberOfLeadingZeros(i));
     }
 
     /**
@@ -1418,19 +1803,11 @@
      *     is equal to zero.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static int numberOfLeadingZeros(long i) {
-        // HD, Figure 5-6
-         if (i == 0)
-            return 64;
-        int n = 1;
         int x = (int)(i >>> 32);
-        if (x == 0) { n += 32; x = (int)i; }
-        if (x >>> 16 == 0) { n += 16; x <<= 16; }
-        if (x >>> 24 == 0) { n +=  8; x <<=  8; }
-        if (x >>> 28 == 0) { n +=  4; x <<=  4; }
-        if (x >>> 30 == 0) { n +=  2; x <<=  2; }
-        n -= x >>> 31;
-        return n;
+        return x == 0 ? 32 + Integer.numberOfLeadingZeros((int)i)
+                : Integer.numberOfLeadingZeros(x);
     }
 
     /**
@@ -1447,6 +1824,7 @@
      *     to zero.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static int numberOfTrailingZeros(long i) {
         // HD, Figure 5-14
         int x, y;
@@ -1470,8 +1848,9 @@
      *     representation of the specified {@code long} value.
      * @since 1.5
      */
+     @HotSpotIntrinsicCandidate
      public static int bitCount(long i) {
-        // HD, Figure 5-14
+        // HD, Figure 5-2
         i = i - ((i >>> 1) & 0x5555555555555555L);
         i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L);
         i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL;
@@ -1544,10 +1923,8 @@
         i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;
         i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;
         i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;
-        i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
-        i = (i << 48) | ((i & 0xffff0000L) << 16) |
-            ((i >>> 16) & 0xffff0000L) | (i >>> 48);
-        return i;
+
+        return reverseBytes(i);
     }
 
     /**
@@ -1573,6 +1950,7 @@
      *     {@code long} value.
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static long reverseBytes(long i) {
         i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
         return (i << 48) | ((i & 0xffff0000L) << 16) |
diff --git a/ojluni/src/main/java/java/lang/Math.java b/ojluni/src/main/java/java/lang/Math.java
index a04b951..ee695db 100644
--- a/ojluni/src/main/java/java/lang/Math.java
+++ b/ojluni/src/main/java/java/lang/Math.java
@@ -27,10 +27,12 @@
 package java.lang;
 
 import dalvik.annotation.optimization.CriticalNative;
-import java.util.Random;
 
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import java.math.BigDecimal;
+import java.util.Random;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 // Android-note: Document that the results from Math are based on libm's behavior.
 // For performance, Android implements many of the methods in this class in terms of the underlying
@@ -157,6 +159,14 @@
      * @param   a   an angle, in radians.
      * @return  the sine of the argument.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double sin(double a) {
+        return StrictMath.sin(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double sin(double a);
 
@@ -171,6 +181,14 @@
      * @param   a   an angle, in radians.
      * @return  the cosine of the argument.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double cos(double a) {
+        return StrictMath.cos(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double cos(double a);
 
@@ -187,6 +205,14 @@
      * @param   a   an angle, in radians.
      * @return  the tangent of the argument.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double tan(double a) {
+        return StrictMath.tan(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double tan(double a);
 
@@ -204,6 +230,13 @@
      * @param   a   the value whose arc sine is to be returned.
      * @return  the arc sine of the argument.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double asin(double a) {
+        return StrictMath.asin(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double asin(double a);
 
@@ -219,6 +252,13 @@
      * @param   a   the value whose arc cosine is to be returned.
      * @return  the arc cosine of the argument.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double acos(double a) {
+        return StrictMath.acos(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double acos(double a);
 
@@ -235,6 +275,13 @@
      * @param   a   the value whose arc tangent is to be returned.
      * @return  the arc tangent of the argument.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double atan(double a) {
+        return StrictMath.atan(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double atan(double a);
 
@@ -284,6 +331,14 @@
      * @return  the value <i>e</i><sup>{@code a}</sup>,
      *          where <i>e</i> is the base of the natural logarithms.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double exp(double a) {
+        return StrictMath.exp(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double exp(double a);
 
@@ -304,6 +359,14 @@
      * @return  the value ln&nbsp;{@code a}, the natural logarithm of
      *          {@code a}.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double log(double a) {
+        return StrictMath.log(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double log(double a);
 
@@ -328,6 +391,14 @@
      * @return  the base 10 logarithm of  {@code a}.
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double log10(double a) {
+        return StrictMath.log10(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double log10(double a);
 
@@ -348,6 +419,18 @@
      * @return  the positive square root of {@code a}.
      *          If the argument is NaN or less than zero, the result is NaN.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double sqrt(double a) {
+        return StrictMath.sqrt(a); // default impl. delegates to StrictMath
+                                   // Note that hardware sqrt instructions
+                                   // frequently can be directly used by JITs
+                                   // and should be much faster than doing
+                                   // Math.sqrt in software.
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double sqrt(double a);
 
@@ -378,6 +461,13 @@
      * @return  the cube root of {@code a}.
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double cbrt(double a) {
+        return StrictMath.cbrt(a);
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double cbrt(double a);
 
@@ -403,6 +493,13 @@
      * @return  the remainder when {@code f1} is divided by
      *          {@code f2}.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double IEEEremainder(double f1, double f2) {
+        return StrictMath.IEEEremainder(f1, f2); // delegate to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double IEEEremainder(double f1, double f2);
 
@@ -425,6 +522,14 @@
      *          floating-point value that is greater than or equal to
      *          the argument and is equal to a mathematical integer.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double ceil(double a) {
+        return StrictMath.ceil(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double ceil(double a);
 
@@ -443,6 +548,14 @@
      *          floating-point value that less than or equal to the argument
      *          and is equal to a mathematical integer.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double floor(double a) {
+        return StrictMath.floor(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double floor(double a);
 
@@ -461,6 +574,14 @@
      * @return  the closest floating-point value to {@code a} that is
      *          equal to a mathematical integer.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double rint(double a) {
+        return StrictMath.rint(a); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double rint(double a);
 
@@ -516,6 +637,14 @@
      *          in polar coordinates that corresponds to the point
      *          (<i>x</i>,&nbsp;<i>y</i>) in Cartesian coordinates.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double atan2(double y, double x) {
+        return StrictMath.atan2(y, x); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double atan2(double y, double x);
 
@@ -649,6 +778,14 @@
      * @param   b   the exponent.
      * @return  the value {@code a}<sup>{@code b}</sup>.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    @HotSpotIntrinsicCandidate
+    public static double pow(double a, double b) {
+        return StrictMath.pow(a, b); // default impl. delegates to StrictMath
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double pow(double a, double b);
 
@@ -773,8 +910,19 @@
      * pseudorandom numbers at a great rate, it may reduce contention
      * for each thread to have its own pseudorandom-number generator.
      *
+     * @apiNote
+     * As the largest {@code double} value less than {@code 1.0}
+     * is {@code Math.nextDown(1.0)}, a value {@code x} in the closed range
+     * {@code [x1,x2]} where {@code x1<=x2} may be defined by the statements
+     *
+     * <blockquote><pre>{@code
+     * double f = Math.random()/Math.nextDown(1.0);
+     * double x = x1*(1.0 - f) + x2*f;
+     * }</pre></blockquote>
+     *
      * @return  a pseudorandom {@code double} greater than or equal
      * to {@code 0.0} and less than {@code 1.0}.
+     * @see #nextDown(double)
      * @see Random#nextDouble()
      */
     public static double random() {
@@ -819,6 +967,7 @@
      * @throws ArithmeticException if the result overflows an int
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static int addExact(int x, int y) {
         int r = x + y;
         // HD 2-12 Overflow iff both arguments have the opposite sign of the result
@@ -838,6 +987,7 @@
      * @throws ArithmeticException if the result overflows a long
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static long addExact(long x, long y) {
         long r = x + y;
         // HD 2-12 Overflow iff both arguments have the opposite sign of the result
@@ -857,10 +1007,11 @@
      * @throws ArithmeticException if the result overflows an int
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static int subtractExact(int x, int y) {
         int r = x - y;
         // HD 2-12 Overflow iff the arguments have different signs and
-        // the sign of the result is different than the sign of x
+        // the sign of the result is different from the sign of x
         if (((x ^ y) & (x ^ r)) < 0) {
             throw new ArithmeticException("integer overflow");
         }
@@ -877,10 +1028,11 @@
      * @throws ArithmeticException if the result overflows a long
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static long subtractExact(long x, long y) {
         long r = x - y;
         // HD 2-12 Overflow iff the arguments have different signs and
-        // the sign of the result is different than the sign of x
+        // the sign of the result is different from the sign of x
         if (((x ^ y) & (x ^ r)) < 0) {
             throw new ArithmeticException("long overflow");
         }
@@ -897,6 +1049,7 @@
      * @throws ArithmeticException if the result overflows an int
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static int multiplyExact(int x, int y) {
         long r = (long)x * (long)y;
         if ((int)r != r) {
@@ -929,6 +1082,7 @@
      * @throws ArithmeticException if the result overflows a long
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static long multiplyExact(long x, long y) {
         long r = x * y;
         long ax = Math.abs(x);
@@ -954,6 +1108,7 @@
      * @throws ArithmeticException if the result overflows an int
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static int incrementExact(int a) {
         if (a == Integer.MAX_VALUE) {
             throw new ArithmeticException("integer overflow");
@@ -971,6 +1126,7 @@
      * @throws ArithmeticException if the result overflows a long
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static long incrementExact(long a) {
         if (a == Long.MAX_VALUE) {
             throw new ArithmeticException("long overflow");
@@ -988,6 +1144,7 @@
      * @throws ArithmeticException if the result overflows an int
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static int decrementExact(int a) {
         if (a == Integer.MIN_VALUE) {
             throw new ArithmeticException("integer overflow");
@@ -1005,6 +1162,7 @@
      * @throws ArithmeticException if the result overflows a long
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static long decrementExact(long a) {
         if (a == Long.MIN_VALUE) {
             throw new ArithmeticException("long overflow");
@@ -1022,6 +1180,7 @@
      * @throws ArithmeticException if the result overflows an int
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static int negateExact(int a) {
         if (a == Integer.MIN_VALUE) {
             throw new ArithmeticException("integer overflow");
@@ -1039,6 +1198,7 @@
      * @throws ArithmeticException if the result overflows a long
      * @since 1.8
      */
+    @HotSpotIntrinsicCandidate
     public static long negateExact(long a) {
         if (a == Long.MIN_VALUE) {
             throw new ArithmeticException("long overflow");
@@ -1084,6 +1244,7 @@
      * @return the result
      * @since 9
      */
+    @HotSpotIntrinsicCandidate
     public static long multiplyHigh(long x, long y) {
         if (x < 0 || y < 0) {
             // Use technique from section 8-2 of Henry S. Warren, Jr.,
@@ -1136,7 +1297,6 @@
      *       whereas {@code (-4 / 3) == -1}.
      *   </li>
      * </ul>
-     * <p>
      *
      * @param x the dividend
      * @param y the divisor
@@ -1333,6 +1493,7 @@
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
      */
+    @HotSpotIntrinsicCandidate
     public static int abs(int a) {
         return (a < 0) ? -a : a;
     }
@@ -1350,6 +1511,7 @@
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
      */
+    @HotSpotIntrinsicCandidate
     public static long abs(long a) {
         return (a < 0) ? -a : a;
     }
@@ -1363,18 +1525,25 @@
      * result is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code float} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value:<br>
+     * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
      */
+    @HotSpotIntrinsicCandidate
     public static float abs(float a) {
         // Android-changed: Implementation modified to exactly match ART intrinsics behavior.
         // Note, as a "quality of implementation", rather than pure "spec compliance",
         // we require that Math.abs() clears the sign bit (but changes nothing else)
         // for all numbers, including NaN (signaling NaN may become quiet though).
         // http://b/30758343
+        // return (a <= 0.0F) ? 0.0F - a : a;
         return Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a));
     }
 
@@ -1387,18 +1556,25 @@
      * is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code double} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value:<br>
+     * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
      */
+    @HotSpotIntrinsicCandidate
     public static double abs(double a) {
         // Android-changed: Implementation modified to exactly match ART intrinsics behavior.
         // Note, as a "quality of implementation", rather than pure "spec compliance",
         // we require that Math.abs() clears the sign bit (but changes nothing else)
         // for all numbers, including NaN (signaling NaN may become quiet though).
         // http://b/30758343
+        // return (a <= 0.0D) ? 0.0D - a : a;
         return Double.longBitsToDouble(0x7fffffffffffffffL & Double.doubleToRawLongBits(a));
     }
 
@@ -1412,6 +1588,7 @@
      * @param   b   another argument.
      * @return  the larger of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static int max(int a, int b) {
         return (a >= b) ? a : b;
     }
@@ -1431,8 +1608,8 @@
     }
 
     // Use raw bit-wise conversions on guaranteed non-NaN arguments.
-    private static long negativeZeroFloatBits  = Float.floatToRawIntBits(-0.0f);
-    private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d);
+    private static final long negativeZeroFloatBits  = Float.floatToRawIntBits(-0.0f);
+    private static final long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d);
 
     /**
      * Returns the greater of two {@code float} values.  That is,
@@ -1448,6 +1625,7 @@
      * @param   b   another argument.
      * @return  the larger of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static float max(float a, float b) {
         if (a != a)
             return a;   // a is NaN
@@ -1474,6 +1652,7 @@
      * @param   b   another argument.
      * @return  the larger of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static double max(double a, double b) {
         if (a != a)
             return a;   // a is NaN
@@ -1496,6 +1675,7 @@
      * @param   b   another argument.
      * @return  the smaller of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static int min(int a, int b) {
         return (a <= b) ? a : b;
     }
@@ -1528,6 +1708,7 @@
      * @param   b   another argument.
      * @return  the smaller of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static float min(float a, float b) {
         if (a != a)
             return a;   // a is NaN
@@ -1554,6 +1735,7 @@
      * @param   b   another argument.
      * @return  the smaller of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static double min(double a, double b) {
         if (a != a)
             return a;   // a is NaN
@@ -1567,6 +1749,192 @@
     }
 
     /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code double}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fma(a, 1.0, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fma(a, b, +0.0)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fma(-0.0, +0.0, +0.0)} is {@code +0.0} while
+     * ({@code -0.0 * +0.0}) is {@code -0.0}; {@code fma(a, b, -0.0)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code double} value
+     *
+     * @since 9
+     */
+    @HotSpotIntrinsicCandidate
+    public static double fma(double a, double b, double c) {
+        /*
+         * Infinity and NaN arithmetic is not quite the same with two
+         * roundings as opposed to just one so the simple expression
+         * "a * b + c" cannot always be used to compute the correct
+         * result.  With two roundings, the product can overflow and
+         * if the addend is infinite, a spurious NaN can be produced
+         * if the infinity from the overflow and the infinite addend
+         * have opposite signs.
+         */
+
+        // First, screen for and handle non-finite input values whose
+        // arithmetic is not supported by BigDecimal.
+        if (Double.isNaN(a) || Double.isNaN(b) || Double.isNaN(c)) {
+            return Double.NaN;
+        } else { // All inputs non-NaN
+            boolean infiniteA = Double.isInfinite(a);
+            boolean infiniteB = Double.isInfinite(b);
+            boolean infiniteC = Double.isInfinite(c);
+            double result;
+
+            if (infiniteA || infiniteB || infiniteC) {
+                if (infiniteA && b == 0.0 ||
+                    infiniteB && a == 0.0 ) {
+                    return Double.NaN;
+                }
+                // Store product in a double field to cause an
+                // overflow even if non-strictfp evaluation is being
+                // used.
+                double product = a * b;
+                if (Double.isInfinite(product) && !infiniteA && !infiniteB) {
+                    // Intermediate overflow; might cause a
+                    // spurious NaN if added to infinite c.
+                    assert Double.isInfinite(c);
+                    return c;
+                } else {
+                    result = product + c;
+                    assert !Double.isFinite(result);
+                    return result;
+                }
+            } else { // All inputs finite
+                BigDecimal product = (new BigDecimal(a)).multiply(new BigDecimal(b));
+                if (c == 0.0) { // Positive or negative zero
+                    // If the product is an exact zero, use a
+                    // floating-point expression to compute the sign
+                    // of the zero final result. The product is an
+                    // exact zero if and only if at least one of a and
+                    // b is zero.
+                    if (a == 0.0 || b == 0.0) {
+                        return a * b + c;
+                    } else {
+                        // The sign of a zero addend doesn't matter if
+                        // the product is nonzero. The sign of a zero
+                        // addend is not factored in the result if the
+                        // exact product is nonzero but underflows to
+                        // zero; see IEEE-754 2008 section 6.3 "The
+                        // sign bit".
+                        return product.doubleValue();
+                    }
+                } else {
+                    return product.add(new BigDecimal(c)).doubleValue();
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code float}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fma(a, 1.0f, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fma(a, b, +0.0f)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fma(-0.0f, +0.0f, +0.0f)} is {@code +0.0f} while
+     * ({@code -0.0f * +0.0f}) is {@code -0.0f}; {@code fma(a, b, -0.0f)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code float} value
+     *
+     * @since 9
+     */
+    @HotSpotIntrinsicCandidate
+    public static float fma(float a, float b, float c) {
+        if (Float.isFinite(a) && Float.isFinite(b) && Float.isFinite(c)) {
+            if (a == 0.0 || b == 0.0) {
+                return a * b + c; // Handled signed zero cases
+            } else {
+                return (new BigDecimal((double)a * (double)b) // Exact multiply
+                        .add(new BigDecimal((double)c)))      // Exact sum
+                    .floatValue();                            // One rounding
+                                                              // to a float value
+            }
+        } else {
+            // At least one of a,b, and c is non-finite. The result
+            // will be non-finite as well and will be the same
+            // non-finite value under double as float arithmetic.
+            return (float)fma((double)a, (double)b, (double)c);
+        }
+    }
+
+    /**
      * Returns the size of an ulp of the argument.  An ulp, unit in
      * the last place, of a {@code double} value is the positive
      * distance between this floating-point value and the {@code
@@ -1593,18 +1961,18 @@
         int exp = getExponent(d);
 
         switch(exp) {
-        case DoubleConsts.MAX_EXPONENT+1:       // NaN or infinity
+        case Double.MAX_EXPONENT + 1:       // NaN or infinity
             return Math.abs(d);
 
-        case DoubleConsts.MIN_EXPONENT-1:       // zero or subnormal
+        case Double.MIN_EXPONENT - 1:       // zero or subnormal
             return Double.MIN_VALUE;
 
         default:
-            assert exp <= DoubleConsts.MAX_EXPONENT && exp >= DoubleConsts.MIN_EXPONENT;
+            assert exp <= Double.MAX_EXPONENT && exp >= Double.MIN_EXPONENT;
 
             // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
             exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH-1);
-            if (exp >= DoubleConsts.MIN_EXPONENT) {
+            if (exp >= Double.MIN_EXPONENT) {
                 return powerOfTwoD(exp);
             }
             else {
@@ -1612,7 +1980,7 @@
                 // representation of Double.MIN_VALUE appropriate
                 // number of positions
                 return Double.longBitsToDouble(1L <<
-                (exp - (DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) ));
+                (exp - (Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) ));
             }
         }
     }
@@ -1644,26 +2012,25 @@
         int exp = getExponent(f);
 
         switch(exp) {
-        case FloatConsts.MAX_EXPONENT+1:        // NaN or infinity
+        case Float.MAX_EXPONENT+1:        // NaN or infinity
             return Math.abs(f);
 
-        case FloatConsts.MIN_EXPONENT-1:        // zero or subnormal
-            return FloatConsts.MIN_VALUE;
+        case Float.MIN_EXPONENT-1:        // zero or subnormal
+            return Float.MIN_VALUE;
 
         default:
-            assert exp <= FloatConsts.MAX_EXPONENT && exp >= FloatConsts.MIN_EXPONENT;
+            assert exp <= Float.MAX_EXPONENT && exp >= Float.MIN_EXPONENT;
 
             // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
             exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1);
-            if (exp >= FloatConsts.MIN_EXPONENT) {
+            if (exp >= Float.MIN_EXPONENT) {
                 return powerOfTwoF(exp);
-            }
-            else {
+            } else {
                 // return a subnormal result; left shift integer
                 // representation of FloatConsts.MIN_VALUE appropriate
                 // number of positions
                 return Float.intBitsToFloat(1 <<
-                (exp - (FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) ));
+                (exp - (Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) ));
             }
         }
     }
@@ -1685,6 +2052,7 @@
      * @author Joseph D. Darcy
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static double signum(double d) {
         return (d == 0.0 || Double.isNaN(d))?d:copySign(1.0, d);
     }
@@ -1706,6 +2074,7 @@
      * @author Joseph D. Darcy
      * @since 1.5
      */
+    @HotSpotIntrinsicCandidate
     public static float signum(float f) {
         return (f == 0.0f || Float.isNaN(f))?f:copySign(1.0f, f);
     }
@@ -1735,6 +2104,13 @@
      * @return  The hyperbolic sine of {@code x}.
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double sinh(double x) {
+        return StrictMath.sinh(x);
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double sinh(double x);
 
@@ -1762,6 +2138,13 @@
      * @return  The hyperbolic cosine of {@code x}.
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double cosh(double x) {
+        return StrictMath.cosh(x);
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double cosh(double x);
 
@@ -1801,6 +2184,13 @@
      * @return  The hyperbolic tangent of {@code x}.
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double tanh(double x) {
+        return StrictMath.tanh(x);
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double tanh(double x);
 
@@ -1829,6 +2219,13 @@
      * without intermediate overflow or underflow
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double hypot(double x, double y) {
+        return StrictMath.hypot(x, y);
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double hypot(double x, double y);
 
@@ -1866,6 +2263,13 @@
      * @return  the value <i>e</i><sup>{@code x}</sup>&nbsp;-&nbsp;1.
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double expm1(double x) {
+        return StrictMath.expm1(x);
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double expm1(double x);
 
@@ -1902,6 +2306,13 @@
      * log of {@code x}&nbsp;+&nbsp;1
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double log1p(double x) {
+        return StrictMath.log1p(x);
+    }
+    */
+    // END Android-changed: Reimplement in native
     @CriticalNative
     public static native double log1p(double x);
 
@@ -1920,6 +2331,7 @@
      * and the sign of {@code sign}.
      * @since 1.6
      */
+    @HotSpotIntrinsicCandidate
     public static double copySign(double magnitude, double sign) {
         return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) &
                                         (DoubleConsts.SIGN_BIT_MASK)) |
@@ -1943,6 +2355,7 @@
      * and the sign of {@code sign}.
      * @since 1.6
      */
+    @HotSpotIntrinsicCandidate
     public static float copySign(float magnitude, float sign) {
         return Float.intBitsToFloat((Float.floatToRawIntBits(sign) &
                                      (FloatConsts.SIGN_BIT_MASK)) |
@@ -2051,51 +2464,36 @@
          * are naturally handled without any additional testing
          */
 
-        // First check for NaN values
-        if (Double.isNaN(start) || Double.isNaN(direction)) {
-            // return a NaN derived from the input NaN(s)
-            return start + direction;
-        } else if (start == direction) {
-            return direction;
-        } else {        // start > direction or start < direction
+        /*
+         * IEEE 754 floating-point numbers are lexicographically
+         * ordered if treated as signed-magnitude integers.
+         * Since Java's integers are two's complement,
+         * incrementing the two's complement representation of a
+         * logically negative floating-point value *decrements*
+         * the signed-magnitude representation. Therefore, when
+         * the integer representation of a floating-point value
+         * is negative, the adjustment to the representation is in
+         * the opposite direction from what would initially be expected.
+         */
+
+        // Branch to descending case first as it is more costly than ascending
+        // case due to start != 0.0d conditional.
+        if (start > direction) { // descending
+            if (start != 0.0d) {
+                final long transducer = Double.doubleToRawLongBits(start);
+                return Double.longBitsToDouble(transducer + ((transducer > 0L) ? -1L : 1L));
+            } else { // start == 0.0d && direction < 0.0d
+                return -Double.MIN_VALUE;
+            }
+        } else if (start < direction) { // ascending
             // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
             // then bitwise convert start to integer.
-            long transducer = Double.doubleToRawLongBits(start + 0.0d);
-
-            /*
-             * IEEE 754 floating-point numbers are lexicographically
-             * ordered if treated as signed- magnitude integers .
-             * Since Java's integers are two's complement,
-             * incrementing" the two's complement representation of a
-             * logically negative floating-point value *decrements*
-             * the signed-magnitude representation. Therefore, when
-             * the integer representation of a floating-point values
-             * is less than zero, the adjustment to the representation
-             * is in the opposite direction than would be expected at
-             * first .
-             */
-            if (direction > start) { // Calculate next greater value
-                transducer = transducer + (transducer >= 0L ? 1L:-1L);
-            } else  { // Calculate next lesser value
-                assert direction < start;
-                if (transducer > 0L)
-                    --transducer;
-                else
-                    if (transducer < 0L )
-                        ++transducer;
-                    /*
-                     * transducer==0, the result is -MIN_VALUE
-                     *
-                     * The transition from zero (implicitly
-                     * positive) to the smallest negative
-                     * signed magnitude value must be done
-                     * explicitly.
-                     */
-                    else
-                        transducer = DoubleConsts.SIGN_BIT_MASK | 1L;
-            }
-
-            return Double.longBitsToDouble(transducer);
+            final long transducer = Double.doubleToRawLongBits(start + 0.0d);
+            return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L : -1L));
+        } else if (start == direction) {
+            return direction;
+        } else { // isNaN(start) || isNaN(direction)
+            return start + direction;
         }
     }
 
@@ -2150,51 +2548,36 @@
          * are naturally handled without any additional testing
          */
 
-        // First check for NaN values
-        if (Float.isNaN(start) || Double.isNaN(direction)) {
-            // return a NaN derived from the input NaN(s)
-            return start + (float)direction;
-        } else if (start == direction) {
-            return (float)direction;
-        } else {        // start > direction or start < direction
+        /*
+         * IEEE 754 floating-point numbers are lexicographically
+         * ordered if treated as signed-magnitude integers.
+         * Since Java's integers are two's complement,
+         * incrementing the two's complement representation of a
+         * logically negative floating-point value *decrements*
+         * the signed-magnitude representation. Therefore, when
+         * the integer representation of a floating-point value
+         * is negative, the adjustment to the representation is in
+         * the opposite direction from what would initially be expected.
+         */
+
+        // Branch to descending case first as it is more costly than ascending
+        // case due to start != 0.0f conditional.
+        if (start > direction) { // descending
+            if (start != 0.0f) {
+                final int transducer = Float.floatToRawIntBits(start);
+                return Float.intBitsToFloat(transducer + ((transducer > 0) ? -1 : 1));
+            } else { // start == 0.0f && direction < 0.0f
+                return -Float.MIN_VALUE;
+            }
+        } else if (start < direction) { // ascending
             // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
             // then bitwise convert start to integer.
-            int transducer = Float.floatToRawIntBits(start + 0.0f);
-
-            /*
-             * IEEE 754 floating-point numbers are lexicographically
-             * ordered if treated as signed- magnitude integers .
-             * Since Java's integers are two's complement,
-             * incrementing" the two's complement representation of a
-             * logically negative floating-point value *decrements*
-             * the signed-magnitude representation. Therefore, when
-             * the integer representation of a floating-point values
-             * is less than zero, the adjustment to the representation
-             * is in the opposite direction than would be expected at
-             * first.
-             */
-            if (direction > start) {// Calculate next greater value
-                transducer = transducer + (transducer >= 0 ? 1:-1);
-            } else  { // Calculate next lesser value
-                assert direction < start;
-                if (transducer > 0)
-                    --transducer;
-                else
-                    if (transducer < 0 )
-                        ++transducer;
-                    /*
-                     * transducer==0, the result is -MIN_VALUE
-                     *
-                     * The transition from zero (implicitly
-                     * positive) to the smallest negative
-                     * signed magnitude value must be done
-                     * explicitly.
-                     */
-                    else
-                        transducer = FloatConsts.SIGN_BIT_MASK | 1;
-            }
-
-            return Float.intBitsToFloat(transducer);
+            final int transducer = Float.floatToRawIntBits(start + 0.0f);
+            return Float.intBitsToFloat(transducer + ((transducer >= 0) ? 1 : -1));
+        } else if (start == direction) {
+            return (float)direction;
+        } else { // isNaN(start) || isNaN(direction)
+            return start + (float)direction;
         }
     }
 
@@ -2224,12 +2607,13 @@
      * @since 1.6
      */
     public static double nextUp(double d) {
-        if( Double.isNaN(d) || d == Double.POSITIVE_INFINITY)
+        // Use a single conditional and handle the likely cases first.
+        if (d < Double.POSITIVE_INFINITY) {
+            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0).
+            final long transducer = Double.doubleToRawLongBits(d + 0.0D);
+            return Double.longBitsToDouble(transducer + ((transducer >= 0L) ? 1L : -1L));
+        } else { // d is NaN or +Infinity
             return d;
-        else {
-            d += 0.0d;
-            return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
-                                           ((d >= 0.0d)?+1L:-1L));
         }
     }
 
@@ -2259,12 +2643,13 @@
      * @since 1.6
      */
     public static float nextUp(float f) {
-        if( Float.isNaN(f) || f == FloatConsts.POSITIVE_INFINITY)
+        // Use a single conditional and handle the likely cases first.
+        if (f < Float.POSITIVE_INFINITY) {
+            // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0).
+            final int transducer = Float.floatToRawIntBits(f + 0.0F);
+            return Float.intBitsToFloat(transducer + ((transducer >= 0) ? 1 : -1));
+        } else { // f is NaN or +Infinity
             return f;
-        else {
-            f += 0.0f;
-            return Float.intBitsToFloat(Float.floatToRawIntBits(f) +
-                                        ((f >= 0.0f)?+1:-1));
         }
     }
 
@@ -2388,7 +2773,7 @@
          * multiply-store result is subnormal, the next multiply will
          * round it away to zero.  This is done by first multiplying
          * by 2 ^ (scaleFactor % n) and then multiplying several
-         * times by by 2^n as needed where n is the exponent of number
+         * times by 2^n as needed where n is the exponent of number
          * that is a covenient power of two.  In this way, at most one
          * real rounding error occurs.  If the double value set is
          * being used exclusively, the rounding will occur on a
@@ -2413,9 +2798,9 @@
 
         // magnitude of a power of two so large that scaling a finite
         // nonzero value by it would be guaranteed to over or
-        // underflow; due to rounding, scaling down takes takes an
+        // underflow; due to rounding, scaling down takes an
         // additional power of two which is reflected here
-        final int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT +
+        final int MAX_SCALE = Double.MAX_EXPONENT + -Double.MIN_EXPONENT +
                               DoubleConsts.SIGNIFICAND_WIDTH + 1;
         int exp_adjust = 0;
         int scale_increment = 0;
@@ -2482,9 +2867,9 @@
     public static float scalb(float f, int scaleFactor) {
         // magnitude of a power of two so large that scaling a finite
         // nonzero value by it would be guaranteed to over or
-        // underflow; due to rounding, scaling down takes takes an
+        // underflow; due to rounding, scaling down takes an
         // additional power of two which is reflected here
-        final int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT +
+        final int MAX_SCALE = Float.MAX_EXPONENT + -Float.MIN_EXPONENT +
                               FloatConsts.SIGNIFICAND_WIDTH + 1;
 
         // Make sure scaling factor is in a reasonable range
@@ -2510,7 +2895,7 @@
      * Returns a floating-point power of two in the normal range.
      */
     static double powerOfTwoD(int n) {
-        assert(n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT);
+        assert(n >= Double.MIN_EXPONENT && n <= Double.MAX_EXPONENT);
         return Double.longBitsToDouble((((long)n + (long)DoubleConsts.EXP_BIAS) <<
                                         (DoubleConsts.SIGNIFICAND_WIDTH-1))
                                        & DoubleConsts.EXP_BIT_MASK);
@@ -2520,7 +2905,7 @@
      * Returns a floating-point power of two in the normal range.
      */
     static float powerOfTwoF(int n) {
-        assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT);
+        assert(n >= Float.MIN_EXPONENT && n <= Float.MAX_EXPONENT);
         return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) <<
                                      (FloatConsts.SIGNIFICAND_WIDTH-1))
                                     & FloatConsts.EXP_BIT_MASK);
diff --git a/ojluni/src/main/java/java/lang/NegativeArraySizeException.java b/ojluni/src/main/java/java/lang/NegativeArraySizeException.java
index a90c815..baccdf7 100644
--- a/ojluni/src/main/java/java/lang/NegativeArraySizeException.java
+++ b/ojluni/src/main/java/java/lang/NegativeArraySizeException.java
@@ -29,7 +29,7 @@
  * Thrown if an application tries to create an array with negative size.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class NegativeArraySizeException extends RuntimeException {
diff --git a/ojluni/src/main/java/java/lang/NoClassDefFoundError.java b/ojluni/src/main/java/java/lang/NoClassDefFoundError.java
index e4f764f..ec86a5f 100644
--- a/ojluni/src/main/java/java/lang/NoClassDefFoundError.java
+++ b/ojluni/src/main/java/java/lang/NoClassDefFoundError.java
@@ -37,7 +37,7 @@
  * found.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class NoClassDefFoundError extends LinkageError {
diff --git a/ojluni/src/main/java/java/lang/NoSuchFieldError.java b/ojluni/src/main/java/java/lang/NoSuchFieldError.java
index 735adbb..ae00589 100644
--- a/ojluni/src/main/java/java/lang/NoSuchFieldError.java
+++ b/ojluni/src/main/java/java/lang/NoSuchFieldError.java
@@ -34,7 +34,7 @@
  * incompatibly changed.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class NoSuchFieldError extends IncompatibleClassChangeError {
diff --git a/ojluni/src/main/java/java/lang/NoSuchFieldException.java b/ojluni/src/main/java/java/lang/NoSuchFieldException.java
index 0058264..933c5b5 100644
--- a/ojluni/src/main/java/java/lang/NoSuchFieldException.java
+++ b/ojluni/src/main/java/java/lang/NoSuchFieldException.java
@@ -29,7 +29,7 @@
  * Signals that the class doesn't have a field of a specified name.
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public class NoSuchFieldException extends ReflectiveOperationException {
     private static final long serialVersionUID = -6143714805279938260L;
diff --git a/ojluni/src/main/java/java/lang/NoSuchMethodError.java b/ojluni/src/main/java/java/lang/NoSuchMethodError.java
index 248de62..3e373a0 100644
--- a/ojluni/src/main/java/java/lang/NoSuchMethodError.java
+++ b/ojluni/src/main/java/java/lang/NoSuchMethodError.java
@@ -35,7 +35,7 @@
  * incompatibly changed.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class NoSuchMethodError extends IncompatibleClassChangeError {
diff --git a/ojluni/src/main/java/java/lang/NoSuchMethodException.java b/ojluni/src/main/java/java/lang/NoSuchMethodException.java
index 701437c..e9f901d 100644
--- a/ojluni/src/main/java/java/lang/NoSuchMethodException.java
+++ b/ojluni/src/main/java/java/lang/NoSuchMethodException.java
@@ -29,7 +29,7 @@
  * Thrown when a particular method cannot be found.
  *
  * @author     unascribed
- * @since      JDK1.0
+ * @since      1.0
  */
 public
 class NoSuchMethodException extends ReflectiveOperationException {
diff --git a/ojluni/src/main/java/java/lang/NullPointerException.java b/ojluni/src/main/java/java/lang/NullPointerException.java
index 5b87ec4..d91d56f 100644
--- a/ojluni/src/main/java/java/lang/NullPointerException.java
+++ b/ojluni/src/main/java/java/lang/NullPointerException.java
@@ -47,7 +47,7 @@
  * stack trace was not writable}.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class NullPointerException extends RuntimeException {
diff --git a/ojluni/src/main/java/java/lang/Number.java b/ojluni/src/main/java/java/lang/Number.java
index d901609..019ed9c 100644
--- a/ojluni/src/main/java/java/lang/Number.java
+++ b/ojluni/src/main/java/java/lang/Number.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
  *
  * For platform classes, the conversion is often analogous to a
  * narrowing primitive conversion or a widening primitive conversion
- * as defining in <cite>The Java&trade; Language Specification</cite>
+ * as defined in <cite>The Java&trade; Language Specification</cite>
  * for converting between primitive types.  Therefore, conversions may
  * lose information about the overall magnitude of a numeric value, may
  * lose precision, and may even return a result of a different sign
@@ -50,12 +50,11 @@
  * @author      Arthur van Hoff
  * @jls 5.1.2 Widening Primitive Conversions
  * @jls 5.1.3 Narrowing Primitive Conversions
- * @since   JDK1.0
+ * @since   1.0
  */
 public abstract class Number implements java.io.Serializable {
     /**
-     * Returns the value of the specified number as an {@code int},
-     * which may involve rounding or truncation.
+     * Returns the value of the specified number as an {@code int}.
      *
      * @return  the numeric value represented by this object after conversion
      *          to type {@code int}.
@@ -63,8 +62,7 @@
     public abstract int intValue();
 
     /**
-     * Returns the value of the specified number as a {@code long},
-     * which may involve rounding or truncation.
+     * Returns the value of the specified number as a {@code long}.
      *
      * @return  the numeric value represented by this object after conversion
      *          to type {@code long}.
@@ -72,8 +70,7 @@
     public abstract long longValue();
 
     /**
-     * Returns the value of the specified number as a {@code float},
-     * which may involve rounding.
+     * Returns the value of the specified number as a {@code float}.
      *
      * @return  the numeric value represented by this object after conversion
      *          to type {@code float}.
@@ -81,8 +78,7 @@
     public abstract float floatValue();
 
     /**
-     * Returns the value of the specified number as a {@code double},
-     * which may involve rounding.
+     * Returns the value of the specified number as a {@code double}.
      *
      * @return  the numeric value represented by this object after conversion
      *          to type {@code double}.
@@ -90,30 +86,28 @@
     public abstract double doubleValue();
 
     /**
-     * Returns the value of the specified number as a {@code byte},
-     * which may involve rounding or truncation.
+     * Returns the value of the specified number as a {@code byte}.
      *
      * <p>This implementation returns the result of {@link #intValue} cast
      * to a {@code byte}.
      *
      * @return  the numeric value represented by this object after conversion
      *          to type {@code byte}.
-     * @since   JDK1.1
+     * @since   1.1
      */
     public byte byteValue() {
         return (byte)intValue();
     }
 
     /**
-     * Returns the value of the specified number as a {@code short},
-     * which may involve rounding or truncation.
+     * Returns the value of the specified number as a {@code short}.
      *
      * <p>This implementation returns the result of {@link #intValue} cast
      * to a {@code short}.
      *
      * @return  the numeric value represented by this object after conversion
      *          to type {@code short}.
-     * @since   JDK1.1
+     * @since   1.1
      */
     public short shortValue() {
         return (short)intValue();
diff --git a/ojluni/src/main/java/java/lang/NumberFormatException.java b/ojluni/src/main/java/java/lang/NumberFormatException.java
index ea1ec9f..7c6345d 100644
--- a/ojluni/src/main/java/java/lang/NumberFormatException.java
+++ b/ojluni/src/main/java/java/lang/NumberFormatException.java
@@ -32,7 +32,7 @@
  *
  * @author  unascribed
  * @see     java.lang.Integer#parseInt(String)
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class NumberFormatException extends IllegalArgumentException {
@@ -56,7 +56,7 @@
     }
 
     /**
-     * Factory method for making a <code>NumberFormatException</code>
+     * Factory method for making a {@code NumberFormatException}
      * given the specified input which caused the error.
      *
      * @param   s   the input causing the error
@@ -64,4 +64,20 @@
     static NumberFormatException forInputString(String s) {
         return new NumberFormatException("For input string: \"" + s + "\"");
     }
+
+    /**
+     * Factory method for making a {@code NumberFormatException}
+     * given the specified input which caused the error.
+     *
+     * @param   s   the input causing the error
+     * @param   beginIndex   the beginning index, inclusive.
+     * @param   endIndex     the ending index, exclusive.
+     * @param   errorIndex   the index of the first error in s
+     */
+    static NumberFormatException forCharSequence(CharSequence s,
+            int beginIndex, int endIndex, int errorIndex) {
+        return new NumberFormatException("Error at index "
+                + (errorIndex - beginIndex) + " in: \""
+                + s.subSequence(beginIndex, endIndex) + "\"");
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/OutOfMemoryError.java b/ojluni/src/main/java/java/lang/OutOfMemoryError.java
index 0f9df4e..2297ed6 100644
--- a/ojluni/src/main/java/java/lang/OutOfMemoryError.java
+++ b/ojluni/src/main/java/java/lang/OutOfMemoryError.java
@@ -36,7 +36,7 @@
  * writable}.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public class OutOfMemoryError extends VirtualMachineError {
     private static final long serialVersionUID = 8228564086184010517L;
diff --git a/ojluni/src/main/java/java/lang/Override.java b/ojluni/src/main/java/java/lang/Override.java
index bf77344..f985258 100644
--- a/ojluni/src/main/java/java/lang/Override.java
+++ b/ojluni/src/main/java/java/lang/Override.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,9 @@
  *
  * @author  Peter von der Ah&eacute;
  * @author  Joshua Bloch
- * @jls 9.6.1.4 @Override
+ * @jls 8.4.8 Inheritance, Overriding, and Hiding
+ * @jls 9.4.1 Inheritance and Overriding
+ * @jls 9.6.4.4 @Override
  * @since 1.5
  */
 @Target(ElementType.METHOD)
diff --git a/ojluni/src/main/java/java/lang/ProcessEnvironment.java b/ojluni/src/main/java/java/lang/ProcessEnvironment.java
index 08d260c..1813419 100644
--- a/ojluni/src/main/java/java/lang/ProcessEnvironment.java
+++ b/ojluni/src/main/java/java/lang/ProcessEnvironment.java
@@ -60,10 +60,14 @@
 
 final class ProcessEnvironment
 {
-    private static final HashMap<Variable,Value> theEnvironment;
-    private static final Map<String,String> theUnmodifiableEnvironment;
+    // BEGIN Android-removed: Don't cache the C environment.  http://b/201665416
+    // private static final HashMap<Variable,Value> theEnvironment;
+    // private static final Map<String,String> theUnmodifiableEnvironment;
+    // END Android-removed: Don't cache the C environment.  http://b/201665416
     static final int MIN_NAME_LENGTH = 0;
 
+    // BEGIN Android-removed: Don't cache the C environment.  http://b/201665416
+    /*
     static {
         // We cache the C environment.  This means that subsequent calls
         // to putenv/setenv from C will not be visible from Java code.
@@ -80,21 +84,42 @@
             (new StringEnvironment(theEnvironment));
     }
 
-    /* Only for use by System.getenv(String) */
+    /* Only for use by System.getenv(String) *
     static String getenv(String name) {
         return theUnmodifiableEnvironment.get(name);
     }
+    */
+    // END Android-removed: Don't cache the C environment.  http://b/201665416
+
+    // BEGIN Android-added: Don't cache the C environment.  http://b/201665416
+    // Instead, build a new copy each time using the same code as the previous
+    // static initializer.
+    private static Map<String, String> buildEnvironment() {
+        byte[][] environ = environ();
+        Map<Variable, Value> env = new HashMap<>(environ.length / 2 + 3);
+        // Read environment variables back to front,
+        // so that earlier variables override later ones.
+        for (int i = environ.length-1; i > 0; i-=2)
+            env.put(Variable.valueOf(environ[i-1]),
+                Value.valueOf(environ[i]));
+        return new StringEnvironment(env);
+    }
+    // END Android-added: Don't cache the C environment.  http://b/201665416
 
     /* Only for use by System.getenv() */
     static Map<String,String> getenv() {
-        return theUnmodifiableEnvironment;
+        // Android-changed: Don't cache the C environment.  http://b/201665416
+        // return theUnmodifiableEnvironment;
+        return Collections.unmodifiableMap(buildEnvironment());
     }
 
     /* Only for use by ProcessBuilder.environment() */
     @SuppressWarnings("unchecked")
     static Map<String,String> environment() {
-        return new StringEnvironment
-            ((Map<Variable,Value>)(theEnvironment.clone()));
+        // Android-changed: Don't cache the C environment.  http://b/201665416
+        // return new StringEnvironment
+        //     ((Map<Variable,Value>)(theEnvironment.clone()));
+        return buildEnvironment();
     }
 
     /* Only for use by Runtime.exec(...String[]envp...) */
diff --git a/ojluni/src/main/java/java/lang/Readable.java b/ojluni/src/main/java/java/lang/Readable.java
index c7a3d1a..2cc40c0 100644
--- a/ojluni/src/main/java/java/lang/Readable.java
+++ b/ojluni/src/main/java/java/lang/Readable.java
@@ -28,8 +28,8 @@
 import java.io.IOException;
 
 /**
- * A <tt>Readable</tt> is a source of characters. Characters from
- * a <tt>Readable</tt> are made available to callers of the read
+ * A {@code Readable} is a source of characters. Characters from
+ * a {@code Readable} are made available to callers of the read
  * method via a {@link java.nio.CharBuffer CharBuffer}.
  *
  * @since 1.5
diff --git a/ojluni/src/main/java/java/lang/Runnable.java b/ojluni/src/main/java/java/lang/Runnable.java
index b9f1df7..f876324 100644
--- a/ojluni/src/main/java/java/lang/Runnable.java
+++ b/ojluni/src/main/java/java/lang/Runnable.java
@@ -50,7 +50,7 @@
  * @author  Arthur van Hoff
  * @see     java.lang.Thread
  * @see     java.util.concurrent.Callable
- * @since   JDK1.0
+ * @since   1.0
  */
 @FunctionalInterface
 public interface Runnable {
diff --git a/ojluni/src/main/java/java/lang/RuntimeException.java b/ojluni/src/main/java/java/lang/RuntimeException.java
index c9731e8..bfa524d 100644
--- a/ojluni/src/main/java/java/lang/RuntimeException.java
+++ b/ojluni/src/main/java/java/lang/RuntimeException.java
@@ -38,7 +38,7 @@
  *
  * @author  Frank Yellin
  * @jls 11.2 Compile-Time Checking of Exceptions
- * @since   JDK1.0
+ * @since   1.0
  */
 public class RuntimeException extends Exception {
     static final long serialVersionUID = -7034897190745766939L;
@@ -71,7 +71,7 @@
      * @param  message the detail message (which is saved for later retrieval
      *         by the {@link #getMessage()} method).
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link #getCause()} method).  (A <tt>null</tt> value is
+     *         {@link #getCause()} method).  (A {@code null} value is
      *         permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since  1.4
@@ -81,13 +81,13 @@
     }
 
     /** Constructs a new runtime exception with the specified cause and a
-     * detail message of <tt>(cause==null ? null : cause.toString())</tt>
+     * detail message of {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
-     * <tt>cause</tt>).  This constructor is useful for runtime exceptions
+     * {@code cause}).  This constructor is useful for runtime exceptions
      * that are little more than wrappers for other throwables.
      *
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link #getCause()} method).  (A <tt>null</tt> value is
+     *         {@link #getCause()} method).  (A {@code null} value is
      *         permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since  1.4
diff --git a/ojluni/src/main/java/java/lang/SafeVarargs.java b/ojluni/src/main/java/java/lang/SafeVarargs.java
index 6fcd48e..4e3eddf 100644
--- a/ojluni/src/main/java/java/lang/SafeVarargs.java
+++ b/ojluni/src/main/java/java/lang/SafeVarargs.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
  * <li>  the declaration is a fixed arity method or constructor
  *
  * <li> the declaration is a variable arity method that is neither
- * {@code static} nor {@code final}.
+ * {@code static} nor {@code final} nor {@code private}.
  *
  * </ul>
  *
@@ -85,7 +85,7 @@
  * @since 1.7
  * @jls 4.7 Reifiable Types
  * @jls 8.4.1 Formal Parameters
- * @jls 9.6.3.7 @SafeVarargs
+ * @jls 9.6.4.7 @SafeVarargs
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/ojluni/src/main/java/java/lang/SecurityException.java b/ojluni/src/main/java/java/lang/SecurityException.java
index 7e07178..534c484 100644
--- a/ojluni/src/main/java/java/lang/SecurityException.java
+++ b/ojluni/src/main/java/java/lang/SecurityException.java
@@ -29,21 +29,21 @@
  *
  * @author  unascribed
  * @see     java.lang.SecurityManager
- * @since   JDK1.0
+ * @since   1.0
  */
 public class SecurityException extends RuntimeException {
 
     private static final long serialVersionUID = 6878364983674394167L;
 
     /**
-     * Constructs a <code>SecurityException</code> with no detail  message.
+     * Constructs a {@code SecurityException} with no detail message.
      */
     public SecurityException() {
         super();
     }
 
     /**
-     * Constructs a <code>SecurityException</code> with the specified
+     * Constructs a {@code SecurityException} with the specified
      * detail message.
      *
      * @param   s   the detail message.
@@ -53,13 +53,13 @@
     }
 
     /**
-     * Creates a <code>SecurityException</code> with the specified
+     * Creates a {@code SecurityException} with the specified
      * detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
      *        by the {@link #getMessage()} method).
      * @param cause the cause (which is saved for later retrieval by the
-     *        {@link #getCause()} method).  (A <tt>null</tt> value is permitted,
+     *        {@link #getCause()} method).  (A {@code null} value is permitted,
      *        and indicates that the cause is nonexistent or unknown.)
      * @since 1.5
      */
@@ -68,13 +68,13 @@
     }
 
     /**
-     * Creates a <code>SecurityException</code> with the specified cause
-     * and a detail message of <tt>(cause==null ? null : cause.toString())</tt>
+     * Creates a {@code SecurityException} with the specified cause
+     * and a detail message of {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
-     * <tt>cause</tt>).
+     * {@code cause}).
      *
      * @param cause the cause (which is saved for later retrieval by the
-     *        {@link #getCause()} method).  (A <tt>null</tt> value is permitted,
+     *        {@link #getCause()} method).  (A {@code null} value is permitted,
      *        and indicates that the cause is nonexistent or unknown.)
      * @since 1.5
      */
diff --git a/ojluni/src/main/java/java/lang/SecurityManager.java b/ojluni/src/main/java/java/lang/SecurityManager.java
index b7053e0..bd3ee29 100644
--- a/ojluni/src/main/java/java/lang/SecurityManager.java
+++ b/ojluni/src/main/java/java/lang/SecurityManager.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -176,6 +176,10 @@
 
     public void checkPropertyAccess(String key) { }
 
+    /**
+     * @deprecated this method is deprecated.
+     */
+    @Deprecated
     public boolean checkTopLevelWindow(Object window) {
         return true;
     }
@@ -192,6 +196,10 @@
 
     public void checkSetFactory() { }
 
+    /**
+     * @deprecated this method is deprecated.
+     */
+    @Deprecated
     public void checkMemberAccess(Class<?> clazz, int which) { }
 
     public void checkSecurityAccess(String target) { }
diff --git a/ojluni/src/main/java/java/lang/Short.java b/ojluni/src/main/java/java/lang/Short.java
index dd6e2e2..57b291f 100644
--- a/ojluni/src/main/java/java/lang/Short.java
+++ b/ojluni/src/main/java/java/lang/Short.java
@@ -25,8 +25,7 @@
 
 package java.lang;
 
-// Android-removed: unsupported @HotSpotIntrinsicCandidate annotation.
-// import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
  * The {@code Short} class wraps a value of primitive type {@code
@@ -230,8 +229,7 @@
      * @return a {@code Short} instance representing {@code s}.
      * @since  1.5
      */
-    // Android-removed: unsupported @HotSpotIntrinsicCandidate annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public static Short valueOf(short s) {
         final int offset = 128;
         int sAsInt = s;
@@ -351,8 +349,7 @@
      * Returns the value of this {@code Short} as a
      * {@code short}.
      */
-    // Android-removed: unsupported @HotSpotIntrinsicCandidate annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public short shortValue() {
         return value;
     }
@@ -522,8 +519,7 @@
      *     the bytes in the specified {@code short} value.
      * @since 1.5
      */
-    // Android-removed: unsupported @HotSpotIntrinsicCandidate annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public static short reverseBytes(short i) {
         return (short) (((i & 0xFF00) >> 8) | (i << 8));
     }
diff --git a/ojluni/src/main/java/java/lang/StackOverflowError.java b/ojluni/src/main/java/java/lang/StackOverflowError.java
index 73fd8c1..8099e71 100644
--- a/ojluni/src/main/java/java/lang/StackOverflowError.java
+++ b/ojluni/src/main/java/java/lang/StackOverflowError.java
@@ -30,7 +30,7 @@
  * recurses too deeply.
  *
  * @author unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class StackOverflowError extends VirtualMachineError {
diff --git a/ojluni/src/main/java/java/lang/StrictMath.java b/ojluni/src/main/java/java/lang/StrictMath.java
index c0a41b9..2f1898b 100644
--- a/ojluni/src/main/java/java/lang/StrictMath.java
+++ b/ojluni/src/main/java/java/lang/StrictMath.java
@@ -26,7 +26,8 @@
 package java.lang;
 
 import java.util.Random;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
  * The class {@code StrictMath} contains methods for performing basic
@@ -226,6 +227,13 @@
      * @return  the value <i>e</i><sup>{@code a}</sup>,
      *          where <i>e</i> is the base of the natural logarithms.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double exp(double a) {
+        return FdLibm.Exp.compute(a);
+    }
+    */
+    // END Android-changed: Reimplement in native
     public static native double exp(double a);
 
     /**
@@ -244,7 +252,6 @@
      */
     public static native double log(double a);
 
-
     /**
      * Returns the base 10 logarithm of a {@code double} value.
      * Special cases:
@@ -281,6 +288,7 @@
      * @param   a   a value.
      * @return  the positive square root of {@code a}.
      */
+    @HotSpotIntrinsicCandidate
     public static native double sqrt(double a);
 
     /**
@@ -306,6 +314,13 @@
      * @return  the cube root of {@code a}.
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double cbrt(double a) {
+        return FdLibm.Cbrt.compute(a);
+    }
+    */
+    // END Android-changed: Reimplement in native
     public static native double cbrt(double a);
 
     /**
@@ -522,7 +537,6 @@
      */
     public static native double atan2(double y, double x);
 
-
     /**
      * Returns the value of the first argument raised to the power of the
      * second argument. Special cases:
@@ -643,6 +657,13 @@
      * @param   b   the exponent.
      * @return  the value {@code a}<sup>{@code b}</sup>.
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double pow(double a, double b) {
+        return FdLibm.Pow.compute(a, b);
+    }
+    */
+    // END Android-changed: Reimplement in native
     public static native double pow(double a, double b);
 
     /**
@@ -1066,8 +1087,13 @@
      * result is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code float} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value: <br>
+     * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
@@ -1085,8 +1111,13 @@
      * is positive zero.
      * <li>If the argument is infinite, the result is positive infinity.
      * <li>If the argument is NaN, the result is NaN.</ul>
-     * In other words, the result is the same as the value of the expression:
-     * <p>{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+     *
+     * @apiNote As implied by the above, one valid implementation of
+     * this method is given by the expression below which computes a
+     * {@code double} with the same exponent and significand as the
+     * argument but with a guaranteed zero sign bit indicating a
+     * positive value: <br>
+     * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
      *
      * @param   a   the argument whose absolute value is to be determined
      * @return  the absolute value of the argument.
@@ -1105,6 +1136,7 @@
      * @param   b   another argument.
      * @return  the larger of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static int max(int a, int b) {
         return Math.max(a, b);
     }
@@ -1137,6 +1169,7 @@
      * @param   b   another argument.
      * @return  the larger of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static float max(float a, float b) {
         return Math.max(a, b);
     }
@@ -1155,6 +1188,7 @@
      * @param   b   another argument.
      * @return  the larger of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static double max(double a, double b) {
         return Math.max(a, b);
     }
@@ -1169,6 +1203,7 @@
      * @param   b   another argument.
      * @return  the smaller of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static int min(int a, int b) {
         return Math.min(a, b);
     }
@@ -1201,6 +1236,7 @@
      * @param   b   another argument.
      * @return  the smaller of {@code a} and {@code b.}
      */
+    @HotSpotIntrinsicCandidate
     public static float min(float a, float b) {
         return Math.min(a, b);
     }
@@ -1219,11 +1255,120 @@
      * @param   b   another argument.
      * @return  the smaller of {@code a} and {@code b}.
      */
+    @HotSpotIntrinsicCandidate
     public static double min(double a, double b) {
         return Math.min(a, b);
     }
 
     /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code double}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fusedMac(a, 1.0, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fusedMac(a, b, +0.0)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fusedMac(-0.0, +0.0, +0.0)} is {@code +0.0} while
+     * ({@code -0.0 * +0.0}) is {@code -0.0}; {@code fusedMac(a, b, -0.0)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code double} value
+     *
+     * @since 9
+     */
+    public static double fma(double a, double b, double c) {
+        return Math.fma(a, b, c);
+    }
+
+    /**
+     * Returns the fused multiply add of the three arguments; that is,
+     * returns the exact product of the first two arguments summed
+     * with the third argument and then rounded once to the nearest
+     * {@code float}.
+     *
+     * The rounding is done using the {@linkplain
+     * java.math.RoundingMode#HALF_EVEN round to nearest even
+     * rounding mode}.
+     *
+     * In contrast, if {@code a * b + c} is evaluated as a regular
+     * floating-point expression, two rounding errors are involved,
+     * the first for the multiply operation, the second for the
+     * addition operation.
+     *
+     * <p>Special cases:
+     * <ul>
+     * <li> If any argument is NaN, the result is NaN.
+     *
+     * <li> If one of the first two arguments is infinite and the
+     * other is zero, the result is NaN.
+     *
+     * <li> If the exact product of the first two arguments is infinite
+     * (in other words, at least one of the arguments is infinite and
+     * the other is neither zero nor NaN) and the third argument is an
+     * infinity of the opposite sign, the result is NaN.
+     *
+     * </ul>
+     *
+     * <p>Note that {@code fma(a, 1.0f, c)} returns the same
+     * result as ({@code a + c}).  However,
+     * {@code fma(a, b, +0.0f)} does <em>not</em> always return the
+     * same result as ({@code a * b}) since
+     * {@code fma(-0.0f, +0.0f, +0.0f)} is {@code +0.0f} while
+     * ({@code -0.0f * +0.0f}) is {@code -0.0f}; {@code fma(a, b, -0.0f)} is
+     * equivalent to ({@code a * b}) however.
+     *
+     * @apiNote This method corresponds to the fusedMultiplyAdd
+     * operation defined in IEEE 754-2008.
+     *
+     * @param a a value
+     * @param b a value
+     * @param c a value
+     *
+     * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
+     * computed, as if with unlimited range and precision, and rounded
+     * once to the nearest {@code float} value
+     *
+     * @since 9
+     */
+    public static float fma(float a, float b, float c) {
+        return Math.fma(a, b, c);
+    }
+
+    /**
      * Returns the size of an ulp of the argument.  An ulp, unit in
      * the last place, of a {@code double} value is the positive
      * distance between this floating-point value and the {@code
@@ -1420,6 +1565,13 @@
      * without intermediate overflow or underflow
      * @since 1.5
      */
+    // BEGIN Android-changed: Reimplement in native
+    /*
+    public static double hypot(double x, double y) {
+        return FdLibm.Hypot.compute(x, y);
+    }
+    */
+    // END Android-changed: Reimplement in native
     public static native double hypot(double x, double y);
 
     /**
diff --git a/ojluni/src/main/java/java/lang/String.java b/ojluni/src/main/java/java/lang/String.java
index 58207eb..984606e 100644
--- a/ojluni/src/main/java/java/lang/String.java
+++ b/ojluni/src/main/java/java/lang/String.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,9 +35,14 @@
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.Objects;
+import java.util.Spliterator;
 import java.util.StringJoiner;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 import libcore.util.CharsetUtils;
 
@@ -75,16 +80,10 @@
  * <p>
  * The Java language provides special support for the string
  * concatenation operator (&nbsp;+&nbsp;), and for conversion of
- * other objects to strings. String concatenation is implemented
- * through the {@code StringBuilder}(or {@code StringBuffer})
- * class and its {@code append} method.
- * String conversions are implemented through the method
- * {@code toString}, defined by {@code Object} and
- * inherited by all classes in Java. For additional information on
- * string concatenation and conversion, see Gosling, Joy, and Steele,
- * <i>The Java Language Specification</i>.
+ * other objects to strings. For additional information on string
+ * concatenation and conversion, see <i>The Java&trade; Language Specification</i>.
  *
- * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
+ * <p> Unless otherwise noted, passing a {@code null} argument to a constructor
  * or method in this class will cause a {@link NullPointerException} to be
  * thrown.
  *
@@ -99,6 +98,18 @@
  * Unicode code points (i.e., characters), in addition to those for
  * dealing with Unicode code units (i.e., {@code char} values).
  *
+ * <p>Unless otherwise noted, methods for comparing Strings do not take locale
+ * into account.  The {@link java.text.Collator} class provides methods for
+ * finer-grain, locale-sensitive String comparison.
+ *
+ * @implNote The implementation of the string concatenation operator is left to
+ * the discretion of a Java compiler, as long as the compiler ultimately conforms
+ * to <i>The Java&trade; Language Specification</i>. For example, the {@code javac} compiler
+ * may implement the operator with {@code StringBuffer}, {@code StringBuilder},
+ * or {@code java.lang.invoke.StringConcatFactory} depending on the JDK version. The
+ * implementation of string conversion is typically through the method {@code toString},
+ * defined by {@code Object} and inherited by all classes in Java.
+ *
  * @author  Lee Boynton
  * @author  Arthur van Hoff
  * @author  Martin Buchholz
@@ -107,27 +118,40 @@
  * @see     java.lang.StringBuffer
  * @see     java.lang.StringBuilder
  * @see     java.nio.charset.Charset
- * @since   JDK1.0
+ * @since   1.0
+ * @jls     15.18.1 String Concatenation Operator +
  */
 
 public final class String
     implements java.io.Serializable, Comparable<String>, CharSequence {
-
     // BEGIN Android-changed: The character data is managed by the runtime.
-    // We only keep track of the length here and compression here. This has several consequences
-    // throughout this class:
-    //  - References to value[i] are replaced by charAt(i).
-    //  - References to value.length are replaced by calls to length().
-    //  - Sometimes the result of length() is assigned to a local variable to avoid repeated calls.
-    //  - We skip several attempts at optimization where the values field was assigned to a local
-    //    variable to avoid the getfield opcode.
-    // These changes are not all marked individually.
-    //
-    // private final char value[];
-    //
-    // If STRING_COMPRESSION_ENABLED, count stores the length shifted one bit to the left with the
-    // lowest bit used to indicate whether or not the bytes are compressed (see GetFlaggedCount in
-    // the native code).
+    /*
+    We only keep track of the length here and compression here. This has several consequences
+    throughout this class:
+     - References to value[i] are replaced by charAt(i).
+     - References to value.length are replaced by calls to length().
+     - Sometimes the result of length() is assigned to a local variable to avoid repeated calls.
+     - We skip several attempts at optimization where the values field was assigned to a local
+       variable to avoid the getfield opcode.
+    These changes are not all marked individually.
+
+    If STRING_COMPRESSION_ENABLED, count stores the length shifted one bit to the left with the
+    lowest bit used to indicate whether or not the bytes are compressed (see GetFlaggedCount in
+    the native code).
+    /**
+     * The value is used for character storage.
+     *
+     * @implNote This field is trusted by the VM, and is a subject to
+     * constant folding if String instance is constant. Overwriting this
+     * field after construction will cause problems.
+     *
+     * Additionally, it is marked with {@link Stable} to trust the contents
+     * of the array. No other facility in JDK provides this functionality (yet).
+     * {@link Stable} is safe here, because value is never null.
+     *
+    @Stable
+    private final byte[] value;
+    */
     private final int count;
     // END Android-changed: The character data is managed by the runtime.
 
@@ -144,7 +168,7 @@
      * Class String is special cased within the Serialization Stream Protocol.
      *
      * A String instance is written into an ObjectOutputStream according to
-     * <a href="https://docs.oracle.com/javase/8/docs/platform/serialization/spec/output.html">
+     * <a href="{@docRoot}/../specs/serialization/protocol.html#stream-elements">
      * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
      */
     private static final ObjectStreamField[] serialPersistentFields =
@@ -156,8 +180,13 @@
      * unnecessary since Strings are immutable.
      */
     public String() {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this.value = "".value;
+        this.coder = "".coder;
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -170,9 +199,16 @@
      * @param  original
      *         A {@code String}
      */
+    @HotSpotIntrinsicCandidate
     public String(String original) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this.value = original.value;
+        this.coder = original.coder;
+        this.hash = original.hash;
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -185,8 +221,12 @@
      *         The initial value of the string
      */
     public String(char value[]) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(value, 0, value.length, null);
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -207,12 +247,21 @@
      *         The length
      *
      * @throws  IndexOutOfBoundsException
-     *          If the {@code offset} and {@code count} arguments index
-     *          characters outside the bounds of the {@code value} array
+     *          If {@code offset} is negative, {@code count} is negative, or
+     *          {@code offset} is greater than {@code value.length - count}
      */
     public String(char value[], int offset, int count) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(value, offset, count, rangeCheck(value, offset, count));
+    }
+
+    private static Void rangeCheck(char[] value, int offset, int count) {
+        checkBoundsOffCount(offset, count, value.length);
+        return null;
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -238,14 +287,33 @@
      *          codePoints}
      *
      * @throws  IndexOutOfBoundsException
-     *          If the {@code offset} and {@code count} arguments index
-     *          characters outside the bounds of the {@code codePoints} array
+     *          If {@code offset} is negative, {@code count} is negative, or
+     *          {@code offset} is greater than {@code codePoints.length - count}
      *
      * @since  1.5
      */
     public String(int[] codePoints, int offset, int count) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        checkBoundsOffCount(offset, count, codePoints.length);
+        if (count == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
+        }
+        if (COMPACT_STRINGS) {
+            byte[] val = StringLatin1.toBytes(codePoints, offset, count);
+            if (val != null) {
+                this.coder = LATIN1;
+                this.value = val;
+                return;
+            }
+        }
+        this.coder = UTF16;
+        this.value = StringUTF16.toBytes(codePoints, offset, count);
+        */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -257,7 +325,7 @@
      * subarray.
      *
      * <p> Each {@code byte} in the subarray is converted to a {@code char} as
-     * specified in the method above.
+     * specified in the {@link #String(byte[],int) String(byte[],int)} constructor.
      *
      * @deprecated This method does not properly convert bytes into characters.
      * As of JDK&nbsp;1.1, the preferred way to do this is via the
@@ -277,7 +345,8 @@
      *         The length
      *
      * @throws  IndexOutOfBoundsException
-     *          If the {@code offset} or {@code count} argument is invalid
+     *          If {@code offset} is negative, {@code count} is negative, or
+     *          {@code offset} is greater than {@code ascii.length - count}
      *
      * @see  #String(byte[], int)
      * @see  #String(byte[], int, int, java.lang.String)
@@ -287,15 +356,36 @@
      * @see  #String(byte[], java.nio.charset.Charset)
      * @see  #String(byte[])
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public String(byte ascii[], int hibyte, int offset, int count) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        checkBoundsOffCount(offset, count, ascii.length);
+        if (count == 0) {
+            this.value = "".value;
+            this.coder = "".coder;
+            return;
+        }
+        if (COMPACT_STRINGS && (byte)hibyte == 0) {
+            this.value = Arrays.copyOfRange(ascii, offset, offset + count);
+            this.coder = LATIN1;
+        } else {
+            hibyte <<= 8;
+            byte[] val = StringUTF16.newBytesFor(count);
+            for (int i = 0; i < count; i++) {
+                StringUTF16.putChar(val, i, hibyte | (ascii[offset++] & 0xff));
+            }
+            this.value = val;
+            this.coder = UTF16;
+        }
+        */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
      * Allocates a new {@code String} containing characters constructed from
-     * an array of 8-bit integer values. Each character <i>c</i>in the
+     * an array of 8-bit integer values. Each character <i>c</i> in the
      * resulting string is constructed from the corresponding component
      * <i>b</i> in the byte array such that:
      *
@@ -323,12 +413,31 @@
      * @see  #String(byte[], java.nio.charset.Charset)
      * @see  #String(byte[])
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public String(byte ascii[], int hibyte) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(ascii, hibyte, 0, ascii.length);
+        */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
+    // BEGIN Android-removed: checkBounds(byte[] bytes, int offset, int length) utility method.
+    /* Common private utility method used to bounds check the byte array
+     * and requested offset & length values used by the String(byte[],..)
+     * constructors.
+     *
+    private static void checkBounds(byte[] bytes, int offset, int length) {
+        if (length < 0)
+            throw new StringIndexOutOfBoundsException(length);
+        if (offset < 0)
+            throw new StringIndexOutOfBoundsException(offset);
+        if (offset > bytes.length - length)
+            throw new StringIndexOutOfBoundsException(offset + length);
+    }
+    // END Android-removed: checkBounds(byte[] bytes, int offset, int length) utility method.
+
     /**
      * Constructs a new {@code String} by decoding the specified subarray of
      * bytes using the specified charset.  The length of the new {@code String}
@@ -357,15 +466,25 @@
      *          If the named charset is not supported
      *
      * @throws  IndexOutOfBoundsException
-     *          If the {@code offset} and {@code length} arguments index
-     *          characters outside the bounds of the {@code bytes} array
+     *          If {@code offset} is negative, {@code length} is negative, or
+     *          {@code offset} is greater than {@code bytes.length - length}
      *
-     * @since  JDK1.1
+     * @since  1.1
      */
     public String(byte bytes[], int offset, int length, String charsetName)
             throws UnsupportedEncodingException {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        if (charsetName == null)
+            throw new NullPointerException("charsetName");
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret =
+            StringCoding.decode(charsetName, bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
+        */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -393,14 +512,24 @@
      *         decode the {@code bytes}
      *
      * @throws  IndexOutOfBoundsException
-     *          If the {@code offset} and {@code length} arguments index
-     *          characters outside the bounds of the {@code bytes} array
+     *          If {@code offset} is negative, {@code length} is negative, or
+     *          {@code offset} is greater than {@code bytes.length - length}
      *
      * @since  1.6
      */
     public String(byte bytes[], int offset, int length, Charset charset) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        if (charset == null)
+            throw new NullPointerException("charset");
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret =
+            StringCoding.decode(charset, bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
+        */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -424,12 +553,16 @@
      * @throws  UnsupportedEncodingException
      *          If the named charset is not supported
      *
-     * @since  JDK1.1
+     * @since  1.1
      */
     public String(byte bytes[], String charsetName)
             throws UnsupportedEncodingException {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(bytes, 0, bytes.length, charsetName);
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -453,8 +586,12 @@
      * @since  1.6
      */
     public String(byte bytes[], Charset charset) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(bytes, 0, bytes.length, charset);
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -478,14 +615,21 @@
      *         The number of bytes to decode
      *
      * @throws  IndexOutOfBoundsException
-     *          If the {@code offset} and the {@code length} arguments index
-     *          characters outside the bounds of the {@code bytes} array
+     *          If {@code offset} is negative, {@code length} is negative, or
+     *          {@code offset} is greater than {@code bytes.length - length}
      *
-     * @since  JDK1.1
+     * @since  1.1
      */
     public String(byte bytes[], int offset, int length) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        checkBoundsOffCount(offset, length, bytes.length);
+        StringCoding.Result ret = StringCoding.decode(bytes, offset, length);
+        this.value = ret.value;
+        this.coder = ret.coder;
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -502,11 +646,15 @@
      * @param  bytes
      *         The bytes to be decoded into characters
      *
-     * @since  JDK1.1
+     * @since  1.1
      */
-    public String(byte bytes[]) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+    public String(byte[] bytes) {
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(bytes, 0, bytes.length);
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -519,8 +667,12 @@
      *         A {@code StringBuffer}
      */
     public String(StringBuffer buffer) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(buffer.toString());
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
     /**
@@ -539,11 +691,28 @@
      * @since  1.5
      */
     public String(StringBuilder builder) {
-        // Android-changed: Constructor unsupported as all calls are intercepted by the runtime.
+        // BEGIN Android-changed: Implemented as compiler and runtime intrinsics.
+        /*
+        this(builder, null);
+         */
         throw new UnsupportedOperationException("Use StringFactory instead.");
+        // END Android-changed: Implemented as compiler and runtime intrinsics.
     }
 
-    // Android-removed: Unused package-private constructor String(char[] value, boolean share).
+    // BEGIN Android-removed: Unused package-private constructor String(char[] value, boolean share).
+    /*
+    /*
+    * Package private constructor which shares value array for speed.
+    * this constructor is always expected to be called with share==true.
+    * a separate constructor is needed because we already have a public
+    * String(char[]) constructor that makes a copy of the given char[].
+    *
+    String(char[] value, boolean share) {
+        // assert share : "unshared not supported";
+        this.value = value;
+    }
+    */
+    // END Android-removed: Unused package-private constructor String(char[] value, boolean share).
 
     // BEGIN Android-added: Constructor for internal use.
     // Not implemented in java as all calls are intercepted by the runtime.
@@ -568,7 +737,9 @@
      */
     public int length() {
         // BEGIN Android-changed: Get length from count field rather than value array (see above).
-        // return value.length;
+        /*
+        return value.length >> coder();
+        */
         final boolean STRING_COMPRESSION_ENABLED = true;
         if (STRING_COMPRESSION_ENABLED) {
             // For the compression purposes (save the characters as 8-bit if all characters
@@ -589,10 +760,13 @@
      * @since 1.6
      */
     public boolean isEmpty() {
-        // Android-changed: Get length from count field rather than value array (see above).
+        // BEGIN Android-changed: Get length from count field rather than value array (see above).
         // Empty string has {@code count == 0} with or without string compression enabled.
-        // return value.length == 0;
+        /*
+        return value.length == 0;
+         */
         return count == 0;
+        // END Android-changed: Get length from count field rather than value array (see above).
     }
 
     /**
@@ -614,6 +788,15 @@
      *             string.
      */
     // BEGIN Android-changed: Replace with implementation in runtime to access chars (see above).
+    /*
+    public char charAt(int index) {
+        if (isLatin1()) {
+            return StringLatin1.charAt(value, index);
+        } else {
+            return StringUTF16.charAt(value, index);
+        }
+    }
+    */
     @FastNative
     public native char charAt(int index);
     // END Android-changed: Replace with implementation in runtime to access chars (see above).
@@ -641,10 +824,17 @@
      * @since      1.5
      */
     public int codePointAt(int index) {
-        if ((index < 0) || (index >= length())) {
-            throw new StringIndexOutOfBoundsException(index);
+        // BEGIN Android-changed: delegate codePointAt() to Character class.
+        /*
+        if (isLatin1()) {
+            checkIndex(index, value.length);
+            return value[index] & 0xff;
         }
-        // Android-changed: Skip codePointAtImpl optimization that needs access to java chars.
+        int length = value.length >> 1;
+        checkIndex(index, length);
+        return StringUTF16.codePointAt(value, index, length);
+         */
+        checkIndex(index, length());
         return Character.codePointAt(this, index);
     }
 
@@ -672,10 +862,16 @@
      */
     public int codePointBefore(int index) {
         int i = index - 1;
-        if ((i < 0) || (i >= length())) {
+        if (i < 0 || i >= length()) {
             throw new StringIndexOutOfBoundsException(index);
         }
-        // Android-changed: Skip codePointBeforeImpl optimization that needs access to java chars.
+        // BEGIN Android-changed: delegate codePointBefore to Character class.
+        /*
+        if (isLatin1()) {
+            return (value[i] & 0xff);
+        }
+        return StringUTF16.codePointBefore(value, index);
+         */
         return Character.codePointBefore(this, index);
     }
 
@@ -701,11 +897,19 @@
      * @since  1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
-        if (beginIndex < 0 || endIndex > length() || beginIndex > endIndex) {
+        if (beginIndex < 0 || beginIndex > endIndex ||
+            endIndex > length()) {
             throw new IndexOutOfBoundsException();
         }
-        // Android-changed: Skip codePointCountImpl optimization that needs access to java chars.
+        // BEGIN Android-changed: delegate codePointCount to Character class.
+        /*
+        if (isLatin1()) {
+            return endIndex - beginIndex;
+        }
+        return StringUTF16.codePointCount(value, beginIndex, endIndex);
+         */
         return Character.codePointCount(this, beginIndex, endIndex);
+        // END Android-changed: delegate codePointCount to Character class.
     }
 
     /**
@@ -732,7 +936,6 @@
         if (index < 0 || index > length()) {
             throw new IndexOutOfBoundsException();
         }
-        // Android-changed: Skip offsetByCodePointsImpl optimization that needs access to java chars
         return Character.offsetByCodePoints(this, index, codePointOffset);
     }
 
@@ -742,6 +945,7 @@
      */
     void getChars(char dst[], int dstBegin) {
         // Android-changed: Replace arraycopy with native call since chars are managed by runtime.
+        // System.arraycopy(value, 0, dst, dstBegin, value.length);
         getCharsNoCheck(0, length(), dst, dstBegin);
     }
 
@@ -776,23 +980,21 @@
      *                {@code dst.length}</ul>
      */
     public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
-        // BEGIN Android-changed: Implement in terms of length() and native getCharsNoCheck method.
+        // BEGIN Android-added: Null pointer check.
         if (dst == null) {
             throw new NullPointerException("dst == null");
         }
-
-        if (srcBegin < 0) {
-            throw new StringIndexOutOfBoundsException(this, srcBegin);
+        // END Android-added: Null pointer check.
+        checkBoundsBeginEnd(srcBegin, srcEnd, length());
+        // BEGIN Android-changed: Implement in terms of length() and native getCharsNoCheck method.
+        /*
+        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
+        if (isLatin1()) {
+            StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);
         }
-        if (srcEnd > length()) {
-            throw new StringIndexOutOfBoundsException(this, srcEnd);
-        }
-
-        int n = srcEnd - srcBegin;
-        if (srcEnd < srcBegin) {
-            throw new StringIndexOutOfBoundsException(this, srcBegin, n);
-        }
-
+        */
         if (dstBegin < 0) {
             throw new ArrayIndexOutOfBoundsException("dstBegin < 0. dstBegin=" + dstBegin);
         }
@@ -802,6 +1004,8 @@
             throw new ArrayIndexOutOfBoundsException(
                     "dstBegin > dst.length. dstBegin=" + dstBegin + ", dst.length=" + dst.length);
         }
+
+        int n = srcEnd - srcBegin;
         if (n > dst.length - dstBegin) {
             throw new ArrayIndexOutOfBoundsException(
                     "n > dst.length - dstBegin. n=" + n + ", dst.length=" + dst.length
@@ -865,18 +1069,19 @@
      *                 dst.length}
      *          </ul>
      */
-    @Deprecated
+    @Deprecated(since="1.1")
     public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
-        if (srcBegin < 0) {
-            throw new StringIndexOutOfBoundsException(this, srcBegin);
+        checkBoundsBeginEnd(srcBegin, srcEnd, length());
+        Objects.requireNonNull(dst);
+        checkBoundsOffCount(dstBegin, srcEnd - srcBegin, dst.length);
+        // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        if (isLatin1()) {
+            StringLatin1.getBytes(value, srcBegin, srcEnd, dst, dstBegin);
+        } else {
+            StringUTF16.getBytes(value, srcBegin, srcEnd, dst, dstBegin);
         }
-        if (srcEnd > length()) {
-            throw new StringIndexOutOfBoundsException(this, srcEnd);
-        }
-        if (srcBegin > srcEnd) {
-            throw new StringIndexOutOfBoundsException(this, srcEnd - srcBegin);
-        }
-
+         */
         int j = dstBegin;
         int n = srcEnd;
         int i = srcBegin;
@@ -884,6 +1089,7 @@
         while (i < n) {
             dst[j++] = (byte)charAt(i++);
         }
+        // END Android-changed: Implement in terms of charAt().
     }
 
     /**
@@ -904,14 +1110,17 @@
      * @throws  UnsupportedEncodingException
      *          If the named charset is not supported
      *
-     * @since  JDK1.1
+     * @since  1.1
      */
     public byte[] getBytes(String charsetName)
             throws UnsupportedEncodingException {
         if (charsetName == null) throw new NullPointerException();
-        // Android-changed: Skip StringCoding optimization that needs access to java chars.
-        // return StringCoding.encode(charsetName, value, 0, value.length);
+        // BEGIN Android-changed: Skip StringCoding optimization that needs access to java chars.
+        /*
+        return StringCoding.encode(charsetName, coder(), value);
+         */
         return getBytes(Charset.forNameUEE(charsetName));
+        // END Android-changed: Skip StringCoding optimization that needs access to java chars.
     }
 
     /**
@@ -933,13 +1142,11 @@
      * @since  1.6
      */
     public byte[] getBytes(Charset charset) {
+        if (charset == null) throw new NullPointerException();
         // BEGIN Android-changed: Skip StringCoding optimization that needs access to java chars.
-        // if (charset == null) throw new NullPointerException();
-        // return StringCoding.encode(charset, value, 0, value.length);
-        if (charset == null) {
-            throw new NullPointerException("charset == null");
-        }
-
+        /*
+        return StringCoding.encode(charset, coder(), value);
+        */
         final int len = length();
         final String name = charset.name();
         if ("UTF-8".equals(name)) {
@@ -970,12 +1177,15 @@
      *
      * @return  The resultant byte array
      *
-     * @since      JDK1.1
+     * @since      1.1
      */
     public byte[] getBytes() {
-        // Android-changed: Skip StringCoding optimization that needs access to java chars.
-        // return StringCoding.encode(value, 0, value.length);
+        // BEGIN Android-changed: Skip StringCoding optimization that needs access to java chars.
+        /*
+        return StringCoding.encode(coder(), value);
+         */
         return getBytes(Charset.defaultCharset());
+        // END Android-changed: Skip StringCoding optimization that needs access to java chars.
     }
 
     /**
@@ -984,6 +1194,9 @@
      * String} object that represents the same sequence of characters as this
      * object.
      *
+     * <p>For finer-grained String comparison, refer to
+     * {@link java.text.Collator}.
+     *
      * @param  anObject
      *         The object to compare this {@code String} against
      *
@@ -998,6 +1211,14 @@
             return true;
         }
         if (anObject instanceof String) {
+            // BEGIN Android-changed: Implement in terms of charAt().
+            /*
+            String aString = (String)anObject;
+            if (coder() == aString.coder()) {
+                return isLatin1() ? StringLatin1.equals(value, aString.value)
+                                  : StringUTF16.equals(value, aString.value);
+            }
+             */
             String anotherString = (String)anObject;
             int n = length();
             if (n == anotherString.length()) {
@@ -1009,6 +1230,7 @@
                 }
                 return true;
             }
+            // END Android-changed: Implement in terms of charAt().
         }
         return false;
     }
@@ -1019,6 +1241,9 @@
      * sequence of characters as the specified {@code StringBuffer}. This method
      * synchronizes on the {@code StringBuffer}.
      *
+     * <p>For finer-grained String comparison, refer to
+     * {@link java.text.Collator}.
+     *
      * @param  sb
      *         The {@code StringBuffer} to compare this {@code String} against
      *
@@ -1033,16 +1258,35 @@
     }
 
     private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
-        char v2[] = sb.getValue();
-        int n = length();
-        if (n != sb.length()) {
+        int len = length();
+        if (len != sb.length()) {
             return false;
         }
-        for (int i = 0; i < n; i++) {
+        // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        byte v1[] = value;
+        byte v2[] = sb.getValue();
+        if (coder() == sb.getCoder()) {
+            int n = v1.length;
+            for (int i = 0; i < n; i++) {
+                if (v1[i] != v2[i]) {
+                    return false;
+                }
+            }
+        } else {
+            if (!isLatin1()) {  // utf16 str and latin1 abs can never be "equal"
+                return false;
+            }
+            return StringUTF16.contentEquals(v1, v2, len);
+        }
+         */
+        char[] v2 = sb.getValue();
+        for (int i = 0; i < len; i++) {
             if (charAt(i) != v2[i]) {
                 return false;
             }
         }
+        // END Android-changed: Implement in terms of charAt().
         return true;
     }
 
@@ -1053,6 +1297,9 @@
      * {@code CharSequence} is a {@code StringBuffer} then the method
      * synchronizes on it.
      *
+     * <p>For finer-grained String comparison, refer to
+     * {@link java.text.Collator}.
+     *
      * @param  cs
      *         The sequence to compare this {@code String} against
      *
@@ -1078,12 +1325,25 @@
             return equals(cs);
         }
         // Argument is a generic CharSequence
-        int n = length();
-        if (n != cs.length()) {
+        int n = cs.length();
+        if (n != length()) {
             return false;
         }
+        // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        byte[] val = this.value;
+        if (isLatin1()) {
+            for (int i = 0; i < n; i++) {
+                if ((val[i] & 0xff) != cs.charAt(i)) {
+                    return false;
+                }
+            }
+        } else {
+            if (!StringUTF16.contentEquals(val, cs, n)) {
+         */
         for (int i = 0; i < n; i++) {
             if (charAt(i) != cs.charAt(i)) {
+        // END Android-changed: Implement in terms of charAt().
                 return false;
             }
         }
@@ -1101,14 +1361,14 @@
      * <ul>
      *   <li> The two characters are the same (as compared by the
      *        {@code ==} operator)
-     *   <li> Applying the method {@link
-     *        java.lang.Character#toUpperCase(char)} to each character
-     *        produces the same result
-     *   <li> Applying the method {@link
-     *        java.lang.Character#toLowerCase(char)} to each character
-     *        produces the same result
+     *   <li> Calling {@code Character.toLowerCase(Character.toUpperCase(char))}
+     *        on each character produces the same result
      * </ul>
      *
+     * <p>Note that this method does <em>not</em> take locale into account, and
+     * will result in unsatisfactory results for certain locales.  The
+     * {@link java.text.Collator} class provides locale-sensitive comparison.
+     *
      * @param  anotherString
      *         The {@code String} to compare this {@code String} against
      *
@@ -1119,6 +1379,7 @@
      * @see  #equals(Object)
      */
     public boolean equalsIgnoreCase(String anotherString) {
+        // Android-added: Cache length() result so it's called once.
         final int len = length();
         return (this == anotherString) ? true
                 : (anotherString != null)
@@ -1145,7 +1406,7 @@
      * or both. If they have different characters at one or more index
      * positions, let <i>k</i> be the smallest such index; then the string
      * whose character at position <i>k</i> has the smaller value, as
-     * determined by using the &lt; operator, lexicographically precedes the
+     * determined by using the {@code <} operator, lexicographically precedes the
      * other string. In this case, {@code compareTo} returns the
      * difference of the two character values at position {@code k} in
      * the two string -- that is, the value:
@@ -1160,6 +1421,9 @@
      * this.length()-anotherString.length()
      * </pre></blockquote>
      *
+     * <p>For finer-grained String comparison, refer to
+     * {@link java.text.Collator}.
+     *
      * @param   anotherString   the {@code String} to be compared.
      * @return  the value {@code 0} if the argument string is equal to
      *          this string; a value less than {@code 0} if this string
@@ -1168,6 +1432,18 @@
      *          lexicographically greater than the string argument.
      */
     // BEGIN Android-changed: Replace with implementation in runtime to access chars (see above).
+    /*
+    public int compareTo(String anotherString) {
+        byte v1[] = value;
+        byte v2[] = anotherString.value;
+        if (coder() == anotherString.coder()) {
+            return isLatin1() ? StringLatin1.compareTo(v1, v2)
+                              : StringUTF16.compareTo(v1, v2);
+        }
+        return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
+                          : StringUTF16.compareToLatin1(v1, v2);
+     }
+    */
     @FastNative
     public native int compareTo(String anotherString);
     // END Android-changed: Replace with implementation in runtime to access chars (see above).
@@ -1178,10 +1454,9 @@
      * <p>
      * Note that this Comparator does <em>not</em> take locale into account,
      * and will result in an unsatisfactory ordering for certain locales.
-     * The java.text package provides <em>Collators</em> to allow
-     * locale-sensitive ordering.
+     * The {@link java.text.Collator} class provides locale-sensitive comparison.
      *
-     * @see     java.text.Collator#compare(String, String)
+     * @see     java.text.Collator
      * @since   1.2
      */
     public static final Comparator<String> CASE_INSENSITIVE_ORDER
@@ -1192,6 +1467,17 @@
         private static final long serialVersionUID = 8575799808933029326L;
 
         public int compare(String s1, String s2) {
+            // BEGIN Android-changed: Implement in terms of charAt().
+            /*
+            byte v1[] = s1.value;
+            byte v2[] = s2.value;
+            if (s1.coder() == s2.coder()) {
+                return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2)
+                                     : StringUTF16.compareToCI(v1, v2);
+            }
+            return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2)
+                                 : StringUTF16.compareToCI_Latin1(v1, v2);
+             */
             int n1 = s1.length();
             int n2 = s2.length();
             int min = Math.min(n1, n2);
@@ -1212,6 +1498,7 @@
                 }
             }
             return n1 - n2;
+            // END Android-changed: Implement in terms of charAt().
         }
 
         /** Replaces the de-serialized object. */
@@ -1228,14 +1515,13 @@
      * <p>
      * Note that this method does <em>not</em> take locale into account,
      * and will result in an unsatisfactory ordering for certain locales.
-     * The java.text package provides <em>collators</em> to allow
-     * locale-sensitive ordering.
+     * The {@link java.text.Collator} class provides locale-sensitive comparison.
      *
      * @param   str   the {@code String} to be compared.
      * @return  a negative integer, zero, or a positive integer as the
      *          specified String is greater than, equal to, or less
      *          than this String, ignoring case considerations.
-     * @see     java.text.Collator#compare(String, String)
+     * @see     java.text.Collator
      * @since   1.2
      */
     public int compareToIgnoreCase(String str) {
@@ -1265,6 +1551,9 @@
      * <i>k</i>{@code )}
      * </ul>
      *
+     * <p>Note that this method does <em>not</em> take locale into account.  The
+     * {@link java.text.Collator} class provides locale-sensitive comparison.
+     *
      * @param   toffset   the starting offset of the subregion in this string.
      * @param   other     the string argument.
      * @param   ooffset   the starting offset of the subregion in the string
@@ -1274,19 +1563,51 @@
      *          exactly matches the specified subregion of the string argument;
      *          {@code false} otherwise.
      */
-    public boolean regionMatches(int toffset, String other, int ooffset,
-            int len) {
-        int to = toffset;
-        int po = ooffset;
+    public boolean regionMatches(int toffset, String other, int ooffset, int len) {
+        // BEGIN Android-removed: Implement in terms of charAt().
+        /*
+        byte tv[] = value;
+        byte ov[] = other.value;
+         */
         // Note: toffset, ooffset, or len might be near -1>>>1.
-        if ((ooffset < 0) || (toffset < 0)
-                || (toffset > (long)length() - len)
-                || (ooffset > (long)other.length() - len)) {
+        if ((ooffset < 0) || (toffset < 0) ||
+             (toffset > (long)length() - len) ||
+             (ooffset > (long)other.length() - len)) {
             return false;
         }
+        // BEGIN Android-removed: Implement in terms of charAt().
+        /*
+        if (coder() == other.coder()) {
+            if (!isLatin1() && (len > 0)) {
+                toffset = toffset << 1;
+                ooffset = ooffset << 1;
+                len = len << 1;
+            }
+            while (len-- > 0) {
+                if (tv[toffset++] != ov[ooffset++]) {
+                    return false;
+                }
+            }
+        } else {
+            if (coder() == LATIN1) {
+                while (len-- > 0) {
+                    if (StringLatin1.getChar(tv, toffset++) !=
+                        StringUTF16.getChar(ov, ooffset++)) {
+                        return false;
+                    }
+                }
+            } else {
+                while (len-- > 0) {
+                    if (StringUTF16.getChar(tv, toffset++) !=
+                        StringLatin1.getChar(ov, ooffset++)) {
+                        return false;
+                    }
+                }
+         */
         while (len-- > 0) {
-            if (charAt(to++) != other.charAt(po++)) {
+            if (charAt(toffset++) != other.charAt(ooffset++)) {
                 return false;
+        // END Android-removed: Implement in terms of charAt().
             }
         }
         return true;
@@ -1318,16 +1639,16 @@
      * <li>{@code ignoreCase} is {@code true} and there is some nonnegative
      * integer <i>k</i> less than {@code len} such that:
      * <blockquote><pre>
-     * Character.toLowerCase(this.charAt(toffset+k)) !=
-     Character.toLowerCase(other.charAt(ooffset+k))
-     * </pre></blockquote>
-     * and:
-     * <blockquote><pre>
-     * Character.toUpperCase(this.charAt(toffset+k)) !=
-     *         Character.toUpperCase(other.charAt(ooffset+k))
+     * Character.toLowerCase(Character.toUpperCase(this.charAt(toffset+k))) !=
+     Character.toLowerCase(Character.toUpperCase(other.charAt(ooffset+k)))
      * </pre></blockquote>
      * </ul>
      *
+     * <p>Note that this method does <em>not</em> take locale into account,
+     * and will result in unsatisfactory results for certain locales when
+     * {@code ignoreCase} is {@code true}.  The {@link java.text.Collator} class
+     * provides locale-sensitive comparison.
+     *
      * @param   ignoreCase   if {@code true}, ignore case when comparing
      *                       characters.
      * @param   toffset      the starting offset of the subregion in this
@@ -1344,17 +1665,31 @@
      */
     public boolean regionMatches(boolean ignoreCase, int toffset,
             String other, int ooffset, int len) {
-        int to = toffset;
-        int po = ooffset;
+        if (!ignoreCase) {
+            return regionMatches(toffset, other, ooffset, len);
+        }
         // Note: toffset, ooffset, or len might be near -1>>>1.
         if ((ooffset < 0) || (toffset < 0)
                 || (toffset > (long)length() - len)
                 || (ooffset > (long)other.length() - len)) {
             return false;
         }
+        // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        byte tv[] = value;
+        byte ov[] = other.value;
+        if (coder() == other.coder()) {
+            return isLatin1()
+              ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len)
+              : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len);
+        }
+        return isLatin1()
+              ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len)
+              : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len);
+         */
         while (len-- > 0) {
-            char c1 = charAt(to++);
-            char c2 = other.charAt(po++);
+            char c1 = charAt(toffset++);
+            char c2 = other.charAt(ooffset++);
             if (c1 == c2) {
                 continue;
             }
@@ -1379,6 +1714,7 @@
             return false;
         }
         return true;
+        // END Android-changed: Implement in terms of charAt().
     }
 
     /**
@@ -1399,17 +1735,42 @@
      *          </pre>
      */
     public boolean startsWith(String prefix, int toffset) {
-        int to = toffset;
-        int po = 0;
+        // Android-added: Cache length() result so it's called once.
         int pc = prefix.length();
         // Note: toffset might be near -1>>>1.
-        if ((toffset < 0) || (toffset > length() - pc)) {
+        if (toffset < 0 || toffset > length() - pc) {
             return false;
         }
-        while (--pc >= 0) {
-            if (charAt(to++) != prefix.charAt(po++)) {
+        // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        byte ta[] = value;
+        byte pa[] = prefix.value;
+        int po = 0;
+        int pc = pa.length;
+        if (coder() == prefix.coder()) {
+            int to = isLatin1() ? toffset : toffset << 1;
+            while (po < pc) {
+                if (ta[to++] != pa[po++]) {
+                    return false;
+                }
+            }
+        } else {
+            if (isLatin1()) {  // && pcoder == UTF16
                 return false;
             }
+            // coder == UTF16 && pcoder == LATIN1)
+            while (po < pc) {
+                if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 0xff)) {
+                    return false;
+               }
+            }
+         */
+        int po = 0;
+        while (--pc >= 0) {
+            if (charAt(toffset++) != prefix.charAt(po++)) {
+                return false;
+            }
+        // END Android-changed: Implement in terms of charAt().
         }
         return true;
     }
@@ -1425,7 +1786,7 @@
      *          argument is an empty string or is equal to this
      *          {@code String} object as determined by the
      *          {@link #equals(Object)} method.
-     * @since   1. 0
+     * @since   1.0
      */
     public boolean startsWith(String prefix) {
         return startsWith(prefix, 0);
@@ -1461,12 +1822,19 @@
      */
     public int hashCode() {
         int h = hash;
+        // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        if (h == 0 && value.length > 0) {
+            hash = h = isLatin1() ? StringLatin1.hashCode(value)
+                                  : StringUTF16.hashCode(value);
+         */
         final int len = length();
         if (h == 0 && len > 0) {
             for (int i = 0; i < len; i++) {
                 h = 31 * h + charAt(i);
             }
             hash = h;
+        // END Android-changed: Implement in terms of charAt().
         }
         return h;
     }
@@ -1539,6 +1907,11 @@
      *          if the character does not occur.
      */
     public int indexOf(int ch, int fromIndex) {
+    // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        return isLatin1() ? StringLatin1.indexOf(value, ch, fromIndex)
+                          : StringUTF16.indexOf(value, ch, fromIndex);
+         */
         final int max = length();
         if (fromIndex < 0) {
             fromIndex = 0;
@@ -1576,6 +1949,7 @@
             }
         }
         return -1;
+    // END Android-changed: Implement in terms of charAt().
     }
 
     /**
@@ -1640,6 +2014,11 @@
      *          if the character does not occur before that point.
      */
     public int lastIndexOf(int ch, int fromIndex) {
+    // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        return isLatin1() ? StringLatin1.lastIndexOf(value, ch, fromIndex)
+                          : StringUTF16.lastIndexOf(value, ch, fromIndex);
+         */
         if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
             // handle most cases here (ch is a BMP code point or a
             // negative value (invalid code point))
@@ -1670,35 +2049,49 @@
             }
         }
         return -1;
+    // END Android-changed: Implement in terms of charAt().
     }
 
     /**
      * Returns the index within this string of the first occurrence of the
      * specified substring.
      *
-     * <p>The returned index is the smallest value <i>k</i> for which:
-     * <blockquote><pre>
-     * this.startsWith(str, <i>k</i>)
-     * </pre></blockquote>
-     * If no such value of <i>k</i> exists, then {@code -1} is returned.
+     * <p>The returned index is the smallest value {@code k} for which:
+     * <pre>{@code
+     * this.startsWith(str, k)
+     * }</pre>
+     * If no such value of {@code k} exists, then {@code -1} is returned.
      *
      * @param   str   the substring to search for.
      * @return  the index of the first occurrence of the specified substring,
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str) {
+        // BEGIN Android-changed: Implement with indexOf() method that takes String parameters.
+        /*
+        if (coder() == str.coder()) {
+            return isLatin1() ? StringLatin1.indexOf(value, str.value)
+                              : StringUTF16.indexOf(value, str.value);
+        }
+        if (coder() == LATIN1) {  // str.coder == UTF16
+            return -1;
+        }
+        return StringUTF16.indexOfLatin1(value, str.value);
+         */
         return indexOf(str, 0);
+        // END Android-changed: Implement with indexOf() method that takes String parameters.
     }
 
     /**
      * Returns the index within this string of the first occurrence of the
      * specified substring, starting at the specified index.
      *
-     * <p>The returned index is the smallest value <i>k</i> for which:
-     * <blockquote><pre>
-     * <i>k</i> &gt;= fromIndex {@code &&} this.startsWith(str, <i>k</i>)
-     * </pre></blockquote>
-     * If no such value of <i>k</i> exists, then {@code -1} is returned.
+     * <p>The returned index is the smallest value {@code k} for which:
+     * <pre>{@code
+     *     k >= Math.min(fromIndex, this.length()) &&
+     *                   this.startsWith(str, k)
+     * }</pre>
+     * If no such value of {@code k} exists, then {@code -1} is returned.
      *
      * @param   str         the substring to search for.
      * @param   fromIndex   the index from which to start the search.
@@ -1707,8 +2100,12 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int indexOf(String str, int fromIndex) {
-        // Android-changed: Delegate to the static indexOf method below.
+        // BEGIN Android-changed: Implement with indexOf() method that takes String parameters.
+        /*
+        return indexOf(value, coder(), length(), str, fromIndex);
+         */
         return indexOf(this, str, fromIndex);
+        // END Android-changed: Implement with indexOf() method that takes String parameters.
     }
 
     // BEGIN Android-added: Private static indexOf method that takes String parameters.
@@ -1833,11 +2230,11 @@
      * specified substring.  The last occurrence of the empty string ""
      * is considered to occur at the index value {@code this.length()}.
      *
-     * <p>The returned index is the largest value <i>k</i> for which:
-     * <blockquote><pre>
-     * this.startsWith(str, <i>k</i>)
-     * </pre></blockquote>
-     * If no such value of <i>k</i> exists, then {@code -1} is returned.
+     * <p>The returned index is the largest value {@code k} for which:
+     * <pre>{@code
+     * this.startsWith(str, k)
+     * }</pre>
+     * If no such value of {@code k} exists, then {@code -1} is returned.
      *
      * @param   str   the substring to search for.
      * @return  the index of the last occurrence of the specified substring,
@@ -1851,11 +2248,12 @@
      * Returns the index within this string of the last occurrence of the
      * specified substring, searching backward starting at the specified index.
      *
-     * <p>The returned index is the largest value <i>k</i> for which:
-     * <blockquote><pre>
-     * <i>k</i> {@code <=} fromIndex {@code &&} this.startsWith(str, <i>k</i>)
-     * </pre></blockquote>
-     * If no such value of <i>k</i> exists, then {@code -1} is returned.
+     * <p>The returned index is the largest value {@code k} for which:
+     * <pre>{@code
+     *     k <= Math.min(fromIndex, this.length()) &&
+     *                   this.startsWith(str, k)
+     * }</pre>
+     * If no such value of {@code k} exists, then {@code -1} is returned.
      *
      * @param   str         the substring to search for.
      * @param   fromIndex   the index to start the search from.
@@ -1864,8 +2262,12 @@
      *          or {@code -1} if there is no such occurrence.
      */
     public int lastIndexOf(String str, int fromIndex) {
-        // Android-changed: Change parameters to static lastIndexOf to match new signature below.
+        // BEGIN Android-changed: Implement with static lastIndexOf() that takes String parameters.
+        /*
+        return lastIndexOf(value, coder(), length(), str, fromIndex);
+         */
         return lastIndexOf(this, str, fromIndex);
+        // END Android-changed: Implement with static lastIndexOf() that takes String parameters.
     }
 
     // BEGIN Android-added: Private static lastIndexOf method that takes String parameters.
@@ -2026,8 +2428,16 @@
         if (subLen < 0) {
             throw new StringIndexOutOfBoundsException(this, beginIndex);
         }
-        // Android-changed: Use native fastSubstring instead of String constructor.
-        return (beginIndex == 0) ? this : fastSubstring(beginIndex, subLen);
+        if (beginIndex == 0) {
+            return this;
+        }
+        // BEGIN Android-changed: Use native fastSubstring instead of String constructor.
+        /*
+        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
+                          : StringUTF16.newString(value, beginIndex, subLen);
+         */
+        return fastSubstring(beginIndex, subLen);
+        // END Android-changed: Use native fastSubstring instead of String constructor.
     }
 
     /**
@@ -2053,20 +2463,20 @@
      *             {@code endIndex}.
      */
     public String substring(int beginIndex, int endIndex) {
-        if (beginIndex < 0) {
-            throw new StringIndexOutOfBoundsException(this, beginIndex);
-        }
-        if (endIndex > length()) {
-            throw new StringIndexOutOfBoundsException(this, endIndex);
-        }
+        int length = length();
+        checkBoundsBeginEnd(beginIndex, endIndex, length);
         int subLen = endIndex - beginIndex;
-        if (subLen < 0) {
-            throw new StringIndexOutOfBoundsException(subLen);
+        if (beginIndex == 0 && endIndex == length) {
+            return this;
         }
 
-        // Android-changed: Use native fastSubstring instead of String constructor.
-        return ((beginIndex == 0) && (endIndex == length())) ? this
-                : fastSubstring(beginIndex, subLen);
+        // BEGIN Android-changed: Use native fastSubstring instead of String constructor.
+        /*
+        return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
+                          : StringUTF16.newString(value, beginIndex, subLen);
+         */
+        return fastSubstring(beginIndex, subLen);
+        // END Android-changed: Use native fastSubstring instead of String constructor.
     }
 
     // BEGIN Android-added: Native method to access char storage managed by runtime.
@@ -2128,6 +2538,27 @@
      *          characters followed by the string argument's characters.
      */
     // BEGIN Android-changed: Replace with implementation in runtime to access chars (see above).
+    /*
+    public String concat(String str) {
+        if (str.isEmpty()) {
+            return this;
+        }
+        if (coder() == str.coder()) {
+            byte[] val = this.value;
+            byte[] oval = str.value;
+            int len = val.length + oval.length;
+            byte[] buf = Arrays.copyOf(val, len);
+            System.arraycopy(oval, 0, buf, val.length, oval.length);
+            return new String(buf, coder);
+        }
+        int len = length();
+        int olen = str.length();
+        byte[] buf = StringUTF16.newBytesFor(len + olen);
+        getBytes(buf, 0, UTF16);
+        str.getBytes(buf, len, UTF16);
+        return new String(buf, UTF16);
+    }
+    */
     @FastNative
     public native String concat(String str);
     // END Android-changed: Replace with implementation in runtime to access chars (see above).
@@ -2164,6 +2595,13 @@
     public String replace(char oldChar, char newChar) {
         // BEGIN Android-changed: Replace with implementation using native doReplace method.
         if (oldChar != newChar) {
+            /*
+            String ret = isLatin1() ? StringLatin1.replace(value, oldChar, newChar)
+                                    : StringUTF16.replace(value, oldChar, newChar);
+            if (ret != null) {
+                return ret;
+            }
+            */
             final int len = length();
             for (int i = 0; i < len; ++i) {
                 if (charAt(i) == oldChar) {
@@ -2221,7 +2659,7 @@
      * @since 1.5
      */
     public boolean contains(CharSequence s) {
-        return indexOf(s.toString()) > -1;
+        return indexOf(s.toString()) >= 0;
     }
 
     /**
@@ -2327,63 +2765,32 @@
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
-        // BEGIN Android-changed: Replace regex-based implementation with a bespoke one.
-        if (target == null) {
-            throw new NullPointerException("target == null");
-        }
+        // BEGIN Android-added: Additional null check for parameters.
+        Objects.requireNonNull(target);
+        Objects.requireNonNull(replacement);
+        // END Android-added: Additional null check for parameters.
 
-        if (replacement == null) {
-            throw new NullPointerException("replacement == null");
-        }
-
-        String replacementStr = replacement.toString();
-        String targetStr = target.toString();
-
-        // Special case when target == "". This is a pretty nonsensical transformation and nobody
-        // should be hitting this.
-        //
-        // See commit 870b23b3febc85 and http://code.google.com/p/android/issues/detail?id=8807
-        // An empty target is inserted at the start of the string, the end of the string and
-        // between all characters.
-        final int len = length();
-        if (targetStr.isEmpty()) {
-            // Note that overallocates by |replacement.size()| if |this| is the empty string, but
-            // that should be a rare case within an already nonsensical case.
-            StringBuilder sb = new StringBuilder(replacementStr.length() * (len + 2) + len);
-            sb.append(replacementStr);
-            for (int i = 0; i < len; ++i) {
-                sb.append(charAt(i));
-                sb.append(replacementStr);
-            }
-
-            return sb.toString();
-        }
-
-        // This is the "regular" case.
-        int lastMatch = 0;
-        StringBuilder sb = null;
-        for (;;) {
-            int currentMatch = indexOf(this, targetStr, lastMatch);
-            if (currentMatch == -1) {
-                break;
-            }
-
-            if (sb == null) {
-                sb = new StringBuilder(len);
-            }
-
-            sb.append(this, lastMatch, currentMatch);
-            sb.append(replacementStr);
-            lastMatch = currentMatch + targetStr.length();
-        }
-
-        if (sb != null) {
-            sb.append(this, lastMatch, len);
-            return sb.toString();
-        } else {
+        String tgtStr = target.toString();
+        String replStr = replacement.toString();
+        int j = indexOf(tgtStr);
+        if (j < 0) {
             return this;
         }
-        // END Android-changed: Replace regex-based implementation with a bespoke one.
+        int tgtLen = tgtStr.length();
+        int tgtLen1 = Math.max(tgtLen, 1);
+        int thisLen = length();
+
+        int newLenHint = thisLen - tgtLen + replStr.length();
+        if (newLenHint < 0) {
+            throw new OutOfMemoryError();
+        }
+        StringBuilder sb = new StringBuilder(newLenHint);
+        int i = 0;
+        do {
+            sb.append(this, i, j).append(replStr);
+            i = j + tgtLen;
+        } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
+        return sb.append(this, i, thisLen).toString();
     }
 
     /**
@@ -2404,42 +2811,56 @@
      *
      * <p> The {@code limit} parameter controls the number of times the
      * pattern is applied and therefore affects the length of the resulting
-     * array.  If the limit <i>n</i> is greater than zero then the pattern
-     * will be applied at most <i>n</i>&nbsp;-&nbsp;1 times, the array's
-     * length will be no greater than <i>n</i>, and the array's last entry
-     * will contain all input beyond the last matched delimiter.  If <i>n</i>
-     * is non-positive then the pattern will be applied as many times as
-     * possible and the array can have any length.  If <i>n</i> is zero then
-     * the pattern will be applied as many times as possible, the array can
-     * have any length, and trailing empty strings will be discarded.
+     * array.
+     * <ul>
+     *    <li><p>
+     *    If the <i>limit</i> is positive then the pattern will be applied
+     *    at most <i>limit</i>&nbsp;-&nbsp;1 times, the array's length will be
+     *    no greater than <i>limit</i>, and the array's last entry will contain
+     *    all input beyond the last matched delimiter.</p></li>
+     *
+     *    <li><p>
+     *    If the <i>limit</i> is zero then the pattern will be applied as
+     *    many times as possible, the array can have any length, and trailing
+     *    empty strings will be discarded.</p></li>
+     *
+     *    <li><p>
+     *    If the <i>limit</i> is negative then the pattern will be applied
+     *    as many times as possible and the array can have any length.</p></li>
+     * </ul>
      *
      * <p> The string {@code "boo:and:foo"}, for example, yields the
      * following results with these parameters:
      *
-     * <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result">
+     * <blockquote><table class="plain">
+     * <caption style="display:none">Split example showing regex, limit, and result</caption>
+     * <thead>
      * <tr>
-     *     <th>Regex</th>
-     *     <th>Limit</th>
-     *     <th>Result</th>
+     *     <th scope="col">Regex</th>
+     *     <th scope="col">Limit</th>
+     *     <th scope="col">Result</th>
      * </tr>
-     * <tr><td align=center>:</td>
-     *     <td align=center>2</td>
+     * </thead>
+     * <tbody>
+     * <tr><th scope="row" rowspan="3" style="font-weight:normal">:</th>
+     *     <th scope="row" style="font-weight:normal; text-align:right; padding-right:1em">2</th>
      *     <td>{@code { "boo", "and:foo" }}</td></tr>
-     * <tr><td align=center>:</td>
-     *     <td align=center>5</td>
+     * <tr><!-- : -->
+     *     <th scope="row" style="font-weight:normal; text-align:right; padding-right:1em">5</th>
      *     <td>{@code { "boo", "and", "foo" }}</td></tr>
-     * <tr><td align=center>:</td>
-     *     <td align=center>-2</td>
+     * <tr><!-- : -->
+     *     <th scope="row" style="font-weight:normal; text-align:right; padding-right:1em">-2</th>
      *     <td>{@code { "boo", "and", "foo" }}</td></tr>
-     * <tr><td align=center>o</td>
-     *     <td align=center>5</td>
+     * <tr><th scope="row" rowspan="3" style="font-weight:normal">o</th>
+     *     <th scope="row" style="font-weight:normal; text-align:right; padding-right:1em">5</th>
      *     <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
-     * <tr><td align=center>o</td>
-     *     <td align=center>-2</td>
+     * <tr><!-- o -->
+     *     <th scope="row" style="font-weight:normal; text-align:right; padding-right:1em">-2</th>
      *     <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
-     * <tr><td align=center>o</td>
-     *     <td align=center>0</td>
+     * <tr><!-- o -->
+     *     <th scope="row" style="font-weight:normal; text-align:right; padding-right:1em">0</th>
      *     <td>{@code { "b", "", ":and:f" }}</td></tr>
+     * </tbody>
      * </table></blockquote>
      *
      * <p> An invocation of this method of the form
@@ -2475,6 +2896,59 @@
     public String[] split(String regex, int limit) {
         // BEGIN Android-changed: Replace custom fast-path with use of new Pattern.fastSplit method.
         // Try fast splitting without allocating Pattern object
+        /*
+        /* fastpath if the regex is a
+         (1)one-char String and this character is not one of the
+            RegEx's meta characters ".$|()[{^?*+\\", or
+         (2)two-char String and the first char is the backslash and
+            the second is not the ascii digit or ascii letter.
+         *
+        char ch = 0;
+        if (((regex.length() == 1 &&
+             ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
+             (regex.length() == 2 &&
+              regex.charAt(0) == '\\' &&
+              (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
+              ((ch-'a')|('z'-ch)) < 0 &&
+              ((ch-'A')|('Z'-ch)) < 0)) &&
+            (ch < Character.MIN_HIGH_SURROGATE ||
+             ch > Character.MAX_LOW_SURROGATE))
+        {
+            int off = 0;
+            int next = 0;
+            boolean limited = limit > 0;
+            ArrayList<String> list = new ArrayList<>();
+            while ((next = indexOf(ch, off)) != -1) {
+                if (!limited || list.size() < limit - 1) {
+                    list.add(substring(off, next));
+                    off = next + 1;
+                } else {    // last one
+                    //assert (list.size() == limit - 1);
+                    int last = length();
+                    list.add(substring(off, last));
+                    off = last;
+                    break;
+                }
+            }
+            // If no match was found, return this
+            if (off == 0)
+                return new String[]{this};
+
+            // Add remaining segment
+            if (!limited || list.size() < limit)
+                list.add(substring(off, length()));
+
+            // Construct result
+            int resultSize = list.size();
+            if (limit == 0) {
+                while (resultSize > 0 && list.get(resultSize - 1).isEmpty()) {
+                    resultSize--;
+                }
+            }
+            String[] result = new String[resultSize];
+            return list.subList(0, resultSize).toArray(result);
+        }
+        */
         String[] fast = Pattern.fastSplit(regex, this, limit);
         if (fast != null) {
             return fast;
@@ -2495,15 +2969,20 @@
      * <p> The string {@code "boo:and:foo"}, for example, yields the following
      * results with these expressions:
      *
-     * <blockquote><table cellpadding=1 cellspacing=0 summary="Split examples showing regex and result">
+     * <blockquote><table class="plain">
+     * <caption style="display:none">Split examples showing regex and result</caption>
+     * <thead>
      * <tr>
-     *  <th>Regex</th>
-     *  <th>Result</th>
+     *  <th scope="col">Regex</th>
+     *  <th scope="col">Result</th>
      * </tr>
-     * <tr><td align=center>:</td>
+     * </thead>
+     * <tbody>
+     * <tr><th scope="row" style="text-weight:normal">:</th>
      *     <td>{@code { "boo", "and", "foo" }}</td></tr>
-     * <tr><td align=center>o</td>
+     * <tr><th scope="row" style="text-weight:normal">o</th>
      *     <td>{@code { "b", "", ":and:f" }}</td></tr>
+     * </tbody>
      * </table></blockquote>
      *
      *
@@ -2568,15 +3047,12 @@
      *
      * <blockquote>For example,
      * <pre>{@code
-     *     List<String> strings = new LinkedList<>();
-     *     strings.add("Java");strings.add("is");
-     *     strings.add("cool");
+     *     List<String> strings = List.of("Java", "is", "cool");
      *     String message = String.join(" ", strings);
      *     //message returned is: "Java is cool"
      *
-     *     Set<String> strings = new LinkedHashSet<>();
-     *     strings.add("Java"); strings.add("is");
-     *     strings.add("very"); strings.add("cool");
+     *     Set<String> strings =
+     *         new LinkedHashSet<>(List.of("Java", "is", "very", "cool"));
      *     String message = String.join("-", strings);
      *     //message returned is: "Java-is-very-cool"
      * }</pre></blockquote>
@@ -2617,41 +3093,43 @@
      * {@code String} may be a different length than the original {@code String}.
      * <p>
      * Examples of lowercase  mappings are in the following table:
-     * <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description">
+     * <table class="plain">
+     * <caption style="display:none">Lowercase mapping examples showing language code of locale, upper case, lower case, and description</caption>
+     * <thead>
      * <tr>
-     *   <th>Language Code of Locale</th>
-     *   <th>Upper Case</th>
-     *   <th>Lower Case</th>
-     *   <th>Description</th>
+     *   <th scope="col">Language Code of Locale</th>
+     *   <th scope="col">Upper Case</th>
+     *   <th scope="col">Lower Case</th>
+     *   <th scope="col">Description</th>
      * </tr>
+     * </thead>
+     * <tbody>
      * <tr>
      *   <td>tr (Turkish)</td>
-     *   <td>&#92;u0130</td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">&#92;u0130</th>
      *   <td>&#92;u0069</td>
      *   <td>capital letter I with dot above -&gt; small letter i</td>
      * </tr>
      * <tr>
      *   <td>tr (Turkish)</td>
-     *   <td>&#92;u0049</td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">&#92;u0049</th>
      *   <td>&#92;u0131</td>
      *   <td>capital letter I -&gt; small letter dotless i </td>
      * </tr>
      * <tr>
      *   <td>(all)</td>
-     *   <td>French Fries</td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">French Fries</th>
      *   <td>french fries</td>
      *   <td>lowercased all chars in String</td>
      * </tr>
      * <tr>
      *   <td>(all)</td>
-     *   <td><img src="doc-files/capiota.gif" alt="capiota"><img src="doc-files/capchi.gif" alt="capchi">
-     *       <img src="doc-files/captheta.gif" alt="captheta"><img src="doc-files/capupsil.gif" alt="capupsil">
-     *       <img src="doc-files/capsigma.gif" alt="capsigma"></td>
-     *   <td><img src="doc-files/iota.gif" alt="iota"><img src="doc-files/chi.gif" alt="chi">
-     *       <img src="doc-files/theta.gif" alt="theta"><img src="doc-files/upsilon.gif" alt="upsilon">
-     *       <img src="doc-files/sigma1.gif" alt="sigma"></td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">
+     *       &Iota;&Chi;&Theta;&Upsilon;&Sigma;</th>
+     *   <td>&iota;&chi;&theta;&upsilon;&sigma;</td>
      *   <td>lowercased all chars in String</td>
      * </tr>
+     * </tbody>
      * </table>
      *
      * @param locale use the case transformation rules for this locale
@@ -2662,8 +3140,13 @@
      * @since   1.1
      */
     public String toLowerCase(Locale locale) {
-        // Android-changed: Replace custom code with call to new CaseMapper class.
+        // BEGIN Android-changed: Replace custom code with call to new CaseMapper class.
+        /*
+        return isLatin1() ? StringLatin1.toLowerCase(this, value, locale)
+                          : StringUTF16.toLowerCase(this, value, locale);
+        */
         return CaseMapper.toLowerCase(locale, this);
+        // END Android-changed: Replace custom code with call to new CaseMapper class.
     }
 
     /**
@@ -2681,7 +3164,7 @@
      * LATIN SMALL LETTER DOTLESS I character.
      * To obtain correct results for locale insensitive strings, use
      * {@code toLowerCase(Locale.ROOT)}.
-     * <p>
+     *
      * @return  the {@code String}, converted to lowercase.
      * @see     java.lang.String#toLowerCase(Locale)
      */
@@ -2698,37 +3181,42 @@
      * <p>
      * Examples of locale-sensitive and 1:M case mappings are in the following table.
      *
-     * <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description.">
+     * <table class="plain">
+     * <caption style="display:none">Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description.</caption>
+     * <thead>
      * <tr>
-     *   <th>Language Code of Locale</th>
-     *   <th>Lower Case</th>
-     *   <th>Upper Case</th>
-     *   <th>Description</th>
+     *   <th scope="col">Language Code of Locale</th>
+     *   <th scope="col">Lower Case</th>
+     *   <th scope="col">Upper Case</th>
+     *   <th scope="col">Description</th>
      * </tr>
+     * </thead>
+     * <tbody>
      * <tr>
      *   <td>tr (Turkish)</td>
-     *   <td>&#92;u0069</td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">&#92;u0069</th>
      *   <td>&#92;u0130</td>
      *   <td>small letter i -&gt; capital letter I with dot above</td>
      * </tr>
      * <tr>
      *   <td>tr (Turkish)</td>
-     *   <td>&#92;u0131</td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">&#92;u0131</th>
      *   <td>&#92;u0049</td>
      *   <td>small letter dotless i -&gt; capital letter I</td>
      * </tr>
      * <tr>
      *   <td>(all)</td>
-     *   <td>&#92;u00df</td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">&#92;u00df</th>
      *   <td>&#92;u0053 &#92;u0053</td>
      *   <td>small letter sharp s -&gt; two letters: SS</td>
      * </tr>
      * <tr>
      *   <td>(all)</td>
-     *   <td>Fahrvergn&uuml;gen</td>
+     *   <th scope="row" style="font-weight:normal; text-align:left">Fahrvergn&uuml;gen</th>
      *   <td>FAHRVERGN&Uuml;GEN</td>
      *   <td></td>
      * </tr>
+     * </tbody>
      * </table>
      * @param locale use the case transformation rules for this locale
      * @return the {@code String}, converted to uppercase.
@@ -2738,8 +3226,13 @@
      * @since   1.1
      */
     public String toUpperCase(Locale locale) {
-        // Android-changed: Replace custom code with call to new CaseMapper class.
+        // BEGIN Android-changed: Replace custom code with call to new CaseMapper class.
+        /*
+        return isLatin1() ? StringLatin1.toUpperCase(this, value, locale)
+                          : StringUTF16.toUpperCase(this, value, locale);
+        */
         return CaseMapper.toUpperCase(locale, this, length());
+        // END Android-changed: Replace custom code with call to new CaseMapper class.
     }
 
     /**
@@ -2757,7 +3250,7 @@
      * LATIN CAPITAL LETTER I WITH DOT ABOVE character.
      * To obtain correct results for locale insensitive strings, use
      * {@code toUpperCase(Locale.ROOT)}.
-     * <p>
+     *
      * @return  the {@code String}, converted to uppercase.
      * @see     java.lang.String#toUpperCase(Locale)
      */
@@ -2766,37 +3259,44 @@
     }
 
     /**
-     * Returns a string whose value is this string, with any leading and trailing
-     * whitespace removed.
+     * Returns a string whose value is this string, with all leading
+     * and trailing space removed, where space is defined
+     * as any character whose codepoint is less than or equal to
+     * {@code 'U+0020'} (the space character).
      * <p>
      * If this {@code String} object represents an empty character
      * sequence, or the first and last characters of character sequence
      * represented by this {@code String} object both have codes
-     * greater than {@code '\u005Cu0020'} (the space character), then a
+     * that are not space (as defined above), then a
      * reference to this {@code String} object is returned.
      * <p>
-     * Otherwise, if there is no character with a code greater than
-     * {@code '\u005Cu0020'} in the string, then a
-     * {@code String} object representing an empty string is
-     * returned.
+     * Otherwise, if all characters in this string are space (as
+     * defined above), then a  {@code String} object representing an
+     * empty string is returned.
      * <p>
      * Otherwise, let <i>k</i> be the index of the first character in the
-     * string whose code is greater than {@code '\u005Cu0020'}, and let
+     * string whose code is not a space (as defined above) and let
      * <i>m</i> be the index of the last character in the string whose code
-     * is greater than {@code '\u005Cu0020'}. A {@code String}
+     * is not a space (as defined above). A {@code String}
      * object is returned, representing the substring of this string that
      * begins with the character at index <i>k</i> and ends with the
      * character at index <i>m</i>-that is, the result of
      * {@code this.substring(k, m + 1)}.
      * <p>
-     * This method may be used to trim whitespace (as defined above) from
+     * This method may be used to trim space (as defined above) from
      * the beginning and end of a string.
      *
-     * @return  A string whose value is this string, with any leading and trailing white
-     *          space removed, or this string if it has no leading or
-     *          trailing white space.
+     * @return  a string whose value is this string, with all leading
+     *          and trailing space removed, or this string if it
+     *          has no leading or trailing space.
      */
     public String trim() {
+        // BEGIN Android-changed: Implement in terms of charAt().
+        /*
+        String ret = isLatin1() ? StringLatin1.trim(value)
+                                : StringUTF16.trim(value);
+        return ret == null ? this : ret;
+         */
         int len = length();
         int st = 0;
 
@@ -2807,6 +3307,184 @@
             len--;
         }
         return ((st > 0) || (len < length())) ? substring(st, len) : this;
+        // END Android-changed: Implement in terms of charAt().
+    }
+
+    /**
+     * Returns a string whose value is this string, with all leading
+     * and trailing {@link Character#isWhitespace(int) white space}
+     * removed.
+     * <p>
+     * If this {@code String} object represents an empty string,
+     * or if all code points in this string are
+     * {@link Character#isWhitespace(int) white space}, then an empty string
+     * is returned.
+     * <p>
+     * Otherwise, returns a substring of this string beginning with the first
+     * code point that is not a {@link Character#isWhitespace(int) white space}
+     * up to and including the last code point that is not a
+     * {@link Character#isWhitespace(int) white space}.
+     * <p>
+     * This method may be used to strip
+     * {@link Character#isWhitespace(int) white space} from
+     * the beginning and end of a string.
+     *
+     * @return  a string whose value is this string, with all leading
+     *          and trailing white space removed
+     *
+     * @see Character#isWhitespace(int)
+     *
+     * @since 11
+     */
+    public String strip() {
+        // BEGIN Android-changed: Delegate to StringUTF16.
+        /*
+        String ret = isLatin1() ? StringLatin1.strip(value)
+                                : StringUTF16.strip(value);
+         */
+        String ret = StringUTF16.strip(this);
+        // END Android-changed: Delegate to StringUTF16.
+        return ret == null ? this : ret;
+    }
+
+    /**
+     * Returns a string whose value is this string, with all leading
+     * {@link Character#isWhitespace(int) white space} removed.
+     * <p>
+     * If this {@code String} object represents an empty string,
+     * or if all code points in this string are
+     * {@link Character#isWhitespace(int) white space}, then an empty string
+     * is returned.
+     * <p>
+     * Otherwise, returns a substring of this string beginning with the first
+     * code point that is not a {@link Character#isWhitespace(int) white space}
+     * up to to and including the last code point of this string.
+     * <p>
+     * This method may be used to trim
+     * {@link Character#isWhitespace(int) white space} from
+     * the beginning of a string.
+     *
+     * @return  a string whose value is this string, with all leading white
+     *          space removed
+     *
+     * @see Character#isWhitespace(int)
+     *
+     * @since 11
+     */
+    public String stripLeading() {
+        // BEGIN Android-changed: Delegate to StringUTF16.
+        /*
+        String ret = isLatin1() ? StringLatin1.stripLeading(value)
+                                : StringUTF16.stripLeading(value);
+         */
+        String ret = StringUTF16.stripLeading(this);
+        // END Android-changed: Delegate to StringUTF16.
+        return ret == null ? this : ret;
+    }
+
+    /**
+     * Returns a string whose value is this string, with all trailing
+     * {@link Character#isWhitespace(int) white space} removed.
+     * <p>
+     * If this {@code String} object represents an empty string,
+     * or if all characters in this string are
+     * {@link Character#isWhitespace(int) white space}, then an empty string
+     * is returned.
+     * <p>
+     * Otherwise, returns a substring of this string beginning with the first
+     * code point of this string up to and including the last code point
+     * that is not a {@link Character#isWhitespace(int) white space}.
+     * <p>
+     * This method may be used to trim
+     * {@link Character#isWhitespace(int) white space} from
+     * the end of a string.
+     *
+     * @return  a string whose value is this string, with all trailing white
+     *          space removed
+     *
+     * @see Character#isWhitespace(int)
+     *
+     * @since 11
+     */
+    public String stripTrailing() {
+        // BEGIN Android-changed: Delegate to StringUTF16.
+        /*
+        String ret = isLatin1() ? StringLatin1.stripTrailing(value)
+                                : StringUTF16.stripTrailing(value);
+         */
+        String ret = StringUTF16.stripTrailing(this);
+        // END Android-changed: Delegate to StringUTF16.
+        return ret == null ? this : ret;
+    }
+
+    /**
+     * Returns {@code true} if the string is empty or contains only
+     * {@link Character#isWhitespace(int) white space} codepoints,
+     * otherwise {@code false}.
+     *
+     * @return {@code true} if the string is empty or contains only
+     *         {@link Character#isWhitespace(int) white space} codepoints,
+     *         otherwise {@code false}
+     *
+     * @see Character#isWhitespace(int)
+     *
+     * @since 11
+     */
+    public boolean isBlank() {
+        return indexOfNonWhitespace() == length();
+    }
+
+    private int indexOfNonWhitespace() {
+        // BEGIN Android-removed: Delegate to StringUTF16.
+        /*
+        if (isLatin1()) {
+            return StringLatin1.indexOfNonWhitespace(value);
+        } else {
+            return StringUTF16.indexOfNonWhitespace(value);
+        }
+         */
+        return StringUTF16.indexOfNonWhitespace(this);
+        // END Android-removed: Delegate to StringUTF16.
+    }
+
+    /**
+     * Returns a stream of lines extracted from this string,
+     * separated by line terminators.
+     * <p>
+     * A <i>line terminator</i> is one of the following:
+     * a line feed character {@code "\n"} (U+000A),
+     * a carriage return character {@code "\r"} (U+000D),
+     * or a carriage return followed immediately by a line feed
+     * {@code "\r\n"} (U+000D U+000A).
+     * <p>
+     * A <i>line</i> is either a sequence of zero or more characters
+     * followed by a line terminator, or it is a sequence of one or
+     * more characters followed by the end of the string. A
+     * line does not include the line terminator.
+     * <p>
+     * The stream returned by this method contains the lines from
+     * this string in the order in which they occur.
+     *
+     * @apiNote This definition of <i>line</i> implies that an empty
+     *          string has zero lines and that there is no empty line
+     *          following a line terminator at the end of a string.
+     *
+     * @implNote This method provides better performance than
+     *           split("\R") by supplying elements lazily and
+     *           by faster search of new line terminators.
+     *
+     * @return  the stream of lines extracted from this string
+     *
+     * @since 11
+     */
+    public Stream<String> lines() {
+        // BEGIN Android-removed: Delegate to StringUTF16.
+        /*
+        return isLatin1() ? StringLatin1.lines(value)
+                          : StringUTF16.lines(value);
+         */
+        return StringUTF16.lines(this);
+        // END Android-removed: Delegate to StringUTF16.
     }
 
     /**
@@ -2819,6 +3497,53 @@
     }
 
     /**
+     * Returns a stream of {@code int} zero-extending the {@code char} values
+     * from this sequence.  Any char which maps to a <a
+     * href="{@docRoot}/java.base/java/lang/Character.html#unicode">surrogate code
+     * point</a> is passed through uninterpreted.
+     *
+     * @return an IntStream of char values from this sequence
+     * @since 9
+     */
+    @Override
+    public IntStream chars() {
+        return StreamSupport.intStream(
+            // BEGIN Android-removed: Delegate to StringUTF16.
+            /*
+            isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
+                       : new StringUTF16.CharsSpliterator(value, Spliterator.IMMUTABLE),
+             */
+            new StringUTF16.CharsSpliterator(this, Spliterator.IMMUTABLE),
+            // END Android-removed: Delegate to StringUTF16.
+            false);
+    }
+
+
+    /**
+     * Returns a stream of code point values from this sequence.  Any surrogate
+     * pairs encountered in the sequence are combined as if by {@linkplain
+     * Character#toCodePoint Character.toCodePoint} and the result is passed
+     * to the stream. Any other code units, including ordinary BMP characters,
+     * unpaired surrogates, and undefined code units, are zero-extended to
+     * {@code int} values which are then passed to the stream.
+     *
+     * @return an IntStream of Unicode code points from this sequence
+     * @since 9
+     */
+    @Override
+    public IntStream codePoints() {
+        return StreamSupport.intStream(
+            // BEGIN Android-removed: Delegate to StringUTF16.
+            /*
+            isLatin1() ? new StringLatin1.CharsSpliterator(value, Spliterator.IMMUTABLE)
+                       : new StringUTF16.CodePointsSpliterator(value, Spliterator.IMMUTABLE),
+             */
+            new StringUTF16.CodePointsSpliterator(this, Spliterator.IMMUTABLE),
+            // END Android-removed: Delegate to StringUTF16.
+            false);
+    }
+
+    /**
      * Converts this string to a new character array.
      *
      * @return  a newly allocated character array whose length is the length
@@ -2826,6 +3551,12 @@
      *          the character sequence represented by this string.
      */
     // BEGIN Android-changed: Replace with implementation in runtime to access chars (see above).
+    /*
+    public char[] toCharArray() {
+        return isLatin1() ? StringLatin1.toChars(value)
+                          : StringUTF16.toChars(value);
+    }
+    */
     @FastNative
     public native char[] toCharArray();
     // END Android-changed: Replace with implementation in runtime to access chars (see above).
@@ -2836,7 +3567,9 @@
      * arguments.
      *
      * <p> The locale always used is the one returned by {@link
-     * java.util.Locale#getDefault() Locale.getDefault()}.
+     * java.util.Locale#getDefault(java.util.Locale.Category)
+     * Locale.getDefault(Locale.Category)} with
+     * {@link java.util.Locale.Category#FORMAT FORMAT} category specified.
      *
      * @param  format
      *         A <a href="../util/Formatter.html#syntax">format string</a>
@@ -3011,11 +3744,16 @@
      *          as its single character the argument {@code c}.
      */
     public static String valueOf(char c) {
-        // Android-changed: Replace constructor call with call to StringFactory class.
+        // BEGIN Android-changed: Replace constructor call with call to StringFactory class.
         // There is currently no String(char[], boolean) on Android to call. http://b/79902155
-        // char data[] = {c};
-        // return new String(data, true);
+        /*
+        if (COMPACT_STRINGS && StringLatin1.canEncode(c)) {
+            return new String(StringLatin1.toBytes(c), LATIN1);
+        }
+        return new String(StringUTF16.toBytes(c), UTF16);
+         */
         return StringFactory.newStringFromChars(0, 1, new char[] { c });
+        // END Android-changed: Replace constructor call with call to StringFactory class.
     }
 
     /**
@@ -3096,9 +3834,113 @@
      *
      * @return  a string that has the same contents as this string, but is
      *          guaranteed to be from a pool of unique strings.
+     * @jls 3.10.5 String Literals
      */
-    // BEGIN Android-changed: Annotate native method as @FastNative.
+    // Android-added: Annotate native method as @FastNative.
     @FastNative
-    // END Android-changed: Annotate native method as @FastNative.
     public native String intern();
+
+    /**
+     * Returns a string whose value is the concatenation of this
+     * string repeated {@code count} times.
+     * <p>
+     * If this string is empty or count is zero then the empty
+     * string is returned.
+     *
+     * @param   count number of times to repeat
+     *
+     * @return  A string composed of this string repeated
+     *          {@code count} times or the empty string if this
+     *          string is empty or count is zero
+     *
+     * @throws  IllegalArgumentException if the {@code count} is
+     *          negative.
+     *
+     * @since 11
+     */
+    public String repeat(int count) {
+        if (count < 0) {
+            throw new IllegalArgumentException("count is negative: " + count);
+        }
+        if (count == 1) {
+            return this;
+        }
+        // Android-changed: Replace with implementation in runtime.
+        // final int len = value.length;
+        final int len = length();
+        if (len == 0 || count == 0) {
+            return "";
+        }
+        // BEGIN Android-changed: Replace with implementation in runtime.
+        /*
+        if (len == 1) {
+            final byte[] single = new byte[count];
+            Arrays.fill(single, value[0]);
+            return new String(single, coder);
+        }
+        */
+        // END Android-changed: Replace with implementation in runtime.
+        if (Integer.MAX_VALUE / count < len) {
+            throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
+                    " times will produce a String exceeding maximum size.");
+        }
+        // BEGIN Android-changed: Replace with implementation in runtime.
+        /*
+        final int limit = len * count;
+        final byte[] multiple = new byte[limit];
+        System.arraycopy(value, 0, multiple, 0, len);
+        int copied = len;
+        for (; copied < limit - copied; copied <<= 1) {
+            System.arraycopy(multiple, 0, multiple, copied, copied);
+        }
+        System.arraycopy(multiple, 0, multiple, copied, limit - copied);
+        return new String(multiple, coder);
+         */
+        // END Android-changed: Replace with implementation in runtime.
+        return doRepeat(count);
+    }
+
+    @FastNative
+    private native String doRepeat(int count);
+
+    /*
+     * StringIndexOutOfBoundsException  if {@code index} is
+     * negative or greater than or equal to {@code length}.
+     */
+    static void checkIndex(int index, int length) {
+        if (index < 0 || index >= length) {
+            throw new StringIndexOutOfBoundsException("index " + index +
+                                                      ",length " + length);
+        }
+    }
+
+    /*
+     * Check {@code offset}, {@code count} against {@code 0} and {@code length}
+     * bounds.
+     *
+     * @throws  StringIndexOutOfBoundsException
+     *          If {@code offset} is negative, {@code count} is negative,
+     *          or {@code offset} is greater than {@code length - count}
+     */
+    static void checkBoundsOffCount(int offset, int count, int length) {
+        if (offset < 0 || count < 0 || offset > length - count) {
+            throw new StringIndexOutOfBoundsException(
+                "offset " + offset + ", count " + count + ", length " + length);
+        }
+    }
+
+    /*
+     * Check {@code begin}, {@code end} against {@code 0} and {@code length}
+     * bounds.
+     *
+     * @throws  StringIndexOutOfBoundsException
+     *          If {@code begin} is negative, {@code begin} is greater than
+     *          {@code end}, or {@code end} is greater than {@code length}.
+     */
+    static void checkBoundsBeginEnd(int begin, int end, int length) {
+        if (begin < 0 || begin > end || end > length) {
+            throw new StringIndexOutOfBoundsException(
+                "begin " + begin + ", end " + end + ", length " + length);
+        }
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/StringIndexOutOfBoundsException.java b/ojluni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
index a40bd29..7044b6f 100644
--- a/ojluni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
+++ b/ojluni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,44 +27,43 @@
 package java.lang;
 
 /**
- * Thrown by {@code String} methods to indicate that an index
- * is either negative or greater than the size of the string.  For
- * some methods such as the charAt method, this exception also is
- * thrown when the index is equal to the size of the string.
+ * Thrown by {@code String} methods to indicate that an index is either negative
+ * or greater than the size of the string.  For some methods such as the
+ * {@link String#charAt charAt} method, this exception also is thrown when the
+ * index is equal to the size of the string.
  *
- * @author  unascribed
- * @see     java.lang.String#charAt(int)
- * @since   JDK1.0
+ * @see java.lang.String#charAt(int)
+ * @since 1.0
  */
-public
-class StringIndexOutOfBoundsException extends IndexOutOfBoundsException {
+public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException {
     private static final long serialVersionUID = -6762910422159637258L;
 
     /**
-     * Constructs a {@code StringIndexOutOfBoundsException} with no
-     * detail message.
-     *
-     * @since   JDK1.0.
+     * Constructs a {@code StringIndexOutOfBoundsException} with no detail
+     * message.
      */
     public StringIndexOutOfBoundsException() {
         super();
     }
 
     /**
-     * Constructs a {@code StringIndexOutOfBoundsException} with
-     * the specified detail message.
+     * Constructs a {@code StringIndexOutOfBoundsException} with the specified
+     * detail message.
      *
-     * @param   s   the detail message.
+     * @param s the detail message.
      */
     public StringIndexOutOfBoundsException(String s) {
         super(s);
     }
 
     /**
-     * Constructs a new {@code StringIndexOutOfBoundsException}
-     * class with an argument indicating the illegal index.
+     * Constructs a new {@code StringIndexOutOfBoundsException} class with an
+     * argument indicating the illegal index.
      *
-     * @param   index   the illegal index.
+     * <p>The index is included in this exception's detail message.  The
+     * exact presentation format of the detail message is unspecified.
+     *
+     * @param index the illegal index.
      */
     public StringIndexOutOfBoundsException(int index) {
         super("String index out of range: " + index);
diff --git a/ojluni/src/main/java/java/lang/StringUTF16.java b/ojluni/src/main/java/java/lang/StringUTF16.java
new file mode 100644
index 0000000..1c843a5
--- /dev/null
+++ b/ojluni/src/main/java/java/lang/StringUTF16.java
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import java.util.function.IntConsumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+// BEGIN Android-added: Clarification for usage of StringUTF16 and not StringLatin1.
+/**
+ * In upstream, this class (StringUTF16) contains implementations of various APIs and their helper
+ * methods for uncompressed strings. Libcore makes use of it to implement APIs for both compressed
+ * and uncompressed strings.
+ *
+ * Upstream implementation also has StringLatin1 class which contains same implementations for
+ * compressed strings (and this class is for uncompressed). In our case we use only StringUTF16
+ * (and StringLatin1 is intentionally not imported) as string characters are managed by ART and
+ * everything is implemented in terms of {@link String#charAt(int)} an other primitives which do not
+ * have direct access to underlying character array. From those two, if we choose to implement
+ * everything in those primitives, StringUTF16 has less difference with upstream, so it is chosen
+ * here.
+ *
+ * @hide
+ */
+// END Android-added: Clarification for usage of StringUTF16 and not StringLatin1.
+final class StringUTF16 {
+
+    // BEGIN Android-changed: Pass String instead of byte[]; implement in terms of charAt().
+    // @HotSpotIntrinsicCandidate
+    // intrinsic performs no bounds checks
+    /*
+    static char getChar(byte[] val, int index) {
+        assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
+        index <<= 1;
+        return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
+                      ((val[index]   & 0xff) << LO_BYTE_SHIFT));
+     */
+    @HotSpotIntrinsicCandidate
+    static char getChar(String val, int index) {
+        return val.charAt(index);
+    }
+    // END Android-changed: Pass String instead of byte[]; implement in terms of charAt().
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static int length(byte[] value) {
+        return value.length >> 1;
+     */
+    public static int length(String value) {
+        return value.length();
+    // END Android-changed: Pass String instead of byte[].
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static int indexOfNonWhitespace(byte[] value) {
+        int length = value.length >> 1;
+     */
+    public static int indexOfNonWhitespace(String value) {
+        int length = value.length();
+        int left = 0;
+        while (left < length) {
+            /*
+            int codepoint = codePointAt(value, left, length);
+             */
+            int codepoint = value.codePointAt(left);
+    // END Android-changed: Pass String instead of byte[].
+            if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
+                break;
+            }
+            left += Character.charCount(codepoint);
+        }
+        return left;
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static int lastIndexOfNonWhitespace(byte[] value) {
+        int length = value.length >> 1;
+        int right = length;
+     */
+    public static int lastIndexOfNonWhitespace(String value) {
+        int right = value.length();
+        while (0 < right) {
+            /*
+            int codepoint = codePointBefore(value, right);
+             */
+            int codepoint = value.codePointBefore(right);
+    // END Android-changed: Pass String instead of byte[].
+            if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
+                break;
+            }
+            right -= Character.charCount(codepoint);
+        }
+        return right;
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static String strip(byte[] value) {
+        int length = value.length >> 1;
+     */
+    public static String strip(String value) {
+        int length = value.length();
+    // END Android-changed: Pass String instead of byte[].
+        int left = indexOfNonWhitespace(value);
+        if (left == length) {
+            return "";
+        }
+        int right = lastIndexOfNonWhitespace(value);
+        return ((left > 0) || (right < length)) ? newString(value, left, right - left) : null;
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static String stripLeading(byte[] value) {
+        int length = value.length >> 1;
+     */
+    public static String stripLeading(String value) {
+        int length = value.length();
+    // END Android-changed: Pass String instead of byte[].
+        int left = indexOfNonWhitespace(value);
+        if (left == length) {
+            return "";
+        }
+        return (left != 0) ? newString(value, left, length - left) : null;
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static String stripTrailing(byte[] value) {
+        int length = value.length >> 1;
+     */
+    public static String stripTrailing(String value) {
+        int length = value.length();
+    // END Android-changed: Pass String instead of byte[].
+        int right = lastIndexOfNonWhitespace(value);
+        if (right == 0) {
+            return "";
+        }
+        return (right != length) ? newString(value, 0, right) : null;
+    }
+
+    private final static class LinesSpliterator implements Spliterator<String> {
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        private byte[] value;
+         */
+        private String value;
+        // END Android-changed: Pass String instead of byte[].
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        LinesSpliterator(byte[] value) {
+            this(value, 0, value.length >>> 1);
+        */
+        LinesSpliterator(String value) {
+            this(value, 0, value.length());
+        // END Android-changed: Pass String instead of byte[].
+        }
+
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        LinesSpliterator(byte[] value, int start, int length) {
+         */
+        LinesSpliterator(String value, int start, int length) {
+        // END Android-changed: Pass String instead of byte[].
+            this.value = value;
+            this.index = start;
+            this.fence = start + length;
+        }
+
+        private int indexOfLineSeparator(int start) {
+            for (int current = start; current < fence; current++) {
+                char ch = getChar(value, current);
+                if (ch == '\n' || ch == '\r') {
+                    return current;
+                }
+            }
+            return fence;
+        }
+
+        private int skipLineSeparator(int start) {
+            if (start < fence) {
+                if (getChar(value, start) == '\r') {
+                    int next = start + 1;
+                    if (next < fence && getChar(value, next) == '\n') {
+                        return next + 1;
+                    }
+                }
+                return start + 1;
+            }
+            return fence;
+        }
+
+        private String next() {
+            int start = index;
+            int end = indexOfLineSeparator(start);
+            index = skipLineSeparator(end);
+            return newString(value, start, end - start);
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super String> action) {
+            if (action == null) {
+                throw new NullPointerException("tryAdvance action missing");
+            }
+            if (index != fence) {
+                action.accept(next());
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void forEachRemaining(Consumer<? super String> action) {
+            if (action == null) {
+                throw new NullPointerException("forEachRemaining action missing");
+            }
+            while (index != fence) {
+                action.accept(next());
+            }
+        }
+
+        @Override
+        public Spliterator<String> trySplit() {
+            int half = (fence + index) >>> 1;
+            int mid = skipLineSeparator(indexOfLineSeparator(half));
+            if (mid < fence) {
+                int start = index;
+                index = mid;
+                return new LinesSpliterator(value, start, mid - start);
+            }
+            return null;
+        }
+
+        @Override
+        public long estimateSize() {
+            return fence - index + 1;
+        }
+
+        @Override
+        public int characteristics() {
+            return Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL;
+        }
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    static Stream<String> lines(byte[] value) {
+     */
+    static Stream<String> lines(String value) {
+        return StreamSupport.stream(new LinesSpliterator(value), false);
+    // END Android-changed: Pass String instead of byte[].
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[]; implement in terms of substring().
+    /*
+    public static String newString(byte[] val, int index, int len) {
+        if (String.COMPACT_STRINGS) {
+            byte[] buf = compress(val, index, len);
+            if (buf != null) {
+                return new String(buf, LATIN1);
+            }
+        }
+        int last = index + len;
+        return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
+    }
+     */
+    public static String newString(String val, int index, int len) {
+        return val.substring(index, index + len);
+    }
+    // END Android-changed: Pass String instead of byte[]; implement in terms of substring().
+
+    static class CharsSpliterator implements Spliterator.OfInt {
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        private final byte[] array;
+         */
+        private final String array;
+        // END Android-changed: Pass String instead of byte[].
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        CharsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length >> 1, acs);
+         */
+        CharsSpliterator(String array, int acs) {
+            this(array, 0, array.length(), acs);
+        // END Android-changed: Pass String instead of byte[].
+        }
+
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        CharsSpliterator(byte[] array, int origin, int fence, int acs) {
+         */
+        CharsSpliterator(String array, int origin, int fence, int acs) {
+        // END Android-changed: Pass String instead of byte[].
+            this.array = array;
+            this.index = origin;
+            this.fence = fence;
+            this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
+                      | Spliterator.SUBSIZED;
+        }
+
+        @Override
+        public OfInt trySplit() {
+            int lo = index, mid = (lo + fence) >>> 1;
+            return (lo >= mid)
+                   ? null
+                   : new CharsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            // BEGIN Android-changed: Pass String instead of byte[].
+            /*
+            byte[] a; int i, hi; // hoist accesses and checks from loop
+             */
+            String a; int i, hi; // hoist accesses and checks from loop
+            // END Android-changed: Pass String instead of byte[].
+            if (action == null)
+                throw new NullPointerException();
+            // BEGIN Android-changed: Pass String instead of byte[].
+            /*
+            if (((a = array).length >> 1) >= (hi = fence) &&
+             */
+            if (((a = array).length()) >= (hi = fence) &&
+            // END Android-changed: Pass String instead of byte[].
+                (i = index) >= 0 && i < (index = hi)) {
+                do {
+                    action.accept(charAt(a, i));
+                } while (++i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            int i = index;
+            if (i >= 0 && i < fence) {
+                action.accept(charAt(array, i));
+                index++;
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    static class CodePointsSpliterator implements Spliterator.OfInt {
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        private final byte[] array;
+         */
+        private final String array;
+        // END Android-changed: Pass String instead of byte[].
+        private int index;        // current index, modified on advance/split
+        private final int fence;  // one past last index
+        private final int cs;
+
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        CodePointsSpliterator(byte[] array, int acs) {
+            this(array, 0, array.length >> 1, acs);
+         */
+        CodePointsSpliterator(String array, int acs) {
+            this(array, 0, array.length(), acs);
+        // END Android-changed: Pass String instead of byte[].
+        }
+
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        CodePointsSpliterator(byte[] array, int origin, int fence, int acs) {
+         */
+        CodePointsSpliterator(String array, int origin, int fence, int acs) {
+        // END Android-changed: Pass String instead of byte[].
+            this.array = array;
+            this.index = origin;
+            this.fence = fence;
+            this.cs = acs | Spliterator.ORDERED;
+        }
+
+        @Override
+        public OfInt trySplit() {
+            int lo = index, mid = (lo + fence) >>> 1;
+            if (lo >= mid)
+                return null;
+
+            int midOneLess;
+            // If the mid-point intersects a surrogate pair
+            if (Character.isLowSurrogate(charAt(array, mid)) &&
+                Character.isHighSurrogate(charAt(array, midOneLess = (mid -1)))) {
+                // If there is only one pair it cannot be split
+                if (lo >= midOneLess)
+                    return null;
+                // Shift the mid-point to align with the surrogate pair
+                return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
+            }
+            return new CodePointsSpliterator(array, lo, index = mid, cs);
+        }
+
+        @Override
+        public void forEachRemaining(IntConsumer action) {
+            // BEGIN Android-changed: Pass String instead of byte[].
+            /*
+            byte[] a; int i, hi; // hoist accesses and checks from loop
+             */
+            String a; int i, hi; // hoist accesses and checks from loop
+            // END Android-changed: Pass String instead of byte[].
+            if (action == null)
+                throw new NullPointerException();
+            // BEGIN Android-changed: Pass String instead of byte[].
+            /*
+            if (((a = array).length >> 1) >= (hi = fence) &&
+             */
+            if (((a = array).length()) >= (hi = fence) &&
+            // END Android-changed: Pass String instead of byte[].
+                (i = index) >= 0 && i < (index = hi)) {
+                do {
+                    i = advance(a, i, hi, action);
+                } while (i < hi);
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+            if (action == null)
+                throw new NullPointerException();
+            if (index >= 0 && index < fence) {
+                index = advance(array, index, fence, action);
+                return true;
+            }
+            return false;
+        }
+
+        // Advance one code point from the index, i, and return the next
+        // index to advance from
+        // BEGIN Android-changed: Pass String instead of byte[].
+        /*
+        private static int advance(byte[] a, int i, int hi, IntConsumer action) {
+         */
+        private static int advance(String a, int i, int hi, IntConsumer action) {
+        // END Android-changed: Pass String instead of byte[].
+            char c1 = charAt(a, i++);
+            int cp = c1;
+            if (Character.isHighSurrogate(c1) && i < hi) {
+                char c2 = charAt(a, i);
+                if (Character.isLowSurrogate(c2)) {
+                    i++;
+                    cp = Character.toCodePoint(c1, c2);
+                }
+            }
+            action.accept(cp);
+            return i;
+        }
+
+        @Override
+        public long estimateSize() { return (long)(fence - index); }
+
+        @Override
+        public int characteristics() {
+            return cs;
+        }
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static char charAt(byte[] value, int index) {
+     */
+    public static char charAt(String value, int index) {
+    // END Android-changed: Pass String instead of byte[].
+        checkIndex(index, value);
+        return getChar(value, index);
+    }
+
+    // BEGIN Android-changed: Pass String instead of byte[].
+    /*
+    public static void checkIndex(int off, byte[] val) {
+     */
+    public static void checkIndex(int off, String val) {
+    // END Android-changed: Pass String instead of byte[].
+        String.checkIndex(off, length(val));
+    }
+
+}
diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java
index 4abba4d..94d74c0 100644
--- a/ojluni/src/main/java/java/lang/System.java
+++ b/ojluni/src/main/java/java/lang/System.java
@@ -296,6 +296,7 @@
     @CriticalNative
     public static native long currentTimeMillis();
 
+    // Android-added: Note on elapse time and deep sleep.
     /**
      * Returns the current value of the running Java Virtual Machine's
      * high-resolution time source, in nanoseconds.
@@ -336,6 +337,10 @@
      * one should use {@code t1 - t0 < 0}, not {@code t1 < t0},
      * because of the possibility of numerical overflow.
      *
+     * <p>The value returned by this method does not account for elapsed
+     * time during deep sleep. For timekeeping facilities available on
+     * Android see {@link android.os.SystemClock}.
+     *
      * @return the current value of the running Java Virtual Machine's
      *         high-resolution time source, in nanoseconds
      * @since 1.5
@@ -971,10 +976,11 @@
         p.put("java.boot.class.path", runtime.bootClassPath());
         p.put("java.class.path", runtime.classPath());
 
-        // TODO: does this make any sense? Should we just leave java.home unset?
-        String javaHome = getenv("JAVA_HOME");
+        // This is probably not useful, but it's documented as being present.
+        // ANDROID_ART_ROOT is defined in `system/core/rootdir/init.environ.rc.in`.
+        String javaHome = getenv("ANDROID_ART_ROOT");
         if (javaHome == null) {
-            javaHome = "/system";
+            javaHome = "/apex/com.android.art";
         }
         p.put("java.home", javaHome);
 
@@ -1006,7 +1012,6 @@
         // Note: it is not possible to override hardcoded values.
         parsePropertyAssignments(p, runtime.properties());
 
-
         // Set static hardcoded properties.
         // These come last, as they must be guaranteed to agree with what a backend compiler
         // may assume when compiling the boot image on Android.
@@ -1031,9 +1036,9 @@
     }
 
     private static Properties setDefaultChangeableProperties(Properties p) {
-        // On Android, each app gets its own temporary directory.
-        // (See android.app.ActivityThread.) This is just a fallback default,
-        // useful only on the host.
+        // On Android, "java.io.tmpdir" is set in android.app.ActivityThread. Each app gets its
+        // own location, a typical value would be "/data/user/0/com.android.deskclock/cache.
+        // The value set here is just a fallback default for host.
         // We check first if the property has not been set already: note that it
         // can only be set from the command line through the '-Djava.io.tmpdir=' option.
         if (!unchangeableProps.containsKey("java.io.tmpdir")) {
@@ -1106,8 +1111,8 @@
      * <tr><td>java.class.version</td> <td>(Not useful on Android)</td>           <td>{@code 50.0}</td></tr>
      * <tr><td>java.compiler</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
      * <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.home</td>          <td>Location of the VM on the file system</td> <td>{@code /apex/com.android.art/}</td></tr>
+     * <tr><td>java.io.tmpdir</td>     <td>Location of a temporary directory.<br>The location varies by application.<br>See {@link java.io.File#createTempFile}</td> <td>{@code /data/user/0/com.android.app/cache}</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>
@@ -1125,9 +1130,9 @@
      *
      * <tr><td>line.separator</td>     <td>The system line separator</td>         <td>{@code \n}</td></tr>
      *
-     * <tr><td>os.arch</td>            <td>OS architecture</td>                   <td>{@code armv7l}</td></tr>
+     * <tr><td>os.arch</td>            <td>OS architecture</td>                   <td>{@code aarch64}</td></tr>
      * <tr><td>os.name</td>            <td>OS (kernel) name</td>                  <td>{@code Linux}</td></tr>
-     * <tr><td>os.version</td>         <td>OS (kernel) version</td>               <td>{@code 2.6.32.9-g103d848}</td></tr>
+     * <tr><td>os.version</td>         <td>OS (kernel) version</td>               <td>{@code 5.10.98-g6ea688a79989}</td></tr>
      *
      * <tr><td>path.separator</td>     <td>See {@link java.io.File#pathSeparator}</td> <td>{@code :}</td></tr>
      *
diff --git a/ojluni/src/main/java/java/lang/Thread.java b/ojluni/src/main/java/java/lang/Thread.java
index ca66ef3..3321b2e 100644
--- a/ojluni/src/main/java/java/lang/Thread.java
+++ b/ojluni/src/main/java/java/lang/Thread.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@
 import sun.reflect.CallerSensitive;
 import dalvik.system.VMStack;
 import libcore.util.EmptyArray;
+import jdk.internal.HotSpotIntrinsicCandidate;
 
 
 /**
@@ -52,30 +53,30 @@
  * Every thread has a priority. Threads with higher priority are
  * executed in preference to threads with lower priority. Each thread
  * may or may not also be marked as a daemon. When code running in
- * some thread creates a new <code>Thread</code> object, the new
+ * some thread creates a new {@code Thread} object, the new
  * thread has its priority initially set equal to the priority of the
  * creating thread, and is a daemon thread if and only if the
  * creating thread is a daemon.
  * <p>
  * When a Java Virtual Machine starts up, there is usually a single
  * non-daemon thread (which typically calls the method named
- * <code>main</code> of some designated class). The Java Virtual
+ * {@code main} of some designated class). The Java Virtual
  * Machine continues to execute threads until either of the following
  * occurs:
  * <ul>
- * <li>The <code>exit</code> method of class <code>Runtime</code> has been
+ * <li>The {@code exit} method of class {@code Runtime} has been
  *     called and the security manager has permitted the exit operation
  *     to take place.
  * <li>All threads that are not daemon threads have died, either by
- *     returning from the call to the <code>run</code> method or by
- *     throwing an exception that propagates beyond the <code>run</code>
+ *     returning from the call to the {@code run} method or by
+ *     throwing an exception that propagates beyond the {@code run}
  *     method.
  * </ul>
  * <p>
  * There are two ways to create a new thread of execution. One is to
- * declare a class to be a subclass of <code>Thread</code>. This
- * subclass should override the <code>run</code> method of class
- * <code>Thread</code>. An instance of the subclass can then be
+ * declare a class to be a subclass of {@code Thread}. This
+ * subclass should override the {@code run} method of class
+ * {@code Thread}. An instance of the subclass can then be
  * allocated and started. For example, a thread that computes primes
  * larger than a stated value could be written as follows:
  * <hr><blockquote><pre>
@@ -99,10 +100,10 @@
  * </pre></blockquote>
  * <p>
  * The other way to create a thread is to declare a class that
- * implements the <code>Runnable</code> interface. That class then
- * implements the <code>run</code> method. An instance of the class can
+ * implements the {@code Runnable} interface. That class then
+ * implements the {@code run} method. An instance of the class can
  * then be allocated, passed as an argument when creating
- * <code>Thread</code>, and started. The same example in this other
+ * {@code Thread}, and started. The same example in this other
  * style looks like the following:
  * <hr><blockquote><pre>
  *     class PrimeRun implements Runnable {
@@ -137,7 +138,7 @@
  * @see     Runtime#exit(int)
  * @see     #run()
  * @see     #stop()
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class Thread implements Runnable {
@@ -165,18 +166,17 @@
     // END Android-added: Android specific fields lock, nativePeer.
 
     private volatile String name;
-    private int            priority;
-    private Thread         threadQ;
-    private long           eetop;
+    private int priority;
 
     /* Whether or not to single_step this thread. */
     private boolean     single_step;
 
     /* Whether or not the thread is a daemon thread. */
-    private boolean     daemon = false;
+    private boolean daemon = false;
 
-    /* JVM state */
-    private boolean     stillborn = false;
+    /* Fields reserved for exclusive use by the JVM */
+    private boolean stillborn = false;
+    private long eetop;
 
     /* What will be run. */
     private Runnable target;
@@ -211,7 +211,7 @@
      * not specify a stack size.  It is up to the VM to do whatever it
      * likes with this number; some VMs will ignore it.
      */
-    private long stackSize;
+    private final long stackSize;
 
     // BEGIN Android-changed: Keep track of whether this thread was unparked while not alive.
     /*
@@ -231,11 +231,14 @@
     /*
      * Thread ID
      */
-    private long tid;
+    private final long tid;
 
     /* For generating thread ID */
     private static long threadSeqNumber;
 
+    private static synchronized long nextThreadID() {
+        return ++threadSeqNumber;
+    }
 
     // Android-added: The concept of "system-daemon" threads. See java.lang.Daemons.
     /** True if this thread is managed by {@link Daemons}. */
@@ -262,11 +265,6 @@
     boolean started = false;
     // END Android-changed: Replace unused threadStatus field with started field.
 
-
-    private static synchronized long nextThreadID() {
-        return ++threadSeqNumber;
-    }
-
     /**
      * The argument supplied to the current call to
      * java.util.concurrent.locks.LockSupport.park.
@@ -296,23 +294,24 @@
     /**
      * The minimum priority that a thread can have.
      */
-    public final static int MIN_PRIORITY = 1;
+    public static final int MIN_PRIORITY = 1;
 
    /**
      * The default priority that is assigned to a thread.
      */
-    public final static int NORM_PRIORITY = 5;
+    public static final int NORM_PRIORITY = 5;
 
     /**
      * The maximum priority that a thread can have.
      */
-    public final static int MAX_PRIORITY = 10;
+    public static final int MAX_PRIORITY = 10;
 
     /**
      * Returns a reference to the currently executing thread object.
      *
      * @return  the currently executing thread.
      */
+    @HotSpotIntrinsicCandidate
     @FastNative
     public static native Thread currentThread();
 
@@ -455,13 +454,43 @@
     }
 
     /**
-     * Initializes a Thread with the current AccessControlContext.
-     * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext)
+     * Indicates that the caller is momentarily unable to progress, until the
+     * occurrence of one or more actions on the part of other activities. By
+     * invoking this method within each iteration of a spin-wait loop construct,
+     * the calling thread indicates to the runtime that it is busy-waiting.
+     * The runtime may take action to improve the performance of invoking
+     * spin-wait loop constructions.
+     *
+     * @apiNote
+     * As an example consider a method in a class that spins in a loop until
+     * some flag is set outside of that method. A call to the {@code onSpinWait}
+     * method should be placed inside the spin loop.
+     * <pre>{@code
+     *     class EventHandler {
+     *         volatile boolean eventNotificationNotReceived;
+     *         void waitForEventAndHandleIt() {
+     *             while ( eventNotificationNotReceived ) {
+     *                 java.lang.Thread.onSpinWait();
+     *             }
+     *             readAndProcessEvent();
+     *         }
+     *
+     *         void readAndProcessEvent() {
+     *             // Read event from some source and process it
+     *              . . .
+     *         }
+     *     }
+     * }</pre>
+     * <p>
+     * The code above would remain correct even if the {@code onSpinWait}
+     * method was not called at all. However on some architectures the Java
+     * Virtual Machine may issue the processor instructions to address such
+     * code patterns in a more beneficial way.
+     *
+     * @since 9
      */
-    private void init(ThreadGroup g, Runnable target, String name,
-                      long stackSize) {
-        init(g, target, name, stackSize, null);
-    }
+    @HotSpotIntrinsicCandidate
+    public static void onSpinWait() {}
 
     /**
      * Initializes a Thread.
@@ -473,9 +502,12 @@
      *        zero to indicate that this parameter is to be ignored.
      * @param acc the AccessControlContext to inherit, or
      *            AccessController.getContext() if null
+     * @param inheritThreadLocals if {@code true}, inherit initial values for
+     *            inheritable thread-locals from the constructing thread
      */
-    private void init(ThreadGroup g, Runnable target, String name,
-                      long stackSize, AccessControlContext acc) {
+    private Thread(ThreadGroup g, Runnable target, String name,
+                   long stackSize, AccessControlContext acc,
+                   boolean inheritThreadLocals) {
         if (name == null) {
             throw new NullPointerException("name cannot be null");
         }
@@ -496,8 +528,8 @@
                 g = security.getThreadGroup();
             }
 
-            /* If the security doesn't have a strong opinion of the matter
-               use the parent thread group. *
+            /* If the security manager doesn't have a strong opinion
+               on the matter, use the parent thread group. *
             if (g == null) {
             */
                 g = parent.getThreadGroup();
@@ -515,7 +547,8 @@
          *
         if (security != null) {
             if (isCCLOverridden(getClass())) {
-                security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
+                security.checkPermission(
+                        SecurityConstants.SUBCLASS_IMPLEMENTATION_PERMISSION);
             }
         }
         */
@@ -525,7 +558,7 @@
         this.group = g;
         this.daemon = parent.isDaemon();
         this.priority = parent.getPriority();
-        // Android-changed: Moved into init2(Thread) helper method.
+        // Android-changed: Moved into init2(Thread, boolean) helper method.
         /*
         if (security == null || isCCLOverridden(parent.getClass()))
             this.contextClassLoader = parent.getContextClassLoader();
@@ -538,17 +571,17 @@
         // Android-removed: The priority parameter is unchecked on Android.
         // It is unclear why this is not being done (b/80180276).
         // setPriority(priority);
-        // Android-changed: Moved into init2(Thread) helper method.
-        // if (parent.inheritableThreadLocals != null)
+        // Android-changed: Moved into init2(Thread, boolean) helper method.
+        // if (inheritThreadLocals && parent.inheritableThreadLocals != null)
         //     this.inheritableThreadLocals =
         //         ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
-        init2(parent);
+        init2(parent, inheritThreadLocals);
 
         /* Stash the specified stack size in case the VM cares */
         this.stackSize = stackSize;
 
         /* Set thread ID */
-        tid = nextThreadID();
+        this.tid = nextThreadID();
     }
 
     /**
@@ -571,7 +604,7 @@
      * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
      */
     public Thread() {
-        init(null, null, "Thread-" + nextThreadNum(), 0);
+        this(null, null, "Thread-" + nextThreadNum(), 0);
     }
 
     /**
@@ -587,15 +620,16 @@
      *         nothing.
      */
     public Thread(Runnable target) {
-        init(null, target, "Thread-" + nextThreadNum(), 0);
+        this(null, target, "Thread-" + nextThreadNum(), 0);
     }
 
     /**
-     * Creates a new Thread that inherits the given AccessControlContext.
+     * Creates a new Thread that inherits the given AccessControlContext
+     * but thread-local variables are not inherited.
      * This is not a public constructor.
      */
     Thread(Runnable target, AccessControlContext acc) {
-        init(null, target, "Thread-" + nextThreadNum(), 0, acc);
+        this(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
     }
 
     /**
@@ -622,7 +656,7 @@
      *          thread group
      */
     public Thread(ThreadGroup group, Runnable target) {
-        init(group, target, "Thread-" + nextThreadNum(), 0);
+        this(group, target, "Thread-" + nextThreadNum(), 0);
     }
 
     /**
@@ -634,7 +668,7 @@
      *          the name of the new thread
      */
     public Thread(String name) {
-        init(null, null, name, 0);
+        this(null, null, name, 0);
     }
 
     /**
@@ -658,7 +692,7 @@
      *          thread group
      */
     public Thread(ThreadGroup group, String name) {
-        init(group, null, name, 0);
+        this(group, null, name, 0);
     }
 
     // BEGIN Android-added: Private constructor - used by the runtime.
@@ -678,17 +712,18 @@
 
         this.priority = priority;
         this.daemon = daemon;
-        init2(currentThread());
-        tid = nextThreadID();
+        init2(currentThread(), true);
+        this.stackSize = 0;
+        this.tid = nextThreadID();
     }
 
     // Android-added: Helper method for previous constructor and init(...) method.
-    private void init2(Thread parent) {
+    private void init2(Thread parent, boolean inheritThreadLocals) {
         this.contextClassLoader = parent.getContextClassLoader();
         this.inheritedAccessControlContext = AccessController.getContext();
-        if (parent.inheritableThreadLocals != null) {
-            this.inheritableThreadLocals = ThreadLocal.createInheritedMap(
-                    parent.inheritableThreadLocals);
+        if (inheritThreadLocals && parent.inheritableThreadLocals != null) {
+            this.inheritableThreadLocals =
+                    ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
         }
     }
     // END Android-added: Private constructor - used by the runtime.
@@ -707,7 +742,7 @@
      *         the name of the new thread
      */
     public Thread(Runnable target, String name) {
-        init(null, target, name, 0);
+        this(null, target, name, 0);
     }
 
     /**
@@ -755,7 +790,7 @@
      *          thread group or cannot override the context class loader methods.
      */
     public Thread(ThreadGroup group, Runnable target, String name) {
-        init(group, target, name, 0);
+        this(group, target, name, 0);
     }
 
     /**
@@ -777,7 +812,7 @@
      * Similarly, specifying a lower value may allow a greater number of
      * threads to exist concurrently without throwing an {@link
      * OutOfMemoryError} (or other internal error).  The details of
-     * the relationship between the value of the <tt>stackSize</tt> parameter
+     * the relationship between the value of the {@code stackSize} parameter
      * and the maximum recursion depth and concurrency level are
      * platform-dependent.  <b>On some platforms, the value of the
      * {@code stackSize} parameter may have no effect whatsoever.</b>
@@ -834,24 +869,79 @@
      */
     public Thread(ThreadGroup group, Runnable target, String name,
                   long stackSize) {
-        init(group, target, name, stackSize);
+        this(group, target, name, stackSize, null, true);
+    }
+
+    /**
+     * Allocates a new {@code Thread} object so that it has {@code target}
+     * as its run object, has the specified {@code name} as its name,
+     * belongs to the thread group referred to by {@code group}, has
+     * the specified {@code stackSize}, and inherits initial values for
+     * {@linkplain InheritableThreadLocal inheritable thread-local} variables
+     * if {@code inheritThreadLocals} is {@code true}.
+     *
+     * <p> This constructor is identical to {@link
+     * #Thread(ThreadGroup,Runnable,String,long)} with the added ability to
+     * suppress, or not, the inheriting of initial values for inheritable
+     * thread-local variables from the constructing thread. This allows for
+     * finer grain control over inheritable thread-locals. Care must be taken
+     * when passing a value of {@code false} for {@code inheritThreadLocals},
+     * as it may lead to unexpected behavior if the new thread executes code
+     * that expects a specific thread-local value to be inherited.
+     *
+     * <p> Specifying a value of {@code true} for the {@code inheritThreadLocals}
+     * parameter will cause this constructor to behave exactly like the
+     * {@code Thread(ThreadGroup, Runnable, String, long)} constructor.
+     *
+     * @param  group
+     *         the thread group. If {@code null} and there is a security
+     *         manager, the group is determined by {@linkplain
+     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+     *         If there is not a security manager or {@code
+     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
+     *         is set to the current thread's thread group.
+     *
+     * @param  target
+     *         the object whose {@code run} method is invoked when this thread
+     *         is started. If {@code null}, this thread's run method is invoked.
+     *
+     * @param  name
+     *         the name of the new thread
+     *
+     * @param  stackSize
+     *         the desired stack size for the new thread, or zero to indicate
+     *         that this parameter is to be ignored
+     *
+     * @param  inheritThreadLocals
+     *         if {@code true}, inherit initial values for inheritable
+     *         thread-locals from the constructing thread, otherwise no initial
+     *         values are inherited
+     *
+     * @throws  SecurityException
+     *          if the current thread cannot create a thread in the specified
+     *          thread group
+     *
+     * @since 9
+     */
+    public Thread(ThreadGroup group, Runnable target, String name,
+                  long stackSize, boolean inheritThreadLocals) {
+        this(group, target, name, stackSize, null, inheritThreadLocals);
     }
 
     /**
      * Causes this thread to begin execution; the Java Virtual Machine
-     * calls the <code>run</code> method of this thread.
+     * calls the {@code run} method of this thread.
      * <p>
      * The result is that two threads are running concurrently: the
      * current thread (which returns from the call to the
-     * <code>start</code> method) and the other thread (which executes its
-     * <code>run</code> method).
+     * {@code start} method) and the other thread (which executes its
+     * {@code run} method).
      * <p>
      * It is never legal to start a thread more than once.
      * In particular, a thread may not be restarted once it has completed
      * execution.
      *
-     * @exception  IllegalThreadStateException  if the thread was already
-     *               started.
+     * @throws     IllegalThreadStateException  if the thread was already started.
      * @see        #run()
      * @see        #stop()
      */
@@ -865,6 +955,7 @@
          */
         // Android-changed: Replace unused threadStatus field with started field.
         // The threadStatus field is unused on Android.
+        // if (threadStatus != 0)
         if (started)
             throw new IllegalThreadStateException();
 
@@ -877,6 +968,7 @@
         // It is necessary to remember the state of this across calls to this method so that it
         // can throw an IllegalThreadStateException if this method is called on an already
         // started thread.
+        // boolean started = false;
         started = false;
         try {
             // Android-changed: Use Android specific nativeCreate() method to create/start thread.
@@ -904,11 +996,11 @@
 
     /**
      * If this thread was constructed using a separate
-     * <code>Runnable</code> run object, then that
-     * <code>Runnable</code> object's <code>run</code> method is called;
+     * {@code Runnable} run object, then that
+     * {@code Runnable} object's {@code run} method is called;
      * otherwise, this method does nothing and returns.
      * <p>
-     * Subclasses of <code>Thread</code> should override this method.
+     * Subclasses of {@code Thread} should override this method.
      *
      * @see     #start()
      * @see     #stop()
@@ -949,23 +1041,23 @@
      *       Stopping a thread with
      *       Thread.stop causes it to unlock all of the monitors that it
      *       has locked (as a natural consequence of the unchecked
-     *       <code>ThreadDeath</code> exception propagating up the stack).  If
+     *       {@code ThreadDeath} exception propagating up the stack).  If
      *       any of the objects previously protected by these monitors were in
      *       an inconsistent state, the damaged objects become visible to
      *       other threads, potentially resulting in arbitrary behavior.  Many
-     *       uses of <code>stop</code> should be replaced by code that simply
+     *       uses of {@code stop} should be replaced by code that simply
      *       modifies some variable to indicate that the target thread should
      *       stop running.  The target thread should check this variable
      *       regularly, and return from its run method in an orderly fashion
      *       if the variable indicates that it is to stop running.  If the
      *       target thread waits for long periods (on a condition variable,
-     *       for example), the <code>interrupt</code> method should be used to
+     *       for example), the {@code interrupt} method should be used to
      *       interrupt the wait.
      *       For more information, see
-     *       <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
+     *       <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public final void stop() {
         /*
         SecurityManager security = System.getSecurityManager();
@@ -998,7 +1090,7 @@
      *        could be used to generate exceptions that the target thread was
      *        not prepared to handle.
      *        For more information, see
-     *        <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
+     *        <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *        are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      */
     @Deprecated
@@ -1046,17 +1138,21 @@
      * @spec JSR-51
      */
     public void interrupt() {
-        if (this != Thread.currentThread())
+        if (this != Thread.currentThread()) {
             checkAccess();
 
-        synchronized (blockerLock) {
-            Interruptible b = blocker;
-            if (b != null) {
-                interrupt0();           // Just to set the interrupt flag
-                b.interrupt(this);
-                return;
+            // thread may be blocked in an I/O operation
+            synchronized (blockerLock) {
+                Interruptible b = blocker;
+                if (b != null) {
+                    interrupt0();  // set interrupt status
+                    b.interrupt(this);
+                    return;
+                }
             }
         }
+
+        // set interrupt status
         interrupt0();
     }
 
@@ -1072,8 +1168,8 @@
      * at the time of the interrupt will be reflected by this method
      * returning false.
      *
-     * @return  <code>true</code> if the current thread has been interrupted;
-     *          <code>false</code> otherwise.
+     * @return  {@code true} if the current thread has been interrupted;
+     *          {@code false} otherwise.
      * @see #isInterrupted()
      * @revised 6.0
      */
@@ -1101,8 +1197,8 @@
      * at the time of the interrupt will be reflected by this method
      * returning false.
      *
-     * @return  <code>true</code> if this thread has been interrupted;
-     *          <code>false</code> otherwise.
+     * @return  {@code true} if this thread has been interrupted;
+     *          {@code false} otherwise.
      * @see     #interrupted()
      * @revised 6.0
      */
@@ -1120,6 +1216,7 @@
      * is reset or not based on the value of ClearInterrupted that is
      * passed.
      *
+    @HotSpotIntrinsicCandidate
     private native boolean isInterrupted(boolean ClearInterrupted);
     */
 
@@ -1137,7 +1234,7 @@
      *     If another thread ever attempted to lock this resource, deadlock
      *     would result. Such deadlocks typically manifest themselves as
      *     "frozen" processes. For more information, see
-     *     <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">
+     *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
      *     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      * @throws UnsupportedOperationException always
      */
@@ -1151,10 +1248,11 @@
      * Tests if this thread is alive. A thread is alive if it has
      * been started and has not yet died.
      *
-     * @return  <code>true</code> if this thread is alive;
-     *          <code>false</code> otherwise.
+     * @return  {@code true} if this thread is alive;
+     *          {@code false} otherwise.
      */
     // Android-changed: Provide pure Java implementation of isAlive().
+    // public final native boolean isAlive();
     public final boolean isAlive() {
         return nativePeer != 0;
     }
@@ -1163,19 +1261,19 @@
     /**
      * Throws {@link UnsupportedOperationException}.
      *
-     * @deprecated   This method was designed to suspend the Thread but it was
+     * @deprecated   This method has been deprecated, as it is
      *   inherently deadlock-prone.  If the target thread holds a lock on the
      *   monitor protecting a critical system resource when it is suspended, no
      *   thread can access this resource until the target thread is resumed. If
      *   the thread that would resume the target thread attempts to lock this
-     *   monitor prior to calling <code>resume</code>, deadlock results.  Such
+     *   monitor prior to calling {@code resume}, deadlock results.  Such
      *   deadlocks typically manifest themselves as "frozen" processes.
      *   For more information, see
-     *   <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
+     *   <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      * @throws UnsupportedOperationException always
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public final void suspend() {
         // Android-changed: Unsupported on Android.
         // checkAccess();
@@ -1191,11 +1289,11 @@
      * @deprecated This method exists solely for use with {@link #suspend},
      *     which has been deprecated because it is deadlock-prone.
      *     For more information, see
-     *     <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
+     *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
      *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
      * @throws UnsupportedOperationException always
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public final void resume() {
         // Android-changed: Unsupported on Android.
         // checkAccess();
@@ -1206,19 +1304,18 @@
     /**
      * Changes the priority of this thread.
      * <p>
-     * First the <code>checkAccess</code> method of this thread is called
-     * with no arguments. This may result in throwing a
-     * <code>SecurityException</code>.
+     * First the {@code checkAccess} method of this thread is called
+     * with no arguments. This may result in throwing a {@code SecurityException}.
      * <p>
      * Otherwise, the priority of this thread is set to the smaller of
-     * the specified <code>newPriority</code> and the maximum permitted
+     * the specified {@code newPriority} and the maximum permitted
      * priority of the thread's thread group.
      *
      * @param newPriority priority to set this thread to
-     * @exception  IllegalArgumentException  If the priority is not in the
-     *               range <code>MIN_PRIORITY</code> to
-     *               <code>MAX_PRIORITY</code>.
-     * @exception  SecurityException  if the current thread cannot modify
+     * @throws     IllegalArgumentException  If the priority is not in the
+     *               range {@code MIN_PRIORITY} to
+     *               {@code MAX_PRIORITY}.
+     * @throws     SecurityException  if the current thread cannot modify
      *               this thread.
      * @see        #getPriority
      * @see        #checkAccess()
@@ -1260,16 +1357,15 @@
     }
 
     /**
-     * Changes the name of this thread to be equal to the argument
-     * <code>name</code>.
+     * Changes the name of this thread to be equal to the argument {@code name}.
      * <p>
-     * First the <code>checkAccess</code> method of this thread is called
+     * First the {@code checkAccess} method of this thread is called
      * with no arguments. This may result in throwing a
-     * <code>SecurityException</code>.
+     * {@code SecurityException}.
      *
      * @param      name   the new name for this thread.
-     * @exception  SecurityException  if the current thread cannot modify this
-     *               thread.
+     * @throws     SecurityException  if the current thread cannot modify this
+     *             thread.
      * @see        #getName
      * @see        #checkAccess()
      */
@@ -1373,13 +1469,14 @@
      * be suspended.
      *
      * @return     the number of stack frames in this thread.
-     * @exception  IllegalThreadStateException  if this thread is not
+     * @throws     IllegalThreadStateException  if this thread is not
      *             suspended.
      * @deprecated The definition of this call depends on {@link #suspend},
      *             which is deprecated.  Further, the results of this call
      *             were never well-defined.
+     *             This method is subject to removal in a future version of Java SE.
      */
-    @Deprecated
+    @Deprecated(since="1.2", forRemoval=true)
     // Android-changed: Provide non-native implementation of countStackFrames().
     // public native int countStackFrames();
     public int countStackFrames() {
@@ -1442,6 +1539,7 @@
     /**
      * Waits at most {@code millis} milliseconds plus
      * {@code nanos} nanoseconds for this thread to die.
+     * If both arguments are {@code 0}, it means to wait forever.
      *
      * <p> This implementation uses a loop of {@code this.wait} calls
      * conditioned on {@code this.isAlive}. As a thread terminates the
@@ -1545,8 +1643,8 @@
     /**
      * Tests if this thread is a daemon thread.
      *
-     * @return  <code>true</code> if this thread is a daemon thread;
-     *          <code>false</code> otherwise.
+     * @return  {@code true} if this thread is a daemon thread;
+     *          {@code false} otherwise.
      * @see     #setDaemon(boolean)
      */
     public final boolean isDaemon() {
@@ -1557,12 +1655,12 @@
      * Determines if the currently running thread has permission to
      * modify this thread.
      * <p>
-     * If there is a security manager, its <code>checkAccess</code> method
+     * If there is a security manager, its {@code checkAccess} method
      * is called with this thread as its argument. This may result in
-     * throwing a <code>SecurityException</code>.
+     * throwing a {@code SecurityException}.
      *
-     * @exception  SecurityException  if the current thread is not allowed to
-     *               access this thread.
+     * @throws  SecurityException  if the current thread is not allowed to
+     *          access this thread.
      * @see        SecurityManager#checkAccess(Thread)
      */
     public final void checkAccess() {
@@ -1591,23 +1689,17 @@
     }
 
     /**
-     * Returns the context ClassLoader for this Thread. The context
-     * ClassLoader is provided by the creator of the thread for use
+     * Returns the context {@code ClassLoader} for this thread. The context
+     * {@code ClassLoader} is provided by the creator of the thread for use
      * by code running in this thread when loading classes and resources.
      * If not {@linkplain #setContextClassLoader set}, the default is the
-     * ClassLoader context of the parent Thread. The context ClassLoader of the
+     * {@code ClassLoader} context of the parent thread. The context
+     * {@code ClassLoader} of the
      * primordial thread is typically set to the class loader used to load the
      * application.
      *
-     * <p>If a security manager is present, and the invoker's class loader is not
-     * {@code null} and is not the same as or an ancestor of the context class
-     * loader, then this method invokes the security manager's {@link
-     * SecurityManager#checkPermission(java.security.Permission) checkPermission}
-     * method with a {@link RuntimePermission RuntimePermission}{@code
-     * ("getClassLoader")} permission to verify that retrieval of the context
-     * class loader is permitted.
      *
-     * @return  the context ClassLoader for this Thread, or {@code null}
+     * @return  the context {@code ClassLoader} for this thread, or {@code null}
      *          indicating the system class loader (or, failing that, the
      *          bootstrap class loader)
      *
@@ -1663,7 +1755,7 @@
     }
 
     /**
-     * Returns <tt>true</tt> if and only if the current thread holds the
+     * Returns {@code true} if and only if the current thread holds the
      * monitor lock on the specified object.
      *
      * <p>This method is designed to allow a program to assert that
@@ -1673,8 +1765,8 @@
      * </pre>
      *
      * @param  obj the object on which to test lock ownership
-     * @throws NullPointerException if obj is <tt>null</tt>
-     * @return <tt>true</tt> if the current thread holds the monitor lock on
+     * @throws NullPointerException if obj is {@code null}
+     * @return {@code true} if the current thread holds the monitor lock on
      *         the specified object.
      * @since 1.4
      */
@@ -1696,8 +1788,8 @@
      *
      * <p>If there is a security manager, and this thread is not
      * the current thread, then the security manager's
-     * <tt>checkPermission</tt> method is called with a
-     * <tt>RuntimePermission("getStackTrace")</tt> permission
+     * {@code checkPermission} method is called with a
+     * {@code RuntimePermission("getStackTrace")} permission
      * to see if it's ok to get the stack trace.
      *
      * <p>Some virtual machines may, under some circumstances, omit one
@@ -1706,12 +1798,12 @@
      * this thread is permitted to return a zero-length array from this
      * method.
      *
-     * @return an array of <tt>StackTraceElement</tt>,
+     * @return an array of {@code StackTraceElement},
      * each represents one stack frame.
      *
      * @throws SecurityException
      *        if a security manager exists and its
-     *        <tt>checkPermission</tt> method doesn't allow
+     *        {@code checkPermission} method doesn't allow
      *        getting the stack trace of thread.
      * @see SecurityManager#checkPermission
      * @see RuntimePermission
@@ -1720,16 +1812,43 @@
      * @since 1.5
      */
     public StackTraceElement[] getStackTrace() {
-        // Android-changed: Use native VMStack to get stack trace.
+        // BEGIN Android-changed: Use native VMStack to get stack trace.
+        /*
+        if (this != Thread.currentThread()) {
+            // check for getStackTrace permission
+            SecurityManager security = System.getSecurityManager();
+            if (security != null) {
+                security.checkPermission(
+                    SecurityConstants.GET_STACK_TRACE_PERMISSION);
+            }
+            // optimization so we do not call into the vm for threads that
+            // have not yet started or have terminated
+            if (!isAlive()) {
+                return EMPTY_STACK_TRACE;
+            }
+            StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
+            StackTraceElement[] stackTrace = stackTraceArray[0];
+            // a thread that was alive during the previous isAlive call may have
+            // since terminated, therefore not having a stacktrace.
+            if (stackTrace == null) {
+                stackTrace = EMPTY_STACK_TRACE;
+            }
+            return stackTrace;
+        } else {
+            return (new Exception()).getStackTrace();
+        }
+        */
         StackTraceElement ste[] = VMStack.getThreadStackTrace(this);
         return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT;
+        // END Android-changed: Use native VMStack to get stack trace.
     }
 
+    // Android-removed: SecurityManager paragraph.
     /**
      * Returns a map of stack traces for all live threads.
      * The map keys are threads and each map value is an array of
-     * <tt>StackTraceElement</tt> that represents the stack dump
-     * of the corresponding <tt>Thread</tt>.
+     * {@code StackTraceElement} that represents the stack dump
+     * of the corresponding {@code Thread}.
      * The returned stack traces are in the format specified for
      * the {@link #getStackTrace getStackTrace} method.
      *
@@ -1739,20 +1858,10 @@
      * array will be returned in the map value if the virtual machine has
      * no stack trace information about a thread.
      *
-     * <p>If there is a security manager, then the security manager's
-     * <tt>checkPermission</tt> method is called with a
-     * <tt>RuntimePermission("getStackTrace")</tt> permission as well as
-     * <tt>RuntimePermission("modifyThreadGroup")</tt> permission
-     * to see if it is ok to get the stack trace of all threads.
-     *
-     * @return a <tt>Map</tt> from <tt>Thread</tt> to an array of
-     * <tt>StackTraceElement</tt> that represents the stack trace of
+     * @return a {@code Map} from {@code Thread} to an array of
+     * {@code StackTraceElement} that represents the stack trace of
      * the corresponding thread.
      *
-     * @throws SecurityException
-     *        if a security manager exists and its
-     *        <tt>checkPermission</tt> method doesn't allow
-     *        getting the stack trace of thread.
      * @see #getStackTrace
      * @see SecurityManager#checkPermission
      * @see RuntimePermission
@@ -1849,7 +1958,7 @@
      */
     private static boolean auditSubclass(final Class<?> subcl) {
         Boolean result = AccessController.doPrivileged(
-            new PrivilegedAction<Boolean>() {
+            new PrivilegedAction<>() {
                 public Boolean run() {
                     for (Class<?> cl = subcl;
                          cl != Thread.class;
@@ -1875,12 +1984,12 @@
     }
 
     // Android-removed: Native methods that are unused on Android.
-    // private native static StackTraceElement[][] dumpThreads(Thread[] threads);
-    // private native static Thread[] getThreads();
+    // private static native StackTraceElement[][] dumpThreads(Thread[] threads);
+    // private static native Thread[] getThreads();
 
     /**
      * Returns the identifier of this Thread.  The thread ID is a positive
-     * <tt>long</tt> number generated when this thread was created.
+     * {@code long} number generated when this thread was created.
      * The thread ID is unique and remains unchanged during its lifetime.
      * When a thread is terminated, this thread ID may be reused.
      *
@@ -1961,10 +2070,10 @@
          * <p>A thread in the waiting state is waiting for another thread to
          * perform a particular action.
          *
-         * For example, a thread that has called <tt>Object.wait()</tt>
+         * For example, a thread that has called {@code Object.wait()}
          * on an object is waiting for another thread to call
-         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
-         * that object. A thread that has called <tt>Thread.join()</tt>
+         * {@code Object.notify()} or {@code Object.notifyAll()} on
+         * that object. A thread that has called {@code Thread.join()}
          * is waiting for a specified thread to terminate.
          */
         WAITING,
@@ -2010,17 +2119,17 @@
     // Added in JSR-166
 
     /**
-     * Interface for handlers invoked when a <tt>Thread</tt> abruptly
+     * Interface for handlers invoked when a {@code Thread} abruptly
      * terminates due to an uncaught exception.
      * <p>When a thread is about to terminate due to an uncaught exception
      * the Java Virtual Machine will query the thread for its
-     * <tt>UncaughtExceptionHandler</tt> using
+     * {@code UncaughtExceptionHandler} using
      * {@link #getUncaughtExceptionHandler} and will invoke the handler's
-     * <tt>uncaughtException</tt> method, passing the thread and the
+     * {@code uncaughtException} method, passing the thread and the
      * exception as arguments.
-     * If a thread has not had its <tt>UncaughtExceptionHandler</tt>
-     * explicitly set, then its <tt>ThreadGroup</tt> object acts as its
-     * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
+     * If a thread has not had its {@code UncaughtExceptionHandler}
+     * explicitly set, then its {@code ThreadGroup} object acts as its
+     * {@code UncaughtExceptionHandler}. If the {@code ThreadGroup} object
      * has no
      * special requirements for dealing with the exception, it can forward
      * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
@@ -2050,6 +2159,7 @@
     // null unless explicitly set
     private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
 
+    // Android-removed: SecurityManager throws clause.
     /**
      * Set the default handler invoked when a thread abruptly terminates
      * due to an uncaught exception, and no other handler has been defined
@@ -2060,8 +2170,8 @@
      * uncaught exception handler. If the thread does not have an explicit
      * uncaught exception handler set, and the thread's thread group
      * (including parent thread groups)  does not specialize its
-     * <tt>uncaughtException</tt> method, then the default handler's
-     * <tt>uncaughtException</tt> method will be invoked.
+     * {@code uncaughtException} method, then the default handler's
+     * {@code uncaughtException} method will be invoked.
      * <p>By setting the default uncaught exception handler, an application
      * can change the way in which uncaught exceptions are handled (such as
      * logging to a specific device, or file) for those threads that would
@@ -2069,15 +2179,11 @@
      * provided.
      *
      * <p>Note that the default uncaught exception handler should not usually
-     * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause
+     * defer to the thread's {@code ThreadGroup} object, as that could cause
      * infinite recursion.
      *
      * @param eh the object to use as the default uncaught exception handler.
-     * If <tt>null</tt> then there is no default handler.
-     *
-     * @throws SecurityException if a security manager is present and it
-     *         denies <tt>{@link RuntimePermission}
-     *         (&quot;setDefaultUncaughtExceptionHandler&quot;)</tt>
+     * If {@code null} then there is no default handler.
      *
      * @see #setUncaughtExceptionHandler
      * @see #getUncaughtExceptionHandler
@@ -2100,7 +2206,7 @@
 
     /**
      * Returns the default handler invoked when a thread abruptly terminates
-     * due to an uncaught exception. If the returned value is <tt>null</tt>,
+     * due to an uncaught exception. If the returned value is {@code null},
      * there is no default.
      * @since 1.5
      * @see #setDefaultUncaughtExceptionHandler
@@ -2148,8 +2254,8 @@
      * Returns the handler invoked when this thread abruptly terminates
      * due to an uncaught exception. If this thread has not had an
      * uncaught exception handler explicitly set then this thread's
-     * <tt>ThreadGroup</tt> object is returned, unless this thread
-     * has terminated, in which case <tt>null</tt> is returned.
+     * {@code ThreadGroup} object is returned, unless this thread
+     * has terminated, in which case {@code null} is returned.
      * @since 1.5
      * @return the uncaught exception handler for this thread
      */
@@ -2163,10 +2269,10 @@
      * due to an uncaught exception.
      * <p>A thread can take full control of how it responds to uncaught
      * exceptions by having its uncaught exception handler explicitly set.
-     * If no such handler is set then the thread's <tt>ThreadGroup</tt>
+     * If no such handler is set then the thread's {@code ThreadGroup}
      * object acts as its handler.
      * @param eh the object to use as this thread's uncaught exception
-     * handler. If <tt>null</tt> then this thread has no explicit handler.
+     * handler. If {@code null} then this thread has no explicit handler.
      * @throws  SecurityException  if the current thread is not allowed to
      *          modify this thread.
      * @see #setDefaultUncaughtExceptionHandler
@@ -2306,19 +2412,17 @@
     // concurrent code, and we can not risk accidental false sharing.
     // Hence, the fields are isolated with @Contended.
 
-    // BEGIN Android-changed: @sun.misc.Contended is not supported on Android.
     /** The current seed for a ThreadLocalRandom */
-    // @sun.misc.Contended("tlr")
+    @jdk.internal.vm.annotation.Contended("tlr")
     long threadLocalRandomSeed;
 
     /** Probe hash value; nonzero if threadLocalRandomSeed initialized */
-    // @sun.misc.Contended("tlr")
+    @jdk.internal.vm.annotation.Contended("tlr")
     int threadLocalRandomProbe;
 
     /** Secondary seed isolated from public ThreadLocalRandom sequence */
-    //  @sun.misc.Contended("tlr")
+    @jdk.internal.vm.annotation.Contended("tlr")
     int threadLocalRandomSecondarySeed;
-    // END Android-changed: @sun.misc.Contended is not supported on Android.
 
     /* Some private helper methods */
     private native void setPriority0(int newPriority);
diff --git a/ojluni/src/main/java/java/lang/ThreadDeath.java b/ojluni/src/main/java/java/lang/ThreadDeath.java
index 79e8bb5..0fa350d 100644
--- a/ojluni/src/main/java/java/lang/ThreadDeath.java
+++ b/ojluni/src/main/java/java/lang/ThreadDeath.java
@@ -43,7 +43,7 @@
  * "normal occurrence", because many applications catch all
  * occurrences of {@code Exception} and then discard the exception.
  *
- * @since   JDK1.0
+ * @since   1.0
  */
 
 public class ThreadDeath extends Error {
diff --git a/ojluni/src/main/java/java/lang/ThreadLocal.java b/ojluni/src/main/java/java/lang/ThreadLocal.java
index 1422044..0b26fdc 100644
--- a/ojluni/src/main/java/java/lang/ThreadLocal.java
+++ b/ojluni/src/main/java/java/lang/ThreadLocal.java
@@ -413,7 +413,7 @@
         private Entry getEntry(ThreadLocal<?> key) {
             int i = key.threadLocalHashCode & (table.length - 1);
             Entry e = table[i];
-            // Android-changed: Use refersTo()
+            // Android-changed: Use refersTo().
             if (e != null && e.refersTo(key))
                 return e;
             else
@@ -434,7 +434,7 @@
             int len = tab.length;
 
             while (e != null) {
-                // Android-changed: Use refersTo()
+                // Android-changed: Use refersTo() (twice).
                 if (e.refersTo(key))
                     return e;
                 if (e.refersTo(null))
@@ -466,14 +466,16 @@
             for (Entry e = tab[i];
                  e != null;
                  e = tab[i = nextIndex(i, len)]) {
-                ThreadLocal<?> k = e.get();
 
-                if (k == key) {
+                // Android-changed: Use refersTo() (twice).
+                // ThreadLocal<?> k = e.get();
+                // if (k == key) { ... } if (k == null) { ... }
+                if (e.refersTo(key)) {
                     e.value = value;
                     return;
                 }
 
-                if (k == null) {
+                if (e.refersTo(null)) {
                     replaceStaleEntry(key, value, i);
                     return;
                 }
@@ -495,7 +497,8 @@
             for (Entry e = tab[i];
                  e != null;
                  e = tab[i = nextIndex(i, len)]) {
-                if (e.get() == key) {
+                // Android-changed: Use refersTo().
+                if (e.refersTo(key)) {
                     e.clear();
                     expungeStaleEntry(i);
                     return;
@@ -532,7 +535,8 @@
             for (int i = prevIndex(staleSlot, len);
                  (e = tab[i]) != null;
                  i = prevIndex(i, len))
-                if (e.get() == null)
+                // Android-changed: Use refersTo().
+                if (e.refersTo(null))
                     slotToExpunge = i;
 
             // Find either the key or trailing null slot of run, whichever
@@ -540,14 +544,15 @@
             for (int i = nextIndex(staleSlot, len);
                  (e = tab[i]) != null;
                  i = nextIndex(i, len)) {
-                ThreadLocal<?> k = e.get();
+                // ThreadLocal<?> k = e.get();
 
                 // If we find key, then we need to swap it
                 // with the stale entry to maintain hash table order.
                 // The newly stale slot, or any other stale slot
                 // encountered above it, can then be sent to expungeStaleEntry
                 // to remove or rehash all of the other entries in run.
-                if (k == key) {
+                // Android-changed: Use refersTo().
+                if (e.refersTo(key)) {
                     e.value = value;
 
                     tab[i] = tab[staleSlot];
@@ -563,7 +568,8 @@
                 // If we didn't find stale entry on backward scan, the
                 // first stale entry seen while scanning for key is the
                 // first still present in the run.
-                if (k == null && slotToExpunge == staleSlot)
+                // Android-changed: Use refersTo().
+                if (e.refersTo(null) && slotToExpunge == staleSlot)
                     slotToExpunge = i;
             }
 
@@ -654,7 +660,8 @@
             do {
                 i = nextIndex(i, len);
                 Entry e = tab[i];
-                if (e != null && e.get() == null) {
+                // Android-changed: Use refersTo().
+                if (e != null && e.refersTo(null)) {
                     n = len;
                     removed = true;
                     i = expungeStaleEntry(i);
@@ -715,7 +722,8 @@
             int len = tab.length;
             for (int j = 0; j < len; j++) {
                 Entry e = tab[j];
-                if (e != null && e.get() == null)
+                // Android-changed: Use refersTo().
+                if (e != null && e.refersTo(null))
                     expungeStaleEntry(j);
             }
         }
diff --git a/ojluni/src/main/java/java/lang/Throwable.java b/ojluni/src/main/java/java/lang/Throwable.java
index 7596681..009a117 100644
--- a/ojluni/src/main/java/java/lang/Throwable.java
+++ b/ojluni/src/main/java/java/lang/Throwable.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
  */
 
 package java.lang;
+
 import dalvik.annotation.optimization.FastNative;
+
 import  java.io.*;
 import  java.util.*;
 
@@ -111,14 +113,14 @@
  * @author  Josh Bloch (Added exception chaining and programmatic access to
  *          stack trace in 1.4.)
  * @jls 11.2 Compile-Time Checking of Exceptions
- * @since JDK1.0
+ * @since 1.0
  */
 public class Throwable implements Serializable {
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = -3042686055658047285L;
 
     /**
-     * Native code saves some indication of the stack backtrace in this slot.
+     * The JVM saves some indication of the stack backtrace in this slot.
      */
     private transient Object backtrace;
 
@@ -141,7 +143,7 @@
          * {@linkplain #setStackTrace(StackTraceElement[]) Setting the
          * stack trace} to a one-element array containing this sentinel
          * value indicates future attempts to set the stack trace will be
-         * ignored.  The sentinal is equal to the result of calling:<br>
+         * ignored.  The sentinel is equal to the result of calling:<br>
          * {@code new StackTraceElement("", "", null, Integer.MIN_VALUE)}
          */
         public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL =
@@ -206,7 +208,7 @@
      * The field is initialized to a zero-length array.  A {@code
      * null} value of this field indicates subsequent calls to {@link
      * #setStackTrace(StackTraceElement[])} and {@link
-     * #fillInStackTrace()} will be be no-ops.
+     * #fillInStackTrace()} will be no-ops.
      *
      * @serial
      * @since 1.4
@@ -215,6 +217,12 @@
     // private StackTraceElement[] stackTrace = UNASSIGNED_STACK;
     private StackTraceElement[] stackTrace = libcore.util.EmptyArray.STACK_TRACE_ELEMENT;
 
+    /**
+     * The JVM code sets the depth of the backtrace for later retrieval
+     */
+    // Android-removed: native getStackTrace is used instead.
+    // private transient int depth;
+
     // Android-removed: Use empty collection in place of SUPPRESSED_SENTINEL.
     // Adding this constant breaks serialization of some subclasses
     /*
@@ -397,7 +405,7 @@
      * {@code getMessage()}.
      *
      * @return  The localized description of this throwable.
-     * @since   JDK1.1
+     * @since   1.1
      */
     public String getLocalizedMessage() {
         return getMessage();
@@ -693,7 +701,7 @@
         // (Using assert adds a static field that determines whether assertions are enabled.)
         // assert Thread.holdsLock(s.lock());
         if (dejaVu.contains(this)) {
-            s.println("\t[CIRCULAR REFERENCE:" + this + "]");
+            s.println(prefix + caption + "[CIRCULAR REFERENCE: " + this + "]");
         } else {
             dejaVu.add(this);
             // Compute number of frames in common between this and enclosing trace
@@ -729,7 +737,7 @@
      * print writer.
      *
      * @param s {@code PrintWriter} to use for output
-     * @since   JDK1.1
+     * @since   1.1
      */
     public void printStackTrace(PrintWriter s) {
         printStackTrace(new WrappedPrintWriter(s));
@@ -907,15 +915,6 @@
         }
     }
 
-    // Android-removed: Unused native method getStackTraceDepth().
-    // /**
-    //  * Returns the number of elements in the stack trace (or 0 if the stack
-    //  * trace is unavailable).
-    //  *
-    //  * package-protection for use by SharedSecrets.
-    //  */
-    // native int getStackTraceDepth();
-
     /**
      * Returns the specified element of the stack trace.
      *
@@ -930,7 +929,6 @@
     @FastNative
     private static native StackTraceElement[] nativeGetStackTrace(Object stackState);
 
-
     /**
      * Reads a {@code Throwable} from a stream, enforcing
      * well-formedness constraints on fields.  Null entries and
@@ -949,27 +947,41 @@
     private void readObject(ObjectInputStream s)
         throws IOException, ClassNotFoundException {
         s.defaultReadObject();     // read in all fields
-        if (suppressedExceptions != null) {
-            List<Throwable> suppressed = null;
-            if (suppressedExceptions.isEmpty()) {
-                // Use the sentinel for a zero-length list
-                // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL.
-                // suppressed = SUPPRESSED_SENTINEL;
-                suppressed = Collections.emptyList();
-            } else { // Copy Throwables to new list
-                suppressed = new ArrayList<>(1);
-                for (Throwable t : suppressedExceptions) {
+
+        // Set suppressed exceptions and stack trace elements fields
+        // to marker values until the contents from the serial stream
+        // are validated.
+        List<Throwable> candidateSuppressedExceptions = suppressedExceptions;
+        // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL.
+        // suppressedExceptions = SUPPRESSED_SENTINEL;
+        suppressedExceptions = Collections.emptyList();
+
+        StackTraceElement[] candidateStackTrace = stackTrace;
+        // Android-changed: Directly create empty array instead of cloning UNASSIGNED_STACK.
+        // stackTrace = UNASSIGNED_STACK.clone();
+        stackTrace = new StackTraceElement[0];
+
+        if (candidateSuppressedExceptions != null) {
+            int suppressedSize = validateSuppressedExceptionsList(candidateSuppressedExceptions);
+            if (suppressedSize > 0) { // Copy valid Throwables to new list
+                var suppList  = new ArrayList<Throwable>(Math.min(100, suppressedSize));
+
+                for (Throwable t : candidateSuppressedExceptions) {
                     // Enforce constraints on suppressed exceptions in
                     // case of corrupt or malicious stream.
                     if (t == null)
                         throw new NullPointerException(NULL_CAUSE_MESSAGE);
                     if (t == this)
                         throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
-                    suppressed.add(t);
+                    suppList.add(t);
                 }
+                // If there are any invalid suppressed exceptions,
+                // implicitly use the sentinel value assigned earlier.
+                suppressedExceptions = suppList;
             }
-            suppressedExceptions = suppressed;
-        } // else a null suppressedExceptions field remains null
+        } else {
+            suppressedExceptions = null;
+        }
 
         /*
          * For zero-length stack traces, use a clone of
@@ -980,28 +992,47 @@
          * the stackTrace needs to be constructed from the information
          * in backtrace.
          */
-        if (stackTrace != null) {
-            if (stackTrace.length == 0) {
-                // Android-removed: clone() call unneeded because of libcore.util.EmptyArray usage.
-                // stackTrace = UNASSIGNED_STACK.clone();
-            }  else if (stackTrace.length == 1 &&
+        if (candidateStackTrace != null) {
+            // Work from a clone of the candidateStackTrace to ensure
+            // consistency of checks.
+            candidateStackTrace = candidateStackTrace.clone();
+            if (candidateStackTrace.length >= 1) {
+                if (candidateStackTrace.length == 1 &&
                         // Check for the marker of an immutable stack trace
-                        SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
-                stackTrace = null;
-            } else { // Verify stack trace elements are non-null.
-                for(StackTraceElement ste : stackTrace) {
-                    if (ste == null)
-                        throw new NullPointerException("null StackTraceElement in serial stream. ");
+                        SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(candidateStackTrace[0])) {
+                    stackTrace = null;
+                } else { // Verify stack trace elements are non-null.
+                    for (StackTraceElement ste : candidateStackTrace) {
+                        if (ste == null)
+                            throw new NullPointerException("null StackTraceElement in serial stream.");
+                    }
+                    stackTrace = candidateStackTrace;
                 }
             }
+        }
+        // A null stackTrace field in the serial form can result from
+        // an exception serialized without that field in older JDK
+        // releases; treat such exceptions as having empty stack
+        // traces by leaving stackTrace assigned to a clone of
+        // UNASSIGNED_STACK.
+    }
+
+    private int validateSuppressedExceptionsList(List<Throwable> deserSuppressedExceptions)
+        throws IOException {
+        // BEGIN Android-changed: Object class hasn't implemented the module system and getModule().
+        /*
+        if (!Object.class.getModule().
+            equals(deserSuppressedExceptions.getClass().getModule())) {
+            throw new StreamCorruptedException("List implementation not in base module.");
         } else {
-            // A null stackTrace field in the serial form can result
-            // from an exception serialized without that field in
-            // older JDK releases; treat such exceptions as having
-            // empty stack traces.
-            // Android-changed: Directly create empty array instead of cloning UNASSIGNED_STACK.
-            // stackTrace = UNASSIGNED_STACK.clone();
-            stackTrace = new StackTraceElement[0];
+        */
+        {
+        // END Android-changed: Object class hasn't implemented the module system and getModule().
+            int size = deserSuppressedExceptions.size();
+            if (size < 0) {
+                throw new StreamCorruptedException("Negative list size reported.");
+            }
+            return size;
         }
     }
 
diff --git a/ojluni/src/main/java/java/lang/TypeNotPresentException.java b/ojluni/src/main/java/java/lang/TypeNotPresentException.java
index 65a0207..0281612 100644
--- a/ojluni/src/main/java/java/lang/TypeNotPresentException.java
+++ b/ojluni/src/main/java/java/lang/TypeNotPresentException.java
@@ -29,7 +29,7 @@
  * Thrown when an application tries to access a type using a string
  * representing the type's name, but no definition for the type with
  * the specified name can be found.   This exception differs from
- * {@link ClassNotFoundException} in that <tt>ClassNotFoundException</tt> is a
+ * {@link ClassNotFoundException} in that {@code ClassNotFoundException} is a
  * checked exception, whereas this exception is unchecked.
  *
  * <p>Note that this exception may be used when undefined type variables
@@ -49,12 +49,12 @@
     private String typeName;
 
     /**
-     * Constructs a <tt>TypeNotPresentException</tt> for the named type
+     * Constructs a {@code TypeNotPresentException} for the named type
      * with the specified cause.
      *
      * @param typeName the fully qualified name of the unavailable type
      * @param cause the exception that was thrown when the system attempted to
-     *    load the named type, or <tt>null</tt> if unavailable or inapplicable
+     *    load the named type, or {@code null} if unavailable or inapplicable
      */
     public TypeNotPresentException(String typeName, Throwable cause) {
         super("Type " + typeName + " not present", cause);
diff --git a/ojluni/src/main/java/java/lang/UnknownError.java b/ojluni/src/main/java/java/lang/UnknownError.java
index 0706f81..a88a6a8 100644
--- a/ojluni/src/main/java/java/lang/UnknownError.java
+++ b/ojluni/src/main/java/java/lang/UnknownError.java
@@ -30,7 +30,7 @@
  * Java Virtual Machine.
  *
  * @author unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class UnknownError extends VirtualMachineError {
diff --git a/ojluni/src/main/java/java/lang/UnsatisfiedLinkError.java b/ojluni/src/main/java/java/lang/UnsatisfiedLinkError.java
index 32a8ba8..482fdbd 100644
--- a/ojluni/src/main/java/java/lang/UnsatisfiedLinkError.java
+++ b/ojluni/src/main/java/java/lang/UnsatisfiedLinkError.java
@@ -31,7 +31,7 @@
  *
  * @author unascribed
  * @see     java.lang.Runtime
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class UnsatisfiedLinkError extends LinkageError {
diff --git a/ojluni/src/main/java/java/lang/UnsupportedOperationException.java b/ojluni/src/main/java/java/lang/UnsupportedOperationException.java
index 1de2508..9a5aa6a 100644
--- a/ojluni/src/main/java/java/lang/UnsupportedOperationException.java
+++ b/ojluni/src/main/java/java/lang/UnsupportedOperationException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@
  * Thrown to indicate that the requested operation is not supported.<p>
  *
  * This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
@@ -63,7 +63,7 @@
      * @param  message the detail message (which is saved for later retrieval
      *         by the {@link Throwable#getMessage()} method).
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link Throwable#getCause()} method).  (A <tt>null</tt> value
+     *         {@link Throwable#getCause()} method).  (A {@code null} value
      *         is permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since 1.5
@@ -74,14 +74,14 @@
 
     /**
      * Constructs a new exception with the specified cause and a detail
-     * message of <tt>(cause==null ? null : cause.toString())</tt> (which
-     * typically contains the class and detail message of <tt>cause</tt>).
+     * message of {@code (cause==null ? null : cause.toString())} (which
+     * typically contains the class and detail message of {@code cause}).
      * This constructor is useful for exceptions that are little more than
      * wrappers for other throwables (for example, {@link
      * java.security.PrivilegedActionException}).
      *
      * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link Throwable#getCause()} method).  (A <tt>null</tt> value is
+     *         {@link Throwable#getCause()} method).  (A {@code null} value is
      *         permitted, and indicates that the cause is nonexistent or
      *         unknown.)
      * @since  1.5
diff --git a/ojluni/src/main/java/java/lang/VerifyError.java b/ojluni/src/main/java/java/lang/VerifyError.java
index 9ca9f90..3f991a7 100644
--- a/ojluni/src/main/java/java/lang/VerifyError.java
+++ b/ojluni/src/main/java/java/lang/VerifyError.java
@@ -31,7 +31,7 @@
  * or security problem.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class VerifyError extends LinkageError {
diff --git a/ojluni/src/main/java/java/lang/VirtualMachineError.java b/ojluni/src/main/java/java/lang/VirtualMachineError.java
index c0a2a92..04e21fa 100644
--- a/ojluni/src/main/java/java/lang/VirtualMachineError.java
+++ b/ojluni/src/main/java/java/lang/VirtualMachineError.java
@@ -31,9 +31,9 @@
  *
  *
  * @author  Frank Yellin
- * @since   JDK1.0
+ * @since   1.0
  */
-abstract public class VirtualMachineError extends Error {
+public abstract class VirtualMachineError extends Error {
     private static final long serialVersionUID = 4161983926571568670L;
 
     /**
diff --git a/ojluni/src/main/java/java/lang/Void.java b/ojluni/src/main/java/java/lang/Void.java
index 96dbe6d..581d0d6 100644
--- a/ojluni/src/main/java/java/lang/Void.java
+++ b/ojluni/src/main/java/java/lang/Void.java
@@ -31,7 +31,7 @@
  * void.
  *
  * @author  unascribed
- * @since   JDK1.1
+ * @since   1.1
  */
 public final
 class Void {
diff --git a/ojluni/src/main/java/java/lang/invoke/ConstantCallSite.java b/ojluni/src/main/java/java/lang/invoke/ConstantCallSite.java
index f27d0e7b..f7d87ba 100644
--- a/ojluni/src/main/java/java/lang/invoke/ConstantCallSite.java
+++ b/ojluni/src/main/java/java/lang/invoke/ConstantCallSite.java
@@ -30,6 +30,7 @@
  * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
  * bound to the call site's target.
  * @author John Rose, JSR 292 EG
+ * @since 1.7
  */
 public class ConstantCallSite extends CallSite {
     private final boolean isFrozen;
diff --git a/ojluni/src/main/java/java/lang/invoke/LambdaConversionException.java b/ojluni/src/main/java/java/lang/invoke/LambdaConversionException.java
index e1123da..2dc8f22 100644
--- a/ojluni/src/main/java/java/lang/invoke/LambdaConversionException.java
+++ b/ojluni/src/main/java/java/lang/invoke/LambdaConversionException.java
@@ -27,6 +27,8 @@
 
 /**
  * LambdaConversionException
+ *
+ * @since 1.8
  */
 public class LambdaConversionException extends Exception {
     private static final long serialVersionUID = 292L + 8L;
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
index 87911c2..b03b769 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandle.java
@@ -25,6 +25,8 @@
 
 package java.lang.invoke;
 
+import java.util.Arrays;
+import java.util.Objects;
 
 import dalvik.system.EmulatedStackFrame;
 
@@ -434,35 +436,26 @@
     // @interface PolymorphicSignature { }
     public @interface PolymorphicSignature { }
 
-    // Android-added: Comment to differentiate between type and nominalType.
     /**
      * The type of this method handle, this corresponds to the exact type of the method
      * being invoked.
-     * 
-     * @see #nominalType
      */
     private final MethodType type;
-    // Android-removed: LambdaForm and customizationCount unused on Android.
+
+    // Android-removed: LambdaForm is unused on Android.
     // They will be substituted with appropriate implementation / delegate classes.
     /*
     /*private* final LambdaForm form;
     // form is not private so that invokers can easily fetch it
-    /*private* MethodHandle asTypeCache;
+    */
+    /*private*/ MethodHandle asTypeCache;
     // asTypeCache is not private so that invokers can easily fetch it
+    /*
+    // Android-removed: customizationCount is unused on Android.
     /*non-public* byte customizationCount;
     // customizationCount should be accessible from invokers
     */
 
-    // BEGIN Android-added: Android specific implementation.
-    // The MethodHandle functionality is tightly coupled with internal details of the runtime and
-    // so Android has a completely different implementation compared to the RI.
-    /**
-     * The nominal type of this method handle, will be non-null if a method handle declares
-     * a different type from its "real" type, which is either the type of the method being invoked
-     * or the type of the emulated stackframe expected by an underyling adapter.
-     */
-    private MethodType nominalType;
-
     /**
      * The spread invoker associated with this type with zero trailing arguments.
      * This is used to speed up invokeWithArguments.
@@ -478,13 +471,6 @@
      * INVOKE_TRANSFORM is a special type of handle which doesn't encode any dex bytecode behaviour,
      * instead it transforms the list of input arguments or performs other higher order operations
      * before (optionally) delegating to another method handle.
-     *
-     * INVOKE_CALLSITE_TRANSFORM is a variation on INVOKE_TRANSFORM where the method type of
-     * a MethodHandle dynamically varies based on the callsite. This is used by
-     * the VarargsCollector implementation which places any number of trailing arguments
-     * into an array before invoking an arity method. The "any number of trailing arguments" means
-     * it would otherwise generate WrongMethodTypeExceptions as the callsite method type and
-     * VarargsCollector method type appear incompatible.
      */
 
     /** @hide */ public static final int INVOKE_VIRTUAL = 0;
@@ -493,13 +479,12 @@
     /** @hide */ public static final int INVOKE_STATIC = 3;
     /** @hide */ public static final int INVOKE_INTERFACE = 4;
     /** @hide */ public static final int INVOKE_TRANSFORM = 5;
-    /** @hide */ public static final int INVOKE_CALLSITE_TRANSFORM = 6;
-    /** @hide */ public static final int INVOKE_VAR_HANDLE = 7;
-    /** @hide */ public static final int INVOKE_VAR_HANDLE_EXACT = 8;
-    /** @hide */ public static final int IGET = 9;
-    /** @hide */ public static final int IPUT = 10;
-    /** @hide */ public static final int SGET = 11;
-    /** @hide */ public static final int SPUT = 12;
+    /** @hide */ public static final int INVOKE_VAR_HANDLE = 6;
+    /** @hide */ public static final int INVOKE_VAR_HANDLE_EXACT = 7;
+    /** @hide */ public static final int IGET = 8;
+    /** @hide */ public static final int IPUT = 9;
+    /** @hide */ public static final int SGET = 10;
+    /** @hide */ public static final int SPUT = 11;
 
     // The kind of this method handle (used by the runtime). This is one of the INVOKE_*
     // constants or SGET/SPUT, IGET/IPUT.
@@ -522,11 +507,6 @@
      * @return the method handle type
      */
     public MethodType type() {
-        // Android-added: Added nominalType field.
-        if (nominalType != null) {
-            return nominalType;
-        }
-
         return type;
     }
 
@@ -715,19 +695,15 @@
      * @see MethodHandles#spreadInvoker
      */
     public Object invokeWithArguments(Object... arguments) throws Throwable {
+        MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length);
         // BEGIN Android-changed: Android specific implementation.
-        // MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length);
         // return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments);
-        MethodHandle invoker = null;
-        synchronized (this) {
-            if (cachedSpreadInvoker == null) {
-                cachedSpreadInvoker = MethodHandles.spreadInvoker(this.type(), 0);
-            }
-
-            invoker = cachedSpreadInvoker;
+        MethodHandle invoker = cachedSpreadInvoker;
+        if (invoker == null || !invoker.type().equals(invocationType)) {
+            invoker = MethodHandles.spreadInvoker(invocationType, 0);
+            cachedSpreadInvoker = invoker;
         }
-
-        return invoker.invoke(this, arguments);
+        return invoker.invoke(asType(invocationType), arguments);
         // END Android-changed: Android specific implementation.
     }
 
@@ -854,30 +830,26 @@
     public MethodHandle asType(MethodType newType) {
         // Fast path alternative to a heavyweight {@code asType} call.
         // Return 'this' if the conversion will be a no-op.
-        if (newType == type) {
+        // Android-changed: use equals() rather than = since MethodTypes are not interned.
+        if (newType.equals(type)) {
             return this;
         }
-        // Android-removed: Type conversion memoizing is unsupported on Android.
-        /*
         // Return 'this.asTypeCache' if the conversion is already memoized.
         MethodHandle atc = asTypeCached(newType);
         if (atc != null) {
             return atc;
         }
-        */
         return asTypeUncached(newType);
     }
 
-    // Android-removed: Type conversion memoizing is unsupported on Android.
-    /*
     private MethodHandle asTypeCached(MethodType newType) {
         MethodHandle atc = asTypeCache;
-        if (atc != null && newType == atc.type) {
+        // Android-changed: use equals() rather than = since MethodTypes are not interned.
+        if (atc != null && newType.equals(atc.type)) {
             return atc;
         }
         return null;
     }
-    */
 
     /** Override this to change asType behavior. */
     /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
@@ -885,9 +857,7 @@
             throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
         // BEGIN Android-changed: Android specific implementation.
         // return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, true);
-        MethodHandle mh = duplicate();
-        mh.nominalType = newType;
-        return mh;
+        return asTypeCache = new Transformers.AsTypeAdapter(this, newType);
         // END Android-changed: Android specific implementation.
     }
 
@@ -918,9 +888,13 @@
      * to the target method handle.
      * (The array may also be null when zero elements are required.)
      * <p>
-     * If, when the adapter is called, the supplied array argument does
-     * not have the correct number of elements, the adapter will throw
-     * an {@link IllegalArgumentException} instead of invoking the target.
+     * When the adapter is called, the length of the supplied {@code array}
+     * argument is queried as if by {@code array.length} or {@code arraylength}
+     * bytecode. If the adapter accepts a zero-length trailing array argument,
+     * the supplied {@code array} argument can either be a zero-length array or
+     * {@code null}; otherwise, the adapter will throw a {@code NullPointerException}
+     * if the array is {@code null} and throw an {@link IllegalArgumentException}
+     * if the array does not have the correct number of elements.
      * <p>
      * Here are some simple examples of array-spreading method handles:
      * <blockquote><pre>{@code
@@ -934,7 +908,7 @@
 assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" }));
 // try to spread from anything but a 2-array:
 for (int n = 0; n <= 10; n++) {
-  Object[] badArityArgs = (n == 2 ? null : new Object[n]);
+  Object[] badArityArgs = (n == 2 ? new Object[0] : new Object[n]);
   try { assert((boolean) eq2.invokeExact(badArityArgs) && false); }
   catch (IllegalArgumentException ex) { } // OK
 }
@@ -981,23 +955,63 @@
      * @see #asCollector
      */
     public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
-        MethodType postSpreadType = asSpreaderChecks(arrayType, arrayLength);
+        return asSpreader(type().parameterCount() - arrayLength, arrayType, arrayLength);
+    }
+
+    /**
+     * Makes an <em>array-spreading</em> method handle, which accepts an array argument at a given position and spreads
+     * its elements as positional arguments in place of the array. The new method handle adapts, as its <i>target</i>,
+     * the current method handle. The type of the adapter will be the same as the type of the target, except that the
+     * {@code arrayLength} parameters of the target's type, starting at the zero-based position {@code spreadArgPos},
+     * are replaced by a single array parameter of type {@code arrayType}.
+     * <p>
+     * This method behaves very much like {@link #asSpreader(Class, int)}, but accepts an additional {@code spreadArgPos}
+     * argument to indicate at which position in the parameter list the spreading should take place.
+     *
+     * @apiNote Example:
+     * <blockquote><pre>{@code
+    MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
+    MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
+    Object[] ints = new Object[]{3, 9, 7, 7};
+    Comparator<Integer> cmp = (a, b) -> a - b;
+    assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
+    assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
+    assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
+     * }</pre></blockquote>
+     * @param spreadArgPos the position (zero-based index) in the argument list at which spreading should start.
+     * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
+     * @param arrayLength the number of arguments to spread from an incoming array argument
+     * @return a new method handle which spreads an array argument at a given position,
+     *         before calling the original method handle
+     * @throws NullPointerException if {@code arrayType} is a null reference
+     * @throws IllegalArgumentException if {@code arrayType} is not an array type,
+     *         or if target does not have at least
+     *         {@code arrayLength} parameter types,
+     *         or if {@code arrayLength} is negative,
+     *         or if {@code spreadArgPos} has an illegal value (negative, or together with arrayLength exceeding the
+     *         number of arguments),
+     *         or if the resulting method handle's type would have
+     *         <a href="MethodHandle.html#maxarity">too many parameters</a>
+     * @throws WrongMethodTypeException if the implied {@code asType} call fails
+     *
+     * @see #asSpreader(Class, int)
+     * @since 9
+     */
+    public MethodHandle asSpreader(int spreadArgPos, Class<?> arrayType, int arrayLength) {
+        MethodType postSpreadType = asSpreaderChecks(arrayType, spreadArgPos, arrayLength);
         // BEGIN Android-changed: Android specific implementation.
         /*
-        int arity = type().parameterCount();
-        int spreadArgPos = arity - arrayLength;
         MethodHandle afterSpread = this.asType(postSpreadType);
         BoundMethodHandle mh = afterSpread.rebind();
         LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength);
-        MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType);
+        MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, spreadArgPos + arrayLength, arrayType);
         return mh.copyWith(preSpreadType, lform);
         */
-        final int targetParamCount = postSpreadType.parameterCount();
-        MethodType dropArrayArgs = postSpreadType.dropParameterTypes(
-                (targetParamCount - arrayLength), targetParamCount);
-        MethodType adapterType = dropArrayArgs.appendParameterTypes(arrayType);
-
-        return new Transformers.Spreader(this, adapterType, arrayLength);
+        final int spreadEnd = spreadArgPos + arrayLength;
+        final MethodType adapterType =
+                postSpreadType.replaceParameterTypes(spreadArgPos, spreadEnd, arrayType);
+        return new Transformers.Spreader(
+                asType(postSpreadType), adapterType, spreadArgPos, arrayLength);
         // END Android-changed: Android specific implementation.
     }
 
@@ -1005,15 +1019,18 @@
      * See if {@code asSpreader} can be validly called with the given arguments.
      * Return the type of the method handle call after spreading but before conversions.
      */
-    private MethodType asSpreaderChecks(Class<?> arrayType, int arrayLength) {
+    private MethodType asSpreaderChecks(Class<?> arrayType, int pos, int arrayLength) {
         spreadArrayChecks(arrayType, arrayLength);
         int nargs = type().parameterCount();
         if (nargs < arrayLength || arrayLength < 0)
             throw newIllegalArgumentException("bad spread array length");
+        if (pos < 0 || pos + arrayLength > nargs) {
+            throw newIllegalArgumentException("bad spread position");
+        }
         Class<?> arrayElement = arrayType.getComponentType();
         MethodType mtype = type();
         boolean match = true, fail = false;
-        for (int i = nargs - arrayLength; i < nargs; i++) {
+        for (int i = pos; i < pos + arrayLength; i++) {
             Class<?> ptype = mtype.parameterType(i);
             if (ptype != arrayElement) {
                 match = false;
@@ -1024,11 +1041,11 @@
             }
         }
         if (match)  return mtype;
-        MethodType needType = mtype.asSpreaderType(arrayType, arrayLength);
+        MethodType needType = mtype.asSpreaderType(arrayType, pos, arrayLength);
         if (!fail)  return needType;
         // elicit an error:
         this.asType(needType);
-        throw newInternalError("should not return", null);
+        throw newInternalError("should not return");
     }
 
     private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
@@ -1046,6 +1063,46 @@
     }
 
     /**
+     * Adapts this method handle to be {@linkplain #asVarargsCollector variable arity}
+     * if the boolean flag is true, else {@linkplain #asFixedArity fixed arity}.
+     * If the method handle is already of the proper arity mode, it is returned
+     * unchanged.
+     * @apiNote
+     * <p>This method is sometimes useful when adapting a method handle that
+     * may be variable arity, to ensure that the resulting adapter is also
+     * variable arity if and only if the original handle was.  For example,
+     * this code changes the first argument of a handle {@code mh} to {@code int} without
+     * disturbing its variable arity property:
+     * {@code mh.asType(mh.type().changeParameterType(0,int.class))
+     *     .withVarargs(mh.isVarargsCollector())}
+     * <p>
+     * This call is approximately equivalent to the following code:
+     * <blockquote><pre>{@code
+     * if (makeVarargs == isVarargsCollector())
+     *   return this;
+     * else if (makeVarargs)
+     *   return asVarargsCollector(type().lastParameterType());
+     * else
+     *   return return asFixedArity();
+     * }</pre></blockquote>
+     * @param makeVarargs true if the return method handle should have variable arity behavior
+     * @return a method handle of the same type, with possibly adjusted variable arity behavior
+     * @throws IllegalArgumentException if {@code makeVarargs} is true and
+     *         this method handle does not have a trailing array parameter
+     * @since 9
+     * @see #asVarargsCollector
+     * @see #asFixedArity
+     */
+    public MethodHandle withVarargs(boolean makeVarargs) {
+        assert(!isVarargsCollector());  // subclass responsibility
+        if (makeVarargs) {
+           return asVarargsCollector(type().lastParameterType());
+        } else {
+            return this;
+        }
+    }
+
+    /**
      * Makes an <em>array-collecting</em> method handle, which accepts a given number of trailing
      * positional arguments and collects them into an array argument.
      * The new method handle adapts, as its <i>target</i>,
@@ -1117,12 +1174,58 @@
      * @see #asVarargsCollector
      */
     public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
-        asCollectorChecks(arrayType, arrayLength);
+        return asCollector(type().parameterCount() - 1, arrayType, arrayLength);
+    }
+
+   /**
+     * Makes an <em>array-collecting</em> method handle, which accepts a given number of positional arguments starting
+     * at a given position, and collects them into an array argument. The new method handle adapts, as its
+     * <i>target</i>, the current method handle. The type of the adapter will be the same as the type of the target,
+     * except that the parameter at the position indicated by {@code collectArgPos} (usually of type {@code arrayType})
+     * is replaced by {@code arrayLength} parameters whose type is element type of {@code arrayType}.
+     * <p>
+     * This method behaves very much like {@link #asCollector(Class, int)}, but differs in that its {@code
+     * collectArgPos} argument indicates at which position in the parameter list arguments should be collected. This
+     * index is zero-based.
+     *
+     * @apiNote Examples:
+     * <blockquote><pre>{@code
+    StringWriter swr = new StringWriter();
+    MethodHandle swWrite = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).bindTo(swr);
+    MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
+    swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
+    assertEquals("BC", swr.toString());
+    swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
+    assertEquals("BCPQRS", swr.toString());
+    swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
+    assertEquals("BCPQRSZ", swr.toString());
+     * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
+     * @param collectArgPos the zero-based position in the parameter list at which to start collecting.
+     * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
+     * @param arrayLength the number of arguments to collect into a new array argument
+     * @return a new method handle which collects some arguments
+     *         into an array, before calling the original method handle
+     * @throws NullPointerException if {@code arrayType} is a null reference
+     * @throws IllegalArgumentException if {@code arrayType} is not an array type
+     *         or {@code arrayType} is not assignable to this method handle's array parameter type,
+     *         or {@code arrayLength} is not a legal array size,
+     *         or {@code collectArgPos} has an illegal value (negative, or greater than the number of arguments),
+     *         or the resulting method handle's type would have
+     *         <a href="MethodHandle.html#maxarity">too many parameters</a>
+     * @throws WrongMethodTypeException if the implied {@code asType} call fails
+     *
+     * @see #asCollector(Class, int)
+     * @since 9
+     */
+    public MethodHandle asCollector(int collectArgPos, Class<?> arrayType, int arrayLength) {
+        asCollectorChecks(arrayType, collectArgPos, arrayLength);
         // BEGIN Android-changed: Android specific implementation.
         /*
-        int collectArgPos = type().parameterCount() - 1;
         BoundMethodHandle mh = rebind();
-        MethodType resultType = type().asCollectorType(arrayType, arrayLength);
+        MethodType resultType = type().asCollectorType(arrayType, collectArgPos, arrayLength);
         MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength);
         LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray);
         if (lform != null) {
@@ -1131,7 +1234,7 @@
         lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType());
         return mh.copyWithExtendL(resultType, lform, newArray);
         */
-        return new Transformers.Collector(this, arrayType, arrayLength);
+        return new Transformers.Collector(this, arrayType, collectArgPos, arrayLength);
         // END Android-changed: Android specific implementation.
     }
 
@@ -1139,15 +1242,18 @@
      * See if {@code asCollector} can be validly called with the given arguments.
      * Return false if the last parameter is not an exact match to arrayType.
      */
-    /*non-public*/ boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
+    /*non-public*/ boolean asCollectorChecks(Class<?> arrayType, int pos, int arrayLength) {
         spreadArrayChecks(arrayType, arrayLength);
         int nargs = type().parameterCount();
-        if (nargs != 0) {
-            Class<?> lastParam = type().parameterType(nargs-1);
-            if (lastParam == arrayType)  return true;
-            if (lastParam.isAssignableFrom(arrayType))  return false;
+        if (pos < 0 || pos >= nargs) {
+            throw newIllegalArgumentException("bad collect position");
         }
-        throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
+        if (nargs != 0) {
+            Class<?> param = type().parameterType(pos);
+            if (param == arrayType)  return true;
+            if (param.isAssignableFrom(arrayType))  return false;
+        }
+        throw newIllegalArgumentException("array type not assignable to argument", this, arrayType);
     }
 
     /**
@@ -1160,7 +1266,9 @@
      * {@code invoke} and {@code asType} requests can lead to
      * trailing positional arguments being collected into target's
      * trailing parameter.
-     * Also, the last parameter type of the adapter will be
+     * Also, the
+     * {@linkplain MethodType#lastParameterType last parameter type}
+     * of the adapter will be
      * {@code arrayType}, even if the target has a different
      * last parameter type.
      * <p>
@@ -1241,7 +1349,7 @@
      * <p>
      * No method handle transformations produce new method handles with
      * variable arity, unless they are documented as doing so.
-     * Therefore, besides {@code asVarargsCollector},
+     * Therefore, besides {@code asVarargsCollector} and {@code withVarargs},
      * all methods in {@code MethodHandle} and {@code MethodHandles}
      * will return a method handle with fixed arity,
      * except in the cases where they are specified to return their original
@@ -1298,11 +1406,12 @@
      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type
      * @see #asCollector
      * @see #isVarargsCollector
+     * @see #withVarargs
      * @see #asFixedArity
      */
     public MethodHandle asVarargsCollector(Class<?> arrayType) {
-        arrayType.getClass(); // explicit NPE
-        boolean lastMatch = asCollectorChecks(arrayType, 0);
+        Objects.requireNonNull(arrayType);
+        boolean lastMatch = asCollectorChecks(arrayType, type().parameterCount() - 1, 0);
         if (isVarargsCollector() && lastMatch)
             return this;
         // Android-changed: Android specific implementation.
@@ -1459,6 +1568,11 @@
     // BEGIN Android-added: Android specific implementation.
     /** @hide */
     public int getHandleKind() {
+        if (handleKind == INVOKE_VAR_HANDLE_EXACT || handleKind == INVOKE_VAR_HANDLE) {
+            // No need to expose Android implementation detail, avoids larger
+            // MethodHandleInfo changes in revealDirect() code path.
+            return INVOKE_VIRTUAL;
+        }
         return handleKind;
     }
 
@@ -1468,6 +1582,15 @@
     }
 
     /**
+     * Entry back into the runtime to dispatch a MethodHandle with a specific EmulatedStackFrame
+     * containing the arguments to provide.
+     * @param arguments the stack frame holding arguments for the invocation.
+     * @hide
+     */
+    /* package-private */ native void invokeExactWithFrame(EmulatedStackFrame arguments)
+            throws Throwable;
+
+    /**
      * Creates a copy of this method handle, copying all relevant data.
      *
      * @hide
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java b/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java
index 6514cb6..a72b07b 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandleImpl.java
@@ -159,8 +159,25 @@
         @Override
         public <T extends Member> T reflectAs(Class<T> expected, MethodHandles.Lookup lookup) {
             try {
-                lookup.checkAccess(member.getDeclaringClass(), member.getDeclaringClass(),
-                        member.getModifiers(), member.getName());
+                final Class declaringClass = member.getDeclaringClass();
+                if (Modifier.isNative(getModifiers()) &&
+                        (MethodHandle.class.isAssignableFrom(declaringClass)
+                                || VarHandle.class.isAssignableFrom(declaringClass))) {
+                    if (member instanceof Method) {
+                        Method m = (Method) member;
+                        if (m.isVarArgs()) {
+                            // Signature-polymorphic methods should not be reflected as there
+                            // is no support for invoking them via reflection.
+                            //
+                            // We've identified this method as signature-polymorphic due to
+                            // its flags (var-args and native) and its class.
+                            throw new IllegalArgumentException(
+                                    "Reflecting signature polymorphic method");
+                        }
+                    }
+                }
+                lookup.checkAccess(
+                        declaringClass, declaringClass, member.getModifiers(), member.getName());
             } catch (IllegalAccessException exception) {
                 throw new IllegalArgumentException("Unable to access member.", exception);
             }
@@ -172,5 +189,11 @@
         public int getModifiers() {
             return member.getModifiers();
         }
+
+        @Override
+        public String toString() {
+            return MethodHandleInfo.toString(
+                    getReferenceKind(), getDeclaringClass(), getName(), getMethodType());
+        }
     }
 }
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
index 1188ac6..d5d4448 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
@@ -25,18 +25,24 @@
 
 package java.lang.invoke;
 
+import sun.invoke.util.VerifyAccess;
+import sun.invoke.util.Wrapper;
+import sun.reflect.Reflection;
+
 import java.lang.reflect.*;
 import java.nio.ByteOrder;
 import java.util.List;
 import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.NoSuchElementException;
-
-import sun.invoke.util.VerifyAccess;
-import sun.invoke.util.Wrapper;
-import sun.reflect.Reflection;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
+import static java.lang.invoke.MethodType.methodType;
 
 /**
  * This class consists exclusively of static methods that operate on or return
@@ -113,6 +119,53 @@
         return Lookup.PUBLIC_LOOKUP;
     }
 
+    // Android-removed: Documentation related to the security manager and module checks
+    /**
+     * Returns a {@link Lookup lookup object} with full capabilities to emulate all
+     * supported bytecode behaviors, including <a href="MethodHandles.Lookup.html#privacc">
+     * private access</a>, on a target class.
+     * @param targetClass the target class
+     * @param lookup the caller lookup object
+     * @return a lookup object for the target class, with private access
+     * @throws IllegalArgumentException if {@code targetClass} is a primitive type or array class
+     * @throws NullPointerException if {@code targetClass} or {@code caller} is {@code null}
+     * @throws IllegalAccessException is not thrown on Android
+     * @since 9
+     */
+    public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException {
+        // Android-removed: SecurityManager calls
+        // SecurityManager sm = System.getSecurityManager();
+        // if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
+        if (targetClass.isPrimitive())
+            throw new IllegalArgumentException(targetClass + " is a primitive class");
+        if (targetClass.isArray())
+            throw new IllegalArgumentException(targetClass + " is an array class");
+        // BEGIN Android-removed: There is no module information on Android
+        /**
+         * Module targetModule = targetClass.getModule();
+         * Module callerModule = lookup.lookupClass().getModule();
+         * if (!callerModule.canRead(targetModule))
+         *     throw new IllegalAccessException(callerModule + " does not read " + targetModule);
+         * if (targetModule.isNamed()) {
+         *     String pn = targetClass.getPackageName();
+         *     assert pn.length() > 0 : "unnamed package cannot be in named module";
+         *     if (!targetModule.isOpen(pn, callerModule))
+         *         throw new IllegalAccessException(targetModule + " does not open " + pn + " to " + callerModule);
+         * }
+         * if ((lookup.lookupModes() & Lookup.MODULE) == 0)
+         *     throw new IllegalAccessException("lookup does not have MODULE lookup mode");
+         * if (!callerModule.isNamed() && targetModule.isNamed()) {
+         *     IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
+         *     if (logger != null) {
+         *         logger.logIfOpenedForIllegalAccess(lookup, targetClass);
+         *     }
+         * }
+         */
+        // END Android-removed: There is no module information on Android
+        return new Lookup(targetClass);
+    }
+
+
     /**
      * Performs an unchecked "crack" of a
      * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
@@ -680,7 +733,9 @@
             // Android-changed: The bootstrap classloader isn't null.
             if (allowedModes == ALL_MODES &&
                     lookupClass.getClassLoader() == Object.class.getClassLoader()) {
-                if (name.startsWith("java.") ||
+                if ((name.startsWith("java.")
+                            && !name.startsWith("java.util.concurrent.")
+                            && !name.equals("java.lang.Thread")) ||
                         (name.startsWith("sun.")
                                 && !name.startsWith("sun.invoke.")
                                 && !name.equals("sun.reflect.ReflectionFactory"))) {
@@ -1330,7 +1385,6 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          * @since 9
-         * @hide
          */
         public VarHandle findVarHandle(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             final Field field = findFieldOfType(recv, name, type);
@@ -1498,14 +1552,13 @@
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
          * @since 9
-         * @hide
          */
         public VarHandle findStaticVarHandle(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             final Field field = findFieldOfType(decl, name, type);
             final boolean isStatic = true;
             final boolean performAccessChecks = true;
             commonFieldChecks(field, decl, type, isStatic, performAccessChecks);
-            return FieldVarHandle.create(field);
+            return StaticFieldVarHandle.create(field);
         }
         // END Android-changed: OpenJDK 9+181 VarHandle API factory method.
 
@@ -1822,13 +1875,12 @@
          * @throws IllegalAccessException if access checking fails
          * @throws NullPointerException if the argument is null
          * @since 9
-         * @hide
          */
         public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException {
             final boolean isStatic = Modifier.isStatic(f.getModifiers());
             final boolean performAccessChecks = true;
             commonFieldChecks(f, f.getDeclaringClass(), f.getType(), isStatic, performAccessChecks);
-            return FieldVarHandle.create(f);
+            return isStatic ? StaticFieldVarHandle.create(f) : FieldVarHandle.create(f);
         }
         // END Android-changed: OpenJDK 9+181 VarHandle API factory method.
 
@@ -1996,6 +2048,61 @@
         throw new IllegalArgumentException(target + " is not a direct handle");
     }
 
+    // Android-removed: unsupported @jvms tag in doc-comment.
+    /**
+     * Produces a method handle constructing arrays of a desired type,
+     * as if by the {@code anewarray} bytecode.
+     * The return type of the method handle will be the array type.
+     * The type of its sole argument will be {@code int}, which specifies the size of the array.
+     *
+     * <p> If the returned method handle is invoked with a negative
+     * array size, a {@code NegativeArraySizeException} will be thrown.
+     *
+     * @param arrayClass an array type
+     * @return a method handle which can create arrays of the given type
+     * @throws NullPointerException if the argument is {@code null}
+     * @throws IllegalArgumentException if {@code arrayClass} is not an array type
+     * @see java.lang.reflect.Array#newInstance(Class, int)
+     * @since 9
+     */
+    public static
+    MethodHandle arrayConstructor(Class<?> arrayClass) throws IllegalArgumentException {
+        if (!arrayClass.isArray()) {
+            throw newIllegalArgumentException("not an array class: " + arrayClass.getName());
+        }
+        // Android-changed: transformer based implementation.
+        // MethodHandle ani = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_Array_newInstance).
+        // bindTo(arrayClass.getComponentType());
+        // return ani.asType(ani.type().changeReturnType(arrayClass))
+        return new Transformers.ArrayConstructor(arrayClass);
+    }
+
+    // Android-removed: unsupported @jvms tag in doc-comment.
+    /**
+     * Produces a method handle returning the length of an array,
+     * as if by the {@code arraylength} bytecode.
+     * The type of the method handle will have {@code int} as return type,
+     * and its sole argument will be the array type.
+     *
+     * <p> If the returned method handle is invoked with a {@code null}
+     * array reference, a {@code NullPointerException} will be thrown.
+     *
+     * @param arrayClass an array type
+     * @return a method handle which can retrieve the length of an array of the given array type
+     * @throws NullPointerException if the argument is {@code null}
+     * @throws IllegalArgumentException if arrayClass is not an array type
+     * @since 9
+     */
+    public static
+    MethodHandle arrayLength(Class<?> arrayClass) throws IllegalArgumentException {
+        // Android-changed: transformer based implementation.
+        // return MethodHandleImpl.makeArrayElementAccessor(arrayClass, MethodHandleImpl.ArrayAccess.LENGTH);
+        if (!arrayClass.isArray()) {
+            throw newIllegalArgumentException("not an array class: " + arrayClass.getName());
+        }
+        return new Transformers.ArrayLength(arrayClass);
+    }
+
     // BEGIN Android-added: method to check if a class is an array.
     private static void checkClassIsArray(Class<?> c) {
         if (!c.isArray()) {
@@ -2148,7 +2255,6 @@
      * @throws NullPointerException if the arrayClass is null
      * @throws IllegalArgumentException if arrayClass is not an array type
      * @since 9
-     * @hide
      */
     public static
     VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException {
@@ -2231,7 +2337,6 @@
      * @throws UnsupportedOperationException if the component type of
      * viewArrayClass is not supported as a variable type
      * @since 9
-     * @hide
      */
     public static
     VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
@@ -2320,7 +2425,6 @@
      * @throws UnsupportedOperationException if the component type of
      * viewArrayClass is not supported as a variable type
      * @since 9
-     * @hide
      */
     public static
     VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass,
@@ -2500,7 +2604,6 @@
      * @return a method handle suitable for invoking an access mode method of
      *         any VarHandle whose access mode type is of the given type.
      * @since 9
-     * @hide
      */
     static public
     MethodHandle varHandleExactInvoker(VarHandle.AccessMode accessMode, MethodType type) {
@@ -2530,7 +2633,6 @@
      *         any VarHandle whose access mode type is convertible to the given
      *         type.
      * @since 9
-     * @hide
      */
     static public
     MethodHandle varHandleInvoker(VarHandle.AccessMode accessMode, MethodType type) {
@@ -2734,9 +2836,14 @@
                 throw newIllegalArgumentException("void type");
             Wrapper w = Wrapper.forPrimitiveType(type);
             value = w.convert(value, type);
+            if (w.zero().equals(value))
+                return zero(w, type);
+            return insertArguments(identity(type), 0, value);
+        } else {
+            if (value == null)
+                return zero(Wrapper.OBJECT, type);
+            return identity(type).bindTo(value);
         }
-
-        return new Transformers.Constant(type, value);
     }
 
     /**
@@ -2748,22 +2855,86 @@
      */
     public static
     MethodHandle identity(Class<?> type) {
-        if (type == null) {
-            throw new NullPointerException("type == null");
+        // Android-added: explicit non-null check.
+        Objects.requireNonNull(type);
+        Wrapper btw = (type.isPrimitive() ? Wrapper.forPrimitiveType(type) : Wrapper.OBJECT);
+        int pos = btw.ordinal();
+        MethodHandle ident = IDENTITY_MHS[pos];
+        if (ident == null) {
+            ident = setCachedMethodHandle(IDENTITY_MHS, pos, makeIdentity(btw.primitiveType()));
         }
+        if (ident.type().returnType() == type)
+            return ident;
+        // something like identity(Foo.class); do not bother to intern these
+        assert (btw == Wrapper.OBJECT);
+        return makeIdentity(type);
+    }
 
-        if (type.isPrimitive()) {
+    /**
+     * Produces a constant method handle of the requested return type which
+     * returns the default value for that type every time it is invoked.
+     * The resulting constant method handle will have no side effects.
+     * <p>The returned method handle is equivalent to {@code empty(methodType(type))}.
+     * It is also equivalent to {@code explicitCastArguments(constant(Object.class, null), methodType(type))},
+     * since {@code explicitCastArguments} converts {@code null} to default values.
+     * @param type the expected return type of the desired method handle
+     * @return a constant method handle that takes no arguments
+     *         and returns the default value of the given type (or void, if the type is void)
+     * @throws NullPointerException if the argument is null
+     * @see MethodHandles#constant
+     * @see MethodHandles#empty
+     * @see MethodHandles#explicitCastArguments
+     * @since 9
+     */
+    public static MethodHandle zero(Class<?> type) {
+        Objects.requireNonNull(type);
+        return type.isPrimitive() ?  zero(Wrapper.forPrimitiveType(type), type) : zero(Wrapper.OBJECT, type);
+    }
+
+    private static MethodHandle identityOrVoid(Class<?> type) {
+        return type == void.class ? zero(type) : identity(type);
+    }
+
+    /**
+     * Produces a method handle of the requested type which ignores any arguments, does nothing,
+     * and returns a suitable default depending on the return type.
+     * That is, it returns a zero primitive value, a {@code null}, or {@code void}.
+     * <p>The returned method handle is equivalent to
+     * {@code dropArguments(zero(type.returnType()), 0, type.parameterList())}.
+     *
+     * @apiNote Given a predicate and target, a useful "if-then" construct can be produced as
+     * {@code guardWithTest(pred, target, empty(target.type())}.
+     * @param type the type of the desired method handle
+     * @return a constant method handle of the given type, which returns a default value of the given return type
+     * @throws NullPointerException if the argument is null
+     * @see MethodHandles#zero
+     * @see MethodHandles#constant
+     * @since 9
+     */
+    public static  MethodHandle empty(MethodType type) {
+        Objects.requireNonNull(type);
+        return dropArguments(zero(type.returnType()), 0, type.parameterList());
+    }
+
+    private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.COUNT];
+    private static MethodHandle makeIdentity(Class<?> ptype) {
+        // Android-changed: Android implementation using identity() functions and transformers.
+        // MethodType mtype = methodType(ptype, ptype);
+        // LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
+        // return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
+        if (ptype.isPrimitive()) {
             try {
-                return Lookup.PUBLIC_LOOKUP.findStatic(MethodHandles.class, "identity",
-                        MethodType.methodType(type, type));
+                final MethodType mt = methodType(ptype, ptype);
+                return Lookup.PUBLIC_LOOKUP.findStatic(MethodHandles.class, "identity", mt);
             } catch (NoSuchMethodException | IllegalAccessException e) {
                 throw new AssertionError(e);
             }
+        } else {
+            return new Transformers.ReferenceIdentity(ptype);
         }
-
-        return new Transformers.ReferenceIdentity(type);
     }
 
+    // Android-added: helper methods for identity().
     /** @hide */ public static byte identity(byte val) { return val; }
     /** @hide */ public static boolean identity(boolean val) { return val; }
     /** @hide */ public static char identity(char val) { return val; }
@@ -2773,6 +2944,33 @@
     /** @hide */ public static float identity(float val) { return val; }
     /** @hide */ public static double identity(double val) { return val; }
 
+    private static MethodHandle zero(Wrapper btw, Class<?> rtype) {
+        int pos = btw.ordinal();
+        MethodHandle zero = ZERO_MHS[pos];
+        if (zero == null) {
+            zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
+        }
+        if (zero.type().returnType() == rtype)
+            return zero;
+        assert(btw == Wrapper.OBJECT);
+        return makeZero(rtype);
+    }
+    private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.COUNT];
+    private static MethodHandle makeZero(Class<?> rtype) {
+        // Android-changed: use Android specific implementation.
+        // MethodType mtype = methodType(rtype);
+        // LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
+        // return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
+        return new Transformers.ZeroValue(rtype);
+    }
+
+    private static synchronized MethodHandle setCachedMethodHandle(MethodHandle[] cache, int pos, MethodHandle value) {
+        // Simulate a CAS, to avoid racy duplication of results.
+        MethodHandle prev = cache[pos];
+        if (prev != null) return prev;
+        return cache[pos] = value;
+    }
+
     /**
      * Provides a target method handle with one or more <em>bound arguments</em>
      * in advance of the method handle's invocation.
@@ -2853,16 +3051,17 @@
         return oldType.ptypes();
     }
 
+    // Android-changed: inclusive language preference for 'placeholder'.
     /**
-     * Produces a method handle which will discard some dummy arguments
+     * Produces a method handle which will discard some placeholder arguments
      * before calling some other specified <i>target</i> method handle.
      * The type of the new method handle will be the same as the target's type,
-     * except it will also include the dummy argument types,
+     * except it will also include the placeholder argument types,
      * at some given position.
      * <p>
      * The {@code pos} argument may range between zero and <i>N</i>,
      * where <i>N</i> is the arity of the target.
-     * If {@code pos} is zero, the dummy arguments will precede
+     * If {@code pos} is zero, the placeholder arguments will precede
      * the target's real arguments; if {@code pos} is <i>N</i>
      * they will come after.
      * <p>
@@ -2897,21 +3096,29 @@
      */
     public static
     MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
-        valueTypes = copyTypes(valueTypes);
-        MethodType oldType = target.type();  // get NPE
-        int dropped = dropArgumentChecks(oldType, pos, valueTypes);
-
-        MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
-        if (dropped == 0) {
-            return target;
-        }
-
-        return new Transformers.DropArguments(newType, target, pos, valueTypes.size());
+        return dropArguments0(target, pos, copyTypes(valueTypes.toArray()));
     }
 
-    private static List<Class<?>> copyTypes(List<Class<?>> types) {
-        Object[] a = types.toArray();
-        return Arrays.asList(Arrays.copyOf(a, a.length, Class[].class));
+    private static List<Class<?>> copyTypes(Object[] array) {
+        return Arrays.asList(Arrays.copyOf(array, array.length, Class[].class));
+    }
+
+    private static
+    MethodHandle dropArguments0(MethodHandle target, int pos, List<Class<?>> valueTypes) {
+        MethodType oldType = target.type();  // get NPE
+        int dropped = dropArgumentChecks(oldType, pos, valueTypes);
+        MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
+        if (dropped == 0)  return target;
+        // Android-changed: transformer implementation.
+        // BoundMethodHandle result = target.rebind();
+        // LambdaForm lform = result.form;
+        // int insertFormArg = 1 + pos;
+        // for (Class<?> ptype : valueTypes) {
+        //     lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype));
+        // }
+        // result = result.copyWith(newType, lform);
+        // return result;
+        return new Transformers.DropArguments(newType, target, pos, dropped);
     }
 
     private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) {
@@ -2926,20 +3133,20 @@
         return dropped;
     }
 
+    // Android-changed: inclusive language preference for 'placeholder'.
     /**
-     * Produces a method handle which will discard some dummy arguments
+     * Produces a method handle which will discard some placeholder arguments
      * before calling some other specified <i>target</i> method handle.
      * The type of the new method handle will be the same as the target's type,
-     * except it will also include the dummy argument types,
+     * except it will also include the placeholder argument types,
      * at some given position.
      * <p>
      * The {@code pos} argument may range between zero and <i>N</i>,
      * where <i>N</i> is the arity of the target.
-     * If {@code pos} is zero, the dummy arguments will precede
+     * If {@code pos} is zero, the placeholder arguments will precede
      * the target's real arguments; if {@code pos} is <i>N</i>
      * they will come after.
-     * <p>
-     * <b>Example:</b>
+     * @apiNote
      * <blockquote><pre>{@code
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.*;
@@ -2975,7 +3182,117 @@
      */
     public static
     MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
-        return dropArguments(target, pos, Arrays.asList(valueTypes));
+        return dropArguments0(target, pos, copyTypes(valueTypes));
+    }
+
+    // private version which allows caller some freedom with error handling
+    private static MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos,
+                                      boolean nullOnFailure) {
+        newTypes = copyTypes(newTypes.toArray());
+        List<Class<?>> oldTypes = target.type().parameterList();
+        int match = oldTypes.size();
+        if (skip != 0) {
+            if (skip < 0 || skip > match) {
+                throw newIllegalArgumentException("illegal skip", skip, target);
+            }
+            oldTypes = oldTypes.subList(skip, match);
+            match -= skip;
+        }
+        List<Class<?>> addTypes = newTypes;
+        int add = addTypes.size();
+        if (pos != 0) {
+            if (pos < 0 || pos > add) {
+                throw newIllegalArgumentException("illegal pos", pos, newTypes);
+            }
+            addTypes = addTypes.subList(pos, add);
+            add -= pos;
+            assert(addTypes.size() == add);
+        }
+        // Do not add types which already match the existing arguments.
+        if (match > add || !oldTypes.equals(addTypes.subList(0, match))) {
+            if (nullOnFailure) {
+                return null;
+            }
+            throw newIllegalArgumentException("argument lists do not match", oldTypes, newTypes);
+        }
+        addTypes = addTypes.subList(match, add);
+        add -= match;
+        assert(addTypes.size() == add);
+        // newTypes:     (   P*[pos], M*[match], A*[add] )
+        // target: ( S*[skip],        M*[match]  )
+        MethodHandle adapter = target;
+        if (add > 0) {
+            adapter = dropArguments0(adapter, skip+ match, addTypes);
+        }
+        // adapter: (S*[skip],        M*[match], A*[add] )
+        if (pos > 0) {
+            adapter = dropArguments0(adapter, skip, newTypes.subList(0, pos));
+        }
+        // adapter: (S*[skip], P*[pos], M*[match], A*[add] )
+        return adapter;
+    }
+
+    // Android-changed: inclusive language preference for 'placeholder'.
+    /**
+     * Adapts a target method handle to match the given parameter type list. If necessary, adds placeholder arguments. Some
+     * leading parameters can be skipped before matching begins. The remaining types in the {@code target}'s parameter
+     * type list must be a sub-list of the {@code newTypes} type list at the starting position {@code pos}. The
+     * resulting handle will have the target handle's parameter type list, with any non-matching parameter types (before
+     * or after the matching sub-list) inserted in corresponding positions of the target's original parameters, as if by
+     * {@link #dropArguments(MethodHandle, int, Class[])}.
+     * <p>
+     * The resulting handle will have the same return type as the target handle.
+     * <p>
+     * In more formal terms, assume these two type lists:<ul>
+     * <li>The target handle has the parameter type list {@code S..., M...}, with as many types in {@code S} as
+     * indicated by {@code skip}. The {@code M} types are those that are supposed to match part of the given type list,
+     * {@code newTypes}.
+     * <li>The {@code newTypes} list contains types {@code P..., M..., A...}, with as many types in {@code P} as
+     * indicated by {@code pos}. The {@code M} types are precisely those that the {@code M} types in the target handle's
+     * parameter type list are supposed to match. The types in {@code A} are additional types found after the matching
+     * sub-list.
+     * </ul>
+     * Given these assumptions, the result of an invocation of {@code dropArgumentsToMatch} will have the parameter type
+     * list {@code S..., P..., M..., A...}, with the {@code P} and {@code A} types inserted as if by
+     * {@link #dropArguments(MethodHandle, int, Class[])}.
+     *
+     * @apiNote
+     * Two method handles whose argument lists are "effectively identical" (i.e., identical in a common prefix) may be
+     * mutually converted to a common type by two calls to {@code dropArgumentsToMatch}, as follows:
+     * <blockquote><pre>{@code
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+...
+MethodHandle h0 = constant(boolean.class, true);
+MethodHandle h1 = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class));
+MethodType bigType = h1.type().insertParameterTypes(1, String.class, int.class);
+MethodHandle h2 = dropArguments(h1, 0, bigType.parameterList());
+if (h1.type().parameterCount() < h2.type().parameterCount())
+    h1 = dropArgumentsToMatch(h1, 0, h2.type().parameterList(), 0);  // lengthen h1
+else
+    h2 = dropArgumentsToMatch(h2, 0, h1.type().parameterList(), 0);    // lengthen h2
+MethodHandle h3 = guardWithTest(h0, h1, h2);
+assertEquals("xy", h3.invoke("x", "y", 1, "a", "b", "c"));
+     * }</pre></blockquote>
+     * @param target the method handle to adapt
+     * @param skip number of targets parameters to disregard (they will be unchanged)
+     * @param newTypes the list of types to match {@code target}'s parameter type list to
+     * @param pos place in {@code newTypes} where the non-skipped target parameters must occur
+     * @return a possibly adapted method handle
+     * @throws NullPointerException if either argument is null
+     * @throws IllegalArgumentException if any element of {@code newTypes} is {@code void.class},
+     *         or if {@code skip} is negative or greater than the arity of the target,
+     *         or if {@code pos} is negative or greater than the newTypes list size,
+     *         or if {@code newTypes} does not contain the {@code target}'s non-skipped parameter types at position
+     *         {@code pos}.
+     * @since 9
+     */
+    public static
+    MethodHandle dropArgumentsToMatch(MethodHandle target, int skip, List<Class<?>> newTypes, int pos) {
+        Objects.requireNonNull(target);
+        Objects.requireNonNull(newTypes);
+        return dropArgumentsToMatch(target, skip, newTypes, pos, false);
     }
 
     /**
@@ -2988,6 +3305,7 @@
      * specified in the elements of the {@code filters} array.
      * The first element of the filter array corresponds to the {@code pos}
      * argument of the target, and so on in sequence.
+     * The filter functions are invoked in left to right order.
      * <p>
      * Null arguments in the array are treated as identity functions,
      * and the corresponding arguments left unchanged.
@@ -3022,14 +3340,25 @@
 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * denotes the return type of both the {@code target} and resulting adapter.
+     * {@code P}/{@code p} and {@code B}/{@code b} represent the types and values
+     * of the parameters and arguments that precede and follow the filter position
+     * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types and
+     * values of the filtered parameters and arguments; they also represent the
+     * return types of the {@code filter[i]} handles. The latter accept arguments
+     * {@code v[i]} of type {@code V[i]}, which also appear in the signature of
+     * the resulting adapter.
      * <blockquote><pre>{@code
-     * V target(P... p, A[i]... a[i], B... b);
+     * T target(P... p, A[i]... a[i], B... b);
      * A[i] filter[i](V[i]);
      * T adapter(P... p, V[i]... v[i], B... b) {
-     *   return target(p..., f[i](v[i])..., b...);
+     *   return target(p..., filter[i](v[i])..., b...);
      * }
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      *
      * @param target the method handle to invoke after arguments are filtered
      * @param pos the position of the first argument to filter
@@ -3046,14 +3375,37 @@
     public static
     MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
         filterArgumentsCheckArity(target, pos, filters);
-
+        MethodHandle adapter = target;
+        // Android-changed: transformer implementation.
+        // process filters in reverse order so that the invocation of
+        // the resulting adapter will invoke the filters in left-to-right order
+        // for (int i = filters.length - 1; i >= 0; --i) {
+        //     MethodHandle filter = filters[i];
+        //     if (filter == null)  continue;  // ignore null elements of filters
+        //     adapter = filterArgument(adapter, pos + i, filter);
+        // }
+        // return adapter;
         for (int i = 0; i < filters.length; ++i) {
             filterArgumentChecks(target, i + pos, filters[i]);
         }
-
         return new Transformers.FilterArguments(target, pos, filters);
     }
 
+    /*non-public*/ static
+    MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
+        filterArgumentChecks(target, pos, filter);
+        // Android-changed: use Transformer implementation.
+        // MethodType targetType = target.type();
+        // MethodType filterType = filter.type();
+        // BoundMethodHandle result = target.rebind();
+        // Class<?> newParamType = filterType.parameterType(0);
+        // LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType));
+        // MethodType newType = targetType.changeParameterType(pos, newParamType);
+        // result = result.copyWithExtendL(newType, lform, filter);
+        // return result;
+        return new Transformers.FilterArguments(target, pos, filter);
+    }
+
     private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) {
         MethodType targetType = target.type();
         int maxPos = targetType.parameterCount();
@@ -3222,29 +3574,36 @@
 MethodHandle f0 = filterReturnValue(cat, length);
 System.out.println((int) f0.invokeExact("x", "y")); // 2
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code,
+     * {@code T}/{@code t} represent the result type and value of the
+     * {@code target}; {@code V}, the result type of the {@code filter}; and
+     * {@code A}/{@code a}, the types and values of the parameters and arguments
+     * of the {@code target} as well as the resulting adapter.
      * <blockquote><pre>{@code
-     * V target(A...);
-     * T filter(V);
-     * T adapter(A... a) {
-     *   V v = target(a...);
-     *   return filter(v);
+     * T target(A...);
+     * V filter(T);
+     * V adapter(A... a) {
+     *   T t = target(a...);
+     *   return filter(t);
      * }
      * // and if the target has a void return:
      * void target2(A...);
-     * T filter2();
-     * T adapter2(A... a) {
+     * V filter2();
+     * V adapter2(A... a) {
      *   target2(a...);
      *   return filter2();
      * }
      * // and if the filter has a void return:
-     * V target3(A...);
+     * T target3(A...);
      * void filter3(V);
      * void adapter3(A... a) {
-     *   V v = target3(a...);
-     *   filter3(v);
+     *   T t = target3(a...);
+     *   filter3(t);
      * }
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param target the method handle to invoke before filtering the return value
      * @param filter method handle to call on the return value
      * @return method handle which incorporates the specified return value filtering logic
@@ -3257,7 +3616,13 @@
         MethodType targetType = target.type();
         MethodType filterType = filter.type();
         filterReturnValueChecks(targetType, filterType);
-
+        // Android-changed: use a transformer.
+        // BoundMethodHandle result = target.rebind();
+        // BasicType rtype = BasicType.basicType(filterType.returnType());
+        // LambdaForm lform = result.editor().filterReturnForm(rtype, false);
+        // MethodType newType = targetType.changeReturnType(filterType.returnType());
+        // result = result.copyWithExtendL(newType, lform, filter);
+        // return result;
         return new Transformers.FilterReturnValue(target, filter);
     }
 
@@ -3318,7 +3683,15 @@
 // also prints "boo":
 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the result type of the {@code target} and resulting adapter.
+     * {@code V}/{@code v} represent the type and value of the parameter and argument
+     * of {@code target} that precedes the folding position; {@code V} also is
+     * the result type of the {@code combiner}. {@code A}/{@code a} denote the
+     * types and values of the {@code N} parameters and arguments at the folding
+     * position. {@code B}/{@code b} represent the types and values of the
+     * {@code target} parameters and arguments that follow the folded parameters
+     * and arguments.
      * <blockquote><pre>{@code
      * // there are N arguments in A...
      * T target(V, A[N]..., B...);
@@ -3335,6 +3708,9 @@
      *   return target2(a..., b...);
      * }
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param target the method handle to invoke after arguments are combined
      * @param combiner method handle to call initially on the incoming arguments
      * @return method handle which incorporates the specified argument folding logic
@@ -3348,12 +3724,96 @@
      */
     public static
     MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
-        int foldPos = 0;
+        return foldArguments(target, 0, combiner);
+    }
+
+    /**
+     * Adapts a target method handle by pre-processing some of its arguments, starting at a given position, and then
+     * calling the target with the result of the pre-processing, inserted into the original sequence of arguments just
+     * before the folded arguments.
+     * <p>
+     * This method is closely related to {@link #foldArguments(MethodHandle, MethodHandle)}, but allows to control the
+     * position in the parameter list at which folding takes place. The argument controlling this, {@code pos}, is a
+     * zero-based index. The aforementioned method {@link #foldArguments(MethodHandle, MethodHandle)} assumes position
+     * 0.
+     *
+     * @apiNote Example:
+     * <blockquote><pre>{@code
+    import static java.lang.invoke.MethodHandles.*;
+    import static java.lang.invoke.MethodType.*;
+    ...
+    MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
+    "println", methodType(void.class, String.class))
+    .bindTo(System.out);
+    MethodHandle cat = lookup().findVirtual(String.class,
+    "concat", methodType(String.class, String.class));
+    assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+    MethodHandle catTrace = foldArguments(cat, 1, trace);
+    // also prints "jum":
+    assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+     * }</pre></blockquote>
+     * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the result type of the {@code target} and resulting adapter.
+     * {@code V}/{@code v} represent the type and value of the parameter and argument
+     * of {@code target} that precedes the folding position; {@code V} also is
+     * the result type of the {@code combiner}. {@code A}/{@code a} denote the
+     * types and values of the {@code N} parameters and arguments at the folding
+     * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types
+     * and values of the {@code target} parameters and arguments that precede and
+     * follow the folded parameters and arguments starting at {@code pos},
+     * respectively.
+     * <blockquote><pre>{@code
+     * // there are N arguments in A...
+     * T target(Z..., V, A[N]..., B...);
+     * V combiner(A...);
+     * T adapter(Z... z, A... a, B... b) {
+     *   V v = combiner(a...);
+     *   return target(z..., v, a..., b...);
+     * }
+     * // and if the combiner has a void return:
+     * T target2(Z..., A[N]..., B...);
+     * void combiner2(A...);
+     * T adapter2(Z... z, A... a, B... b) {
+     *   combiner2(a...);
+     *   return target2(z..., a..., b...);
+     * }
+     * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
+     *
+     * @param target the method handle to invoke after arguments are combined
+     * @param pos the position at which to start folding and at which to insert the folding result; if this is {@code
+     *            0}, the effect is the same as for {@link #foldArguments(MethodHandle, MethodHandle)}.
+     * @param combiner method handle to call initially on the incoming arguments
+     * @return method handle which incorporates the specified argument folding logic
+     * @throws NullPointerException if either argument is null
+     * @throws IllegalArgumentException if either of the following two conditions holds:
+     *          (1) {@code combiner}'s return type is non-{@code void} and not the same as the argument type at position
+     *              {@code pos} of the target signature;
+     *          (2) the {@code N} argument types at position {@code pos} of the target signature (skipping one matching
+     *              the {@code combiner}'s return type) are not identical with the argument types of {@code combiner}.
+     *
+     * @see #foldArguments(MethodHandle, MethodHandle)
+     * @since 9
+     */
+    public static
+    MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner) {
         MethodType targetType = target.type();
         MethodType combinerType = combiner.type();
-        Class<?> rtype = foldArgumentChecks(foldPos, targetType, combinerType);
+        Class<?> rtype = foldArgumentChecks(pos, targetType, combinerType);
+        // Android-changed: // Android-changed: transformer implementation.
+        // BoundMethodHandle result = target.rebind();
+        // boolean dropResult = rtype == void.class;
+        // LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType());
+        // MethodType newType = targetType;
+        // if (!dropResult) {
+        //     newType = newType.dropParameterTypes(pos, pos + 1);
+        // }
+        // result = result.copyWithExtendL(newType, lform, combiner);
+        // return result;
 
-        return new Transformers.FoldArguments(target, combiner);
+        return new Transformers.FoldArguments(target, pos, combiner);
     }
 
     private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
@@ -3362,11 +3822,15 @@
         int foldVals = rtype == void.class ? 0 : 1;
         int afterInsertPos = foldPos + foldVals;
         boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
-        if (ok && !(combinerType.parameterList()
-                    .equals(targetType.parameterList().subList(afterInsertPos,
-                                                               afterInsertPos + foldArgs))))
-            ok = false;
-        if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0))
+        if (ok) {
+            for (int i = 0; i < foldArgs; i++) {
+                if (combinerType.parameterType(i) != targetType.parameterType(i + afterInsertPos)) {
+                    ok = false;
+                    break;
+                }
+            }
+        }
+        if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
             ok = false;
         if (!ok)
             throw misMatchedTypes("target and combiner types", targetType, combinerType);
@@ -3429,7 +3893,7 @@
         return new Transformers.GuardWithTest(test, target, fallback);
     }
 
-    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
+    static <T> RuntimeException misMatchedTypes(String what, T t1, T t2) {
         return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
     }
 
@@ -3444,7 +3908,13 @@
      * argument and return types, except that handler may omit trailing arguments
      * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
      * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>
+     * Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the return type of the {@code target} and {@code handler},
+     * and correspondingly that of the resulting adapter; {@code A}/{@code a},
+     * the types and values of arguments to the resulting handle consumed by
+     * {@code handler}; and {@code B}/{@code b}, those of arguments to the
+     * resulting handle discarded by {@code handler}.
      * <blockquote><pre>{@code
      * T target(A..., B...);
      * T handler(ExType, A...);
@@ -3475,6 +3945,7 @@
      *          the given exception type, or if the method handle types do
      *          not match in their return types and their
      *          corresponding parameters
+     * @see MethodHandles#tryFinally(MethodHandle, MethodHandle)
      */
     public static
     MethodHandle catchException(MethodHandle target,
@@ -3482,20 +3953,19 @@
                                 MethodHandle handler) {
         MethodType ttype = target.type();
         MethodType htype = handler.type();
+        if (!Throwable.class.isAssignableFrom(exType))
+            throw new ClassCastException(exType.getName());
         if (htype.parameterCount() < 1 ||
             !htype.parameterType(0).isAssignableFrom(exType))
             throw newIllegalArgumentException("handler does not accept exception type "+exType);
         if (htype.returnType() != ttype.returnType())
             throw misMatchedTypes("target and handler return types", ttype, htype);
-        List<Class<?>> targs = ttype.parameterList();
-        List<Class<?>> hargs = htype.parameterList();
-        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
-        if (!targs.equals(hargs)) {
-            int hpc = hargs.size(), tpc = targs.size();
-            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
-                throw misMatchedTypes("target and handler types", ttype, htype);
+        handler = dropArgumentsToMatch(handler, 1, ttype.parameterList(), 0, true);
+        if (handler == null) {
+            throw misMatchedTypes("target and handler types", ttype, htype);
         }
-
+        // Android-changed: use Transformer implementation.
+        // return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
         return new Transformers.CatchException(target, handler, exType);
     }
 
@@ -3515,7 +3985,1643 @@
     MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
         if (!Throwable.class.isAssignableFrom(exType))
             throw new ClassCastException(exType.getName());
-
+        // Android-changed: use Transformer implementation.
+        // return MethodHandleImpl.throwException(methodType(returnType, exType));
         return new Transformers.AlwaysThrow(returnType, exType);
     }
+
+    /**
+     * Constructs a method handle representing a loop with several loop variables that are updated and checked upon each
+     * iteration. Upon termination of the loop due to one of the predicates, a corresponding finalizer is run and
+     * delivers the loop's result, which is the return value of the resulting handle.
+     * <p>
+     * Intuitively, every loop is formed by one or more "clauses", each specifying a local <em>iteration variable</em> and/or a loop
+     * exit. Each iteration of the loop executes each clause in order. A clause can optionally update its iteration
+     * variable; it can also optionally perform a test and conditional loop exit. In order to express this logic in
+     * terms of method handles, each clause will specify up to four independent actions:<ul>
+     * <li><em>init:</em> Before the loop executes, the initialization of an iteration variable {@code v} of type {@code V}.
+     * <li><em>step:</em> When a clause executes, an update step for the iteration variable {@code v}.
+     * <li><em>pred:</em> When a clause executes, a predicate execution to test for loop exit.
+     * <li><em>fini:</em> If a clause causes a loop exit, a finalizer execution to compute the loop's return value.
+     * </ul>
+     * The full sequence of all iteration variable types, in clause order, will be notated as {@code (V...)}.
+     * The values themselves will be {@code (v...)}.  When we speak of "parameter lists", we will usually
+     * be referring to types, but in some contexts (describing execution) the lists will be of actual values.
+     * <p>
+     * Some of these clause parts may be omitted according to certain rules, and useful default behavior is provided in
+     * this case. See below for a detailed description.
+     * <p>
+     * <em>Parameters optional everywhere:</em>
+     * Each clause function is allowed but not required to accept a parameter for each iteration variable {@code v}.
+     * As an exception, the init functions cannot take any {@code v} parameters,
+     * because those values are not yet computed when the init functions are executed.
+     * Any clause function may neglect to take any trailing subsequence of parameters it is entitled to take.
+     * In fact, any clause function may take no arguments at all.
+     * <p>
+     * <em>Loop parameters:</em>
+     * A clause function may take all the iteration variable values it is entitled to, in which case
+     * it may also take more trailing parameters. Such extra values are called <em>loop parameters</em>,
+     * with their types and values notated as {@code (A...)} and {@code (a...)}.
+     * These become the parameters of the resulting loop handle, to be supplied whenever the loop is executed.
+     * (Since init functions do not accept iteration variables {@code v}, any parameter to an
+     * init function is automatically a loop parameter {@code a}.)
+     * As with iteration variables, clause functions are allowed but not required to accept loop parameters.
+     * These loop parameters act as loop-invariant values visible across the whole loop.
+     * <p>
+     * <em>Parameters visible everywhere:</em>
+     * Each non-init clause function is permitted to observe the entire loop state, because it can be passed the full
+     * list {@code (v... a...)} of current iteration variable values and incoming loop parameters.
+     * The init functions can observe initial pre-loop state, in the form {@code (a...)}.
+     * Most clause functions will not need all of this information, but they will be formally connected to it
+     * as if by {@link #dropArguments}.
+     * <a id="astar"></a>
+     * More specifically, we shall use the notation {@code (V*)} to express an arbitrary prefix of a full
+     * sequence {@code (V...)} (and likewise for {@code (v*)}, {@code (A*)}, {@code (a*)}).
+     * In that notation, the general form of an init function parameter list
+     * is {@code (A*)}, and the general form of a non-init function parameter list is {@code (V*)} or {@code (V... A*)}.
+     * <p>
+     * <em>Checking clause structure:</em>
+     * Given a set of clauses, there is a number of checks and adjustments performed to connect all the parts of the
+     * loop. They are spelled out in detail in the steps below. In these steps, every occurrence of the word "must"
+     * corresponds to a place where {@link IllegalArgumentException} will be thrown if the required constraint is not
+     * met by the inputs to the loop combinator.
+     * <p>
+     * <em>Effectively identical sequences:</em>
+     * <a id="effid"></a>
+     * A parameter list {@code A} is defined to be <em>effectively identical</em> to another parameter list {@code B}
+     * if {@code A} and {@code B} are identical, or if {@code A} is shorter and is identical with a proper prefix of {@code B}.
+     * When speaking of an unordered set of parameter lists, we say they the set is "effectively identical"
+     * as a whole if the set contains a longest list, and all members of the set are effectively identical to
+     * that longest list.
+     * For example, any set of type sequences of the form {@code (V*)} is effectively identical,
+     * and the same is true if more sequences of the form {@code (V... A*)} are added.
+     * <p>
+     * <em>Step 0: Determine clause structure.</em><ol type="a">
+     * <li>The clause array (of type {@code MethodHandle[][]}) must be non-{@code null} and contain at least one element.
+     * <li>The clause array may not contain {@code null}s or sub-arrays longer than four elements.
+     * <li>Clauses shorter than four elements are treated as if they were padded by {@code null} elements to length
+     * four. Padding takes place by appending elements to the array.
+     * <li>Clauses with all {@code null}s are disregarded.
+     * <li>Each clause is treated as a four-tuple of functions, called "init", "step", "pred", and "fini".
+     * </ol>
+     * <p>
+     * <em>Step 1A: Determine iteration variable types {@code (V...)}.</em><ol type="a">
+     * <li>The iteration variable type for each clause is determined using the clause's init and step return types.
+     * <li>If both functions are omitted, there is no iteration variable for the corresponding clause ({@code void} is
+     * used as the type to indicate that). If one of them is omitted, the other's return type defines the clause's
+     * iteration variable type. If both are given, the common return type (they must be identical) defines the clause's
+     * iteration variable type.
+     * <li>Form the list of return types (in clause order), omitting all occurrences of {@code void}.
+     * <li>This list of types is called the "iteration variable types" ({@code (V...)}).
+     * </ol>
+     * <p>
+     * <em>Step 1B: Determine loop parameters {@code (A...)}.</em><ul>
+     * <li>Examine and collect init function parameter lists (which are of the form {@code (A*)}).
+     * <li>Examine and collect the suffixes of the step, pred, and fini parameter lists, after removing the iteration variable types.
+     * (They must have the form {@code (V... A*)}; collect the {@code (A*)} parts only.)
+     * <li>Do not collect suffixes from step, pred, and fini parameter lists that do not begin with all the iteration variable types.
+     * (These types will be checked in step 2, along with all the clause function types.)
+     * <li>Omitted clause functions are ignored.  (Equivalently, they are deemed to have empty parameter lists.)
+     * <li>All of the collected parameter lists must be effectively identical.
+     * <li>The longest parameter list (which is necessarily unique) is called the "external parameter list" ({@code (A...)}).
+     * <li>If there is no such parameter list, the external parameter list is taken to be the empty sequence.
+     * <li>The combined list consisting of iteration variable types followed by the external parameter types is called
+     * the "internal parameter list".
+     * </ul>
+     * <p>
+     * <em>Step 1C: Determine loop return type.</em><ol type="a">
+     * <li>Examine fini function return types, disregarding omitted fini functions.
+     * <li>If there are no fini functions, the loop return type is {@code void}.
+     * <li>Otherwise, the common return type {@code R} of the fini functions (their return types must be identical) defines the loop return
+     * type.
+     * </ol>
+     * <p>
+     * <em>Step 1D: Check other types.</em><ol type="a">
+     * <li>There must be at least one non-omitted pred function.
+     * <li>Every non-omitted pred function must have a {@code boolean} return type.
+     * </ol>
+     * <p>
+     * <em>Step 2: Determine parameter lists.</em><ol type="a">
+     * <li>The parameter list for the resulting loop handle will be the external parameter list {@code (A...)}.
+     * <li>The parameter list for init functions will be adjusted to the external parameter list.
+     * (Note that their parameter lists are already effectively identical to this list.)
+     * <li>The parameter list for every non-omitted, non-init (step, pred, and fini) function must be
+     * effectively identical to the internal parameter list {@code (V... A...)}.
+     * </ol>
+     * <p>
+     * <em>Step 3: Fill in omitted functions.</em><ol type="a">
+     * <li>If an init function is omitted, use a {@linkplain #empty default value} for the clause's iteration variable
+     * type.
+     * <li>If a step function is omitted, use an {@linkplain #identity identity function} of the clause's iteration
+     * variable type; insert dropped argument parameters before the identity function parameter for the non-{@code void}
+     * iteration variables of preceding clauses. (This will turn the loop variable into a local loop invariant.)
+     * <li>If a pred function is omitted, use a constant {@code true} function. (This will keep the loop going, as far
+     * as this clause is concerned.  Note that in such cases the corresponding fini function is unreachable.)
+     * <li>If a fini function is omitted, use a {@linkplain #empty default value} for the
+     * loop return type.
+     * </ol>
+     * <p>
+     * <em>Step 4: Fill in missing parameter types.</em><ol type="a">
+     * <li>At this point, every init function parameter list is effectively identical to the external parameter list {@code (A...)},
+     * but some lists may be shorter. For every init function with a short parameter list, pad out the end of the list.
+     * <li>At this point, every non-init function parameter list is effectively identical to the internal parameter
+     * list {@code (V... A...)}, but some lists may be shorter. For every non-init function with a short parameter list,
+     * pad out the end of the list.
+     * <li>Argument lists are padded out by {@linkplain #dropArgumentsToMatch(MethodHandle, int, List, int) dropping unused trailing arguments}.
+     * </ol>
+     * <p>
+     * <em>Final observations.</em><ol type="a">
+     * <li>After these steps, all clauses have been adjusted by supplying omitted functions and arguments.
+     * <li>All init functions have a common parameter type list {@code (A...)}, which the final loop handle will also have.
+     * <li>All fini functions have a common return type {@code R}, which the final loop handle will also have.
+     * <li>All non-init functions have a common parameter type list {@code (V... A...)}, of
+     * (non-{@code void}) iteration variables {@code V} followed by loop parameters.
+     * <li>Each pair of init and step functions agrees in their return type {@code V}.
+     * <li>Each non-init function will be able to observe the current values {@code (v...)} of all iteration variables.
+     * <li>Every function will be able to observe the incoming values {@code (a...)} of all loop parameters.
+     * </ol>
+     * <p>
+     * <em>Example.</em> As a consequence of step 1A above, the {@code loop} combinator has the following property:
+     * <ul>
+     * <li>Given {@code N} clauses {@code Cn = {null, Sn, Pn}} with {@code n = 1..N}.
+     * <li>Suppose predicate handles {@code Pn} are either {@code null} or have no parameters.
+     * (Only one {@code Pn} has to be non-{@code null}.)
+     * <li>Suppose step handles {@code Sn} have signatures {@code (B1..BX)Rn}, for some constant {@code X>=N}.
+     * <li>Suppose {@code Q} is the count of non-void types {@code Rn}, and {@code (V1...VQ)} is the sequence of those types.
+     * <li>It must be that {@code Vn == Bn} for {@code n = 1..min(X,Q)}.
+     * <li>The parameter types {@code Vn} will be interpreted as loop-local state elements {@code (V...)}.
+     * <li>Any remaining types {@code BQ+1..BX} (if {@code Q<X}) will determine
+     * the resulting loop handle's parameter types {@code (A...)}.
+     * </ul>
+     * In this example, the loop handle parameters {@code (A...)} were derived from the step functions,
+     * which is natural if most of the loop computation happens in the steps.  For some loops,
+     * the burden of computation might be heaviest in the pred functions, and so the pred functions
+     * might need to accept the loop parameter values.  For loops with complex exit logic, the fini
+     * functions might need to accept loop parameters, and likewise for loops with complex entry logic,
+     * where the init functions will need the extra parameters.  For such reasons, the rules for
+     * determining these parameters are as symmetric as possible, across all clause parts.
+     * In general, the loop parameters function as common invariant values across the whole
+     * loop, while the iteration variables function as common variant values, or (if there is
+     * no step function) as internal loop invariant temporaries.
+     * <p>
+     * <em>Loop execution.</em><ol type="a">
+     * <li>When the loop is called, the loop input values are saved in locals, to be passed to
+     * every clause function. These locals are loop invariant.
+     * <li>Each init function is executed in clause order (passing the external arguments {@code (a...)})
+     * and the non-{@code void} values are saved (as the iteration variables {@code (v...)}) into locals.
+     * These locals will be loop varying (unless their steps behave as identity functions, as noted above).
+     * <li>All function executions (except init functions) will be passed the internal parameter list, consisting of
+     * the non-{@code void} iteration values {@code (v...)} (in clause order) and then the loop inputs {@code (a...)}
+     * (in argument order).
+     * <li>The step and pred functions are then executed, in clause order (step before pred), until a pred function
+     * returns {@code false}.
+     * <li>The non-{@code void} result from a step function call is used to update the corresponding value in the
+     * sequence {@code (v...)} of loop variables.
+     * The updated value is immediately visible to all subsequent function calls.
+     * <li>If a pred function returns {@code false}, the corresponding fini function is called, and the resulting value
+     * (of type {@code R}) is returned from the loop as a whole.
+     * <li>If all the pred functions always return true, no fini function is ever invoked, and the loop cannot exit
+     * except by throwing an exception.
+     * </ol>
+     * <p>
+     * <em>Usage tips.</em>
+     * <ul>
+     * <li>Although each step function will receive the current values of <em>all</em> the loop variables,
+     * sometimes a step function only needs to observe the current value of its own variable.
+     * In that case, the step function may need to explicitly {@linkplain #dropArguments drop all preceding loop variables}.
+     * This will require mentioning their types, in an expression like {@code dropArguments(step, 0, V0.class, ...)}.
+     * <li>Loop variables are not required to vary; they can be loop invariant.  A clause can create
+     * a loop invariant by a suitable init function with no step, pred, or fini function.  This may be
+     * useful to "wire" an incoming loop argument into the step or pred function of an adjacent loop variable.
+     * <li>If some of the clause functions are virtual methods on an instance, the instance
+     * itself can be conveniently placed in an initial invariant loop "variable", using an initial clause
+     * like {@code new MethodHandle[]{identity(ObjType.class)}}.  In that case, the instance reference
+     * will be the first iteration variable value, and it will be easy to use virtual
+     * methods as clause parts, since all of them will take a leading instance reference matching that value.
+     * </ul>
+     * <p>
+     * Here is pseudocode for the resulting loop handle. As above, {@code V} and {@code v} represent the types
+     * and values of loop variables; {@code A} and {@code a} represent arguments passed to the whole loop;
+     * and {@code R} is the common result type of all finalizers as well as of the resulting loop.
+     * <blockquote><pre>{@code
+     * V... init...(A...);
+     * boolean pred...(V..., A...);
+     * V... step...(V..., A...);
+     * R fini...(V..., A...);
+     * R loop(A... a) {
+     *   V... v... = init...(a...);
+     *   for (;;) {
+     *     for ((v, p, s, f) in (v..., pred..., step..., fini...)) {
+     *       v = s(v..., a...);
+     *       if (!p(v..., a...)) {
+     *         return f(v..., a...);
+     *       }
+     *     }
+     *   }
+     * }
+     * }</pre></blockquote>
+     * Note that the parameter type lists {@code (V...)} and {@code (A...)} have been expanded
+     * to their full length, even though individual clause functions may neglect to take them all.
+     * As noted above, missing parameters are filled in as if by {@link #dropArgumentsToMatch(MethodHandle, int, List, int)}.
+     *
+     * @apiNote Example:
+     * <blockquote><pre>{@code
+     * // iterative implementation of the factorial function as a loop handle
+     * static int one(int k) { return 1; }
+     * static int inc(int i, int acc, int k) { return i + 1; }
+     * static int mult(int i, int acc, int k) { return i * acc; }
+     * static boolean pred(int i, int acc, int k) { return i < k; }
+     * static int fin(int i, int acc, int k) { return acc; }
+     * // assume MH_one, MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods
+     * // null initializer for counter, should initialize to 0
+     * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+     * MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+     * MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+     * assertEquals(120, loop.invoke(5));
+     * }</pre></blockquote>
+     * The same example, dropping arguments and using combinators:
+     * <blockquote><pre>{@code
+     * // simplified implementation of the factorial function as a loop handle
+     * static int inc(int i) { return i + 1; } // drop acc, k
+     * static int mult(int i, int acc) { return i * acc; } //drop k
+     * static boolean cmp(int i, int k) { return i < k; }
+     * // assume MH_inc, MH_mult, and MH_cmp are handles to the above methods
+     * // null initializer for counter, should initialize to 0
+     * MethodHandle MH_one = MethodHandles.constant(int.class, 1);
+     * MethodHandle MH_pred = MethodHandles.dropArguments(MH_cmp, 1, int.class); // drop acc
+     * MethodHandle MH_fin = MethodHandles.dropArguments(MethodHandles.identity(int.class), 0, int.class); // drop i
+     * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+     * MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+     * MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+     * assertEquals(720, loop.invoke(6));
+     * }</pre></blockquote>
+     * A similar example, using a helper object to hold a loop parameter:
+     * <blockquote><pre>{@code
+     * // instance-based implementation of the factorial function as a loop handle
+     * static class FacLoop {
+     *   final int k;
+     *   FacLoop(int k) { this.k = k; }
+     *   int inc(int i) { return i + 1; }
+     *   int mult(int i, int acc) { return i * acc; }
+     *   boolean pred(int i) { return i < k; }
+     *   int fin(int i, int acc) { return acc; }
+     * }
+     * // assume MH_FacLoop is a handle to the constructor
+     * // assume MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods
+     * // null initializer for counter, should initialize to 0
+     * MethodHandle MH_one = MethodHandles.constant(int.class, 1);
+     * MethodHandle[] instanceClause = new MethodHandle[]{MH_FacLoop};
+     * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+     * MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+     * MethodHandle loop = MethodHandles.loop(instanceClause, counterClause, accumulatorClause);
+     * assertEquals(5040, loop.invoke(7));
+     * }</pre></blockquote>
+     *
+     * @param clauses an array of arrays (4-tuples) of {@link MethodHandle}s adhering to the rules described above.
+     *
+     * @return a method handle embodying the looping behavior as defined by the arguments.
+     *
+     * @throws IllegalArgumentException in case any of the constraints described above is violated.
+     *
+     * @see MethodHandles#whileLoop(MethodHandle, MethodHandle, MethodHandle)
+     * @see MethodHandles#doWhileLoop(MethodHandle, MethodHandle, MethodHandle)
+     * @see MethodHandles#countedLoop(MethodHandle, MethodHandle, MethodHandle)
+     * @see MethodHandles#iteratedLoop(MethodHandle, MethodHandle, MethodHandle)
+     * @since 9
+     */
+    public static MethodHandle loop(MethodHandle[]... clauses) {
+        // Step 0: determine clause structure.
+        loopChecks0(clauses);
+
+        List<MethodHandle> init = new ArrayList<>();
+        List<MethodHandle> step = new ArrayList<>();
+        List<MethodHandle> pred = new ArrayList<>();
+        List<MethodHandle> fini = new ArrayList<>();
+
+        Stream.of(clauses).filter(c -> Stream.of(c).anyMatch(Objects::nonNull)).forEach(clause -> {
+            init.add(clause[0]); // all clauses have at least length 1
+            step.add(clause.length <= 1 ? null : clause[1]);
+            pred.add(clause.length <= 2 ? null : clause[2]);
+            fini.add(clause.length <= 3 ? null : clause[3]);
+        });
+
+        assert Stream.of(init, step, pred, fini).map(List::size).distinct().count() == 1;
+        final int nclauses = init.size();
+
+        // Step 1A: determine iteration variables (V...).
+        final List<Class<?>> iterationVariableTypes = new ArrayList<>();
+        for (int i = 0; i < nclauses; ++i) {
+            MethodHandle in = init.get(i);
+            MethodHandle st = step.get(i);
+            if (in == null && st == null) {
+                iterationVariableTypes.add(void.class);
+            } else if (in != null && st != null) {
+                loopChecks1a(i, in, st);
+                iterationVariableTypes.add(in.type().returnType());
+            } else {
+                iterationVariableTypes.add(in == null ? st.type().returnType() : in.type().returnType());
+            }
+        }
+        final List<Class<?>> commonPrefix = iterationVariableTypes.stream().filter(t -> t != void.class).
+                collect(Collectors.toList());
+
+        // Step 1B: determine loop parameters (A...).
+        final List<Class<?>> commonSuffix = buildCommonSuffix(init, step, pred, fini, commonPrefix.size());
+        loopChecks1b(init, commonSuffix);
+
+        // Step 1C: determine loop return type.
+        // Step 1D: check other types.
+        // local variable required here; see JDK-8223553
+        Stream<Class<?>> cstream = fini.stream().filter(Objects::nonNull).map(MethodHandle::type)
+                .map(MethodType::returnType);
+        final Class<?> loopReturnType = cstream.findFirst().orElse(void.class);
+        loopChecks1cd(pred, fini, loopReturnType);
+
+        // Step 2: determine parameter lists.
+        final List<Class<?>> commonParameterSequence = new ArrayList<>(commonPrefix);
+        commonParameterSequence.addAll(commonSuffix);
+        loopChecks2(step, pred, fini, commonParameterSequence);
+
+        // Step 3: fill in omitted functions.
+        for (int i = 0; i < nclauses; ++i) {
+            Class<?> t = iterationVariableTypes.get(i);
+            if (init.get(i) == null) {
+                init.set(i, empty(methodType(t, commonSuffix)));
+            }
+            if (step.get(i) == null) {
+                step.set(i, dropArgumentsToMatch(identityOrVoid(t), 0, commonParameterSequence, i));
+            }
+            if (pred.get(i) == null) {
+                pred.set(i, dropArguments0(constant(boolean.class, true), 0, commonParameterSequence));
+            }
+            if (fini.get(i) == null) {
+                fini.set(i, empty(methodType(t, commonParameterSequence)));
+            }
+        }
+
+        // Step 4: fill in missing parameter types.
+        // Also convert all handles to fixed-arity handles.
+        List<MethodHandle> finit = fixArities(fillParameterTypes(init, commonSuffix));
+        List<MethodHandle> fstep = fixArities(fillParameterTypes(step, commonParameterSequence));
+        List<MethodHandle> fpred = fixArities(fillParameterTypes(pred, commonParameterSequence));
+        List<MethodHandle> ffini = fixArities(fillParameterTypes(fini, commonParameterSequence));
+
+        assert finit.stream().map(MethodHandle::type).map(MethodType::parameterList).
+                allMatch(pl -> pl.equals(commonSuffix));
+        assert Stream.of(fstep, fpred, ffini).flatMap(List::stream).map(MethodHandle::type).map(MethodType::parameterList).
+                allMatch(pl -> pl.equals(commonParameterSequence));
+
+        // Android-changed: transformer implementation.
+        // return MethodHandleImpl.makeLoop(loopReturnType, commonSuffix, finit, fstep, fpred, ffini);
+        return new Transformers.Loop(loopReturnType,
+                                     commonSuffix,
+                                     finit.toArray(MethodHandle[]::new),
+                                     fstep.toArray(MethodHandle[]::new),
+                                     fpred.toArray(MethodHandle[]::new),
+                                     ffini.toArray(MethodHandle[]::new));
+    }
+
+    private static void loopChecks0(MethodHandle[][] clauses) {
+        if (clauses == null || clauses.length == 0) {
+            throw newIllegalArgumentException("null or no clauses passed");
+        }
+        if (Stream.of(clauses).anyMatch(Objects::isNull)) {
+            throw newIllegalArgumentException("null clauses are not allowed");
+        }
+        if (Stream.of(clauses).anyMatch(c -> c.length > 4)) {
+            throw newIllegalArgumentException("All loop clauses must be represented as MethodHandle arrays with at most 4 elements.");
+        }
+    }
+
+    private static void loopChecks1a(int i, MethodHandle in, MethodHandle st) {
+        if (in.type().returnType() != st.type().returnType()) {
+            throw misMatchedTypes("clause " + i + ": init and step return types", in.type().returnType(),
+                    st.type().returnType());
+        }
+    }
+
+    private static List<Class<?>> longestParameterList(Stream<MethodHandle> mhs, int skipSize) {
+        final List<Class<?>> empty = List.of();
+        final List<Class<?>> longest = mhs.filter(Objects::nonNull).
+                // take only those that can contribute to a common suffix because they are longer than the prefix
+                        map(MethodHandle::type).
+                        filter(t -> t.parameterCount() > skipSize).
+                        map(MethodType::parameterList).
+                        reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+        return longest.size() == 0 ? empty : longest.subList(skipSize, longest.size());
+    }
+
+    private static List<Class<?>> longestParameterList(List<List<Class<?>>> lists) {
+        final List<Class<?>> empty = List.of();
+        return lists.stream().reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
+    }
+
+    private static List<Class<?>> buildCommonSuffix(List<MethodHandle> init, List<MethodHandle> step, List<MethodHandle> pred, List<MethodHandle> fini, int cpSize) {
+        final List<Class<?>> longest1 = longestParameterList(Stream.of(step, pred, fini).flatMap(List::stream), cpSize);
+        final List<Class<?>> longest2 = longestParameterList(init.stream(), 0);
+        return longestParameterList(Arrays.asList(longest1, longest2));
+    }
+
+    private static void loopChecks1b(List<MethodHandle> init, List<Class<?>> commonSuffix) {
+        if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).
+                anyMatch(t -> !t.effectivelyIdenticalParameters(0, commonSuffix))) {
+            throw newIllegalArgumentException("found non-effectively identical init parameter type lists: " + init +
+                    " (common suffix: " + commonSuffix + ")");
+        }
+    }
+
+    private static void loopChecks1cd(List<MethodHandle> pred, List<MethodHandle> fini, Class<?> loopReturnType) {
+        if (fini.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::returnType).
+                anyMatch(t -> t != loopReturnType)) {
+            throw newIllegalArgumentException("found non-identical finalizer return types: " + fini + " (return type: " +
+                    loopReturnType + ")");
+        }
+
+        if (!pred.stream().filter(Objects::nonNull).findFirst().isPresent()) {
+            throw newIllegalArgumentException("no predicate found", pred);
+        }
+        if (pred.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::returnType).
+                anyMatch(t -> t != boolean.class)) {
+            throw newIllegalArgumentException("predicates must have boolean return type", pred);
+        }
+    }
+
+    private static void loopChecks2(List<MethodHandle> step, List<MethodHandle> pred, List<MethodHandle> fini, List<Class<?>> commonParameterSequence) {
+        if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type).
+                anyMatch(t -> !t.effectivelyIdenticalParameters(0, commonParameterSequence))) {
+            throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step +
+                    "\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")");
+        }
+    }
+
+    private static List<MethodHandle> fillParameterTypes(List<MethodHandle> hs, final List<Class<?>> targetParams) {
+        return hs.stream().map(h -> {
+            int pc = h.type().parameterCount();
+            int tpsize = targetParams.size();
+            return pc < tpsize ? dropArguments0(h, pc, targetParams.subList(pc, tpsize)) : h;
+        }).collect(Collectors.toList());
+    }
+
+    private static List<MethodHandle> fixArities(List<MethodHandle> hs) {
+        return hs.stream().map(MethodHandle::asFixedArity).collect(Collectors.toList());
+    }
+
+    /**
+     * Constructs a {@code while} loop from an initializer, a body, and a predicate.
+     * This is a convenience wrapper for the {@linkplain #loop(MethodHandle[][]) generic loop combinator}.
+     * <p>
+     * The {@code pred} handle describes the loop condition; and {@code body}, its body. The loop resulting from this
+     * method will, in each iteration, first evaluate the predicate and then execute its body (if the predicate
+     * evaluates to {@code true}).
+     * The loop will terminate once the predicate evaluates to {@code false} (the body will not be executed in this case).
+     * <p>
+     * The {@code init} handle describes the initial value of an additional optional loop-local variable.
+     * In each iteration, this loop-local variable, if present, will be passed to the {@code body}
+     * and updated with the value returned from its invocation. The result of loop execution will be
+     * the final value of the additional loop-local variable (if present).
+     * <p>
+     * The following rules hold for these argument handles:<ul>
+     * <li>The {@code body} handle must not be {@code null}; its type must be of the form
+     * {@code (V A...)V}, where {@code V} is non-{@code void}, or else {@code (A...)void}.
+     * (In the {@code void} case, we assign the type {@code void} to the name {@code V},
+     * and we will write {@code (V A...)V} with the understanding that a {@code void} type {@code V}
+     * is quietly dropped from the parameter list, leaving {@code (A...)V}.)
+     * <li>The parameter list {@code (V A...)} of the body is called the <em>internal parameter list</em>.
+     * It will constrain the parameter lists of the other loop parts.
+     * <li>If the iteration variable type {@code V} is dropped from the internal parameter list, the resulting shorter
+     * list {@code (A...)} is called the <em>external parameter list</em>.
+     * <li>The body return type {@code V}, if non-{@code void}, determines the type of an
+     * additional state variable of the loop.
+     * The body must both accept and return a value of this type {@code V}.
+     * <li>If {@code init} is non-{@code null}, it must have return type {@code V}.
+     * Its parameter list (of some <a href="MethodHandles.html#astar">form {@code (A*)}</a>) must be
+     * <a href="MethodHandles.html#effid">effectively identical</a>
+     * to the external parameter list {@code (A...)}.
+     * <li>If {@code init} is {@code null}, the loop variable will be initialized to its
+     * {@linkplain #empty default value}.
+     * <li>The {@code pred} handle must not be {@code null}.  It must have {@code boolean} as its return type.
+     * Its parameter list (either empty or of the form {@code (V A*)}) must be
+     * effectively identical to the internal parameter list.
+     * </ul>
+     * <p>
+     * The resulting loop handle's result type and parameter signature are determined as follows:<ul>
+     * <li>The loop handle's result type is the result type {@code V} of the body.
+     * <li>The loop handle's parameter types are the types {@code (A...)},
+     * from the external parameter list.
+     * </ul>
+     * <p>
+     * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
+     * the sole loop variable as well as the result type of the loop; and {@code A}/{@code a}, that of the argument
+     * passed to the loop.
+     * <blockquote><pre>{@code
+     * V init(A...);
+     * boolean pred(V, A...);
+     * V body(V, A...);
+     * V whileLoop(A... a...) {
+     *   V v = init(a...);
+     *   while (pred(v, a...)) {
+     *     v = body(v, a...);
+     *   }
+     *   return v;
+     * }
+     * }</pre></blockquote>
+     *
+     * @apiNote Example:
+     * <blockquote><pre>{@code
+     * // implement the zip function for lists as a loop handle
+     * static List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); }
+     * static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); }
+     * static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+     *   zip.add(a.next());
+     *   zip.add(b.next());
+     *   return zip;
+     * }
+     * // assume MH_initZip, MH_zipPred, and MH_zipStep are handles to the above methods
+     * MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep);
+     * List<String> a = Arrays.asList("a", "b", "c", "d");
+     * List<String> b = Arrays.asList("e", "f", "g", "h");
+     * List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
+     * assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
+     * }</pre></blockquote>
+     *
+     *
+     * @apiNote The implementation of this method can be expressed as follows:
+     * <blockquote><pre>{@code
+     * MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) {
+     *     MethodHandle fini = (body.type().returnType() == void.class
+     *                         ? null : identity(body.type().returnType()));
+     *     MethodHandle[]
+     *         checkExit = { null, null, pred, fini },
+     *         varBody   = { init, body };
+     *     return loop(checkExit, varBody);
+     * }
+     * }</pre></blockquote>
+     *
+     * @param init optional initializer, providing the initial value of the loop variable.
+     *             May be {@code null}, implying a default initial value.  See above for other constraints.
+     * @param pred condition for the loop, which may not be {@code null}. Its result type must be {@code boolean}. See
+     *             above for other constraints.
+     * @param body body of the loop, which may not be {@code null}. It controls the loop parameters and result type.
+     *             See above for other constraints.
+     *
+     * @return a method handle implementing the {@code while} loop as described by the arguments.
+     * @throws IllegalArgumentException if the rules for the arguments are violated.
+     * @throws NullPointerException if {@code pred} or {@code body} are {@code null}.
+     *
+     * @see #loop(MethodHandle[][])
+     * @see #doWhileLoop(MethodHandle, MethodHandle, MethodHandle)
+     * @since 9
+     */
+    public static MethodHandle whileLoop(MethodHandle init, MethodHandle pred, MethodHandle body) {
+        whileLoopChecks(init, pred, body);
+        MethodHandle fini = identityOrVoid(body.type().returnType());
+        MethodHandle[] checkExit = { null, null, pred, fini };
+        MethodHandle[] varBody = { init, body };
+        return loop(checkExit, varBody);
+    }
+
+    /**
+     * Constructs a {@code do-while} loop from an initializer, a body, and a predicate.
+     * This is a convenience wrapper for the {@linkplain #loop(MethodHandle[][]) generic loop combinator}.
+     * <p>
+     * The {@code pred} handle describes the loop condition; and {@code body}, its body. The loop resulting from this
+     * method will, in each iteration, first execute its body and then evaluate the predicate.
+     * The loop will terminate once the predicate evaluates to {@code false} after an execution of the body.
+     * <p>
+     * The {@code init} handle describes the initial value of an additional optional loop-local variable.
+     * In each iteration, this loop-local variable, if present, will be passed to the {@code body}
+     * and updated with the value returned from its invocation. The result of loop execution will be
+     * the final value of the additional loop-local variable (if present).
+     * <p>
+     * The following rules hold for these argument handles:<ul>
+     * <li>The {@code body} handle must not be {@code null}; its type must be of the form
+     * {@code (V A...)V}, where {@code V} is non-{@code void}, or else {@code (A...)void}.
+     * (In the {@code void} case, we assign the type {@code void} to the name {@code V},
+     * and we will write {@code (V A...)V} with the understanding that a {@code void} type {@code V}
+     * is quietly dropped from the parameter list, leaving {@code (A...)V}.)
+     * <li>The parameter list {@code (V A...)} of the body is called the <em>internal parameter list</em>.
+     * It will constrain the parameter lists of the other loop parts.
+     * <li>If the iteration variable type {@code V} is dropped from the internal parameter list, the resulting shorter
+     * list {@code (A...)} is called the <em>external parameter list</em>.
+     * <li>The body return type {@code V}, if non-{@code void}, determines the type of an
+     * additional state variable of the loop.
+     * The body must both accept and return a value of this type {@code V}.
+     * <li>If {@code init} is non-{@code null}, it must have return type {@code V}.
+     * Its parameter list (of some <a href="MethodHandles.html#astar">form {@code (A*)}</a>) must be
+     * <a href="MethodHandles.html#effid">effectively identical</a>
+     * to the external parameter list {@code (A...)}.
+     * <li>If {@code init} is {@code null}, the loop variable will be initialized to its
+     * {@linkplain #empty default value}.
+     * <li>The {@code pred} handle must not be {@code null}.  It must have {@code boolean} as its return type.
+     * Its parameter list (either empty or of the form {@code (V A*)}) must be
+     * effectively identical to the internal parameter list.
+     * </ul>
+     * <p>
+     * The resulting loop handle's result type and parameter signature are determined as follows:<ul>
+     * <li>The loop handle's result type is the result type {@code V} of the body.
+     * <li>The loop handle's parameter types are the types {@code (A...)},
+     * from the external parameter list.
+     * </ul>
+     * <p>
+     * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
+     * the sole loop variable as well as the result type of the loop; and {@code A}/{@code a}, that of the argument
+     * passed to the loop.
+     * <blockquote><pre>{@code
+     * V init(A...);
+     * boolean pred(V, A...);
+     * V body(V, A...);
+     * V doWhileLoop(A... a...) {
+     *   V v = init(a...);
+     *   do {
+     *     v = body(v, a...);
+     *   } while (pred(v, a...));
+     *   return v;
+     * }
+     * }</pre></blockquote>
+     *
+     * @apiNote Example:
+     * <blockquote><pre>{@code
+     * // int i = 0; while (i < limit) { ++i; } return i; => limit
+     * static int zero(int limit) { return 0; }
+     * static int step(int i, int limit) { return i + 1; }
+     * static boolean pred(int i, int limit) { return i < limit; }
+     * // assume MH_zero, MH_step, and MH_pred are handles to the above methods
+     * MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
+     * assertEquals(23, loop.invoke(23));
+     * }</pre></blockquote>
+     *
+     *
+     * @apiNote The implementation of this method can be expressed as follows:
+     * <blockquote><pre>{@code
+     * MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) {
+     *     MethodHandle fini = (body.type().returnType() == void.class
+     *                         ? null : identity(body.type().returnType()));
+     *     MethodHandle[] clause = { init, body, pred, fini };
+     *     return loop(clause);
+     * }
+     * }</pre></blockquote>
+     *
+     * @param init optional initializer, providing the initial value of the loop variable.
+     *             May be {@code null}, implying a default initial value.  See above for other constraints.
+     * @param body body of the loop, which may not be {@code null}. It controls the loop parameters and result type.
+     *             See above for other constraints.
+     * @param pred condition for the loop, which may not be {@code null}. Its result type must be {@code boolean}. See
+     *             above for other constraints.
+     *
+     * @return a method handle implementing the {@code while} loop as described by the arguments.
+     * @throws IllegalArgumentException if the rules for the arguments are violated.
+     * @throws NullPointerException if {@code pred} or {@code body} are {@code null}.
+     *
+     * @see #loop(MethodHandle[][])
+     * @see #whileLoop(MethodHandle, MethodHandle, MethodHandle)
+     * @since 9
+     */
+    public static MethodHandle doWhileLoop(MethodHandle init, MethodHandle body, MethodHandle pred) {
+        whileLoopChecks(init, pred, body);
+        MethodHandle fini = identityOrVoid(body.type().returnType());
+        MethodHandle[] clause = {init, body, pred, fini };
+        return loop(clause);
+    }
+
+    private static void whileLoopChecks(MethodHandle init, MethodHandle pred, MethodHandle body) {
+        Objects.requireNonNull(pred);
+        Objects.requireNonNull(body);
+        MethodType bodyType = body.type();
+        Class<?> returnType = bodyType.returnType();
+        List<Class<?>> innerList = bodyType.parameterList();
+        List<Class<?>> outerList = innerList;
+        if (returnType == void.class) {
+            // OK
+        } else if (innerList.size() == 0 || innerList.get(0) != returnType) {
+            // leading V argument missing => error
+            MethodType expected = bodyType.insertParameterTypes(0, returnType);
+            throw misMatchedTypes("body function", bodyType, expected);
+        } else {
+            outerList = innerList.subList(1, innerList.size());
+        }
+        MethodType predType = pred.type();
+        if (predType.returnType() != boolean.class ||
+                !predType.effectivelyIdenticalParameters(0, innerList)) {
+            throw misMatchedTypes("loop predicate", predType, methodType(boolean.class, innerList));
+        }
+        if (init != null) {
+            MethodType initType = init.type();
+            if (initType.returnType() != returnType ||
+                    !initType.effectivelyIdenticalParameters(0, outerList)) {
+                throw misMatchedTypes("loop initializer", initType, methodType(returnType, outerList));
+            }
+        }
+    }
+
+    /**
+     * Constructs a loop that runs a given number of iterations.
+     * This is a convenience wrapper for the {@linkplain #loop(MethodHandle[][]) generic loop combinator}.
+     * <p>
+     * The number of iterations is determined by the {@code iterations} handle evaluation result.
+     * The loop counter {@code i} is an extra loop iteration variable of type {@code int}.
+     * It will be initialized to 0 and incremented by 1 in each iteration.
+     * <p>
+     * If the {@code body} handle returns a non-{@code void} type {@code V}, a leading loop iteration variable
+     * of that type is also present.  This variable is initialized using the optional {@code init} handle,
+     * or to the {@linkplain #empty default value} of type {@code V} if that handle is {@code null}.
+     * <p>
+     * In each iteration, the iteration variables are passed to an invocation of the {@code body} handle.
+     * A non-{@code void} value returned from the body (of type {@code V}) updates the leading
+     * iteration variable.
+     * The result of the loop handle execution will be the final {@code V} value of that variable
+     * (or {@code void} if there is no {@code V} variable).
+     * <p>
+     * The following rules hold for the argument handles:<ul>
+     * <li>The {@code iterations} handle must not be {@code null}, and must return
+     * the type {@code int}, referred to here as {@code I} in parameter type lists.
+     * <li>The {@code body} handle must not be {@code null}; its type must be of the form
+     * {@code (V I A...)V}, where {@code V} is non-{@code void}, or else {@code (I A...)void}.
+     * (In the {@code void} case, we assign the type {@code void} to the name {@code V},
+     * and we will write {@code (V I A...)V} with the understanding that a {@code void} type {@code V}
+     * is quietly dropped from the parameter list, leaving {@code (I A...)V}.)
+     * <li>The parameter list {@code (V I A...)} of the body contributes to a list
+     * of types called the <em>internal parameter list</em>.
+     * It will constrain the parameter lists of the other loop parts.
+     * <li>As a special case, if the body contributes only {@code V} and {@code I} types,
+     * with no additional {@code A} types, then the internal parameter list is extended by
+     * the argument types {@code A...} of the {@code iterations} handle.
+     * <li>If the iteration variable types {@code (V I)} are dropped from the internal parameter list, the resulting shorter
+     * list {@code (A...)} is called the <em>external parameter list</em>.
+     * <li>The body return type {@code V}, if non-{@code void}, determines the type of an
+     * additional state variable of the loop.
+     * The body must both accept a leading parameter and return a value of this type {@code V}.
+     * <li>If {@code init} is non-{@code null}, it must have return type {@code V}.
+     * Its parameter list (of some <a href="MethodHandles.html#astar">form {@code (A*)}</a>) must be
+     * <a href="MethodHandles.html#effid">effectively identical</a>
+     * to the external parameter list {@code (A...)}.
+     * <li>If {@code init} is {@code null}, the loop variable will be initialized to its
+     * {@linkplain #empty default value}.
+     * <li>The parameter list of {@code iterations} (of some form {@code (A*)}) must be
+     * effectively identical to the external parameter list {@code (A...)}.
+     * </ul>
+     * <p>
+     * The resulting loop handle's result type and parameter signature are determined as follows:<ul>
+     * <li>The loop handle's result type is the result type {@code V} of the body.
+     * <li>The loop handle's parameter types are the types {@code (A...)},
+     * from the external parameter list.
+     * </ul>
+     * <p>
+     * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
+     * the second loop variable as well as the result type of the loop; and {@code A...}/{@code a...} represent
+     * arguments passed to the loop.
+     * <blockquote><pre>{@code
+     * int iterations(A...);
+     * V init(A...);
+     * V body(V, int, A...);
+     * V countedLoop(A... a...) {
+     *   int end = iterations(a...);
+     *   V v = init(a...);
+     *   for (int i = 0; i < end; ++i) {
+     *     v = body(v, i, a...);
+     *   }
+     *   return v;
+     * }
+     * }</pre></blockquote>
+     *
+     * @apiNote Example with a fully conformant body method:
+     * <blockquote><pre>{@code
+     * // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
+     * // => a variation on a well known theme
+     * static String step(String v, int counter, String init) { return "na " + v; }
+     * // assume MH_step is a handle to the method above
+     * MethodHandle fit13 = MethodHandles.constant(int.class, 13);
+     * MethodHandle start = MethodHandles.identity(String.class);
+     * MethodHandle loop = MethodHandles.countedLoop(fit13, start, MH_step);
+     * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+     * }</pre></blockquote>
+     *
+     * @apiNote Example with the simplest possible body method type,
+     * and passing the number of iterations to the loop invocation:
+     * <blockquote><pre>{@code
+     * // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
+     * // => a variation on a well known theme
+     * static String step(String v, int counter ) { return "na " + v; }
+     * // assume MH_step is a handle to the method above
+     * MethodHandle count = MethodHandles.dropArguments(MethodHandles.identity(int.class), 1, String.class);
+     * MethodHandle start = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, int.class);
+     * MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step);  // (v, i) -> "na " + v
+     * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "Lambdaman!"));
+     * }</pre></blockquote>
+     *
+     * @apiNote Example that treats the number of iterations, string to append to, and string to append
+     * as loop parameters:
+     * <blockquote><pre>{@code
+     * // String s = "Lambdaman!", t = "na"; for (int i = 0; i < 13; ++i) { s = t + " " + s; } return s;
+     * // => a variation on a well known theme
+     * static String step(String v, int counter, int iterations_, String pre, String start_) { return pre + " " + v; }
+     * // assume MH_step is a handle to the method above
+     * MethodHandle count = MethodHandles.identity(int.class);
+     * MethodHandle start = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, int.class, String.class);
+     * MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step);  // (v, i, _, pre, _) -> pre + " " + v
+     * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "na", "Lambdaman!"));
+     * }</pre></blockquote>
+     *
+     * @apiNote Example that illustrates the usage of {@link #dropArgumentsToMatch(MethodHandle, int, List, int)}
+     * to enforce a loop type:
+     * <blockquote><pre>{@code
+     * // String s = "Lambdaman!", t = "na"; for (int i = 0; i < 13; ++i) { s = t + " " + s; } return s;
+     * // => a variation on a well known theme
+     * static String step(String v, int counter, String pre) { return pre + " " + v; }
+     * // assume MH_step is a handle to the method above
+     * MethodType loopType = methodType(String.class, String.class, int.class, String.class);
+     * MethodHandle count = MethodHandles.dropArgumentsToMatch(MethodHandles.identity(int.class),    0, loopType.parameterList(), 1);
+     * MethodHandle start = MethodHandles.dropArgumentsToMatch(MethodHandles.identity(String.class), 0, loopType.parameterList(), 2);
+     * MethodHandle body  = MethodHandles.dropArgumentsToMatch(MH_step,                              2, loopType.parameterList(), 0);
+     * MethodHandle loop = MethodHandles.countedLoop(count, start, body);  // (v, i, pre, _, _) -> pre + " " + v
+     * assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("na", 13, "Lambdaman!"));
+     * }</pre></blockquote>
+     *
+     * @apiNote The implementation of this method can be expressed as follows:
+     * <blockquote><pre>{@code
+     * MethodHandle countedLoop(MethodHandle iterations, MethodHandle init, MethodHandle body) {
+     *     return countedLoop(empty(iterations.type()), iterations, init, body);
+     * }
+     * }</pre></blockquote>
+     *
+     * @param iterations a non-{@code null} handle to return the number of iterations this loop should run. The handle's
+     *                   result type must be {@code int}. See above for other constraints.
+     * @param init optional initializer, providing the initial value of the loop variable.
+     *             May be {@code null}, implying a default initial value.  See above for other constraints.
+     * @param body body of the loop, which may not be {@code null}.
+     *             It controls the loop parameters and result type in the standard case (see above for details).
+     *             It must accept its own return type (if non-void) plus an {@code int} parameter (for the counter),
+     *             and may accept any number of additional types.
+     *             See above for other constraints.
+     *
+     * @return a method handle representing the loop.
+     * @throws NullPointerException if either of the {@code iterations} or {@code body} handles is {@code null}.
+     * @throws IllegalArgumentException if any argument violates the rules formulated above.
+     *
+     * @see #countedLoop(MethodHandle, MethodHandle, MethodHandle, MethodHandle)
+     * @since 9
+     */
+    public static MethodHandle countedLoop(MethodHandle iterations, MethodHandle init, MethodHandle body) {
+        return countedLoop(empty(iterations.type()), iterations, init, body);
+    }
+
+    /**
+     * Constructs a loop that counts over a range of numbers.
+     * This is a convenience wrapper for the {@linkplain #loop(MethodHandle[][]) generic loop combinator}.
+     * <p>
+     * The loop counter {@code i} is a loop iteration variable of type {@code int}.
+     * The {@code start} and {@code end} handles determine the start (inclusive) and end (exclusive)
+     * values of the loop counter.
+     * The loop counter will be initialized to the {@code int} value returned from the evaluation of the
+     * {@code start} handle and run to the value returned from {@code end} (exclusively) with a step width of 1.
+     * <p>
+     * If the {@code body} handle returns a non-{@code void} type {@code V}, a leading loop iteration variable
+     * of that type is also present.  This variable is initialized using the optional {@code init} handle,
+     * or to the {@linkplain #empty default value} of type {@code V} if that handle is {@code null}.
+     * <p>
+     * In each iteration, the iteration variables are passed to an invocation of the {@code body} handle.
+     * A non-{@code void} value returned from the body (of type {@code V}) updates the leading
+     * iteration variable.
+     * The result of the loop handle execution will be the final {@code V} value of that variable
+     * (or {@code void} if there is no {@code V} variable).
+     * <p>
+     * The following rules hold for the argument handles:<ul>
+     * <li>The {@code start} and {@code end} handles must not be {@code null}, and must both return
+     * the common type {@code int}, referred to here as {@code I} in parameter type lists.
+     * <li>The {@code body} handle must not be {@code null}; its type must be of the form
+     * {@code (V I A...)V}, where {@code V} is non-{@code void}, or else {@code (I A...)void}.
+     * (In the {@code void} case, we assign the type {@code void} to the name {@code V},
+     * and we will write {@code (V I A...)V} with the understanding that a {@code void} type {@code V}
+     * is quietly dropped from the parameter list, leaving {@code (I A...)V}.)
+     * <li>The parameter list {@code (V I A...)} of the body contributes to a list
+     * of types called the <em>internal parameter list</em>.
+     * It will constrain the parameter lists of the other loop parts.
+     * <li>As a special case, if the body contributes only {@code V} and {@code I} types,
+     * with no additional {@code A} types, then the internal parameter list is extended by
+     * the argument types {@code A...} of the {@code end} handle.
+     * <li>If the iteration variable types {@code (V I)} are dropped from the internal parameter list, the resulting shorter
+     * list {@code (A...)} is called the <em>external parameter list</em>.
+     * <li>The body return type {@code V}, if non-{@code void}, determines the type of an
+     * additional state variable of the loop.
+     * The body must both accept a leading parameter and return a value of this type {@code V}.
+     * <li>If {@code init} is non-{@code null}, it must have return type {@code V}.
+     * Its parameter list (of some <a href="MethodHandles.html#astar">form {@code (A*)}</a>) must be
+     * <a href="MethodHandles.html#effid">effectively identical</a>
+     * to the external parameter list {@code (A...)}.
+     * <li>If {@code init} is {@code null}, the loop variable will be initialized to its
+     * {@linkplain #empty default value}.
+     * <li>The parameter list of {@code start} (of some form {@code (A*)}) must be
+     * effectively identical to the external parameter list {@code (A...)}.
+     * <li>Likewise, the parameter list of {@code end} must be effectively identical
+     * to the external parameter list.
+     * </ul>
+     * <p>
+     * The resulting loop handle's result type and parameter signature are determined as follows:<ul>
+     * <li>The loop handle's result type is the result type {@code V} of the body.
+     * <li>The loop handle's parameter types are the types {@code (A...)},
+     * from the external parameter list.
+     * </ul>
+     * <p>
+     * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
+     * the second loop variable as well as the result type of the loop; and {@code A...}/{@code a...} represent
+     * arguments passed to the loop.
+     * <blockquote><pre>{@code
+     * int start(A...);
+     * int end(A...);
+     * V init(A...);
+     * V body(V, int, A...);
+     * V countedLoop(A... a...) {
+     *   int e = end(a...);
+     *   int s = start(a...);
+     *   V v = init(a...);
+     *   for (int i = s; i < e; ++i) {
+     *     v = body(v, i, a...);
+     *   }
+     *   return v;
+     * }
+     * }</pre></blockquote>
+     *
+     * @apiNote The implementation of this method can be expressed as follows:
+     * <blockquote><pre>{@code
+     * MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
+     *     MethodHandle returnVar = dropArguments(identity(init.type().returnType()), 0, int.class, int.class);
+     *     // assume MH_increment and MH_predicate are handles to implementation-internal methods with
+     *     // the following semantics:
+     *     // MH_increment: (int limit, int counter) -> counter + 1
+     *     // MH_predicate: (int limit, int counter) -> counter < limit
+     *     Class<?> counterType = start.type().returnType();  // int
+     *     Class<?> returnType = body.type().returnType();
+     *     MethodHandle incr = MH_increment, pred = MH_predicate, retv = null;
+     *     if (returnType != void.class) {  // ignore the V variable
+     *         incr = dropArguments(incr, 1, returnType);  // (limit, v, i) => (limit, i)
+     *         pred = dropArguments(pred, 1, returnType);  // ditto
+     *         retv = dropArguments(identity(returnType), 0, counterType); // ignore limit
+     *     }
+     *     body = dropArguments(body, 0, counterType);  // ignore the limit variable
+     *     MethodHandle[]
+     *         loopLimit  = { end, null, pred, retv }, // limit = end(); i < limit || return v
+     *         bodyClause = { init, body },            // v = init(); v = body(v, i)
+     *         indexVar   = { start, incr };           // i = start(); i = i + 1
+     *     return loop(loopLimit, bodyClause, indexVar);
+     * }
+     * }</pre></blockquote>
+     *
+     * @param start a non-{@code null} handle to return the start value of the loop counter, which must be {@code int}.
+     *              See above for other constraints.
+     * @param end a non-{@code null} handle to return the end value of the loop counter (the loop will run to
+     *            {@code end-1}). The result type must be {@code int}. See above for other constraints.
+     * @param init optional initializer, providing the initial value of the loop variable.
+     *             May be {@code null}, implying a default initial value.  See above for other constraints.
+     * @param body body of the loop, which may not be {@code null}.
+     *             It controls the loop parameters and result type in the standard case (see above for details).
+     *             It must accept its own return type (if non-void) plus an {@code int} parameter (for the counter),
+     *             and may accept any number of additional types.
+     *             See above for other constraints.
+     *
+     * @return a method handle representing the loop.
+     * @throws NullPointerException if any of the {@code start}, {@code end}, or {@code body} handles is {@code null}.
+     * @throws IllegalArgumentException if any argument violates the rules formulated above.
+     *
+     * @see #countedLoop(MethodHandle, MethodHandle, MethodHandle)
+     * @since 9
+     */
+    public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
+        countedLoopChecks(start, end, init, body);
+        Class<?> counterType = start.type().returnType();  // int, but who's counting?
+        Class<?> limitType   = end.type().returnType();    // yes, int again
+        Class<?> returnType  = body.type().returnType();
+        // Android-changed: getConstantHandle is in MethodHandles.
+        // MethodHandle incr = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep);
+        // MethodHandle pred = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred);
+        MethodHandle incr = getConstantHandle(MH_countedLoopStep);
+        MethodHandle pred = getConstantHandle(MH_countedLoopPred);
+        MethodHandle retv = null;
+        if (returnType != void.class) {
+            incr = dropArguments(incr, 1, returnType);  // (limit, v, i) => (limit, i)
+            pred = dropArguments(pred, 1, returnType);  // ditto
+            retv = dropArguments(identity(returnType), 0, counterType);
+        }
+        body = dropArguments(body, 0, counterType);  // ignore the limit variable
+        MethodHandle[]
+            loopLimit  = { end, null, pred, retv }, // limit = end(); i < limit || return v
+            bodyClause = { init, body },            // v = init(); v = body(v, i)
+            indexVar   = { start, incr };           // i = start(); i = i + 1
+        return loop(loopLimit, bodyClause, indexVar);
+    }
+
+    private static void countedLoopChecks(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
+        Objects.requireNonNull(start);
+        Objects.requireNonNull(end);
+        Objects.requireNonNull(body);
+        Class<?> counterType = start.type().returnType();
+        if (counterType != int.class) {
+            MethodType expected = start.type().changeReturnType(int.class);
+            throw misMatchedTypes("start function", start.type(), expected);
+        } else if (end.type().returnType() != counterType) {
+            MethodType expected = end.type().changeReturnType(counterType);
+            throw misMatchedTypes("end function", end.type(), expected);
+        }
+        MethodType bodyType = body.type();
+        Class<?> returnType = bodyType.returnType();
+        List<Class<?>> innerList = bodyType.parameterList();
+        // strip leading V value if present
+        int vsize = (returnType == void.class ? 0 : 1);
+        if (vsize != 0 && (innerList.size() == 0 || innerList.get(0) != returnType)) {
+            // argument list has no "V" => error
+            MethodType expected = bodyType.insertParameterTypes(0, returnType);
+            throw misMatchedTypes("body function", bodyType, expected);
+        } else if (innerList.size() <= vsize || innerList.get(vsize) != counterType) {
+            // missing I type => error
+            MethodType expected = bodyType.insertParameterTypes(vsize, counterType);
+            throw misMatchedTypes("body function", bodyType, expected);
+        }
+        List<Class<?>> outerList = innerList.subList(vsize + 1, innerList.size());
+        if (outerList.isEmpty()) {
+            // special case; take lists from end handle
+            outerList = end.type().parameterList();
+            innerList = bodyType.insertParameterTypes(vsize + 1, outerList).parameterList();
+        }
+        MethodType expected = methodType(counterType, outerList);
+        if (!start.type().effectivelyIdenticalParameters(0, outerList)) {
+            throw misMatchedTypes("start parameter types", start.type(), expected);
+        }
+        if (end.type() != start.type() &&
+            !end.type().effectivelyIdenticalParameters(0, outerList)) {
+            throw misMatchedTypes("end parameter types", end.type(), expected);
+        }
+        if (init != null) {
+            MethodType initType = init.type();
+            if (initType.returnType() != returnType ||
+                !initType.effectivelyIdenticalParameters(0, outerList)) {
+                throw misMatchedTypes("loop initializer", initType, methodType(returnType, outerList));
+            }
+        }
+    }
+
+    /**
+     * Constructs a loop that ranges over the values produced by an {@code Iterator<T>}.
+     * This is a convenience wrapper for the {@linkplain #loop(MethodHandle[][]) generic loop combinator}.
+     * <p>
+     * The iterator itself will be determined by the evaluation of the {@code iterator} handle.
+     * Each value it produces will be stored in a loop iteration variable of type {@code T}.
+     * <p>
+     * If the {@code body} handle returns a non-{@code void} type {@code V}, a leading loop iteration variable
+     * of that type is also present.  This variable is initialized using the optional {@code init} handle,
+     * or to the {@linkplain #empty default value} of type {@code V} if that handle is {@code null}.
+     * <p>
+     * In each iteration, the iteration variables are passed to an invocation of the {@code body} handle.
+     * A non-{@code void} value returned from the body (of type {@code V}) updates the leading
+     * iteration variable.
+     * The result of the loop handle execution will be the final {@code V} value of that variable
+     * (or {@code void} if there is no {@code V} variable).
+     * <p>
+     * The following rules hold for the argument handles:<ul>
+     * <li>The {@code body} handle must not be {@code null}; its type must be of the form
+     * {@code (V T A...)V}, where {@code V} is non-{@code void}, or else {@code (T A...)void}.
+     * (In the {@code void} case, we assign the type {@code void} to the name {@code V},
+     * and we will write {@code (V T A...)V} with the understanding that a {@code void} type {@code V}
+     * is quietly dropped from the parameter list, leaving {@code (T A...)V}.)
+     * <li>The parameter list {@code (V T A...)} of the body contributes to a list
+     * of types called the <em>internal parameter list</em>.
+     * It will constrain the parameter lists of the other loop parts.
+     * <li>As a special case, if the body contributes only {@code V} and {@code T} types,
+     * with no additional {@code A} types, then the internal parameter list is extended by
+     * the argument types {@code A...} of the {@code iterator} handle; if it is {@code null} the
+     * single type {@code Iterable} is added and constitutes the {@code A...} list.
+     * <li>If the iteration variable types {@code (V T)} are dropped from the internal parameter list, the resulting shorter
+     * list {@code (A...)} is called the <em>external parameter list</em>.
+     * <li>The body return type {@code V}, if non-{@code void}, determines the type of an
+     * additional state variable of the loop.
+     * The body must both accept a leading parameter and return a value of this type {@code V}.
+     * <li>If {@code init} is non-{@code null}, it must have return type {@code V}.
+     * Its parameter list (of some <a href="MethodHandles.html#astar">form {@code (A*)}</a>) must be
+     * <a href="MethodHandles.html#effid">effectively identical</a>
+     * to the external parameter list {@code (A...)}.
+     * <li>If {@code init} is {@code null}, the loop variable will be initialized to its
+     * {@linkplain #empty default value}.
+     * <li>If the {@code iterator} handle is non-{@code null}, it must have the return
+     * type {@code java.util.Iterator} or a subtype thereof.
+     * The iterator it produces when the loop is executed will be assumed
+     * to yield values which can be converted to type {@code T}.
+     * <li>The parameter list of an {@code iterator} that is non-{@code null} (of some form {@code (A*)}) must be
+     * effectively identical to the external parameter list {@code (A...)}.
+     * <li>If {@code iterator} is {@code null} it defaults to a method handle which behaves
+     * like {@link java.lang.Iterable#iterator()}.  In that case, the internal parameter list
+     * {@code (V T A...)} must have at least one {@code A} type, and the default iterator
+     * handle parameter is adjusted to accept the leading {@code A} type, as if by
+     * the {@link MethodHandle#asType asType} conversion method.
+     * The leading {@code A} type must be {@code Iterable} or a subtype thereof.
+     * This conversion step, done at loop construction time, must not throw a {@code WrongMethodTypeException}.
+     * </ul>
+     * <p>
+     * The type {@code T} may be either a primitive or reference.
+     * Since type {@code Iterator<T>} is erased in the method handle representation to the raw type {@code Iterator},
+     * the {@code iteratedLoop} combinator adjusts the leading argument type for {@code body} to {@code Object}
+     * as if by the {@link MethodHandle#asType asType} conversion method.
+     * Therefore, if an iterator of the wrong type appears as the loop is executed, runtime exceptions may occur
+     * as the result of dynamic conversions performed by {@link MethodHandle#asType(MethodType)}.
+     * <p>
+     * The resulting loop handle's result type and parameter signature are determined as follows:<ul>
+     * <li>The loop handle's result type is the result type {@code V} of the body.
+     * <li>The loop handle's parameter types are the types {@code (A...)},
+     * from the external parameter list.
+     * </ul>
+     * <p>
+     * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
+     * the loop variable as well as the result type of the loop; {@code T}/{@code t}, that of the elements of the
+     * structure the loop iterates over, and {@code A...}/{@code a...} represent arguments passed to the loop.
+     * <blockquote><pre>{@code
+     * Iterator<T> iterator(A...);  // defaults to Iterable::iterator
+     * V init(A...);
+     * V body(V,T,A...);
+     * V iteratedLoop(A... a...) {
+     *   Iterator<T> it = iterator(a...);
+     *   V v = init(a...);
+     *   while (it.hasNext()) {
+     *     T t = it.next();
+     *     v = body(v, t, a...);
+     *   }
+     *   return v;
+     * }
+     * }</pre></blockquote>
+     *
+     * @apiNote Example:
+     * <blockquote><pre>{@code
+     * // get an iterator from a list
+     * static List<String> reverseStep(List<String> r, String e) {
+     *   r.add(0, e);
+     *   return r;
+     * }
+     * static List<String> newArrayList() { return new ArrayList<>(); }
+     * // assume MH_reverseStep and MH_newArrayList are handles to the above methods
+     * MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
+     * List<String> list = Arrays.asList("a", "b", "c", "d", "e");
+     * List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
+     * assertEquals(reversedList, (List<String>) loop.invoke(list));
+     * }</pre></blockquote>
+     *
+     * @apiNote The implementation of this method can be expressed approximately as follows:
+     * <blockquote><pre>{@code
+     * MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
+     *     // assume MH_next, MH_hasNext, MH_startIter are handles to methods of Iterator/Iterable
+     *     Class<?> returnType = body.type().returnType();
+     *     Class<?> ttype = body.type().parameterType(returnType == void.class ? 0 : 1);
+     *     MethodHandle nextVal = MH_next.asType(MH_next.type().changeReturnType(ttype));
+     *     MethodHandle retv = null, step = body, startIter = iterator;
+     *     if (returnType != void.class) {
+     *         // the simple thing first:  in (I V A...), drop the I to get V
+     *         retv = dropArguments(identity(returnType), 0, Iterator.class);
+     *         // body type signature (V T A...), internal loop types (I V A...)
+     *         step = swapArguments(body, 0, 1);  // swap V <-> T
+     *     }
+     *     if (startIter == null)  startIter = MH_getIter;
+     *     MethodHandle[]
+     *         iterVar    = { startIter, null, MH_hasNext, retv }, // it = iterator; while (it.hasNext())
+     *         bodyClause = { init, filterArguments(step, 0, nextVal) };  // v = body(v, t, a)
+     *     return loop(iterVar, bodyClause);
+     * }
+     * }</pre></blockquote>
+     *
+     * @param iterator an optional handle to return the iterator to start the loop.
+     *                 If non-{@code null}, the handle must return {@link java.util.Iterator} or a subtype.
+     *                 See above for other constraints.
+     * @param init optional initializer, providing the initial value of the loop variable.
+     *             May be {@code null}, implying a default initial value.  See above for other constraints.
+     * @param body body of the loop, which may not be {@code null}.
+     *             It controls the loop parameters and result type in the standard case (see above for details).
+     *             It must accept its own return type (if non-void) plus a {@code T} parameter (for the iterated values),
+     *             and may accept any number of additional types.
+     *             See above for other constraints.
+     *
+     * @return a method handle embodying the iteration loop functionality.
+     * @throws NullPointerException if the {@code body} handle is {@code null}.
+     * @throws IllegalArgumentException if any argument violates the above requirements.
+     *
+     * @since 9
+     */
+    public static MethodHandle iteratedLoop(MethodHandle iterator, MethodHandle init, MethodHandle body) {
+        Class<?> iterableType = iteratedLoopChecks(iterator, init, body);
+        Class<?> returnType = body.type().returnType();
+        // Android-changed: getConstantHandle is in MethodHandles.
+        // MethodHandle hasNext = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iteratePred);
+        // MethodHandle nextRaw = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_iterateNext);
+        MethodHandle hasNext = getConstantHandle(MH_iteratePred);
+        MethodHandle nextRaw = getConstantHandle(MH_iterateNext);
+        MethodHandle startIter;
+        MethodHandle nextVal;
+        {
+            MethodType iteratorType;
+            if (iterator == null) {
+                // derive argument type from body, if available, else use Iterable
+                // Android-changed: getConstantHandle is in MethodHandles.
+                // startIter = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_initIterator);
+                startIter = getConstantHandle(MH_initIterator);
+                iteratorType = startIter.type().changeParameterType(0, iterableType);
+            } else {
+                // force return type to the internal iterator class
+                iteratorType = iterator.type().changeReturnType(Iterator.class);
+                startIter = iterator;
+            }
+            Class<?> ttype = body.type().parameterType(returnType == void.class ? 0 : 1);
+            MethodType nextValType = nextRaw.type().changeReturnType(ttype);
+
+            // perform the asType transforms under an exception transformer, as per spec.:
+            try {
+                startIter = startIter.asType(iteratorType);
+                nextVal = nextRaw.asType(nextValType);
+            } catch (WrongMethodTypeException ex) {
+                throw new IllegalArgumentException(ex);
+            }
+        }
+
+        MethodHandle retv = null, step = body;
+        if (returnType != void.class) {
+            // the simple thing first:  in (I V A...), drop the I to get V
+            retv = dropArguments(identity(returnType), 0, Iterator.class);
+            // body type signature (V T A...), internal loop types (I V A...)
+            step = swapArguments(body, 0, 1);  // swap V <-> T
+        }
+
+        MethodHandle[]
+            iterVar    = { startIter, null, hasNext, retv },
+            bodyClause = { init, filterArgument(step, 0, nextVal) };
+        return loop(iterVar, bodyClause);
+    }
+
+    private static Class<?> iteratedLoopChecks(MethodHandle iterator, MethodHandle init, MethodHandle body) {
+        Objects.requireNonNull(body);
+        MethodType bodyType = body.type();
+        Class<?> returnType = bodyType.returnType();
+        List<Class<?>> internalParamList = bodyType.parameterList();
+        // strip leading V value if present
+        int vsize = (returnType == void.class ? 0 : 1);
+        if (vsize != 0 && (internalParamList.size() == 0 || internalParamList.get(0) != returnType)) {
+            // argument list has no "V" => error
+            MethodType expected = bodyType.insertParameterTypes(0, returnType);
+            throw misMatchedTypes("body function", bodyType, expected);
+        } else if (internalParamList.size() <= vsize) {
+            // missing T type => error
+            MethodType expected = bodyType.insertParameterTypes(vsize, Object.class);
+            throw misMatchedTypes("body function", bodyType, expected);
+        }
+        List<Class<?>> externalParamList = internalParamList.subList(vsize + 1, internalParamList.size());
+        Class<?> iterableType = null;
+        if (iterator != null) {
+            // special case; if the body handle only declares V and T then
+            // the external parameter list is obtained from iterator handle
+            if (externalParamList.isEmpty()) {
+                externalParamList = iterator.type().parameterList();
+            }
+            MethodType itype = iterator.type();
+            if (!Iterator.class.isAssignableFrom(itype.returnType())) {
+                throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type");
+            }
+            if (!itype.effectivelyIdenticalParameters(0, externalParamList)) {
+                MethodType expected = methodType(itype.returnType(), externalParamList);
+                throw misMatchedTypes("iterator parameters", itype, expected);
+            }
+        } else {
+            if (externalParamList.isEmpty()) {
+                // special case; if the iterator handle is null and the body handle
+                // only declares V and T then the external parameter list consists
+                // of Iterable
+                externalParamList = Arrays.asList(Iterable.class);
+                iterableType = Iterable.class;
+            } else {
+                // special case; if the iterator handle is null and the external
+                // parameter list is not empty then the first parameter must be
+                // assignable to Iterable
+                iterableType = externalParamList.get(0);
+                if (!Iterable.class.isAssignableFrom(iterableType)) {
+                    throw newIllegalArgumentException(
+                            "inferred first loop argument must inherit from Iterable: " + iterableType);
+                }
+            }
+        }
+        if (init != null) {
+            MethodType initType = init.type();
+            if (initType.returnType() != returnType ||
+                    !initType.effectivelyIdenticalParameters(0, externalParamList)) {
+                throw misMatchedTypes("loop initializer", initType, methodType(returnType, externalParamList));
+            }
+        }
+        return iterableType;  // help the caller a bit
+    }
+
+    /*non-public*/ static MethodHandle swapArguments(MethodHandle mh, int i, int j) {
+        // there should be a better way to uncross my wires
+        int arity = mh.type().parameterCount();
+        int[] order = new int[arity];
+        for (int k = 0; k < arity; k++)  order[k] = k;
+        order[i] = j; order[j] = i;
+        Class<?>[] types = mh.type().parameterArray();
+        Class<?> ti = types[i]; types[i] = types[j]; types[j] = ti;
+        MethodType swapType = methodType(mh.type().returnType(), types);
+        return permuteArguments(mh, swapType, order);
+    }
+
+    /**
+     * Makes a method handle that adapts a {@code target} method handle by wrapping it in a {@code try-finally} block.
+     * Another method handle, {@code cleanup}, represents the functionality of the {@code finally} block. Any exception
+     * thrown during the execution of the {@code target} handle will be passed to the {@code cleanup} handle. The
+     * exception will be rethrown, unless {@code cleanup} handle throws an exception first.  The
+     * value returned from the {@code cleanup} handle's execution will be the result of the execution of the
+     * {@code try-finally} handle.
+     * <p>
+     * The {@code cleanup} handle will be passed one or two additional leading arguments.
+     * The first is the exception thrown during the
+     * execution of the {@code target} handle, or {@code null} if no exception was thrown.
+     * The second is the result of the execution of the {@code target} handle, or, if it throws an exception,
+     * a {@code null}, zero, or {@code false} value of the required type is supplied as a placeholder.
+     * The second argument is not present if the {@code target} handle has a {@code void} return type.
+     * (Note that, except for argument type conversions, combinators represent {@code void} values in parameter lists
+     * by omitting the corresponding paradoxical arguments, not by inserting {@code null} or zero values.)
+     * <p>
+     * The {@code target} and {@code cleanup} handles must have the same corresponding argument and return types, except
+     * that the {@code cleanup} handle may omit trailing arguments. Also, the {@code cleanup} handle must have one or
+     * two extra leading parameters:<ul>
+     * <li>a {@code Throwable}, which will carry the exception thrown by the {@code target} handle (if any); and
+     * <li>a parameter of the same type as the return type of both {@code target} and {@code cleanup}, which will carry
+     * the result from the execution of the {@code target} handle.
+     * This parameter is not present if the {@code target} returns {@code void}.
+     * </ul>
+     * <p>
+     * The pseudocode for the resulting adapter looks as follows. In the code, {@code V} represents the result type of
+     * the {@code try/finally} construct; {@code A}/{@code a}, the types and values of arguments to the resulting
+     * handle consumed by the cleanup; and {@code B}/{@code b}, those of arguments to the resulting handle discarded by
+     * the cleanup.
+     * <blockquote><pre>{@code
+     * V target(A..., B...);
+     * V cleanup(Throwable, V, A...);
+     * V adapter(A... a, B... b) {
+     *   V result = (zero value for V);
+     *   Throwable throwable = null;
+     *   try {
+     *     result = target(a..., b...);
+     *   } catch (Throwable t) {
+     *     throwable = t;
+     *     throw t;
+     *   } finally {
+     *     result = cleanup(throwable, result, a...);
+     *   }
+     *   return result;
+     * }
+     * }</pre></blockquote>
+     * <p>
+     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
+     * be modified by execution of the target, and so are passed unchanged
+     * from the caller to the cleanup, if it is invoked.
+     * <p>
+     * The target and cleanup must return the same type, even if the cleanup
+     * always throws.
+     * To create such a throwing cleanup, compose the cleanup logic
+     * with {@link #throwException throwException},
+     * in order to create a method handle of the correct return type.
+     * <p>
+     * Note that {@code tryFinally} never converts exceptions into normal returns.
+     * In rare cases where exceptions must be converted in that way, first wrap
+     * the target with {@link #catchException(MethodHandle, Class, MethodHandle)}
+     * to capture an outgoing exception, and then wrap with {@code tryFinally}.
+     * <p>
+     * It is recommended that the first parameter type of {@code cleanup} be
+     * declared {@code Throwable} rather than a narrower subtype.  This ensures
+     * {@code cleanup} will always be invoked with whatever exception that
+     * {@code target} throws.  Declaring a narrower type may result in a
+     * {@code ClassCastException} being thrown by the {@code try-finally}
+     * handle if the type of the exception thrown by {@code target} is not
+     * assignable to the first parameter type of {@code cleanup}.  Note that
+     * various exception types of {@code VirtualMachineError},
+     * {@code LinkageError}, and {@code RuntimeException} can in principle be
+     * thrown by almost any kind of Java code, and a finally clause that
+     * catches (say) only {@code IOException} would mask any of the others
+     * behind a {@code ClassCastException}.
+     *
+     * @param target the handle whose execution is to be wrapped in a {@code try} block.
+     * @param cleanup the handle that is invoked in the finally block.
+     *
+     * @return a method handle embodying the {@code try-finally} block composed of the two arguments.
+     * @throws NullPointerException if any argument is null
+     * @throws IllegalArgumentException if {@code cleanup} does not accept
+     *          the required leading arguments, or if the method handle types do
+     *          not match in their return types and their
+     *          corresponding trailing parameters
+     *
+     * @see MethodHandles#catchException(MethodHandle, Class, MethodHandle)
+     * @since 9
+     */
+    public static MethodHandle tryFinally(MethodHandle target, MethodHandle cleanup) {
+        List<Class<?>> targetParamTypes = target.type().parameterList();
+        Class<?> rtype = target.type().returnType();
+
+        tryFinallyChecks(target, cleanup);
+
+        // Match parameter lists: if the cleanup has a shorter parameter list than the target, add ignored arguments.
+        // The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the
+        // target parameter list.
+        cleanup = dropArgumentsToMatch(cleanup, (rtype == void.class ? 1 : 2), targetParamTypes, 0);
+
+        // Ensure that the intrinsic type checks the instance thrown by the
+        // target against the first parameter of cleanup
+        cleanup = cleanup.asType(cleanup.type().changeParameterType(0, Throwable.class));
+
+        // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
+        // Android-changed: use Transformer implementation.
+        // return MethodHandleImpl.makeTryFinally(target.asFixedArity(), cleanup.asFixedArity(), rtype, targetParamTypes);
+        return new Transformers.TryFinally(target.asFixedArity(), cleanup.asFixedArity());
+    }
+
+    private static void tryFinallyChecks(MethodHandle target, MethodHandle cleanup) {
+        Class<?> rtype = target.type().returnType();
+        if (rtype != cleanup.type().returnType()) {
+            throw misMatchedTypes("target and return types", cleanup.type().returnType(), rtype);
+        }
+        MethodType cleanupType = cleanup.type();
+        if (!Throwable.class.isAssignableFrom(cleanupType.parameterType(0))) {
+            throw misMatchedTypes("cleanup first argument and Throwable", cleanup.type(), Throwable.class);
+        }
+        if (rtype != void.class && cleanupType.parameterType(1) != rtype) {
+            throw misMatchedTypes("cleanup second argument and target return type", cleanup.type(), rtype);
+        }
+        // The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the
+        // target parameter list.
+        int cleanupArgIndex = rtype == void.class ? 1 : 2;
+        if (!cleanupType.effectivelyIdenticalParameters(cleanupArgIndex, target.type().parameterList())) {
+            throw misMatchedTypes("cleanup parameters after (Throwable,result) and target parameter list prefix",
+                    cleanup.type(), target.type());
+        }
+    }
+
+    // BEGIN Android-added: Code from OpenJDK's MethodHandleImpl.
+
+    /**
+     * This method is bound as the predicate in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle,
+     * MethodHandle) counting loops}.
+     *
+     * @param limit the upper bound of the parameter, statically bound at loop creation time.
+     * @param counter the counter parameter, passed in during loop execution.
+     *
+     * @return whether the counter has reached the limit.
+     * @hide
+     */
+    public static boolean countedLoopPredicate(int limit, int counter) {
+        return counter < limit;
+    }
+
+    /**
+     * This method is bound as the step function in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle,
+     * MethodHandle) counting loops} to increment the counter.
+     *
+     * @param limit the upper bound of the loop counter (ignored).
+     * @param counter the loop counter.
+     *
+     * @return the loop counter incremented by 1.
+     * @hide
+     */
+    public static int countedLoopStep(int limit, int counter) {
+        return counter + 1;
+    }
+
+    /**
+     * This is bound to initialize the loop-local iterator in {@linkplain MethodHandles#iteratedLoop iterating loops}.
+     *
+     * @param it the {@link Iterable} over which the loop iterates.
+     *
+     * @return an {@link Iterator} over the argument's elements.
+     * @hide
+     */
+    public static Iterator<?> initIterator(Iterable<?> it) {
+        return it.iterator();
+    }
+
+    /**
+     * This method is bound as the predicate in {@linkplain MethodHandles#iteratedLoop iterating loops}.
+     *
+     * @param it the iterator to be checked.
+     *
+     * @return {@code true} iff there are more elements to iterate over.
+     * @hide
+     */
+    public static boolean iteratePredicate(Iterator<?> it) {
+        return it.hasNext();
+    }
+
+    /**
+     * This method is bound as the step for retrieving the current value from the iterator in {@linkplain
+     * MethodHandles#iteratedLoop iterating loops}.
+     *
+     * @param it the iterator.
+     *
+     * @return the next element from the iterator.
+     * @hide
+     */
+    public static Object iterateNext(Iterator<?> it) {
+        return it.next();
+    }
+
+    // Indexes into constant method handles:
+    static final int
+        MH_cast                  =  0,
+        MH_selectAlternative     =  1,
+        MH_copyAsPrimitiveArray  =  2,
+        MH_fillNewTypedArray     =  3,
+        MH_fillNewArray          =  4,
+        MH_arrayIdentity         =  5,
+        MH_countedLoopPred       =  6,
+        MH_countedLoopStep       =  7,
+        MH_initIterator          =  8,
+        MH_iteratePred           =  9,
+        MH_iterateNext           = 10,
+        MH_Array_newInstance     = 11,
+        MH_LIMIT                 = 12;
+
+    static MethodHandle getConstantHandle(int idx) {
+        MethodHandle handle = HANDLES[idx];
+        if (handle != null) {
+            return handle;
+        }
+        return setCachedHandle(idx, makeConstantHandle(idx));
+    }
+
+    private static synchronized MethodHandle setCachedHandle(int idx, final MethodHandle method) {
+        // Simulate a CAS, to avoid racy duplication of results.
+        MethodHandle prev = HANDLES[idx];
+        if (prev != null) {
+            return prev;
+        }
+        HANDLES[idx] = method;
+        return method;
+    }
+
+    // Local constant method handles:
+    private static final @Stable MethodHandle[] HANDLES = new MethodHandle[MH_LIMIT];
+
+    private static MethodHandle makeConstantHandle(int idx) {
+        try {
+            // Android-added: local IMPL_LOOKUP.
+            final Lookup IMPL_LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP;
+            switch (idx) {
+                // Android-removed: not-used.
+                /*
+                case MH_cast:
+                    return IMPL_LOOKUP.findVirtual(Class.class, "cast",
+                            MethodType.methodType(Object.class, Object.class));
+                case MH_copyAsPrimitiveArray:
+                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "copyAsPrimitiveArray",
+                            MethodType.methodType(Object.class, Wrapper.class, Object[].class));
+                case MH_arrayIdentity:
+                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "identity",
+                            MethodType.methodType(Object[].class, Object[].class));
+                case MH_fillNewArray:
+                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewArray",
+                            MethodType.methodType(Object[].class, Integer.class, Object[].class));
+                case MH_fillNewTypedArray:
+                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewTypedArray",
+                            MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
+                case MH_selectAlternative:
+                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
+                            MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
+                */
+                case MH_countedLoopPred:
+                    // Android-changed: methods moved to this file.
+                    // return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopPredicate",
+                    //         MethodType.methodType(boolean.class, int.class, int.class));
+                    return IMPL_LOOKUP.findStatic(MethodHandles.class, "countedLoopPredicate",
+                            MethodType.methodType(boolean.class, int.class, int.class));
+                case MH_countedLoopStep:
+                    // Android-changed: methods moved to this file.
+                    // return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopStep",
+                    //         MethodType.methodType(int.class, int.class, int.class));
+                    return IMPL_LOOKUP.findStatic(MethodHandles.class, "countedLoopStep",
+                            MethodType.methodType(int.class, int.class, int.class));
+                case MH_initIterator:
+                    // Android-changed: methods moved to this file.
+                    // return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "initIterator",
+                    //         MethodType.methodType(Iterator.class, Iterable.class));
+                    return IMPL_LOOKUP.findStatic(MethodHandles.class, "initIterator",
+                            MethodType.methodType(Iterator.class, Iterable.class));
+                case MH_iteratePred:
+                    // Android-changed: methods moved to this file.
+                    // return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iteratePredicate",
+                    //         MethodType.methodType(boolean.class, Iterator.class));
+                    return IMPL_LOOKUP.findStatic(MethodHandles.class, "iteratePredicate",
+                            MethodType.methodType(boolean.class, Iterator.class));
+                case MH_iterateNext:
+                    // Android-changed: methods moved to this file.
+                    // return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iterateNext",
+                    //         MethodType.methodType(Object.class, Iterator.class));
+                    return IMPL_LOOKUP.findStatic(MethodHandles.class, "iterateNext",
+                            MethodType.methodType(Object.class, Iterator.class));
+                // Android-removed: not-used.
+                /*
+                case MH_Array_newInstance:
+                    return IMPL_LOOKUP.findStatic(Array.class, "newInstance",
+                            MethodType.methodType(Object.class, Class.class, int.class));
+                */
+            }
+        } catch (ReflectiveOperationException ex) {
+            throw newInternalError(ex);
+        }
+
+        throw newInternalError("Unknown function index: " + idx);
+    }
+    // END Android-added: Code from OpenJDK's MethodHandleImpl.
 }
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodType.java b/ojluni/src/main/java/java/lang/invoke/MethodType.java
index 4652c93..a1b3a9c 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodType.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodType.java
@@ -473,12 +473,13 @@
 
     /** Replace the last arrayLength parameter types with the component type of arrayType.
      * @param arrayType any array type
+     * @param pos position at which to spread
      * @param arrayLength the number of parameter types to change
      * @return the resulting type
      */
-    /*non-public*/ MethodType asSpreaderType(Class<?> arrayType, int arrayLength) {
+    /*non-public*/ MethodType asSpreaderType(Class<?> arrayType, int pos, int arrayLength) {
         assert(parameterCount() >= arrayLength);
-        int spreadPos = ptypes.length - arrayLength;
+        int spreadPos = pos;
         if (arrayLength == 0)  return this;  // nothing to change
         if (arrayType == Object[].class) {
             if (isGeneric())  return this;  // nothing to change
@@ -493,10 +494,10 @@
         }
         Class<?> elemType = arrayType.getComponentType();
         assert(elemType != null);
-        for (int i = spreadPos; i < ptypes.length; i++) {
+        for (int i = spreadPos; i < spreadPos + arrayLength; i++) {
             if (ptypes[i] != elemType) {
                 Class<?>[] fixedPtypes = ptypes.clone();
-                Arrays.fill(fixedPtypes, i, ptypes.length, elemType);
+                Arrays.fill(fixedPtypes, i, spreadPos + arrayLength, elemType);
                 return methodType(rtype, fixedPtypes);
             }
         }
@@ -516,12 +517,14 @@
 
     /** Delete the last parameter type and replace it with arrayLength copies of the component type of arrayType.
      * @param arrayType any array type
+     * @param pos position at which to insert parameters
      * @param arrayLength the number of parameter types to insert
      * @return the resulting type
      */
-    /*non-public*/ MethodType asCollectorType(Class<?> arrayType, int arrayLength) {
+    /*non-public*/ MethodType asCollectorType(Class<?> arrayType, int pos, int arrayLength) {
         assert(parameterCount() >= 1);
-        assert(lastParameterType().isAssignableFrom(arrayType));
+        assert(pos < ptypes.length);
+        assert(ptypes[pos].isAssignableFrom(arrayType));
         MethodType res;
         if (arrayType == Object[].class) {
             res = genericMethodType(arrayLength);
@@ -536,7 +539,11 @@
         if (ptypes.length == 1) {
             return res;
         } else {
-            return res.insertParameterTypes(0, parameterList().subList(0, ptypes.length-1));
+            // insert after (if need be), then before
+            if (pos < ptypes.length - 1) {
+                res = res.insertParameterTypes(arrayLength, Arrays.copyOfRange(ptypes, pos + 1, ptypes.length));
+            }
+            return res.insertParameterTypes(0, Arrays.copyOf(ptypes, pos));
         }
     }
 
@@ -738,7 +745,23 @@
         return Collections.unmodifiableList(Arrays.asList(ptypes.clone()));
     }
 
-    /*non-public*/ Class<?> lastParameterType() {
+    /**
+     * Returns the last parameter type of this method type.
+     * If this type has no parameters, the sentinel value
+     * {@code void.class} is returned instead.
+     * @apiNote
+     * <p>
+     * The sentinel value is chosen so that reflective queries can be
+     * made directly against the result value.
+     * The sentinel value cannot be confused with a real parameter,
+     * since {@code void} is never acceptable as a parameter type.
+     * For variable arity invocation modes, the expression
+     * {@link Class#getComponentType lastParameterType().getComponentType()}
+     * is useful to query the type of the "varargs" parameter.
+     * @return the last parameter type if any, else {@code void.class}
+     * @since 10
+     */
+    public Class<?> lastParameterType() {
         int len = ptypes.length;
         return len == 0 ? void.class : ptypes[len-1];
     }
@@ -810,6 +833,28 @@
         return sb.toString();
     }
 
+    /** True if my parameter list is effectively identical to the given full list,
+     *  after skipping the given number of my own initial parameters.
+     *  In other words, after disregarding {@code skipPos} parameters,
+     *  my remaining parameter list is no longer than the {@code fullList}, and
+     *  is equal to the same-length initial sublist of {@code fullList}.
+     */
+    /*non-public*/
+    boolean effectivelyIdenticalParameters(int skipPos, List<Class<?>> fullList) {
+        int myLen = ptypes.length, fullLen = fullList.size();
+        if (skipPos > myLen || myLen - skipPos > fullLen)
+            return false;
+        List<Class<?>> myList = Arrays.asList(ptypes);
+        if (skipPos != 0) {
+            myList = myList.subList(skipPos, myLen);
+            myLen -= skipPos;
+        }
+        if (fullLen == myLen)
+            return myList.equals(fullList);
+        else
+            return myList.equals(fullList.subList(0, myLen));
+    }
+
     // BEGIN Android-removed: Implementation methods unused on Android.
     /*
     /** True if the old return type can always be viewed (w/o casting) under new return type,
@@ -842,11 +887,12 @@
 
     /*non-public*/
     boolean isConvertibleTo(MethodType newType) {
-        MethodTypeForm oldForm = this.form();
-        MethodTypeForm newForm = newType.form();
-        if (oldForm == newForm)
-            // same parameter count, same primitive/object mix
-            return true;
+        // Android-removed: use of MethodTypeForm does not apply to Android implementation.
+        // MethodTypeForm oldForm = this.form();
+        // MethodTypeForm newForm = newType.form();
+        // if (oldForm == newForm)
+        //     // same parameter count, same primitive/object mix
+        //     return true;
         if (!canConvert(returnType(), newType.returnType()))
             return false;
         Class<?>[] srcTypes = newType.ptypes;
@@ -861,13 +907,14 @@
                 return false;
             return true;
         }
-        if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) ||
-            (newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) {
-            // Somewhat complicated test to avoid a loop of 2 or more trips.
-            // If either type has only Object parameters, we know we can convert.
-            assert(canConvertParameters(srcTypes, dstTypes));
-            return true;
-        }
+        // Android-removed: use of MethodTypeForm does not apply to Android implementation.
+        // if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) ||
+        //     (newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) {
+        //     // Somewhat complicated test to avoid a loop of 2 or more trips.
+        //     // If either type has only Object parameters, we know we can convert.
+        //     assert(canConvertParameters(srcTypes, dstTypes));
+        //     return true;
+        // }
         return canConvertParameters(srcTypes, dstTypes);
     }
 
diff --git a/ojluni/src/main/java/java/lang/invoke/Transformers.java b/ojluni/src/main/java/java/lang/invoke/Transformers.java
index 15546a8..590b9a7 100644
--- a/ojluni/src/main/java/java/lang/invoke/Transformers.java
+++ b/ojluni/src/main/java/java/lang/invoke/Transformers.java
@@ -21,41 +21,46 @@
 
 package java.lang.invoke;
 
+import static dalvik.system.EmulatedStackFrame.StackFrameAccessor.copyNext;
+
 import dalvik.system.EmulatedStackFrame;
 import dalvik.system.EmulatedStackFrame.Range;
+import dalvik.system.EmulatedStackFrame.RandomOrderStackFrameReader;
 import dalvik.system.EmulatedStackFrame.StackFrameAccessor;
 import dalvik.system.EmulatedStackFrame.StackFrameReader;
 import dalvik.system.EmulatedStackFrame.StackFrameWriter;
+
+import sun.invoke.util.Wrapper;
+import sun.misc.Unsafe;
+
 import java.lang.reflect.Array;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import sun.invoke.util.Wrapper;
-import sun.misc.Unsafe;
-import static dalvik.system.EmulatedStackFrame.StackFrameAccessor.copyNext;
+import java.util.ArrayList;
+import java.util.List;
 
-/**
- * @hide Public for testing only.
- */
+/** @hide Public for testing only. */
 public class Transformers {
     private Transformers() {}
 
     static {
         try {
-            TRANSFORM_INTERNAL = MethodHandle.class.getDeclaredMethod("transformInternal",
-                    EmulatedStackFrame.class);
+            TRANSFORM_INTERNAL =
+                    MethodHandle.class.getDeclaredMethod(
+                            "transformInternal", EmulatedStackFrame.class);
         } catch (NoSuchMethodException nsme) {
             throw new AssertionError();
         }
     }
 
     /**
-     * Method reference to the private {@code MethodHandle.transformInternal} method. This is
-     * cached here because it's the point of entry for all transformers.
+     * Method reference to the private {@code MethodHandle.transformInternal} method. This is cached
+     * here because it's the point of entry for all transformers.
      */
     private static final Method TRANSFORM_INTERNAL;
 
     /** @hide */
-    public static abstract class Transformer extends MethodHandle implements Cloneable {
+    public abstract static class Transformer extends MethodHandle implements Cloneable {
         protected Transformer(MethodType type) {
             super(TRANSFORM_INTERNAL.getArtMethod(), MethodHandle.INVOKE_TRANSFORM, type);
         }
@@ -68,20 +73,44 @@
         public Object clone() throws CloneNotSupportedException {
             return super.clone();
         }
+
+        /**
+         * Performs a MethodHandle.invoke() call with arguments held in an
+         * EmulatedStackFrame.
+         * @param target the method handle to invoke
+         * @param stackFrame the stack frame containing arguments for the invocation
+         */
+        protected static void invokeFromTransform(MethodHandle target,
+                                                  EmulatedStackFrame stackFrame) throws Throwable {
+            if (target instanceof Transformer) {
+                ((Transformer) target).transform(stackFrame);
+            } else {
+                final MethodHandle adaptedTarget = target.asType(stackFrame.getMethodType());
+                adaptedTarget.invokeExactWithFrame(stackFrame);
+            }
+        }
+
+        /**
+         * Performs a MethodHandle.invokeExact() call with arguments held in an
+         * EmulatedStackFrame.
+         * @param target the method handle to invoke
+         * @param stackFrame the stack frame containing arguments for the invocation
+         */
+        protected void invokeExactFromTransform(MethodHandle target,
+                                                EmulatedStackFrame stackFrame) throws Throwable {
+            if (target instanceof Transformer) {
+                ((Transformer) target).transform(stackFrame);
+            } else {
+                target.invokeExactWithFrame(stackFrame);
+            }
+        }
     }
 
-    /**
-     * A method handle that always throws an exception of a specified type.
-     *
-     * The handle declares a nominal return type, which is immaterial to the execution
-     * of the handle because it never returns.
-     *
-     * @hide
-     */
-    public static class AlwaysThrow extends Transformer {
+    /** Implements {@code MethodHandles.throwException}. */
+    static class AlwaysThrow extends Transformer {
         private final Class<? extends Throwable> exceptionType;
 
-        public AlwaysThrow(Class<?> nominalReturnType, Class<? extends  Throwable> exType) {
+        AlwaysThrow(Class<?> nominalReturnType, Class<? extends Throwable> exType) {
             super(MethodType.methodType(nominalReturnType, exType));
             this.exceptionType = exType;
         }
@@ -92,22 +121,13 @@
         }
     }
 
-    /**
-     * Implements {@code MethodHandles.dropArguments}.
-     */
-    public static class DropArguments extends Transformer {
+    /** Implements {@code MethodHandles.dropArguments}. */
+    static class DropArguments extends Transformer {
         private final MethodHandle delegate;
-
         private final EmulatedStackFrame.Range range1;
+        private final EmulatedStackFrame.Range range2;
 
-        /**
-         * Note that {@code range2} will be null if the arguments that are being dropped
-         * are the last {@code n}.
-         */
-        /* @Nullable */ private final EmulatedStackFrame.Range range2;
-
-        public DropArguments(MethodType type, MethodHandle delegate,
-                             int startPos, int numDropped) {
+        DropArguments(MethodType type, MethodHandle delegate, int startPos, int numDropped) {
             super(type);
 
             this.delegate = delegate;
@@ -115,45 +135,32 @@
             // We pre-calculate the ranges of values we have to copy through to the delegate
             // handle at the time of instantiation so that the actual invoke is performant.
             this.range1 = EmulatedStackFrame.Range.of(type, 0, startPos);
-            final int numArgs = type.ptypes().length;
-            if (startPos + numDropped < numArgs) {
-                this.range2 = EmulatedStackFrame.Range.of(type, startPos + numDropped, numArgs);
-            } else {
-                this.range2 = null;
-            }
+            this.range2 = EmulatedStackFrame.Range.from(type, startPos + numDropped);
         }
 
         @Override
         public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
             EmulatedStackFrame calleeFrame = EmulatedStackFrame.create(delegate.type());
 
-            emulatedStackFrame.copyRangeTo(calleeFrame, range1,
-                    0 /* referencesStart */, 0 /* stackFrameStart */);
+            emulatedStackFrame.copyRangeTo(
+                    calleeFrame, range1, 0 /* referencesStart */, 0 /* stackFrameStart */);
+            emulatedStackFrame.copyRangeTo(
+                    calleeFrame, range2, range1.numReferences, range1.numBytes);
 
-            if (range2 != null) {
-                final int referencesStart = range1.numReferences;
-                final int stackFrameStart = range1.numBytes;
-
-                emulatedStackFrame.copyRangeTo(calleeFrame, range2,
-                        referencesStart, stackFrameStart);
-            }
-
-            delegate.invoke(calleeFrame);
+            invokeFromTransform(delegate, calleeFrame);
             calleeFrame.copyReturnValueTo(emulatedStackFrame);
         }
     }
 
-    /**
-     * Implements {@code MethodHandles.catchException}.
-     */
-    public static class CatchException extends Transformer {
+    /** Implements {@code MethodHandles.catchException}. */
+    static class CatchException extends Transformer {
         private final MethodHandle target;
         private final MethodHandle handler;
         private final Class<?> exType;
 
         private final EmulatedStackFrame.Range handlerArgsRange;
 
-        public CatchException(MethodHandle target, MethodHandle handler, Class<?> exType) {
+        CatchException(MethodHandle target, MethodHandle handler, Class<?> exType) {
             super(target.type());
 
             this.target = target;
@@ -163,14 +170,15 @@
             // We only copy the first "count" args, dropping others if required. Note that
             // we subtract one because the first handler arg is the exception thrown by the
             // target.
-            handlerArgsRange = EmulatedStackFrame.Range.of(target.type(), 0,
-                    (handler.type().parameterCount() - 1));
+            handlerArgsRange =
+                    EmulatedStackFrame.Range.of(
+                            target.type(), 0, (handler.type().parameterCount() - 1));
         }
 
         @Override
         public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
             try {
-                target.invoke(emulatedStackFrame);
+                invokeFromTransform(target, emulatedStackFrame);
             } catch (Throwable th) {
                 if (th.getClass() == exType) {
                     // We've gotten an exception of the appropriate type, so we need to call
@@ -183,11 +191,14 @@
                     // We then copy other arguments that need to be passed through to the handler.
                     // Note that we might drop arguments at the end, if needed. Note that
                     // referencesStart == 1 because the first argument is the exception type.
-                    emulatedStackFrame.copyRangeTo(fallback, handlerArgsRange,
-                            1 /* referencesStart */, 0 /* stackFrameStart */);
+                    emulatedStackFrame.copyRangeTo(
+                            fallback,
+                            handlerArgsRange,
+                            1 /* referencesStart */,
+                            0 /* stackFrameStart */);
 
                     // Perform the invoke and return the appropriate value.
-                    handler.invoke(fallback);
+                    invokeFromTransform(handler, fallback);
                     fallback.copyReturnValueTo(emulatedStackFrame);
                 } else {
                     // The exception is not of the expected type, we throw it.
@@ -197,17 +208,79 @@
         }
     }
 
-    /**
-     * Implements {@code MethodHandles.GuardWithTest}.
-     */
-    public static class GuardWithTest extends Transformer {
+    /** Implements {@code MethodHandles.tryFinally}. */
+    static class TryFinally extends Transformer {
+        /** The target handle to try. */
+        private final MethodHandle target;
+
+        /** The cleanup handle to invoke after the target. */
+        private final MethodHandle cleanup;
+
+        TryFinally(MethodHandle target, MethodHandle cleanup) {
+            super(target.type());
+            this.target = target;
+            this.cleanup = cleanup;
+        }
+
+        @Override
+        protected void transform(EmulatedStackFrame callerFrame) throws Throwable {
+            Throwable throwable = null;
+            try {
+                invokeExactFromTransform(target, callerFrame);
+            } catch (Throwable t) {
+                throwable = t;
+                throw t;
+            } finally {
+                final EmulatedStackFrame cleanupFrame = prepareCleanupFrame(callerFrame, throwable);
+                invokeExactFromTransform(cleanup, cleanupFrame);
+                if (cleanup.type().returnType() != void.class) {
+                    cleanupFrame.copyReturnValueTo(callerFrame);
+                }
+            }
+        }
+
+        /** Prepares the frame used to invoke the cleanup handle. */
+        private EmulatedStackFrame prepareCleanupFrame(final EmulatedStackFrame callerFrame,
+                                                       final Throwable throwable) {
+            final EmulatedStackFrame cleanupFrame = EmulatedStackFrame.create(cleanup.type());
+            final StackFrameWriter cleanupWriter = new StackFrameWriter();
+            cleanupWriter.attach(cleanupFrame);
+
+            // The first argument to `cleanup` is (any) pending exception kind.
+            cleanupWriter.putNextReference(throwable, Throwable.class);
+            int added = 1;
+
+            // The second argument to `cleanup` is the result from `target` (if not void).
+            Class<?> targetReturnType = target.type().returnType();
+            StackFrameReader targetReader = new StackFrameReader();
+            targetReader.attach(callerFrame);
+            if (targetReturnType != void.class) {
+                targetReader.makeReturnValueAccessor();
+                copyNext(targetReader, cleanupWriter, targetReturnType);
+                added += 1;
+                // Reset `targetReader` to reference the arguments in `callerFrame`.
+                targetReader.attach(callerFrame);
+            }
+
+            // The final arguments from the invocation of target. As many are copied as the cleanup
+            // handle expects (it may be fewer than the arguments provided to target).
+            Class<?> [] cleanupTypes = cleanup.type().parameterArray();
+            for (; added != cleanupTypes.length; ++added) {
+                copyNext(targetReader, cleanupWriter, cleanupTypes[added]);
+            }
+            return cleanupFrame;
+        }
+    }
+
+    /** Implements {@code MethodHandles.GuardWithTest}. */
+    static class GuardWithTest extends Transformer {
         private final MethodHandle test;
         private final MethodHandle target;
         private final MethodHandle fallback;
 
         private final EmulatedStackFrame.Range testArgsRange;
 
-        public GuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) {
+        GuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) {
             super(target.type());
 
             this.test = test;
@@ -215,7 +288,8 @@
             this.fallback = fallback;
 
             // The test method might have a subset of the arguments of the handle / target.
-            testArgsRange = EmulatedStackFrame.Range.of(target.type(), 0, test.type().parameterCount());
+            testArgsRange =
+                    EmulatedStackFrame.Range.of(target.type(), 0, test.type().parameterCount());
         }
 
         @Override
@@ -223,26 +297,28 @@
             EmulatedStackFrame testFrame = EmulatedStackFrame.create(test.type());
             emulatedStackFrame.copyRangeTo(testFrame, testArgsRange, 0, 0);
 
-            // We know that the return value for test is going to be boolean.class, so we don't have
-            // to do the copyReturnValue dance.
-            final boolean value = (boolean) test.invoke(testFrame);
-            if (value) {
-                target.invoke(emulatedStackFrame);
+            // We know that the return value for test is going to be boolean.class.
+            StackFrameReader reader = new StackFrameReader();
+            reader.attach(testFrame);
+            reader.makeReturnValueAccessor();
+            invokeFromTransform(test, testFrame);
+            final boolean testResult = (boolean) reader.nextBoolean();
+            if (testResult) {
+                invokeFromTransform(target, emulatedStackFrame);
             } else {
-                fallback.invoke(emulatedStackFrame);
+                invokeFromTransform(fallback, emulatedStackFrame);
             }
         }
     }
 
-    /**
-     * Implementation of MethodHandles.arrayElementGetter for reference types.
-     */
-    public static class ReferenceArrayElementGetter extends Transformer {
+    /** Implements {@code MethodHandles.arrayElementGetter}. */
+    static class ReferenceArrayElementGetter extends Transformer {
         private final Class<?> arrayClass;
 
-        public ReferenceArrayElementGetter(Class<?> arrayClass) {
-            super(MethodType.methodType(arrayClass.getComponentType(),
-                    new Class<?>[]{arrayClass, int.class}));
+        ReferenceArrayElementGetter(Class<?> arrayClass) {
+            super(
+                    MethodType.methodType(
+                            arrayClass.getComponentType(), new Class<?>[] {arrayClass, int.class}));
             this.arrayClass = arrayClass;
         }
 
@@ -263,15 +339,15 @@
         }
     }
 
-    /**
-     * Implementation of MethodHandles.arrayElementSetter for reference types.
-     */
-    public static class ReferenceArrayElementSetter extends Transformer {
+    /** Implements {@code MethodHandles.arrayElementSetter}. */
+    static class ReferenceArrayElementSetter extends Transformer {
         private final Class<?> arrayClass;
 
-        public ReferenceArrayElementSetter(Class<?> arrayClass) {
-            super(MethodType.methodType(void.class,
-                    new Class<?>[] { arrayClass, int.class, arrayClass.getComponentType() }));
+        ReferenceArrayElementSetter(Class<?> arrayClass) {
+            super(
+                    MethodType.methodType(
+                            void.class,
+                            new Class<?>[] {arrayClass, int.class, arrayClass.getComponentType()}));
             this.arrayClass = arrayClass;
         }
 
@@ -289,13 +365,11 @@
         }
     }
 
-    /**
-     * Implementation of MethodHandles.identity() for reference types.
-     */
-    public static class ReferenceIdentity extends Transformer {
+    /** Implements {@code MethodHandles.identity}. */
+    static class ReferenceIdentity extends Transformer {
         private final Class<?> type;
 
-        public ReferenceIdentity(Class<?> type) {
+        ReferenceIdentity(Class<?> type) {
             super(MethodType.methodType(type, type));
             this.type = type;
         }
@@ -312,89 +386,97 @@
         }
     }
 
-    /**
-     * Implementation of MethodHandles.constant.
-     */
-    public static class Constant extends Transformer {
-        private final Class<?> type;
-
-        // NOTE: This implementation turned out to be more awkward than expected becuase
-        // of the type system. We could simplify this considerably at the cost of making
-        // the emulated stack frame API uglier or by transitioning into JNI.
-        //
-        // We could consider implementing this in terms of bind() once that's implemented.
-        // This would then just become : MethodHandles.identity(type).bind(value).
-        private int asInt;
-        private long asLong;
-        private float asFloat;
-        private double asDouble;
-        private Object asReference;
-
-        private char typeChar;
-
-        public Constant(Class<?> type, Object value) {
+    /** Implements {@code MethodHandles.makeZero}. */
+    static class ZeroValue extends Transformer {
+        public ZeroValue(Class<?> type) {
             super(MethodType.methodType(type));
-            this.type = type;
-
-            if (!type.isPrimitive()) {
-                asReference = value;
-                typeChar = 'L';
-            } else if (type == int.class) {
-                asInt = (int) value;
-                typeChar = 'I';
-            } else if (type == char.class) {
-                asInt = (int) (char) value;
-                typeChar = 'C';
-            } else if (type == short.class) {
-                asInt = (int) (short) value;
-                typeChar = 'S';
-            } else if (type == byte.class) {
-                asInt = (int) (byte) value;
-                typeChar = 'B';
-            } else if (type == boolean.class) {
-                asInt = ((boolean) value) ? 1 : 0;
-                typeChar = 'Z';
-            } else if (type == long.class) {
-                asLong = (long) value;
-                typeChar = 'J';
-            } else if (type == float.class) {
-                asFloat = (float) value;
-                typeChar = 'F';
-            } else if (type == double.class) {
-                asDouble = (double) value;
-                typeChar = 'D';
-            } else {
-                throw new AssertionError("unknown type: " + typeChar);
-            }
         }
 
         @Override
         public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
-            final StackFrameWriter writer = new StackFrameWriter();
-            writer.attach(emulatedStackFrame);
-            writer.makeReturnValueAccessor();
-
-            switch (typeChar) {
-                case 'L' : { writer.putNextReference(asReference, type); break; }
-                case 'I' : { writer.putNextInt(asInt); break; }
-                case 'C' : { writer.putNextChar((char) asInt); break; }
-                case 'S' : { writer.putNextShort((short) asInt); break; }
-                case 'B' : { writer.putNextByte((byte) asInt); break; }
-                case 'Z' : { writer.putNextBoolean(asInt == 1); break; }
-                case 'J' : { writer.putNextLong(asLong); break; }
-                case 'F' : { writer.putNextFloat(asFloat); break; }
-                case 'D' : { writer.putNextDouble(asDouble); break; }
-                default:
-                    throw new AssertionError("Unexpected typeChar: " + typeChar);
-            }
+            // Return-value is zero-initialized in emulatedStackFrame.
         }
     }
 
-    /*package*/ static class Construct extends Transformer {
+    /** Implements {@code MethodHandles.arrayConstructor}. */
+    static class ArrayConstructor extends Transformer {
+        private final Class<?> componentType;
+
+        ArrayConstructor(Class<?> arrayType) {
+            super(MethodType.methodType(arrayType, int.class));
+            componentType = arrayType.getComponentType();
+        }
+
+        @Override
+        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
+            final StackFrameReader reader = new StackFrameReader();
+            reader.attach(emulatedStackFrame);
+            final int length = reader.nextInt();
+            final Object array = Array.newInstance(componentType, length);
+            emulatedStackFrame.setReturnValueTo(array);
+        }
+    }
+
+    /** Implements {@code MethodHandles.arrayLength}. */
+    static class ArrayLength extends Transformer {
+        private final Class<?> arrayType;
+
+        ArrayLength(Class<?> arrayType) {
+            super(MethodType.methodType(int.class, arrayType));
+            this.arrayType = arrayType;
+        }
+
+        @Override
+        public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
+            final StackFrameReader reader = new StackFrameReader();
+            reader.attach(emulatedStackFrame);
+            final Object arrayObject = reader.nextReference(arrayType);
+
+            int length;
+            switch (Wrapper.basicTypeChar(arrayType.getComponentType())) {
+                case 'L':
+                    length = ((Object[]) arrayObject).length;
+                    break;
+                case 'Z':
+                    length = ((boolean[]) arrayObject).length;
+                    break;
+                case 'B':
+                    length = ((byte[]) arrayObject).length;
+                    break;
+                case 'C':
+                    length = ((char[]) arrayObject).length;
+                    break;
+                case 'S':
+                    length = ((short[]) arrayObject).length;
+                    break;
+                case 'I':
+                    length = ((int[]) arrayObject).length;
+                    break;
+                case 'J':
+                    length = ((long[]) arrayObject).length;
+                    break;
+                case 'F':
+                    length = ((float[]) arrayObject).length;
+                    break;
+                case 'D':
+                    length = ((double[]) arrayObject).length;
+                    break;
+                default:
+                    throw new IllegalStateException("Unsupported type: " + arrayType);
+            }
+
+            final StackFrameWriter writer = new StackFrameWriter();
+            writer.attach(emulatedStackFrame).makeReturnValueAccessor();
+            writer.putNextInt(length);
+        }
+    }
+
+    /** Implements {@code MethodHandles.createMethodHandleForConstructor}. */
+    static class Construct extends Transformer {
         private final MethodHandle constructorHandle;
         private final EmulatedStackFrame.Range callerRange;
 
-        /*package*/ Construct(MethodHandle constructorHandle, MethodType returnedType) {
+        Construct(MethodHandle constructorHandle, MethodType returnedType) {
             super(returnedType);
             this.constructorHandle = constructorHandle;
             this.callerRange = EmulatedStackFrame.Range.all(type());
@@ -432,25 +514,21 @@
                     EmulatedStackFrame.create(constructorHandle.type());
             constructorFrame.setReference(0, receiver);
             emulatedStackFrame.copyRangeTo(constructorFrame, callerRange, 1, 0);
-            constructorHandle.invoke(constructorFrame);
+            invokeExactFromTransform(constructorHandle, constructorFrame);
 
             // Set return result for caller.
             emulatedStackFrame.setReturnValueTo(receiver);
         }
     }
 
-    /**
-     * Implements MethodHandle.bindTo.
-     *
-     * @hide
-     */
-    public static class BindTo extends Transformer {
+    /** Implements {@code MethodHandle.bindTo}. */
+    static class BindTo extends Transformer {
         private final MethodHandle delegate;
         private final Object receiver;
 
         private final EmulatedStackFrame.Range range;
 
-        public BindTo(MethodHandle delegate, Object receiver) {
+        BindTo(MethodHandle delegate, Object receiver) {
             super(delegate.type().dropParameterTypes(0, 1));
 
             this.delegate = delegate;
@@ -468,25 +546,23 @@
             // The first reference argument must be the receiver.
             stackFrame.setReference(0, receiver);
             // Copy all other arguments.
-            emulatedStackFrame.copyRangeTo(stackFrame, range,
-                    1 /* referencesStart */, 0 /* stackFrameStart */);
+            emulatedStackFrame.copyRangeTo(
+                    stackFrame, range, 1 /* referencesStart */, 0 /* stackFrameStart */);
 
             // Perform the invoke.
-            delegate.invoke(stackFrame);
+            invokeFromTransform(delegate, stackFrame);
             stackFrame.copyReturnValueTo(emulatedStackFrame);
         }
     }
 
-    /**
-     * Implements MethodHandle.filterReturnValue.
-     */
-    public static class FilterReturnValue extends Transformer {
+    /** Implements {@code MethodHandle.filterReturnValue}. */
+    static class FilterReturnValue extends Transformer {
         private final MethodHandle target;
         private final MethodHandle filter;
 
         private final EmulatedStackFrame.Range allArgs;
 
-        public FilterReturnValue(MethodHandle target, MethodHandle filter) {
+        FilterReturnValue(MethodHandle target, MethodHandle filter) {
             super(MethodType.methodType(filter.type().rtype(), target.type().ptypes()));
 
             this.target = target;
@@ -502,56 +578,33 @@
             // the same parameter shapes.
             EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
             emulatedStackFrame.copyRangeTo(targetFrame, allArgs, 0, 0);
-            target.invoke(targetFrame);
+            invokeFromTransform(target, targetFrame);
 
-            // Perform the invoke.
-            final StackFrameReader returnValueReader = new StackFrameReader();
-            returnValueReader.attach(targetFrame);
-            returnValueReader.makeReturnValueAccessor();
+            // Create an emulated frame for the filter and move the return value from
+            // target to the argument of the filter.
+            final EmulatedStackFrame filterFrame = EmulatedStackFrame.create(filter.type());
+            final Class<?> filterArgumentType = target.type().rtype();
+            if (filterArgumentType != void.class) {
+                final StackFrameReader returnValueReader = new StackFrameReader();
+                returnValueReader.attach(targetFrame).makeReturnValueAccessor();
 
-            // Create an emulated frame for the filter and copy all its arguments across.
-            EmulatedStackFrame filterFrame = EmulatedStackFrame.create(filter.type());
-            final StackFrameWriter filterWriter = new StackFrameWriter();
-            filterWriter.attach(filterFrame);
-
-            final Class<?> returnType = target.type().rtype();
-            if (!returnType.isPrimitive()) {
-                filterWriter.putNextReference(returnValueReader.nextReference(returnType),
-                        returnType);
-            } else if (returnType == boolean.class) {
-                filterWriter.putNextBoolean(returnValueReader.nextBoolean());
-            } else if (returnType == byte.class) {
-                filterWriter.putNextByte(returnValueReader.nextByte());
-            } else if (returnType == char.class) {
-                filterWriter.putNextChar(returnValueReader.nextChar());
-            } else if (returnType == short.class) {
-                filterWriter.putNextShort(returnValueReader.nextShort());
-            } else if (returnType == int.class) {
-                filterWriter.putNextInt(returnValueReader.nextInt());
-            } else if (returnType == long.class) {
-                filterWriter.putNextLong(returnValueReader.nextLong());
-            } else if (returnType == float.class) {
-                filterWriter.putNextFloat(returnValueReader.nextFloat());
-            } else if (returnType == double.class) {
-                filterWriter.putNextDouble(returnValueReader.nextDouble());
+                final StackFrameWriter filterWriter = new StackFrameWriter();
+                filterWriter.attach(filterFrame);
+                StackFrameAccessor.copyNext(returnValueReader, filterWriter, filterArgumentType);
             }
 
             // Invoke the filter and copy its return value back to the original frame.
-            filter.invoke(filterFrame);
+            invokeExactFromTransform(filter, filterFrame);
             filterFrame.copyReturnValueTo(emulatedStackFrame);
         }
     }
 
-    /*
-     * Implements MethodHandles.permuteArguments.
-     *
-     * @hide
-     */
-    public static class PermuteArguments extends Transformer {
+    /** Implements {@code MethodHandles.permuteArguments}. */
+    static class PermuteArguments extends Transformer {
         private final MethodHandle target;
         private final int[] reorder;
 
-        public PermuteArguments(MethodType type, MethodHandle target, int[] reorder) {
+        PermuteArguments(MethodType type, MethodHandle target, int[] reorder) {
             super(type);
 
             this.target = target;
@@ -560,93 +613,39 @@
 
         @Override
         public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
-            final StackFrameReader reader = new StackFrameReader();
+            final RandomOrderStackFrameReader reader = new RandomOrderStackFrameReader();
             reader.attach(emulatedStackFrame);
 
-            // In the interests of simplicity, we box / unbox arguments while performing
-            // the permutation. We first iterate through the incoming stack frame and box
-            // each argument. We then unbox and write out the argument to the target frame
-            // according to the specified reordering.
-            Object[] arguments = new Object[reorder.length];
-            final Class<?>[] ptypes = type().ptypes();
-            for (int i = 0; i < ptypes.length; ++i) {
-                final Class<?> ptype = ptypes[i];
-                if (!ptype.isPrimitive()) {
-                    arguments[i] = reader.nextReference(ptype);
-                } else if (ptype == boolean.class) {
-                    arguments[i] = reader.nextBoolean();
-                } else if (ptype == byte.class) {
-                    arguments[i] = reader.nextByte();
-                } else if (ptype == char.class) {
-                    arguments[i] = reader.nextChar();
-                } else if (ptype == short.class) {
-                    arguments[i] = reader.nextShort();
-                } else if (ptype == int.class) {
-                    arguments[i] = reader.nextInt();
-                } else if (ptype == long.class) {
-                    arguments[i] = reader.nextLong();
-                } else if (ptype == float.class) {
-                    arguments[i] = reader.nextFloat();
-                } else if (ptype == double.class) {
-                    arguments[i] = reader.nextDouble();
-                } else {
-                    throw new AssertionError("Unexpected type: " + ptype);
-                }
-            }
-
-            EmulatedStackFrame calleeFrame = EmulatedStackFrame.create(target.type());
+            final EmulatedStackFrame calleeFrame = EmulatedStackFrame.create(target.type());
             final StackFrameWriter writer = new StackFrameWriter();
             writer.attach(calleeFrame);
 
-            for (int i = 0; i < ptypes.length; ++i) {
-                int idx = reorder[i];
-                final Class<?> ptype = ptypes[idx];
-                final Object argument = arguments[idx];
-
-                if (!ptype.isPrimitive()) {
-                    writer.putNextReference(argument, ptype);
-                } else if (ptype == boolean.class) {
-                    writer.putNextBoolean((boolean) argument);
-                } else if (ptype == byte.class) {
-                    writer.putNextByte((byte) argument);
-                } else if (ptype == char.class) {
-                    writer.putNextChar((char) argument);
-                } else if (ptype == short.class) {
-                    writer.putNextShort((short) argument);
-                } else if (ptype == int.class) {
-                    writer.putNextInt((int) argument);
-                } else if (ptype == long.class) {
-                    writer.putNextLong((long) argument);
-                } else if (ptype == float.class) {
-                    writer.putNextFloat((float) argument);
-                } else if (ptype == double.class) {
-                    writer.putNextDouble((double) argument);
-                } else {
-                    throw new AssertionError("Unexpected type: " + ptype);
-                }
+            final Class<?> [] ptypes = emulatedStackFrame.getMethodType().parameterArray();
+            for (int i = 0; i < reorder.length; ++i) {
+                final int readerIndex = reorder[i];
+                reader.moveTo(readerIndex);
+                StackFrameAccessor.copyNext(reader, writer, ptypes[readerIndex]);
             }
 
-            target.invoke(calleeFrame);
+            invokeFromTransform(target, calleeFrame);
             calleeFrame.copyReturnValueTo(emulatedStackFrame);
         }
     }
 
-    /**
-     * Converts methods with a trailing array argument to variable arity
-     * methods. So (A,B,C[])R can be invoked with any number of convertible
-     * arguments after B, e.g. (A,B)R or (A, B, C0)R or (A, B, C0...Cn)R.
-     *
-     * @hide
-     */
-    /*package*/ static class VarargsCollector extends Transformer {
+    /** Implements {@code MethodHandle.asVarargsCollector}. */
+    static class VarargsCollector extends Transformer {
         final MethodHandle target;
+        private final Class<?> arrayType;
 
-        /*package*/ VarargsCollector(MethodHandle target) {
-            super(target.type(), MethodHandle.INVOKE_CALLSITE_TRANSFORM);
-            if (!lastParameterTypeIsAnArray(target.type().ptypes())) {
+        VarargsCollector(MethodHandle target) {
+            super(target.type());
+
+            Class<?>[] parameterTypes = target.type().ptypes();
+            if (!lastParameterTypeIsAnArray(parameterTypes)) {
                 throw new IllegalArgumentException("target does not have array as last parameter");
             }
             this.target = target;
+            this.arrayType = parameterTypes[parameterTypes.length - 1];
         }
 
         private static boolean lastParameterTypeIsAnArray(Class<?>[] parameterTypes) {
@@ -655,10 +654,52 @@
         }
 
         @Override
-        public boolean isVarargsCollector() { return true; }
+        public boolean isVarargsCollector() {
+            return true;
+        }
 
         @Override
-        public MethodHandle asFixedArity() { return target; }
+        public MethodHandle asFixedArity() {
+            return target;
+        }
+
+        @Override
+        MethodHandle asTypeUncached(MethodType newType) {
+            // asType() behavior is specialized per:
+            //
+            // https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/MethodHandle.html#asVarargsCollector(java.lang.Class)
+            //
+            // "The behavior of asType is also specialized for variable arity adapters, to maintain
+            //  the invariant that plain, inexact invoke is always equivalent to an asType call to
+            //  adjust the target type, followed by invokeExact. Therefore, a variable arity
+            //  adapter responds to an asType request by building a fixed arity collector, if and
+            //  only if the adapter and requested type differ either in arity or trailing argument
+            //  type. The resulting fixed arity collector has its type further adjusted
+            //  (if necessary) to the requested type by pairwise conversion, as if by another
+            //  application of asType."
+            final MethodType currentType = type();
+            final MethodHandle currentFixedArity = asFixedArity();
+            if (currentType.parameterCount() == newType.parameterCount()
+                    && currentType
+                            .lastParameterType()
+                            .isAssignableFrom(newType.lastParameterType())) {
+                return asTypeCache = currentFixedArity.asType(newType);
+            }
+
+            final int arrayLength = newType.parameterCount() - currentType.parameterCount() + 1;
+            if (arrayLength < 0) {
+                // arrayType is definitely array per VarargsCollector constructor.
+                throwWrongMethodTypeException(currentType, newType);
+            }
+
+            MethodHandle collector = null;
+            try {
+                collector = currentFixedArity.asCollector(arrayType, arrayLength).asType(newType);
+            } catch (IllegalArgumentException ex) {
+                throwWrongMethodTypeException(currentType, newType);
+            }
+            return asTypeCache = collector;
+        }
 
         @Override
         public void transform(EmulatedStackFrame callerFrame) throws Throwable {
@@ -667,12 +708,13 @@
             Class<?>[] targetPTypes = type().ptypes();
 
             int lastTargetIndex = targetPTypes.length - 1;
-            if (callerPTypes.length == targetPTypes.length &&
-                targetPTypes[lastTargetIndex].isAssignableFrom(callerPTypes[lastTargetIndex])) {
+            if (callerPTypes.length == targetPTypes.length
+                    && targetPTypes[lastTargetIndex].isAssignableFrom(
+                            callerPTypes[lastTargetIndex])) {
                 // Caller frame matches target frame in the arity array parameter. Invoke
                 // immediately, and let the invoke() dispatch perform any necessary conversions
                 // on the other parameters present.
-                target.invoke(callerFrame);
+                invokeFromTransform(target, callerFrame);
                 return;
             }
 
@@ -698,21 +740,26 @@
             prepareFrame(callerFrame, targetFrame);
 
             // Invoke target.
-            target.invoke(targetFrame);
+            invokeExactFromTransform(target, targetFrame);
 
             // Copy return value to the caller's frame.
             targetFrame.copyReturnValueTo(callerFrame);
         }
 
+        @Override
+        public MethodHandle withVarargs(boolean makeVarargs) {
+            return makeVarargs ? this : target;
+        }
+
         private static void throwWrongMethodTypeException(MethodType from, MethodType to) {
             throw new WrongMethodTypeException("Cannot convert " + from + " to " + to);
         }
 
-        private static boolean arityArgumentsConvertible(Class<?>[] ptypes, int arityStart,
-                                                         Class<?> elementType) {
+        private static boolean arityArgumentsConvertible(
+                Class<?>[] ptypes, int arityStart, Class<?> elementType) {
             if (ptypes.length - 1 == arityStart) {
-                if (ptypes[arityStart].isArray() &&
-                    ptypes[arityStart].getComponentType() == elementType) {
+                if (ptypes[arityStart].isArray()
+                        && ptypes[arityStart].getComponentType() == elementType) {
                     // The last ptype is in the same position as the arity
                     // array and has the same type.
                     return true;
@@ -727,112 +774,162 @@
             return true;
         }
 
-        private static Object referenceArray(StackFrameReader reader, Class<?>[] ptypes,
-                                             Class<?> elementType, int offset, int length) {
+        private static Object referenceArray(
+                StackFrameReader reader,
+                Class<?>[] ptypes,
+                Class<?> elementType,
+                int offset,
+                int length) {
             Object arityArray = Array.newInstance(elementType, length);
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 Object o = null;
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { o = reader.nextReference(argumentType); break; }
-                    case 'I': { o = reader.nextInt(); break; }
-                    case 'J': { o = reader.nextLong(); break; }
-                    case 'B': { o = reader.nextByte(); break; }
-                    case 'S': { o = reader.nextShort(); break; }
-                    case 'C': { o = reader.nextChar(); break; }
-                    case 'Z': { o = reader.nextBoolean(); break; }
-                    case 'F': { o = reader.nextFloat(); break; }
-                    case 'D': { o = reader.nextDouble(); break; }
+                    case 'L':
+                        o = reader.nextReference(argumentType);
+                        break;
+                    case 'I':
+                        o = reader.nextInt();
+                        break;
+                    case 'J':
+                        o = reader.nextLong();
+                        break;
+                    case 'B':
+                        o = reader.nextByte();
+                        break;
+                    case 'S':
+                        o = reader.nextShort();
+                        break;
+                    case 'C':
+                        o = reader.nextChar();
+                        break;
+                    case 'Z':
+                        o = reader.nextBoolean();
+                        break;
+                    case 'F':
+                        o = reader.nextFloat();
+                        break;
+                    case 'D':
+                        o = reader.nextDouble();
+                        break;
                 }
                 Array.set(arityArray, i, elementType.cast(o));
             }
             return arityArray;
         }
 
-        private static Object intArray(StackFrameReader reader, Class<?> ptypes[],
-                                       int offset, int length) {
+        private static Object intArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             int[] arityArray = new int[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'I': { arityArray[i] = reader.nextInt(); break; }
-                    case 'S': { arityArray[i] = reader.nextShort(); break; }
-                    case 'B': { arityArray[i] = reader.nextByte(); break; }
-                    default: {
+                    case 'I':
+                        arityArray[i] = reader.nextInt();
+                        break;
+                    case 'S':
+                        arityArray[i] = reader.nextShort();
+                        break;
+                    case 'B':
+                        arityArray[i] = reader.nextByte();
+                        break;
+                    default:
                         arityArray[i] = (Integer) reader.nextReference(argumentType);
                         break;
-                    }
                 }
             }
             return arityArray;
         }
 
-        private static Object longArray(StackFrameReader reader, Class<?> ptypes[],
-                                        int offset, int length) {
+        private static Object longArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             long[] arityArray = new long[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'J': { arityArray[i] = reader.nextLong(); break; }
-                    case 'I': { arityArray[i] = reader.nextInt(); break; }
-                    case 'S': { arityArray[i] = reader.nextShort(); break; }
-                    case 'B': { arityArray[i] = reader.nextByte(); break; }
-                    default: { arityArray[i] = (Long) reader.nextReference(argumentType); break; }
+                    case 'J':
+                        arityArray[i] = reader.nextLong();
+                        break;
+                    case 'I':
+                        arityArray[i] = reader.nextInt();
+                        break;
+                    case 'S':
+                        arityArray[i] = reader.nextShort();
+                        break;
+                    case 'B':
+                        arityArray[i] = reader.nextByte();
+                        break;
+                    default:
+                        arityArray[i] = (Long) reader.nextReference(argumentType);
+                        break;
                 }
             }
             return arityArray;
         }
 
-        private static Object byteArray(StackFrameReader reader, Class<?> ptypes[],
-                                        int offset, int length) {
+        private static Object byteArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             byte[] arityArray = new byte[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'B': { arityArray[i] = reader.nextByte(); break; }
-                    default: { arityArray[i] = (Byte) reader.nextReference(argumentType); break; }
+                    case 'B':
+                        arityArray[i] = reader.nextByte();
+                        break;
+                    default:
+                        arityArray[i] = (Byte) reader.nextReference(argumentType);
+                        break;
                 }
             }
             return arityArray;
         }
 
-        private static Object shortArray(StackFrameReader reader, Class<?> ptypes[],
-                                        int offset, int length) {
+        private static Object shortArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             short[] arityArray = new short[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'S': { arityArray[i] = reader.nextShort(); break; }
-                    case 'B': { arityArray[i] = reader.nextByte(); break; }
-                    default: { arityArray[i] = (Short) reader.nextReference(argumentType); break; }
+                    case 'S':
+                        arityArray[i] = reader.nextShort();
+                        break;
+                    case 'B':
+                        arityArray[i] = reader.nextByte();
+                        break;
+                    default:
+                        arityArray[i] = (Short) reader.nextReference(argumentType);
+                        break;
                 }
             }
             return arityArray;
         }
 
-        private static Object charArray(StackFrameReader reader, Class<?> ptypes[],
-                                        int offset, int length) {
+        private static Object charArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             char[] arityArray = new char[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'C': { arityArray[i] = reader.nextChar(); break; }
-                    default: {
+                    case 'C':
+                        arityArray[i] = reader.nextChar();
+                        break;
+                    default:
                         arityArray[i] = (Character) reader.nextReference(argumentType);
                         break;
-                    }
                 }
             }
             return arityArray;
         }
 
-        private static Object booleanArray(StackFrameReader reader, Class<?> ptypes[],
-                                        int offset, int length) {
+        private static Object booleanArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             boolean[] arityArray = new boolean[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'Z': { arityArray[i] = reader.nextBoolean(); break; }
+                    case 'Z':
+                        arityArray[i] = reader.nextBoolean();
+                        break;
                     default:
                         arityArray[i] = (Boolean) reader.nextReference(argumentType);
                         break;
@@ -841,114 +938,188 @@
             return arityArray;
         }
 
-        private static Object floatArray(StackFrameReader reader, Class<?> ptypes[],
-                                        int offset, int length) {
+        private static Object floatArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             float[] arityArray = new float[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'F': { arityArray[i] = reader.nextFloat(); break; }
-                    case 'J': { arityArray[i] = reader.nextLong(); break; }
-                    case 'I': { arityArray[i] = reader.nextInt(); break; }
-                    case 'S': { arityArray[i] = reader.nextShort(); break; }
-                    case 'B': { arityArray[i] = reader.nextByte(); break; }
-                    default: {
+                    case 'F':
+                        arityArray[i] = reader.nextFloat();
+                        break;
+                    case 'J':
+                        arityArray[i] = reader.nextLong();
+                        break;
+                    case 'I':
+                        arityArray[i] = reader.nextInt();
+                        break;
+                    case 'S':
+                        arityArray[i] = reader.nextShort();
+                        break;
+                    case 'B':
+                        arityArray[i] = reader.nextByte();
+                        break;
+                    default:
                         arityArray[i] = (Float) reader.nextReference(argumentType);
                         break;
-                    }
                 }
             }
             return arityArray;
         }
 
-        private static Object doubleArray(StackFrameReader reader, Class<?> ptypes[],
-                                        int offset, int length) {
+        private static Object doubleArray(
+                StackFrameReader reader, Class<?> ptypes[], int offset, int length) {
             double[] arityArray = new double[length];
             for (int i = 0; i < length; ++i) {
                 Class<?> argumentType = ptypes[i + offset];
                 switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'D': { arityArray[i] = reader.nextDouble(); break; }
-                    case 'F': { arityArray[i] = reader.nextFloat(); break; }
-                    case 'J': { arityArray[i] = reader.nextLong(); break; }
-                    case 'I': { arityArray[i] = reader.nextInt(); break; }
-                    case 'S': { arityArray[i] = reader.nextShort(); break; }
-                    case 'B': { arityArray[i] = reader.nextByte(); break; }
-                    default: {
+                    case 'D':
+                        arityArray[i] = reader.nextDouble();
+                        break;
+                    case 'F':
+                        arityArray[i] = reader.nextFloat();
+                        break;
+                    case 'J':
+                        arityArray[i] = reader.nextLong();
+                        break;
+                    case 'I':
+                        arityArray[i] = reader.nextInt();
+                        break;
+                    case 'S':
+                        arityArray[i] = reader.nextShort();
+                        break;
+                    case 'B':
+                        arityArray[i] = reader.nextByte();
+                        break;
+                    default:
                         arityArray[i] = (Double) reader.nextReference(argumentType);
                         break;
-                    }
                 }
             }
             return arityArray;
         }
 
-        private static Object makeArityArray(MethodType callerFrameType,
-                                             StackFrameReader callerFrameReader,
-                                             int indexOfArityArray,
-                                             Class<?> arityArrayType) {
+        private static Object makeArityArray(
+                MethodType callerFrameType,
+                StackFrameReader callerFrameReader,
+                int indexOfArityArray,
+                Class<?> arityArrayType) {
             int arityArrayLength = callerFrameType.ptypes().length - indexOfArityArray;
             Class<?> elementType = arityArrayType.getComponentType();
             Class<?>[] callerPTypes = callerFrameType.ptypes();
 
             char elementBasicType = Wrapper.basicTypeChar(elementType);
             switch (elementBasicType) {
-                case 'L': return referenceArray(callerFrameReader, callerPTypes, elementType,
-                                                indexOfArityArray, arityArrayLength);
-                case 'I': return intArray(callerFrameReader, callerPTypes,
-                                          indexOfArityArray, arityArrayLength);
-                case 'J': return longArray(callerFrameReader, callerPTypes,
-                                           indexOfArityArray, arityArrayLength);
-                case 'B': return byteArray(callerFrameReader, callerPTypes,
-                                           indexOfArityArray, arityArrayLength);
-                case 'S': return shortArray(callerFrameReader, callerPTypes,
-                                            indexOfArityArray, arityArrayLength);
-                case 'C': return charArray(callerFrameReader, callerPTypes,
-                                           indexOfArityArray, arityArrayLength);
-                case 'Z': return booleanArray(callerFrameReader, callerPTypes,
-                                              indexOfArityArray, arityArrayLength);
-                case 'F': return floatArray(callerFrameReader, callerPTypes,
-                                            indexOfArityArray, arityArrayLength);
-                case 'D': return doubleArray(callerFrameReader, callerPTypes,
-                                             indexOfArityArray, arityArrayLength);
+                case 'L':
+                    return referenceArray(
+                            callerFrameReader,
+                            callerPTypes,
+                            elementType,
+                            indexOfArityArray,
+                            arityArrayLength);
+                case 'I':
+                    return intArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
+                case 'J':
+                    return longArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
+                case 'B':
+                    return byteArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
+                case 'S':
+                    return shortArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
+                case 'C':
+                    return charArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
+                case 'Z':
+                    return booleanArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
+                case 'F':
+                    return floatArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
+                case 'D':
+                    return doubleArray(
+                            callerFrameReader, callerPTypes,
+                            indexOfArityArray, arityArrayLength);
             }
             throw new InternalError("Unexpected type: " + elementType);
         }
 
-        public static Object collectArguments(char basicComponentType, Class<?> componentType,
-                                              StackFrameReader reader, Class<?>[] types,
-                                              int startIdx, int length) {
+        public static Object collectArguments(
+                char basicComponentType,
+                Class<?> componentType,
+                StackFrameReader reader,
+                Class<?>[] types,
+                int startIdx,
+                int length) {
             switch (basicComponentType) {
-                case 'L': return referenceArray(reader, types, componentType, startIdx, length);
-                case 'I': return intArray(reader, types, startIdx, length);
-                case 'J': return longArray(reader, types, startIdx, length);
-                case 'B': return byteArray(reader, types, startIdx, length);
-                case 'S': return shortArray(reader, types, startIdx, length);
-                case 'C': return charArray(reader, types, startIdx, length);
-                case 'Z': return booleanArray(reader, types, startIdx, length);
-                case 'F': return floatArray(reader, types, startIdx, length);
-                case 'D': return doubleArray(reader, types, startIdx, length);
+                case 'L':
+                    return referenceArray(reader, types, componentType, startIdx, length);
+                case 'I':
+                    return intArray(reader, types, startIdx, length);
+                case 'J':
+                    return longArray(reader, types, startIdx, length);
+                case 'B':
+                    return byteArray(reader, types, startIdx, length);
+                case 'S':
+                    return shortArray(reader, types, startIdx, length);
+                case 'C':
+                    return charArray(reader, types, startIdx, length);
+                case 'Z':
+                    return booleanArray(reader, types, startIdx, length);
+                case 'F':
+                    return floatArray(reader, types, startIdx, length);
+                case 'D':
+                    return doubleArray(reader, types, startIdx, length);
             }
             throw new InternalError("Unexpected type: " + basicComponentType);
         }
 
-        private static void copyParameter(StackFrameReader reader, StackFrameWriter writer,
-                                          Class<?> ptype) {
+        private static void copyParameter(
+                StackFrameReader reader, StackFrameWriter writer, Class<?> ptype) {
             switch (Wrapper.basicTypeChar(ptype)) {
-                case 'L': { writer.putNextReference(reader.nextReference(ptype), ptype); break; }
-                case 'I': { writer.putNextInt(reader.nextInt()); break; }
-                case 'J': { writer.putNextLong(reader.nextLong()); break; }
-                case 'B': { writer.putNextByte(reader.nextByte()); break; }
-                case 'S': { writer.putNextShort(reader.nextShort()); break; }
-                case 'C': { writer.putNextChar(reader.nextChar()); break; }
-                case 'Z': { writer.putNextBoolean(reader.nextBoolean()); break; }
-                case 'F': { writer.putNextFloat(reader.nextFloat()); break; }
-                case 'D': { writer.putNextDouble(reader.nextDouble()); break; }
-                default: throw new InternalError("Unexpected type: " + ptype);
+                case 'L':
+                    writer.putNextReference(reader.nextReference(ptype), ptype);
+                    break;
+                case 'I':
+                    writer.putNextInt(reader.nextInt());
+                    break;
+                case 'J':
+                    writer.putNextLong(reader.nextLong());
+                    break;
+                case 'B':
+                    writer.putNextByte(reader.nextByte());
+                    break;
+                case 'S':
+                    writer.putNextShort(reader.nextShort());
+                    break;
+                case 'C':
+                    writer.putNextChar(reader.nextChar());
+                    break;
+                case 'Z':
+                    writer.putNextBoolean(reader.nextBoolean());
+                    break;
+                case 'F':
+                    writer.putNextFloat(reader.nextFloat());
+                    break;
+                case 'D':
+                    writer.putNextDouble(reader.nextDouble());
+                    break;
+                default:
+                    throw new InternalError("Unexpected type: " + ptype);
             }
         }
 
-        private static void prepareFrame(EmulatedStackFrame callerFrame,
-                                         EmulatedStackFrame targetFrame) {
+        private static void prepareFrame(
+                EmulatedStackFrame callerFrame, EmulatedStackFrame targetFrame) {
             StackFrameWriter targetWriter = new StackFrameWriter();
             targetWriter.attach(targetFrame);
             StackFrameReader callerReader = new StackFrameReader();
@@ -964,22 +1135,25 @@
 
             // Add arity array as last parameter in |targetFrame|.
             Class<?> arityArrayType = targetMethodType.ptypes()[indexOfArityArray];
-            Object arityArray = makeArityArray(callerFrame.getMethodType(), callerReader,
-                                               indexOfArityArray, arityArrayType);
+            Object arityArray =
+                    makeArityArray(
+                            callerFrame.getMethodType(),
+                            callerReader,
+                            indexOfArityArray,
+                            arityArrayType);
             targetWriter.putNextReference(arityArray, arityArrayType);
         }
 
         /**
-         * Computes the frame type to invoke the target method handle with. This
-         * is the same as the caller frame type, but with the trailing argument
-         * being the array type that is the trailing argument in the target method
-         * handle.
+         * Computes the frame type to invoke the target method handle with. This is the same as the
+         * caller frame type, but with the trailing argument being the array type that is the
+         * trailing argument in the target method handle.
          *
-         * Suppose the targetType is (T0, T1, T2[])RT and the callerType is (C0, C1, C2, C3)RC
+         * <p>Suppose the targetType is (T0, T1, T2[])RT and the callerType is (C0, C1, C2, C3)RC
          * then the constructed type is (C0, C1, T2[])RC.
          */
-        private static MethodType makeTargetFrameType(MethodType callerType,
-                                                      MethodType targetType) {
+        private static MethodType makeTargetFrameType(
+                MethodType callerType, MethodType targetType) {
             final int ptypesLength = targetType.ptypes().length;
             final Class<?>[] ptypes = new Class<?>[ptypesLength];
             // Copy types from caller types to new methodType.
@@ -991,9 +1165,7 @@
         }
     }
 
-    /**
-     * Implements MethodHandles.invoker & MethodHandles.exactInvoker.
-     */
+    /** Implements {@code MethodHandles.invoker} and {@code MethodHandles.exactInvoker}. */
     static class Invoker extends Transformer {
         private final MethodType targetType;
         private final boolean isExactInvoker;
@@ -1003,23 +1175,11 @@
             super(targetType.insertParameterTypes(0, MethodHandle.class));
             this.targetType = targetType;
             this.isExactInvoker = isExactInvoker;
-            copyRange = EmulatedStackFrame.Range.of(type(), 1, type().parameterCount());
+            copyRange = EmulatedStackFrame.Range.from(type(), 1);
         }
 
         @Override
         public void transform(EmulatedStackFrame emulatedStackFrame) throws Throwable {
-            // We need to artifically throw a WrongMethodTypeException here because we
-            // can't call invokeExact on the target inside the transformer.
-            if (isExactInvoker) {
-                // TODO: We should do the comparison by hand if this new type creation
-                // on every invoke proves too expensive.
-                MethodType callType = emulatedStackFrame.getCallsiteType().dropParameterTypes(0, 1);
-                if (!targetType.equals(callType)) {
-                    throw new WrongMethodTypeException("Wrong type, Expected: " + targetType
-                            + " was: " + callType);
-                }
-            }
-
             // The first argument to the stack frame is the handle that needs to be invoked.
             MethodHandle target = emulatedStackFrame.getReference(0, MethodHandle.class);
 
@@ -1028,426 +1188,373 @@
             emulatedStackFrame.copyRangeTo(targetFrame, copyRange, 0, 0);
 
             // Finally, invoke the handle and copy the return value.
-            target.invoke(targetFrame);
+            if (isExactInvoker) {
+                invokeExactFromTransform(target, targetFrame);
+            } else {
+                invokeFromTransform(target, targetFrame);
+            }
             targetFrame.copyReturnValueTo(emulatedStackFrame);
         }
+
+        /**
+         * Checks whether two method types are compatible as an exact match. The exact match is
+         * based on the erased form (all reference types treated as Object).
+         *
+         * @param callsiteType the MethodType associated with the invocation.
+         * @param targetType the MethodType of the MethodHandle being invoked.
+         * @return true if {@code callsiteType} and {@code targetType} are an exact match.
+         */
+        private static boolean exactMatch(MethodType callsiteType, MethodType targetType) {
+            final int parameterCount = callsiteType.parameterCount();
+            if (callsiteType.parameterCount() != targetType.parameterCount()) {
+                return false;
+            }
+
+            for (int i = 0; i < parameterCount; ++i) {
+                Class argumentType = callsiteType.parameterType(i);
+                Class parameterType = targetType.parameterType(i);
+                if (!exactMatch(argumentType, parameterType)) {
+                    return false;
+                }
+            }
+            // Check return type, noting it's always okay to discard the return value.
+            return callsiteType.returnType() == Void.TYPE
+                    || exactMatch(callsiteType.returnType(), targetType.returnType());
+        }
+
+        /**
+         * Checks whether two types are an exact match. The exact match is based on the erased types
+         * so any two reference types match, but primitive types must be the same.
+         *
+         * @param lhs first class to compare.
+         * @param rhs second class to compare.
+         * @return true if both classes satisfy the exact match criteria.
+         */
+        private static boolean exactMatch(Class lhs, Class rhs) {
+            if (lhs.isPrimitive() || rhs.isPrimitive()) {
+                return lhs == rhs;
+            }
+            return true; // Both types are references, compatibility is checked at the point of use.
+        }
     }
 
-    /**
-     * Implements MethodHandle.asSpreader / MethodHandles.spreadInvoker.
-     */
+    /** Implements {@code MethodHandle.asSpreader}. */
     static class Spreader extends Transformer {
         /** The method handle we're delegating to. */
         private final MethodHandle target;
 
         /**
-         * The offset of the trailing array argument in the list of arguments to
-         * this transformer. The array argument is always the last argument.
+         * The offset of the trailing array argument in the list of arguments to this transformer.
+         * The array argument is always the last argument.
          */
         private final int arrayOffset;
 
-        /**
-         * The type char of the component type of the array.
-         */
-        private final char arrayTypeChar;
+        /** The component type of the array. */
+        private final Class<?> componentType;
 
         /**
-         * The number of input arguments that will be present in the array. In other words,
-         * this is the expected array length.
+         * The number of input arguments that will be present in the array. In other words, this is
+         * the expected array length.
          */
         private final int numArrayArgs;
 
         /**
-         * Range of arguments to copy verbatim from the input frame, This will cover all
-         * arguments that aren't a part of the trailing array.
+         * Range of arguments to copy verbatim from the input frame, This will cover all arguments
+         * that aren't a part of the trailing array.
          */
-        private final Range copyRange;
+        private final Range leadingRange;
+        private final Range trailingRange;
 
-        Spreader(MethodHandle target, MethodType spreaderType, int numArrayArgs) {
+        Spreader(MethodHandle target, MethodType spreaderType, int spreadArgPos, int numArrayArgs) {
             super(spreaderType);
             this.target = target;
-            // Copy all arguments except the last argument (which is the trailing array argument
-            // that needs to be spread).
-            arrayOffset = spreaderType.parameterCount() - 1;
-
-            // Get and cache the component type of the input array.
-            final Class<?> componentType = spreaderType.ptypes()[arrayOffset].getComponentType();
+            arrayOffset = spreadArgPos;
+            componentType = spreaderType.ptypes()[arrayOffset].getComponentType();
             if (componentType == null) {
-                throw new AssertionError("Trailing argument must be an array.");
+                throw new AssertionError("Argument " + spreadArgPos + " must be an array.");
             }
-            arrayTypeChar = Wrapper.basicTypeChar(componentType);
-
             this.numArrayArgs = numArrayArgs;
-            // Copy all args except for the last argument.
-            this.copyRange = EmulatedStackFrame.Range.of(spreaderType, 0, arrayOffset);
+            // Copy all args except the spreader array.
+            leadingRange = EmulatedStackFrame.Range.of(spreaderType, 0, arrayOffset);
+            trailingRange = EmulatedStackFrame.Range.from(spreaderType, arrayOffset + 1);
         }
 
         @Override
         public void transform(EmulatedStackFrame callerFrame) throws Throwable {
+            // Get the array reference and check that its length is as expected.
+            final Class<?> arrayType = type().parameterType(arrayOffset);
+            final Object arrayObj = callerFrame.getReference(arrayOffset, arrayType);
+
+            // The incoming array may be null if the expected number of array arguments is zero.
+            final int arrayLength =
+                (numArrayArgs == 0 && arrayObj == null) ? 0 : Array.getLength(arrayObj);
+            if (arrayLength != numArrayArgs) {
+                throw new IllegalArgumentException(
+                        "Invalid array length " + arrayLength + " expected " + numArrayArgs);
+            }
+
             // Create a new stack frame for the callee.
             EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
 
-            // Copy all arguments except for the trailing array argument.
-            callerFrame.copyRangeTo(targetFrame, copyRange, 0, 0);
-
-            // Attach the writer, prepare to spread the trailing array arguments into
-            // the callee frame.
-            StackFrameWriter writer = new StackFrameWriter();
-            writer.attach(targetFrame,
-                    arrayOffset,
-                    copyRange.numReferences,
-                    copyRange.numBytes);
-
-            // Get the array reference and check that its length is as expected.
-            Object arrayObj = callerFrame.getReference(
-                    copyRange.numReferences, this.type().ptypes()[arrayOffset]);
-            final int arrayLength = Array.getLength(arrayObj);
-            if (arrayLength != numArrayArgs) {
-                throw new IllegalArgumentException("Invalid array length: " + arrayLength);
+            // Copy ranges not affected by the spreading.
+            callerFrame.copyRangeTo(targetFrame, leadingRange, 0, 0);
+            if (componentType.isPrimitive()) {
+                final int elementBytes = EmulatedStackFrame.getSize(componentType);
+                final int spreadBytes = elementBytes * arrayLength;
+                callerFrame.copyRangeTo(targetFrame, trailingRange,
+                    leadingRange.numReferences, leadingRange.numBytes + spreadBytes);
+            } else {
+                callerFrame.copyRangeTo(targetFrame, trailingRange,
+                    leadingRange.numReferences + numArrayArgs, leadingRange.numBytes);
             }
 
-            final MethodType type = target.type();
-            switch (arrayTypeChar) {
-                case 'L':
-                    spreadArray((Object[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'I':
-                    spreadArray((int[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'J':
-                    spreadArray((long[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'B':
-                    spreadArray((byte[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'S':
-                    spreadArray((short[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'C':
-                    spreadArray((char[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'Z':
-                    spreadArray((boolean[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'F':
-                    spreadArray((float[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-                case 'D':
-                    spreadArray((double[]) arrayObj, writer, type, numArrayArgs, arrayOffset);
-                    break;
-
+            if (arrayLength != 0) {
+                StackFrameWriter writer = new StackFrameWriter();
+                writer.attach(targetFrame,
+                              arrayOffset,
+                              leadingRange.numReferences,
+                              leadingRange.numBytes);
+                spreadArray(arrayType, arrayObj, writer);
             }
 
-            target.invoke(targetFrame);
+            invokeExactFromTransform(target, targetFrame);
             targetFrame.copyReturnValueTo(callerFrame);
         }
 
-        public static void spreadArray(Object[] array, StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                Object o = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(o, argumentType); break; }
-                    case 'I': { writer.putNextInt((int) o); break; }
-                    case 'J': { writer.putNextLong((long) o); break; }
-                    case 'B': { writer.putNextByte((byte) o); break; }
-                    case 'S': { writer.putNextShort((short) o); break; }
-                    case 'C': { writer.putNextChar((char) o); break; }
-                    case 'Z': { writer.putNextBoolean((boolean) o); break; }
-                    case 'F': { writer.putNextFloat((float) o); break; }
-                    case 'D': { writer.putNextDouble((double) o); break; }
+        private void spreadArray(Class<?> arrayType, Object arrayObj, StackFrameWriter writer) {
+            final Class<?> componentType = arrayType.getComponentType();
+            switch (Wrapper.basicTypeChar(componentType)) {
+                case 'L':
+                {
+                    final Object[] array = (Object[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextReference(array[i], componentType);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(int[] array, StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                int j = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(j, argumentType); break; }
-                    case 'I': { writer.putNextInt(j); break; }
-                    case 'J': { writer.putNextLong(j); break; }
-                    case 'F': { writer.putNextFloat(j); break; }
-                    case 'D': { writer.putNextDouble(j); break; }
-                    default : { throw new AssertionError(); }
+                case 'I':
+                {
+                    final int[] array = (int[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextInt(array[i]);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(long[] array, StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                long l = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(l, argumentType); break; }
-                    case 'J': { writer.putNextLong(l); break; }
-                    case 'F': { writer.putNextFloat((float) l); break; }
-                    case 'D': { writer.putNextDouble((double) l); break; }
-                    default : { throw new AssertionError(); }
+                case 'J':
+                {
+                    final long[] array = (long[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextLong(array[i]);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(byte[] array,
-                                       StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                byte b = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(b, argumentType); break; }
-                    case 'I': { writer.putNextInt(b); break; }
-                    case 'J': { writer.putNextLong(b); break; }
-                    case 'B': { writer.putNextByte(b); break; }
-                    case 'S': { writer.putNextShort(b); break; }
-                    case 'F': { writer.putNextFloat(b); break; }
-                    case 'D': { writer.putNextDouble(b); break; }
-                    default : { throw new AssertionError(); }
+                case 'B':
+                {
+                    final byte[] array = (byte[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextByte(array[i]);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(short[] array,
-                                       StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                short s = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(s, argumentType); break; }
-                    case 'I': { writer.putNextInt(s); break; }
-                    case 'J': { writer.putNextLong(s); break; }
-                    case 'S': { writer.putNextShort(s); break; }
-                    case 'F': { writer.putNextFloat(s); break; }
-                    case 'D': { writer.putNextDouble(s); break; }
-                    default : { throw new AssertionError(); }
+                case 'S':
+                {
+                    final short[] array = (short[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextShort(array[i]);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(char[] array,
-                                       StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                char c = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(c, argumentType); break; }
-                    case 'I': { writer.putNextInt(c); break; }
-                    case 'J': { writer.putNextLong(c); break; }
-                    case 'C': { writer.putNextChar(c); break; }
-                    case 'F': { writer.putNextFloat(c); break; }
-                    case 'D': { writer.putNextDouble(c); break; }
-                    default : { throw new AssertionError(); }
+                case 'C':
+                {
+                    final char[] array = (char[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextChar(array[i]);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(boolean[] array,
-                                       StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                boolean z = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(z, argumentType); break; }
-                    case 'Z': { writer.putNextBoolean(z); break; }
-                    default : { throw new AssertionError(); }
+                case 'Z':
+                {
+                    final boolean[] array = (boolean[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextBoolean(array[i]);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(double[] array,
-                                       StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                double d = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(d, argumentType); break; }
-                    case 'D': { writer.putNextDouble(d); break; }
-                    default : { throw new AssertionError(); }
+                case 'F':
+                {
+                    final float[] array = (float[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextFloat(array[i]);
+                    }
+                    break;
                 }
-            }
-        }
-
-        public static void spreadArray(float[] array, StackFrameWriter writer, MethodType type,
-                                       int numArgs, int offset) {
-            final Class<?>[] ptypes = type.ptypes();
-            for (int i = 0; i < numArgs; ++i) {
-                Class<?> argumentType = ptypes[i + offset];
-                float f = array[i];
-                switch (Wrapper.basicTypeChar(argumentType)) {
-                    case 'L': { writer.putNextReference(f, argumentType); break; }
-                    case 'D': { writer.putNextDouble((double) f); break; }
-                    case 'F': { writer.putNextFloat(f); break; }
-                    default : { throw new AssertionError(); }
+                case 'D':
+                {
+                    final double[] array = (double[]) arrayObj;
+                    for (int i = 0; i < array.length; ++i) {
+                        writer.putNextDouble(array[i]);
+                    }
+                    break;
                 }
             }
         }
     }
 
-    /**
-     * Implements MethodHandle.asCollector.
-     */
+    /** Implements {@code MethodHandle.asCollector}. */
     static class Collector extends Transformer {
         private final MethodHandle target;
 
         /**
-         * The offset of the trailing array argument in the list of arguments to
-         * this transformer. The array argument is always the last argument.
+         * The array start is the position in the target outputs of the array collecting arguments
+         * and the position in the source inputs where collection starts.
          */
         private final int arrayOffset;
 
         /**
-         * The number of input arguments that will be present in the array. In other words,
-         * this is the expected array length.
+         * The array length is the number of arguments to be collected.
          */
-        private final int numArrayArgs;
+        private final int arrayLength;
+
+        /** The type of the array. */
+        private final Class arrayType;
 
         /**
-         * The type char of the component type of the array.
+         * Range of arguments to copy verbatim from the start of the input frame.
          */
-        private final char arrayTypeChar;
+        private final Range leadingRange;
 
         /**
-         * Range of arguments to copy verbatim from the input frame, This will cover all
-         * arguments that aren't a part of the trailing array.
+         * Range of arguments to copy verbatim from the end of the input frame.
          */
-        private final Range copyRange;
+        private final Range trailingRange;
 
-        Collector(MethodHandle delegate, Class<?> arrayType, int length) {
-            super(delegate.type().asCollectorType(arrayType, length));
+        Collector(MethodHandle delegate, Class<?> arrayType, int start, int length) {
+            super(delegate.type().asCollectorType(arrayType, start, length));
+            this.target = delegate;
+            this.arrayOffset = start;
+            this.arrayLength = length;
+            this.arrayType = arrayType;
 
-            target = delegate;
-            // Copy all arguments except the last argument (which is the trailing array argument
-            // that needs to be spread).
-            arrayOffset = delegate.type().parameterCount() - 1;
-            arrayTypeChar = Wrapper.basicTypeChar(arrayType.getComponentType());
-            numArrayArgs = length;
-
-            // Copy all args except for the last argument.
-            copyRange = EmulatedStackFrame.Range.of(delegate.type(), 0, arrayOffset);
+            // Build ranges of arguments to be copied.
+            leadingRange = EmulatedStackFrame.Range.of(type(), 0, arrayOffset);
+            trailingRange = EmulatedStackFrame.Range.from(type(), arrayOffset + arrayLength);
         }
 
         @Override
         public void transform(EmulatedStackFrame callerFrame) throws Throwable {
             // Create a new stack frame for the callee.
-            EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
+            final EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
 
-            // Copy all arguments except for the trailing array argument.
-            callerFrame.copyRangeTo(targetFrame, copyRange, 0, 0);
+            // Copy arguments before the collector array.
+            callerFrame.copyRangeTo(targetFrame, leadingRange, 0, 0);
 
-            // Attach the writer, prepare to spread the trailing array arguments into
-            // the callee frame.
+            // Copy arguments after the collector array.
+            callerFrame.copyRangeTo(targetFrame, trailingRange,
+                leadingRange.numReferences + 1, leadingRange.numBytes);
+
+            // Collect arguments between arrayOffset and arrayOffset + arrayLength.
             final StackFrameWriter writer = new StackFrameWriter();
-            writer.attach(targetFrame, arrayOffset, copyRange.numReferences, copyRange.numBytes);
+            writer.attach(targetFrame, arrayOffset, leadingRange.numReferences, leadingRange.numBytes);
             final StackFrameReader reader = new StackFrameReader();
-            reader.attach(callerFrame, arrayOffset, copyRange.numReferences, copyRange.numBytes);
+            reader.attach(callerFrame, arrayOffset, leadingRange.numReferences, leadingRange.numBytes);
 
+            final char arrayTypeChar = Wrapper.basicTypeChar(arrayType.getComponentType());
             switch (arrayTypeChar) {
-                case 'L': {
-                    // Reference arrays are the only case where the component type of the
-                    // array we construct might differ from the type of the reference we read
-                    // from the stack frame.
-                    final Class<?> targetType = target.type().ptypes()[arrayOffset];
-                    final Class<?> targetComponentType = targetType.getComponentType();
-                    final Class<?> adapterComponentType = type().lastParameterType();
-
-                    Object[] arr = (Object[]) Array.newInstance(targetComponentType, numArrayArgs);
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        arr[i] = reader.nextReference(adapterComponentType);
+                case 'L':
+                    {
+                        // Reference arrays are the only case where the component type of the
+                        // array we construct might differ from the type of the reference we read
+                        // from the stack frame.
+                        final Class<?> targetType = target.type().ptypes()[arrayOffset];
+                        final Class<?> arrayComponentType = arrayType.getComponentType();
+                        Object[] arr =
+                                (Object[]) Array.newInstance(arrayComponentType, arrayLength);
+                        for (int i = 0; i < arrayLength; ++i) {
+                            arr[i] = reader.nextReference(arrayComponentType);
+                        }
+                        writer.putNextReference(arr, targetType);
+                        break;
                     }
-
-                    writer.putNextReference(arr, targetType);
-                    break;
-                }
-                case 'I': {
-                    int[] array = new int[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextInt();
+                case 'I':
+                    {
+                        int[] array = new int[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextInt();
+                        }
+                        writer.putNextReference(array, int[].class);
+                        break;
                     }
-                    writer.putNextReference(array, int[].class);
-                    break;
-                }
-                case 'J': {
-                    long[] array = new long[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextLong();
+                case 'J':
+                    {
+                        long[] array = new long[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextLong();
+                        }
+                        writer.putNextReference(array, long[].class);
+                        break;
                     }
-                    writer.putNextReference(array, long[].class);
-                    break;
-                }
-                case 'B': {
-                    byte[] array = new byte[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextByte();
+                case 'B':
+                    {
+                        byte[] array = new byte[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextByte();
+                        }
+                        writer.putNextReference(array, byte[].class);
+                        break;
                     }
-                    writer.putNextReference(array, byte[].class);
-                    break;
-                }
-                case 'S': {
-                    short[] array = new short[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextShort();
+                case 'S':
+                    {
+                        short[] array = new short[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextShort();
+                        }
+                        writer.putNextReference(array, short[].class);
+                        break;
                     }
-                    writer.putNextReference(array, short[].class);
-                    break;
-                }
-                case 'C': {
-                    char[] array = new char[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextChar();
+                case 'C':
+                    {
+                        char[] array = new char[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextChar();
+                        }
+                        writer.putNextReference(array, char[].class);
+                        break;
                     }
-                    writer.putNextReference(array, char[].class);
-                    break;
-                }
-                case 'Z': {
-                    boolean[] array = new boolean[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextBoolean();
+                case 'Z':
+                    {
+                        boolean[] array = new boolean[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextBoolean();
+                        }
+                        writer.putNextReference(array, boolean[].class);
+                        break;
                     }
-                    writer.putNextReference(array, boolean[].class);
-                    break;
-                }
-                case 'F': {
-                    float[] array = new float[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextFloat();
+                case 'F':
+                    {
+                        float[] array = new float[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextFloat();
+                        }
+                        writer.putNextReference(array, float[].class);
+                        break;
                     }
-                    writer.putNextReference(array, float[].class);
-                    break;
-                }
-                case 'D': {
-                    double[] array = new double[numArrayArgs];
-                    for (int i = 0; i < numArrayArgs; ++i) {
-                        array[i] = reader.nextDouble();
+                case 'D':
+                    {
+                        double[] array = new double[arrayLength];
+                        for (int i = 0; i < arrayLength; ++i) {
+                            array[i] = reader.nextDouble();
+                        }
+                        writer.putNextReference(array, double[].class);
+                        break;
                     }
-                    writer.putNextReference(array, double[].class);
-                    break;
-                }
             }
 
-            target.invoke(targetFrame);
+            invokeFromTransform(target, targetFrame);
             targetFrame.copyReturnValueTo(callerFrame);
         }
     }
 
-    /*
-     * Implements MethodHandles.filterArguments.
-     */
+    /** Implements {@code MethodHandles.filterArguments}. */
     static class FilterArguments extends Transformer {
         /** The target handle. */
         private final MethodHandle target;
@@ -1456,13 +1563,12 @@
         /** The list of filters to apply */
         private final MethodHandle[] filters;
 
-        FilterArguments(MethodHandle target, int pos, MethodHandle[] filters) {
+        FilterArguments(MethodHandle target, int pos, MethodHandle... filters) {
             super(deriveType(target, pos, filters));
 
             this.target = target;
             this.pos = pos;
             this.filters = filters;
-
         }
 
         private static MethodType deriveType(MethodHandle target, int pos, MethodHandle[] filters) {
@@ -1507,7 +1613,7 @@
                     filterWriter.attach(filterFrame);
                     copyNext(reader, filterWriter, filter.type().ptypes()[0]);
 
-                    filter.invoke(filterFrame);
+                    invokeFromTransform(filter, filterFrame);
 
                     // Copy the argument back from the filter frame to the stack frame.
                     final StackFrameReader filterReader = new StackFrameReader();
@@ -1521,14 +1627,12 @@
                 }
             }
 
-            target.invoke(transformedFrame);
+            invokeFromTransform(target, transformedFrame);
             transformedFrame.copyReturnValueTo(stackFrame);
         }
     }
 
-    /**
-     * Implements MethodHandles.collectArguments.
-     */
+    /** Implements {@code MethodHandles.collectArguments}. */
     static class CollectArguments extends Transformer {
         private final MethodHandle target;
         private final MethodHandle collector;
@@ -1538,8 +1642,8 @@
         private final Range collectorRange;
 
         /**
-         * The first range of arguments we copy to the target. These are arguments
-         * in the range [0, pos). Note that arg[pos] is the return value of the filter.
+         * The first range of arguments we copy to the target. These are arguments in the range [0,
+         * pos). Note that arg[pos] is the return value of the filter.
          */
         private final Range range1;
 
@@ -1552,8 +1656,8 @@
         private final int referencesOffset;
         private final int stackFrameOffset;
 
-        CollectArguments(MethodHandle target, MethodHandle collector, int pos,
-                         MethodType adapterType) {
+        CollectArguments(
+                MethodHandle target, MethodHandle collector, int pos, MethodType adapterType) {
             super(adapterType);
 
             this.target = target;
@@ -1561,15 +1665,10 @@
             this.pos = pos;
 
             final int numFilterArgs = collector.type().parameterCount();
-            final int numAdapterArgs = type().parameterCount();
             collectorRange = Range.of(type(), pos, pos + numFilterArgs);
 
             range1 = Range.of(type(), 0, pos);
-            if (pos + numFilterArgs < numAdapterArgs) {
-                this.range2 = Range.of(type(), pos + numFilterArgs, numAdapterArgs);
-            } else {
-                this.range2 = null;
-            }
+            this.range2 = Range.from(type(), pos + numFilterArgs);
 
             // Calculate the number of primitive bytes (or references) we copy to the
             // target frame based on the return value of the combiner.
@@ -1591,7 +1690,7 @@
             // First invoke the collector.
             EmulatedStackFrame filterFrame = EmulatedStackFrame.create(collector.type());
             stackFrame.copyRangeTo(filterFrame, collectorRange, 0, 0);
-            collector.invoke(filterFrame);
+            invokeFromTransform(collector, filterFrame);
 
             // Start constructing the target frame.
             EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
@@ -1606,38 +1705,46 @@
                 copyNext(reader, writer, target.type().ptypes()[0]);
             }
 
-            if (range2 != null) {
-                stackFrame.copyRangeTo(targetFrame, range2,
-                        range1.numReferences + referencesOffset,
-                        range2.numBytes + stackFrameOffset);
-            }
+            stackFrame.copyRangeTo(
+                    targetFrame,
+                    range2,
+                    range1.numReferences + referencesOffset,
+                    range2.numBytes + stackFrameOffset);
 
-            target.invoke(targetFrame);
+            invokeFromTransform(target, targetFrame);
             targetFrame.copyReturnValueTo(stackFrame);
         }
     }
 
-    /**
-     * Implements MethodHandles.foldArguments.
-     */
+    /** Implements {@code MethodHandles.foldArguments}. */
     static class FoldArguments extends Transformer {
         private final MethodHandle target;
         private final MethodHandle combiner;
+        private final int position;
 
+        /** The range of arguments in our frame passed to the combiner. */
         private final Range combinerArgs;
-        private final Range targetArgs;
+
+        /** The range of arguments in our frame copied to the start of the target frame. */
+        private final Range leadingArgs;
+
+        /** The range of arguments in our frame copied to the end of the target frame. */
+        private final Range trailingArgs;
 
         private final int referencesOffset;
         private final int stackFrameOffset;
 
-        FoldArguments(MethodHandle target, MethodHandle combiner) {
-            super(deriveType(target, combiner));
+        FoldArguments(MethodHandle target, int position, MethodHandle combiner) {
+            super(deriveType(target, position, combiner));
 
             this.target = target;
             this.combiner = combiner;
+            this.position = position;
 
-            combinerArgs = Range.all(combiner.type());
-            targetArgs = Range.all(type());
+            this.combinerArgs =
+                    Range.of(type(), position, position + combiner.type().parameterCount());
+            this.leadingArgs = Range.of(type(), 0, position);
+            this.trailingArgs = Range.from(type(), position);
 
             final Class<?> combinerRType = combiner.type().rtype();
             if (combinerRType == void.class) {
@@ -1647,6 +1754,7 @@
                 stackFrameOffset = EmulatedStackFrame.getSize(combinerRType);
                 referencesOffset = 0;
             } else {
+                // combinerRType is a reference.
                 stackFrameOffset = 0;
                 referencesOffset = 1;
             }
@@ -1654,41 +1762,51 @@
 
         @Override
         public void transform(EmulatedStackFrame stackFrame) throws Throwable {
-            // First construct the combiner frame and invoke it.
+            // First construct the combiner frame and invoke the combiner.
             EmulatedStackFrame combinerFrame = EmulatedStackFrame.create(combiner.type());
             stackFrame.copyRangeTo(combinerFrame, combinerArgs, 0, 0);
-            combiner.invoke(combinerFrame);
+            invokeExactFromTransform(combiner, combinerFrame);
 
-            // Create the stack frame for the target.
+            // Create the stack frame for the target and copy leading arguments to it.
             EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
+            stackFrame.copyRangeTo(targetFrame, leadingArgs, 0, 0);
 
-            // If one of these offsets is not zero, we have a return value to copy.
+            // If one of these offsets is not zero, we have to slot the return value from the
+            // combiner into the target frame.
             if (referencesOffset != 0 || stackFrameOffset != 0) {
                 final StackFrameReader reader = new StackFrameReader();
                 reader.attach(combinerFrame).makeReturnValueAccessor();
                 final StackFrameWriter writer = new StackFrameWriter();
-                writer.attach(targetFrame);
-                copyNext(reader, writer, target.type().ptypes()[0]);
+                writer.attach(targetFrame,
+                              position,
+                              leadingArgs.numReferences,
+                              leadingArgs.numBytes);
+                copyNext(reader, writer, target.type().ptypes()[position]);
             }
 
-            stackFrame.copyRangeTo(targetFrame, targetArgs, referencesOffset, stackFrameOffset);
-            target.invoke(targetFrame);
+            // Copy the arguments provided to the combiner to the tail of the target frame.
+            stackFrame.copyRangeTo(
+                targetFrame,
+                trailingArgs,
+                leadingArgs.numReferences + referencesOffset,
+                leadingArgs.numBytes + stackFrameOffset);
 
+            // Call the target and propagate return value.
+            invokeExactFromTransform(target, targetFrame);
             targetFrame.copyReturnValueTo(stackFrame);
         }
 
-        private static MethodType deriveType(MethodHandle target, MethodHandle combiner) {
+        private static MethodType deriveType(MethodHandle target,
+                                             int position,
+                                             MethodHandle combiner) {
             if (combiner.type().rtype() == void.class) {
                 return target.type();
             }
-
-            return target.type().dropParameterTypes(0, 1);
+            return target.type().dropParameterTypes(position, position + 1);
         }
     }
 
-    /**
-     * Implements MethodHandles.insertArguments.
-     */
+    /** Implements {@code MethodHandles.insertArguments}. */
     static class InsertArguments extends Transformer {
         private final MethodHandle target;
         private final int pos;
@@ -1726,52 +1844,450 @@
             final Class<?>[] ptypes = target.type().ptypes();
             for (int i = 0; i < values.length; ++i) {
                 final Class<?> ptype = ptypes[i + pos];
-                if (ptype.isPrimitive()) {
-                    if (ptype == boolean.class) {
-                        writer.putNextBoolean((boolean) values[i]);
-                    } else if (ptype == byte.class) {
-                        writer.putNextByte((byte) values[i]);
-                    } else if (ptype == char.class) {
-                        writer.putNextChar((char) values[i]);
-                    } else if (ptype == short.class) {
-                        writer.putNextShort((short) values[i]);
-                    } else if (ptype == int.class) {
-                        writer.putNextInt((int) values[i]);
-                    } else if (ptype == long.class) {
-                        writer.putNextLong((long) values[i]);
-                    } else if (ptype == float.class) {
-                        writer.putNextFloat((float) values[i]);
-                    } else if (ptype == double.class) {
-                        writer.putNextDouble((double) values[i]);
-                    }
-
-                    bytesCopied += EmulatedStackFrame.getSize(ptype);
-                } else {
+                final char typeChar = Wrapper.basicTypeChar(ptype);
+                if (typeChar == 'L') {
                     writer.putNextReference(values[i], ptype);
                     referencesCopied++;
+                } else {
+                    switch (typeChar) {
+                        case 'Z':
+                            writer.putNextBoolean((boolean) values[i]);
+                            break;
+                        case 'B':
+                            writer.putNextByte((byte) values[i]);
+                            break;
+                        case 'C':
+                            writer.putNextChar((char) values[i]);
+                            break;
+                        case 'S':
+                            writer.putNextShort((short) values[i]);
+                            break;
+                        case 'I':
+                            writer.putNextInt((int) values[i]);
+                            break;
+                        case 'J':
+                            writer.putNextLong((long) values[i]);
+                            break;
+                        case 'F':
+                            writer.putNextFloat((float) values[i]);
+                            break;
+                        case 'D':
+                            writer.putNextDouble((double) values[i]);
+                            break;
+                    }
+                    bytesCopied += EmulatedStackFrame.getSize(ptype);
                 }
             }
 
             // Copy all remaining arguments.
             if (range2 != null) {
-                stackFrame.copyRangeTo(calleeFrame, range2,
+                stackFrame.copyRangeTo(
+                        calleeFrame,
+                        range2,
                         range1.numReferences + referencesCopied,
                         range1.numBytes + bytesCopied);
             }
 
-            target.invoke(calleeFrame);
+            invokeFromTransform(target, calleeFrame);
             calleeFrame.copyReturnValueTo(stackFrame);
         }
     }
 
-
-    /**
-     * Implements {@link java.lang.invokeMethodHandles#explicitCastArguments()}.
-     */
-    public static class ExplicitCastArguments extends Transformer {
+    /** Implements {@code MethodHandle.asType}. */
+    static class AsTypeAdapter extends Transformer {
         private final MethodHandle target;
 
-        public ExplicitCastArguments(MethodHandle target, MethodType type) {
+        AsTypeAdapter(MethodHandle target, MethodType type) {
+            super(type);
+            this.target = target;
+        }
+
+        @Override
+        public void transform(EmulatedStackFrame callerFrame) throws Throwable {
+            final EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
+            final StackFrameReader reader = new StackFrameReader();
+            final StackFrameWriter writer = new StackFrameWriter();
+
+            // Adapt arguments
+            reader.attach(callerFrame);
+            writer.attach(targetFrame);
+            adaptArguments(reader, writer);
+
+            // Invoke target
+            invokeFromTransform(target, targetFrame);
+
+            if (callerFrame.getMethodType().rtype() != void.class) {
+                // Adapt return value
+                reader.attach(targetFrame).makeReturnValueAccessor();
+                writer.attach(callerFrame).makeReturnValueAccessor();
+                adaptReturnValue(reader, writer);
+            }
+        }
+
+        private void adaptArguments(final StackFrameReader reader, final StackFrameWriter writer) {
+            final Class<?>[] fromTypes = type().ptypes();
+            final Class<?>[] toTypes = target.type().ptypes();
+            for (int i = 0; i < fromTypes.length; ++i) {
+                adaptArgument(reader, fromTypes[i], writer, toTypes[i]);
+            }
+        }
+
+        private void adaptReturnValue(
+                final StackFrameReader reader, final StackFrameWriter writer) {
+            final Class<?> fromType = target.type().rtype();
+            final Class<?> toType = type().rtype();
+            adaptArgument(reader, fromType, writer, toType);
+        }
+
+        private void throwWrongMethodTypeException() throws WrongMethodTypeException {
+            throw new WrongMethodTypeException(
+                    "Cannot convert from " + type() + " to " + target.type());
+        }
+
+        private static void throwClassCastException(Class from, Class to)
+                throws ClassCastException {
+            throw new ClassCastException("Cannot cast from " + from + " to " + to);
+        }
+
+        private void writePrimitiveByteAs(final StackFrameWriter writer, char baseType, byte value)
+                throws WrongMethodTypeException {
+            switch (baseType) {
+                case 'B':
+                    writer.putNextByte(value);
+                    return;
+                case 'S':
+                    writer.putNextShort((short) value);
+                    return;
+                case 'I':
+                    writer.putNextInt((int) value);
+                    return;
+                case 'J':
+                    writer.putNextLong((long) value);
+                    return;
+                case 'F':
+                    writer.putNextFloat((float) value);
+                    return;
+                case 'D':
+                    writer.putNextDouble((double) value);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+        }
+
+        private void writePrimitiveShortAs(
+                final StackFrameWriter writer, char baseType, short value)
+                throws WrongMethodTypeException {
+            switch (baseType) {
+                case 'S':
+                    writer.putNextShort(value);
+                    return;
+                case 'I':
+                    writer.putNextInt((int) value);
+                    return;
+                case 'J':
+                    writer.putNextLong((long) value);
+                    return;
+                case 'F':
+                    writer.putNextFloat((float) value);
+                    return;
+                case 'D':
+                    writer.putNextDouble((double) value);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+        }
+
+        private void writePrimitiveCharAs(final StackFrameWriter writer, char baseType, char value)
+                throws WrongMethodTypeException {
+            switch (baseType) {
+                case 'C':
+                    writer.putNextChar(value);
+                    return;
+                case 'I':
+                    writer.putNextInt((int) value);
+                    return;
+                case 'J':
+                    writer.putNextLong((long) value);
+                    return;
+                case 'F':
+                    writer.putNextFloat((float) value);
+                    return;
+                case 'D':
+                    writer.putNextDouble((double) value);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+        }
+
+        private void writePrimitiveIntAs(final StackFrameWriter writer, char baseType, int value)
+                throws WrongMethodTypeException {
+            switch (baseType) {
+                case 'I':
+                    writer.putNextInt(value);
+                    return;
+                case 'J':
+                    writer.putNextLong((long) value);
+                    return;
+                case 'F':
+                    writer.putNextFloat((float) value);
+                    return;
+                case 'D':
+                    writer.putNextDouble((double) value);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+            throwWrongMethodTypeException();
+        }
+
+        private void writePrimitiveLongAs(final StackFrameWriter writer, char baseType, long value)
+                throws WrongMethodTypeException {
+            switch (baseType) {
+                case 'J':
+                    writer.putNextLong(value);
+                    return;
+                case 'F':
+                    writer.putNextFloat((float) value);
+                    return;
+                case 'D':
+                    writer.putNextDouble((double) value);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+        }
+
+        private void writePrimitiveFloatAs(
+                final StackFrameWriter writer, char baseType, float value)
+                throws WrongMethodTypeException {
+            switch (baseType) {
+                case 'F':
+                    writer.putNextFloat(value);
+                    return;
+                case 'D':
+                    writer.putNextDouble((double) value);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+        }
+
+        private void writePrimitiveDoubleAs(
+                final StackFrameWriter writer, char baseType, double value)
+                throws WrongMethodTypeException {
+            switch (baseType) {
+                case 'D':
+                    writer.putNextDouble(value);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+        }
+
+        private void writePrimitiveVoidAs(final StackFrameWriter writer, char baseType) {
+            switch (baseType) {
+                case 'Z':
+                    writer.putNextBoolean(false);
+                    return;
+                case 'B':
+                    writer.putNextByte((byte) 0);
+                    return;
+                case 'S':
+                    writer.putNextShort((short) 0);
+                    return;
+                case 'C':
+                    writer.putNextChar((char) 0);
+                    return;
+                case 'I':
+                    writer.putNextInt(0);
+                    return;
+                case 'J':
+                    writer.putNextLong(0L);
+                    return;
+                case 'F':
+                    writer.putNextFloat(0.0f);
+                    return;
+                case 'D':
+                    writer.putNextDouble(0.0);
+                    return;
+                default:
+                    throwWrongMethodTypeException();
+            }
+        }
+
+        private static Class getBoxedPrimitiveClass(char baseType) {
+            switch (baseType) {
+                case 'Z':
+                    return Boolean.class;
+                case 'B':
+                    return Byte.class;
+                case 'S':
+                    return Short.class;
+                case 'C':
+                    return Character.class;
+                case 'I':
+                    return Integer.class;
+                case 'J':
+                    return Long.class;
+                case 'F':
+                    return Float.class;
+                case 'D':
+                    return Double.class;
+                default:
+                    return null;
+            }
+        }
+
+        private void adaptArgument(
+                final StackFrameReader reader,
+                final Class<?> from,
+                final StackFrameWriter writer,
+                final Class<?> to) {
+            if (from.equals(to)) {
+                StackFrameAccessor.copyNext(reader, writer, from);
+                return;
+            }
+
+            if (to.isPrimitive()) {
+                if (from.isPrimitive()) {
+                    final char fromBaseType = Wrapper.basicTypeChar(from);
+                    final char toBaseType = Wrapper.basicTypeChar(to);
+                    switch (fromBaseType) {
+                        case 'B':
+                            writePrimitiveByteAs(writer, toBaseType, reader.nextByte());
+                            return;
+                        case 'S':
+                            writePrimitiveShortAs(writer, toBaseType, reader.nextShort());
+                            return;
+                        case 'C':
+                            writePrimitiveCharAs(writer, toBaseType, reader.nextChar());
+                            return;
+                        case 'I':
+                            writePrimitiveIntAs(writer, toBaseType, reader.nextInt());
+                            return;
+                        case 'J':
+                            writePrimitiveLongAs(writer, toBaseType, reader.nextLong());
+                            return;
+                        case 'F':
+                            writePrimitiveFloatAs(writer, toBaseType, reader.nextFloat());
+                            return;
+                        case 'V':
+                            writePrimitiveVoidAs(writer, toBaseType);
+                            return;
+                        default:
+                            throwWrongMethodTypeException();
+                    }
+                } else {
+                    final Object value = reader.nextReference(Object.class);
+                    if (to == void.class) {
+                        return;
+                    }
+                    if (value == null) {
+                        throw new NullPointerException();
+                    }
+                    if (!Wrapper.isWrapperType(value.getClass())) {
+                        throwClassCastException(value.getClass(), to);
+                    }
+                    final Wrapper fromWrapper = Wrapper.forWrapperType(value.getClass());
+                    final Wrapper toWrapper = Wrapper.forPrimitiveType(to);
+                    if (!toWrapper.isConvertibleFrom(fromWrapper)) {
+                        throwClassCastException(from, to);
+                    }
+
+                    final char toChar = toWrapper.basicTypeChar();
+                    switch (fromWrapper.basicTypeChar()) {
+                        case 'Z':
+                            writer.putNextBoolean(((Boolean) value).booleanValue());
+                            return;
+                        case 'B':
+                            writePrimitiveByteAs(writer, toChar, ((Byte) value).byteValue());
+                            return;
+                        case 'S':
+                            writePrimitiveShortAs(writer, toChar, ((Short) value).shortValue());
+                            return;
+                        case 'C':
+                            writePrimitiveCharAs(writer, toChar, ((Character) value).charValue());
+                            return;
+                        case 'I':
+                            writePrimitiveIntAs(writer, toChar, ((Integer) value).intValue());
+                            return;
+                        case 'J':
+                            writePrimitiveLongAs(writer, toChar, ((Long) value).longValue());
+                            return;
+                        case 'F':
+                            writePrimitiveFloatAs(writer, toChar, ((Float) value).floatValue());
+                            return;
+                        case 'D':
+                            writePrimitiveDoubleAs(writer, toChar, ((Double) value).doubleValue());
+                            return;
+                        default:
+                            throw new IllegalStateException();
+                    }
+                }
+            } else {
+                if (from.isPrimitive()) {
+                    // Boxing conversion
+                    final char fromBaseType = Wrapper.basicTypeChar(from);
+                    final Class fromBoxed = getBoxedPrimitiveClass(fromBaseType);
+                    // 'to' maybe a super class of the boxed `from` type, e.g. Number.
+                    if (fromBoxed != null && !to.isAssignableFrom(fromBoxed)) {
+                        throwWrongMethodTypeException();
+                    }
+
+                    Object boxed;
+                    switch (fromBaseType) {
+                        case 'Z':
+                            boxed = Boolean.valueOf(reader.nextBoolean());
+                            break;
+                        case 'B':
+                            boxed = Byte.valueOf(reader.nextByte());
+                            break;
+                        case 'S':
+                            boxed = Short.valueOf(reader.nextShort());
+                            break;
+                        case 'C':
+                            boxed = Character.valueOf(reader.nextChar());
+                            break;
+                        case 'I':
+                            boxed = Integer.valueOf(reader.nextInt());
+                            break;
+                        case 'J':
+                            boxed = Long.valueOf(reader.nextLong());
+                            break;
+                        case 'F':
+                            boxed = Float.valueOf(reader.nextFloat());
+                            break;
+                        case 'D':
+                            boxed = Double.valueOf(reader.nextDouble());
+                            break;
+                        case 'V':
+                            boxed = null;
+                            break;
+                        default:
+                            throw new IllegalStateException();
+                    }
+                    writer.putNextReference(boxed, to);
+                    return;
+                } else {
+                    // Cast
+                    Object value = reader.nextReference(Object.class);
+                    if (value != null && !to.isAssignableFrom(value.getClass())) {
+                        throwClassCastException(value.getClass(), to);
+                    }
+                    writer.putNextReference(value, to);
+                }
+            }
+        }
+    }
+
+    /** Implements {@code MethodHandles.explicitCastArguments}. */
+    static class ExplicitCastArguments extends Transformer {
+        private final MethodHandle target;
+
+        ExplicitCastArguments(MethodHandle target, MethodType type) {
             super(type);
             this.target = target;
         }
@@ -1782,12 +2298,12 @@
             EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
 
             explicitCastArguments(callerFrame, targetFrame);
-            target.invoke(targetFrame);
+            invokeFromTransform(target, targetFrame);
             explicitCastReturnValue(callerFrame, targetFrame);
         }
 
-        private void explicitCastArguments(final EmulatedStackFrame callerFrame,
-                                           final EmulatedStackFrame targetFrame) {
+        private void explicitCastArguments(
+                final EmulatedStackFrame callerFrame, final EmulatedStackFrame targetFrame) {
             final StackFrameReader reader = new StackFrameReader();
             reader.attach(callerFrame);
             final StackFrameWriter writer = new StackFrameWriter();
@@ -1800,8 +2316,8 @@
             }
         }
 
-        private void explicitCastReturnValue(final EmulatedStackFrame callerFrame,
-                                             final EmulatedStackFrame targetFrame) {
+        private void explicitCastReturnValue(
+                final EmulatedStackFrame callerFrame, final EmulatedStackFrame targetFrame) {
             Class<?> from = target.type().rtype();
             Class<?> to = type().rtype();
             if (to != void.class) {
@@ -1833,447 +2349,577 @@
         }
 
         /**
-         * Converts byte value to boolean according to
-         * {@link java.lang.invoke.MethodHandles#explicitCast()}
+         * Converts byte value to boolean according to {@link
+         * java.lang.invoke.MethodHandles#explicitCast()}
          */
         private static boolean toBoolean(byte value) {
             return (value & 1) == 1;
         }
 
-        private static byte readPrimitiveAsByte(final StackFrameReader reader,
-                                                final Class<?> from) {
-            if (from == byte.class) {
-                return (byte) reader.nextByte();
-            } else if (from == char.class) {
-                return (byte) reader.nextChar();
-            } else if (from == short.class) {
-                return (byte) reader.nextShort();
-            } else if (from == int.class) {
-                return (byte) reader.nextInt();
-            } else if (from == long.class) {
-                return (byte) reader.nextLong();
-            } else if (from == float.class) {
-                return (byte) reader.nextFloat();
-            } else if (from == double.class) {
-                return (byte) reader.nextDouble();
-            } else if (from == boolean.class) {
-                return reader.nextBoolean() ? (byte) 1 : (byte) 0;
-            } else {
-                throwUnexpectedType(from);
-                return 0;
+        private static byte readPrimitiveAsByte(
+                final StackFrameReader reader, final Class<?> from) {
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'B':
+                    return (byte) reader.nextByte();
+                case 'C':
+                    return (byte) reader.nextChar();
+                case 'S':
+                    return (byte) reader.nextShort();
+                case 'I':
+                    return (byte) reader.nextInt();
+                case 'J':
+                    return (byte) reader.nextLong();
+                case 'F':
+                    return (byte) reader.nextFloat();
+                case 'D':
+                    return (byte) reader.nextDouble();
+                case 'Z':
+                    return reader.nextBoolean() ? (byte) 1 : (byte) 0;
+                default:
+                    throwUnexpectedType(from);
+                    return 0;
             }
         }
 
-        private static char readPrimitiveAsChar(final StackFrameReader reader,
-                                                final Class<?> from) {
-            if (from == byte.class) {
-                return (char) reader.nextByte();
-            } else if (from == char.class) {
-                return (char) reader.nextChar();
-            } else if (from == short.class) {
-                return (char) reader.nextShort();
-            } else if (from == int.class) {
-                return (char) reader.nextInt();
-            } else if (from == long.class) {
-                return (char) reader.nextLong();
-            } else if (from == float.class) {
-                return (char) reader.nextFloat();
-            } else if (from == double.class) {
-                return (char) reader.nextDouble();
-            } else if (from == boolean.class) {
-                return reader.nextBoolean() ? (char) 1 : (char) 0;
-            } else {
-                throwUnexpectedType(from);
-                return 0;
+        private static char readPrimitiveAsChar(
+                final StackFrameReader reader, final Class<?> from) {
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'B':
+                    return (char) reader.nextByte();
+                case 'C':
+                    return (char) reader.nextChar();
+                case 'S':
+                    return (char) reader.nextShort();
+                case 'I':
+                    return (char) reader.nextInt();
+                case 'J':
+                    return (char) reader.nextLong();
+                case 'F':
+                    return (char) reader.nextFloat();
+                case 'D':
+                    return (char) reader.nextDouble();
+                case 'Z':
+                    return reader.nextBoolean() ? (char) 1 : (char) 0;
+                default:
+                    throwUnexpectedType(from);
+                    return 0;
             }
         }
 
-        private static short readPrimitiveAsShort(final StackFrameReader reader,
-                                                  final Class<?> from) {
-            if (from == byte.class) {
-                return (short) reader.nextByte();
-            } else if (from == char.class) {
-                return (short) reader.nextChar();
-            } else if (from == short.class) {
-                return (short) reader.nextShort();
-            } else if (from == int.class) {
-                return (short) reader.nextInt();
-            } else if (from == long.class) {
-                return (short) reader.nextLong();
-            } else if (from == float.class) {
-                return (short) reader.nextFloat();
-            } else if (from == double.class) {
-                return (short) reader.nextDouble();
-            } else if (from == boolean.class) {
-                return reader.nextBoolean() ? (short) 1 : (short) 0;
-            } else {
-                throwUnexpectedType(from);
-                return 0;
+        private static short readPrimitiveAsShort(
+                final StackFrameReader reader, final Class<?> from) {
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'B':
+                    return (short) reader.nextByte();
+                case 'C':
+                    return (short) reader.nextChar();
+                case 'S':
+                    return (short) reader.nextShort();
+                case 'I':
+                    return (short) reader.nextInt();
+                case 'J':
+                    return (short) reader.nextLong();
+                case 'F':
+                    return (short) reader.nextFloat();
+                case 'D':
+                    return (short) reader.nextDouble();
+                case 'Z':
+                    return reader.nextBoolean() ? (short) 1 : (short) 0;
+                default:
+                    throwUnexpectedType(from);
+                    return 0;
             }
         }
 
-        private static int readPrimitiveAsInt(final StackFrameReader reader,
-                                              final Class<?> from) {
-            if (from == byte.class) {
-                return (int) reader.nextByte();
-            } else if (from == char.class) {
-                return (int) reader.nextChar();
-            } else if (from == short.class) {
-                return (int) reader.nextShort();
-            } else if (from == int.class) {
-                return (int) reader.nextInt();
-            } else if (from == long.class) {
-                return (int) reader.nextLong();
-            } else if (from == float.class) {
-                return (int) reader.nextFloat();
-            } else if (from == double.class) {
-                return (int) reader.nextDouble();
-            } else if (from == boolean.class) {
-                return reader.nextBoolean() ? 1 : 0;
-            } else {
-                throwUnexpectedType(from);
-                return 0;
+        private static int readPrimitiveAsInt(final StackFrameReader reader, final Class<?> from) {
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'B':
+                    return (int) reader.nextByte();
+                case 'C':
+                    return (int) reader.nextChar();
+                case 'S':
+                    return (int) reader.nextShort();
+                case 'I':
+                    return (int) reader.nextInt();
+                case 'J':
+                    return (int) reader.nextLong();
+                case 'F':
+                    return (int) reader.nextFloat();
+                case 'D':
+                    return (int) reader.nextDouble();
+                case 'Z':
+                    return reader.nextBoolean() ? 1 : 0;
+                default:
+                    throwUnexpectedType(from);
+                    return 0;
             }
         }
 
-        private static long readPrimitiveAsLong(final StackFrameReader reader,
-                                                final Class<?> from) {
-            if (from == byte.class) {
-                return (long) reader.nextByte();
-            } else if (from == char.class) {
-                return (long) reader.nextChar();
-            } else if (from == short.class) {
-                return (long) reader.nextShort();
-            } else if (from == int.class) {
-                return (long) reader.nextInt();
-            } else if (from == long.class) {
-                return (long) reader.nextLong();
-            } else if (from == float.class) {
-                return (long) reader.nextFloat();
-            } else if (from == double.class) {
-                return (long) reader.nextDouble();
-            } else if (from == boolean.class) {
-                return reader.nextBoolean() ? 1L : 0L;
-            } else {
-                throwUnexpectedType(from);
-                return 0;
+        private static long readPrimitiveAsLong(
+                final StackFrameReader reader, final Class<?> from) {
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'B':
+                    return (long) reader.nextByte();
+                case 'C':
+                    return (long) reader.nextChar();
+                case 'S':
+                    return (long) reader.nextShort();
+                case 'I':
+                    return (long) reader.nextInt();
+                case 'J':
+                    return (long) reader.nextLong();
+                case 'F':
+                    return (long) reader.nextFloat();
+                case 'D':
+                    return (long) reader.nextDouble();
+                case 'Z':
+                    return reader.nextBoolean() ? 1L : 0L;
+                default:
+                    throwUnexpectedType(from);
+                    return 0;
             }
         }
 
-        private static float readPrimitiveAsFloat(final StackFrameReader reader,
-                                                  final Class<?> from) {
-            if (from == byte.class) {
-                return (float) reader.nextByte();
-            } else if (from == char.class) {
-                return (float) reader.nextChar();
-            } else if (from == short.class) {
-                return (float) reader.nextShort();
-            } else if (from == int.class) {
-                return (float) reader.nextInt();
-            } else if (from == long.class) {
-                return (float) reader.nextLong();
-            } else if (from == float.class) {
-                return (float) reader.nextFloat();
-            } else if (from == double.class) {
-                return (float) reader.nextDouble();
-            } else if (from == boolean.class) {
-                return reader.nextBoolean() ? 1.0f : 0.0f;
-            } else {
-                throwUnexpectedType(from);
-                return 0;
+        private static float readPrimitiveAsFloat(
+                final StackFrameReader reader, final Class<?> from) {
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'B':
+                    return (float) reader.nextByte();
+                case 'C':
+                    return (float) reader.nextChar();
+                case 'S':
+                    return (float) reader.nextShort();
+                case 'I':
+                    return (float) reader.nextInt();
+                case 'J':
+                    return (float) reader.nextLong();
+                case 'F':
+                    return (float) reader.nextFloat();
+                case 'D':
+                    return (float) reader.nextDouble();
+                case 'Z':
+                    return reader.nextBoolean() ? 1.0f : 0.0f;
+                default:
+                    throwUnexpectedType(from);
+                    return 0;
             }
         }
 
-        private static double readPrimitiveAsDouble(final StackFrameReader reader,
-                                                    final Class<?> from) {
-            if (from == byte.class) {
-                return (double) reader.nextByte();
-            } else if (from == char.class) {
-                return (double) reader.nextChar();
-            } else if (from == short.class) {
-                return (double) reader.nextShort();
-            } else if (from == int.class) {
-                return (double) reader.nextInt();
-            } else if (from == long.class) {
-                return (double) reader.nextLong();
-            } else if (from == float.class) {
-                return (double) reader.nextFloat();
-            } else if (from == double.class) {
-                return (double) reader.nextDouble();
-            } else if (from == boolean.class) {
-                return reader.nextBoolean() ? 1.0 : 0.0;
-            } else {
-                throwUnexpectedType(from);
-                return 0;
+        private static double readPrimitiveAsDouble(
+                final StackFrameReader reader, final Class<?> from) {
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'B':
+                    return (double) reader.nextByte();
+                case 'C':
+                    return (double) reader.nextChar();
+                case 'S':
+                    return (double) reader.nextShort();
+                case 'I':
+                    return (double) reader.nextInt();
+                case 'J':
+                    return (double) reader.nextLong();
+                case 'F':
+                    return (double) reader.nextFloat();
+                case 'D':
+                    return (double) reader.nextDouble();
+                case 'Z':
+                    return reader.nextBoolean() ? 1.0 : 0.0;
+                default:
+                    throwUnexpectedType(from);
+                    return 0;
             }
         }
 
-        private static void explicitCastPrimitives(final StackFrameReader reader,
-                                                   final Class<?> from,
-                                                   final StackFrameWriter writer,
-                                                   final Class<?> to) {
-            if (to == byte.class) {
-                byte value = readPrimitiveAsByte(reader, from);
-                writer.putNextByte(value);
-            } else if (to == char.class) {
-                char value = readPrimitiveAsChar(reader, from);
-                writer.putNextChar(value);
-            } else if (to == short.class) {
-                short value = readPrimitiveAsShort(reader, from);
-                writer.putNextShort(value);
-            } else if (to == int.class) {
-                int value = readPrimitiveAsInt(reader, from);
-                writer.putNextInt(value);
-            } else if (to == long.class) {
-                long value = readPrimitiveAsLong(reader, from);
-                writer.putNextLong(value);
-            } else if (to == float.class) {
-                float value = readPrimitiveAsFloat(reader, from);
-                writer.putNextFloat(value);
-            } else if (to == double.class) {
-                double value = readPrimitiveAsDouble(reader, from);
-                writer.putNextDouble(value);
-            } else if (to == boolean.class) {
-                byte byteValue = readPrimitiveAsByte(reader, from);
-                writer.putNextBoolean(toBoolean(byteValue));
-            } else {
-                throwUnexpectedType(to);
+        private static void explicitCastPrimitives(
+                final StackFrameReader reader,
+                final Class<?> from,
+                final StackFrameWriter writer,
+                final Class<?> to) {
+            switch (Wrapper.basicTypeChar(to)) {
+                case 'B':
+                    writer.putNextByte(readPrimitiveAsByte(reader, from));
+                    break;
+                case 'C':
+                    writer.putNextChar(readPrimitiveAsChar(reader, from));
+                    break;
+                case 'S':
+                    writer.putNextShort(readPrimitiveAsShort(reader, from));
+                    break;
+                case 'I':
+                    writer.putNextInt(readPrimitiveAsInt(reader, from));
+                    break;
+                case 'J':
+                    writer.putNextLong(readPrimitiveAsLong(reader, from));
+                    break;
+                case 'F':
+                    writer.putNextFloat(readPrimitiveAsFloat(reader, from));
+                    break;
+                case 'D':
+                    writer.putNextDouble(readPrimitiveAsDouble(reader, from));
+                    break;
+                case 'Z':
+                    writer.putNextBoolean(toBoolean(readPrimitiveAsByte(reader, from)));
+                    break;
+                default:
+                    throwUnexpectedType(to);
+                    break;
             }
         }
 
         private static void unboxNull(final StackFrameWriter writer, final Class<?> to) {
-            if (to == boolean.class) {
-                writer.putNextBoolean(false);
-            } else if (to == byte.class) {
-                writer.putNextByte((byte) 0);
-            } else if (to == char.class) {
-                writer.putNextChar((char) 0);
-            } else if (to == short.class) {
-                writer.putNextShort((short) 0);
-            } else if (to == int.class) {
-                writer.putNextInt((int) 0);
-            } else if (to == long.class) {
-                writer.putNextLong((long) 0);
-            } else if (to == float.class) {
-                writer.putNextFloat((float) 0);
-            } else if (to == double.class) {
-                writer.putNextDouble((double) 0);
-            } else {
-                throwUnexpectedType(to);
+            switch (Wrapper.basicTypeChar(to)) {
+                case 'Z':
+                    writer.putNextBoolean(false);
+                    break;
+                case 'B':
+                    writer.putNextByte((byte) 0);
+                    break;
+                case 'C':
+                    writer.putNextChar((char) 0);
+                    break;
+                case 'S':
+                    writer.putNextShort((short) 0);
+                    break;
+                case 'I':
+                    writer.putNextInt((int) 0);
+                    break;
+                case 'J':
+                    writer.putNextLong((long) 0);
+                    break;
+                case 'F':
+                    writer.putNextFloat((float) 0);
+                    break;
+                case 'D':
+                    writer.putNextDouble((double) 0);
+                    break;
+                default:
+                    throwUnexpectedType(to);
+                    break;
             }
         }
 
-        private static void unboxNonNull(final Object ref, final Class<?> from,
-                                         final StackFrameWriter writer, final Class<?> to) {
-            if (from == Boolean.class) {
-                boolean z = (boolean) ref;
-                if (to == boolean.class) {
-                    writer.putNextBoolean(z);
-                } else if (to == byte.class) {
-                    writer.putNextByte(z ? (byte) 1 : (byte) 0);
-                } else if (to == short.class) {
-                    writer.putNextShort(z ? (short) 1 : (short) 0);
-                } else if (to == char.class) {
-                    writer.putNextChar(z ? (char) 1 : (char) 0);
-                } else if (to == int.class) {
-                    writer.putNextInt(z ? 1 : 0);
-                } else if (to == long.class) {
-                    writer.putNextLong(z ? 1l : 0l);
-                } else if (to == float.class) {
-                    writer.putNextFloat(z ? 1.0f : 0.0f);
-                } else if (to == double.class) {
-                    writer.putNextDouble(z ? 1.0 : 0.0);
-                } else {
+        private static void unboxNonNull(
+                final Object ref,
+                final StackFrameWriter writer,
+                final Class<?> to) {
+            final Class<?> from = ref.getClass();
+            final Class<?> unboxedFromType = Wrapper.asPrimitiveType(from);
+            switch (Wrapper.basicTypeChar(unboxedFromType)) {
+                case 'Z':
+                    boolean z = (boolean) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'Z':
+                            writer.putNextBoolean(z);
+                            break;
+                        case 'B':
+                            writer.putNextByte(z ? (byte) 1 : (byte) 0);
+                            break;
+                        case 'S':
+                            writer.putNextShort(z ? (short) 1 : (short) 0);
+                            break;
+                        case 'C':
+                            writer.putNextChar(z ? (char) 1 : (char) 0);
+                            break;
+                        case 'I':
+                            writer.putNextInt(z ? 1 : 0);
+                            break;
+                        case 'J':
+                            writer.putNextLong(z ? 1l : 0l);
+                            break;
+                        case 'F':
+                            writer.putNextFloat(z ? 1.0f : 0.0f);
+                            break;
+                        case 'D':
+                            writer.putNextDouble(z ? 1.0 : 0.0);
+                            break;
+                        default:
+                            badCast(from, to);
+                            break;
+                    }
+                    break;
+                case 'B':
+                    byte b = (byte) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'B':
+                            writer.putNextByte(b);
+                            break;
+                        case 'Z':
+                            writer.putNextBoolean(toBoolean(b));
+                            break;
+                        case 'S':
+                            writer.putNextShort((short) b);
+                            break;
+                        case 'C':
+                            writer.putNextChar((char) b);
+                            break;
+                        case 'I':
+                            writer.putNextInt((int) b);
+                            break;
+                        case 'J':
+                            writer.putNextLong((long) b);
+                            break;
+                        case 'F':
+                            writer.putNextFloat((float) b);
+                            break;
+                        case 'D':
+                            writer.putNextDouble((double) b);
+                            break;
+                        default:
+                            badCast(from, to);
+                            break;
+                    }
+                    break;
+                case 'S':
+                    short s = (short) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'Z':
+                            writer.putNextBoolean((s & 1) == 1);
+                            break;
+                        case 'B':
+                            writer.putNextByte((byte) s);
+                            break;
+                        case 'S':
+                            writer.putNextShort(s);
+                            break;
+                        case 'C':
+                            writer.putNextChar((char) s);
+                            break;
+                        case 'I':
+                            writer.putNextInt((int) s);
+                            break;
+                        case 'J':
+                            writer.putNextLong((long) s);
+                            break;
+                        case 'F':
+                            writer.putNextFloat((float) s);
+                            break;
+                        case 'D':
+                            writer.putNextDouble((double) s);
+                            break;
+                        default:
+                            badCast(from, to);
+                            break;
+                    }
+                    break;
+                case 'C':
+                    char c = (char) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'Z':
+                            writer.putNextBoolean((c & (char) 1) == (char) 1);
+                            break;
+                        case 'B':
+                            writer.putNextByte((byte) c);
+                            break;
+                        case 'S':
+                            writer.putNextShort((short) c);
+                            break;
+                        case 'C':
+                            writer.putNextChar(c);
+                            break;
+                        case 'I':
+                            writer.putNextInt((int) c);
+                            break;
+                        case 'J':
+                            writer.putNextLong((long) c);
+                            break;
+                        case 'F':
+                            writer.putNextFloat((float) c);
+                            break;
+                        case 'D':
+                            writer.putNextDouble((double) c);
+                            break;
+                        default:
+                            badCast(from, to);
+                            break;
+                    }
+                    break;
+                case 'I':
+                    int i = (int) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'Z':
+                            writer.putNextBoolean((i & 1) == 1);
+                            break;
+                        case 'B':
+                            writer.putNextByte((byte) i);
+                            break;
+                        case 'S':
+                            writer.putNextShort((short) i);
+                            break;
+                        case 'C':
+                            writer.putNextChar((char) i);
+                            break;
+                        case 'I':
+                            writer.putNextInt(i);
+                            break;
+                        case 'J':
+                            writer.putNextLong((long) i);
+                            break;
+                        case 'F':
+                            writer.putNextFloat((float) i);
+                            break;
+                        case 'D':
+                            writer.putNextDouble((double) i);
+                            break;
+                        default:
+                            badCast(from, to);
+                    }
+                    break;
+                case 'J':
+                    long j = (long) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'Z':
+                            writer.putNextBoolean((j & 1l) == 1l);
+                            break;
+                        case 'B':
+                            writer.putNextByte((byte) j);
+                            break;
+                        case 'S':
+                            writer.putNextShort((short) j);
+                            break;
+                        case 'C':
+                            writer.putNextChar((char) j);
+                            break;
+                        case 'I':
+                            writer.putNextInt((int) j);
+                            break;
+                        case 'J':
+                            writer.putNextLong(j);
+                            break;
+                        case 'F':
+                            writer.putNextFloat((float) j);
+                            break;
+                        case 'D':
+                            writer.putNextDouble((double) j);
+                            break;
+                        default:
+                            badCast(from, to);
+                            break;
+                    }
+                    break;
+                case 'F':
+                    float f = (float) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'Z':
+                            writer.putNextBoolean(((byte) f & 1) != 0);
+                            break;
+                        case 'B':
+                            writer.putNextByte((byte) f);
+                            break;
+                        case 'S':
+                            writer.putNextShort((short) f);
+                            break;
+                        case 'C':
+                            writer.putNextChar((char) f);
+                            break;
+                        case 'I':
+                            writer.putNextInt((int) f);
+                            break;
+                        case 'J':
+                            writer.putNextLong((long) f);
+                            break;
+                        case 'F':
+                            writer.putNextFloat(f);
+                            break;
+                        case 'D':
+                            writer.putNextDouble((double) f);
+                            break;
+                        default:
+                            badCast(from, to);
+                            break;
+                    }
+                    break;
+                case 'D':
+                    double d = (double) ref;
+                    switch (Wrapper.basicTypeChar(to)) {
+                        case 'Z':
+                            writer.putNextBoolean(((byte) d & 1) != 0);
+                            break;
+                        case 'B':
+                            writer.putNextByte((byte) d);
+                            break;
+                        case 'S':
+                            writer.putNextShort((short) d);
+                            break;
+                        case 'C':
+                            writer.putNextChar((char) d);
+                            break;
+                        case 'I':
+                            writer.putNextInt((int) d);
+                            break;
+                        case 'J':
+                            writer.putNextLong((long) d);
+                            break;
+                        case 'F':
+                            writer.putNextFloat((float) d);
+                            break;
+                        case 'D':
+                            writer.putNextDouble(d);
+                            break;
+                        default:
+                            badCast(from, to);
+                            break;
+                    }
+                    break;
+                default:
                     badCast(from, to);
-                }
-            } else if (from == Byte.class) {
-                byte b = (byte) ref;
-                if (to == byte.class) {
-                    writer.putNextByte(b);
-                } else if (to == boolean.class) {
-                    writer.putNextBoolean(toBoolean(b));
-                } else if (to == short.class) {
-                    writer.putNextShort((short) b);
-                } else if (to == char.class) {
-                    writer.putNextChar((char) b);
-                } else if (to == int.class) {
-                    writer.putNextInt((int) b);
-                } else if (to == long.class) {
-                    writer.putNextLong((long) b);
-                } else if (to == float.class) {
-                    writer.putNextFloat((float) b);
-                } else if (to == double.class) {
-                    writer.putNextDouble((double) b);
-                } else {
-                    badCast(from, to);
-                }
-            } else if (from == Short.class) {
-                short s = (short) ref;
-                if (to == boolean.class) {
-                    writer.putNextBoolean((s & 1) == 1);
-                } else if (to == byte.class) {
-                    writer.putNextByte((byte) s);
-                } else if (to == short.class) {
-                    writer.putNextShort(s);
-                } else if (to == char.class) {
-                    writer.putNextChar((char) s);
-                } else if (to == int.class) {
-                    writer.putNextInt((int) s);
-                } else if (to == long.class) {
-                    writer.putNextLong((long) s);
-                } else if (to == float.class) {
-                    writer.putNextFloat((float) s);
-                } else if (to == double.class) {
-                    writer.putNextDouble((double) s);
-                } else {
-                    badCast(from, to);
-                }
-            } else if (from == Character.class) {
-                char c = (char) ref;
-                if (to == boolean.class) {
-                    writer.putNextBoolean((c & (char) 1) == (char) 1);
-                } else if (to == byte.class) {
-                    writer.putNextByte((byte) c);
-                } else if (to == short.class) {
-                    writer.putNextShort((short) c);
-                } else if (to == char.class) {
-                    writer.putNextChar(c);
-                } else if (to == int.class) {
-                    writer.putNextInt((int) c);
-                } else if (to == long.class) {
-                    writer.putNextLong((long) c);
-                } else if (to == float.class) {
-                    writer.putNextFloat((float) c);
-                } else if (to == double.class) {
-                    writer.putNextDouble((double) c);
-                } else {
-                    badCast(from, to);
-                }
-            } else if (from == Integer.class) {
-                int i = (int) ref;
-                if (to == boolean.class) {
-                    writer.putNextBoolean((i & 1) == 1);
-                } else if (to == byte.class) {
-                    writer.putNextByte((byte) i);
-                } else if (to == short.class) {
-                    writer.putNextShort((short) i);
-                } else if (to == char.class) {
-                    writer.putNextChar((char) i);
-                } else if (to == int.class) {
-                    writer.putNextInt(i);
-                } else if (to == long.class) {
-                    writer.putNextLong((long) i);
-                } else if (to == float.class) {
-                    writer.putNextFloat((float) i);
-                } else if (to == double.class) {
-                    writer.putNextDouble((double) i);
-                } else {
-                    badCast(from, to);
-                }
-            } else if (from == Long.class) {
-                long j = (long) ref;
-                if (to == boolean.class) {
-                    writer.putNextBoolean((j & 1l) == 1l);
-                } else if (to == byte.class) {
-                    writer.putNextByte((byte) j);
-                } else if (to == short.class) {
-                    writer.putNextShort((short) j);
-                } else if (to == char.class) {
-                    writer.putNextChar((char) j);
-                } else if (to == int.class) {
-                    writer.putNextInt((int) j);
-                } else if (to == long.class) {
-                    writer.putNextLong(j);
-                } else if (to == float.class) {
-                    writer.putNextFloat((float) j);
-                } else if (to == double.class) {
-                    writer.putNextDouble((double) j);
-                } else {
-                    badCast(from, to);
-                }
-            } else if (from == Float.class) {
-                float f = (float) ref;
-                if (to == boolean.class) {
-                    writer.putNextBoolean(((byte) f & 1) != 0);
-                } else if (to == byte.class) {
-                    writer.putNextByte((byte) f);
-                } else if (to == short.class) {
-                    writer.putNextShort((short) f);
-                } else if (to == char.class) {
-                    writer.putNextChar((char) f);
-                } else if (to == int.class) {
-                    writer.putNextInt((int) f);
-                } else if (to == long.class) {
-                    writer.putNextLong((long) f);
-                } else if (to == float.class) {
-                    writer.putNextFloat(f);
-                } else if (to == double.class) {
-                    writer.putNextDouble((double) f);
-                } else {
-                    badCast(from, to);
-                }
-            } else if (from == Double.class) {
-                double d = (double) ref;
-                if (to == boolean.class) {
-                    writer.putNextBoolean(((byte) d & 1) != 0);
-                } else if (to == byte.class) {
-                    writer.putNextByte((byte) d);
-                } else if (to == short.class) {
-                    writer.putNextShort((short) d);
-                } else if (to == char.class) {
-                    writer.putNextChar((char) d);
-                } else if (to == int.class) {
-                    writer.putNextInt((int) d);
-                } else if (to == long.class) {
-                    writer.putNextLong((long) d);
-                } else if (to == float.class) {
-                    writer.putNextFloat((float) d);
-                } else if (to == double.class) {
-                    writer.putNextDouble(d);
-                } else {
-                    badCast(from, to);
-                }
-            } else {
-                badCast(from, to);
+                    break;
             }
         }
 
-        private static void unbox(final Object ref, final Class<?> from,
-                                  final StackFrameWriter writer, final Class<?> to) {
+        private static void unbox(
+                final Object ref,
+                final StackFrameWriter writer,
+                final Class<?> to) {
             if (ref == null) {
                 unboxNull(writer, to);
             } else {
-                unboxNonNull(ref, from, writer, to);
+                unboxNonNull(ref, writer, to);
             }
         }
 
-        private static void box(final StackFrameReader reader, final Class<?> from,
-                                final StackFrameWriter writer, final Class<?> to) {
+        private static void box(
+                final StackFrameReader reader,
+                final Class<?> from,
+                final StackFrameWriter writer,
+                final Class<?> to) {
             Object boxed = null;
-            if (from == boolean.class) {
-                boxed = Boolean.valueOf(reader.nextBoolean());
-            } else if (from == byte.class) {
-                boxed = Byte.valueOf(reader.nextByte());
-            } else if (from == char.class) {
-                boxed = Character.valueOf(reader.nextChar());
-            } else if (from == short.class) {
-                boxed = Short.valueOf(reader.nextShort());
-            } else if (from == int.class) {
-                boxed = Integer.valueOf(reader.nextInt());
-            } else if (from == long.class) {
-                boxed = Long.valueOf(reader.nextLong());
-            } else if (from == float.class) {
-                boxed = Float.valueOf(reader.nextFloat());
-            } else if (from == double.class) {
-                boxed = Double.valueOf(reader.nextDouble());
-            } else {
-                throwUnexpectedType(from);
+            switch (Wrapper.basicTypeChar(from)) {
+                case 'Z':
+                    boxed = Boolean.valueOf(reader.nextBoolean());
+                    break;
+                case 'B':
+                    boxed = Byte.valueOf(reader.nextByte());
+                    break;
+                case 'C':
+                    boxed = Character.valueOf(reader.nextChar());
+                    break;
+                case 'S':
+                    boxed = Short.valueOf(reader.nextShort());
+                    break;
+                case 'I':
+                    boxed = Integer.valueOf(reader.nextInt());
+                    break;
+                case 'J':
+                    boxed = Long.valueOf(reader.nextLong());
+                    break;
+                case 'F':
+                    boxed = Float.valueOf(reader.nextFloat());
+                    break;
+                case 'D':
+                    boxed = Double.valueOf(reader.nextDouble());
+                    break;
+                default:
+                    throwUnexpectedType(from);
+                    break;
             }
             writer.putNextReference(to.cast(boxed), to);
         }
 
-        private static void explicitCast(final StackFrameReader reader, final Class<?> from,
-                                         final StackFrameWriter writer, final Class<?> to) {
+        private static void explicitCast(
+                final StackFrameReader reader,
+                final Class<?> from,
+                final StackFrameWriter writer,
+                final Class<?> to) {
             if (from.equals(to)) {
                 StackFrameAccessor.copyNext(reader, writer, from);
                 return;
@@ -2292,7 +2938,7 @@
                 Object ref = reader.nextReference(from);
                 if (to.isPrimitive()) {
                     // |from| is a reference type, |to| is a primitive type,
-                    unbox(ref, from, writer, to);
+                    unbox(ref, writer, to);
                 } else if (to.isInterface()) {
                     // Pass from without a cast according to description for
                     // {@link java.lang.invoke.MethodHandles#explicitCastArguments()}.
@@ -2304,4 +2950,164 @@
             }
         }
     }
+
+    /** Implements {@code MethodHandles.loop}. */
+    static class Loop extends Transformer {
+
+        /** Loop variable initialization methods. */
+        final MethodHandle[] inits;
+
+        /** Loop variable step methods. */
+        final MethodHandle[] steps;
+
+        /** Loop variable predicate methods. */
+        final MethodHandle[] preds;
+
+        /** Loop return value calculating methods. */
+        final MethodHandle[] finis;
+
+        /** Synthetic method type for frame used to hold loop variables. */
+        final MethodType loopVarsType;
+
+        /** Range of loop variables in the frame used for loop variables. */
+        final Range loopVarsRange;
+
+        /** Range of suffix variables in the caller frame. */
+        final Range suffixRange;
+
+        public Loop(Class<?> loopReturnType,
+                    List<Class<?>> commonSuffix,
+                    MethodHandle[] finit,
+                    MethodHandle[] fstep,
+                    MethodHandle[] fpred,
+                    MethodHandle[] ffini) {
+            super(MethodType.methodType(loopReturnType, commonSuffix));
+
+            inits = finit;
+            steps = fstep;
+            preds = fpred;
+            finis = ffini;
+
+            loopVarsType = deduceLoopVarsType(finit);
+            loopVarsRange = EmulatedStackFrame.Range.all(loopVarsType);
+            suffixRange = EmulatedStackFrame.Range.all(type());
+        }
+
+        @Override
+        public void transform(EmulatedStackFrame callerFrame) throws Throwable {
+            final EmulatedStackFrame loopVarsFrame = EmulatedStackFrame.create(loopVarsType);
+            final StackFrameWriter loopVarsWriter = new StackFrameWriter();
+
+            init(callerFrame, loopVarsFrame, loopVarsWriter);
+
+            for (;;) {
+                loopVarsWriter.attach(loopVarsFrame);
+                for (int i = 0; i < steps.length; ++i) {
+                    // Future optimization opportunity: there is a good deal of StackFrame
+                    // allocation here, one is allocated per MH invocation. Consider caching
+                    // frames <method-type:stack-frame> and passing the cache on the stack.
+                    doStep(steps[i], callerFrame, loopVarsFrame, loopVarsWriter);
+                    boolean keepGoing = doPredicate(preds[i], callerFrame, loopVarsFrame);
+                    if (!keepGoing) {
+                        doFinish(finis[i], callerFrame, loopVarsFrame);
+                        return;
+                    }
+                }
+            }
+        }
+
+        private static MethodType deduceLoopVarsType(final MethodHandle[] inits) {
+            List<Class<?>> loopVarTypes = new ArrayList(inits.length);
+            for (MethodHandle init : inits) {
+                Class<?> returnType = init.type().returnType();
+                if (returnType != void.class) {
+                    loopVarTypes.add(returnType);
+                }
+            }
+            return MethodType.methodType(void.class, loopVarTypes);
+        }
+
+        private void init(final EmulatedStackFrame callerFrame,
+                          final EmulatedStackFrame loopVarsFrame,
+                          final StackFrameWriter loopVarsWriter) throws Throwable {
+            loopVarsWriter.attach(loopVarsFrame);
+            for (MethodHandle init : inits) {
+                EmulatedStackFrame initFrame = EmulatedStackFrame.create(init.type());
+                callerFrame.copyRangeTo(initFrame, suffixRange, 0, 0);
+
+                invokeExactFromTransform(init, initFrame);
+
+                final Class<?> loopVarType = init.type().returnType();
+                if (loopVarType != void.class) {
+                    StackFrameReader initReader = new StackFrameReader();
+                    initReader.attach(initFrame).makeReturnValueAccessor();
+                    copyNext(initReader, loopVarsWriter, loopVarType);
+                }
+            }
+        }
+
+        /**
+         * Creates a frame for invoking a method of specified type.
+         *
+         * The frame arguments are the loop variables followed by the arguments provided to the
+         * loop MethodHandle.
+         *
+         * @param mt the type of the method to be invoked.
+         * @param callerFrame the frame invoking the loop MethodHandle.
+         * @param loopVarsFrame the frame holding loop variables.
+         * @return an EmulatedStackFrame initialized with the required arguments.
+         */
+        private EmulatedStackFrame prepareFrame(final MethodType mt,
+                                                final EmulatedStackFrame callerFrame,
+                                                final EmulatedStackFrame loopVarsFrame) {
+            EmulatedStackFrame frame = EmulatedStackFrame.create(mt);
+
+            // Copy loop variables.
+            loopVarsFrame.copyRangeTo(frame, loopVarsRange, 0, 0);
+
+            // Copy arguments provided in the loop invoke().
+            callerFrame.copyRangeTo(frame,
+                                    suffixRange,
+                                    loopVarsRange.numReferences,
+                                    loopVarsRange.numBytes);
+            return frame;
+        }
+
+        private void doStep(final MethodHandle step,
+                            final EmulatedStackFrame callerFrame,
+                            final EmulatedStackFrame loopVarsFrame,
+                            final StackFrameWriter loopVarsWriter) throws Throwable {
+            final EmulatedStackFrame stepFrame =
+                prepareFrame(step.type(), callerFrame, loopVarsFrame);
+            invokeExactFromTransform(step, stepFrame);
+
+            final Class<?> loopVarType = step.type().returnType();
+            if (loopVarType != void.class) {
+                final StackFrameReader stepReader = new StackFrameReader();
+                stepReader.attach(stepFrame).makeReturnValueAccessor();
+                copyNext(stepReader, loopVarsWriter, loopVarType);
+            }
+        }
+
+        private boolean doPredicate(final MethodHandle pred,
+                                    final EmulatedStackFrame callerFrame,
+                                    final EmulatedStackFrame loopVarsFrame) throws Throwable {
+            final EmulatedStackFrame predFrame =
+                    prepareFrame(pred.type(), callerFrame, loopVarsFrame);
+            invokeExactFromTransform(pred, predFrame);
+
+            final StackFrameReader predReader = new StackFrameReader();
+            predReader.attach(predFrame).makeReturnValueAccessor();
+            return predReader.nextBoolean();
+        }
+
+        private void doFinish(final MethodHandle fini,
+                              final EmulatedStackFrame callerFrame,
+                              final EmulatedStackFrame loopVarsFrame) throws Throwable {
+            final EmulatedStackFrame finiFrame =
+                    prepareFrame(fini.type(), callerFrame, loopVarsFrame);
+            invokeExactFromTransform(fini, finiFrame);
+            finiFrame.copyReturnValueTo(callerFrame);
+        }
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/invoke/VarHandle.java b/ojluni/src/main/java/java/lang/invoke/VarHandle.java
index 7b5ac00..d163d40 100644
--- a/ojluni/src/main/java/java/lang/invoke/VarHandle.java
+++ b/ojluni/src/main/java/java/lang/invoke/VarHandle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package java.lang.invoke;
 
 import dalvik.system.VMRuntime;
+import jdk.internal.HotSpotIntrinsicCandidate;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
@@ -40,7 +41,7 @@
  * non-static fields, array elements, or components of an off-heap data
  * structure.  Access to such variables is supported under various
  * <em>access modes</em>, including plain read/write access, volatile
- * read/write access, and compare-and-swap.
+ * read/write access, and compare-and-set.
  *
  * <p>VarHandles are immutable and have no visible state.  VarHandles cannot be
  * subclassed by the user.
@@ -95,7 +96,7 @@
  * is {@code String}.  The access mode type for {@code compareAndSet} on this
  * VarHandle instance would be
  * {@code (String[] c1, int c2, String expectedValue, String newValue)boolean}.
- * Such a VarHandle instance may produced by the
+ * Such a VarHandle instance may be produced by the
  * {@link MethodHandles#arrayElementVarHandle(Class) array factory method} and
  * access array elements as follows:
  * <pre> {@code
@@ -199,7 +200,7 @@
  * and {@code double} on 32-bit platforms.
  *
  * <p>Access modes will override any memory ordering effects specified at
- * the declaration site of a variable.  For example, a VarHandle accessing a
+ * the declaration site of a variable.  For example, a VarHandle accessing
  * a field using the {@code get} access mode will access the field as
  * specified <em>by its access mode</em> even if that field is declared
  * {@code volatile}.  When mixed access is performed extreme care should be
@@ -417,7 +418,7 @@
  * {@link java.lang.invoke.MethodHandles#varHandleInvoker}.
  *
  * <h1>Interoperation between VarHandles and Java generics</h1>
- * A VarHandle can be obtained for a variable, such as a a field, which is
+ * A VarHandle can be obtained for a variable, such as a field, which is
  * declared with Java generic types.  As with the Core Reflection API, the
  * VarHandle's variable type will be constructed from the erasure of the
  * source-level type.  When a VarHandle access mode method is invoked, the
@@ -431,7 +432,6 @@
  * @see MethodHandles
  * @see MethodType
  * @since 9
- * @hide
  */
 public abstract class VarHandle {
     // Android-added: Using sun.misc.Unsafe for fence implementation.
@@ -491,8 +491,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object get(Object... args);
 
     /**
@@ -518,8 +517,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     void set(Object... args);
 
 
@@ -551,8 +549,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getVolatile(Object... args);
 
     /**
@@ -582,8 +579,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     void setVolatile(Object... args);
 
 
@@ -613,8 +609,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getOpaque(Object... args);
 
     /**
@@ -641,8 +636,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     void setOpaque(Object... args);
 
 
@@ -679,8 +673,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAcquire(Object... args);
 
     /**
@@ -711,8 +704,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     void setRelease(Object... args);
 
 
@@ -748,8 +740,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     boolean compareAndSet(Object... args);
 
     /**
@@ -784,8 +775,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object compareAndExchange(Object... args);
 
     /**
@@ -820,8 +810,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object compareAndExchangeAcquire(Object... args);
 
     /**
@@ -856,8 +845,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object compareAndExchangeRelease(Object... args);
 
     // Weak (spurious failures allowed)
@@ -896,8 +884,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     boolean weakCompareAndSetPlain(Object... args);
 
     /**
@@ -934,8 +921,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     boolean weakCompareAndSet(Object... args);
 
     /**
@@ -973,8 +959,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     boolean weakCompareAndSetAcquire(Object... args);
 
     /**
@@ -1012,8 +997,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     boolean weakCompareAndSetRelease(Object... args);
 
     /**
@@ -1046,8 +1030,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndSet(Object... args);
 
     /**
@@ -1080,8 +1063,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndSetAcquire(Object... args);
 
     /**
@@ -1114,8 +1096,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndSetRelease(Object... args);
 
     // Primitive adders
@@ -1151,8 +1132,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndAdd(Object... args);
 
     /**
@@ -1185,8 +1165,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndAddAcquire(Object... args);
 
     /**
@@ -1219,8 +1198,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndAddRelease(Object... args);
 
 
@@ -1261,8 +1239,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseOr(Object... args);
 
     /**
@@ -1299,8 +1276,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseOrAcquire(Object... args);
 
     /**
@@ -1337,8 +1313,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseOrRelease(Object... args);
 
     /**
@@ -1375,8 +1350,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseAnd(Object... args);
 
     /**
@@ -1413,8 +1387,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseAndAcquire(Object... args);
 
     /**
@@ -1451,8 +1424,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseAndRelease(Object... args);
 
     /**
@@ -1489,8 +1461,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseXor(Object... args);
 
     /**
@@ -1527,8 +1498,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseXorAcquire(Object... args);
 
     /**
@@ -1565,8 +1535,7 @@
      */
     public final native
     @MethodHandle.PolymorphicSignature
-    // Android-removed: unsupported annotation.
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     Object getAndBitwiseXorRelease(Object... args);
 
 
@@ -1574,7 +1543,7 @@
     enum AccessType {
         GET,
         SET,
-        COMPARE_AND_SWAP,
+        COMPARE_AND_SET,
         COMPARE_AND_EXCHANGE,
         GET_AND_UPDATE,
         // Android-added: Finer grained access types.
@@ -1596,7 +1565,7 @@
                     i = fillParameters(ps, receiver, intermediate);
                     ps[i] = value;
                     return MethodType.methodType(void.class, ps);
-                case COMPARE_AND_SWAP:
+                case COMPARE_AND_SET:
                     ps = allocateParameters(2, receiver, intermediate);
                     i = fillParameters(ps, receiver, intermediate);
                     ps[i++] = value;
@@ -1695,7 +1664,7 @@
          * method
          * {@link VarHandle#compareAndSet VarHandle.compareAndSet}
          */
-        COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP),
+        COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
@@ -1719,25 +1688,25 @@
          * method
          * {@link VarHandle#weakCompareAndSetPlain VarHandle.weakCompareAndSetPlain}
          */
-        WEAK_COMPARE_AND_SET_PLAIN("weakCompareAndSetPlain", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET_PLAIN("weakCompareAndSetPlain", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
          */
-        WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
          */
-        WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
          */
-        WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP),
+        WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SET),
         /**
          * The access mode whose access is specified by the corresponding
          * method
@@ -1832,10 +1801,12 @@
 
         static final Map<String, AccessMode> methodNameToAccessMode;
         static {
-            // Initial capacity of # values is sufficient to avoid resizes
-            // for the smallest table size (32)
-            methodNameToAccessMode = new HashMap<>(AccessMode.values().length);
-            for (AccessMode am : AccessMode.values()) {
+            AccessMode[] values = AccessMode.values();
+            // Initial capacity of # values divided by the load factor is sufficient
+            // to avoid resizes for the smallest table size (64)
+            int initialCapacity = (int)(values.length / 0.75f) + 1;
+            methodNameToAccessMode = new HashMap<>(initialCapacity);
+            for (AccessMode am : values) {
                 methodNameToAccessMode.put(am.methodName, am);
             }
         }
@@ -1869,7 +1840,7 @@
          *         value associated with method name (indicating the method
          *         name does not correspond to a {@code VarHandle}
          *         signature-polymorphic method name).
-         * @see #methodName
+         * @see #methodName()
          */
         public static AccessMode valueFromMethodName(String methodName) {
             AccessMode am = methodNameToAccessMode.get(methodName);
@@ -2110,12 +2081,7 @@
     private static final long VFORM_OFFSET;
 
     static {
-        try {
-            VFORM_OFFSET = UNSAFE.objectFieldOffset(VarHandle.class.getDeclaredField("vform"));
-        }
-        catch (ReflectiveOperationException e) {
-            throw newInternalError(e);
-        }
+        VFORM_OFFSET = UNSAFE.objectFieldOffset(VarHandle.class, "vform");
 
         // The VarHandleGuards must be initialized to ensure correct
         // compilation of the guard methods
@@ -2298,7 +2264,7 @@
 
         ATOMIC_UPDATE_ACCESS_MODES_BIT_MASK =
                 accessTypesToBitMask(EnumSet.of(AccessType.COMPARE_AND_EXCHANGE,
-                                                AccessType.COMPARE_AND_SWAP,
+                                                AccessType.COMPARE_AND_SET,
                                                 AccessType.GET_AND_UPDATE));
 
         NUMERIC_ATOMIC_UPDATE_ACCESS_MODES_BIT_MASK =
diff --git a/ojluni/src/main/java/java/lang/package-info.java b/ojluni/src/main/java/java/lang/package-info.java
index aa7a79d..882a610 100644
--- a/ojluni/src/main/java/java/lang/package-info.java
+++ b/ojluni/src/main/java/java/lang/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,8 +57,8 @@
  * by the {@code throw} statement. Subclasses of {@code Throwable}
  * represent errors and exceptions.
  *
- * <a name="charenc"></a>
- * <h3>Character Encodings</h3>
+ * <a id="charenc"></a>
+ * <h2>Character Encodings</h2>
  *
  * The specification of the {@link java.nio.charset.Charset
  * java.nio.charset.Charset} class describes the naming conventions
@@ -66,6 +66,6 @@
  * that must be supported by every implementation of the Java
  * platform.
  *
- * @since JDK1.0
+ * @since 1.0
  */
 package java.lang;
diff --git a/ojluni/src/main/java/java/lang/ref/Cleaner.java b/ojluni/src/main/java/java/lang/ref/Cleaner.java
new file mode 100644
index 0000000..04e2101
--- /dev/null
+++ b/ojluni/src/main/java/java/lang/ref/Cleaner.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.ref;
+
+import jdk.internal.ref.CleanerImpl;
+
+import java.util.Objects;
+import java.util.concurrent.ThreadFactory;
+import java.util.function.Function;
+
+/**
+ * {@code Cleaner} manages a set of object references and corresponding cleaning actions.
+ * <p>
+ * Cleaning actions are {@link #register(Object object, Runnable action) registered}
+ * to run after the cleaner is notified that the object has become
+ * phantom reachable.
+ * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be
+ * notified when the <a href="package-summary.html#reachability">reachability</a>
+ * changes.
+ * <p>
+ * Each cleaner operates independently, managing the pending cleaning actions
+ * and handling threading and termination when the cleaner is no longer in use.
+ * Registering an object reference and corresponding cleaning action returns
+ * a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke
+ * the {@link Cleanable#clean clean} method when the object is closed or
+ * no longer needed.
+ * The cleaning action is a {@link Runnable} to be invoked at most once when
+ * the object has become phantom reachable unless it has already been explicitly cleaned.
+ * Note that the cleaning action must not refer to the object being registered.
+ * If so, the object will not become phantom reachable and the cleaning action
+ * will not be invoked automatically.
+ * <p>
+ * The execution of the cleaning action is performed
+ * by a thread associated with the cleaner.
+ * All exceptions thrown by the cleaning action are ignored.
+ * The cleaner and other cleaning actions are not affected by
+ * exceptions in a cleaning action.
+ * The thread runs until all registered cleaning actions have
+ * completed and the cleaner itself is reclaimed by the garbage collector.
+ * <p>
+ * The behavior of cleaners during {@link System#exit(int) System.exit}
+ * is implementation specific. No guarantees are made relating
+ * to whether cleaning actions are invoked or not.
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor or
+ * method in this class will cause a
+ * {@link java.lang.NullPointerException NullPointerException} to be thrown.
+ *
+ * @apiNote
+ * The cleaning action is invoked only after the associated object becomes
+ * phantom reachable, so it is important that the object implementing the
+ * cleaning action does not hold references to the object.
+ * In this example, a static class encapsulates the cleaning state and action.
+ * An "inner" class, anonymous or not,  must not be used because it implicitly
+ * contains a reference to the outer instance, preventing it from becoming
+ * phantom reachable.
+ * The choice of a new cleaner or sharing an existing cleaner is determined
+ * by the use case.
+ * <p>
+ * If the CleaningExample is used in a try-finally block then the
+ * {@code close} method calls the cleaning action.
+ * If the {@code close} method is not called, the cleaning action is called
+ * by the Cleaner when the CleaningExample instance has become phantom reachable.
+ * <pre>{@code
+ * public class CleaningExample implements AutoCloseable {
+ *        // A cleaner, preferably one shared within a library
+ *        private static final Cleaner cleaner = <cleaner>;
+ *
+ *        static class State implements Runnable {
+ *
+ *            State(...) {
+ *                // initialize State needed for cleaning action
+ *            }
+ *
+ *            public void run() {
+ *                // cleanup action accessing State, executed at most once
+ *            }
+ *        }
+ *
+ *        private final State;
+ *        private final Cleaner.Cleanable cleanable
+ *
+ *        public CleaningExample() {
+ *            this.state = new State(...);
+ *            this.cleanable = cleaner.register(this, state);
+ *        }
+ *
+ *        public void close() {
+ *            cleanable.clean();
+ *        }
+ *    }
+ * }</pre>
+ * The cleaning action could be a lambda but all too easily will capture
+ * the object reference, by referring to fields of the object being cleaned,
+ * preventing the object from becoming phantom reachable.
+ * Using a static nested class, as above, will avoid accidentally retaining the
+ * object reference.
+ * <p>
+ * <a id="compatible-cleaners"></a>
+ * Cleaning actions should be prepared to be invoked concurrently with
+ * other cleaning actions.
+ * Typically the cleaning actions should be very quick to execute
+ * and not block. If the cleaning action blocks, it may delay processing
+ * other cleaning actions registered to the same cleaner.
+ * All cleaning actions registered to a cleaner should be mutually compatible.
+ * @since 9
+ */
+public final class Cleaner {
+
+    /**
+     * The Cleaner implementation.
+     */
+    final CleanerImpl impl;
+
+    static {
+        CleanerImpl.setCleanerImplAccess(new Function<Cleaner, CleanerImpl>() {
+            @Override
+            public CleanerImpl apply(Cleaner cleaner) {
+                return cleaner.impl;
+            }
+        });
+    }
+
+    /**
+     * Construct a Cleaner implementation and start it.
+     */
+    private Cleaner() {
+        impl = new CleanerImpl();
+    }
+
+    /**
+     * Returns a new {@code Cleaner}.
+     * <p>
+     * The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
+     * to process the phantom reachable objects and to invoke cleaning actions.
+     * The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
+     * of the thread is set to the
+     * {@link ClassLoader#getSystemClassLoader() system class loader}.
+     * The thread has no permissions, enforced only if a
+     * {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
+     * <p>
+     * The cleaner terminates when it is phantom reachable and all of the
+     * registered cleaning actions are complete.
+     *
+     * @return a new {@code Cleaner}
+     *
+     * @throws  SecurityException  if the current thread is not allowed to
+     *               create or start the thread.
+     */
+    public static Cleaner create() {
+        Cleaner cleaner = new Cleaner();
+        cleaner.impl.start(cleaner, null);
+        return cleaner;
+    }
+
+    /**
+     * Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
+     * <p>
+     * A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
+     * method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
+     * and started to process phantom reachable objects and invoke cleaning actions.
+     * On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
+     * must provide a Thread that is suitable for performing the cleaning actions.
+     * <p>
+     * The cleaner terminates when it is phantom reachable and all of the
+     * registered cleaning actions are complete.
+     *
+     * @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
+     *                      to process cleaning actions
+     * @return a new {@code Cleaner}
+     *
+     * @throws  IllegalThreadStateException  if the thread from the thread
+     *               factory was {@link Thread.State#NEW not a new thread}.
+     * @throws  SecurityException  if the current thread is not allowed to
+     *               create or start the thread.
+     */
+    public static Cleaner create(ThreadFactory threadFactory) {
+        Objects.requireNonNull(threadFactory, "threadFactory");
+        Cleaner cleaner = new Cleaner();
+        cleaner.impl.start(cleaner, threadFactory);
+        return cleaner;
+    }
+
+    /**
+     * Registers an object and a cleaning action to run when the object
+     * becomes phantom reachable.
+     * Refer to the <a href="#compatible-cleaners">API Note</a> above for
+     * cautions about the behavior of cleaning actions.
+     *
+     * @param obj   the object to monitor
+     * @param action a {@code Runnable} to invoke when the object becomes phantom reachable
+     * @return a {@code Cleanable} instance
+     */
+    public Cleanable register(Object obj, Runnable action) {
+        Objects.requireNonNull(obj, "obj");
+        Objects.requireNonNull(action, "action");
+        return new CleanerImpl.PhantomCleanableRef(obj, this, action);
+    }
+
+    /**
+     * {@code Cleanable} represents an object and a
+     * cleaning action registered in a {@code Cleaner}.
+     * @since 9
+     */
+    public interface Cleanable {
+        /**
+         * Unregisters the cleanable and invokes the cleaning action.
+         * The cleanable's cleaning action is invoked at most once
+         * regardless of the number of calls to {@code clean}.
+         */
+        void clean();
+    }
+
+}
diff --git a/ojluni/src/main/java/java/lang/ref/PhantomReference.java b/ojluni/src/main/java/java/lang/ref/PhantomReference.java
index 1c1364a..b79e338 100644
--- a/ojluni/src/main/java/java/lang/ref/PhantomReference.java
+++ b/ojluni/src/main/java/java/lang/ref/PhantomReference.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,22 +29,19 @@
 /**
  * Phantom reference objects, which are enqueued after the collector
  * determines that their referents may otherwise be reclaimed.  Phantom
- * references are most often used for scheduling pre-mortem cleanup actions in
- * a more flexible way than is possible with the Java finalization mechanism.
+ * references are most often used to schedule post-mortem cleanup actions.
  *
- * <p> If the garbage collector determines at a certain point in time that the
- * referent of a phantom reference is <a
- * href="package-summary.html#reachability">phantom reachable</a>, then at that
- * time or at some later time it will enqueue the reference.
+ * <p> Suppose the garbage collector determines at a certain point in time
+ * that an object is <a href="package-summary.html#reachability">
+ * phantom reachable</a>.  At that time it will atomically clear
+ * all phantom references to that object and all phantom references to
+ * any other phantom-reachable objects from which that object is reachable.
+ * At the same time or at some later time it will enqueue those newly-cleared
+ * phantom references that are registered with reference queues.
  *
  * <p> In order to ensure that a reclaimable object remains so, the referent of
- * a phantom reference may not be retrieved: The <code>get</code> method of a
- * phantom reference always returns <code>null</code>.
- *
- * <p> Unlike soft and weak references, phantom references are not
- * automatically cleared by the garbage collector as they are enqueued.  An
- * object that is reachable via phantom references will remain so until all
- * such references are cleared or themselves become unreachable.
+ * a phantom reference may not be retrieved: The {@code get} method of a
+ * phantom reference always returns {@code null}.
  *
  * @author   Mark Reinhold
  * @since    1.2
@@ -55,9 +52,9 @@
     /**
      * Returns this reference object's referent.  Because the referent of a
      * phantom reference is always inaccessible, this method always returns
-     * <code>null</code>.
+     * {@code null}.
      *
-     * @return  <code>null</code>
+     * @return {@code null}
      */
     public T get() {
         return null;
@@ -67,14 +64,14 @@
      * Creates a new phantom reference that refers to the given object and
      * is registered with the given queue.
      *
-     * <p> It is possible to create a phantom reference with a <tt>null</tt>
-     * queue, but such a reference is completely useless: Its <tt>get</tt>
-     * method will always return null and, since it does not have a queue, it
-     * will never be enqueued.
+     * <p> It is possible to create a phantom reference with a {@code null}
+     * queue, but such a reference is completely useless: Its {@code get}
+     * method will always return {@code null} and, since it does not have a queue,
+     * it will never be enqueued.
      *
      * @param referent the object the new phantom reference will refer to
      * @param q the queue with which the reference is to be registered,
-     *          or <tt>null</tt> if registration is not required
+     *          or {@code null} if registration is not required
      */
     public PhantomReference(T referent, ReferenceQueue<? super T> q) {
         super(referent, q);
diff --git a/ojluni/src/main/java/java/lang/ref/Reference.java b/ojluni/src/main/java/java/lang/ref/Reference.java
index faaddd7..f244e81 100644
--- a/ojluni/src/main/java/java/lang/ref/Reference.java
+++ b/ojluni/src/main/java/java/lang/ref/Reference.java
@@ -57,8 +57,9 @@
      * Used by the reference processor to determine whether or not the referent
      * can be immediately returned. Because the referent might get swept during
      * GC, the slow path, which passes through JNI, must be taken.
-     * This is only modified with mutators suspended, and hence does not need to
-     * be volatile.
+     * After initialization, this is only accessed by native code. It is not
+     * used with the concurrent copying collector. It is enabled with mutators
+     * suspended, but disabled asynchronously.
      */
     private static boolean slowPathEnabled = false;
 
@@ -116,11 +117,11 @@
     /**
      * Tests if the referent of this reference object is {@code obj}.
      * Using a {@code null} {@code obj} returns {@code true} if the
-     * reference object has been cleared.
+     * reference object has been cleared. Prefer this to a comparison
+     * with the result of {@code get}.
      *
      * @param  obj the object to compare with this reference object's referent
      * @return {@code true} if {@code obj} is the referent of this reference object
-     * @hide
      */
     public final boolean refersTo(T obj) {
         return refersTo0(obj);
diff --git a/ojluni/src/main/java/java/lang/ref/ReferenceQueue.java b/ojluni/src/main/java/java/lang/ref/ReferenceQueue.java
index 72e55c1b..6923a3b 100644
--- a/ojluni/src/main/java/java/lang/ref/ReferenceQueue.java
+++ b/ojluni/src/main/java/java/lang/ref/ReferenceQueue.java
@@ -27,6 +27,7 @@
 package java.lang.ref;
 
 import sun.misc.Cleaner;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Reference queues, to which registered reference objects are appended by the
@@ -50,6 +51,8 @@
 
     private final Object lock = new Object();
 
+    private static ReferenceQueue currentQueue = null;  // Current target of enqueuePending.
+
     /**
      * Constructs a new reference-object queue.
      */
@@ -93,6 +96,16 @@
     }
 
     /**
+     * The queue currently being targeted by enqueuePending. Used only to get slightly
+     * informative output for timeouts. May be read via a data race, but only for crash
+     * debugging output.
+     * @hide
+     */
+    public static ReferenceQueue getCurrentQueue() {
+        return currentQueue;
+    }
+
+    /**
      * Test if the given reference object has been enqueued but not yet
      * removed from the queue, assuming this is the reference object's queue.
      */
@@ -216,10 +229,11 @@
      *
      * @hide
      */
-    public static void enqueuePending(Reference<?> list) {
+    public static void enqueuePending(Reference<?> list, AtomicInteger progressCounter) {
         Reference<?> start = list;
         do {
             ReferenceQueue queue = list.queue;
+            currentQueue = queue;
             if (queue == null) {
                 Reference<?> next = list.pendingNext;
 
@@ -230,9 +244,12 @@
                 list = next;
             } else {
                 // To improve performance, we try to avoid repeated
-                // synchronization on the same queue by batching enqueue of
+                // synchronization on the same queue by batching enqueueing of
                 // consecutive references in the list that have the same
-                // queue.
+                // queue. We limit this so that progressCounter gets incremented
+                // occasionally,
+                final int MAX_ITERS = 100;
+                int i = 0;
                 synchronized (queue.lock) {
                     do {
                         Reference<?> next = list.pendingNext;
@@ -244,10 +261,11 @@
                         list.pendingNext = list;
                         queue.enqueueLocked(list);
                         list = next;
-                    } while (list != start && list.queue == queue);
+                    } while (list != start && list.queue == queue && ++i <= MAX_ITERS);
                     queue.lock.notifyAll();
                 }
             }
+            progressCounter.incrementAndGet();
         } while (list != start);
     }
 
diff --git a/ojluni/src/main/java/java/lang/ref/SoftReference.java b/ojluni/src/main/java/java/lang/ref/SoftReference.java
index 272d1bd..a250ad7 100644
--- a/ojluni/src/main/java/java/lang/ref/SoftReference.java
+++ b/ojluni/src/main/java/java/lang/ref/SoftReference.java
@@ -41,7 +41,7 @@
  *
  * <p> All soft references to softly-reachable objects are guaranteed to have
  * been cleared before the virtual machine throws an
- * <code>OutOfMemoryError</code>.  Otherwise no constraints are placed upon the
+ * {@code OutOfMemoryError}.  Otherwise no constraints are placed upon the
  * time at which a soft reference will be cleared or the order in which a set
  * of such references to different objects will be cleared.  Virtual machine
  * implementations are, however, encouraged to bias against clearing
@@ -70,7 +70,7 @@
     /**
      * Timestamp clock, updated by the garbage collector
      */
-    static private long clock;
+    private static long clock;
 
     /**
      * Timestamp updated by each invocation of the get method.  The VM may use
@@ -96,7 +96,7 @@
      *
      * @param referent object the new soft reference will refer to
      * @param q the queue with which the reference is to be registered,
-     *          or <tt>null</tt> if registration is not required
+     *          or {@code null} if registration is not required
      *
      */
     public SoftReference(T referent, ReferenceQueue<? super T> q) {
@@ -107,10 +107,10 @@
     /**
      * Returns this reference object's referent.  If this reference object has
      * been cleared, either by the program or by the garbage collector, then
-     * this method returns <code>null</code>.
+     * this method returns {@code null}.
      *
      * @return   The object to which this reference refers, or
-     *           <code>null</code> if this reference object has been cleared
+     *           {@code null} if this reference object has been cleared
      */
     public T get() {
         T o = super.get();
diff --git a/ojluni/src/main/java/java/lang/ref/WeakReference.java b/ojluni/src/main/java/java/lang/ref/WeakReference.java
index 025949a..fdf2b5c 100644
--- a/ojluni/src/main/java/java/lang/ref/WeakReference.java
+++ b/ojluni/src/main/java/java/lang/ref/WeakReference.java
@@ -63,7 +63,7 @@
      *
      * @param referent object the new weak reference will refer to
      * @param q the queue with which the reference is to be registered,
-     *          or <tt>null</tt> if registration is not required
+     *          or {@code null} if registration is not required
      */
     public WeakReference(T referent, ReferenceQueue<? super T> q) {
         super(referent, q);
diff --git a/ojluni/src/main/java/java/lang/ref/package-info.java b/ojluni/src/main/java/java/lang/ref/package-info.java
index cc7f9ef..3f37878 100644
--- a/ojluni/src/main/java/java/lang/ref/package-info.java
+++ b/ojluni/src/main/java/java/lang/ref/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,113 +23,109 @@
  * questions.
  */
 
-
 /**
- * Provides reference-object classes, which support a limited degree of
- * interaction with the garbage collector.  A program may use a reference object
- * to maintain a reference to some other object in such a way that the latter
- * object may still be reclaimed by the collector.  A program may also arrange to
- * be notified some time after the collector has determined that the reachability
- * of a given object has changed.
+ * Provides reference-object classes, which support a limited degree
+ * of interaction with the garbage collector.  A program may use a
+ * reference object to maintain a reference to some other object in
+ * such a way that the latter object may still be reclaimed by the
+ * collector.  A program may also arrange to be notified some time
+ * after the collector has determined that the reachability of a given
+ * object has changed.
  *
+ *<h2>Package Specification</h2>
  *
- * <h2>Package Specification</h2>
+ * A <em>reference object</em> encapsulates a reference to some other
+ * object so that the reference itself may be examined and manipulated
+ * like any other object.  Three types of reference objects are
+ * provided, each weaker than the last: <em>soft</em>, <em>weak</em>,
+ * and <em>phantom</em>.  Each type corresponds to a different level
+ * of reachability, as defined below.  Soft references are for
+ * implementing memory-sensitive caches, weak references are for
+ * implementing canonicalizing mappings that do not prevent their keys
+ * (or values) from being reclaimed, and phantom references are for
+ * scheduling post-mortem cleanup actions.
+ * Post-mortem cleanup actions can be registered and managed by a
+ * {@link java.lang.ref.Cleaner}.
  *
- * A <em>reference object</em> encapsulates a reference to some other object so
- * that the reference itself may be examined and manipulated like any other
- * object.  Three types of reference objects are provided, each weaker than the
- * last: <em>soft</em>, <em>weak</em>, and <em>phantom</em>.  Each type
- * corresponds to a different level of reachability, as defined below.  Soft
- * references are for implementing memory-sensitive caches, weak references are
- * for implementing canonicalizing mappings that do not prevent their keys (or
- * values) from being reclaimed, and phantom references are for scheduling
- * pre-mortem cleanup actions in a more flexible way than is possible with the
- * Java finalization mechanism.
- *
- * <p> Each reference-object type is implemented by a subclass of the abstract
- * base <code>{@link java.lang.ref.Reference}</code> class.  An instance of one of
- * these subclasses encapsulates a single reference to a particular object, called
- * the <em>referent</em>.  Every reference object provides methods for getting and
- * clearing the reference.  Aside from the clearing operation reference objects
- * are otherwise immutable, so no <code>set</code> operation is provided.  A
- * program may further subclass these subclasses, adding whatever fields and
- * methods are required for its purposes, or it may use these subclasses without
- * change.
- *
+ * <p> Each reference-object type is implemented by a subclass of the
+ * abstract base {@link java.lang.ref.Reference} class.
+ * An instance of one of these subclasses encapsulates a single
+ * reference to a particular object, called the <em>referent</em>.
+ * Every reference object provides methods for getting and clearing
+ * the reference.  Aside from the clearing operation reference objects
+ * are otherwise immutable, so no {@code set} operation is
+ * provided.  A program may further subclass these subclasses, adding
+ * whatever fields and methods are required for its purposes, or it
+ * may use these subclasses without change.
  *
  * <h3>Notification</h3>
  *
- * A program may request to be notified of changes in an object's reachability by
- * <em>registering</em> an appropriate reference object with a <em>reference
- * queue</em> at the time the reference object is created.  Some time after the
- * garbage collector determines that the reachability of the referent has changed
- * to the value corresponding to the type of the reference, it will add the
- * reference to the associated queue.  At this point, the reference is considered
- * to be <em>enqueued</em>.  The program may remove references from a queue either
- * by polling or by blocking until a reference becomes available.  Reference
- * queues are implemented by the <code>{@link java.lang.ref.ReferenceQueue}</code>
- * class.
+ * A program may request to be notified of changes in an object's
+ * reachability by <em>registering</em> an appropriate reference
+ * object with a <em>reference queue</em> at the time the reference
+ * object is created.  Some time after the garbage collector
+ * determines that the reachability of the referent has changed to the
+ * value corresponding to the type of the reference, it will clear the
+ * reference and add it to the associated queue.  At this point, the
+ * reference is considered to be <em>enqueued</em>.  The program may remove
+ * references from a queue either by polling or by blocking until a
+ * reference becomes available.  Reference queues are implemented by
+ * the {@link java.lang.ref.ReferenceQueue} class.
  *
- * <p> The relationship between a registered reference object and its queue is
- * one-sided.  That is, a queue does not keep track of the references that are
- * registered with it.  If a registered reference becomes unreachable itself, then
- * it will never be enqueued.  It is the responsibility of the program using
- * reference objects to ensure that the objects remain reachable for as long as
- * the program is interested in their referents.
+ * <p> The relationship between a registered reference object and its
+ * queue is one-sided.  That is, a queue does not keep track of the
+ * references that are registered with it.  If a registered reference
+ * becomes unreachable itself, then it will never be enqueued.  It is
+ * the responsibility of the program using reference objects to ensure
+ * that the objects remain reachable for as long as the program is
+ * interested in their referents.
  *
- * <p> While some programs will choose to dedicate a thread to removing reference
- * objects from one or more queues and processing them, this is by no means
- * necessary.  A tactic that often works well is to examine a reference queue in
- * the course of performing some other fairly-frequent action.  For example, a
- * hashtable that uses weak references to implement weak keys could poll its
- * reference queue each time the table is accessed.  This is how the <code>{@link
- * java.util.WeakHashMap}</code> class works.  Because the <code>{@link
- * java.lang.ref.ReferenceQueue#poll ReferenceQueue.poll}</code> method simply
- * checks an internal data structure, this check will add little overhead to the
- * hashtable access methods.
+ * <p> While some programs will choose to dedicate a thread to
+ * removing reference objects from one or more queues and processing
+ * them, this is by no means necessary.  A tactic that often works
+ * well is to examine a reference queue in the course of performing
+ * some other fairly-frequent action.  For example, a hashtable that
+ * uses weak references to implement weak keys could poll its
+ * reference queue each time the table is accessed.  This is how the
+ * {@link java.util.WeakHashMap} class works.  Because
+ * the {@link java.lang.ref.ReferenceQueue#poll
+ * ReferenceQueue.poll} method simply checks an internal data
+ * structure, this check will add little overhead to the hashtable
+ * access methods.
  *
- *
- * <h3>Automatically-cleared references</h3>
- *
- * Soft and weak references are automatically cleared by the collector before
- * being added to the queues with which they are registered, if any.  Therefore
- * soft and weak references need not be registered with a queue in order to be
- * useful, while phantom references do.  An object that is reachable via phantom
- * references will remain so until all such references are cleared or themselves
- * become unreachable.
- *
- *
- * <a name="reachability"></a>
+ * <a id="reachability"></a>
  * <h3>Reachability</h3>
  *
- * Going from strongest to weakest, the different levels of reachability reflect
- * the life cycle of an object.  They are operationally defined as follows:
+ * Going from strongest to weakest, the different levels of
+ * reachability reflect the life cycle of an object.  They are
+ * operationally defined as follows:
  *
  * <ul>
  *
- * <li> An object is <em>strongly reachable</em> if it can be reached by some
- * thread without traversing any reference objects.  A newly-created object is
- * strongly reachable by the thread that created it.
+ * <li> An object is <em>strongly reachable</em> if it can be reached
+ * by some thread without traversing any reference objects.  A
+ * newly-created object is strongly reachable by the thread that
+ * created it.
  *
- * <li> An object is <em>softly reachable</em> if it is not strongly reachable but
- * can be reached by traversing a soft reference.
+ * <li> An object is <em>softly reachable</em> if it is not strongly
+ * reachable but can be reached by traversing a soft reference.
  *
- * <li> An object is <em>weakly reachable</em> if it is neither strongly nor
- * softly reachable but can be reached by traversing a weak reference.  When the
- * weak references to a weakly-reachable object are cleared, the object becomes
- * eligible for finalization.
+ * <li> An object is <em>weakly reachable</em> if it is neither
+ * strongly nor softly reachable but can be reached by traversing a
+ * weak reference.  When the weak references to a weakly-reachable
+ * object are cleared, the object becomes eligible for finalization.
  *
- * <li> An object is <em>phantom reachable</em> if it is neither strongly, softly,
- * nor weakly reachable, it has been finalized, and some phantom reference refers
- * to it.
+ * <li> An object is <em>phantom reachable</em> if it is neither
+ * strongly, softly, nor weakly reachable, it has been finalized, and
+ * some phantom reference refers to it.
  *
- * <li> Finally, an object is <em>unreachable</em>, and therefore eligible for
- * reclamation, when it is not reachable in any of the above ways.
+ * <li> Finally, an object is <em>unreachable</em>, and therefore
+ * eligible for reclamation, when it is not reachable in any of the
+ * above ways.
  *
  * </ul>
  *
- *
- * @author	  Mark Reinhold
- * @since	  1.2
+ * @author        Mark Reinhold
+ * @since         1.2
  */
 package java.lang.ref;
diff --git a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
index 7bb2a60..7338802 100644
--- a/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
+++ b/ojluni/src/main/java/java/lang/reflect/AnnotatedElement.java
@@ -100,28 +100,44 @@
  * <p>The table below summarizes which kind of annotation presence
  * different methods in this interface examine.
  *
- * <table border>
+ * <table class="plain">
  * <caption>Overview of kind of presence detected by different AnnotatedElement methods</caption>
- * <tr><th colspan=2></th><th colspan=4>Kind of Presence</th>
- * <tr><th colspan=2>Method</th><th>Directly Present</th><th>Indirectly Present</th><th>Present</th><th>Associated</th>
- * <tr><td align=right>{@code T}</td><td>{@link #getAnnotation(Class) getAnnotation(Class&lt;T&gt;)}
- * <td></td><td></td><td>X</td><td></td>
+ * <thead>
+ * <tr><th colspan=2 scope="col">Method</th>
+ *     <th colspan=4 scope="col">Kind of Presence</th>
+ * <tr><th scope="col">Return Type</th>
+ *     <th scope="col">Signature</th>
+ *     <th scope="col">Directly Present</th>
+ *     <th scope="col">Indirectly Present</th>
+ *     <th scope="col">Present</th>
+ *     <th scope="col">Associated</th>
+ * </thead>
+ * <tbody>
+ * <tr><td style="text-align:right">{@code T}</td>
+ * <th scope="row" style="font-weight:normal; text-align:left">{@link #getAnnotation(Class) getAnnotation(Class&lt;T&gt;)}
+ * <td></td><td></td><td style="text-align:center">X</td><td></td>
  * </tr>
- * <tr><td align=right>{@code Annotation[]}</td><td>{@link #getAnnotations getAnnotations()}
- * <td></td><td></td><td>X</td><td></td>
+ * <tr><td style="text-align:right">{@code Annotation[]}</td>
+ * <th scope="row" style="font-weight:normal; text-align:left">{@link #getAnnotations getAnnotations()}
+ * <td></td><td></td><td style="text-align:center">X</td><td></td>
  * </tr>
- * <tr><td align=right>{@code T[]}</td><td>{@link #getAnnotationsByType(Class) getAnnotationsByType(Class&lt;T&gt;)}
- * <td></td><td></td><td></td><td>X</td>
+ * <tr><td style="text-align:right">{@code T[]}</td>
+ * <th scope="row" style="font-weight:normal; text-align:left">{@link #getAnnotationsByType(Class) getAnnotationsByType(Class&lt;T&gt;)}
+ * <td></td><td></td><td></td><td style="text-align:center">X</td>
  * </tr>
- * <tr><td align=right>{@code T}</td><td>{@link #getDeclaredAnnotation(Class) getDeclaredAnnotation(Class&lt;T&gt;)}
- * <td>X</td><td></td><td></td><td></td>
+ * <tr><td style="text-align:right">{@code T}</td>
+ * <th scope="row" style="font-weight:normal; text-align:left">{@link #getDeclaredAnnotation(Class) getDeclaredAnnotation(Class&lt;T&gt;)}
+ * <td style="text-align:center">X</td><td></td><td></td><td></td>
  * </tr>
- * <tr><td align=right>{@code Annotation[]}</td><td>{@link #getDeclaredAnnotations getDeclaredAnnotations()}
- * <td>X</td><td></td><td></td><td></td>
+ * <tr><td style="text-align:right">{@code Annotation[]}</td>
+ * <th scope="row" style="font-weight:normal; text-align:left">{@link #getDeclaredAnnotations getDeclaredAnnotations()}
+ * <td style="text-align:center">X</td><td></td><td></td><td></td>
  * </tr>
- * <tr><td align=right>{@code T[]}</td><td>{@link #getDeclaredAnnotationsByType(Class) getDeclaredAnnotationsByType(Class&lt;T&gt;)}
- * <td>X</td><td>X</td><td></td><td></td>
+ * <tr><td style="text-align:right">{@code T[]}</td>
+ * <th scope="row" style="font-weight:normal; text-align:left">{@link #getDeclaredAnnotationsByType(Class) getDeclaredAnnotationsByType(Class&lt;T&gt;)}
+ * <td style="text-align:center">X</td><td style="text-align:center">X</td><td></td><td></td>
  * </tr>
+ * </tbody>
  * </table>
  *
  * <p>For an invocation of {@code get[Declared]AnnotationsByType( Class <
diff --git a/ojluni/src/main/java/java/lang/reflect/Array.java b/ojluni/src/main/java/java/lang/reflect/Array.java
index db7e9a2..9bf81c4 100644
--- a/ojluni/src/main/java/java/lang/reflect/Array.java
+++ b/ojluni/src/main/java/java/lang/reflect/Array.java
@@ -37,6 +37,7 @@
  * conversion would occur.
  *
  * @author Nakul Saraiya
+ * @since 1.1
  */
 public final
 class Array {
diff --git a/ojluni/src/main/java/java/lang/reflect/InvocationTargetException.java b/ojluni/src/main/java/java/lang/reflect/InvocationTargetException.java
index 360d0ba..e1133e3 100644
--- a/ojluni/src/main/java/java/lang/reflect/InvocationTargetException.java
+++ b/ojluni/src/main/java/java/lang/reflect/InvocationTargetException.java
@@ -38,6 +38,7 @@
  *
  * @see Method
  * @see Constructor
+ * @since 1.1
  */
 public class InvocationTargetException extends ReflectiveOperationException {
     /**
diff --git a/ojluni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java b/ojluni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
index a9efc55..b485be1 100644
--- a/ojluni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
+++ b/ojluni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,4 +36,21 @@
  */
 public class MalformedParameterizedTypeException extends RuntimeException {
     private static final long serialVersionUID = -5696557788586220964L;
+
+    /**
+     * Constructs a {@code MalformedParameterizedTypeException} with
+     * no detail message.
+     */
+    public MalformedParameterizedTypeException() {
+        super();
+    }
+
+    /**
+     * Constructs a {@code MalformedParameterizedTypeException} with
+     * the given detail message.
+     * @param message the detail message; may be {@code null}
+     */
+    public MalformedParameterizedTypeException(String message) {
+        super(message);
+    }
 }
diff --git a/ojluni/src/main/java/java/lang/reflect/Member.java b/ojluni/src/main/java/java/lang/reflect/Member.java
index 2241d45..3ac457d 100644
--- a/ojluni/src/main/java/java/lang/reflect/Member.java
+++ b/ojluni/src/main/java/java/lang/reflect/Member.java
@@ -35,6 +35,7 @@
  * @see Constructor
  *
  * @author Nakul Saraiya
+ * @since 1.1
  */
 public
 interface Member {
diff --git a/ojluni/src/main/java/java/lang/reflect/Modifier.java b/ojluni/src/main/java/java/lang/reflect/Modifier.java
index 28d89bb..f27f14e 100644
--- a/ojluni/src/main/java/java/lang/reflect/Modifier.java
+++ b/ojluni/src/main/java/java/lang/reflect/Modifier.java
@@ -26,6 +26,8 @@
 
 package java.lang.reflect;
 
+import java.util.StringJoiner;
+
 /**
  * The Modifier class provides {@code static} methods and
  * constants to decode class and member access modifiers.  The sets of
@@ -49,8 +51,7 @@
      *  packages
      *
     static {
-        sun.reflect.ReflectionFactory factory =
-            AccessController.doPrivileged(
+        ReflectionFactory factory = AccessController.doPrivileged(
                 new ReflectionFactory.GetReflectionFactoryAction());
         factory.setLangReflectAccess(new java.lang.reflect.ReflectAccess());
     }
@@ -241,27 +242,24 @@
      * represented by {@code mod}
      */
     public static String toString(int mod) {
-        StringBuilder sb = new StringBuilder();
-        int len;
+        StringJoiner sj = new StringJoiner(" ");
 
-        if ((mod & PUBLIC) != 0)        sb.append("public ");
-        if ((mod & PROTECTED) != 0)     sb.append("protected ");
-        if ((mod & PRIVATE) != 0)       sb.append("private ");
+        if ((mod & PUBLIC) != 0)        sj.add("public");
+        if ((mod & PROTECTED) != 0)     sj.add("protected");
+        if ((mod & PRIVATE) != 0)       sj.add("private");
 
         /* Canonical order */
-        if ((mod & ABSTRACT) != 0)      sb.append("abstract ");
-        if ((mod & STATIC) != 0)        sb.append("static ");
-        if ((mod & FINAL) != 0)         sb.append("final ");
-        if ((mod & TRANSIENT) != 0)     sb.append("transient ");
-        if ((mod & VOLATILE) != 0)      sb.append("volatile ");
-        if ((mod & SYNCHRONIZED) != 0)  sb.append("synchronized ");
-        if ((mod & NATIVE) != 0)        sb.append("native ");
-        if ((mod & STRICT) != 0)        sb.append("strictfp ");
-        if ((mod & INTERFACE) != 0)     sb.append("interface ");
+        if ((mod & ABSTRACT) != 0)      sj.add("abstract");
+        if ((mod & STATIC) != 0)        sj.add("static");
+        if ((mod & FINAL) != 0)         sj.add("final");
+        if ((mod & TRANSIENT) != 0)     sj.add("transient");
+        if ((mod & VOLATILE) != 0)      sj.add("volatile");
+        if ((mod & SYNCHRONIZED) != 0)  sj.add("synchronized");
+        if ((mod & NATIVE) != 0)        sj.add("native");
+        if ((mod & STRICT) != 0)        sj.add("strictfp");
+        if ((mod & INTERFACE) != 0)     sj.add("interface");
 
-        if ((len = sb.length()) > 0)    /* trim trailing space */
-            return sb.toString().substring(0, len-1);
-        return "";
+        return sj.toString();
     }
 
     /*
diff --git a/ojluni/src/main/java/java/lang/reflect/Parameter.java b/ojluni/src/main/java/java/lang/reflect/Parameter.java
index 4dc32b4..0dfbbb9 100644
--- a/ojluni/src/main/java/java/lang/reflect/Parameter.java
+++ b/ojluni/src/main/java/java/lang/reflect/Parameter.java
@@ -176,7 +176,7 @@
      *         a name.
      */
     public String getName() {
-        // Note: empty strings as paramete names are now outlawed.
+        // Note: empty strings as parameter names are now outlawed.
         // The .equals("") is for compatibility with current JVM
         // behavior.  It may be removed at some point.
         if(name == null || name.equals(""))
@@ -208,7 +208,7 @@
         return tmp;
     }
 
-    private transient volatile Type parameterTypeCache = null;
+    private transient volatile Type parameterTypeCache;
 
     /**
      * Returns a {@code Class} object that identifies the
diff --git a/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java b/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java
index a5e5be1..6d5459f 100644
--- a/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java
+++ b/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/lang/reflect/TypeVariable.java b/ojluni/src/main/java/java/lang/reflect/TypeVariable.java
index 4e29a94..1c06c09 100644
--- a/ojluni/src/main/java/java/lang/reflect/TypeVariable.java
+++ b/ojluni/src/main/java/java/lang/reflect/TypeVariable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@
 public interface TypeVariable<D extends GenericDeclaration> extends Type/*, AnnotatedElement*/ {
     /**
      * Returns an array of {@code Type} objects representing the
-     * upper bound(s) of this type variable.  Note that if no upper bound is
+     * upper bound(s) of this type variable.  If no upper bound is
      * explicitly declared, the upper bound is {@code Object}.
      *
      * <p>For each upper bound B: <ul> <li>if B is a parameterized
@@ -69,7 +69,7 @@
      *     for any reason
      * @return an array of {@code Type}s representing the upper
      *     bound(s) of this type variable
-    */
+     */
     Type[] getBounds();
 
     /**
@@ -95,11 +95,11 @@
      * Returns an array of AnnotatedType objects that represent the use of
      * types to denote the upper bounds of the type parameter represented by
      * this TypeVariable. The order of the objects in the array corresponds to
-     * the order of the bounds in the declaration of the type parameter.
+     * the order of the bounds in the declaration of the type parameter. Note that
+     * if no upper bound is explicitly declared, the upper bound is unannotated
+     * {@code Object}.
      *
-     * Returns an array of length 0 if the type parameter declares no bounds.
-     *
-     * @return an array of objects representing the upper bounds of the type variable
+     * @return an array of objects representing the upper bound(s) of the type variable
      * @since 1.8
      *
      AnnotatedType[] getAnnotatedBounds();
diff --git a/ojluni/src/main/java/java/lang/reflect/WildcardType.java b/ojluni/src/main/java/java/lang/reflect/WildcardType.java
index aa8e824..7b8f396 100644
--- a/ojluni/src/main/java/java/lang/reflect/WildcardType.java
+++ b/ojluni/src/main/java/java/lang/reflect/WildcardType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 public interface WildcardType extends Type {
     /**
      * Returns an array of {@code Type} objects representing the  upper
-     * bound(s) of this type variable.  Note that if no upper bound is
+     * bound(s) of this type variable.  If no upper bound is
      * explicitly declared, the upper bound is {@code Object}.
      *
      * <p>For each upper bound B :
@@ -57,7 +57,7 @@
 
     /**
      * Returns an array of {@code Type} objects representing the
-     * lower bound(s) of this type variable.  Note that if no lower bound is
+     * lower bound(s) of this type variable.  If no lower bound is
      * explicitly declared, the lower bound is the type of {@code null}.
      * In this case, a zero length array is returned.
      *
diff --git a/ojluni/src/main/java/java/lang/reflect/package-info.java b/ojluni/src/main/java/java/lang/reflect/package-info.java
index 258a07e..e771f31 100644
--- a/ojluni/src/main/java/java/lang/reflect/package-info.java
+++ b/ojluni/src/main/java/java/lang/reflect/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,12 +24,11 @@
  */
 
 /**
- * Provides classes and interfaces for obtaining reflective
- * information about classes and objects.  Reflection allows
- * programmatic access to information about the fields, methods and
- * constructors of loaded classes, and the use of reflected fields,
- * methods, and constructors to operate on their underlying
- * counterparts, within security restrictions.
+ * Provides classes and interfaces for obtaining reflective information about
+ * classes and objects.  Reflection allows programmatic access to information
+ * about the fields, methods and constructors of loaded classes, and the use
+ * of reflected fields, methods, and constructors to operate on their underlying
+ * counterparts, within encapsulation and security restrictions.
  *
  * <p>{@code AccessibleObject} allows suppression of access checks if
  * the necessary {@code ReflectPermission} is available.
@@ -44,6 +43,8 @@
  * members of a target object (based on its runtime class) or the
  * members declared by a given class.
  *
- * @since JDK1.1
+ * @since 1.1
+ * @revised 9
+ * @spec JPMS
  */
 package java.lang.reflect;
diff --git a/ojluni/src/main/java/java/math/BigDecimal.java b/ojluni/src/main/java/java/math/BigDecimal.java
index 9e012a6..9a1fdf0 100644
--- a/ojluni/src/main/java/java/math/BigDecimal.java
+++ b/ojluni/src/main/java/java/math/BigDecimal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 
 import static java.math.BigInteger.LONG_MASK;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Immutable, arbitrary-precision signed decimal numbers.  A
@@ -40,7 +41,7 @@
  * decimal point.  If negative, the unscaled value of the number is
  * multiplied by ten to the power of the negation of the scale.  The
  * value of the number represented by the {@code BigDecimal} is
- * therefore <tt>(unscaledValue &times; 10<sup>-scale</sup>)</tt>.
+ * therefore <code>(unscaledValue &times; 10<sup>-scale</sup>)</code>.
  *
  * <p>The {@code BigDecimal} class provides operations for
  * arithmetic, scale manipulation, rounding, comparison, hashing, and
@@ -55,7 +56,7 @@
  * object to the operation.  In either case, eight <em>rounding
  * modes</em> are provided for the control of rounding.  Using the
  * integer fields in this class (such as {@link #ROUND_HALF_UP}) to
- * represent rounding mode is largely obsolete; the enumeration values
+ * represent rounding mode is deprecated; the enumeration values
  * of the {@code RoundingMode} {@code enum}, (such as {@link
  * RoundingMode#HALF_UP}) should be used instead.
  *
@@ -93,7 +94,7 @@
  * <p>In general the rounding modes and precision setting determine
  * how operations return results with a limited number of digits when
  * the exact result has more digits (perhaps infinitely many in the
- * case of division) than the number of digits returned.
+ * case of division and square root) than the number of digits returned.
  *
  * First, the
  * total number of digits to return is specified by the
@@ -120,14 +121,19 @@
  * preferred scale for representing a result.  The preferred
  * scale for each operation is listed in the table below.
  *
- * <table border>
- * <caption><b>Preferred Scales for Results of Arithmetic Operations
- * </b></caption>
- * <tr><th>Operation</th><th>Preferred Scale of Result</th></tr>
- * <tr><td>Add</td><td>max(addend.scale(), augend.scale())</td>
- * <tr><td>Subtract</td><td>max(minuend.scale(), subtrahend.scale())</td>
- * <tr><td>Multiply</td><td>multiplier.scale() + multiplicand.scale()</td>
- * <tr><td>Divide</td><td>dividend.scale() - divisor.scale()</td>
+ * <table class="striped" style="text-align:left">
+ * <caption>Preferred Scales for Results of Arithmetic Operations
+ * </caption>
+ * <thead>
+ * <tr><th scope="col">Operation</th><th scope="col">Preferred Scale of Result</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><th scope="row">Add</th><td>max(addend.scale(), augend.scale())</td>
+ * <tr><th scope="row">Subtract</th><td>max(minuend.scale(), subtrahend.scale())</td>
+ * <tr><th scope="row">Multiply</th><td>multiplier.scale() + multiplicand.scale()</td>
+ * <tr><th scope="row">Divide</th><td>dividend.scale() - divisor.scale()</td>
+ * <tr><th scope="row">Square root</th><td>radicand.scale()/2</td>
+ * </tbody>
  * </table>
  *
  * These scales are the ones used by the methods which return exact
@@ -195,18 +201,19 @@
  * {@code BigDecimal} value; for example [19, 2] is the
  * {@code BigDecimal} numerically equal to 0.19 having a scale of 2.
  *
- * <p>Note: care should be exercised if {@code BigDecimal} objects
- * are used as keys in a {@link java.util.SortedMap SortedMap} or
- * elements in a {@link java.util.SortedSet SortedSet} since
- * {@code BigDecimal}'s <i>natural ordering</i> is <i>inconsistent
- * with equals</i>.  See {@link Comparable}, {@link
- * java.util.SortedMap} or {@link java.util.SortedSet} for more
- * information.
  *
  * <p>All methods and constructors for this class throw
  * {@code NullPointerException} when passed a {@code null} object
  * reference for any input parameter.
  *
+ * @apiNote Care should be exercised if {@code BigDecimal} objects
+ * are used as keys in a {@link java.util.SortedMap SortedMap} or
+ * elements in a {@link java.util.SortedSet SortedSet} since
+ * {@code BigDecimal}'s <i>natural ordering</i> is <em>inconsistent
+ * with equals</em>.  See {@link Comparable}, {@link
+ * java.util.SortedMap} or {@link java.util.SortedSet} for more
+ * information.
+ *
  * @see     BigInteger
  * @see     MathContext
  * @see     RoundingMode
@@ -216,6 +223,7 @@
  * @author  Mike Cowlishaw
  * @author  Joseph D. Darcy
  * @author  Sergey V. Kuksenko
+ * @since 1.1
  */
 public class BigDecimal extends Number implements Comparable<BigDecimal> {
     /**
@@ -283,10 +291,10 @@
     };
 
     // Cache of common small BigDecimal values.
-    private static final BigDecimal zeroThroughTen[] = {
+    private static final BigDecimal ZERO_THROUGH_TEN[] = {
         new BigDecimal(BigInteger.ZERO,       0,  0, 1),
         new BigDecimal(BigInteger.ONE,        1,  0, 1),
-        new BigDecimal(BigInteger.valueOf(2), 2,  0, 1),
+        new BigDecimal(BigInteger.TWO,        2,  0, 1),
         new BigDecimal(BigInteger.valueOf(3), 3,  0, 1),
         new BigDecimal(BigInteger.valueOf(4), 4,  0, 1),
         new BigDecimal(BigInteger.valueOf(5), 5,  0, 1),
@@ -299,7 +307,7 @@
 
     // Cache of zero scaled by 0 - 15
     private static final BigDecimal[] ZERO_SCALED_BY = {
-        zeroThroughTen[0],
+        ZERO_THROUGH_TEN[0],
         new BigDecimal(BigInteger.ZERO, 0, 1, 1),
         new BigDecimal(BigInteger.ZERO, 0, 2, 1),
         new BigDecimal(BigInteger.ZERO, 0, 3, 1),
@@ -328,7 +336,7 @@
      * @since  1.5
      */
     public static final BigDecimal ZERO =
-        zeroThroughTen[0];
+        ZERO_THROUGH_TEN[0];
 
     /**
      * The value 1, with a scale of 0.
@@ -336,7 +344,7 @@
      * @since  1.5
      */
     public static final BigDecimal ONE =
-        zeroThroughTen[1];
+        ZERO_THROUGH_TEN[1];
 
     /**
      * The value 10, with a scale of 0.
@@ -344,7 +352,17 @@
      * @since  1.5
      */
     public static final BigDecimal TEN =
-        zeroThroughTen[10];
+        ZERO_THROUGH_TEN[10];
+
+    /**
+     * The value 0.1, with a scale of 1.
+     */
+    private static final BigDecimal ONE_TENTH = valueOf(1L, 1);
+
+    /**
+     * The value 0.5, with a scale of 1.
+     */
+    private static final BigDecimal ONE_HALF = valueOf(5L, 1);
 
     // Constructors
 
@@ -366,10 +384,10 @@
      * same sequence of characters as the {@link #BigDecimal(String)}
      * constructor, while allowing a sub-array to be specified.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * within a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
-     * {@code BigDecimal(String)} constructor .
+     * {@code BigDecimal(String)} constructor.
      *
      * @param  in {@code char} array that is the source of characters.
      * @param  offset first character in the array to inspect.
@@ -390,14 +408,14 @@
      * constructor, while allowing a sub-array to be specified and
      * with rounding according to the context settings.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * within a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
-     * {@code BigDecimal(String)} constructor .
+     * {@code BigDecimal(String)} constructor.
      *
      * @param  in {@code char} array that is the source of characters.
      * @param  offset first character in the array to inspect.
-     * @param  len number of characters to consider..
+     * @param  len number of characters to consider.
      * @param  mc the context to use.
      * @throws ArithmeticException if the result is inexact but the
      *         rounding mode is {@code UNNECESSARY}.
@@ -408,7 +426,9 @@
      */
     public BigDecimal(char[] in, int offset, int len, MathContext mc) {
         // protect against huge length, negative values, and integer overflow
-        if ((in.length | len | offset) < 0 || len > in.length - offset) {
+        try {
+            Objects.checkFromIndexSize(offset, len, in.length);
+        } catch (IndexOutOfBoundsException e) {
             throw new NumberFormatException
                 ("Bad offset or len arguments for char[] input.");
         }
@@ -469,7 +489,8 @@
                     } else if (c == '.') {   // have dot
                         // have dot
                         if (dot) // two dots
-                            throw new NumberFormatException();
+                            throw new NumberFormatException("Character array"
+                                + " contains more than one decimal point.");
                         dot = true;
                     } else if (Character.isDigit(c)) { // slow path
                         int digit = Character.digit(c, 10);
@@ -491,14 +512,16 @@
                         exp = parseExp(in, offset, len);
                         // Next test is required for backwards compatibility
                         if ((int) exp != exp) // overflow
-                            throw new NumberFormatException();
+                            throw new NumberFormatException("Exponent overflow.");
                         break; // [saves a test]
                     } else {
-                        throw new NumberFormatException();
+                        throw new NumberFormatException("Character " + c
+                            + " is neither a decimal digit number, decimal point, nor"
+                            + " \"e\" notation exponential mark.");
                     }
                 }
                 if (prec == 0) // no digits found
-                    throw new NumberFormatException();
+                    throw new NumberFormatException("No digits found.");
                 // Adjust scale if exp is not zero.
                 if (exp != 0) { // had significant exponent
                     scl = adjustScale(scl, exp);
@@ -544,22 +567,24 @@
                     if (c == '.') {
                         // have dot
                         if (dot) // two dots
-                            throw new NumberFormatException();
+                            throw new NumberFormatException("Character array"
+                                + " contains more than one decimal point.");
                         dot = true;
                         continue;
                     }
                     // exponent expected
                     if ((c != 'e') && (c != 'E'))
-                        throw new NumberFormatException();
+                        throw new NumberFormatException("Character array"
+                            + " is missing \"e\" notation exponential mark.");
                     exp = parseExp(in, offset, len);
                     // Next test is required for backwards compatibility
                     if ((int) exp != exp) // overflow
-                        throw new NumberFormatException();
+                        throw new NumberFormatException("Exponent overflow.");
                     break; // [saves a test]
                 }
                 // here when no characters left
                 if (prec == 0) // no digits found
-                    throw new NumberFormatException();
+                    throw new NumberFormatException("No digits found.");
                 // Adjust scale if exp is not zero.
                 if (exp != 0) { // had significant exponent
                     scl = adjustScale(scl, exp);
@@ -595,10 +620,10 @@
                     }
                 }
             }
-        } catch (ArrayIndexOutOfBoundsException e) {
-            throw new NumberFormatException();
-        } catch (NegativeArraySizeException e) {
-            throw new NumberFormatException();
+        } catch (ArrayIndexOutOfBoundsException | NegativeArraySizeException e) {
+            NumberFormatException nfe = new NumberFormatException();
+            nfe.initCause(e);
+            throw nfe;
         }
         this.scale = scl;
         this.precision = prec;
@@ -630,7 +655,7 @@
             len--;
         }
         if (len <= 0) // no exponent digits
-            throw new NumberFormatException();
+            throw new NumberFormatException("No exponent digits.");
         // skip leading zeros in the exponent
         while (len > 10 && (c=='0' || (Character.digit(c, 10) == 0))) {
             offset++;
@@ -638,7 +663,7 @@
             len--;
         }
         if (len > 10) // too many nonzero exponent digits
-            throw new NumberFormatException();
+            throw new NumberFormatException("Too many nonzero exponent digits.");
         // c now holds first digit of exponent
         for (;; len--) {
             int v;
@@ -647,7 +672,7 @@
             } else {
                 v = Character.digit(c, 10);
                 if (v < 0) // not a digit
-                    throw new NumberFormatException();
+                    throw new NumberFormatException("Not a digit.");
             }
             exp = exp * 10 + v;
             if (len == 1)
@@ -666,10 +691,10 @@
      * same sequence of characters as the {@link #BigDecimal(String)}
      * constructor.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * as a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
-     * {@code BigDecimal(String)} constructor .
+     * {@code BigDecimal(String)} constructor.
      *
      * @param in {@code char} array that is the source of characters.
      * @throws NumberFormatException if {@code in} is not a valid
@@ -687,10 +712,10 @@
      * constructor and with rounding according to the context
      * settings.
      *
-     * <p>Note that if the sequence of characters is already available
+     * @implNote If the sequence of characters is already available
      * as a character array, using this constructor is faster than
      * converting the {@code char} array to string and using the
-     * {@code BigDecimal(String)} constructor .
+     * {@code BigDecimal(String)} constructor.
      *
      * @param  in {@code char} array that is the source of characters.
      * @param  mc the context to use.
@@ -707,8 +732,8 @@
     /**
      * Translates the string representation of a {@code BigDecimal}
      * into a {@code BigDecimal}.  The string representation consists
-     * of an optional sign, {@code '+'} (<tt> '&#92;u002B'</tt>) or
-     * {@code '-'} (<tt>'&#92;u002D'</tt>), followed by a sequence of
+     * of an optional sign, {@code '+'} (<code> '&#92;u002B'</code>) or
+     * {@code '-'} (<code>'&#92;u002D'</code>), followed by a sequence of
      * zero or more decimal digits ("the integer"), optionally
      * followed by a fraction, optionally followed by an exponent.
      *
@@ -719,7 +744,7 @@
      * <i>significand</i>.
      *
      * <p>The exponent consists of the character {@code 'e'}
-     * (<tt>'&#92;u0065'</tt>) or {@code 'E'} (<tt>'&#92;u0045'</tt>)
+     * (<code>'&#92;u0065'</code>) or {@code 'E'} (<code>'&#92;u0045'</code>)
      * followed by one or more decimal digits.  The value of the
      * exponent must lie between -{@link Integer#MAX_VALUE} ({@link
      * Integer#MIN_VALUE}+1) and {@link Integer#MAX_VALUE}, inclusive.
@@ -792,7 +817,7 @@
      * "-0"           [0,0]
      * </pre>
      *
-     * <p>Note: For values other than {@code float} and
+     * @apiNote For values other than {@code float} and
      * {@code double} NaN and &plusmn;Infinity, this constructor is
      * compatible with the values returned by {@link Float#toString}
      * and {@link Double#toString}.  This is generally the preferred
@@ -832,7 +857,7 @@
      * is the exact decimal representation of the {@code double}'s
      * binary floating-point value.  The scale of the returned
      * {@code BigDecimal} is the smallest value such that
-     * <tt>(10<sup>scale</sup> &times; val)</tt> is an integer.
+     * <code>(10<sup>scale</sup> &times; val)</code> is an integer.
      * <p>
      * <b>Notes:</b>
      * <ol>
@@ -846,16 +871,16 @@
      * This is because 0.1 cannot be represented exactly as a
      * {@code double} (or, for that matter, as a binary fraction of
      * any finite length).  Thus, the value that is being passed
-     * <i>in</i> to the constructor is not exactly equal to 0.1,
+     * <em>in</em> to the constructor is not exactly equal to 0.1,
      * appearances notwithstanding.
      *
      * <li>
      * The {@code String} constructor, on the other hand, is
      * perfectly predictable: writing {@code new BigDecimal("0.1")}
-     * creates a {@code BigDecimal} which is <i>exactly</i> equal to
+     * creates a {@code BigDecimal} which is <em>exactly</em> equal to
      * 0.1, as one would expect.  Therefore, it is generally
      * recommended that the {@linkplain #BigDecimal(String)
-     * <tt>String</tt> constructor} be used in preference to this one.
+     * String constructor} be used in preference to this one.
      *
      * <li>
      * When a {@code double} must be used as a source for a
@@ -879,7 +904,7 @@
      * Translates a {@code double} into a {@code BigDecimal}, with
      * rounding according to the context settings.  The scale of the
      * {@code BigDecimal} is the smallest value such that
-     * <tt>(10<sup>scale</sup> &times; val)</tt> is an integer.
+     * <code>(10<sup>scale</sup> &times; val)</code> is an integer.
      *
      * <p>The results of this constructor can be somewhat unpredictable
      * and its use is generally not recommended; see the notes under
@@ -923,20 +948,20 @@
             significand >>= 1;
             exponent++;
         }
-        int scale = 0;
+        int scl = 0;
         // Calculate intVal and scale
-        BigInteger intVal;
+        BigInteger rb;
         long compactVal = sign * significand;
         if (exponent == 0) {
-            intVal = (compactVal == INFLATED) ? INFLATED_BIGINT : null;
+            rb = (compactVal == INFLATED) ? INFLATED_BIGINT : null;
         } else {
             if (exponent < 0) {
-                intVal = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal);
-                scale = -exponent;
+                rb = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal);
+                scl = -exponent;
             } else { //  (exponent > 0)
-                intVal = BigInteger.valueOf(2).pow(exponent).multiply(compactVal);
+                rb = BigInteger.TWO.pow(exponent).multiply(compactVal);
             }
-            compactVal = compactValFor(intVal);
+            compactVal = compactValFor(rb);
         }
         int prec = 0;
         int mcp = mc.precision;
@@ -944,16 +969,16 @@
             int mode = mc.roundingMode.oldMode;
             int drop;
             if (compactVal == INFLATED) {
-                prec = bigDigitLength(intVal);
+                prec = bigDigitLength(rb);
                 drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
-                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
-                    compactVal = compactValFor(intVal);
+                    scl = checkScaleNonZero((long) scl - drop);
+                    rb = divideAndRoundByTenPow(rb, drop, mode);
+                    compactVal = compactValFor(rb);
                     if (compactVal != INFLATED) {
                         break;
                     }
-                    prec = bigDigitLength(intVal);
+                    prec = bigDigitLength(rb);
                     drop = prec - mcp;
                 }
             }
@@ -961,17 +986,17 @@
                 prec = longDigitLength(compactVal);
                 drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
+                    scl = checkScaleNonZero((long) scl - drop);
                     compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
                     prec = longDigitLength(compactVal);
                     drop = prec - mcp;
                 }
-                intVal = null;
+                rb = null;
             }
         }
-        this.intVal = intVal;
+        this.intVal = rb;
         this.intCompact = compactVal;
-        this.scale = scale;
+        this.scale = scl;
         this.precision = prec;
     }
 
@@ -1008,7 +1033,7 @@
      * Translates a {@code BigInteger} unscaled value and an
      * {@code int} scale into a {@code BigDecimal}.  The value of
      * the {@code BigDecimal} is
-     * <tt>(unscaledVal &times; 10<sup>-scale</sup>)</tt>.
+     * <code>(unscaledVal &times; 10<sup>-scale</sup>)</code>.
      *
      * @param unscaledVal unscaled value of the {@code BigDecimal}.
      * @param scale scale of the {@code BigDecimal}.
@@ -1024,8 +1049,8 @@
      * Translates a {@code BigInteger} unscaled value and an
      * {@code int} scale into a {@code BigDecimal}, with rounding
      * according to the context settings.  The value of the
-     * {@code BigDecimal} is <tt>(unscaledVal &times;
-     * 10<sup>-scale</sup>)</tt>, rounded according to the
+     * {@code BigDecimal} is <code>(unscaledVal &times;
+     * 10<sup>-scale</sup>)</code>, rounded according to the
      * {@code precision} and rounding mode settings.
      *
      * @param  unscaledVal unscaled value of the {@code BigDecimal}.
@@ -1101,13 +1126,13 @@
     public BigDecimal(int val, MathContext mc) {
         int mcp = mc.precision;
         long compactVal = val;
-        int scale = 0;
+        int scl = 0;
         int prec = 0;
         if (mcp > 0) { // do rounding
             prec = longDigitLength(compactVal);
             int drop = prec - mcp; // drop can't be more than 18
             while (drop > 0) {
-                scale = checkScaleNonZero((long) scale - drop);
+                scl = checkScaleNonZero((long) scl - drop);
                 compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
                 prec = longDigitLength(compactVal);
                 drop = prec - mcp;
@@ -1115,7 +1140,7 @@
         }
         this.intVal = null;
         this.intCompact = compactVal;
-        this.scale = scale;
+        this.scale = scl;
         this.precision = prec;
     }
 
@@ -1147,20 +1172,20 @@
         int mcp = mc.precision;
         int mode = mc.roundingMode.oldMode;
         int prec = 0;
-        int scale = 0;
-        BigInteger intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
+        int scl = 0;
+        BigInteger rb = (val == INFLATED) ? INFLATED_BIGINT : null;
         if (mcp > 0) { // do rounding
             if (val == INFLATED) {
                 prec = 19;
                 int drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
-                    intVal = divideAndRoundByTenPow(intVal, drop, mode);
-                    val = compactValFor(intVal);
+                    scl = checkScaleNonZero((long) scl - drop);
+                    rb = divideAndRoundByTenPow(rb, drop, mode);
+                    val = compactValFor(rb);
                     if (val != INFLATED) {
                         break;
                     }
-                    prec = bigDigitLength(intVal);
+                    prec = bigDigitLength(rb);
                     drop = prec - mcp;
                 }
             }
@@ -1168,17 +1193,17 @@
                 prec = longDigitLength(val);
                 int drop = prec - mcp;
                 while (drop > 0) {
-                    scale = checkScaleNonZero((long) scale - drop);
+                    scl = checkScaleNonZero((long) scl - drop);
                     val = divideAndRound(val, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
                     prec = longDigitLength(val);
                     drop = prec - mcp;
                 }
-                intVal = null;
+                rb = null;
             }
         }
-        this.intVal = intVal;
+        this.intVal = rb;
         this.intCompact = val;
-        this.scale = scale;
+        this.scale = scl;
         this.precision = prec;
     }
 
@@ -1186,15 +1211,16 @@
 
     /**
      * Translates a {@code long} unscaled value and an
-     * {@code int} scale into a {@code BigDecimal}.  This
-     * {@literal "static factory method"} is provided in preference to
-     * a ({@code long}, {@code int}) constructor because it
-     * allows for reuse of frequently used {@code BigDecimal} values..
+     * {@code int} scale into a {@code BigDecimal}.
+     *
+     * @apiNote This static factory method is provided in preference
+     * to a ({@code long}, {@code int}) constructor because it allows
+     * for reuse of frequently used {@code BigDecimal} values.
      *
      * @param unscaledVal unscaled value of the {@code BigDecimal}.
      * @param scale scale of the {@code BigDecimal}.
      * @return a {@code BigDecimal} whose value is
-     *         <tt>(unscaledVal &times; 10<sup>-scale</sup>)</tt>.
+     *         <code>(unscaledVal &times; 10<sup>-scale</sup>)</code>.
      */
     public static BigDecimal valueOf(long unscaledVal, int scale) {
         if (scale == 0)
@@ -1209,25 +1235,26 @@
 
     /**
      * Translates a {@code long} value into a {@code BigDecimal}
-     * with a scale of zero.  This {@literal "static factory method"}
-     * is provided in preference to a ({@code long}) constructor
-     * because it allows for reuse of frequently used
-     * {@code BigDecimal} values.
+     * with a scale of zero.
+     *
+     * @apiNote This static factory method is provided in preference
+     * to a ({@code long}) constructor because it allows for reuse of
+     * frequently used {@code BigDecimal} values.
      *
      * @param val value of the {@code BigDecimal}.
      * @return a {@code BigDecimal} whose value is {@code val}.
      */
     public static BigDecimal valueOf(long val) {
-        if (val >= 0 && val < zeroThroughTen.length)
-            return zeroThroughTen[(int)val];
+        if (val >= 0 && val < ZERO_THROUGH_TEN.length)
+            return ZERO_THROUGH_TEN[(int)val];
         else if (val != INFLATED)
             return new BigDecimal(null, val, 0, 0);
         return new BigDecimal(INFLATED_BIGINT, val, 0, 0);
     }
 
     static BigDecimal valueOf(long unscaledVal, int scale, int prec) {
-        if (scale == 0 && unscaledVal >= 0 && unscaledVal < zeroThroughTen.length) {
-            return zeroThroughTen[(int) unscaledVal];
+        if (scale == 0 && unscaledVal >= 0 && unscaledVal < ZERO_THROUGH_TEN.length) {
+            return ZERO_THROUGH_TEN[(int) unscaledVal];
         } else if (unscaledVal == 0) {
             return zeroValueOf(scale);
         }
@@ -1239,8 +1266,8 @@
         long val = compactValFor(intVal);
         if (val == 0) {
             return zeroValueOf(scale);
-        } else if (scale == 0 && val >= 0 && val < zeroThroughTen.length) {
-            return zeroThroughTen[(int) val];
+        } else if (scale == 0 && val >= 0 && val < ZERO_THROUGH_TEN.length) {
+            return ZERO_THROUGH_TEN[(int) val];
         }
         return new BigDecimal(intVal, val, scale, prec);
     }
@@ -1257,11 +1284,11 @@
      * the {@code double}'s canonical string representation provided
      * by the {@link Double#toString(double)} method.
      *
-     * <p><b>Note:</b> This is generally the preferred way to convert
-     * a {@code double} (or {@code float}) into a
-     * {@code BigDecimal}, as the value returned is equal to that
-     * resulting from constructing a {@code BigDecimal} from the
-     * result of using {@link Double#toString(double)}.
+     * @apiNote This is generally the preferred way to convert a
+     * {@code double} (or {@code float}) into a {@code BigDecimal}, as
+     * the value returned is equal to that resulting from constructing
+     * a {@code BigDecimal} from the result of using {@link
+     * Double#toString(double)}.
      *
      * @param  val {@code double} to convert to a {@code BigDecimal}.
      * @return a {@code BigDecimal} whose value is equal to or approximately
@@ -1474,8 +1501,8 @@
     }
 
     /**
-     * Returns a {@code BigDecimal} whose value is <tt>(this &times;
-     * multiplicand)</tt>, and whose scale is {@code (this.scale() +
+     * Returns a {@code BigDecimal} whose value is <code>(this &times;
+     * multiplicand)</code>, and whose scale is {@code (this.scale() +
      * multiplicand.scale())}.
      *
      * @param  multiplicand value to be multiplied by this {@code BigDecimal}.
@@ -1499,8 +1526,8 @@
     }
 
     /**
-     * Returns a {@code BigDecimal} whose value is <tt>(this &times;
-     * multiplicand)</tt>, with rounding according to the context settings.
+     * Returns a {@code BigDecimal} whose value is <code>(this &times;
+     * multiplicand)</code>, with rounding according to the context settings.
      *
      * @param  multiplicand value to be multiplied by this {@code BigDecimal}.
      * @param  mc the context to use.
@@ -1534,7 +1561,7 @@
      * be performed to generate a result with the specified scale, the
      * specified rounding mode is applied.
      *
-     * <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method
+     * @deprecated The method {@link #divide(BigDecimal, int, RoundingMode)}
      * should be used in preference to this legacy method.
      *
      * @param  divisor value by which this {@code BigDecimal} is to be divided.
@@ -1556,6 +1583,7 @@
      * @see    #ROUND_HALF_EVEN
      * @see    #ROUND_UNNECESSARY
      */
+    @Deprecated(since="9")
     public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
         if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
             throw new IllegalArgumentException("Invalid rounding mode");
@@ -1600,7 +1628,7 @@
      * rounding must be performed to generate a result with the given
      * scale, the specified rounding mode is applied.
      *
-     * <p>The new {@link #divide(BigDecimal, RoundingMode)} method
+     * @deprecated The method {@link #divide(BigDecimal, RoundingMode)}
      * should be used in preference to this legacy method.
      *
      * @param  divisor value by which this {@code BigDecimal} is to be divided.
@@ -1621,6 +1649,7 @@
      * @see    #ROUND_HALF_EVEN
      * @see    #ROUND_UNNECESSARY
      */
+    @Deprecated(since="9")
     public BigDecimal divide(BigDecimal divisor, int roundingMode) {
         return this.divide(divisor, scale, roundingMode);
     }
@@ -1881,7 +1910,7 @@
      *
      * <p>The remainder is given by
      * {@code this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))}.
-     * Note that this is not the modulo operation (the result can be
+     * Note that this is <em>not</em> the modulo operation (the result can be
      * negative).
      *
      * @param  divisor value by which this {@code BigDecimal} is to be divided.
@@ -1992,8 +2021,390 @@
     }
 
     /**
+     * Returns an approximation to the square root of {@code this}
+     * with rounding according to the context settings.
+     *
+     * <p>The preferred scale of the returned result is equal to
+     * {@code this.scale()/2}. The value of the returned result is
+     * always within one ulp of the exact decimal value for the
+     * precision in question.  If the rounding mode is {@link
+     * RoundingMode#HALF_UP HALF_UP}, {@link RoundingMode#HALF_DOWN
+     * HALF_DOWN}, or {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
+     * result is within one half an ulp of the exact decimal value.
+     *
+     * <p>Special case:
+     * <ul>
+     * <li> The square root of a number numerically equal to {@code
+     * ZERO} is numerically equal to {@code ZERO} with a preferred
+     * scale according to the general rule above. In particular, for
+     * {@code ZERO}, {@code ZERO.sqrt(mc).equals(ZERO)} is true with
+     * any {@code MathContext} as an argument.
+     * </ul>
+     *
+     * @param mc the context to use.
+     * @return the square root of {@code this}.
+     * @throws ArithmeticException if {@code this} is less than zero.
+     * @throws ArithmeticException if an exact result is requested
+     * ({@code mc.getPrecision()==0}) and there is no finite decimal
+     * expansion of the exact result
+     * @throws ArithmeticException if
+     * {@code (mc.getRoundingMode()==RoundingMode.UNNECESSARY}) and
+     * the exact result cannot fit in {@code mc.getPrecision()}
+     * digits.
+     * @see BigInteger#sqrt()
+     * @since  9
+     */
+    public BigDecimal sqrt(MathContext mc) {
+        int signum = signum();
+        if (signum == 1) {
+            /*
+             * The following code draws on the algorithm presented in
+             * "Properly Rounded Variable Precision Square Root," Hull and
+             * Abrham, ACM Transactions on Mathematical Software, Vol 11,
+             * No. 3, September 1985, Pages 229-237.
+             *
+             * The BigDecimal computational model differs from the one
+             * presented in the paper in several ways: first BigDecimal
+             * numbers aren't necessarily normalized, second many more
+             * rounding modes are supported, including UNNECESSARY, and
+             * exact results can be requested.
+             *
+             * The main steps of the algorithm below are as follows,
+             * first argument reduce the value to the numerical range
+             * [1, 10) using the following relations:
+             *
+             * x = y * 10 ^ exp
+             * sqrt(x) = sqrt(y) * 10^(exp / 2) if exp is even
+             * sqrt(x) = sqrt(y/10) * 10 ^((exp+1)/2) is exp is odd
+             *
+             * Then use Newton's iteration on the reduced value to compute
+             * the numerical digits of the desired result.
+             *
+             * Finally, scale back to the desired exponent range and
+             * perform any adjustment to get the preferred scale in the
+             * representation.
+             */
+
+            // The code below favors relative simplicity over checking
+            // for special cases that could run faster.
+
+            int preferredScale = this.scale()/2;
+            BigDecimal zeroWithFinalPreferredScale = valueOf(0L, preferredScale);
+
+            // First phase of numerical normalization, strip trailing
+            // zeros and check for even powers of 10.
+            BigDecimal stripped = this.stripTrailingZeros();
+            int strippedScale = stripped.scale();
+
+            // Numerically sqrt(10^2N) = 10^N
+            if (stripped.isPowerOfTen() &&
+                strippedScale % 2 == 0) {
+                BigDecimal result = valueOf(1L, strippedScale/2);
+                if (result.scale() != preferredScale) {
+                    // Adjust to requested precision and preferred
+                    // scale as appropriate.
+                    result = result.add(zeroWithFinalPreferredScale, mc);
+                }
+                return result;
+            }
+
+            // After stripTrailingZeros, the representation is normalized as
+            //
+            // unscaledValue * 10^(-scale)
+            //
+            // where unscaledValue is an integer with the mimimum
+            // precision for the cohort of the numerical value. To
+            // allow binary floating-point hardware to be used to get
+            // approximately a 15 digit approximation to the square
+            // root, it is helpful to instead normalize this so that
+            // the significand portion is to right of the decimal
+            // point by roughly (scale() - precision() + 1).
+
+            // Now the precision / scale adjustment
+            int scaleAdjust = 0;
+            int scale = stripped.scale() - stripped.precision() + 1;
+            if (scale % 2 == 0) {
+                scaleAdjust = scale;
+            } else {
+                scaleAdjust = scale - 1;
+            }
+
+            BigDecimal working = stripped.scaleByPowerOfTen(scaleAdjust);
+
+            assert  // Verify 0.1 <= working < 10
+                ONE_TENTH.compareTo(working) <= 0 && working.compareTo(TEN) < 0;
+
+            // Use good ole' Math.sqrt to get the initial guess for
+            // the Newton iteration, good to at least 15 decimal
+            // digits. This approach does incur the cost of a
+            //
+            // BigDecimal -> double -> BigDecimal
+            //
+            // conversion cycle, but it avoids the need for several
+            // Newton iterations in BigDecimal arithmetic to get the
+            // working answer to 15 digits of precision. If many fewer
+            // than 15 digits were needed, it might be faster to do
+            // the loop entirely in BigDecimal arithmetic.
+            //
+            // (A double value might have as many as 17 decimal
+            // digits of precision; it depends on the relative density
+            // of binary and decimal numbers at different regions of
+            // the number line.)
+            //
+            // (It would be possible to check for certain special
+            // cases to avoid doing any Newton iterations. For
+            // example, if the BigDecimal -> double conversion was
+            // known to be exact and the rounding mode had a
+            // low-enough precision, the post-Newton rounding logic
+            // could be applied directly.)
+
+            BigDecimal guess = new BigDecimal(Math.sqrt(working.doubleValue()));
+            int guessPrecision = 15;
+            int originalPrecision = mc.getPrecision();
+            int targetPrecision;
+
+            // If an exact value is requested, it must only need about
+            // half of the input digits to represent since multiplying
+            // an N digit number by itself yield a 2N-1 digit or 2N
+            // digit result.
+            if (originalPrecision == 0) {
+                targetPrecision = stripped.precision()/2 + 1;
+            } else {
+                /*
+                 * To avoid the need for post-Newton fix-up logic, in
+                 * the case of half-way rounding modes, double the
+                 * target precision so that the "2p + 2" property can
+                 * be relied on to accomplish the final rounding.
+                 */
+                switch (mc.getRoundingMode()) {
+                case HALF_UP:
+                case HALF_DOWN:
+                case HALF_EVEN:
+                    targetPrecision = 2 * originalPrecision;
+                    if (targetPrecision < 0) // Overflow
+                        targetPrecision = Integer.MAX_VALUE - 2;
+                    break;
+
+                default:
+                    targetPrecision = originalPrecision;
+                    break;
+                }
+            }
+
+            // When setting the precision to use inside the Newton
+            // iteration loop, take care to avoid the case where the
+            // precision of the input exceeds the requested precision
+            // and rounding the input value too soon.
+            BigDecimal approx = guess;
+            int workingPrecision = working.precision();
+            do {
+                int tmpPrecision = Math.max(Math.max(guessPrecision, targetPrecision + 2),
+                                           workingPrecision);
+                MathContext mcTmp = new MathContext(tmpPrecision, RoundingMode.HALF_EVEN);
+                // approx = 0.5 * (approx + fraction / approx)
+                approx = ONE_HALF.multiply(approx.add(working.divide(approx, mcTmp), mcTmp));
+                guessPrecision *= 2;
+            } while (guessPrecision < targetPrecision + 2);
+
+            BigDecimal result;
+            RoundingMode targetRm = mc.getRoundingMode();
+            if (targetRm == RoundingMode.UNNECESSARY || originalPrecision == 0) {
+                RoundingMode tmpRm =
+                    (targetRm == RoundingMode.UNNECESSARY) ? RoundingMode.DOWN : targetRm;
+                MathContext mcTmp = new MathContext(targetPrecision, tmpRm);
+                result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mcTmp);
+
+                // If result*result != this numerically, the square
+                // root isn't exact
+                if (this.subtract(result.square()).compareTo(ZERO) != 0) {
+                    throw new ArithmeticException("Computed square root not exact.");
+                }
+            } else {
+                result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mc);
+
+                switch (targetRm) {
+                case DOWN:
+                case FLOOR:
+                    // Check if too big
+                    if (result.square().compareTo(this) > 0) {
+                        BigDecimal ulp = result.ulp();
+                        // Adjust increment down in case of 1.0 = 10^0
+                        // since the next smaller number is only 1/10
+                        // as far way as the next larger at exponent
+                        // boundaries. Test approx and *not* result to
+                        // avoid having to detect an arbitrary power
+                        // of ten.
+                        if (approx.compareTo(ONE) == 0) {
+                            ulp = ulp.multiply(ONE_TENTH);
+                        }
+                        result = result.subtract(ulp);
+                    }
+                    break;
+
+                case UP:
+                case CEILING:
+                    // Check if too small
+                    if (result.square().compareTo(this) < 0) {
+                        result = result.add(result.ulp());
+                    }
+                    break;
+
+                default:
+                    // No additional work, rely on "2p + 2" property
+                    // for correct rounding. Alternatively, could
+                    // instead run the Newton iteration to around p
+                    // digits and then do tests and fix-ups on the
+                    // rounded value. One possible set of tests and
+                    // fix-ups is given in the Hull and Abrham paper;
+                    // however, additional half-way cases can occur
+                    // for BigDecimal given the more varied
+                    // combinations of input and output precisions
+                    // supported.
+                    break;
+                }
+
+            }
+
+            // Test numerical properties at full precision before any
+            // scale adjustments.
+            assert squareRootResultAssertions(result, mc);
+            if (result.scale() != preferredScale) {
+                // The preferred scale of an add is
+                // max(addend.scale(), augend.scale()). Therefore, if
+                // the scale of the result is first minimized using
+                // stripTrailingZeros(), adding a zero of the
+                // preferred scale rounding to the correct precision
+                // will perform the proper scale vs precision
+                // tradeoffs.
+                result = result.stripTrailingZeros().
+                    add(zeroWithFinalPreferredScale,
+                        new MathContext(originalPrecision, RoundingMode.UNNECESSARY));
+            }
+            return result;
+        } else {
+            BigDecimal result = null;
+            switch (signum) {
+            case -1:
+                throw new ArithmeticException("Attempted square root " +
+                                              "of negative BigDecimal");
+            case 0:
+                result = valueOf(0L, scale()/2);
+                assert squareRootResultAssertions(result, mc);
+                return result;
+
+            default:
+                throw new AssertionError("Bad value from signum");
+            }
+        }
+    }
+
+    private BigDecimal square() {
+        return this.multiply(this);
+    }
+
+    private boolean isPowerOfTen() {
+        return BigInteger.ONE.equals(this.unscaledValue());
+    }
+
+    /**
+     * For nonzero values, check numerical correctness properties of
+     * the computed result for the chosen rounding mode.
+     *
+     * For the directed rounding modes:
+     *
+     * <ul>
+     *
+     * <li> For DOWN and FLOOR, result^2 must be {@code <=} the input
+     * and (result+ulp)^2 must be {@code >} the input.
+     *
+     * <li>Conversely, for UP and CEIL, result^2 must be {@code >=}
+     * the input and (result-ulp)^2 must be {@code <} the input.
+     * </ul>
+     */
+    private boolean squareRootResultAssertions(BigDecimal result, MathContext mc) {
+        if (result.signum() == 0) {
+            return squareRootZeroResultAssertions(result, mc);
+        } else {
+            RoundingMode rm = mc.getRoundingMode();
+            BigDecimal ulp = result.ulp();
+            BigDecimal neighborUp   = result.add(ulp);
+            // Make neighbor down accurate even for powers of ten
+            if (result.isPowerOfTen()) {
+                ulp = ulp.divide(TEN);
+            }
+            BigDecimal neighborDown = result.subtract(ulp);
+
+            // Both the starting value and result should be nonzero and positive.
+            assert (result.signum() == 1 &&
+                    this.signum() == 1) :
+                "Bad signum of this and/or its sqrt.";
+
+            switch (rm) {
+            case DOWN:
+            case FLOOR:
+                assert
+                    result.square().compareTo(this)     <= 0 &&
+                    neighborUp.square().compareTo(this) > 0:
+                "Square of result out for bounds rounding " + rm;
+                return true;
+
+            case UP:
+            case CEILING:
+                assert
+                    result.square().compareTo(this)       >= 0 &&
+                    neighborDown.square().compareTo(this) < 0:
+                "Square of result out for bounds rounding " + rm;
+                return true;
+
+
+            case HALF_DOWN:
+            case HALF_EVEN:
+            case HALF_UP:
+                BigDecimal err = result.square().subtract(this).abs();
+                BigDecimal errUp = neighborUp.square().subtract(this);
+                BigDecimal errDown =  this.subtract(neighborDown.square());
+                // All error values should be positive so don't need to
+                // compare absolute values.
+
+                int err_comp_errUp = err.compareTo(errUp);
+                int err_comp_errDown = err.compareTo(errDown);
+
+                assert
+                    errUp.signum()   == 1 &&
+                    errDown.signum() == 1 :
+                "Errors of neighbors squared don't have correct signs";
+
+                // For breaking a half-way tie, the return value may
+                // have a larger error than one of the neighbors. For
+                // example, the square root of 2.25 to a precision of
+                // 1 digit is either 1 or 2 depending on how the exact
+                // value of 1.5 is rounded. If 2 is returned, it will
+                // have a larger rounding error than its neighbor 1.
+                assert
+                    err_comp_errUp   <= 0 ||
+                    err_comp_errDown <= 0 :
+                "Computed square root has larger error than neighbors for " + rm;
+
+                assert
+                    ((err_comp_errUp   == 0 ) ? err_comp_errDown < 0 : true) &&
+                    ((err_comp_errDown == 0 ) ? err_comp_errUp   < 0 : true) :
+                        "Incorrect error relationships";
+                // && could check for digit conditions for ties too
+                return true;
+
+            default: // Definition of UNNECESSARY already verified.
+                return true;
+            }
+        }
+    }
+
+    private boolean squareRootZeroResultAssertions(BigDecimal result, MathContext mc) {
+        return this.compareTo(ZERO) == 0;
+    }
+
+    /**
      * Returns a {@code BigDecimal} whose value is
-     * <tt>(this<sup>n</sup>)</tt>, The power is computed exactly, to
+     * <code>(this<sup>n</sup>)</code>, The power is computed exactly, to
      * unlimited precision.
      *
      * <p>The parameter {@code n} must be in the range 0 through
@@ -2004,7 +2415,7 @@
      * range of this method.
      *
      * @param  n power to raise this {@code BigDecimal} to.
-     * @return <tt>this<sup>n</sup></tt>
+     * @return <code>this<sup>n</sup></code>
      * @throws ArithmeticException if {@code n} is out of range.
      * @since  1.5
      */
@@ -2020,7 +2431,7 @@
 
     /**
      * Returns a {@code BigDecimal} whose value is
-     * <tt>(this<sup>n</sup>)</tt>.  The current implementation uses
+     * <code>(this<sup>n</sup>)</code>.  The current implementation uses
      * the core algorithm defined in ANSI standard X3.274-1996 with
      * rounding according to the context settings.  In general, the
      * returned numerical value is within two ulps of the exact
@@ -2061,7 +2472,7 @@
      *
      * @param  n power to raise this {@code BigDecimal} to.
      * @param  mc the context to use.
-     * @return <tt>this<sup>n</sup></tt> using the ANSI standard X3.274-1996
+     * @return <code>this<sup>n</sup></code> using the ANSI standard X3.274-1996
      *         algorithm
      * @throws ArithmeticException if the result is inexact but the
      *         rounding mode is {@code UNNECESSARY}, or {@code n} is out
@@ -2249,8 +2660,8 @@
 
     /**
      * Returns a {@code BigInteger} whose value is the <i>unscaled
-     * value</i> of this {@code BigDecimal}.  (Computes <tt>(this *
-     * 10<sup>this.scale()</sup>)</tt>.)
+     * value</i> of this {@code BigDecimal}.  (Computes <code>(this *
+     * 10<sup>this.scale()</sup>)</code>.)
      *
      * @return the unscaled value of this {@code BigDecimal}.
      * @since  1.2
@@ -2265,15 +2676,21 @@
      * Rounding mode to round away from zero.  Always increments the
      * digit prior to a nonzero discarded fraction.  Note that this rounding
      * mode never decreases the magnitude of the calculated value.
+     *
+     * @deprecated Use {@link RoundingMode#UP} instead.
      */
-    public final static int ROUND_UP =           0;
+    @Deprecated(since="9")
+    public static final int ROUND_UP =           0;
 
     /**
      * Rounding mode to round towards zero.  Never increments the digit
      * prior to a discarded fraction (i.e., truncates).  Note that this
      * rounding mode never increases the magnitude of the calculated value.
+     *
+     * @deprecated Use {@link RoundingMode#DOWN} instead.
      */
-    public final static int ROUND_DOWN =         1;
+    @Deprecated(since="9")
+    public static final int ROUND_DOWN =         1;
 
     /**
      * Rounding mode to round towards positive infinity.  If the
@@ -2281,8 +2698,11 @@
      * {@code ROUND_UP}; if negative, behaves as for
      * {@code ROUND_DOWN}.  Note that this rounding mode never
      * decreases the calculated value.
+     *
+     * @deprecated Use {@link RoundingMode#CEILING} instead.
      */
-    public final static int ROUND_CEILING =      2;
+    @Deprecated(since="9")
+    public static final int ROUND_CEILING =      2;
 
     /**
      * Rounding mode to round towards negative infinity.  If the
@@ -2290,8 +2710,11 @@
      * {@code ROUND_DOWN}; if negative, behave as for
      * {@code ROUND_UP}.  Note that this rounding mode never
      * increases the calculated value.
+     *
+     * @deprecated Use {@link RoundingMode#FLOOR} instead.
      */
-    public final static int ROUND_FLOOR =        3;
+    @Deprecated(since="9")
+    public static final int ROUND_FLOOR =        3;
 
     /**
      * Rounding mode to round towards {@literal "nearest neighbor"}
@@ -2300,8 +2723,11 @@
      * &ge; 0.5; otherwise, behaves as for {@code ROUND_DOWN}.  Note
      * that this is the rounding mode that most of us were taught in
      * grade school.
+     *
+     * @deprecated Use {@link RoundingMode#HALF_UP} instead.
      */
-    public final static int ROUND_HALF_UP =      4;
+    @Deprecated(since="9")
+    public static final int ROUND_HALF_UP =      4;
 
     /**
      * Rounding mode to round towards {@literal "nearest neighbor"}
@@ -2309,8 +2735,11 @@
      * down.  Behaves as for {@code ROUND_UP} if the discarded
      * fraction is {@literal >} 0.5; otherwise, behaves as for
      * {@code ROUND_DOWN}.
+     *
+     * @deprecated Use {@link RoundingMode#HALF_DOWN} instead.
      */
-    public final static int ROUND_HALF_DOWN =    5;
+    @Deprecated(since="9")
+    public static final int ROUND_HALF_DOWN =    5;
 
     /**
      * Rounding mode to round towards the {@literal "nearest neighbor"}
@@ -2321,16 +2750,22 @@
      * {@code ROUND_HALF_DOWN} if it's even.  Note that this is the
      * rounding mode that minimizes cumulative error when applied
      * repeatedly over a sequence of calculations.
+     *
+     * @deprecated Use {@link RoundingMode#HALF_EVEN} instead.
      */
-    public final static int ROUND_HALF_EVEN =    6;
+    @Deprecated(since="9")
+    public static final int ROUND_HALF_EVEN =    6;
 
     /**
      * Rounding mode to assert that the requested operation has an exact
      * result, hence no rounding is necessary.  If this rounding mode is
      * specified on an operation that yields an inexact result, an
      * {@code ArithmeticException} is thrown.
+     *
+     * @deprecated Use {@link RoundingMode#UNNECESSARY} instead.
      */
-    public final static int ROUND_UNNECESSARY =  7;
+    @Deprecated(since="9")
+    public static final int ROUND_UNNECESSARY =  7;
 
 
     // Scaling/Rounding Operations
@@ -2366,10 +2801,10 @@
      * in this case, the specified rounding mode is applied to the
      * division.
      *
-     * <p>Note that since BigDecimal objects are immutable, calls of
-     * this method do <i>not</i> result in the original object being
+     * @apiNote Since BigDecimal objects are immutable, calls of
+     * this method do <em>not</em> result in the original object being
      * modified, contrary to the usual convention of having methods
-     * named <tt>set<i>X</i></tt> mutate field <i>{@code X}</i>.
+     * named <code>set<i>X</i></code> mutate field <i>{@code X}</i>.
      * Instead, {@code setScale} returns an object with the proper
      * scale; the returned object may or may not be newly allocated.
      *
@@ -2399,14 +2834,14 @@
      * in this case, the specified rounding mode is applied to the
      * division.
      *
-     * <p>Note that since BigDecimal objects are immutable, calls of
-     * this method do <i>not</i> result in the original object being
+     * @apiNote Since BigDecimal objects are immutable, calls of
+     * this method do <em>not</em> result in the original object being
      * modified, contrary to the usual convention of having methods
-     * named <tt>set<i>X</i></tt> mutate field <i>{@code X}</i>.
+     * named <code>set<i>X</i></code> mutate field <i>{@code X}</i>.
      * Instead, {@code setScale} returns an object with the proper
      * scale; the returned object may or may not be newly allocated.
      *
-     * <p>The new {@link #setScale(int, RoundingMode)} method should
+     * @deprecated The method {@link #setScale(int, RoundingMode)} should
      * be used in preference to this legacy method.
      *
      * @param  newScale scale of the {@code BigDecimal} value to be returned.
@@ -2429,6 +2864,7 @@
      * @see    #ROUND_HALF_EVEN
      * @see    #ROUND_UNNECESSARY
      */
+    @Deprecated(since="9")
     public BigDecimal setScale(int newScale, int roundingMode) {
         if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
             throw new IllegalArgumentException("Invalid rounding mode");
@@ -2493,10 +2929,10 @@
      * versions of {@code setScale}, but saves the caller the trouble
      * of specifying a rounding mode in cases where it is irrelevant.
      *
-     * <p>Note that since {@code BigDecimal} objects are immutable,
-     * calls of this method do <i>not</i> result in the original
+     * @apiNote Since {@code BigDecimal} objects are immutable,
+     * calls of this method do <em>not</em> result in the original
      * object being modified, contrary to the usual convention of
-     * having methods named <tt>set<i>X</i></tt> mutate field
+     * having methods named <code>set<i>X</i></code> mutate field
      * <i>{@code X}</i>.  Instead, {@code setScale} returns an
      * object with the proper scale; the returned object may or may
      * not be newly allocated.
@@ -2523,8 +2959,8 @@
      * {@code n} is non-negative, the call merely adds {@code n} to
      * the scale.  If {@code n} is negative, the call is equivalent
      * to {@code movePointRight(-n)}.  The {@code BigDecimal}
-     * returned by this call has value <tt>(this &times;
-     * 10<sup>-n</sup>)</tt> and scale {@code max(this.scale()+n,
+     * returned by this call has value <code>(this &times;
+     * 10<sup>-n</sup>)</code> and scale {@code max(this.scale()+n,
      * 0)}.
      *
      * @param  n number of places to move the decimal point to the left.
@@ -2545,8 +2981,8 @@
      * If {@code n} is non-negative, the call merely subtracts
      * {@code n} from the scale.  If {@code n} is negative, the call
      * is equivalent to {@code movePointLeft(-n)}.  The
-     * {@code BigDecimal} returned by this call has value <tt>(this
-     * &times; 10<sup>n</sup>)</tt> and scale {@code max(this.scale()-n,
+     * {@code BigDecimal} returned by this call has value <code>(this
+     * &times; 10<sup>n</sup>)</code> and scale {@code max(this.scale()-n,
      * 0)}.
      *
      * @param  n number of places to move the decimal point to the right.
@@ -2623,6 +3059,7 @@
      * @return -1, 0, or 1 as this {@code BigDecimal} is numerically
      *          less than, equal to, or greater than {@code val}.
      */
+    @Override
     public int compareTo(BigDecimal val) {
         // Quick path for equal scale and non-inflated case.
         if (scale == val.scale) {
@@ -2662,14 +3099,13 @@
                 return -1;
             if (xae > yae)
                 return 1;
-            BigInteger rb = null;
             if (sdiff < 0) {
                 // The cases sdiff <= Integer.MIN_VALUE intentionally fall through.
                 if ( sdiff > Integer.MIN_VALUE &&
                       (xs == INFLATED ||
                       (xs = longMultiplyPowerTen(xs, (int)-sdiff)) == INFLATED) &&
                      ys == INFLATED) {
-                    rb = bigMultiplyPowerTen((int)-sdiff);
+                    BigInteger rb = bigMultiplyPowerTen((int)-sdiff);
                     return rb.compareMagnitude(val.intVal);
                 }
             } else { // sdiff > 0
@@ -2678,7 +3114,7 @@
                       (ys == INFLATED ||
                       (ys = longMultiplyPowerTen(ys, (int)sdiff)) == INFLATED) &&
                      xs == INFLATED) {
-                    rb = val.bigMultiplyPowerTen((int)sdiff);
+                    BigInteger rb = val.bigMultiplyPowerTen((int)sdiff);
                     return this.intVal.compareMagnitude(rb);
                 }
             }
@@ -2762,7 +3198,7 @@
     /**
      * Returns the hash code for this {@code BigDecimal}.  Note that
      * two {@code BigDecimal} objects that are numerically equal but
-     * differ in scale (like 2.0 and 2.00) will generally <i>not</i>
+     * differ in scale (like 2.0 and 2.00) will generally <em>not</em>
      * have the same hash code.
      *
      * @return hash code for this {@code BigDecimal}.
@@ -2823,12 +3259,12 @@
      * adjusted exponent converted to a character form.  The latter is
      * in base ten, using the characters {@code '0'} through
      * {@code '9'} with no leading zeros, and is always prefixed by a
-     * sign character {@code '-'} (<tt>'&#92;u002D'</tt>) if the
+     * sign character {@code '-'} (<code>'&#92;u002D'</code>) if the
      * adjusted exponent is negative, {@code '+'}
-     * (<tt>'&#92;u002B'</tt>) otherwise).
+     * (<code>'&#92;u002B'</code>) otherwise).
      *
      * <p>Finally, the entire string is prefixed by a minus sign
-     * character {@code '-'} (<tt>'&#92;u002D'</tt>) if the unscaled
+     * character {@code '-'} (<code>'&#92;u002D'</code>) if the unscaled
      * value is less than zero.  No sign character is prefixed if the
      * unscaled value is zero or positive.
      *
@@ -2883,8 +3319,9 @@
     @Override
     public String toString() {
         String sc = stringCache;
-        if (sc == null)
+        if (sc == null) {
             stringCache = sc = layoutChars(true);
+        }
         return sc;
     }
 
@@ -2927,7 +3364,7 @@
      * in the result.
      *
      * The entire string is prefixed by a minus sign character '-'
-     * (<tt>'&#92;u002D'</tt>) if the unscaled value is less than
+     * (<code>'&#92;u002D'</code>) if the unscaled value is less than
      * zero. No sign character is prefixed if the unscaled value is
      * zero or positive.
      *
@@ -2961,18 +3398,19 @@
             if(signum()==0) {
                 return "0";
             }
-            int tailingZeros = checkScaleNonZero((-(long)scale));
+            int trailingZeros = checkScaleNonZero((-(long)scale));
             StringBuilder buf;
             if(intCompact!=INFLATED) {
-                buf = new StringBuilder(20+tailingZeros);
+                buf = new StringBuilder(20+trailingZeros);
                 buf.append(intCompact);
             } else {
                 String str = intVal.toString();
-                buf = new StringBuilder(str.length()+tailingZeros);
+                buf = new StringBuilder(str.length()+trailingZeros);
                 buf.append(str);
             }
-            for (int i = 0; i < tailingZeros; i++)
+            for (int i = 0; i < trailingZeros; i++) {
                 buf.append('0');
+            }
             return buf.toString();
         }
         String str ;
@@ -2999,8 +3437,9 @@
         } else { /* We must insert zeros between point and intVal */
             buf = new StringBuilder(3-insertionPoint + intString.length());
             buf.append(signum<0 ? "-0." : "0.");
-            for (int i=0; i<-insertionPoint; i++)
+            for (int i=0; i<-insertionPoint; i++) {
                 buf.append('0');
+            }
             buf.append(intString);
         }
         return buf.toString();
@@ -3010,7 +3449,7 @@
      * Converts this {@code BigDecimal} to a {@code BigInteger}.
      * This conversion is analogous to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code long} as defined in section 5.1.3 of
+     * {@code long} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * any fractional part of this
      * {@code BigDecimal} will be discarded.  Note that this
@@ -3022,6 +3461,7 @@
      * {@link #toBigIntegerExact()} method.
      *
      * @return this {@code BigDecimal} converted to a {@code BigInteger}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public BigInteger toBigInteger() {
         // force to an integer, quietly
@@ -3047,7 +3487,7 @@
      * Converts this {@code BigDecimal} to a {@code long}.
      * This conversion is analogous to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code short} as defined in section 5.1.3 of
+     * {@code short} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * any fractional part of this
      * {@code BigDecimal} will be discarded, and if the resulting
@@ -3058,7 +3498,9 @@
      * as return a result with the opposite sign.
      *
      * @return this {@code BigDecimal} converted to a {@code long}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
+    @Override
     public long longValue(){
         if (intCompact != INFLATED && scale == 0) {
             return intCompact;
@@ -3143,7 +3585,7 @@
      * Converts this {@code BigDecimal} to an {@code int}.
      * This conversion is analogous to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code short} as defined in section 5.1.3 of
+     * {@code short} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * any fractional part of this
      * {@code BigDecimal} will be discarded, and if the resulting
@@ -3154,7 +3596,9 @@
      * value as well as return a result with the opposite sign.
      *
      * @return this {@code BigDecimal} converted to an {@code int}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
+    @Override
     public int intValue() {
         return  (intCompact != INFLATED && scale == 0) ?
             (int)intCompact :
@@ -3225,7 +3669,7 @@
      * Converts this {@code BigDecimal} to a {@code float}.
      * This conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this {@code BigDecimal} has too great a
      * magnitude to represent as a {@code float}, it will be
@@ -3236,7 +3680,9 @@
      * value.
      *
      * @return this {@code BigDecimal} converted to a {@code float}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
+    @Override
     public float floatValue(){
         if(intCompact != INFLATED) {
             if (scale == 0) {
@@ -3252,10 +3698,10 @@
                     // Don't have too guard against
                     // Math.abs(MIN_VALUE) because of outer check
                     // against INFLATED.
-                    if (scale > 0 && scale < float10pow.length) {
-                        return (float)intCompact / float10pow[scale];
-                    } else if (scale < 0 && scale > -float10pow.length) {
-                        return (float)intCompact * float10pow[-scale];
+                    if (scale > 0 && scale < FLOAT_10_POW.length) {
+                        return (float)intCompact / FLOAT_10_POW[scale];
+                    } else if (scale < 0 && scale > -FLOAT_10_POW.length) {
+                        return (float)intCompact * FLOAT_10_POW[-scale];
                     }
                 }
             }
@@ -3268,7 +3714,7 @@
      * Converts this {@code BigDecimal} to a {@code double}.
      * This conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this {@code BigDecimal} has too great a
      * magnitude represent as a {@code double}, it will be
@@ -3279,7 +3725,9 @@
      * value.
      *
      * @return this {@code BigDecimal} converted to a {@code double}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
+    @Override
     public double doubleValue(){
         if(intCompact != INFLATED) {
             if (scale == 0) {
@@ -3295,10 +3743,10 @@
                     // Don't have too guard against
                     // Math.abs(MIN_VALUE) because of outer check
                     // against INFLATED.
-                    if (scale > 0 && scale < double10pow.length) {
-                        return (double)intCompact / double10pow[scale];
-                    } else if (scale < 0 && scale > -double10pow.length) {
-                        return (double)intCompact * double10pow[-scale];
+                    if (scale > 0 && scale < DOUBLE_10_POW.length) {
+                        return (double)intCompact / DOUBLE_10_POW[scale];
+                    } else if (scale < 0 && scale > -DOUBLE_10_POW.length) {
+                        return (double)intCompact * DOUBLE_10_POW[-scale];
                     }
                 }
             }
@@ -3311,7 +3759,7 @@
      * Powers of 10 which can be represented exactly in {@code
      * double}.
      */
-    private static final double double10pow[] = {
+    private static final double DOUBLE_10_POW[] = {
         1.0e0,  1.0e1,  1.0e2,  1.0e3,  1.0e4,  1.0e5,
         1.0e6,  1.0e7,  1.0e8,  1.0e9,  1.0e10, 1.0e11,
         1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17,
@@ -3322,7 +3770,7 @@
      * Powers of 10 which can be represented exactly in {@code
      * float}.
      */
-    private static final float float10pow[] = {
+    private static final float FLOAT_10_POW[] = {
         1.0e0f, 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
         1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
     };
@@ -3417,7 +3865,7 @@
             return charPos;
         }
 
-        final static char[] DIGIT_TENS = {
+        static final char[] DIGIT_TENS = {
             '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
             '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
             '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
@@ -3430,7 +3878,7 @@
             '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
         };
 
-        final static char[] DIGIT_ONES = {
+        static final char[] DIGIT_ONES = {
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
             '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
@@ -3535,8 +3983,9 @@
                 } else if (sig >= coeffLen) {   // significand all in integer
                     buf.append(coeff, offset, coeffLen);
                     // may need some zeros, too
-                    for (int i = sig - coeffLen; i > 0; i--)
+                    for (int i = sig - coeffLen; i > 0; i--) {
                         buf.append('0');
+                    }
                 } else {                     // xx.xxE form
                     buf.append(coeff, offset, sig);
                     buf.append('.');
@@ -3590,11 +4039,13 @@
             // to prevent multiple threads from expanding the same array.
             if (curLen <= n) {
                 int newLen = curLen << 1;
-                while (newLen <= n)
+                while (newLen <= n) {
                     newLen <<= 1;
+                }
                 pows = Arrays.copyOf(pows, newLen);
-                for (int i = curLen; i < newLen; i++)
+                for (int i = curLen; i < newLen; i++) {
                     pows[i] = pows[i - 1].multiply(BigInteger.TEN);
+                }
                 // Based on the following facts:
                 // 1. pows is a private local variable;
                 // 2. the following store is a volatile store.
@@ -3734,9 +4185,7 @@
      *         {@code BigDecimal}s to be aligned.
      */
     private static void matchScale(BigDecimal[] val) {
-        if (val[0].scale == val[1].scale) {
-            return;
-        } else if (val[0].scale < val[1].scale) {
+        if (val[0].scale < val[1].scale) {
             val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY);
         } else if (val[1].scale < val[0].scale) {
             val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY);
@@ -4240,16 +4689,16 @@
      * do rounding based on the passed in roundingMode.
      */
     private static BigInteger divideAndRound(BigInteger bdividend, long ldivisor, int roundingMode) {
-        boolean isRemainderZero; // record remainder is zero or not
-        int qsign; // quotient sign
-        long r = 0; // store quotient & remainder in long
-        MutableBigInteger mq = null; // store quotient
         // Descend into mutables for faster remainder checks
         MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
-        mq = new MutableBigInteger();
-        r = mdividend.divide(ldivisor, mq);
-        isRemainderZero = (r == 0);
-        qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
+        // store quotient
+        MutableBigInteger mq = new MutableBigInteger();
+        // store quotient & remainder in long
+        long r = mdividend.divide(ldivisor, mq);
+        // record remainder is zero or not
+        boolean isRemainderZero = (r == 0);
+        // quotient sign
+        int qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
         if (!isRemainderZero) {
             if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) {
                 mq.add(MutableBigInteger.ONE);
@@ -4269,16 +4718,16 @@
      */
     private static BigDecimal divideAndRound(BigInteger bdividend,
                                              long ldivisor, int scale, int roundingMode, int preferredScale) {
-        boolean isRemainderZero; // record remainder is zero or not
-        int qsign; // quotient sign
-        long r = 0; // store quotient & remainder in long
-        MutableBigInteger mq = null; // store quotient
         // Descend into mutables for faster remainder checks
         MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
-        mq = new MutableBigInteger();
-        r = mdividend.divide(ldivisor, mq);
-        isRemainderZero = (r == 0);
-        qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
+        // store quotient
+        MutableBigInteger mq = new MutableBigInteger();
+        // store quotient & remainder in long
+        long r = mdividend.divide(ldivisor, mq);
+        // record remainder is zero or not
+        boolean isRemainderZero = (r == 0);
+        // quotient sign
+        int qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
         if (!isRemainderZero) {
             if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) {
                 mq.add(MutableBigInteger.ONE);
diff --git a/ojluni/src/main/java/java/math/BigInteger.java b/ojluni/src/main/java/java/math/BigInteger.java
index b20c5ec..dc70f11 100644
--- a/ojluni/src/main/java/java/math/BigInteger.java
+++ b/ojluni/src/main/java/java/math/BigInteger.java
@@ -34,13 +34,15 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
 import java.util.Arrays;
+import java.util.Objects;
 import java.util.Random;
 import java.util.concurrent.ThreadLocalRandom;
-import libcore.math.NativeBN;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
-import libcore.util.NonNull;
 
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.HotSpotIntrinsicCandidate;
+
+import libcore.math.NativeBN;
 /**
  * Immutable arbitrary-precision integers.  All operations behave as if
  * BigIntegers were represented in two's-complement notation (like Java's
@@ -51,19 +53,17 @@
  * and a few other miscellaneous operations.
  *
  * <p>Semantics of arithmetic operations exactly mimic those of Java's integer
- * arithmetic operators, as defined in <i>The Java Language Specification</i>.
+ * arithmetic operators, as defined in <i>The Java&trade; Language Specification</i>.
  * For example, division by zero throws an {@code ArithmeticException}, and
  * division of a negative by a positive yields a negative (or zero) remainder.
- * All of the details in the Spec concerning overflow are ignored, as
- * BigIntegers are made as large as necessary to accommodate the results of an
- * operation.
  *
  * <p>Semantics of shift operations extend those of Java's shift operators
  * to allow for negative shift distances.  A right-shift with a negative
  * shift distance results in a left shift, and vice-versa.  The unsigned
- * right shift operator ({@code >>>}) is omitted, as this operation makes
- * little sense in combination with the "infinite word size" abstraction
- * provided by this class.
+ * right shift operator ({@code >>>}) is omitted since this operation
+ * only makes sense for a fixed sized word and not for a
+ * representation conceptually having an infinite number of leading
+ * virtual sign bits.
  *
  * <p>Semantics of bitwise logical operations exactly mimic those of Java's
  * bitwise integer operators.  The binary operators ({@code and},
@@ -83,8 +83,8 @@
  * extended so that it contains the designated bit.  None of the single-bit
  * operations can produce a BigInteger with a different sign from the
  * BigInteger being operated on, as they affect only a single bit, and the
- * "infinite word size" abstraction provided by this class ensures that there
- * are infinitely many "virtual sign bits" preceding each BigInteger.
+ * arbitrarily large abstraction provided by this class ensures that conceptually
+ * there are infinitely many "virtual sign bits" preceding each BigInteger.
  *
  * <p>For the sake of brevity and clarity, pseudo-code is used throughout the
  * descriptions of BigInteger methods.  The pseudo-code expression
@@ -104,34 +104,36 @@
  * +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive)
  * and may support values outside of that range.
  *
+ * An {@code ArithmeticException} is thrown when a BigInteger
+ * constructor or method would generate a value outside of the
+ * supported range.
+ *
  * The range of probable prime values is limited and may be less than
  * the full supported positive range of {@code BigInteger}.
  * The range must be at least 1 to 2<sup>500000000</sup>.
  *
  * @implNote
- * BigInteger constructors and operations throw {@code ArithmeticException} when
- * the result is out of the supported range of
+ * In the reference implementation, BigInteger constructors and
+ * operations throw {@code ArithmeticException} when the result is out
+ * of the supported range of
  * -2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive) to
  * +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive).
  *
  * @see     BigDecimal
+ * @jls     4.2.2 Integer Operations
  * @author  Josh Bloch
  * @author  Michael McCloskey
  * @author  Alan Eliasen
  * @author  Timothy Buktu
- * @since JDK1.1
+ * @since 1.1
  */
 
 public class BigInteger extends Number implements Comparable<BigInteger> {
-    // Android-changed: Added @NonNull annotations.
-
     /**
      * The signum of this BigInteger: -1 for negative, 0 for zero, or
-     * 1 for positive.  Note that the BigInteger zero <i>must</i> have
+     * 1 for positive.  Note that the BigInteger zero <em>must</em> have
      * a signum of 0.  This is necessary to ensures that there is exactly one
      * representation for each BigInteger value.
-     *
-     * @serial
      */
     final int signum;
 
@@ -146,60 +148,48 @@
      */
     final int[] mag;
 
-    // These "redundant fields" are initialized with recognizable nonsense
-    // values, and cached the first time they are needed (or never, if they
-    // aren't needed).
-
-     /**
-     * One plus the bitCount of this BigInteger. Zeros means uninitialized.
-     *
-     * @serial
-     * @see #bitCount
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
-     */
-    @Deprecated
-    private int bitCount;
+    // The following fields are stable variables. A stable variable's value
+    // changes at most once from the default zero value to a non-zero stable
+    // value. A stable value is calculated lazily on demand.
 
     /**
-     * One plus the bitLength of this BigInteger. Zeros means uninitialized.
+     * One plus the bitCount of this BigInteger. This is a stable variable.
+     *
+     * @see #bitCount
+     */
+    private int bitCountPlusOne;
+
+    /**
+     * One plus the bitLength of this BigInteger. This is a stable variable.
      * (either value is acceptable).
      *
-     * @serial
      * @see #bitLength()
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
      */
-    @Deprecated
-    private int bitLength;
+    private int bitLengthPlusOne;
 
     /**
-     * Two plus the lowest set bit of this BigInteger, as returned by
-     * getLowestSetBit().
+     * Two plus the lowest set bit of this BigInteger. This is a stable variable.
      *
-     * @serial
      * @see #getLowestSetBit
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
      */
-    @Deprecated
-    private int lowestSetBit;
+    private int lowestSetBitPlusTwo;
 
     /**
      * Two plus the index of the lowest-order int in the magnitude of this
-     * BigInteger that contains a nonzero int, or -2 (either value is acceptable).
-     * The least significant int has int-number 0, the next int in order of
+     * BigInteger that contains a nonzero int. This is a stable variable. The
+     * least significant int has int-number 0, the next int in order of
      * increasing significance has int-number 1, and so forth.
-     * @deprecated Deprecated since logical value is offset from stored
-     * value and correction factor is applied in accessor method.
+     *
+     * <p>Note: never used for a BigInteger with a magnitude of zero.
+     *
+     * @see #firstNonzeroIntNum()
      */
-    @Deprecated
-    private int firstNonzeroIntNum;
+    private int firstNonzeroIntNumPlusTwo;
 
     /**
      * This mask is used to obtain the value of an int as if it were unsigned.
      */
-    final static long LONG_MASK = 0xffffffffL;
+    static final long LONG_MASK = 0xffffffffL;
 
     /**
      * This constant limits {@code mag.length} of BigIntegers to the supported
@@ -292,24 +282,39 @@
     // Constructors
 
     /**
-     * Translates a byte array containing the two's-complement binary
-     * representation of a BigInteger into a BigInteger.  The input array is
+     * Translates a byte sub-array containing the two's-complement binary
+     * representation of a BigInteger into a BigInteger.  The sub-array is
+     * specified via an offset into the array and a length.  The sub-array is
      * assumed to be in <i>big-endian</i> byte-order: the most significant
-     * byte is in the zeroth element.
+     * byte is the element at index {@code off}.  The {@code val} array is
+     * assumed to be unchanged for the duration of the constructor call.
      *
-     * @param  val big-endian two's-complement binary representation of
-     *         BigInteger.
+     * An {@code IndexOutOfBoundsException} is thrown if the length of the array
+     * {@code val} is non-zero and either {@code off} is negative, {@code len}
+     * is negative, or {@code off+len} is greater than the length of
+     * {@code val}.
+     *
+     * @param  val byte array containing a sub-array which is the big-endian
+     *         two's-complement binary representation of a BigInteger.
+     * @param  off the start offset of the binary representation.
+     * @param  len the number of bytes to use.
      * @throws NumberFormatException {@code val} is zero bytes long.
+     * @throws IndexOutOfBoundsException if the provided array offset and
+     *         length would cause an index into the byte array to be
+     *         negative or greater than or equal to the array length.
+     * @since 9
      */
-    public BigInteger(byte[] val) {
-        if (val.length == 0)
+    public BigInteger(byte[] val, int off, int len) {
+        if (val.length == 0) {
             throw new NumberFormatException("Zero length BigInteger");
+        }
+        Objects.checkFromIndexSize(off, len, val.length);
 
-        if (val[0] < 0) {
-            mag = makePositive(val);
+        if (val[off] < 0) {
+            mag = makePositive(val, off, len);
             signum = -1;
         } else {
-            mag = stripLeadingZeroBytes(val);
+            mag = stripLeadingZeroBytes(val, off, len);
             signum = (mag.length == 0 ? 0 : 1);
         }
         if (mag.length >= MAX_MAG_LENGTH) {
@@ -318,10 +323,27 @@
     }
 
     /**
+     * Translates a byte array containing the two's-complement binary
+     * representation of a BigInteger into a BigInteger.  The input array is
+     * assumed to be in <i>big-endian</i> byte-order: the most significant
+     * byte is in the zeroth element.  The {@code val} array is assumed to be
+     * unchanged for the duration of the constructor call.
+     *
+     * @param  val big-endian two's-complement binary representation of a
+     *         BigInteger.
+     * @throws NumberFormatException {@code val} is zero bytes long.
+     */
+    public BigInteger(byte[] val) {
+        this(val, 0, val.length);
+    }
+
+    /**
      * This private constructor translates an int array containing the
      * two's-complement binary representation of a BigInteger into a
      * BigInteger. The input array is assumed to be in <i>big-endian</i>
-     * int-order: the most significant int is in the zeroth element.
+     * int-order: the most significant int is in the zeroth element.  The
+     * {@code val} array is assumed to be unchanged for the duration of
+     * the constructor call.
      */
     private BigInteger(int[] val) {
         if (val.length == 0)
@@ -342,24 +364,40 @@
     /**
      * Translates the sign-magnitude representation of a BigInteger into a
      * BigInteger.  The sign is represented as an integer signum value: -1 for
-     * negative, 0 for zero, or 1 for positive.  The magnitude is a byte array
-     * in <i>big-endian</i> byte-order: the most significant byte is in the
-     * zeroth element.  A zero-length magnitude array is permissible, and will
-     * result in a BigInteger value of 0, whether signum is -1, 0 or 1.
+     * negative, 0 for zero, or 1 for positive.  The magnitude is a sub-array of
+     * a byte array in <i>big-endian</i> byte-order: the most significant byte
+     * is the element at index {@code off}.  A zero value of the length
+     * {@code len} is permissible, and will result in a BigInteger value of 0,
+     * whether signum is -1, 0 or 1.  The {@code magnitude} array is assumed to
+     * be unchanged for the duration of the constructor call.
+     *
+     * An {@code IndexOutOfBoundsException} is thrown if the length of the array
+     * {@code magnitude} is non-zero and either {@code off} is negative,
+     * {@code len} is negative, or {@code off+len} is greater than the length of
+     * {@code magnitude}.
      *
      * @param  signum signum of the number (-1 for negative, 0 for zero, 1
      *         for positive).
      * @param  magnitude big-endian binary representation of the magnitude of
      *         the number.
+     * @param  off the start offset of the binary representation.
+     * @param  len the number of bytes to use.
      * @throws NumberFormatException {@code signum} is not one of the three
      *         legal values (-1, 0, and 1), or {@code signum} is 0 and
      *         {@code magnitude} contains one or more non-zero bytes.
+     * @throws IndexOutOfBoundsException if the provided array offset and
+     *         length would cause an index into the byte array to be
+     *         negative or greater than or equal to the array length.
+     * @since 9
      */
-    public BigInteger(int signum, byte[] magnitude) {
-        this.mag = stripLeadingZeroBytes(magnitude);
-
-        if (signum < -1 || signum > 1)
+    public BigInteger(int signum, byte[] magnitude, int off, int len) {
+        if (signum < -1 || signum > 1) {
             throw(new NumberFormatException("Invalid signum value"));
+        }
+        Objects.checkFromIndexSize(off, len, magnitude.length);
+
+        // stripLeadingZeroBytes() returns a zero length array if len == 0
+        this.mag = stripLeadingZeroBytes(magnitude, off, len);
 
         if (this.mag.length == 0) {
             this.signum = 0;
@@ -374,10 +412,33 @@
     }
 
     /**
+     * Translates the sign-magnitude representation of a BigInteger into a
+     * BigInteger.  The sign is represented as an integer signum value: -1 for
+     * negative, 0 for zero, or 1 for positive.  The magnitude is a byte array
+     * in <i>big-endian</i> byte-order: the most significant byte is the
+     * zeroth element.  A zero-length magnitude array is permissible, and will
+     * result in a BigInteger value of 0, whether signum is -1, 0 or 1.  The
+     * {@code magnitude} array is assumed to be unchanged for the duration of
+     * the constructor call.
+     *
+     * @param  signum signum of the number (-1 for negative, 0 for zero, 1
+     *         for positive).
+     * @param  magnitude big-endian binary representation of the magnitude of
+     *         the number.
+     * @throws NumberFormatException {@code signum} is not one of the three
+     *         legal values (-1, 0, and 1), or {@code signum} is 0 and
+     *         {@code magnitude} contains one or more non-zero bytes.
+     */
+    public BigInteger(int signum, byte[] magnitude) {
+         this(signum, magnitude, 0, magnitude.length);
+    }
+
+    /**
      * A constructor for internal use that translates the sign-magnitude
      * representation of a BigInteger into a BigInteger. It checks the
      * arguments and copies the magnitude so this constructor would be
-     * safe for external use.
+     * safe for external use.  The {@code magnitude} array is assumed to be
+     * unchanged for the duration of the constructor call.
      */
     private BigInteger(int signum, int[] magnitude) {
         this.mag = stripLeadingZeroInts(magnitude);
@@ -414,7 +475,7 @@
      *         {@link Character#MAX_RADIX}, inclusive.
      * @see    Character#digit
      */
-    public BigInteger(@NonNull String val, int radix) {
+    public BigInteger(String val, int radix) {
         int cursor = 0, numDigits;
         final int len = val.length();
 
@@ -494,7 +555,9 @@
 
     /*
      * Constructs a new BigInteger using a char array with radix=10.
-     * Sign is precalculated outside and not allowed in the val.
+     * Sign is precalculated outside and not allowed in the val. The {@code val}
+     * array is assumed to be unchanged for the duration of the constructor
+     * call.
      */
     BigInteger(char[] val, int sign, int len) {
         int cursor = 0, numDigits;
@@ -606,7 +669,7 @@
      *         of a BigInteger.
      * @see    Character#digit
      */
-    public BigInteger(@NonNull String val) {
+    public BigInteger(String val) {
         this(val, 10);
     }
 
@@ -623,7 +686,7 @@
      * @throws IllegalArgumentException {@code numBits} is negative.
      * @see #bitLength()
      */
-    public BigInteger(int numBits, @NonNull Random rnd) {
+    public BigInteger(int numBits, Random rnd) {
         this(1, randomBits(numBits, rnd));
     }
 
@@ -646,7 +709,7 @@
      * Constructs a randomly generated positive BigInteger that is probably
      * prime, with the specified bitLength.
      *
-     * <p>It is recommended that the {@link #probablePrime probablePrime}
+     * @apiNote It is recommended that the {@link #probablePrime probablePrime}
      * method be used in preference to this constructor unless there
      * is a compelling need to specify a certainty.
      *
@@ -661,7 +724,7 @@
      * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
      * @see    #bitLength()
      */
-    public BigInteger(int bitLength, int certainty, @NonNull Random rnd) {
+    public BigInteger(int bitLength, int certainty, Random rnd) {
         BigInteger prime;
 
         if (bitLength < 2)
@@ -694,7 +757,7 @@
      * @see    #bitLength()
      * @since 1.4
      */
-    @NonNull public static BigInteger probablePrime(int bitLength, @NonNull Random rnd) {
+    public static BigInteger probablePrime(int bitLength, Random rnd) {
         if (bitLength < 2)
             throw new ArithmeticException("bitLength < 2");
 
@@ -710,7 +773,7 @@
      *
      * This method assumes bitLength > 1.
      */
-    private static BigInteger smallPrime(int bitLength, int certainty, @NonNull Random rnd) {
+    private static BigInteger smallPrime(int bitLength, int certainty, Random rnd) {
         int magLen = (bitLength + 31) >>> 5;
         int temp[] = new int[magLen];
         int highBit = 1 << ((bitLength+31) & 0x1f);  // High bit of high int
@@ -754,7 +817,7 @@
      * a sieve to eliminate most composites before using a more expensive
      * test.
      */
-    private static BigInteger largePrime(int bitLength, int certainty, @NonNull Random rnd) {
+    private static BigInteger largePrime(int bitLength, int certainty, Random rnd) {
         BigInteger p;
         p = new BigInteger(bitLength, rnd).setBit(bitLength-1);
         p.mag[p.mag.length-1] &= 0xfffffffe;
@@ -787,7 +850,7 @@
     * @throws ArithmeticException {@code this < 0} or {@code this} is too large.
     * @since 1.5
     */
-    @NonNull public BigInteger nextProbablePrime() {
+    public BigInteger nextProbablePrime() {
         if (this.signum < 0)
             throw new ArithmeticException("start < 0: " + this);
 
@@ -866,7 +929,7 @@
      * @return {@code true} if this BigInteger is probably prime,
      *         {@code false} if it's definitely composite.
      */
-    boolean primeToCertainty(int certainty, @NonNull Random random) {
+    boolean primeToCertainty(int certainty, Random random) {
         int rounds = 0;
         int n = (Math.min(certainty, Integer.MAX_VALUE-1)+1)/2;
 
@@ -923,7 +986,7 @@
      * Computes Jacobi(p,n).
      * Assumes n positive, odd, n>=3.
      */
-    private static int jacobiSymbol(int p, @NonNull BigInteger n) {
+    private static int jacobiSymbol(int p, BigInteger n) {
         if (p == 0)
             return 0;
 
@@ -977,7 +1040,7 @@
         return 0;
     }
 
-    @NonNull private static BigInteger lucasLehmerSequence(int z, @NonNull BigInteger k, @NonNull BigInteger n) {
+    private static BigInteger lucasLehmerSequence(int z, BigInteger k, BigInteger n) {
         BigInteger d = BigInteger.valueOf(z);
         BigInteger u = ONE; BigInteger u2;
         BigInteger v = ONE; BigInteger v2;
@@ -1018,7 +1081,7 @@
      * This BigInteger is a positive, odd number greater than 2.
      * iterations<=50.
      */
-    private boolean passesMillerRabin(int iterations, @NonNull Random rnd) {
+    private boolean passesMillerRabin(int iterations, Random rnd) {
         // Find a and m such that m is odd and this == 1 + 2**a * m
         BigInteger thisMinusOne = this.subtract(ONE);
         BigInteger m = thisMinusOne;
@@ -1062,11 +1125,12 @@
 
     /**
      * This private constructor is for internal use and assumes that its
-     * arguments are correct.
+     * arguments are correct.  The {@code magnitude} array is assumed to be
+     * unchanged for the duration of the constructor call.
      */
     private BigInteger(byte[] magnitude, int signum) {
         this.signum = (magnitude.length == 0 ? 0 : signum);
-        this.mag = stripLeadingZeroBytes(magnitude);
+        this.mag = stripLeadingZeroBytes(magnitude, 0, magnitude.length);
         if (mag.length >= MAX_MAG_LENGTH) {
             checkRange();
         }
@@ -1092,14 +1156,16 @@
 
     /**
      * Returns a BigInteger whose value is equal to that of the
-     * specified {@code long}.  This "static factory method" is
-     * provided in preference to a ({@code long}) constructor
-     * because it allows for reuse of frequently used BigIntegers.
+     * specified {@code long}.
+     *
+     * @apiNote This static factory method is provided in preference
+     * to a ({@code long}) constructor because it allows for reuse of
+     * frequently used BigIntegers.
      *
      * @param  val value of the BigInteger to return.
      * @return a BigInteger with the specified value.
      */
-    @NonNull public static BigInteger valueOf(long val) {
+    public static BigInteger valueOf(long val) {
         // If -MAX_CONSTANT < val < MAX_CONSTANT, return stashed constant
         if (val == 0)
             return ZERO;
@@ -1114,7 +1180,7 @@
     /**
      * Constructs a BigInteger with the specified value, which may not be zero.
      */
-    @NonNull private BigInteger(long val) {
+    private BigInteger(long val) {
         if (val < 0) {
             val = -val;
             signum = -1;
@@ -1138,7 +1204,7 @@
      * Assumes that the input array will not be modified (the returned
      * BigInteger will reference the input array if feasible).
      */
-    @NonNull private static BigInteger valueOf(int val[]) {
+    private static BigInteger valueOf(int val[]) {
         return (val[0] > 0 ? new BigInteger(val, 1) : new BigInteger(val));
     }
 
@@ -1147,7 +1213,7 @@
     /**
      * Initialize static constant array when class is loaded.
      */
-    private final static int MAX_CONSTANT = 16;
+    private static final int MAX_CONSTANT = 16;
     private static BigInteger posConst[] = new BigInteger[MAX_CONSTANT+1];
     private static BigInteger negConst[] = new BigInteger[MAX_CONSTANT+1];
 
@@ -1199,31 +1265,33 @@
      *
      * @since   1.2
      */
-    @NonNull public static final BigInteger ZERO = new BigInteger(new int[0], 0);
+    public static final BigInteger ZERO = new BigInteger(new int[0], 0);
 
     /**
      * The BigInteger constant one.
      *
      * @since   1.2
      */
-    @NonNull public static final BigInteger ONE = valueOf(1);
+    public static final BigInteger ONE = valueOf(1);
 
     /**
-     * The BigInteger constant two.  (Not exported.)
+     * The BigInteger constant two.
+     *
+     * @since   9
      */
-    @NonNull private static final BigInteger TWO = valueOf(2);
+    public static final BigInteger TWO = valueOf(2);
 
     /**
      * The BigInteger constant -1.  (Not exported.)
      */
-    @NonNull private static final BigInteger NEGATIVE_ONE = valueOf(-1);
+    private static final BigInteger NEGATIVE_ONE = valueOf(-1);
 
     /**
      * The BigInteger constant ten.
      *
      * @since   1.5
      */
-    @NonNull public static final BigInteger TEN = valueOf(10);
+    public static final BigInteger TEN = valueOf(10);
 
     // Arithmetic Operations
 
@@ -1233,7 +1301,7 @@
      * @param  val value to be added to this BigInteger.
      * @return {@code this + val}
      */
-    @NonNull public BigInteger add(@NonNull BigInteger val) {
+    public BigInteger add(BigInteger val) {
         if (val.signum == 0)
             return this;
         if (signum == 0)
@@ -1255,7 +1323,7 @@
      * Package private methods used by BigDecimal code to add a BigInteger
      * with a long. Assumes val is not equal to INFLATED.
      */
-    @NonNull BigInteger add(long val) {
+    BigInteger add(long val) {
         if (val == 0)
             return this;
         if (signum == 0)
@@ -1435,7 +1503,7 @@
      * @param  val value to be subtracted from this BigInteger.
      * @return {@code this - val}
      */
-    @NonNull public BigInteger subtract(@NonNull BigInteger val) {
+    public BigInteger subtract(BigInteger val) {
         if (val.signum == 0)
             return this;
         if (signum == 0)
@@ -1493,7 +1561,7 @@
      * @param  val value to be multiplied by this BigInteger.
      * @return {@code this * val}
      */
-    @NonNull public BigInteger multiply(@NonNull BigInteger val) {
+    public BigInteger multiply(BigInteger val) {
         return multiply(val, false);
     }
 
@@ -1505,7 +1573,7 @@
      * @param  isRecursion whether this is a recursive invocation
      * @return {@code this * val}
      */
-    @NonNull private BigInteger multiply(@NonNull BigInteger val, boolean isRecursion) {
+    private BigInteger multiply(BigInteger val, boolean isRecursion) {
         if (val.signum == 0 || signum == 0)
             return ZERO;
 
@@ -1513,17 +1581,17 @@
 
         // BEGIN Android-changed: Fall back to the boringssl implementation for
         // large arguments.
-        int ylen = val.mag.length;
-
         final int BORINGSSL_MUL_THRESHOLD = 50;
 
+        if (val == this && xlen > MULTIPLY_SQUARE_THRESHOLD
+                && xlen < BORINGSSL_MUL_THRESHOLD) {
+            return square();
+        }
+
+        int ylen = val.mag.length;
+
         int resultSign = signum == val.signum ? 1 : -1;
         if ((xlen < BORINGSSL_MUL_THRESHOLD) || (ylen < BORINGSSL_MUL_THRESHOLD)) {
-            if (val == this && xlen > MULTIPLY_SQUARE_THRESHOLD) {
-                // Helps less than boringssl fallback; prefer that.
-                return square();
-            }
-
             if (val.mag.length == 1) {
                 return multiplyByInt(mag,val.mag[0], resultSign);
             }
@@ -1612,14 +1680,18 @@
                 return multiplyToomCook3(this, val);
             }
             */
+        // END Android-changed: Fall back to the boringssl implementation for
+        // large arguments.
         }
     }
 
-    @NonNull private static BigInteger multiplyByInt(int[] x, int y, int sign) {
+    private static BigInteger multiplyByInt(int[] x, int y, int sign) {
         if (Integer.bitCount(y) == 1) {
             return new BigInteger(shiftLeft(x,Integer.numberOfTrailingZeros(y)), sign);
         }
         int xlen = x.length;
+        // BEGIN Android-changed: Try to predict result length to avoid copy. http://b/140780742
+        /*
         int[] rmag =  new int[xlen + 1];
         long carry = 0;
         long yl = y & LONG_MASK;
@@ -1634,6 +1706,32 @@
         } else {
             rmag[rstart] = (int)carry;
         }
+        */
+        long carry = 0;
+        long yl = y & LONG_MASK;
+        // Bound the 2 most significant product (int-sized) "digits". Less-significant ints in x's
+        // magnitude cannot contribute more than 1 in the uppermost int.
+        long highDigitsBound = ((x[0] & LONG_MASK) + 1) * yl;  // Cannot overflow as unsigned long.
+        int rlen = ((highDigitsBound >>> 32) == 0) ? xlen : xlen + 1;
+        int[] rmag =  new int[rlen];
+        int rindex = rlen - 1;
+        for (int i = xlen - 1; i >= 0; i--) {
+            long product = (x[i] & LONG_MASK) * yl + carry;
+            rmag[rindex--] = (int)product;
+            carry = product >>> 32;
+        }
+        if (rindex == -1) {
+            assert(carry == 0);
+        } else {
+            assert(rindex == 0);
+            if (carry == 0) {
+                // We mis-estimated the length. Very rare.
+                rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length);
+            } else {
+                rmag[0] = (int)carry;
+            }
+        }
+        // END Android-changed: Try to predict result length to avoid copy.
         return new BigInteger(rmag, sign);
     }
 
@@ -1641,7 +1739,7 @@
      * Package private methods used by BigDecimal code to multiply a BigInteger
      * with a long. Assumes v is not equal to INFLATED.
      */
-    @NonNull BigInteger multiply(long v) {
+    BigInteger multiply(long v) {
         if (v == 0 || signum == 0)
           return ZERO;
         if (v == BigDecimal.INFLATED)
@@ -1684,6 +1782,13 @@
      * the result into z. There will be no leading zeros in the resultant array.
      */
     private static int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) {
+        multiplyToLenCheck(x, xlen);
+        multiplyToLenCheck(y, ylen);
+        return implMultiplyToLen(x, xlen, y, ylen, z);
+    }
+
+    @HotSpotIntrinsicCandidate
+    private static int[] implMultiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) {
         int xstart = xlen - 1;
         int ystart = ylen - 1;
 
@@ -1713,6 +1818,18 @@
         return z;
     }
 
+    private static void multiplyToLenCheck(int[] array, int length) {
+        if (length <= 0) {
+            return;  // not an error because multiplyToLen won't execute if len <= 0
+        }
+
+        Objects.requireNonNull(array);
+
+        if (length > array.length) {
+            throw new ArrayIndexOutOfBoundsException(length - 1);
+        }
+    }
+
     /**
      * Multiplies two BigIntegers using the Karatsuba multiplication
      * algorithm.  This is a recursive divide-and-conquer algorithm which is
@@ -1728,7 +1845,7 @@
      *
      * See:  http://en.wikipedia.org/wiki/Karatsuba_algorithm
      */
-    @NonNull private static BigInteger multiplyKaratsuba(@NonNull BigInteger x, @NonNull BigInteger y) {
+    private static BigInteger multiplyKaratsuba(BigInteger x, BigInteger y) {
         int xlen = x.mag.length;
         int ylen = y.mag.length;
 
@@ -1786,7 +1903,7 @@
      * LNCS #4547. Springer, Madrid, Spain, June 21-22, 2007.
      *
      */
-    @NonNull private static BigInteger multiplyToomCook3(@NonNull BigInteger a, @NonNull BigInteger b) {
+    private static BigInteger multiplyToomCook3(BigInteger a, BigInteger b) {
         int alen = a.mag.length;
         int blen = b.mag.length;
 
@@ -1861,7 +1978,7 @@
      * slices to the appropriate position when multiplying different-sized
      * numbers.
      */
-    @NonNull private BigInteger getToomSlice(int lowerSize, int upperSize, int slice,
+    private BigInteger getToomSlice(int lowerSize, int upperSize, int slice,
                                     int fullsize) {
         int start, end, sliceSize, len, offset;
 
@@ -1909,7 +2026,7 @@
      * undefined.  Note that this is expected to be called with positive
      * arguments only.
      */
-    @NonNull private BigInteger exactDivideBy3() {
+    private BigInteger exactDivideBy3() {
         int len = mag.length;
         int[] result = new int[len];
         long x, w, q, borrow;
@@ -1945,7 +2062,7 @@
      * Returns a new BigInteger representing n lower ints of the number.
      * This is used by Karatsuba multiplication and Karatsuba squaring.
      */
-    @NonNull private BigInteger getLower(int n) {
+    private BigInteger getLower(int n) {
         int len = mag.length;
 
         if (len <= n) {
@@ -1963,7 +2080,7 @@
      * ints of the number.  This is used by Karatsuba multiplication and
      * Karatsuba squaring.
      */
-    @NonNull private BigInteger getUpper(int n) {
+    private BigInteger getUpper(int n) {
         int len = mag.length;
 
         if (len <= n) {
@@ -1984,7 +2101,7 @@
      *
      * @return {@code this<sup>2</sup>}
      */
-    @NonNull private BigInteger square() {
+    private BigInteger square() {
         return square(false);
     }
 
@@ -1995,7 +2112,7 @@
      * @param isRecursion whether this is a recursive invocation
      * @return {@code this<sup>2</sup>}
      */
-    @NonNull private BigInteger square(boolean isRecursion) {
+    private BigInteger square(boolean isRecursion) {
         if (signum == 0) {
             return ZERO;
         }
@@ -2063,6 +2180,7 @@
      /**
       * Java Runtime may use intrinsic for this method.
       */
+     @HotSpotIntrinsicCandidate
      private static final int[] implSquareToLen(int[] x, int len, int[] z, int zlen) {
         /*
          * The algorithm used here is adapted from Colin Plumb's C library.
@@ -2130,7 +2248,7 @@
      * has better asymptotic performance than the algorithm used in
      * squareToLen.
      */
-    @NonNull private BigInteger squareKaratsuba() {
+    private BigInteger squareKaratsuba() {
         int half = (mag.length+1) / 2;
 
         BigInteger xl = getLower(half);
@@ -2150,7 +2268,7 @@
      * that has better asymptotic performance than the algorithm used in
      * squareToLen or squareKaratsuba.
      */
-    @NonNull private BigInteger squareToomCook3() {
+    private BigInteger squareToomCook3() {
         int len = mag.length;
 
         // k is the size (in ints) of the lower-order slices.
@@ -2198,7 +2316,7 @@
     // Division
 
 
-    // BEGIN Android-modified: Fall back to boringssl for large problems.
+    // BEGIN Android-changed: Fall back to boringssl for large problems.
     private static final int BORINGSSL_DIV_THRESHOLD = 40;
     private static final int BORINGSSL_DIV_OFFSET = 20;
 
@@ -2209,18 +2327,18 @@
      * @return {@code this / val}
      * @throws ArithmeticException if {@code val} is zero.
      */
-    @NonNull public BigInteger divide(@NonNull BigInteger val) {
+    public BigInteger divide(BigInteger val) {
         // if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD ||
         //        mag.length - val.mag.length < BURNIKEL_ZIEGLER_OFFSET) {
         if (mag.length < BORINGSSL_DIV_THRESHOLD ||
                 mag.length - val.mag.length < BORINGSSL_DIV_OFFSET) {
             return divideKnuth(val);
         } else {
-            return divideAndRemainder(val)[0];
             // return divideBurnikelZiegler(val);
+            return divideAndRemainder(val)[0];
         }
     }
-    // END Android-modified: Fall back to boringssl for large problems.
+    // END Android-changed: Fall back to boringssl for large problems.
 
 
     /**
@@ -2231,7 +2349,7 @@
      * @throws ArithmeticException if {@code val} is zero.
      * @see MutableBigInteger#divideKnuth(MutableBigInteger, MutableBigInteger, boolean)
      */
-    @NonNull private BigInteger divideKnuth(@NonNull BigInteger val) {
+    private BigInteger divideKnuth(BigInteger val) {
         MutableBigInteger q = new MutableBigInteger(),
                           a = new MutableBigInteger(this.mag),
                           b = new MutableBigInteger(val.mag);
@@ -2251,16 +2369,20 @@
      *         is the final element.
      * @throws ArithmeticException if {@code val} is zero.
      */
-    @NonNull public BigInteger[] divideAndRemainder(@NonNull BigInteger val) {
-        // BEGIN Android-modified: Fall back to boringssl for large problems.
-
-        // if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD ||
-        //        mag.length - val.mag < BURNIKEL_ZIEGLER_OFFSET) {
+    public BigInteger[] divideAndRemainder(BigInteger val) {
+        // BEGIN Android-changed: Fall back to boringssl for large problems.
+        /*
+        if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD ||
+               mag.length - val.mag < BURNIKEL_ZIEGLER_OFFSET) {
+         */
         if (val.mag.length < BORINGSSL_DIV_THRESHOLD ||
                 mag.length < BORINGSSL_DIV_OFFSET ||
                 mag.length - val.mag.length < BORINGSSL_DIV_OFFSET) {
             return divideAndRemainderKnuth(val);
         } else {
+            /*
+            return divideAndRemainderBurnikelZiegler(val);
+            */
             int quotSign = signum == val.signum ? 1 : -1;  // 0 divided doesn't get here.
             long xBN = 0, yBN = 0, quotBN = 0, remBN = 0;
             try {
@@ -2280,13 +2402,12 @@
                 NativeBN.BN_free(quotBN);
                 NativeBN.BN_free(remBN);
             }
-            // return divideAndRemainderBurnikelZiegler(val);
         }
-        // END Android-modified: Fall back to boringssl for large problems.
+        // END Android-changed: Fall back to boringssl for large problems.
     }
 
     /** Long division */
-    @NonNull private BigInteger[] divideAndRemainderKnuth(@NonNull BigInteger val) {
+    private BigInteger[] divideAndRemainderKnuth(BigInteger val) {
         BigInteger[] result = new BigInteger[2];
         MutableBigInteger q = new MutableBigInteger(),
                           a = new MutableBigInteger(this.mag),
@@ -2305,22 +2426,24 @@
      * @return {@code this % val}
      * @throws ArithmeticException if {@code val} is zero.
      */
-    @NonNull public BigInteger remainder(@NonNull BigInteger val) {
-        // BEGIN Android-modified: Fall back to boringssl for large problems.
-        // if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD ||
-        //        mag.length - val.mag.length < BURNIKEL_ZIEGLER_OFFSET) {
+    public BigInteger remainder(BigInteger val) {
+        // BEGIN Android-changed: Fall back to boringssl for large problems.
+        /*
+        if (val.mag.length < BURNIKEL_ZIEGLER_THRESHOLD ||
+               mag.length - val.mag.length < BURNIKEL_ZIEGLER_OFFSET) {
+         */
         if (val.mag.length < BORINGSSL_DIV_THRESHOLD ||
                 mag.length - val.mag.length < BORINGSSL_DIV_THRESHOLD) {
             return remainderKnuth(val);
         } else {
-            return divideAndRemainder(val)[1];
             // return remainderBurnikelZiegler(val);
+            return divideAndRemainder(val)[1];
         }
-        // END Android-modified: Fall back to boringssl for large problems.
+        // END Android-changed: Fall back to boringssl for large problems.
     }
 
     /** Long division */
-    @NonNull private BigInteger remainderKnuth(@NonNull BigInteger val) {
+    private BigInteger remainderKnuth(BigInteger val) {
         MutableBigInteger q = new MutableBigInteger(),
                           a = new MutableBigInteger(this.mag),
                           b = new MutableBigInteger(val.mag);
@@ -2333,7 +2456,7 @@
      * @param  val the divisor
      * @return {@code this / val}
      */
-    @NonNull private BigInteger divideBurnikelZiegler(@NonNull BigInteger val) {
+    private BigInteger divideBurnikelZiegler(BigInteger val) {
         return divideAndRemainderBurnikelZiegler(val)[0];
     }
 
@@ -2342,7 +2465,7 @@
      * @param val the divisor
      * @return {@code this % val}
      */
-    @NonNull private BigInteger remainderBurnikelZiegler(@NonNull BigInteger val) {
+    private BigInteger remainderBurnikelZiegler(BigInteger val) {
         return divideAndRemainderBurnikelZiegler(val)[1];
     }
 
@@ -2352,7 +2475,7 @@
      * @param val the divisor
      * @return an array containing the quotient and remainder
      */
-    @NonNull private BigInteger[] divideAndRemainderBurnikelZiegler(@NonNull BigInteger val) {
+    private BigInteger[] divideAndRemainderBurnikelZiegler(BigInteger val) {
         MutableBigInteger q = new MutableBigInteger();
         MutableBigInteger r = new MutableBigInteger(this).divideAndRemainderBurnikelZiegler(new MutableBigInteger(val), q);
         BigInteger qBigInt = q.isZero() ? ZERO : q.toBigInteger(signum*val.signum);
@@ -2361,15 +2484,15 @@
     }
 
     /**
-     * Returns a BigInteger whose value is <tt>(this<sup>exponent</sup>)</tt>.
+     * Returns a BigInteger whose value is <code>(this<sup>exponent</sup>)</code>.
      * Note that {@code exponent} is an integer rather than a BigInteger.
      *
      * @param  exponent exponent to which this BigInteger is to be raised.
-     * @return <tt>this<sup>exponent</sup></tt>
+     * @return <code>this<sup>exponent</sup></code>
      * @throws ArithmeticException {@code exponent} is negative.  (This would
      *         cause the operation to yield a non-integer value.)
      */
-    @NonNull public BigInteger pow(int exponent) {
+    public BigInteger pow(int exponent) {
         if (exponent < 0) {
             throw new ArithmeticException("Negative exponent");
         }
@@ -2486,6 +2609,53 @@
     }
 
     /**
+     * Returns the integer square root of this BigInteger.  The integer square
+     * root of the corresponding mathematical integer {@code n} is the largest
+     * mathematical integer {@code s} such that {@code s*s <= n}.  It is equal
+     * to the value of {@code floor(sqrt(n))}, where {@code sqrt(n)} denotes the
+     * real square root of {@code n} treated as a real.  Note that the integer
+     * square root will be less than the real square root if the latter is not
+     * representable as an integral value.
+     *
+     * @return the integer square root of {@code this}
+     * @throws ArithmeticException if {@code this} is negative.  (The square
+     *         root of a negative integer {@code val} is
+     *         {@code (i * sqrt(-val))} where <i>i</i> is the
+     *         <i>imaginary unit</i> and is equal to
+     *         {@code sqrt(-1)}.)
+     * @since  9
+     */
+    public BigInteger sqrt() {
+        if (this.signum < 0) {
+            throw new ArithmeticException("Negative BigInteger");
+        }
+
+        return new MutableBigInteger(this.mag).sqrt().toBigInteger();
+    }
+
+    /**
+     * Returns an array of two BigIntegers containing the integer square root
+     * {@code s} of {@code this} and its remainder {@code this - s*s},
+     * respectively.
+     *
+     * @return an array of two BigIntegers with the integer square root at
+     *         offset 0 and the remainder at offset 1
+     * @throws ArithmeticException if {@code this} is negative.  (The square
+     *         root of a negative integer {@code val} is
+     *         {@code (i * sqrt(-val))} where <i>i</i> is the
+     *         <i>imaginary unit</i> and is equal to
+     *         {@code sqrt(-1)}.)
+     * @see #sqrt()
+     * @since  9
+     */
+    public BigInteger[] sqrtAndRemainder() {
+        BigInteger s = sqrt();
+        BigInteger r = this.subtract(s.square());
+        assert r.compareTo(BigInteger.ZERO) >= 0;
+        return new BigInteger[] {s, r};
+    }
+
+    /**
      * Returns a BigInteger whose value is the greatest common divisor of
      * {@code abs(this)} and {@code abs(val)}.  Returns 0 if
      * {@code this == 0 && val == 0}.
@@ -2493,7 +2663,7 @@
      * @param  val value with which the GCD is to be computed.
      * @return {@code GCD(abs(this), abs(val))}
      */
-    @NonNull public BigInteger gcd(@NonNull BigInteger val) {
+    public BigInteger gcd(BigInteger val) {
         if (val.signum == 0)
             return this.abs();
         else if (this.signum == 0)
@@ -2583,7 +2753,7 @@
      *
      * @return {@code abs(this)}
      */
-    @NonNull public BigInteger abs() {
+    public BigInteger abs() {
         return (signum >= 0 ? this : this.negate());
     }
 
@@ -2592,7 +2762,7 @@
      *
      * @return {@code -this}
      */
-    @NonNull public BigInteger negate() {
+    public BigInteger negate() {
         return new BigInteger(this.mag, -this.signum);
     }
 
@@ -2618,7 +2788,7 @@
      * @throws ArithmeticException {@code m} &le; 0
      * @see    #remainder
      */
-    @NonNull public BigInteger mod(@NonNull BigInteger m) {
+    public BigInteger mod(BigInteger m) {
         if (m.signum <= 0)
             throw new ArithmeticException("BigInteger: modulus not positive");
 
@@ -2657,18 +2827,18 @@
 
     /**
      * Returns a BigInteger whose value is
-     * <tt>(this<sup>exponent</sup> mod m)</tt>.  (Unlike {@code pow}, this
+     * <code>(this<sup>exponent</sup> mod m)</code>.  (Unlike {@code pow}, this
      * method permits negative exponents.)
      *
      * @param  exponent the exponent.
      * @param  m the modulus.
-     * @return <tt>this<sup>exponent</sup> mod m</tt>
+     * @return <code>this<sup>exponent</sup> mod m</code>
      * @throws ArithmeticException {@code m} &le; 0 or the exponent is
      *         negative and this BigInteger is not <i>relatively
      *         prime</i> to {@code m}.
      * @see    #modInverse
      */
-    @NonNull public BigInteger modPow(@NonNull BigInteger exponent, @NonNull BigInteger m) {
+    public BigInteger modPow(BigInteger exponent, BigInteger m) {
         if (m.signum <= 0)
             throw new ArithmeticException("BigInteger: modulus not positive");
 
@@ -2816,13 +2986,15 @@
          return z;
     }
 
-    // These methods are intended to be be replaced by virtual machine
+    // These methods are intended to be replaced by virtual machine
     // intrinsics.
+    @HotSpotIntrinsicCandidate
     private static int[] implMontgomeryMultiply(int[] a, int[] b, int[] n, int len,
                                          long inv, int[] product) {
         product = multiplyToLen(a, len, b, len, product);
         return montReduce(product, n, len, (int)inv);
     }
+    @HotSpotIntrinsicCandidate
     private static int[] implMontgomerySquare(int[] a, int[] n, int len,
                                        long inv, int[] product) {
         product = squareToLen(a, len, product);
@@ -2836,7 +3008,7 @@
      * Returns a BigInteger whose value is x to the power of y mod z.
      * Assumes: z is odd && x < z.
      */
-    @NonNull private BigInteger oddModPow(@NonNull BigInteger y, @NonNull BigInteger z) {
+    private BigInteger oddModPow(BigInteger y, BigInteger z) {
     /*
      * The algorithm is adapted from Colin Plumb's C library.
      *
@@ -3154,6 +3326,7 @@
     /**
      * Java Runtime may use intrinsic for this method.
      */
+    @HotSpotIntrinsicCandidate
     private static int implMulAdd(int[] out, int[] in, int offset, int len, int k) {
         long kLong = k & LONG_MASK;
         long carry = 0;
@@ -3194,7 +3367,7 @@
     /**
      * Returns a BigInteger whose value is (this ** exponent) mod (2**p)
      */
-    @NonNull private BigInteger modPow2(@NonNull BigInteger exponent, int p) {
+    private BigInteger modPow2(BigInteger exponent, int p) {
         /*
          * Perform exponentiation using repeated squaring trick, chopping off
          * high order bits as indicated by modulus.
@@ -3223,7 +3396,7 @@
      * Returns a BigInteger whose value is this mod(2**p).
      * Assumes that this {@code BigInteger >= 0} and {@code p > 0}.
      */
-    @NonNull private BigInteger mod2(int p) {
+    private BigInteger mod2(int p) {
         if (bitLength() <= p)
             return this;
 
@@ -3248,7 +3421,7 @@
      *         has no multiplicative inverse mod m (that is, this BigInteger
      *         is not <i>relatively prime</i> to m).
      */
-    @NonNull public BigInteger modInverse(@NonNull BigInteger m) {
+    public BigInteger modInverse(BigInteger m) {
         if (m.signum != 1)
             throw new ArithmeticException("BigInteger: modulus not positive");
 
@@ -3276,13 +3449,13 @@
      * Returns a BigInteger whose value is {@code (this << n)}.
      * The shift distance, {@code n}, may be negative, in which case
      * this method performs a right shift.
-     * (Computes <tt>floor(this * 2<sup>n</sup>)</tt>.)
+     * (Computes <code>floor(this * 2<sup>n</sup>)</code>.)
      *
      * @param  n shift distance, in bits.
      * @return {@code this << n}
      * @see #shiftRight
      */
-    @NonNull public BigInteger shiftLeft(int n) {
+    public BigInteger shiftLeft(int n) {
         if (signum == 0)
             return ZERO;
         if (n > 0) {
@@ -3299,7 +3472,7 @@
     /**
      * Returns a magnitude array whose value is {@code (mag << n)}.
      * The shift distance, {@code n}, is considered unnsigned.
-     * (Computes <tt>this * 2<sup>n</sup></tt>.)
+     * (Computes <code>this * 2<sup>n</sup></code>.)
      *
      * @param mag magnitude, the most-significant int ({@code mag[0]}) must be non-zero.
      * @param  n unsigned shift distance, in bits.
@@ -3336,13 +3509,13 @@
      * Returns a BigInteger whose value is {@code (this >> n)}.  Sign
      * extension is performed.  The shift distance, {@code n}, may be
      * negative, in which case this method performs a left shift.
-     * (Computes <tt>floor(this / 2<sup>n</sup>)</tt>.)
+     * (Computes <code>floor(this / 2<sup>n</sup>)</code>.)
      *
      * @param  n shift distance, in bits.
      * @return {@code this >> n}
      * @see #shiftLeft
      */
-    @NonNull public BigInteger shiftRight(int n) {
+    public BigInteger shiftRight(int n) {
         if (signum == 0)
             return ZERO;
         if (n > 0) {
@@ -3359,12 +3532,12 @@
     /**
      * Returns a BigInteger whose value is {@code (this >> n)}. The shift
      * distance, {@code n}, is considered unsigned.
-     * (Computes <tt>floor(this * 2<sup>-n</sup>)</tt>.)
+     * (Computes <code>floor(this * 2<sup>-n</sup>)</code>.)
      *
      * @param  n unsigned shift distance, in bits.
      * @return {@code this >> n}
      */
-    @NonNull private BigInteger shiftRightImpl(int n) {
+    private BigInteger shiftRightImpl(int n) {
         int nInts = n >>> 5;
         int nBits = n & 0x1f;
         int magLen = mag.length;
@@ -3429,7 +3602,7 @@
      * @param val value to be AND'ed with this BigInteger.
      * @return {@code this & val}
      */
-    @NonNull public BigInteger and(@NonNull BigInteger val) {
+    public BigInteger and(BigInteger val) {
         int[] result = new int[Math.max(intLength(), val.intLength())];
         for (int i=0; i < result.length; i++)
             result[i] = (getInt(result.length-i-1)
@@ -3446,7 +3619,7 @@
      * @param val value to be OR'ed with this BigInteger.
      * @return {@code this | val}
      */
-    @NonNull public BigInteger or(@NonNull BigInteger val) {
+    public BigInteger or(BigInteger val) {
         int[] result = new int[Math.max(intLength(), val.intLength())];
         for (int i=0; i < result.length; i++)
             result[i] = (getInt(result.length-i-1)
@@ -3463,7 +3636,7 @@
      * @param val value to be XOR'ed with this BigInteger.
      * @return {@code this ^ val}
      */
-    @NonNull public BigInteger xor(@NonNull BigInteger val) {
+    public BigInteger xor(BigInteger val) {
         int[] result = new int[Math.max(intLength(), val.intLength())];
         for (int i=0; i < result.length; i++)
             result[i] = (getInt(result.length-i-1)
@@ -3479,7 +3652,7 @@
      *
      * @return {@code ~this}
      */
-    @NonNull public BigInteger not() {
+    public BigInteger not() {
         int[] result = new int[intLength()];
         for (int i=0; i < result.length; i++)
             result[i] = ~getInt(result.length-i-1);
@@ -3497,7 +3670,7 @@
      * @param val value to be complemented and AND'ed with this BigInteger.
      * @return {@code this & ~val}
      */
-    @NonNull public BigInteger andNot(@NonNull BigInteger val) {
+    public BigInteger andNot(BigInteger val) {
         int[] result = new int[Math.max(intLength(), val.intLength())];
         for (int i=0; i < result.length; i++)
             result[i] = (getInt(result.length-i-1)
@@ -3532,7 +3705,7 @@
      * @return {@code this | (1<<n)}
      * @throws ArithmeticException {@code n} is negative.
      */
-    @NonNull public BigInteger setBit(int n) {
+    public BigInteger setBit(int n) {
         if (n < 0)
             throw new ArithmeticException("Negative bit address");
 
@@ -3556,7 +3729,7 @@
      * @return {@code this & ~(1<<n)}
      * @throws ArithmeticException {@code n} is negative.
      */
-    @NonNull public BigInteger clearBit(int n) {
+    public BigInteger clearBit(int n) {
         if (n < 0)
             throw new ArithmeticException("Negative bit address");
 
@@ -3580,7 +3753,7 @@
      * @return {@code this ^ (1<<n)}
      * @throws ArithmeticException {@code n} is negative.
      */
-    @NonNull public BigInteger flipBit(int n) {
+    public BigInteger flipBit(int n) {
         if (n < 0)
             throw new ArithmeticException("Negative bit address");
 
@@ -3604,7 +3777,7 @@
      * @return index of the rightmost one bit in this BigInteger.
      */
     public int getLowestSetBit() {
-        @SuppressWarnings("deprecation") int lsb = lowestSetBit - 2;
+        int lsb = lowestSetBitPlusTwo - 2;
         if (lsb == -2) {  // lowestSetBit not initialized yet
             lsb = 0;
             if (signum == 0) {
@@ -3616,7 +3789,7 @@
                     ;
                 lsb += (i << 5) + Integer.numberOfTrailingZeros(b);
             }
-            lowestSetBit = lsb + 2;
+            lowestSetBitPlusTwo = lsb + 2;
         }
         return lsb;
     }
@@ -3626,16 +3799,16 @@
 
     /**
      * Returns the number of bits in the minimal two's-complement
-     * representation of this BigInteger, <i>excluding</i> a sign bit.
+     * representation of this BigInteger, <em>excluding</em> a sign bit.
      * For positive BigIntegers, this is equivalent to the number of bits in
-     * the ordinary binary representation.  (Computes
-     * {@code (ceil(log2(this < 0 ? -this : this+1)))}.)
+     * the ordinary binary representation.  For zero this method returns
+     * {@code 0}.  (Computes {@code (ceil(log2(this < 0 ? -this : this+1)))}.)
      *
      * @return number of bits in the minimal two's-complement
-     *         representation of this BigInteger, <i>excluding</i> a sign bit.
+     *         representation of this BigInteger, <em>excluding</em> a sign bit.
      */
     public int bitLength() {
-        @SuppressWarnings("deprecation") int n = bitLength - 1;
+        int n = bitLengthPlusOne - 1;
         if (n == -1) { // bitLength not initialized yet
             int[] m = mag;
             int len = m.length;
@@ -3655,7 +3828,7 @@
                      n = magBitLength;
                  }
             }
-            bitLength = n + 1;
+            bitLengthPlusOne = n + 1;
         }
         return n;
     }
@@ -3669,7 +3842,7 @@
      *         of this BigInteger that differ from its sign bit.
      */
     public int bitCount() {
-        @SuppressWarnings("deprecation") int bc = bitCount - 1;
+        int bc = bitCountPlusOne - 1;
         if (bc == -1) {  // bitCount not initialized yet
             bc = 0;      // offset by one to initialize
             // Count the bits in the magnitude
@@ -3683,7 +3856,7 @@
                 magTrailingZeroCount += Integer.numberOfTrailingZeros(mag[j]);
                 bc += magTrailingZeroCount - 1;
             }
-            bitCount = bc + 1;
+            bitCountPlusOne = bc + 1;
         }
         return bc;
     }
@@ -3731,7 +3904,7 @@
      * @return -1, 0 or 1 as this BigInteger is numerically less than, equal
      *         to, or greater than {@code val}.
      */
-    public int compareTo(@NonNull BigInteger val) {
+    public int compareTo(BigInteger val) {
         if (signum == val.signum) {
             switch (signum) {
             case 1:
@@ -3753,7 +3926,7 @@
      * @return -1, 0 or 1 as this magnitude array is less than, equal to or
      *         greater than the magnitude aray for the specified BigInteger's.
      */
-    final int compareMagnitude(@NonNull BigInteger val) {
+    final int compareMagnitude(BigInteger val) {
         int[] m1 = mag;
         int len1 = m1.length;
         int[] m2 = val.mag;
@@ -3821,7 +3994,7 @@
      * @return {@code true} if and only if the specified Object is a
      *         BigInteger whose value is numerically equal to this BigInteger.
      */
-    public boolean equals(@NonNull Object x) {
+    public boolean equals(Object x) {
         // This test is just an optimization, which may or may not help
         if (x == this)
             return true;
@@ -3853,7 +4026,7 @@
      * @return the BigInteger whose value is the lesser of this BigInteger and
      *         {@code val}.  If they are equal, either may be returned.
      */
-    @NonNull public BigInteger min(@NonNull BigInteger val) {
+    public BigInteger min(BigInteger val) {
         return (compareTo(val) < 0 ? this : val);
     }
 
@@ -3864,7 +4037,7 @@
      * @return the BigInteger whose value is the greater of this and
      *         {@code val}.  If they are equal, either may be returned.
      */
-    @NonNull public BigInteger max(@NonNull BigInteger val) {
+    public BigInteger max(BigInteger val) {
         return (compareTo(val) > 0 ? this : val);
     }
 
@@ -3902,7 +4075,7 @@
      * @see    Character#forDigit
      * @see    #BigInteger(java.lang.String, int)
      */
-    @NonNull public String toString(int radix) {
+    public String toString(int radix) {
         if (signum == 0)
             return "0";
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
@@ -3926,7 +4099,7 @@
     }
 
     /** This method is used to perform toString when arguments are small. */
-    @NonNull private String smallToString(int radix) {
+    private String smallToString(int radix) {
         if (signum == 0) {
             return "0";
         }
@@ -3975,7 +4148,7 @@
      * Converts the specified BigInteger to a string and appends to
      * {@code sb}.  This implements the recursive Schoenhage algorithm
      * for base conversions.
-     * <p/>
+     * <p>
      * See Knuth, Donald,  _The Art of Computer Programming_, Vol. 2,
      * Answers to Exercises (4.4) Question 14.
      *
@@ -3984,18 +4157,18 @@
      * @param radix  The base to convert to.
      * @param digits The minimum number of digits to pad to.
      */
-    private static void toString(@NonNull BigInteger u, StringBuilder sb, int radix,
+    private static void toString(BigInteger u, StringBuilder sb, int radix,
                                  int digits) {
-        /* If we're smaller than a certain threshold, use the smallToString
-           method, padding with leading zeroes when necessary. */
+        // If we're smaller than a certain threshold, use the smallToString
+        // method, padding with leading zeroes when necessary.
         if (u.mag.length <= SCHOENHAGE_BASE_CONVERSION_THRESHOLD) {
             String s = u.smallToString(radix);
 
             // Pad with internal zeros if necessary.
             // Don't pad if we're at the beginning of the string.
             if ((s.length() < digits) && (sb.length() > 0)) {
-                for (int i=s.length(); i < digits; i++) { // May be a faster way to
-                    sb.append('0');                    // do this?
+                for (int i=s.length(); i < digits; i++) {
+                    sb.append('0');
                 }
             }
 
@@ -4024,11 +4197,11 @@
     /**
      * Returns the value radix^(2^exponent) from the cache.
      * If this value doesn't already exist in the cache, it is added.
-     * <p/>
+     * <p>
      * This could be changed to a more complicated caching method using
      * {@code Future}.
      */
-    @NonNull private static BigInteger getRadixConversionCache(int radix, int exponent) {
+    private static BigInteger getRadixConversionCache(int radix, int exponent) {
         BigInteger[] cacheLine = powerCache[radix]; // volatile read
         if (exponent < cacheLine.length) {
             return cacheLine[exponent];
@@ -4070,7 +4243,7 @@
      * @see    Character#forDigit
      * @see    #BigInteger(java.lang.String)
      */
-    @NonNull public String toString() {
+    public String toString() {
         return toString(10);
     }
 
@@ -4109,7 +4282,7 @@
      * Converts this BigInteger to an {@code int}.  This
      * conversion is analogous to a
      * <i>narrowing primitive conversion</i> from {@code long} to
-     * {@code int} as defined in section 5.1.3 of
+     * {@code int} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger is too big to fit in an
      * {@code int}, only the low-order 32 bits are returned.
@@ -4119,6 +4292,7 @@
      *
      * @return this BigInteger converted to an {@code int}.
      * @see #intValueExact()
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public int intValue() {
         int result = 0;
@@ -4130,7 +4304,7 @@
      * Converts this BigInteger to a {@code long}.  This
      * conversion is analogous to a
      * <i>narrowing primitive conversion</i> from {@code long} to
-     * {@code int} as defined in section 5.1.3 of
+     * {@code int} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger is too big to fit in a
      * {@code long}, only the low-order 64 bits are returned.
@@ -4140,6 +4314,7 @@
      *
      * @return this BigInteger converted to a {@code long}.
      * @see #longValueExact()
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public long longValue() {
         long result = 0;
@@ -4153,7 +4328,7 @@
      * Converts this BigInteger to a {@code float}.  This
      * conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger has too great a magnitude
      * to represent as a {@code float}, it will be converted to
@@ -4163,6 +4338,7 @@
      * information about the precision of the BigInteger value.
      *
      * @return this BigInteger converted to a {@code float}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public float floatValue() {
         if (signum == 0) {
@@ -4237,7 +4413,7 @@
      * Converts this BigInteger to a {@code double}.  This
      * conversion is similar to the
      * <i>narrowing primitive conversion</i> from {@code double} to
-     * {@code float} as defined in section 5.1.3 of
+     * {@code float} as defined in
      * <cite>The Java&trade; Language Specification</cite>:
      * if this BigInteger has too great a magnitude
      * to represent as a {@code double}, it will be converted to
@@ -4247,6 +4423,7 @@
      * information about the precision of the BigInteger value.
      *
      * @return this BigInteger converted to a {@code double}.
+     * @jls 5.1.3 Narrowing Primitive Conversion
      */
     public double doubleValue() {
         if (signum == 0) {
@@ -4355,18 +4532,18 @@
     /**
      * Returns a copy of the input array stripped of any leading zero bytes.
      */
-    private static int[] stripLeadingZeroBytes(byte a[]) {
-        int byteLength = a.length;
+    private static int[] stripLeadingZeroBytes(byte a[], int off, int len) {
+        int indexBound = off + len;
         int keep;
 
         // Find first nonzero byte
-        for (keep = 0; keep < byteLength && a[keep] == 0; keep++)
+        for (keep = off; keep < indexBound && a[keep] == 0; keep++)
             ;
 
         // Allocate new array and copy relevant part of input array
-        int intLength = ((byteLength - keep) + 3) >>> 2;
+        int intLength = ((indexBound - keep) + 3) >>> 2;
         int[] result = new int[intLength];
-        int b = byteLength - 1;
+        int b = indexBound - 1;
         for (int i = intLength-1; i >= 0; i--) {
             result[i] = a[b--] & 0xff;
             int bytesRemaining = b - keep + 1;
@@ -4381,27 +4558,27 @@
      * Takes an array a representing a negative 2's-complement number and
      * returns the minimal (no leading zero bytes) unsigned whose value is -a.
      */
-    private static int[] makePositive(byte a[]) {
+    private static int[] makePositive(byte a[], int off, int len) {
         int keep, k;
-        int byteLength = a.length;
+        int indexBound = off + len;
 
         // Find first non-sign (0xff) byte of input
-        for (keep=0; keep < byteLength && a[keep] == -1; keep++)
+        for (keep=off; keep < indexBound && a[keep] == -1; keep++)
             ;
 
 
         /* Allocate output array.  If all non-sign bytes are 0x00, we must
          * allocate space for one extra output byte. */
-        for (k=keep; k < byteLength && a[k] == 0; k++)
+        for (k=keep; k < indexBound && a[k] == 0; k++)
             ;
 
-        int extraByte = (k == byteLength) ? 1 : 0;
-        int intLength = ((byteLength - keep + extraByte) + 3) >>> 2;
+        int extraByte = (k == indexBound) ? 1 : 0;
+        int intLength = ((indexBound - keep + extraByte) + 3) >>> 2;
         int result[] = new int[intLength];
 
         /* Copy one's complement of input into output, leaving extra
          * byte (if it exists) == 0x00 */
-        int b = byteLength - 1;
+        int b = indexBound - 1;
         for (int i = intLength-1; i >= 0; i--) {
             result[i] = a[b--] & 0xff;
             int numBytesToTransfer = Math.min(3, b-keep+1);
@@ -4549,22 +4726,23 @@
     }
 
     /**
-     * Returns the index of the int that contains the first nonzero int in the
-     * little-endian binary representation of the magnitude (int 0 is the
-     * least significant). If the magnitude is zero, return value is undefined.
-     */
+    * Returns the index of the int that contains the first nonzero int in the
+    * little-endian binary representation of the magnitude (int 0 is the
+    * least significant). If the magnitude is zero, return value is undefined.
+    *
+    * <p>Note: never used for a BigInteger with a magnitude of zero.
+    * @see #getInt.
+    */
     private int firstNonzeroIntNum() {
-        int fn = firstNonzeroIntNum - 2;
+        int fn = firstNonzeroIntNumPlusTwo - 2;
         if (fn == -2) { // firstNonzeroIntNum not initialized yet
-            fn = 0;
-
             // Search for the first nonzero int
             int i;
             int mlen = mag.length;
             for (i = mlen - 1; i >= 0 && mag[i] == 0; i--)
                 ;
             fn = mlen - i - 1;
-            firstNonzeroIntNum = fn + 2; // offset by two to initialize
+            firstNonzeroIntNumPlusTwo = fn + 2; // offset by two to initialize
         }
         return fn;
     }
@@ -4576,16 +4754,17 @@
      * Serializable fields for BigInteger.
      *
      * @serialField signum  int
-     *              signum of this BigInteger.
-     * @serialField magnitude int[]
-     *              magnitude array of this BigInteger.
+     *              signum of this BigInteger
+     * @serialField magnitude byte[]
+     *              magnitude array of this BigInteger
      * @serialField bitCount  int
-     *              number of bits in this BigInteger
+     *              appears in the serialized form for backward compatibility
      * @serialField bitLength int
-     *              the number of bits in the minimal two's-complement
-     *              representation of this BigInteger
+     *              appears in the serialized form for backward compatibility
+     * @serialField firstNonzeroByteNum int
+     *              appears in the serialized form for backward compatibility
      * @serialField lowestSetBit int
-     *              lowest set bit in the twos complement representation
+     *              appears in the serialized form for backward compatibility
      */
     private static final ObjectStreamField[] serialPersistentFields = {
         new ObjectStreamField("signum", Integer.TYPE),
@@ -4602,22 +4781,14 @@
      * for historical reasons, but it is converted to an array of ints
      * and the byte array is discarded.
      * Note:
-     * The current convention is to initialize the cache fields, bitCount,
-     * bitLength and lowestSetBit, to 0 rather than some other marker value.
-     * Therefore, no explicit action to set these fields needs to be taken in
-     * readObject because those fields already have a 0 value be default since
-     * defaultReadObject is not being used.
+     * The current convention is to initialize the cache fields, bitCountPlusOne,
+     * bitLengthPlusOne and lowestSetBitPlusTwo, to 0 rather than some other
+     * marker value. Therefore, no explicit action to set these fields needs to
+     * be taken in readObject because those fields already have a 0 value by
+     * default since defaultReadObject is not being used.
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
-        /*
-         * In order to maintain compatibility with previous serialized forms,
-         * the magnitude of a BigInteger is serialized as an array of bytes.
-         * The magnitude field is used as a temporary store for the byte array
-         * that is deserialized. The cached computation fields should be
-         * transient but are serialized for compatibility reasons.
-         */
-
         // prepare to read the alternate persistent fields
         ObjectInputStream.GetField fields = s.readFields();
 
@@ -4632,7 +4803,7 @@
                 message = "BigInteger: Signum not present in stream";
             throw new java.io.StreamCorruptedException(message);
         }
-        int[] mag = stripLeadingZeroBytes(magnitude);
+        int[] mag = stripLeadingZeroBytes(magnitude, 0, magnitude.length);
         if ((mag.length == 0) != (sign == 0)) {
             String message = "BigInteger: signum-magnitude mismatch";
             if (fields.defaulted("magnitude"))
@@ -4681,12 +4852,14 @@
     }
 
     /**
-     * Save the {@code BigInteger} instance to a stream.
-     * The magnitude of a BigInteger is serialized as a byte array for
-     * historical reasons.
-     *
-     * @serialData two necessary fields are written as well as obsolete
-     *             fields for compatibility with older versions.
+     * Save the {@code BigInteger} instance to a stream.  The magnitude of a
+     * {@code BigInteger} is serialized as a byte array for historical reasons.
+     * To maintain compatibility with older implementations, the integers
+     * -1, -1, -2, and -2 are written as the values of the obsolete fields
+     * {@code bitCount}, {@code bitLength}, {@code lowestSetBit}, and
+     * {@code firstNonzeroByteNum}, respectively.  These values are compatible
+     * with older implementations, but will be ignored by current
+     * implementations.
      */
     private void writeObject(ObjectOutputStream s) throws IOException {
         // set the values of the Serializable fields
@@ -4696,15 +4869,17 @@
         // The values written for cached fields are compatible with older
         // versions, but are ignored in readObject so don't otherwise matter.
         // BEGIN Android-changed: Don't include the following fields.
-        // fields.put("bitCount", -1);
-        // fields.put("bitLength", -1);
-        // fields.put("lowestSetBit", -2);
-        // fields.put("firstNonzeroByteNum", -2);
-        // END Android-changed
+        /*
+        fields.put("bitCount", -1);
+        fields.put("bitLength", -1);
+        fields.put("lowestSetBit", -2);
+        fields.put("firstNonzeroByteNum", -2);
+        */
+        // END Android-changed: Don't include the following fields.
 
         // save them
         s.writeFields();
-}
+    }
 
     /**
      * Returns the mag array as an array of bytes.
@@ -4757,7 +4932,7 @@
      *
      * @return this {@code BigInteger} converted to an {@code int}.
      * @throws ArithmeticException if the value of {@code this} will
-     * not exactly fit in a {@code int}.
+     * not exactly fit in an {@code int}.
      * @see BigInteger#intValue
      * @since  1.8
      */
diff --git a/ojluni/src/main/java/java/math/MathContext.java b/ojluni/src/main/java/java/math/MathContext.java
index f9947d3..e0b2dca 100644
--- a/ojluni/src/main/java/java/math/MathContext.java
+++ b/ojluni/src/main/java/java/math/MathContext.java
@@ -268,7 +268,7 @@
      * Returns the string representation of this {@code MathContext}.
      * The {@code String} returned represents the settings of the
      * {@code MathContext} object as two space-delimited words
-     * (separated by a single space character, <tt>'&#92;u0020'</tt>,
+     * (separated by a single space character, <code>'&#92;u0020'</code>,
      * and with no leading or trailing white space), as follows:
      * <ol>
      * <li>
diff --git a/ojluni/src/main/java/java/math/MutableBigInteger.java b/ojluni/src/main/java/java/math/MutableBigInteger.java
index b9cb0fb..f95ea9c 100644
--- a/ojluni/src/main/java/java/math/MutableBigInteger.java
+++ b/ojluni/src/main/java/java/math/MutableBigInteger.java
@@ -254,7 +254,7 @@
     /**
      * Compare the magnitude of two MutableBigIntegers. Returns -1, 0 or 1
      * as this MutableBigInteger is numerically less than, equal to, or
-     * greater than <tt>b</tt>.
+     * greater than {@code b}.
      */
     final int compare(MutableBigInteger b) {
         int blen = b.intLen;
@@ -1867,6 +1867,96 @@
     }
 
     /**
+     * Calculate the integer square root {@code floor(sqrt(this))} where
+     * {@code sqrt(.)} denotes the mathematical square root. The contents of
+     * {@code this} are <b>not</b> changed. The value of {@code this} is assumed
+     * to be non-negative.
+     *
+     * @implNote The implementation is based on the material in Henry S. Warren,
+     * Jr., <i>Hacker's Delight (2nd ed.)</i> (Addison Wesley, 2013), 279-282.
+     *
+     * @throws ArithmeticException if the value returned by {@code bitLength()}
+     * overflows the range of {@code int}.
+     * @return the integer square root of {@code this}
+     * @since 9
+     */
+    MutableBigInteger sqrt() {
+        // Special cases.
+        if (this.isZero()) {
+            return new MutableBigInteger(0);
+        } else if (this.value.length == 1
+                && (this.value[0] & LONG_MASK) < 4) { // result is unity
+            return ONE;
+        }
+
+        if (bitLength() <= 63) {
+            // Initial estimate is the square root of the positive long value.
+            long v = new BigInteger(this.value, 1).longValueExact();
+            long xk = (long)Math.floor(Math.sqrt(v));
+
+            // Refine the estimate.
+            do {
+                long xk1 = (xk + v/xk)/2;
+
+                // Terminate when non-decreasing.
+                if (xk1 >= xk) {
+                    return new MutableBigInteger(new int[] {
+                        (int)(xk >>> 32), (int)(xk & LONG_MASK)
+                    });
+                }
+
+                xk = xk1;
+            } while (true);
+        } else {
+            // Set up the initial estimate of the iteration.
+
+            // Obtain the bitLength > 63.
+            int bitLength = (int) this.bitLength();
+            if (bitLength != this.bitLength()) {
+                throw new ArithmeticException("bitLength() integer overflow");
+            }
+
+            // Determine an even valued right shift into positive long range.
+            int shift = bitLength - 63;
+            if (shift % 2 == 1) {
+                shift++;
+            }
+
+            // Shift the value into positive long range.
+            MutableBigInteger xk = new MutableBigInteger(this);
+            xk.rightShift(shift);
+            xk.normalize();
+
+            // Use the square root of the shifted value as an approximation.
+            double d = new BigInteger(xk.value, 1).doubleValue();
+            BigInteger bi = BigInteger.valueOf((long)Math.ceil(Math.sqrt(d)));
+            xk = new MutableBigInteger(bi.mag);
+
+            // Shift the approximate square root back into the original range.
+            xk.leftShift(shift / 2);
+
+            // Refine the estimate.
+            MutableBigInteger xk1 = new MutableBigInteger();
+            do {
+                // xk1 = (xk + n/xk)/2
+                this.divide(xk, xk1, false);
+                xk1.add(xk);
+                xk1.rightShift(1);
+
+                // Terminate when non-decreasing.
+                if (xk1.compare(xk) >= 0) {
+                    return xk;
+                }
+
+                // xk = xk1
+                xk.copyValue(xk1);
+
+                xk1.reset();
+            } while (true);
+        }
+    }
+
+    /**
      * Calculate GCD of this and b. This and b are changed by the computation.
      */
     MutableBigInteger hybridGCD(MutableBigInteger b) {
diff --git a/ojluni/src/main/java/java/math/RoundingMode.java b/ojluni/src/main/java/java/math/RoundingMode.java
index 3a4fe97..b4c37f6 100644
--- a/ojluni/src/main/java/java/math/RoundingMode.java
+++ b/ojluni/src/main/java/java/math/RoundingMode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,12 +51,13 @@
  * proper {@code MathContext}.  A summary table showing the results
  * of these rounding operations for all rounding modes appears below.
  *
- *<table border>
+ *<table class="striped">
  * <caption><b>Summary of Rounding Operations Under Different Rounding Modes</b></caption>
- * <tr><th></th><th colspan=8>Result of rounding input to one digit with the given
+ * <thead>
+ * <tr><th scope="col" rowspan="2">Input Number</th><th scope="col"colspan=8>Result of rounding input to one digit with the given
  *                           rounding mode</th>
- * <tr valign=top>
- * <th>Input Number</th>         <th>{@code UP}</th>
+ * <tr style="vertical-align:top">
+ *                               <th>{@code UP}</th>
  *                                           <th>{@code DOWN}</th>
  *                                                        <th>{@code CEILING}</th>
  *                                                                       <th>{@code FLOOR}</th>
@@ -64,18 +65,21 @@
  *                                                                                                   <th>{@code HALF_DOWN}</th>
  *                                                                                                                    <th>{@code HALF_EVEN}</th>
  *                                                                                                                                     <th>{@code UNNECESSARY}</th>
+ * </thead>
+ * <tbody style="text-align:right">
  *
- * <tr align=right><td>5.5</td>  <td>6</td>  <td>5</td>    <td>6</td>    <td>5</td>  <td>6</td>      <td>5</td>       <td>6</td>       <td>throw {@code ArithmeticException}</td>
- * <tr align=right><td>2.5</td>  <td>3</td>  <td>2</td>    <td>3</td>    <td>2</td>  <td>3</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
- * <tr align=right><td>1.6</td>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>2</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
- * <tr align=right><td>1.1</td>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>throw {@code ArithmeticException}</td>
- * <tr align=right><td>1.0</td>  <td>1</td>  <td>1</td>    <td>1</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>1</td>
- * <tr align=right><td>-1.0</td> <td>-1</td> <td>-1</td>   <td>-1</td>   <td>-1</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>-1</td>
- * <tr align=right><td>-1.1</td> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>throw {@code ArithmeticException}</td>
- * <tr align=right><td>-1.6</td> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-2</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
- * <tr align=right><td>-2.5</td> <td>-3</td> <td>-2</td>   <td>-2</td>   <td>-3</td> <td>-3</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
- * <tr align=right><td>-5.5</td> <td>-6</td> <td>-5</td>   <td>-5</td>   <td>-6</td> <td>-6</td>     <td>-5</td>      <td>-6</td>      <td>throw {@code ArithmeticException}</td>
- *</table>
+ * <tr><th scope="row">5.5</th>  <td>6</td>  <td>5</td>    <td>6</td>    <td>5</td>  <td>6</td>      <td>5</td>       <td>6</td>       <td>throw {@code ArithmeticException}</td>
+ * <tr><th scope="row">2.5</th>  <td>3</td>  <td>2</td>    <td>3</td>    <td>2</td>  <td>3</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
+ * <tr><th scope="row">1.6</th>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>2</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
+ * <tr><th scope="row">1.1</th>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>throw {@code ArithmeticException}</td>
+ * <tr><th scope="row">1.0</th>  <td>1</td>  <td>1</td>    <td>1</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>1</td>
+ * <tr><th scope="row">-1.0</th> <td>-1</td> <td>-1</td>   <td>-1</td>   <td>-1</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>-1</td>
+ * <tr><th scope="row">-1.1</th> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>throw {@code ArithmeticException}</td>
+ * <tr><th scope="row">-1.6</th> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-2</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
+ * <tr><th scope="row">-2.5</th> <td>-3</td> <td>-2</td>   <td>-2</td>   <td>-3</td> <td>-3</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
+ * <tr><th scope="row">-5.5</th> <td>-6</td> <td>-5</td>   <td>-5</td>   <td>-6</td> <td>-6</td>     <td>-5</td>      <td>-6</td>      <td>throw {@code ArithmeticException}</td>
+ * </tbody>
+ * </table>
  *
  *
  * <p>This {@code enum} is intended to replace the integer-based
@@ -90,6 +94,7 @@
  * @author  Joseph D. Darcy
  * @since 1.5
  */
+@SuppressWarnings("deprecation") // Legacy rounding mode constants in BigDecimal
 public enum RoundingMode {
 
         /**
@@ -99,20 +104,24 @@
          * value.
          *
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode UP Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
-         *    <th>Input rounded to one digit<br> with {@code UP} rounding
-         *<tr align=right><td>5.5</td>  <td>6</td>
-         *<tr align=right><td>2.5</td>  <td>3</td>
-         *<tr align=right><td>1.6</td>  <td>2</td>
-         *<tr align=right><td>1.1</td>  <td>2</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>-2</td>
-         *<tr align=right><td>-1.6</td> <td>-2</td>
-         *<tr align=right><td>-2.5</td> <td>-3</td>
-         *<tr align=right><td>-5.5</td> <td>-6</td>
+         *<table class="striped">
+         * <caption>Rounding mode UP Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th scope="col">Input Number</th>
+         *    <th scope="col">Input rounded to one digit<br> with {@code UP} rounding
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>6</td>
+         *<tr><th scope="row">2.5</th>  <td>3</td>
+         *<tr><th scope="row">1.6</th>  <td>2</td>
+         *<tr><th scope="row">1.1</th>  <td>2</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>-2</td>
+         *<tr><th scope="row">-1.6</th> <td>-2</td>
+         *<tr><th scope="row">-2.5</th> <td>-3</td>
+         *<tr><th scope="row">-5.5</th> <td>-6</td>
+         *</tbody>
          *</table>
          */
     UP(BigDecimal.ROUND_UP),
@@ -123,20 +132,24 @@
          * rounding mode never increases the magnitude of the calculated value.
          *
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode DOWN Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
-         *    <th>Input rounded to one digit<br> with {@code DOWN} rounding
-         *<tr align=right><td>5.5</td>  <td>5</td>
-         *<tr align=right><td>2.5</td>  <td>2</td>
-         *<tr align=right><td>1.6</td>  <td>1</td>
-         *<tr align=right><td>1.1</td>  <td>1</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>-1</td>
-         *<tr align=right><td>-1.6</td> <td>-1</td>
-         *<tr align=right><td>-2.5</td> <td>-2</td>
-         *<tr align=right><td>-5.5</td> <td>-5</td>
+         *<table class="striped">
+         * <caption>Rounding mode DOWN Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th scope="col">Input Number</th>
+         *    <th scope="col">Input rounded to one digit<br> with {@code DOWN} rounding
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>5</td>
+         *<tr><th scope="row">2.5</th>  <td>2</td>
+         *<tr><th scope="row">1.6</th>  <td>1</td>
+         *<tr><th scope="row">1.1</th>  <td>1</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>-1</td>
+         *<tr><th scope="row">-1.6</th> <td>-1</td>
+         *<tr><th scope="row">-2.5</th> <td>-2</td>
+         *<tr><th scope="row">-5.5</th> <td>-5</td>
+         *</tbody>
          *</table>
          */
     DOWN(BigDecimal.ROUND_DOWN),
@@ -148,20 +161,24 @@
          * that this rounding mode never decreases the calculated value.
          *
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode CEILING Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
+         *<table class="striped">
+         * <caption>Rounding mode CEILING Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th>Input Number</th>
          *    <th>Input rounded to one digit<br> with {@code CEILING} rounding
-         *<tr align=right><td>5.5</td>  <td>6</td>
-         *<tr align=right><td>2.5</td>  <td>3</td>
-         *<tr align=right><td>1.6</td>  <td>2</td>
-         *<tr align=right><td>1.1</td>  <td>2</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>-1</td>
-         *<tr align=right><td>-1.6</td> <td>-1</td>
-         *<tr align=right><td>-2.5</td> <td>-2</td>
-         *<tr align=right><td>-5.5</td> <td>-5</td>
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>6</td>
+         *<tr><th scope="row">2.5</th>  <td>3</td>
+         *<tr><th scope="row">1.6</th>  <td>2</td>
+         *<tr><th scope="row">1.1</th>  <td>2</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>-1</td>
+         *<tr><th scope="row">-1.6</th> <td>-1</td>
+         *<tr><th scope="row">-2.5</th> <td>-2</td>
+         *<tr><th scope="row">-5.5</th> <td>-5</td>
+         *</tbody>
          *</table>
          */
     CEILING(BigDecimal.ROUND_CEILING),
@@ -173,20 +190,24 @@
          * this rounding mode never increases the calculated value.
          *
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode FLOOR Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
-         *    <th>Input rounded to one digit<br> with {@code FLOOR} rounding
-         *<tr align=right><td>5.5</td>  <td>5</td>
-         *<tr align=right><td>2.5</td>  <td>2</td>
-         *<tr align=right><td>1.6</td>  <td>1</td>
-         *<tr align=right><td>1.1</td>  <td>1</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>-2</td>
-         *<tr align=right><td>-1.6</td> <td>-2</td>
-         *<tr align=right><td>-2.5</td> <td>-3</td>
-         *<tr align=right><td>-5.5</td> <td>-6</td>
+         *<table class="striped">
+         * <caption>Rounding mode FLOOR Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th scope="col">Input Number</th>
+         *    <th scope="col">Input rounded to one digit<br> with {@code FLOOR} rounding
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>5</td>
+         *<tr><th scope="row">2.5</th>  <td>2</td>
+         *<tr><th scope="row">1.6</th>  <td>1</td>
+         *<tr><th scope="row">1.1</th>  <td>1</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>-2</td>
+         *<tr><th scope="row">-1.6</th> <td>-2</td>
+         *<tr><th scope="row">-2.5</th> <td>-3</td>
+         *<tr><th scope="row">-5.5</th> <td>-6</td>
+         *</tbody>
          *</table>
          */
     FLOOR(BigDecimal.ROUND_FLOOR),
@@ -200,20 +221,24 @@
          * mode commonly taught at school.
          *
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode HALF_UP Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
-         *    <th>Input rounded to one digit<br> with {@code HALF_UP} rounding
-         *<tr align=right><td>5.5</td>  <td>6</td>
-         *<tr align=right><td>2.5</td>  <td>3</td>
-         *<tr align=right><td>1.6</td>  <td>2</td>
-         *<tr align=right><td>1.1</td>  <td>1</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>-1</td>
-         *<tr align=right><td>-1.6</td> <td>-2</td>
-         *<tr align=right><td>-2.5</td> <td>-3</td>
-         *<tr align=right><td>-5.5</td> <td>-6</td>
+         *<table class="striped">
+         * <caption>Rounding mode HALF_UP Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th scope="col">Input Number</th>
+         *    <th scope="col">Input rounded to one digit<br> with {@code HALF_UP} rounding
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>6</td>
+         *<tr><th scope="row">2.5</th>  <td>3</td>
+         *<tr><th scope="row">1.6</th>  <td>2</td>
+         *<tr><th scope="row">1.1</th>  <td>1</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>-1</td>
+         *<tr><th scope="row">-1.6</th> <td>-2</td>
+         *<tr><th scope="row">-2.5</th> <td>-3</td>
+         *<tr><th scope="row">-5.5</th> <td>-6</td>
+         *</tbody>
          *</table>
          */
     HALF_UP(BigDecimal.ROUND_HALF_UP),
@@ -226,20 +251,24 @@
          * {@code RoundingMode.DOWN}.
          *
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode HALF_DOWN Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
-         *    <th>Input rounded to one digit<br> with {@code HALF_DOWN} rounding
-         *<tr align=right><td>5.5</td>  <td>5</td>
-         *<tr align=right><td>2.5</td>  <td>2</td>
-         *<tr align=right><td>1.6</td>  <td>2</td>
-         *<tr align=right><td>1.1</td>  <td>1</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>-1</td>
-         *<tr align=right><td>-1.6</td> <td>-2</td>
-         *<tr align=right><td>-2.5</td> <td>-2</td>
-         *<tr align=right><td>-5.5</td> <td>-5</td>
+         *<table class="striped">
+         * <caption>Rounding mode HALF_DOWN Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th scope="col">Input Number</th>
+         *    <th scope="col">Input rounded to one digit<br> with {@code HALF_DOWN} rounding
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>5</td>
+         *<tr><th scope="row">2.5</th>  <td>2</td>
+         *<tr><th scope="row">1.6</th>  <td>2</td>
+         *<tr><th scope="row">1.1</th>  <td>1</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>-1</td>
+         *<tr><th scope="row">-1.6</th> <td>-2</td>
+         *<tr><th scope="row">-2.5</th> <td>-2</td>
+         *<tr><th scope="row">-5.5</th> <td>-5</td>
+         *</tbody>
          *</table>
          */
     HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
@@ -259,20 +288,24 @@
          * arithmetic in Java.
          *
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode HALF_EVEN Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
-         *    <th>Input rounded to one digit<br> with {@code HALF_EVEN} rounding
-         *<tr align=right><td>5.5</td>  <td>6</td>
-         *<tr align=right><td>2.5</td>  <td>2</td>
-         *<tr align=right><td>1.6</td>  <td>2</td>
-         *<tr align=right><td>1.1</td>  <td>1</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>-1</td>
-         *<tr align=right><td>-1.6</td> <td>-2</td>
-         *<tr align=right><td>-2.5</td> <td>-2</td>
-         *<tr align=right><td>-5.5</td> <td>-6</td>
+         *<table class="striped">
+         * <caption>Rounding mode HALF_EVEN Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th scope="col">Input Number</th>
+         *    <th scope="col">Input rounded to one digit<br> with {@code HALF_EVEN} rounding
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>6</td>
+         *<tr><th scope="row">2.5</th>  <td>2</td>
+         *<tr><th scope="row">1.6</th>  <td>2</td>
+         *<tr><th scope="row">1.1</th>  <td>1</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>-1</td>
+         *<tr><th scope="row">-1.6</th> <td>-2</td>
+         *<tr><th scope="row">-2.5</th> <td>-2</td>
+         *<tr><th scope="row">-5.5</th> <td>-6</td>
+         *</tbody>
          *</table>
          */
     HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
@@ -283,20 +316,24 @@
          * specified on an operation that yields an inexact result, an
          * {@code ArithmeticException} is thrown.
          *<p>Example:
-         *<table border>
-         * <caption><b>Rounding mode UNNECESSARY Examples</b></caption>
-         *<tr valign=top><th>Input Number</th>
-         *    <th>Input rounded to one digit<br> with {@code UNNECESSARY} rounding
-         *<tr align=right><td>5.5</td>  <td>throw {@code ArithmeticException}</td>
-         *<tr align=right><td>2.5</td>  <td>throw {@code ArithmeticException}</td>
-         *<tr align=right><td>1.6</td>  <td>throw {@code ArithmeticException}</td>
-         *<tr align=right><td>1.1</td>  <td>throw {@code ArithmeticException}</td>
-         *<tr align=right><td>1.0</td>  <td>1</td>
-         *<tr align=right><td>-1.0</td> <td>-1</td>
-         *<tr align=right><td>-1.1</td> <td>throw {@code ArithmeticException}</td>
-         *<tr align=right><td>-1.6</td> <td>throw {@code ArithmeticException}</td>
-         *<tr align=right><td>-2.5</td> <td>throw {@code ArithmeticException}</td>
-         *<tr align=right><td>-5.5</td> <td>throw {@code ArithmeticException}</td>
+         *<table class="striped">
+         * <caption>Rounding mode UNNECESSARY Examples</caption>
+         *<thead>
+         *<tr style="vertical-align:top"><th scope="col">Input Number</th>
+         *    <th scope="col">Input rounded to one digit<br> with {@code UNNECESSARY} rounding
+         *</thead>
+         *<tbody style="text-align:right">
+         *<tr><th scope="row">5.5</th>  <td>throw {@code ArithmeticException}</td>
+         *<tr><th scope="row">2.5</th>  <td>throw {@code ArithmeticException}</td>
+         *<tr><th scope="row">1.6</th>  <td>throw {@code ArithmeticException}</td>
+         *<tr><th scope="row">1.1</th>  <td>throw {@code ArithmeticException}</td>
+         *<tr><th scope="row">1.0</th>  <td>1</td>
+         *<tr><th scope="row">-1.0</th> <td>-1</td>
+         *<tr><th scope="row">-1.1</th> <td>throw {@code ArithmeticException}</td>
+         *<tr><th scope="row">-1.6</th> <td>throw {@code ArithmeticException}</td>
+         *<tr><th scope="row">-2.5</th> <td>throw {@code ArithmeticException}</td>
+         *<tr><th scope="row">-5.5</th> <td>throw {@code ArithmeticException}</td>
+         *</tbody>
          *</table>
          */
     UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
diff --git a/ojluni/src/main/java/java/math/package-info.java b/ojluni/src/main/java/java/math/package-info.java
index 377cc25..ed3a8dc 100644
--- a/ojluni/src/main/java/java/math/package-info.java
+++ b/ojluni/src/main/java/java/math/package-info.java
@@ -40,6 +40,6 @@
  * allowing the user to choose from a comprehensive set of eight
  * rounding modes.
  *
- * @since JDK1.1
+ * @since 1.1
  */
 package java.math;
diff --git a/ojluni/src/main/java/java/net/BindException.java b/ojluni/src/main/java/java/net/BindException.java
index 9c2bb48..48c7106 100644
--- a/ojluni/src/main/java/java/net/BindException.java
+++ b/ojluni/src/main/java/java/net/BindException.java
@@ -31,7 +31,7 @@
  * socket to a local address and port.  Typically, the port is
  * in use, or the requested local address could not be assigned.
  *
- * @since   JDK1.1
+ * @since   1.1
  */
 
 public class BindException extends SocketException {
diff --git a/ojluni/src/main/java/java/net/ConnectException.java b/ojluni/src/main/java/java/net/ConnectException.java
index ff58643..e67894e 100644
--- a/ojluni/src/main/java/java/net/ConnectException.java
+++ b/ojluni/src/main/java/java/net/ConnectException.java
@@ -32,7 +32,7 @@
  * was refused remotely (e.g., no process is listening on the
  * remote address/port).
  *
- * @since   JDK1.1
+ * @since   1.1
  */
 public class ConnectException extends SocketException {
     private static final long serialVersionUID = 3831404271622369215L;
diff --git a/ojluni/src/main/java/java/net/ContentHandlerFactory.java b/ojluni/src/main/java/java/net/ContentHandlerFactory.java
index 64112e3..994e266 100644
--- a/ojluni/src/main/java/java/net/ContentHandlerFactory.java
+++ b/ojluni/src/main/java/java/net/ContentHandlerFactory.java
@@ -36,15 +36,16 @@
  * @author  James Gosling
  * @see     java.net.ContentHandler
  * @see     java.net.URLStreamHandler
- * @since   JDK1.0
+ * @since   1.0
  */
 public interface ContentHandlerFactory {
+
     /**
      * Creates a new {@code ContentHandler} to read an object from
      * a {@code URLStreamHandler}.
      *
      * @param   mimetype   the MIME type for which a content handler is desired.
-
+     *
      * @return  a new {@code ContentHandler} to read an object from a
      *          {@code URLStreamHandler}.
      * @see     java.net.ContentHandler
diff --git a/ojluni/src/main/java/java/net/CookieHandler.java b/ojluni/src/main/java/java/net/CookieHandler.java
index ef91d00..922eaf5 100644
--- a/ojluni/src/main/java/java/net/CookieHandler.java
+++ b/ojluni/src/main/java/java/net/CookieHandler.java
@@ -36,9 +36,9 @@
  * handler. The HTTP state management mechanism specifies a way to
  * create a stateful session with HTTP requests and responses.
  *
- * <p>A system-wide CookieHandler that to used by the HTTP protocol
- * handler can be registered by doing a
- * CookieHandler.setDefault(CookieHandler). The currently registered
+ * <p> A system-wide CookieHandler to be used by the {@linkplain
+ * HttpURLConnection HTTP URL stream protocol handler} can be registered by
+ * doing a CookieHandler.setDefault(CookieHandler). The currently registered
  * CookieHandler can be retrieved by calling
  * CookieHandler.getDefault().
  *
@@ -69,7 +69,7 @@
      * {@link NetPermission}{@code ("getCookieHandler")}
      * @see #setDefault(CookieHandler)
      */
-    public synchronized static CookieHandler getDefault() {
+    public static synchronized CookieHandler getDefault() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(SecurityConstants.GET_COOKIEHANDLER_PERMISSION);
@@ -89,7 +89,7 @@
      * {@link NetPermission}{@code ("setCookieHandler")}
      * @see #getDefault()
      */
-    public synchronized static void setDefault(CookieHandler cHandler) {
+    public static synchronized void setDefault(CookieHandler cHandler) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(SecurityConstants.SET_COOKIEHANDLER_PERMISSION);
diff --git a/ojluni/src/main/java/java/net/CookieManager.java b/ojluni/src/main/java/java/net/CookieManager.java
index bff9734..15bd272 100644
--- a/ojluni/src/main/java/java/net/CookieManager.java
+++ b/ojluni/src/main/java/java/net/CookieManager.java
@@ -82,7 +82,7 @@
  *   <li>
  *     Currently, only CookieStore.add(URI, HttpCookie) and CookieStore.get(URI)
  *     are used by CookieManager. Others are for completeness and might be needed
- *     by a more sophisticated CookieStore implementation, e.g. a NetscapeCookieSotre.
+ *     by a more sophisticated CookieStore implementation, e.g. a NetscapeCookieStore.
  *   </li>
  * </ul>
  * </blockquote>
@@ -202,14 +202,12 @@
             throw new IllegalArgumentException("Argument is null");
         }
 
-        Map<String, List<String>> cookieMap =
-                        new java.util.HashMap<String, List<String>>();
         // if there's no default CookieStore, no way for us to get any cookie
         if (cookieJar == null)
-            return Collections.unmodifiableMap(cookieMap);
+            return Map.of();
 
         boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
-        List<HttpCookie> cookies = new java.util.ArrayList<HttpCookie>();
+        List<HttpCookie> cookies = new java.util.ArrayList<>();
         // BEGIN Android-removed: The logic of converting null path is moved into pathMatches.
         /*
         String path = uri.getPath();
@@ -258,8 +256,7 @@
         // apply sort rule (RFC 2965 sec. 3.3.4)
         List<String> cookieHeader = sortByPath(cookies);
 
-        cookieMap.put("Cookie", cookieHeader);
-        return Collections.unmodifiableMap(cookieMap);
+        return Map.of("Cookie", cookieHeader);
     }
 
     public void
@@ -307,7 +304,7 @@
                             // the path is the directory of the page/doc
                             String path = uri.getPath();
                             if (!path.endsWith("/")) {
-                                int i = path.lastIndexOf("/");
+                                int i = path.lastIndexOf('/');
                                 if (i > 0) {
                                     path = path.substring(0, i + 1);
                                 } else {
@@ -382,8 +379,8 @@
     }
 
 
-    static private boolean isInPortList(String lst, int port) {
-        int i = lst.indexOf(",");
+    private static boolean isInPortList(String lst, int port) {
+        int i = lst.indexOf(',');
         int val = -1;
         while (i > 0) {
             try {
@@ -394,7 +391,7 @@
             } catch (NumberFormatException numberFormatException) {
             }
             lst = lst.substring(i+1);
-            i = lst.indexOf(",");
+            i = lst.indexOf(',');
         }
         if (!lst.isEmpty()) {
             try {
@@ -459,7 +456,7 @@
             result.append(cookies.get(i).toString());
         }
 
-        List<String> cookieHeader = new java.util.ArrayList<String>();
+        List<String> cookieHeader = new java.util.ArrayList<>();
         cookieHeader.add(result.toString());
         // END Android-changed: Cookie header differs in Netscape cookie spec and RFC 2965.
         return cookieHeader;
diff --git a/ojluni/src/main/java/java/net/DatagramPacket.java b/ojluni/src/main/java/java/net/DatagramPacket.java
index c1bd692..542c5a7 100644
--- a/ojluni/src/main/java/java/net/DatagramPacket.java
+++ b/ojluni/src/main/java/java/net/DatagramPacket.java
@@ -38,7 +38,7 @@
  *
  * @author  Pavani Diwanji
  * @author  Benjamin Renaud
- * @since   JDK1.0
+ * @since   1.0
  */
 public final
 class DatagramPacket {
@@ -49,7 +49,7 @@
      *
     static {
         java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
+            new java.security.PrivilegedAction<>() {
                 public Void run() {
                     System.loadLibrary("net");
                     return null;
@@ -292,7 +292,7 @@
      * Sets the IP address of the machine to which this datagram
      * is being sent.
      * @param iaddr the {@code InetAddress}
-     * @since   JDK1.1
+     * @since   1.1
      * @see #getAddress()
      */
     public synchronized void setAddress(InetAddress iaddr) {
@@ -313,7 +313,7 @@
      * Sets the port number on the remote host to which this datagram
      * is being sent.
      * @param iport the port number
-     * @since   JDK1.1
+     * @since   1.1
      * @see #getPort()
      */
     public synchronized void setPort(int iport) {
@@ -368,7 +368,7 @@
      * @see #getLength
      * @see #getData
      *
-     * @since JDK1.1
+     * @since 1.1
      */
     public synchronized void setData(byte[] buf) {
         if (buf == null) {
@@ -396,7 +396,7 @@
      * @see #getLength
      * @see #setData
      *
-     * @since JDK1.1
+     * @since 1.1
      */
     public synchronized void setLength(int length) {
         if ((length + offset) > buf.length || length < 0 ||
diff --git a/ojluni/src/main/java/java/net/DatagramSocket.java b/ojluni/src/main/java/java/net/DatagramSocket.java
index e78f3f2..8d72701 100755
--- a/ojluni/src/main/java/java/net/DatagramSocket.java
+++ b/ojluni/src/main/java/java/net/DatagramSocket.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,8 @@
 import java.nio.channels.DatagramChannel;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
+import java.util.Set;
+import java.util.Collections;
 import libcore.io.Libcore;
 
 /**
@@ -125,7 +127,7 @@
     /**
      * Connects this socket to a remote socket address (IP address + port number).
      * Binds socket if not already bound.
-     * <p>
+     *
      * @param   address The remote address.
      * @param   port    The remote port
      * @throws  SocketException if binding the socket fails.
@@ -313,7 +315,7 @@
      *             {@code checkListen} method doesn't allow the operation.
      *
      * @see SecurityManager#checkListen
-     * @since   JDK1.1
+     * @since   1.1
      */
     public DatagramSocket(int port, InetAddress laddr) throws SocketException {
         this(new InetSocketAddress(laddr, port));
@@ -326,7 +328,7 @@
         // getDeclaredMethod, therefore we need permission to access the member
         try {
             AccessController.doPrivileged(
-                new PrivilegedExceptionAction<Void>() {
+                new PrivilegedExceptionAction<>() {
                     public Void run() throws NoSuchMethodException {
                         Class<?>[] cl = new Class<?>[1];
                         cl[0] = DatagramPacket.class;
@@ -379,7 +381,7 @@
      * <p>
      * If the address is {@code null}, then the system will pick up
      * an ephemeral port and a valid local address to bind the socket.
-     *<p>
+     *
      * @param   addr The address and port to bind to.
      * @throws  SocketException if any error happens during the bind, or if the
      *          socket is already bound.
@@ -489,7 +491,7 @@
      *
      * <p> If given an {@link InetSocketAddress InetSocketAddress}, this method
      * behaves as if invoking {@link #connect(InetAddress,int) connect(InetAddress,int)}
-     * with the the given socket addresses IP address and port number.
+     * with the given socket addresses IP address and port number.
      *
      * @param   addr    The remote address.
      *
@@ -928,13 +930,13 @@
      *
      * @param timeout the specified timeout in milliseconds.
      * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
-     * @since   JDK1.1
+     * @since   1.1
      * @see #getSoTimeout()
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
+        getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
     }
 
     /**
@@ -943,7 +945,7 @@
      *
      * @return the setting for SO_TIMEOUT
      * @throws SocketException if there is an error in the underlying protocol, such as an UDP error.
-     * @since   JDK1.1
+     * @since   1.1
      * @see #setSoTimeout(int)
      */
     public synchronized int getSoTimeout() throws SocketException {
@@ -996,7 +998,7 @@
         }
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
+        getImpl().setOption(SocketOptions.SO_SNDBUF, size);
     }
 
     /**
@@ -1021,7 +1023,7 @@
 
     /**
      * Sets the SO_RCVBUF option to the specified value for this
-     * {@code DatagramSocket}. The SO_RCVBUF option is used by the
+     * {@code DatagramSocket}. The SO_RCVBUF option is used by
      * the network implementation as a hint to size the underlying
      * network I/O buffers. The SO_RCVBUF setting may also be used
      * by the network implementation to determine the maximum size
@@ -1054,7 +1056,7 @@
         }
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
+        getImpl().setOption(SocketOptions.SO_RCVBUF, size);
     }
 
     /**
@@ -1116,7 +1118,7 @@
             throw new SocketException("Socket is closed");
         // Integer instead of Boolean for compatibility with older DatagramSocketImpl
         if (oldImpl)
-            getImpl().setOption(SocketOptions.SO_REUSEADDR, new Integer(on?-1:0));
+            getImpl().setOption(SocketOptions.SO_REUSEADDR, on?-1:0);
         else
             getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
     }
@@ -1326,10 +1328,8 @@
      *              datagram socket factory.
      * @exception  SocketException  if the factory is already defined.
      * @exception  SecurityException  if a security manager exists and its
-     *             {@code checkSetFactory} method doesn't allow the
-     operation.
-     * @see
-     java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
+     *             {@code checkSetFactory} method doesn't allow the operation.
+     * @see       java.net.DatagramSocketImplFactory#createDatagramSocketImpl()
      * @see       SecurityManager#checkSetFactory
      * @since 1.3
      */
@@ -1347,6 +1347,98 @@
         factory = fac;
     }
 
+    /**
+     * Sets the value of a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     *
+     * @return this DatagramSocket
+     *
+     * @throws UnsupportedOperationException if the datagram socket
+     *         does not support the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @since 9
+     */
+    public <T> DatagramSocket setOption(SocketOption<T> name, T value)
+        throws IOException
+    {
+        getImpl().setOption(name, value);
+        return this;
+    }
+
+    /**
+     * Returns the value of a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the datagram socket
+     *         does not support the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 9
+     */
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return getImpl().getOption(name);
+    }
+
+    private static Set<SocketOption<?>> options;
+    private static boolean optionsSet = false;
+
+    /**
+     * Returns a set of the socket options supported by this socket.
+     *
+     * This method will continue to return the set of options even after
+     * the socket has been closed.
+     *
+     * @return A set of the socket options supported by this socket. This set
+     *        may be empty if the socket's DatagramSocketImpl cannot be created.
+     *
+     * @since 9
+     */
+    public Set<SocketOption<?>> supportedOptions() {
+        synchronized(DatagramSocket.class) {
+            if (optionsSet) {
+                return options;
+            }
+            try {
+                DatagramSocketImpl impl = getImpl();
+                options = Collections.unmodifiableSet(impl.supportedOptions());
+            } catch (IOException e) {
+                options = Collections.emptySet();
+            }
+            optionsSet = true;
+            return options;
+        }
+    }
+
     // Android-added: for testing and internal use.
     /**
      * Gets socket's underlying {@link FileDescriptor}.
@@ -1358,5 +1450,4 @@
     public FileDescriptor getFileDescriptor$() {
         return impl.fd;
     }
-
 }
diff --git a/ojluni/src/main/java/java/net/DatagramSocketImpl.java b/ojluni/src/main/java/java/net/DatagramSocketImpl.java
index 537edfe..98f0683 100644
--- a/ojluni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/ojluni/src/main/java/java/net/DatagramSocketImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,12 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.io.InterruptedIOException;
+import java.util.Set;
 
 /**
  * Abstract datagram and multicast socket implementation base class.
  * @author Pavani Diwanji
- * @since  JDK1.1
+ * @since  1.1
  */
 
 public abstract class DatagramSocketImpl implements SocketOptions {
@@ -47,12 +47,6 @@
      */
     protected FileDescriptor fd;
 
-    int dataAvailable() {
-        // default impl returns zero, which disables the calling
-        // functionality
-        return 0;
-    }
-
     /**
      * The DatagramSocket or MulticastSocket
      * that owns this impl
@@ -67,6 +61,12 @@
         return socket;
     }
 
+    int dataAvailable() {
+        // default impl returns zero, which disables the calling
+        // functionality
+        return 0;
+    }
+
     /**
      * Creates a datagram socket.
      * @exception SocketException if there is an error in the
@@ -253,13 +253,41 @@
         return localPort;
     }
 
-    <T> void setOption(SocketOption<T> name, T value) throws IOException {
+    /**
+     * Gets the datagram socket file descriptor.
+     * @return a {@code FileDescriptor} object representing the datagram socket
+     * file descriptor
+     */
+    protected FileDescriptor getFileDescriptor() {
+        return fd;
+    }
+
+    /**
+     * Called to set a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     *
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     *
+     * @throws UnsupportedOperationException if the DatagramSocketImpl does not
+     *         support the option
+     *
+     * @throws NullPointerException if name is {@code null}
+     * @throws IOException if an I/O problem occurs while attempting to set the option
+     * @since 9
+     */
+    protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
         if (name == StandardSocketOptions.SO_SNDBUF) {
             setOption(SocketOptions.SO_SNDBUF, value);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             setOption(SocketOptions.SO_RCVBUF, value);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             setOption(SocketOptions.SO_REUSEADDR, value);
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            setOption(SocketOptions.SO_REUSEPORT, value);
         } else if (name == StandardSocketOptions.IP_TOS) {
             setOption(SocketOptions.IP_TOS, value);
         } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
@@ -279,13 +307,32 @@
         }
     }
 
-    <T> T getOption(SocketOption<T> name) throws IOException {
+    /**
+     * Called to get a socket option.
+     *
+     * @return the socket option
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     *
+     * @throws UnsupportedOperationException if the DatagramSocketImpl does not
+     *         support the option
+     *
+     * @throws NullPointerException if name is {@code null}
+     * @throws IOException if an I/O problem occurs while attempting to set the option
+     *
+     * @since 9
+     */
+    @SuppressWarnings("unchecked")
+    protected <T> T getOption(SocketOption<T> name) throws IOException {
         if (name == StandardSocketOptions.SO_SNDBUF) {
             return (T) getOption(SocketOptions.SO_SNDBUF);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             return (T) getOption(SocketOptions.SO_RCVBUF);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             return (T) getOption(SocketOptions.SO_REUSEADDR);
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            return (T) getOption(SocketOptions.SO_REUSEPORT);
         } else if (name == StandardSocketOptions.IP_TOS) {
             return (T) getOption(SocketOptions.IP_TOS);
         } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
@@ -303,12 +350,38 @@
         }
     }
 
+    private static final Set<SocketOption<?>> dgSocketOptions;
+
+    private static final Set<SocketOption<?>> mcSocketOptions;
+
+    static {
+        dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
+                                 StandardSocketOptions.SO_RCVBUF,
+                                 StandardSocketOptions.SO_REUSEADDR,
+                                 StandardSocketOptions.IP_TOS);
+
+        mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF,
+                                 StandardSocketOptions.SO_RCVBUF,
+                                 StandardSocketOptions.SO_REUSEADDR,
+                                 StandardSocketOptions.IP_TOS,
+                                 StandardSocketOptions.IP_MULTICAST_IF,
+                                 StandardSocketOptions.IP_MULTICAST_TTL,
+                                 StandardSocketOptions.IP_MULTICAST_LOOP);
+    }
+
     /**
-     * Gets the datagram socket file descriptor.
-     * @return a {@code FileDescriptor} object representing the datagram socket
-     * file descriptor
+     * Returns a set of SocketOptions supported by this impl
+     * and by this impl's socket (DatagramSocket or MulticastSocket)
+     *
+     * @return a Set of SocketOptions
+     *
+     * @since 9
      */
-    protected FileDescriptor getFileDescriptor() {
-        return fd;
+    protected Set<SocketOption<?>> supportedOptions() {
+        if (getDatagramSocket() instanceof MulticastSocket) {
+            return mcSocketOptions;
+        } else {
+            return dgSocketOptions;
+        }
     }
 }
diff --git a/ojluni/src/main/java/java/net/FileNameMap.java b/ojluni/src/main/java/java/net/FileNameMap.java
index 393b5aa..857787d 100644
--- a/ojluni/src/main/java/java/net/FileNameMap.java
+++ b/ojluni/src/main/java/java/net/FileNameMap.java
@@ -30,7 +30,7 @@
  * between a file name and a MIME type string.
  *
  * @author  Steven B. Byrne
- * @since   JDK1.1
+ * @since   1.1
  */
 public interface FileNameMap {
 
diff --git a/ojluni/src/main/java/java/net/InMemoryCookieStore.java b/ojluni/src/main/java/java/net/InMemoryCookieStore.java
index 85aab8b..7fbd130 100644
--- a/ojluni/src/main/java/java/net/InMemoryCookieStore.java
+++ b/ojluni/src/main/java/java/net/InMemoryCookieStore.java
@@ -171,7 +171,7 @@
     public List<URI> getURIs() {
         // BEGIN Android-changed: App compat. Return URI with no cookies. http://b/65538736
         /*
-        List<URI> uris = new ArrayList<URI>();
+        List<URI> uris = new ArrayList<>();
 
         lock.lock();
         try {
@@ -400,7 +400,7 @@
 
             cookies.add(cookie);
         } else {
-            cookies = new ArrayList<HttpCookie>();
+            cookies = new ArrayList<>();
             cookies.add(cookie);
             indexStore.put(index, cookies);
         }
diff --git a/ojluni/src/main/java/java/net/Inet4Address.java b/ojluni/src/main/java/java/net/Inet4Address.java
index 08952ee..25b3dae 100644
--- a/ojluni/src/main/java/java/net/Inet4Address.java
+++ b/ojluni/src/main/java/java/net/Inet4Address.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,17 +38,17 @@
  * and <a href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC&nbsp;2365:
  * Administratively Scoped IP Multicast</i></a>
  *
- * <h3> <A NAME="format">Textual representation of IP addresses</a> </h3>
+ * <h3> <a id="format">Textual representation of IP addresses</a> </h3>
  *
  * Textual representation of IPv4 address used as input to methods
  * takes one of the following forms:
  *
- * <blockquote><table cellpadding=0 cellspacing=0 summary="layout">
- * <tr><td>{@code d.d.d.d}</td></tr>
- * <tr><td>{@code d.d.d}</td></tr>
- * <tr><td>{@code d.d}</td></tr>
- * <tr><td>{@code d}</td></tr>
- * </table></blockquote>
+ * <blockquote><ul style="list-style-type:none">
+ * <li>{@code d.d.d.d}</li>
+ * <li>{@code d.d.d}</li>
+ * <li>{@code d.d}</li>
+ * <li>{@code d}</li>
+ * </ul></blockquote>
  *
  * <p> When four parts are specified, each is interpreted as a byte of
  * data and assigned, from left to right, to the four bytes of an IPv4
@@ -86,7 +86,7 @@
 
 public final
 class Inet4Address extends InetAddress {
-    final static int INADDRSZ = 4;
+    static final int INADDRSZ = 4;
 
     /** use serialVersionUID from InetAddress, but Inet4Address instance
      *  is always replaced by an InetAddress instance before being
@@ -188,17 +188,15 @@
      * address i.e first four bits of the address are 1110.
      * @return a {@code boolean} indicating if the InetAddress is
      * an IP multicast address
-     * @since   JDK1.1
      */
     public boolean isMulticastAddress() {
         return ((holder().getAddress() & 0xf0000000) == 0xe0000000);
     }
 
     /**
-     * Utility routine to check if the InetAddress in a wildcard address.
+     * Utility routine to check if the InetAddress is a wildcard address.
      * @return a {@code boolean} indicating if the Inetaddress is
      *         a wildcard address.
-     * @since 1.4
      */
     public boolean isAnyLocalAddress() {
         return holder().getAddress() == 0;
@@ -209,7 +207,6 @@
      *
      * @return a {@code boolean} indicating if the InetAddress is
      * a loopback address; or false otherwise.
-     * @since 1.4
      */
     public boolean isLoopbackAddress() {
         /* 127.x.x.x */
@@ -222,7 +219,6 @@
      *
      * @return a {@code boolean} indicating if the InetAddress is
      * a link local address; or false if address is not a link local unicast address.
-     * @since 1.4
      */
     public boolean isLinkLocalAddress() {
         // link-local unicast in IPv4 (169.254.0.0/16)
@@ -239,7 +235,6 @@
      *
      * @return a {@code boolean} indicating if the InetAddress is
      * a site local address; or false if address is not a site local unicast address.
-     * @since 1.4
      */
     public boolean isSiteLocalAddress() {
         // refer to RFC 1918
@@ -260,7 +255,6 @@
      * @return a {@code boolean} indicating if the address has
      *         is a multicast address of global scope, false if it is not
      *         of global scope or it is not a multicast address
-     * @since 1.4
      */
     public boolean isMCGlobal() {
         // 224.0.1.0 to 238.255.255.255
@@ -276,7 +270,6 @@
      * @return a {@code boolean} indicating if the address has
      *         is a multicast address of node-local scope, false if it is not
      *         of node-local scope or it is not a multicast address
-     * @since 1.4
      */
     public boolean isMCNodeLocal() {
         // unless ttl == 0
@@ -289,7 +282,6 @@
      * @return a {@code boolean} indicating if the address has
      *         is a multicast address of link-local scope, false if it is not
      *         of link-local scope or it is not a multicast address
-     * @since 1.4
      */
     public boolean isMCLinkLocal() {
         // 224.0.0/24 prefix and ttl == 1
@@ -305,7 +297,6 @@
      * @return a {@code boolean} indicating if the address has
      *         is a multicast address of site-local scope, false if it is not
      *         of site-local scope or it is not a multicast address
-     * @since 1.4
      */
     public boolean isMCSiteLocal() {
         // 239.255/16 prefix or ttl < 32
@@ -321,7 +312,6 @@
      *         is a multicast address of organization-local scope,
      *         false if it is not of organization-local scope
      *         or it is not a multicast address
-     * @since 1.4
      */
     public boolean isMCOrgLocal() {
         // 239.192 - 239.195
@@ -353,7 +343,6 @@
      * Returns the IP address string in textual presentation form.
      *
      * @return  the raw IP address in a string format.
-     * @since   JDK1.0.2
      */
     public String getHostAddress() {
         return numericToTextFormat(getAddress());
@@ -390,15 +379,13 @@
     }
 
     // Utilities
-    /*
+
+    /**
      * Converts IPv4 binary address into a string suitable for presentation.
      *
      * @param src a byte array representing an IPv4 numeric address
      * @return a String representing the IPv4 address in
-     *         textual representation format
-     * @since 1.4
      */
-
     static String numericToTextFormat(byte[] src)
     {
         return (src[0] & 0xff) + "." + (src[1] & 0xff) + "." + (src[2] & 0xff) + "." + (src[3] & 0xff);
diff --git a/ojluni/src/main/java/java/net/InetSocketAddress.java b/ojluni/src/main/java/java/net/InetSocketAddress.java
index 74b559b..fee3c19 100644
--- a/ojluni/src/main/java/java/net/InetSocketAddress.java
+++ b/ojluni/src/main/java/java/net/InetSocketAddress.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -168,7 +168,7 @@
      * A valid port value is between 0 and 65535.
      * A port number of {@code zero} will let the system pick up an
      * ephemeral port in a {@code bind} operation.
-     * <p>
+     *
      * @param   port    The port number
      * @throws IllegalArgumentException if the port parameter is outside the specified
      * range of valid port values.
@@ -188,7 +188,7 @@
      * ephemeral port in a {@code bind} operation.
      * <P>
      * A {@code null} address will assign the <i>wildcard</i> address.
-     * <p>
+     *
      * @param   addr    The IP address
      * @param   port    The port number
      * @throws IllegalArgumentException if the port parameter is outside the specified
@@ -217,11 +217,11 @@
      * A valid port value is between 0 and 65535.
      * A port number of {@code zero} will let the system pick up an
      * ephemeral port in a {@code bind} operation.
-     * <P>
+     *
      * @param   hostname the Host name
      * @param   port    The port number
      * @throws IllegalArgumentException if the port parameter is outside the range
-     * of valid port values, or if the hostname parameter is <TT>null</TT>.
+     * of valid port values, or if the hostname parameter is {@code null}.
      * @throws SecurityException if a security manager is present and
      *                           permission to resolve the host name is
      *                           denied.
@@ -254,14 +254,14 @@
      * A valid port value is between 0 and 65535.
      * A port number of {@code zero} will let the system pick up an
      * ephemeral port in a {@code bind} operation.
-     * <P>
+     *
      * @param   host    the Host name
      * @param   port    The port number
      * @throws IllegalArgumentException if the port parameter is outside
      *                  the range of valid port values, or if the hostname
-     *                  parameter is <TT>null</TT>.
+     *                  parameter is {@code null}.
      * @see     #isUnresolved()
-     * @return  a {@code InetSocketAddress} representing the unresolved
+     * @return  an {@code InetSocketAddress} representing the unresolved
      *          socket address
      * @since 1.5
      */
@@ -317,18 +317,10 @@
         throw new InvalidObjectException("Stream data required");
     }
 
-    private static final long FIELDS_OFFSET;
-    private static final sun.misc.Unsafe UNSAFE;
-    static {
-        try {
-            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
-            FIELDS_OFFSET = unsafe.objectFieldOffset(
-                    InetSocketAddress.class.getDeclaredField("holder"));
-            UNSAFE = unsafe;
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
+    private static final jdk.internal.misc.Unsafe UNSAFE
+            = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final long FIELDS_OFFSET
+            = UNSAFE.objectFieldOffset(InetSocketAddress.class, "holder");
 
     /**
      * Gets the port number.
@@ -340,10 +332,9 @@
     }
 
     /**
-     *
      * Gets the {@code InetAddress}.
      *
-     * @return the InetAdress or {@code null} if it is unresolved.
+     * @return the InetAddress or {@code null} if it is unresolved.
      */
     public final InetAddress getAddress() {
         return holder.getAddress();
diff --git a/ojluni/src/main/java/java/net/JarURLConnection.java b/ojluni/src/main/java/java/net/JarURLConnection.java
index 70dedec..c5acbf4 100644
--- a/ojluni/src/main/java/java/net/JarURLConnection.java
+++ b/ojluni/src/main/java/java/net/JarURLConnection.java
@@ -173,7 +173,18 @@
         }
 
         jarFileURL = new URL(spec.substring(0, separator++));
+
+        // Android-removed: runtime versioning is unsupported
+        /*
+         * The url argument may have had a runtime fragment appended, so
+         * we need to add a runtime fragment to the jarFileURL to enable
+         * runtime versioning when the underlying jar file is opened.
+         *
+        if ("runtime".equals(url.getRef())) {
+            jarFileURL = new URL(jarFileURL, "#runtime");
+        }
         entryName = null;
+        */
 
         /* if ! is the last letter of the innerURL, entryName is null */
         if (++separator != spec.length()) {
@@ -246,7 +257,7 @@
      * @see #getJarEntry
      */
     public JarEntry getJarEntry() throws IOException {
-        return getJarFile().getJarEntry(entryName);
+        return entryName == null ? null : getJarFile().getJarEntry(entryName);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/net/MalformedURLException.java b/ojluni/src/main/java/java/net/MalformedURLException.java
index 7aef75c..5f9ab51 100644
--- a/ojluni/src/main/java/java/net/MalformedURLException.java
+++ b/ojluni/src/main/java/java/net/MalformedURLException.java
@@ -33,7 +33,7 @@
  * string could not be parsed.
  *
  * @author  Arthur van Hoff
- * @since   JDK1.0
+ * @since   1.0
  */
 public class MalformedURLException extends IOException {
     private static final long serialVersionUID = -182787522200415866L;
diff --git a/ojluni/src/main/java/java/net/MulticastSocket.java b/ojluni/src/main/java/java/net/MulticastSocket.java
index 83a18c3..5b5863f 100644
--- a/ojluni/src/main/java/java/net/MulticastSocket.java
+++ b/ojluni/src/main/java/java/net/MulticastSocket.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,9 @@
 package java.net;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.Enumeration;
+import java.util.Set;
 
 // Android-changed: Updated example code to handle non-ASCII characters
 /**
@@ -79,7 +81,7 @@
  * Currently applets are not allowed to use multicast sockets.
  *
  * @author Pavani Diwanji
- * @since  JDK1.1
+ * @since  1.1
  */
 public
 class MulticastSocket extends DatagramSocket {
@@ -93,21 +95,22 @@
     /**
      * Create a multicast socket.
      *
-     * <p>If there is a security manager,
-     * its {@code checkListen} method is first called
-     * with 0 as its argument to ensure the operation is allowed.
-     * This could result in a SecurityException.
+     * <p>
+     * If there is a security manager, its {@code checkListen} method is first
+     * called with 0 as its argument to ensure the operation is allowed. This
+     * could result in a SecurityException.
      * <p>
      * When the socket is created the
-     * {@link DatagramSocket#setReuseAddress(boolean)} method is
-     * called to enable the SO_REUSEADDR socket option.
+     * {@link DatagramSocket#setReuseAddress(boolean)} method is called to
+     * enable the SO_REUSEADDR socket option.
      *
-     * @exception IOException if an I/O exception occurs
-     * while creating the MulticastSocket
-     * @exception  SecurityException  if a security manager exists and its
-     *             {@code checkListen} method doesn't allow the operation.
+     * @exception IOException if an I/O exception occurs while creating the
+     * MulticastSocket
+     * @exception SecurityException if a security manager exists and its
+     * {@code checkListen} method doesn't allow the operation.
      * @see SecurityManager#checkListen
      * @see java.net.DatagramSocket#setReuseAddress(boolean)
+     * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object)
      */
     public MulticastSocket() throws IOException {
         this(new InetSocketAddress(0));
@@ -173,8 +176,9 @@
             try {
                 bind(bindaddr);
             } finally {
-                if (!isBound())
+                if (!isBound()) {
                     close();
+                }
             }
         }
     }
@@ -290,8 +294,9 @@
      *
      * @param mcastaddr is the multicast address to join
      *
-     * @exception IOException if there is an error joining
-     * or when the address is not a multicast address.
+     * @exception IOException if there is an error joining, or when the address
+     *            is not a multicast address, or the platform does not support
+     *            multicasting
      * @exception  SecurityException  if a security manager exists and its
      * {@code checkMulticast} method doesn't allow the join.
      *
@@ -374,8 +379,9 @@
      *       {@link MulticastSocket#setInterface(InetAddress)} or
      *       {@link MulticastSocket#setNetworkInterface(NetworkInterface)}
      *
-     * @exception IOException if there is an error joining
-     * or when the address is not a multicast address.
+     * @exception IOException if there is an error joining, or when the address
+     *            is not a multicast address, or the platform does not support
+     *            multicasting
      * @exception  SecurityException  if a security manager exists and its
      * {@code checkMulticast} method doesn't allow the join.
      * @throws  IllegalArgumentException if mcastaddr is null or is a
@@ -709,4 +715,24 @@
                 } // synch p
             }  //synch ttl
     } //method
+
+    private static Set<SocketOption<?>> options;
+    private static boolean optionsSet = false;
+
+    @Override
+    public Set<SocketOption<?>> supportedOptions() {
+        synchronized (MulticastSocket.class) {
+            if (optionsSet) {
+                return options;
+            }
+            try {
+                DatagramSocketImpl impl = getImpl();
+                options = Collections.unmodifiableSet(impl.supportedOptions());
+            } catch (SocketException ex) {
+                options = Collections.emptySet();
+            }
+            optionsSet = true;
+            return options;
+        }
+    }
 }
diff --git a/ojluni/src/main/java/java/net/NetPermission.java b/ojluni/src/main/java/java/net/NetPermission.java
index b5a0eab..10918e0 100644
--- a/ojluni/src/main/java/java/net/NetPermission.java
+++ b/ojluni/src/main/java/java/net/NetPermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/net/NetworkInterface.java b/ojluni/src/main/java/java/net/NetworkInterface.java
index e56e0cb..c2b2e58 100644
--- a/ojluni/src/main/java/java/net/NetworkInterface.java
+++ b/ojluni/src/main/java/java/net/NetworkInterface.java
@@ -37,7 +37,11 @@
 import java.util.Map;
 import java.util.NoSuchElementException;
 
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.system.StructIfaddrs;
+import dalvik.annotation.compat.VersionCodes;
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
 import sun.security.action.*;
@@ -47,7 +51,7 @@
 
 // Android-note: NetworkInterface has been rewritten to avoid native code.
 // Fix upstream bug not returning link-down interfaces. http://b/26238832
-// Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+// Android-added: Document restrictions for non-system apps. http://b/170188668
 /**
  * This class represents a Network Interface made up of a name,
  * and a list of IP addresses assigned to this interface.
@@ -58,13 +62,30 @@
  * <p>
  * <a name="access-restrictions"></a>Note that information about
  * {@link NetworkInterface}s may be restricted. For example, non-system apps
- * with {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R} will only
- * have access to information about {@link NetworkInterface}s that are
+ * will only have access to information about {@link NetworkInterface}s that are
  * associated with an {@link InetAddress}.
  *
  * @since 1.4
  */
 public final class NetworkInterface {
+    // Android-added: Anonymized address for apps targeting old API versions. http://b/170188668
+    /**
+     * If this change is enabled, {@link #getHardwareAddress()} returns null when the hardware
+     * address is <a href="#access-restrictions">inaccessible</a>. If the change is disabled, the
+     * default MAC address (02:00:00:00:00:00) is returned instead.
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion=VersionCodes.R)
+    public static final long RETURN_NULL_HARDWARE_ADDRESS = 170188668L;
+    // The default hardware address is a zeroed-out MAC address with only its
+    // locally-administered bit set, returned to apps targeting older API versions if they would
+    // otherwise see a null MAC address.
+    // Matches android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS
+    private static final byte[] DEFAULT_MAC_ADDRESS = {
+        0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
     private String name;
     private String displayName;
     private int index;
@@ -272,7 +293,7 @@
         return "".equals(displayName) ? null : displayName;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Document restrictions for non-system apps. http://b/170188668
     /**
      * Searches for the network interface with the specified name.
      *
@@ -304,7 +325,7 @@
         return null;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Document restrictions for non-system apps. http://b/170188668
     /**
      * Get a network interface given its index.
      *
@@ -373,7 +394,8 @@
         return null;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Document restrictions for non-system apps. http://b/170188668
+    // Android-added: Note about NullPointerException in older versions. http://b/206053582
     /**
      * Returns all the interfaces on this machine. The {@code Enumeration}
      * contains at least one element, possibly representing a loopback
@@ -383,10 +405,12 @@
      * NOTE: can use getNetworkInterfaces()+getInetAddresses()
      *       to obtain all IP addresses for this node
      * <p>
-     * For non-system apps with
-     * {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}, this
-     * method will only return information for {@link NetworkInterface}s that
-     * are associated with an {@link InetAddress}.
+     * For non-system apps, this method will only return information for
+     * {@link NetworkInterface}s associated with an {@link InetAddress}.
+     * <p>
+     * ANDROID NOTE: On Android versions before S (API level 31), this method may throw a
+     *               NullPointerException if called in an environment where there is a virtual
+     *               interface without a parent interface present.
      *
      * @return an Enumeration of NetworkInterfaces found on this machine
      *         that <a href="#access-restrictions">are accessible</a>.
@@ -433,6 +457,10 @@
         StructIfaddrs[] ifaddrs;
         try {
             ifaddrs = Libcore.os.getifaddrs();
+            // Defensive check for b/217749090: ifaddrs should never be null.
+            if (ifaddrs == null) {
+                throw new SocketException("Failed to query network interfaces.");
+            }
         } catch (ErrnoException e) {
             throw e.rethrowAsSocketException();
         }
@@ -562,7 +590,7 @@
         return (getFlags() & IFF_MULTICAST) != 0;
     }
 
-    // Android-added: Document restrictions for targetSdkVersion >= R. http://b/141455849
+    // Android-added: Restrictions for non-system apps. http://b/170188668
     /**
      * Returns the hardware address (usually MAC) of the interface if it
      * has one and if it can be accessed given the current privileges.
@@ -574,8 +602,8 @@
      *          manager is set and the caller does not have the permission
      *          NetPermission("getNetworkInformation"). For example, this
      *          method will generally return {@code null} when called by
-     *          non-system apps having
-     *          {@code targetSdkVersion >= android.os.Build.VERSION_CODES.R}.
+     *          non-system apps (or 02:00:00:00:00:00 for apps having
+     *          {@code targetSdkVersion < android.os.Build.VERSION_CODES.R}).
      *
      * @exception       SocketException if an I/O error occurs.
      * @since 1.6
@@ -594,6 +622,12 @@
         if (ni == null) {
             throw new SocketException("NetworkInterface doesn't exist anymore");
         }
+        // Return 02:00:00:00:00:00 for apps having a target SDK version < R if they would have
+        // otherwise gotten a null MAC address (excluding loopback).
+        if (ni.hardwareAddr == null && !"lo".equals(name)
+                && !Compatibility.isChangeEnabled(RETURN_NULL_HARDWARE_ADDRESS)) {
+            return DEFAULT_MAC_ADDRESS.clone();
+        }
         return ni.hardwareAddr;
         // END Android-changed: Fix upstream not returning link-down interfaces. http://b/26238832
     }
diff --git a/ojluni/src/main/java/java/net/NoRouteToHostException.java b/ojluni/src/main/java/java/net/NoRouteToHostException.java
index 76f0814..cf6e68c 100644
--- a/ojluni/src/main/java/java/net/NoRouteToHostException.java
+++ b/ojluni/src/main/java/java/net/NoRouteToHostException.java
@@ -31,7 +31,7 @@
  * host cannot be reached because of an intervening firewall, or
  * if an intermediate router is down.
  *
- * @since   JDK1.1
+ * @since   1.1
  */
 public class NoRouteToHostException extends SocketException {
     private static final long serialVersionUID = -1897550894873493790L;
diff --git a/ojluni/src/main/java/java/net/ProtocolException.java b/ojluni/src/main/java/java/net/ProtocolException.java
index 5944282..31d0449 100644
--- a/ojluni/src/main/java/java/net/ProtocolException.java
+++ b/ojluni/src/main/java/java/net/ProtocolException.java
@@ -33,7 +33,7 @@
  * protocol, such as a TCP error.
  *
  * @author  Chris Warth
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class ProtocolException extends IOException {
@@ -43,10 +43,10 @@
      * Constructs a new {@code ProtocolException} with the
      * specified detail message.
      *
-     * @param   host   the detail message.
+     * @param   message   the detail message.
      */
-    public ProtocolException(String host) {
-        super(host);
+    public ProtocolException(String message) {
+        super(message);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/net/Proxy.java b/ojluni/src/main/java/java/net/Proxy.java
index 8ba020e..672235b 100644
--- a/ojluni/src/main/java/java/net/Proxy.java
+++ b/ojluni/src/main/java/java/net/Proxy.java
@@ -69,7 +69,7 @@
      * {@code Socket s = new Socket(Proxy.NO_PROXY);}
      *
      */
-    public final static Proxy NO_PROXY = new Proxy();
+    public static final Proxy NO_PROXY = new Proxy();
 
     // Creates the proxy that represents a {@code DIRECT} connection.
     private Proxy() {
diff --git a/ojluni/src/main/java/java/net/ResponseCache.java b/ojluni/src/main/java/java/net/ResponseCache.java
index 2dfaf4a..e023735 100644
--- a/ojluni/src/main/java/java/net/ResponseCache.java
+++ b/ojluni/src/main/java/java/net/ResponseCache.java
@@ -80,7 +80,7 @@
      * @return the system-wide {@code ResponseCache}
      * @since 1.5
      */
-    public synchronized  static ResponseCache getDefault() {
+    public static synchronized ResponseCache getDefault() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(SecurityConstants.GET_RESPONSECACHE_PERMISSION);
@@ -103,7 +103,7 @@
      * @see #getDefault()
      * @since 1.5
      */
-    public synchronized static void setDefault(ResponseCache responseCache) {
+    public static synchronized void setDefault(ResponseCache responseCache) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(SecurityConstants.SET_RESPONSECACHE_PERMISSION);
diff --git a/ojluni/src/main/java/java/net/ServerSocket.java b/ojluni/src/main/java/java/net/ServerSocket.java
index 444a84d..925352a 100644
--- a/ojluni/src/main/java/java/net/ServerSocket.java
+++ b/ojluni/src/main/java/java/net/ServerSocket.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,17 @@
 
 package java.net;
 
+import sun.security.util.SecurityConstants;
+
 import java.io.FileDescriptor;
 import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.nio.channels.ServerSocketChannel;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
+import java.util.Set;
+import java.util.Collections;
 
 /**
  * This class implements server sockets. A server socket waits for
@@ -46,7 +52,7 @@
  * @see     java.net.SocketImpl
  * @see     java.net.ServerSocket#setSocketFactory(java.net.SocketImplFactory)
  * @see     java.nio.channels.ServerSocketChannel
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class ServerSocket implements java.io.Closeable {
@@ -71,12 +77,29 @@
     /**
      * Package-private constructor to create a ServerSocket associated with
      * the given SocketImpl.
+     *
+     * @throws     SecurityException if a security manager is set and
+     *             its {@code checkPermission} method doesn't allow
+     *             {@code NetPermission("setSocketImpl")}.
      */
     ServerSocket(SocketImpl impl) {
+        checkPermission();
         this.impl = impl;
         impl.setServerSocket(this);
     }
 
+    private static Void checkPermission() {
+        // BEGIN Android-removed: SM is no-op.
+        /*
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
+        }
+        */
+        // END Android-removed: SM is no-op.
+        return null;
+    }
+
     /**
      * Creates an unbound server socket.
      *
@@ -157,7 +180,6 @@
      * or may choose to ignore the parameter altogther. The value provided
      * should be greater than {@code 0}. If it is less than or equal to
      * {@code 0}, then an implementation specific default will be used.
-     * <P>
      *
      * @param      port     the port number, or {@code 0} to use a port
      *                      number that is automatically allocated.
@@ -206,7 +228,7 @@
      * or may choose to ignore the parameter altogther. The value provided
      * should be greater than {@code 0}. If it is less than or equal to
      * {@code 0}, then an implementation specific default will be used.
-     * <P>
+     *
      * @param port  the port number, or {@code 0} to use a port
      *              number that is automatically allocated.
      * @param backlog requested maximum length of the queue of incoming
@@ -224,7 +246,7 @@
      * @see SocketOptions
      * @see SocketImpl
      * @see SecurityManager#checkListen
-     * @since   JDK1.1
+     * @since   1.1
      */
     public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {
         setImpl();
@@ -317,7 +339,7 @@
      * <p>
      * If the address is {@code null}, then the system will pick up
      * an ephemeral port and a valid local address to bind the socket.
-     * <p>
+     *
      * @param   endpoint        The IP address and port number to bind to.
      * @throws  IOException if the bind operation fails, or if the socket
      *                     is already bound.
@@ -528,7 +550,7 @@
      *         and the channel is in non-blocking mode
      * @throws IOException if an I/O error occurs when waiting
      * for a connection.
-     * @since   JDK1.1
+     * @since   1.1
      * @revised 1.4
      * @spec JSR-51
      */
@@ -545,6 +567,8 @@
             si.address = new InetAddress();
             si.fd = new FileDescriptor();
             getImpl().accept(si);
+            // Android-removed: SocketCleanable is unsupported
+            // SocketCleanable.register(si.fd);   // raw fd has been set
 
             SecurityManager security = System.getSecurityManager();
             if (security != null) {
@@ -645,13 +669,13 @@
      * @param timeout the specified timeout, in milliseconds
      * @exception SocketException if there is an error in
      * the underlying protocol, such as a TCP error.
-     * @since   JDK1.1
+     * @since   1.1
      * @see #getSoTimeout()
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
+        getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
     }
 
     /**
@@ -659,7 +683,7 @@
      * 0 returns implies that the option is disabled (i.e., timeout of infinity).
      * @return the {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} value
      * @exception IOException if an I/O error occurs
-     * @since   JDK1.1
+     * @since   1.1
      * @see #setSoTimeout(int)
      */
     public synchronized int getSoTimeout() throws IOException {
@@ -848,7 +872,7 @@
         }
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
+        getImpl().setOption(SocketOptions.SO_RCVBUF, size);
     }
 
     /**
@@ -922,6 +946,123 @@
         /* Not implemented yet */
     }
 
+    /**
+     * Sets the value of a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     * @return this ServerSocket
+     *
+     * @throws UnsupportedOperationException if the server socket does not
+     *         support the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 9
+     */
+    public <T> ServerSocket setOption(SocketOption<T> name, T value)
+        throws IOException
+    {
+        getImpl().setOption(name, value);
+        return this;
+    }
+
+    /**
+     * Returns the value of a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the server socket does not
+     *         support the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 9
+     */
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return getImpl().getOption(name);
+    }
+
+    private static Set<SocketOption<?>> options;
+    private static boolean optionsSet = false;
+
+    /**
+     * Returns a set of the socket options supported by this server socket.
+     *
+     * This method will continue to return the set of options even after
+     * the socket has been closed.
+     *
+     * @return A set of the socket options supported by this socket. This set
+     *         may be empty if the socket's SocketImpl cannot be created.
+     *
+     * @since 9
+     */
+    public Set<SocketOption<?>> supportedOptions() {
+        synchronized (ServerSocket.class) {
+            if (optionsSet) {
+                return options;
+            }
+            try {
+                SocketImpl impl = getImpl();
+                options = Collections.unmodifiableSet(impl.supportedOptions());
+            } catch (IOException e) {
+                options = Collections.emptySet();
+            }
+            optionsSet = true;
+            return options;
+        }
+    }
+
+    // BEGIN Android-removed: Pruned unused access interfaces.
+    /*
+    static {
+        SharedSecrets.setJavaNetSocketAccess(
+            new JavaNetSocketAccess() {
+                @Override
+                public ServerSocket newServerSocket(SocketImpl impl) {
+                    return new ServerSocket(impl);
+                }
+
+                @Override
+                public SocketImpl newSocketImpl(Class<? extends SocketImpl> implClass) {
+                    try {
+                        Constructor<? extends SocketImpl> ctor =
+                            implClass.getDeclaredConstructor();
+                        return ctor.newInstance();
+                    } catch (NoSuchMethodException | InstantiationException |
+                             IllegalAccessException | InvocationTargetException e) {
+                        throw new AssertionError(e);
+                    }
+                }
+            }
+        );
+    }
+    */
+
     // Android-added: getFileDescriptor$(), for testing / internal use.
     /**
      * @hide internal use only
diff --git a/ojluni/src/main/java/java/net/Socket.java b/ojluni/src/main/java/java/net/Socket.java
index e8c253b..b063773 100644
--- a/ojluni/src/main/java/java/net/Socket.java
+++ b/ojluni/src/main/java/java/net/Socket.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,9 @@
 
 package java.net;
 
+import sun.security.util.SecurityConstants;
+
+
 import java.io.FileDescriptor;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -34,6 +37,8 @@
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedAction;
+import java.util.Set;
+import java.util.Collections;
 
 /**
  * This class implements client sockets (also called just
@@ -50,7 +55,7 @@
  * @see     java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory)
  * @see     java.net.SocketImpl
  * @see     java.nio.channels.SocketChannel
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class Socket implements java.io.Closeable {
@@ -79,7 +84,7 @@
      * Creates an unconnected socket, with the
      * system-default type of SocketImpl.
      *
-     * @since   JDK1.1
+     * @since   1.1
      * @revised 1.4
      */
     public Socket() {
@@ -159,15 +164,20 @@
     /**
      * Creates an unconnected Socket with a user-specified
      * SocketImpl.
-     * <P>
+     *
      * @param impl an instance of a <B>SocketImpl</B>
      * the subclass wishes to use on the Socket.
      *
      * @exception SocketException if there is an error in the underlying protocol,
      * such as a TCP error.
-     * @since   JDK1.1
+     *
+     * @throws SecurityException if {@code impl} is non-null and a security manager is set
+     * and its {@code checkPermission} method doesn't allow {@code NetPermission("setSocketImpl")}.
+     *
+     * @since   1.1
      */
     protected Socket(SocketImpl impl) throws SocketException {
+        checkPermission(impl);
         this.impl = impl;
         if (impl != null) {
             checkOldImpl();
@@ -175,6 +185,21 @@
         }
     }
 
+    private static Void checkPermission(SocketImpl impl) {
+        // BEGIN Android-removed: SM is no-op.
+        /*
+        if (impl == null) {
+            return null;
+        }
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
+        }
+        */
+        // END Android-removed: SM is no-op.
+        return null;
+    }
+
     /**
      * Creates a stream socket and connects it to the specified port
      * number on the named host.
@@ -284,7 +309,7 @@
      *             parameter is outside the specified range of valid port values,
      *             which is between 0 and 65535, inclusive.
      * @see        SecurityManager#checkConnect
-     * @since   JDK1.1
+     * @since   1.1
      */
     public Socket(String host, int port, InetAddress localAddr,
                   int localPort) throws IOException {
@@ -326,7 +351,7 @@
      *             which is between 0 and 65535, inclusive.
      * @exception  NullPointerException if {@code address} is null.
      * @see        SecurityManager#checkConnect
-     * @since   JDK1.1
+     * @since   1.1
      */
     public Socket(InetAddress address, int port, InetAddress localAddr,
                   int localPort) throws IOException {
@@ -500,7 +525,7 @@
         // getDeclaredMethod, therefore we need permission to access the member
 
         oldImpl = AccessController.doPrivileged
-                                (new PrivilegedAction<Boolean>() {
+                                (new PrivilegedAction<>() {
             public Boolean run() {
                 Class<?> clazz = impl.getClass();
                 while (true) {
@@ -738,7 +763,7 @@
      * @return the local address to which the socket is bound,
      *         the loopback address if denied by the security manager, or
      *         the wildcard address if the socket is closed or not bound yet.
-     * @since   JDK1.1
+     * @since   1.1
      *
      * @see SecurityManager#checkConnect
      */
@@ -937,11 +962,10 @@
             throw new SocketException("Socket is not connected");
         if (isInputShutdown())
             throw new SocketException("Socket input is shutdown");
-        final Socket s = this;
         InputStream is = null;
         try {
             is = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<InputStream>() {
+                new PrivilegedExceptionAction<>() {
                     public InputStream run() throws IOException {
                         return impl.getInputStream();
                     }
@@ -977,11 +1001,10 @@
             throw new SocketException("Socket is not connected");
         if (isOutputShutdown())
             throw new SocketException("Socket output is shutdown");
-        final Socket s = this;
         OutputStream os = null;
         try {
             os = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<OutputStream>() {
+                new PrivilegedExceptionAction<>() {
                     public OutputStream run() throws IOException {
                         return impl.getOutputStream();
                     }
@@ -1002,7 +1025,7 @@
      * @exception SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
      *
-     * @since   JDK1.1
+     * @since   1.1
      *
      * @see #getTcpNoDelay()
      */
@@ -1019,7 +1042,7 @@
      *         {@link SocketOptions#TCP_NODELAY TCP_NODELAY} is enabled.
      * @exception SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
-     * @since   JDK1.1
+     * @since   1.1
      * @see #setTcpNoDelay(boolean)
      */
     public boolean getTcpNoDelay() throws SocketException {
@@ -1040,21 +1063,21 @@
      * @exception SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
      * @exception IllegalArgumentException if the linger value is negative.
-     * @since JDK1.1
+     * @since 1.1
      * @see #getSoLinger()
      */
     public void setSoLinger(boolean on, int linger) throws SocketException {
         if (isClosed())
             throw new SocketException("Socket is closed");
         if (!on) {
-            getImpl().setOption(SocketOptions.SO_LINGER, new Boolean(on));
+            getImpl().setOption(SocketOptions.SO_LINGER, on);
         } else {
             if (linger < 0) {
                 throw new IllegalArgumentException("invalid value for SO_LINGER");
             }
             if (linger > 65535)
                 linger = 65535;
-            getImpl().setOption(SocketOptions.SO_LINGER, new Integer(linger));
+            getImpl().setOption(SocketOptions.SO_LINGER, linger);
         }
     }
 
@@ -1068,7 +1091,7 @@
      * @return the setting for {@link SocketOptions#SO_LINGER SO_LINGER}.
      * @exception SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
-     * @since   JDK1.1
+     * @since   1.1
      * @see #setSoLinger(boolean, int)
      */
     public int getSoLinger() throws SocketException {
@@ -1168,7 +1191,7 @@
      * @param timeout the specified timeout, in milliseconds.
      * @exception SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
-     * @since   JDK 1.1
+     * @since   1.1
      * @see #getSoTimeout()
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
@@ -1177,7 +1200,7 @@
         if (timeout < 0)
           throw new IllegalArgumentException("timeout can't be negative");
 
-        getImpl().setOption(SocketOptions.SO_TIMEOUT, new Integer(timeout));
+        getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout);
     }
 
     /**
@@ -1188,7 +1211,7 @@
      * @exception SocketException if there is an error
      * in the underlying protocol, such as a TCP error.
      *
-     * @since   JDK1.1
+     * @since   1.1
      * @see #setSoTimeout(int)
      */
     public synchronized int getSoTimeout() throws SocketException {
@@ -1233,7 +1256,7 @@
         }
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.SO_SNDBUF, new Integer(size));
+        getImpl().setOption(SocketOptions.SO_SNDBUF, size);
     }
 
     /**
@@ -1284,7 +1307,7 @@
      * <ol>
      * <li>For sockets accepted from a ServerSocket, this must be done by calling
      * {@link ServerSocket#setReceiveBufferSize(int)} before the ServerSocket
-     * is bound to a local address.<p></li>
+     * is bound to a local address.</li>
      * <li>For client sockets, setReceiveBufferSize() must be called before
      * connecting the socket to its remote peer.</li></ol>
      * @param size the size to which to set the receive buffer
@@ -1307,7 +1330,7 @@
         }
         if (isClosed())
             throw new SocketException("Socket is closed");
-        getImpl().setOption(SocketOptions.SO_RCVBUF, new Integer(size));
+        getImpl().setOption(SocketOptions.SO_RCVBUF, size);
     }
 
     /**
@@ -1773,6 +1796,97 @@
         /* Not implemented yet */
     }
 
+
+    /**
+     * Sets the value of a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     * @return this Socket
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 9
+     */
+    public <T> Socket setOption(SocketOption<T> name, T value) throws IOException {
+        getImpl().setOption(name, value);
+        return this;
+    }
+
+    /**
+     * Returns the value of a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @throws NullPointerException if name is {@code null}
+     *
+     * @throws SecurityException if a security manager is set and if the socket
+     *         option requires a security permission and if the caller does
+     *         not have the required permission.
+     *         {@link java.net.StandardSocketOptions StandardSocketOptions}
+     *         do not require any security permission.
+     *
+     * @since 9
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T getOption(SocketOption<T> name) throws IOException {
+        return getImpl().getOption(name);
+    }
+
+    private static Set<SocketOption<?>> options;
+    private static boolean optionsSet = false;
+
+    /**
+     * Returns a set of the socket options supported by this socket.
+     *
+     * This method will continue to return the set of options even after
+     * the socket has been closed.
+     *
+     * @return A set of the socket options supported by this socket. This set
+     *         may be empty if the socket's SocketImpl cannot be created.
+     *
+     * @since 9
+     */
+    public Set<SocketOption<?>> supportedOptions() {
+        synchronized (Socket.class) {
+            if (optionsSet) {
+                return options;
+            }
+            try {
+                SocketImpl impl = getImpl();
+                options = Collections.unmodifiableSet(impl.supportedOptions());
+            } catch (IOException e) {
+                options = Collections.emptySet();
+            }
+            optionsSet = true;
+            return options;
+        }
+    }
+
     // Android-added: getFileDescriptor$() method for testing and internal use.
     /**
      * Gets socket's underlying {@link FileDescriptor}.
diff --git a/ojluni/src/main/java/java/net/SocketException.java b/ojluni/src/main/java/java/net/SocketException.java
index 64ae771..679c1dc 100644
--- a/ojluni/src/main/java/java/net/SocketException.java
+++ b/ojluni/src/main/java/java/net/SocketException.java
@@ -32,7 +32,7 @@
  * Thrown to indicate that there is an error creating or accessing a Socket.
  *
  * @author  Jonathan Payne
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class SocketException extends IOException {
diff --git a/ojluni/src/main/java/java/net/SocketImpl.java b/ojluni/src/main/java/java/net/SocketImpl.java
index 51000db..6628db4 100644
--- a/ojluni/src/main/java/java/net/SocketImpl.java
+++ b/ojluni/src/main/java/java/net/SocketImpl.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.FileDescriptor;
+import java.util.Set;
 
 /**
  * The abstract class {@code SocketImpl} is a common superclass
@@ -40,7 +41,7 @@
  * described, without attempting to go through a firewall or proxy.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public abstract class SocketImpl implements SocketOptions {
     /**
@@ -345,7 +346,7 @@
      * latency, and low latency above short connection time, then it could
      * invoke this method with the values {@code (0, 1, 2)}.
      *
-     * By default, this method does nothing, unless it is overridden in a
+     * By default, this method does nothing, unless it is overridden in
      * a sub-class.
      *
      * @param  connectionTime
@@ -369,43 +370,123 @@
         /* Not implemented yet */
     }
 
-    <T> void setOption(SocketOption<T> name, T value) throws IOException {
-        if (name == StandardSocketOptions.SO_KEEPALIVE) {
+    /**
+     * Called to set a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     *
+     * @param value The value of the socket option. A value of {@code null}
+     *              may be valid for some options.
+     *
+     * @throws UnsupportedOperationException if the SocketImpl does not
+     *         support the option
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @since 9
+     */
+    protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
+        if (name == StandardSocketOptions.SO_KEEPALIVE &&
+                (getSocket() != null)) {
             setOption(SocketOptions.SO_KEEPALIVE, value);
-        } else if (name == StandardSocketOptions.SO_SNDBUF) {
+        } else if (name == StandardSocketOptions.SO_SNDBUF &&
+                (getSocket() != null)) {
             setOption(SocketOptions.SO_SNDBUF, value);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             setOption(SocketOptions.SO_RCVBUF, value);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             setOption(SocketOptions.SO_REUSEADDR, value);
-        } else if (name == StandardSocketOptions.SO_LINGER) {
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            setOption(SocketOptions.SO_REUSEPORT, value);
+        } else if (name == StandardSocketOptions.SO_LINGER &&
+                (getSocket() != null)) {
             setOption(SocketOptions.SO_LINGER, value);
         } else if (name == StandardSocketOptions.IP_TOS) {
             setOption(SocketOptions.IP_TOS, value);
-        } else if (name == StandardSocketOptions.TCP_NODELAY) {
+        } else if (name == StandardSocketOptions.TCP_NODELAY &&
+                (getSocket() != null)) {
             setOption(SocketOptions.TCP_NODELAY, value);
         } else {
             throw new UnsupportedOperationException("unsupported option");
         }
     }
 
-    <T> T getOption(SocketOption<T> name) throws IOException {
-        if (name == StandardSocketOptions.SO_KEEPALIVE) {
+    /**
+     * Called to get a socket option.
+     *
+     * @param <T> The type of the socket option value
+     * @param name The socket option
+     *
+     * @return the value of the named option
+     *
+     * @throws UnsupportedOperationException if the SocketImpl does not
+     *         support the option.
+     *
+     * @throws IOException if an I/O error occurs, or if the socket is closed.
+     *
+     * @since 9
+     */
+    @SuppressWarnings("unchecked")
+    protected <T> T getOption(SocketOption<T> name) throws IOException {
+        if (name == StandardSocketOptions.SO_KEEPALIVE &&
+                (getSocket() != null)) {
             return (T)getOption(SocketOptions.SO_KEEPALIVE);
-        } else if (name == StandardSocketOptions.SO_SNDBUF) {
+        } else if (name == StandardSocketOptions.SO_SNDBUF &&
+                (getSocket() != null)) {
             return (T)getOption(SocketOptions.SO_SNDBUF);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             return (T)getOption(SocketOptions.SO_RCVBUF);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             return (T)getOption(SocketOptions.SO_REUSEADDR);
-        } else if (name == StandardSocketOptions.SO_LINGER) {
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            return (T)getOption(SocketOptions.SO_REUSEPORT);
+        } else if (name == StandardSocketOptions.SO_LINGER &&
+                (getSocket() != null)) {
             return (T)getOption(SocketOptions.SO_LINGER);
         } else if (name == StandardSocketOptions.IP_TOS) {
             return (T)getOption(SocketOptions.IP_TOS);
-        } else if (name == StandardSocketOptions.TCP_NODELAY) {
+        } else if (name == StandardSocketOptions.TCP_NODELAY &&
+                (getSocket() != null)) {
             return (T)getOption(SocketOptions.TCP_NODELAY);
         } else {
             throw new UnsupportedOperationException("unsupported option");
         }
     }
+
+    private static final Set<SocketOption<?>> socketOptions;
+
+    private static final Set<SocketOption<?>> serverSocketOptions;
+
+    static {
+        socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE,
+                               StandardSocketOptions.SO_SNDBUF,
+                               StandardSocketOptions.SO_RCVBUF,
+                               StandardSocketOptions.SO_REUSEADDR,
+                               StandardSocketOptions.SO_LINGER,
+                               StandardSocketOptions.IP_TOS,
+                               StandardSocketOptions.TCP_NODELAY);
+
+        serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF,
+                                     StandardSocketOptions.SO_REUSEADDR,
+                                     StandardSocketOptions.IP_TOS);
+    }
+
+    /**
+     * Returns a set of SocketOptions supported by this impl
+     * and by this impl's socket (Socket or ServerSocket)
+     *
+     * @return a Set of SocketOptions
+     *
+     * @since 9
+     */
+    protected Set<SocketOption<?>> supportedOptions() {
+        if (getSocket() != null) {
+            return socketOptions;
+        } else {
+            return serverSocketOptions;
+        }
+    }
 }
diff --git a/ojluni/src/main/java/java/net/SocketImplFactory.java b/ojluni/src/main/java/java/net/SocketImplFactory.java
index 7aa6363..57b40da 100644
--- a/ojluni/src/main/java/java/net/SocketImplFactory.java
+++ b/ojluni/src/main/java/java/net/SocketImplFactory.java
@@ -34,7 +34,7 @@
  * @author  Arthur van Hoff
  * @see     java.net.Socket
  * @see     java.net.ServerSocket
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 interface SocketImplFactory {
diff --git a/ojluni/src/main/java/java/net/SocketInputStream.java b/ojluni/src/main/java/java/net/SocketInputStream.java
index 8d0e0c5..db6faad 100644
--- a/ojluni/src/main/java/java/net/SocketInputStream.java
+++ b/ojluni/src/main/java/java/net/SocketInputStream.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,8 +42,7 @@
  * @author      Jonathan Payne
  * @author      Arthur van Hoff
  */
-class SocketInputStream extends FileInputStream
-{
+class SocketInputStream extends FileInputStream {
     // Android-removed: Android doesn't need to call native init.
     // static {
     //    init();
@@ -166,8 +165,6 @@
                     + " off == " + off + " buffer length == " + b.length);
         }
 
-        boolean gotReset = false;
-
         // acquire file descriptor and do the read
         FileDescriptor fd = impl.acquireFD();
         try {
@@ -178,39 +175,18 @@
                 return n;
             }
         } catch (ConnectionResetException rstExc) {
-            gotReset = true;
+            impl.setConnectionReset();
         } finally {
             impl.releaseFD();
         }
 
         /*
-         * We receive a "connection reset" but there may be bytes still
-         * buffered on the socket
-         */
-        if (gotReset) {
-            impl.setConnectionResetPending();
-            impl.acquireFD();
-            try {
-                n = socketRead(fd, b, off, length, timeout);
-                if (n > 0) {
-                    return n;
-                }
-            } catch (ConnectionResetException rstExc) {
-            } finally {
-                impl.releaseFD();
-            }
-        }
-
-        /*
          * If we get here we are at EOF, the socket has been closed,
          * or the connection has been reset.
          */
         if (impl.isClosedOrPending()) {
             throw new SocketException("Socket closed");
         }
-        if (impl.isConnectionResetPending()) {
-            impl.setConnectionReset();
-        }
         if (impl.isConnectionReset()) {
             throw new SocketException("Connection reset");
         }
diff --git a/ojluni/src/main/java/java/net/SocketOptions.java b/ojluni/src/main/java/java/net/SocketOptions.java
index 7e1b0fc..2e9d28a 100644
--- a/ojluni/src/main/java/java/net/SocketOptions.java
+++ b/ojluni/src/main/java/java/net/SocketOptions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,9 @@
  * DatagramSocketImpl, <B>you won't use these directly.</B> There are
  * type-safe methods to get/set each of these options in Socket, ServerSocket,
  * DatagramSocket and MulticastSocket.
- * <P>
+ *
  * @author David Brown
+ * @since 1.1
  */
 
 
@@ -61,21 +62,21 @@
      * If the requested option is binary, it can be set using this method by
      * a java.lang.Boolean:
      * <BR><PRE>
-     * s.setOption(TCP_NODELAY, new Boolean(true));
+     * s.setOption(TCP_NODELAY, Boolean.TRUE);
      *    // OK - enables TCP_NODELAY, a binary option
      * </PRE>
      * <BR>
-     * Any option can be disabled using this method with a Boolean(false):
+     * Any option can be disabled using this method with a Boolean.FALSE:
      * <BR><PRE>
-     * s.setOption(TCP_NODELAY, new Boolean(false));
+     * s.setOption(TCP_NODELAY, Boolean.FALSE);
      *    // OK - disables TCP_NODELAY
-     * s.setOption(SO_LINGER, new Boolean(false));
+     * s.setOption(SO_LINGER, Boolean.FALSE);
      *    // OK - disables SO_LINGER
      * </PRE>
      * <BR>
      * For an option that has a notion of on and off, and requires
      * a non-boolean parameter, setting its value to anything other than
-     * <I>Boolean(false)</I> implicitly enables it.
+     * <I>Boolean.FALSE</I> implicitly enables it.
      * <BR>
      * Throws SocketException if the option is unrecognized,
      * the socket is closed, or some low-level error occurred
@@ -91,8 +92,8 @@
 
     /**
      * Fetch the value of an option.
-     * Binary options will return java.lang.Boolean(true)
-     * if enabled, java.lang.Boolean(false) if disabled, e.g.:
+     * Binary options will return java.lang.Boolean.TRUE
+     * if enabled, java.lang.Boolean.FALSE if disabled, e.g.:
      * <BR><PRE>
      * SocketImpl s;
      * ...
@@ -105,13 +106,13 @@
      * <P>
      * For options that take a particular type as a parameter,
      * getOption(int) will return the parameter's value, else
-     * it will return java.lang.Boolean(false):
+     * it will return java.lang.Boolean.FALSE:
      * <PRE>
      * Object o = s.getOption(SO_LINGER);
      * if (o instanceof Integer) {
      *     System.out.print("Linger time is " + ((Integer)o).intValue());
      * } else {
-     *   // the true type of o is java.lang.Boolean(false);
+     *   // the true type of o is java.lang.Boolean.FALSE;
      * }
      * </PRE>
      *
@@ -139,7 +140,7 @@
      * @see Socket#getTcpNoDelay
      */
 
-    @Native public final static int TCP_NODELAY = 0x0001;
+    @Native public static final int TCP_NODELAY = 0x0001;
 
     /**
      * Fetch the local address binding of a socket (this option cannot
@@ -160,7 +161,7 @@
      * @see DatagramSocket#getLocalAddress
      */
 
-    @Native public final static int SO_BINDADDR = 0x000F;
+    @Native public static final int SO_BINDADDR = 0x000F;
 
     /** Sets SO_REUSEADDR for a socket.  This is used only for MulticastSockets
      * in java, and it is set by default for MulticastSockets.
@@ -168,7 +169,18 @@
      * Valid for: DatagramSocketImpl
      */
 
-    @Native public final static int SO_REUSEADDR = 0x04;
+    @Native public static final int SO_REUSEADDR = 0x04;
+
+    /** Sets SO_REUSEPORT for a socket. This option enables and disables
+     *  the ability to have multiple sockets listen to the same address
+     *  and port.
+     * <P>
+     * Valid for: SocketImpl, DatagramSocketImpl
+     *
+     * @since 9
+     * @see StandardSocketOptions#SO_REUSEPORT
+     */
+    @Native public static final int SO_REUSEPORT = 0x0E;
 
     /**
      * Sets SO_BROADCAST for a socket. This option enables and disables
@@ -179,7 +191,7 @@
      * @since 1.4
      */
 
-    @Native public final static int SO_BROADCAST = 0x0020;
+    @Native public static final int SO_BROADCAST = 0x0020;
 
     /** Set which outgoing interface on which to send multicast packets.
      * Useful on hosts with multiple network interfaces, where applications
@@ -191,7 +203,7 @@
      * @see MulticastSocket#getInterface()
      */
 
-    @Native public final static int IP_MULTICAST_IF = 0x10;
+    @Native public static final int IP_MULTICAST_IF = 0x10;
 
     /** Same as above. This option is introduced so that the behaviour
      *  with IP_MULTICAST_IF will be kept the same as before, while
@@ -203,7 +215,7 @@
      * @see MulticastSocket#getNetworkInterface()
      * @since 1.4
      */
-    @Native public final static int IP_MULTICAST_IF2 = 0x1f;
+    @Native public static final int IP_MULTICAST_IF2 = 0x1f;
 
     /**
      * This option enables or disables local loopback of multicast datagrams.
@@ -211,7 +223,7 @@
      * @since 1.4
      */
 
-    @Native public final static int IP_MULTICAST_LOOP = 0x12;
+    @Native public static final int IP_MULTICAST_LOOP = 0x12;
 
     /**
      * This option sets the type-of-service or traffic class field
@@ -219,7 +231,7 @@
      * @since 1.4
      */
 
-    @Native public final static int IP_TOS = 0x3;
+    @Native public static final int IP_TOS = 0x3;
 
     /**
      * Specify a linger-on-close timeout.  This option disables/enables
@@ -237,7 +249,7 @@
      * @see Socket#setSoLinger
      * @see Socket#getSoLinger
      */
-    @Native public final static int SO_LINGER = 0x0080;
+    @Native public static final int SO_LINGER = 0x0080;
 
     /** Set a timeout on blocking Socket operations:
      * <PRE>
@@ -258,7 +270,7 @@
      * @see ServerSocket#setSoTimeout
      * @see DatagramSocket#setSoTimeout
      */
-    @Native public final static int SO_TIMEOUT = 0x1006;
+    @Native public static final int SO_TIMEOUT = 0x1006;
 
     /**
      * Set a hint the size of the underlying buffers used by the
@@ -275,7 +287,7 @@
      * @see DatagramSocket#setSendBufferSize
      * @see DatagramSocket#getSendBufferSize
      */
-    @Native public final static int SO_SNDBUF = 0x1001;
+    @Native public static final int SO_SNDBUF = 0x1001;
 
     /**
      * Set a hint the size of the underlying buffers used by the
@@ -293,7 +305,7 @@
      * @see DatagramSocket#setReceiveBufferSize
      * @see DatagramSocket#getReceiveBufferSize
      */
-    @Native public final static int SO_RCVBUF = 0x1002;
+    @Native public static final int SO_RCVBUF = 0x1002;
 
     /**
      * When the keepalive option is set for a TCP socket and no data
@@ -316,7 +328,7 @@
      * @see Socket#setKeepAlive
      * @see Socket#getKeepAlive
      */
-    @Native public final static int SO_KEEPALIVE = 0x0008;
+    @Native public static final int SO_KEEPALIVE = 0x0008;
 
     /**
      * When the OOBINLINE option is set, any TCP urgent data received on
@@ -327,5 +339,5 @@
      * @see Socket#setOOBInline
      * @see Socket#getOOBInline
      */
-    @Native public final static int SO_OOBINLINE = 0x1003;
+    @Native public static final int SO_OOBINLINE = 0x1003;
 }
diff --git a/ojluni/src/main/java/java/net/SocketOutputStream.java b/ojluni/src/main/java/java/net/SocketOutputStream.java
index 9e8e792..e8b23b1 100644
--- a/ojluni/src/main/java/java/net/SocketOutputStream.java
+++ b/ojluni/src/main/java/java/net/SocketOutputStream.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,8 +41,7 @@
  * @author      Jonathan Payne
  * @author      Arthur van Hoff
  */
-class SocketOutputStream extends FileOutputStream
-{
+class SocketOutputStream extends FileOutputStream {
     // Android-removed: Android doesn't need to call native init.
     // static {
     //    init();
@@ -116,10 +115,6 @@
             BlockGuard.getThreadPolicy().onNetwork();
             socketWrite0(fd, b, off, len);
         } catch (SocketException se) {
-            if (se instanceof sun.net.ConnectionResetException) {
-                impl.setConnectionResetPending();
-                se = new SocketException("Connection reset");
-            }
             if (impl.isClosedOrPending()) {
                 throw new SocketException("Socket closed");
             } else {
diff --git a/ojluni/src/main/java/java/net/SocketPermission.java b/ojluni/src/main/java/java/net/SocketPermission.java
index 2195ecc..97346cd 100644
--- a/ojluni/src/main/java/java/net/SocketPermission.java
+++ b/ojluni/src/main/java/java/net/SocketPermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/net/StandardSocketOptions.java b/ojluni/src/main/java/java/net/StandardSocketOptions.java
index 7fdd5f0..ae47845 100644
--- a/ojluni/src/main/java/java/net/StandardSocketOptions.java
+++ b/ojluni/src/main/java/java/net/StandardSocketOptions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -187,6 +187,29 @@
         new StdSocketOption<Boolean>("SO_REUSEADDR", Boolean.class);
 
     /**
+     * Re-use port.
+     *
+     * <p> The value of this socket option is a {@code Boolean} that represents
+     * whether the option is enabled or disabled. The exact semantics of this
+     * socket option are socket type and system dependent.
+     *
+     * <p> In the case of stream-oriented sockets, this socket option usually allows
+     * multiple listening sockets to be bound to both same address
+     * and same port.
+     *
+     * <p> For datagram-oriented sockets the socket option usually allows
+     * multiple UDP sockets to be bound to the same address and port.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Changing the value of this socket option
+     * after the socket is bound has no effect.
+     *
+     * @since 9
+     */
+    public static final SocketOption<Boolean> SO_REUSEPORT =
+        new StdSocketOption<Boolean>("SO_REUSEPORT", Boolean.class);
+
+    /**
      * Linger on close if data is present.
      *
      * <p> The value of this socket option is an {@code Integer} that controls
diff --git a/ojluni/src/main/java/java/net/URISyntaxException.java b/ojluni/src/main/java/java/net/URISyntaxException.java
index 8072c37..17d12bd 100644
--- a/ojluni/src/main/java/java/net/URISyntaxException.java
+++ b/ojluni/src/main/java/java/net/URISyntaxException.java
@@ -121,7 +121,7 @@
      * @return  A string describing the parse error
      */
     public String getMessage() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append(getReason());
         if (index > -1) {
             sb.append(" at index ");
diff --git a/ojluni/src/main/java/java/net/URLDecoder.java b/ojluni/src/main/java/java/net/URLDecoder.java
index 8b14eb8..0d2d431 100644
--- a/ojluni/src/main/java/java/net/URLDecoder.java
+++ b/ojluni/src/main/java/java/net/URLDecoder.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,10 @@
 package java.net;
 
 import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Objects;
 
 /**
  * Utility class for HTML form decoding. This class contains static methods
@@ -107,9 +111,45 @@
     }
 
     /**
-     * Decodes a {@code application/x-www-form-urlencoded} string using a specific
-     * encoding scheme.
-     * The supplied encoding is used to determine
+     * Decodes an {@code application/x-www-form-urlencoded} string using
+     * a specific encoding scheme.
+     *
+     * <p>
+     * This method behaves the same as {@linkplain String decode(String s, Charset charset)}
+     * except that it will {@linkplain java.nio.charset.Charset#forName look up the charset}
+     * using the given encoding name.
+     *
+     * @implNote This implementation will throw an {@link java.lang.IllegalArgumentException}
+     * when illegal strings are encountered.
+     *
+     * @param s the {@code String} to decode
+     * @param enc   The name of a supported
+     *    <a href="../lang/package-summary.html#charenc">character
+     *    encoding</a>.
+     * @return the newly decoded {@code String}
+     * @throws UnsupportedEncodingException
+     *             If character encoding needs to be consulted, but
+     *             named character encoding is not supported
+     * @see URLEncoder#encode(java.lang.String, java.lang.String)
+     * @since 1.4
+     */
+    public static String decode(String s, String enc) throws UnsupportedEncodingException {
+        if (enc.isEmpty()) {
+            throw new UnsupportedEncodingException ("URLDecoder: empty string enc parameter");
+        }
+
+        try {
+            Charset charset = Charset.forName(enc);
+            return decode(s, charset);
+        } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
+            throw new UnsupportedEncodingException(enc);
+        }
+    }
+
+    /**
+     * Decodes an {@code application/x-www-form-urlencoded} string using
+     * a specific {@linkplain java.nio.charset.Charset Charset}.
+     * The supplied charset is used to determine
      * what characters are represented by any consecutive sequences of the
      * form "<i>{@code %xy}</i>".
      * <p>
@@ -119,29 +159,25 @@
      * UTF-8 should be used. Not doing so may introduce
      * incompatibilities.</em>
      *
+     * @implNote This implementation will throw an {@link java.lang.IllegalArgumentException}
+     * when illegal strings are encountered.
+     *
      * @param s the {@code String} to decode
-     * @param enc   The name of a supported
-     *    <a href="../lang/package-summary.html#charenc">character
-     *    encoding</a>.
+     * @param charset the given charset
      * @return the newly decoded {@code String}
-     * @exception  UnsupportedEncodingException
-     *             If character encoding needs to be consulted, but
-     *             named character encoding is not supported
-     * @see URLEncoder#encode(java.lang.String, java.lang.String)
-     * @since 1.4
+     * @throws NullPointerException if {@code s} or {@code charset} is {@code null}
+     * @throws IllegalArgumentException if the implementation encounters illegal
+     * characters
+     * @see URLEncoder#encode(java.lang.String, java.nio.charset.Charset)
+     * @since 10
      */
-    public static String decode(String s, String enc)
-        throws UnsupportedEncodingException{
-
+    public static String decode(String s, Charset charset) {
+        Objects.requireNonNull(charset, "Charset");
         boolean needToChange = false;
         int numChars = s.length();
-        StringBuffer sb = new StringBuffer(numChars > 500 ? numChars / 2 : numChars);
+        StringBuilder sb = new StringBuilder(numChars > 500 ? numChars / 2 : numChars);
         int i = 0;
 
-        if (enc.length() == 0) {
-            throw new UnsupportedEncodingException ("URLDecoder: empty string enc parameter");
-        }
-
         char c;
         byte[] bytes = null;
         while (i < numChars) {
@@ -196,7 +232,7 @@
                         throw new IllegalArgumentException(
                          "URLDecoder: Incomplete trailing escape (%) pattern");
 
-                    sb.append(new String(bytes, 0, pos, enc));
+                    sb.append(new String(bytes, 0, pos, charset));
                 } catch (NumberFormatException e) {
                     throw new IllegalArgumentException(
                     "URLDecoder: Illegal hex characters in escape (%) pattern - "
diff --git a/ojluni/src/main/java/java/net/URLEncoder.java b/ojluni/src/main/java/java/net/URLEncoder.java
index 86377b7..a3cc49d 100644
--- a/ojluni/src/main/java/java/net/URLEncoder.java
+++ b/ojluni/src/main/java/java/net/URLEncoder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,19 +25,13 @@
 
 package java.net;
 
-import java.io.ByteArrayOutputStream;
-import java.io.BufferedWriter;
-import java.io.OutputStreamWriter;
-import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.io.CharArrayWriter;
 import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException ;
 import java.util.BitSet;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetBooleanAction;
+import java.util.Objects;
 import sun.security.action.GetPropertyAction;
 
 /**
@@ -77,7 +71,7 @@
  * character @ is encoded as one byte 40 (hex).
  *
  * @author  Herb Jellinek
- * @since   JDK1.0
+ * @since   1.0
  */
 public class URLEncoder {
     static BitSet dontNeedEncoding;
@@ -140,9 +134,7 @@
         dontNeedEncoding.set('.');
         dontNeedEncoding.set('*');
 
-        dfltEncName = AccessController.doPrivileged(
-            new GetPropertyAction("file.encoding")
-        );
+        dfltEncName = GetPropertyAction.privilegedGetProperty("file.encoding");
     }
 
     /**
@@ -177,44 +169,60 @@
 
     /**
      * Translates a string into {@code application/x-www-form-urlencoded}
-     * format using a specific encoding scheme. This method uses the
-     * supplied encoding scheme to obtain the bytes for unsafe
-     * characters.
+     * format using a specific encoding scheme.
      * <p>
-     * <em><strong>Note:</strong> The <a href=
-     * "http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars">
-     * World Wide Web Consortium Recommendation</a> states that
-     * UTF-8 should be used. Not doing so may introduce
-     * incompatibilities.</em>
+     * This method behaves the same as {@linkplain String encode(String s, Charset charset)}
+     * except that it will {@linkplain java.nio.charset.Charset#forName look up the charset}
+     * using the given encoding name.
      *
      * @param   s   {@code String} to be translated.
      * @param   enc   The name of a supported
      *    <a href="../lang/package-summary.html#charenc">character
      *    encoding</a>.
      * @return  the translated {@code String}.
-     * @exception  UnsupportedEncodingException
+     * @throws  UnsupportedEncodingException
      *             If the named encoding is not supported
      * @see URLDecoder#decode(java.lang.String, java.lang.String)
      * @since 1.4
      */
     public static String encode(String s, String enc)
         throws UnsupportedEncodingException {
-
-        boolean needToChange = false;
-        StringBuffer out = new StringBuffer(s.length());
-        Charset charset;
-        CharArrayWriter charArrayWriter = new CharArrayWriter();
-
-        if (enc == null)
+        if (enc == null) {
             throw new NullPointerException("charsetName");
+        }
 
         try {
-            charset = Charset.forName(enc);
-        } catch (IllegalCharsetNameException e) {
-            throw new UnsupportedEncodingException(enc);
-        } catch (UnsupportedCharsetException e) {
+            Charset charset = Charset.forName(enc);
+            return encode(s, charset);
+        } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
             throw new UnsupportedEncodingException(enc);
         }
+    }
+
+    /**
+     * Translates a string into {@code application/x-www-form-urlencoded}
+     * format using a specific {@linkplain java.nio.charset.Charset Charset}.
+     * This method uses the supplied charset to obtain the bytes for unsafe
+     * characters.
+     * <p>
+     * <em><strong>Note:</strong> The <a href=
+     * "http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars">
+     * World Wide Web Consortium Recommendation</a> states that
+     * UTF-8 should be used. Not doing so may introduce incompatibilities.</em>
+     *
+     * @param   s   {@code String} to be translated.
+     * @param charset the given charset
+     * @return  the translated {@code String}.
+     * @throws NullPointerException if {@code s} or {@code charset} is {@code null}.
+     * @see URLDecoder#decode(java.lang.String, java.nio.charset.Charset)
+     * @since 10
+     */
+    public static String encode(String s, Charset charset) {
+        Objects.requireNonNull(charset, "charset");
+
+        boolean needToChange = false;
+        StringBuilder out = new StringBuilder(s.length());
+        CharArrayWriter charArrayWriter = new CharArrayWriter();
 
         for (int i = 0; i < s.length();) {
             int c = (int) s.charAt(i);
@@ -234,7 +242,7 @@
                     /*
                      * If this character represents the start of a Unicode
                      * surrogate pair, then pass in two characters. It's not
-                     * clear what should be done if a bytes reserved in the
+                     * clear what should be done if a byte reserved in the
                      * surrogate pairs range occurs outside of a legal
                      * surrogate pair. For now, just treat it as if it were
                      * any other character.
diff --git a/ojluni/src/main/java/java/net/URLStreamHandlerFactory.java b/ojluni/src/main/java/java/net/URLStreamHandlerFactory.java
index e46e028..c35af10 100644
--- a/ojluni/src/main/java/java/net/URLStreamHandlerFactory.java
+++ b/ojluni/src/main/java/java/net/URLStreamHandlerFactory.java
@@ -28,14 +28,14 @@
 /**
  * This interface defines a factory for {@code URL} stream
  * protocol handlers.
- * <p>
- * It is used by the {@code URL} class to create a
- * {@code URLStreamHandler} for a specific protocol.
+  *
+ * <p> A URL stream handler factory is used as specified in the
+ * {@linkplain java.net.URL#URL(String,String,int,String) URL constructor}.
  *
  * @author  Arthur van Hoff
  * @see     java.net.URL
  * @see     java.net.URLStreamHandler
- * @since   JDK1.0
+ * @since   1.0
  */
 public interface URLStreamHandlerFactory {
     /**
@@ -44,7 +44,9 @@
      *
      * @param   protocol   the protocol ("{@code ftp}",
      *                     "{@code http}", "{@code nntp}", etc.).
-     * @return  a {@code URLStreamHandler} for the specific protocol.
+     * @return  a {@code URLStreamHandler} for the specific protocol, or {@code
+     *          null} if this factory cannot create a handler for the specific
+     *          protocol
      * @see     java.net.URLStreamHandler
      */
     URLStreamHandler createURLStreamHandler(String protocol);
diff --git a/ojluni/src/main/java/java/net/UnknownHostException.java b/ojluni/src/main/java/java/net/UnknownHostException.java
index 21a9d14..9a9fea5 100644
--- a/ojluni/src/main/java/java/net/UnknownHostException.java
+++ b/ojluni/src/main/java/java/net/UnknownHostException.java
@@ -31,7 +31,7 @@
  * Thrown to indicate that the IP address of a host could not be determined.
  *
  * @author  Jonathan Payne
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class UnknownHostException extends IOException {
@@ -41,10 +41,10 @@
      * Constructs a new {@code UnknownHostException} with the
      * specified detail message.
      *
-     * @param   host   the detail message.
+     * @param   message   the detail message.
      */
-    public UnknownHostException(String host) {
-        super(host);
+    public UnknownHostException(String message) {
+        super(message);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/net/UnknownServiceException.java b/ojluni/src/main/java/java/net/UnknownServiceException.java
index 4eea4a7..7daa8a4 100644
--- a/ojluni/src/main/java/java/net/UnknownServiceException.java
+++ b/ojluni/src/main/java/java/net/UnknownServiceException.java
@@ -34,7 +34,7 @@
  * read-only URL connection.
  *
  * @author  unascribed
- * @since   JDK1.0
+ * @since   1.0
  */
 public class UnknownServiceException extends IOException {
     private static final long serialVersionUID = -4169033248853639508L;
diff --git a/ojluni/src/main/java/java/nio/ByteBuffer.java b/ojluni/src/main/java/java/nio/ByteBuffer.java
index b286cbd..bec1079 100644
--- a/ojluni/src/main/java/java/nio/ByteBuffer.java
+++ b/ojluni/src/main/java/java/nio/ByteBuffer.java
@@ -28,6 +28,8 @@
 
 package java.nio;
 
+import jdk.internal.misc.Unsafe;
+
 import libcore.io.Memory;
 
 import dalvik.annotation.codegen.CovariantReturnType;
@@ -1069,6 +1071,150 @@
         return this;
     }
 
+    /**
+     * Returns the memory address, pointing to the byte at the given index,
+     * modulus the given unit size.
+     *
+     * <p> A return value greater than zero indicates the address of the byte at
+     * the index is misaligned for the unit size, and the value's quantity
+     * indicates how much the index should be rounded up or down to locate a
+     * byte at an aligned address.  Otherwise, a value of {@code 0} indicates
+     * that the address of the byte at the index is aligned for the unit size.
+     *
+     * @apiNote
+     * This method may be utilized to determine if unit size bytes from an
+     * index can be accessed atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater than {@code 8}.
+     *
+     * @param  index
+     *         The index to query for alignment offset, must be non-negative, no
+     *         upper bounds check is performed
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The indexed byte's memory address modulus the unit size
+     *
+     * @throws IllegalArgumentException
+     *         If the index is negative or the unit size is not a power of
+     *         {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable alignment offset
+     *         values for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignedSlice(int)
+     * @since 9
+     */
+    public final int alignmentOffset(int index, int unitSize) {
+        if (index < 0)
+            throw new IllegalArgumentException("Index less than zero: " + index);
+        if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
+            throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
+        if (unitSize > 8 && !isDirect())
+            throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
+
+        // BEGIN Android-changed: Android specific alignment calculation.
+        // return (int) ((address + index) % unitSize);
+        final long baseAddress =
+            isDirect() ? address : (Unsafe.getUnsafe().arrayBaseOffset(byte[].class) + offset);
+
+        final long elementAddress = baseAddress + index;
+        return (int) (elementAddress & (unitSize - 1));
+        // END Android-changed: Android specific alignment calculation.
+    }
+
+    /**
+     * Creates a new byte buffer whose content is a shared and aligned
+     * subsequence of this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position rounded up to the index of the nearest aligned byte for the
+     * given unit size, and end at this buffer's limit rounded down to the index
+     * of the nearest aligned byte for the given unit size.
+     * If rounding results in out-of-bound values then the new buffer's capacity
+     * and limit will be zero.  If rounding is within bounds the following
+     * expressions will be true for a new buffer {@code nb} and unit size
+     * {@code unitSize}:
+     * <pre>{@code
+     * nb.alignmentOffset(0, unitSize) == 0
+     * nb.alignmentOffset(nb.limit(), unitSize) == 0
+     * }</pre>
+     *
+     * <p> Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer or fewer subject to
+     * alignment, its mark will be undefined, and its byte order will be
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+     *
+     * The new buffer will be direct if, and only if, this buffer is direct, and
+     * it will be read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @apiNote
+     * This method may be utilized to create a new buffer where unit size bytes
+     * from index, that is a multiple of the unit size, may be accessed
+     * atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater than {@code 8}.
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The new byte buffer
+     *
+     * @throws IllegalArgumentException
+     *         If the unit size not a power of {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable aligned slices
+     *         for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignmentOffset(int, int)
+     * @see #slice()
+     * @since 9
+     */
+    public final ByteBuffer alignedSlice(int unitSize) {
+        int pos = position();
+        int lim = limit();
+
+        int pos_mod = alignmentOffset(pos, unitSize);
+        int lim_mod = alignmentOffset(lim, unitSize);
+
+        // Round up the position to align with unit size
+        int aligned_pos = (pos_mod > 0)
+            ? pos + (unitSize - pos_mod)
+            : pos;
+
+        // Round down the limit to align with unit size
+        int aligned_lim = lim - lim_mod;
+
+        if (aligned_pos > lim || aligned_lim < pos) {
+            aligned_pos = aligned_lim = pos;
+        }
+
+        return slice(aligned_pos, aligned_lim);
+    }
+
+    abstract ByteBuffer slice(int pos, int lim);
+
     // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
     //
     abstract byte _get(int i);                          // package-private
diff --git a/ojluni/src/main/java/java/nio/ByteBufferAs-X-Buffer.java.template b/ojluni/src/main/java/java/nio/ByteBufferAs-X-Buffer.java.template
new file mode 100644
index 0000000..dfa442e
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/ByteBufferAs-X-Buffer.java.template
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+import jdk.internal.misc.Unsafe;
+
+
+class ByteBufferAs$Type$Buffer$RW$$BO$                  // package-private
+    extends {#if[ro]?ByteBufferAs}$Type$Buffer{#if[ro]?$BO$}
+{
+
+#if[rw]
+
+    protected final ByteBuffer bb;
+
+#end[rw]
+
+    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb) {   // package-private
+#if[rw]
+        super(-1, 0,
+              bb.remaining() >> $LG_BYTES_PER_VALUE$,
+              bb.remaining() >> $LG_BYTES_PER_VALUE$);
+        this.bb = bb;
+        // enforce limit == capacity
+        int cap = this.capacity();
+        this.limit(cap);
+        int pos = this.position();
+        assert (pos <= cap);
+        address = bb.address;
+#else[rw]
+        super(bb);
+#end[rw]
+    }
+
+    ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb,
+                                     int mark, int pos, int lim, int cap,
+                                     long addr)
+    {
+#if[rw]
+        super(mark, pos, lim, cap);
+        this.bb = bb;
+        address = addr;
+        assert address >= bb.address;
+#else[rw]
+        super(bb, mark, pos, lim, cap, addr);
+#end[rw]
+    }
+
+    @Override
+    Object base() {
+        return bb.hb;
+    }
+
+    public $Type$Buffer slice() {
+        int pos = this.position();
+        int lim = this.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        long addr = byteOffset(pos);
+        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb, -1, 0, rem, rem, addr);
+    }
+
+    public $Type$Buffer duplicate() {
+        return new ByteBufferAs$Type$Buffer$RW$$BO$(bb,
+                                                    this.markValue(),
+                                                    this.position(),
+                                                    this.limit(),
+                                                    this.capacity(),
+                                                    address);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new ByteBufferAs$Type$BufferR$BO$(bb,
+                                                 this.markValue(),
+                                                 this.position(),
+                                                 this.limit(),
+                                                 this.capacity(),
+                                                 address);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    private int ix(int i) {
+        int off = (int) (address - bb.address);
+        return (i << $LG_BYTES_PER_VALUE$) + off;
+    }
+
+    protected long byteOffset(long i) {
+        return (i << $LG_BYTES_PER_VALUE$) + address;
+    }
+
+    public $type$ get() {
+        $memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(nextGetIndex()),
+            {#if[boB]?true:false});
+        return $fromBits$(x);
+    }
+
+    public $type$ get(int i) {
+        $memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)),
+            {#if[boB]?true:false});
+        return $fromBits$(x);
+    }
+
+#if[streamableType]
+   $type$ getUnchecked(int i) {
+        $memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(i),
+            {#if[boB]?true:false});
+        return $fromBits$(x);
+    }
+#end[streamableType]
+
+#end[rw]
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        $memtype$ y = $toBits$(x);
+        UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(nextPutIndex()), y,
+            {#if[boB]?true:false});
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        $memtype$ y = $toBits$(x);
+        UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), y,
+            {#if[boB]?true:false});
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+
+        ByteBuffer db = bb.duplicate();
+        db.limit(ix(lim));
+        db.position(ix(0));
+        ByteBuffer sb = db.slice();
+        sb.position(pos << $LG_BYTES_PER_VALUE$);
+        sb.compact();
+        position(rem);
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public boolean isDirect() {
+        return bb.isDirect();
+    }
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+#if[char]
+
+    public String toString(int start, int end) {
+        if ((end > limit()) || (start > end))
+            throw new IndexOutOfBoundsException();
+        try {
+            int len = end - start;
+            char[] ca = new char[len];
+            CharBuffer cb = CharBuffer.wrap(ca);
+            CharBuffer db = this.duplicate();
+            db.position(start);
+            db.limit(end);
+            cb.put(db);
+            return new String(ca);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        pos = (pos <= lim ? pos : lim);
+        int len = lim - pos;
+
+        if ((start < 0) || (end > len) || (start > end))
+            throw new IndexOutOfBoundsException();
+        return new ByteBufferAsCharBuffer$RW$$BO$(bb,
+                                                  -1,
+                                                  pos + start,
+                                                  pos + end,
+                                                  capacity(),
+                                                  address);
+    }
+
+#end[char]
+
+
+    public ByteOrder order() {
+#if[boB]
+        return ByteOrder.BIG_ENDIAN;
+#end[boB]
+#if[boL]
+        return ByteOrder.LITTLE_ENDIAN;
+#end[boL]
+    }
+
+#if[char]
+    ByteOrder charRegionOrder() {
+        return order();
+    }
+#end[char]
+}
\ No newline at end of file
diff --git a/ojluni/src/main/java/java/nio/Direct-X-Buffer-bin.java.template b/ojluni/src/main/java/java/nio/Direct-X-Buffer-bin.java.template
new file mode 100644
index 0000000..8c75116
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/Direct-X-Buffer-bin.java.template
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+class XXX {
+
+#begin
+
+#if[rw]
+
+    private $type$ get$Type$(long a) {
+        try {
+            $memtype$ x = UNSAFE.get$Memtype$Unaligned(null, a, bigEndian);
+            return $fromBits$(x);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    public $type$ get$Type$() {
+        try {
+            return get$Type$(ix(nextGetIndex($BYTES_PER_VALUE$)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    public $type$ get$Type$(int i) {
+        try {
+            return get$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+#end[rw]
+
+    private ByteBuffer put$Type$(long a, $type$ x) {
+#if[rw]
+        try {
+            $memtype$ y = $toBits$(x);
+            UNSAFE.put$Memtype$Unaligned(null, a, y, bigEndian);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ByteBuffer put$Type$($type$ x) {
+#if[rw]
+        put$Type$(ix(nextPutIndex($BYTES_PER_VALUE$)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ByteBuffer put$Type$(int i, $type$ x) {
+#if[rw]
+        put$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)), x);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer as$Type$Buffer() {
+        int off = this.position();
+        int lim = this.limit();
+        assert (off <= lim);
+        int rem = (off <= lim ? lim - off : 0);
+
+        int size = rem >> $LG_BYTES_PER_VALUE$;
+        if (!UNALIGNED && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
+            return (bigEndian
+                    ? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this,
+                                                                       -1,
+                                                                       0,
+                                                                       size,
+                                                                       size,
+                                                                       address + off))
+                    : ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$L(this,
+                                                                       -1,
+                                                                       0,
+                                                                       size,
+                                                                       size,
+                                                                       address + off)));
+        } else {
+            return (nativeByteOrder
+                    ? ($Type$Buffer)(new Direct$Type$Buffer$RW$U(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off))
+                    : ($Type$Buffer)(new Direct$Type$Buffer$RW$S(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 off)));
+        }
+    }
+
+#end
+
+}
\ No newline at end of file
diff --git a/ojluni/src/main/java/java/nio/Direct-X-Buffer.java.template b/ojluni/src/main/java/java/nio/Direct-X-Buffer.java.template
new file mode 100644
index 0000000..7f7e0f1
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/Direct-X-Buffer.java.template
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+import java.io.FileDescriptor;
+import java.lang.ref.Reference;
+import jdk.internal.misc.VM;
+import jdk.internal.ref.Cleaner;
+import sun.nio.ch.DirectBuffer;
+
+
+class Direct$Type$Buffer$RW$$BO$
+#if[rw]
+    extends {#if[byte]?Mapped$Type$Buffer:$Type$Buffer}
+#else[rw]
+    extends Direct$Type$Buffer$BO$
+#end[rw]
+    implements DirectBuffer
+{
+
+#if[rw]
+
+    // Cached array base offset
+    private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
+
+    // Cached unaligned-access capability
+    protected static final boolean UNALIGNED = Bits.unaligned();
+
+    // Base address, used in all indexing calculations
+    // NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
+    //    protected long address;
+
+    // An object attached to this buffer. If this buffer is a view of another
+    // buffer then we use this field to keep a reference to that buffer to
+    // ensure that its memory isn't freed before we are done with it.
+    private final Object att;
+
+    public Object attachment() {
+        return att;
+    }
+
+#if[byte]
+
+    private static class Deallocator
+        implements Runnable
+    {
+
+        private long address;
+        private long size;
+        private int capacity;
+
+        private Deallocator(long address, long size, int capacity) {
+            assert (address != 0);
+            this.address = address;
+            this.size = size;
+            this.capacity = capacity;
+        }
+
+        public void run() {
+            if (address == 0) {
+                // Paranoia
+                return;
+            }
+            UNSAFE.freeMemory(address);
+            address = 0;
+            Bits.unreserveMemory(size, capacity);
+        }
+
+    }
+
+    private final Cleaner cleaner;
+
+    public Cleaner cleaner() { return cleaner; }
+
+#else[byte]
+
+    public Cleaner cleaner() { return null; }
+
+#end[byte]
+
+#end[rw]
+
+#if[byte]
+
+    // Primary constructor
+    //
+    Direct$Type$Buffer$RW$(int cap) {                   // package-private
+#if[rw]
+        super(-1, 0, cap, cap);
+        boolean pa = VM.isDirectMemoryPageAligned();
+        int ps = Bits.pageSize();
+        long size = Math.max(1L, (long)cap + (pa ? ps : 0));
+        Bits.reserveMemory(size, cap);
+
+        long base = 0;
+        try {
+            base = UNSAFE.allocateMemory(size);
+        } catch (OutOfMemoryError x) {
+            Bits.unreserveMemory(size, cap);
+            throw x;
+        }
+        UNSAFE.setMemory(base, size, (byte) 0);
+        if (pa && (base % ps != 0)) {
+            // Round up to page boundary
+            address = base + ps - (base & (ps - 1));
+        } else {
+            address = base;
+        }
+        cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
+        att = null;
+#else[rw]
+        super(cap);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+#if[rw]
+
+    // Invoked to construct a direct ByteBuffer referring to the block of
+    // memory. A given arbitrary object may also be attached to the buffer.
+    //
+    Direct$Type$Buffer(long addr, int cap, Object ob) {
+        super(-1, 0, cap, cap);
+        address = addr;
+        cleaner = null;
+        att = ob;
+    }
+
+
+    // Invoked only by JNI: NewDirectByteBuffer(void*, long)
+    //
+    private Direct$Type$Buffer(long addr, int cap) {
+        super(-1, 0, cap, cap);
+        address = addr;
+        cleaner = null;
+        att = null;
+    }
+
+#end[rw]
+
+    // For memory-mapped buffers -- invoked by FileChannelImpl via reflection
+    //
+    protected Direct$Type$Buffer$RW$(int cap, long addr,
+                                     FileDescriptor fd,
+                                     Runnable unmapper)
+    {
+#if[rw]
+        super(-1, 0, cap, cap, fd);
+        address = addr;
+        cleaner = Cleaner.create(this, unmapper);
+        att = null;
+#else[rw]
+        super(cap, addr, fd, unmapper);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+#end[byte]
+
+    // For duplicates and slices
+    //
+    Direct$Type$Buffer$RW$$BO$(DirectBuffer db,         // package-private
+                               int mark, int pos, int lim, int cap,
+                               int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap);
+        address = db.address() + off;
+#if[byte]
+        cleaner = null;
+#end[byte]
+        att = db;
+#else[rw]
+        super(db, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    @Override
+    Object base() {
+        return null;
+    }
+
+    public $Type$Buffer slice() {
+        int pos = this.position();
+        int lim = this.limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        int off = (pos << $LG_BYTES_PER_VALUE$);
+        assert (off >= 0);
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
+    }
+
+#if[byte]
+    public $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
+    }
+#end[byte]
+
+    public $Type$Buffer duplicate() {
+        return new Direct$Type$Buffer$RW$$BO$(this,
+                                              this.markValue(),
+                                              this.position(),
+                                              this.limit(),
+                                              this.capacity(),
+                                              0);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new Direct$Type$BufferR$BO$(this,
+                                           this.markValue(),
+                                           this.position(),
+                                           this.limit(),
+                                           this.capacity(),
+                                           0);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    public long address() {
+        return address;
+    }
+
+    private long ix(int i) {
+        return address + ((long)i << $LG_BYTES_PER_VALUE$);
+    }
+
+    public $type$ get() {
+        try {
+            return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex()))));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+    public $type$ get(int i) {
+        try {
+            return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i)))));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+
+#if[streamableType]
+    $type$ getUnchecked(int i) {
+        try {
+            return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i))));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+    }
+#end[streamableType]
+
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+#if[rw]
+        if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, dst.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferUnderflowException();
+
+            long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
+            try {
+#if[!byte]
+                if (order() != ByteOrder.nativeOrder())
+                    UNSAFE.copySwapMemory(null,
+                                          ix(pos),
+                                          dst,
+                                          dstOffset,
+                                          (long)length << $LG_BYTES_PER_VALUE$,
+                                          (long)1 << $LG_BYTES_PER_VALUE$);
+                else
+#end[!byte]
+                    UNSAFE.copyMemory(null,
+                                      ix(pos),
+                                      dst,
+                                      dstOffset,
+                                      (long)length << $LG_BYTES_PER_VALUE$);
+            } finally {
+                Reference.reachabilityFence(this);
+            }
+            position(pos + length);
+        } else {
+            super.get(dst, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+#end[rw]
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        try {
+            UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        try {
+            UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($Type$Buffer src) {
+#if[rw]
+        if (src instanceof Direct$Type$Buffer$BO$) {
+            if (src == this)
+                throw createSameBufferException();
+            Direct$Type$Buffer$RW$$BO$ sb = (Direct$Type$Buffer$RW$$BO$)src;
+
+            int spos = sb.position();
+            int slim = sb.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+
+            if (srem > rem)
+                throw new BufferOverflowException();
+            try {
+                UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
+            } finally {
+                Reference.reachabilityFence(sb);
+                Reference.reachabilityFence(this);
+            }
+            sb.position(spos + srem);
+            position(pos + srem);
+        } else if (src.hb != null) {
+
+            int spos = src.position();
+            int slim = src.limit();
+            assert (spos <= slim);
+            int srem = (spos <= slim ? slim - spos : 0);
+
+            put(src.hb, src.offset + spos, srem);
+            src.position(spos + srem);
+
+        } else {
+            super.put(src);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+#if[rw]
+        if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
+            checkBounds(offset, length, src.length);
+            int pos = position();
+            int lim = limit();
+            assert (pos <= lim);
+            int rem = (pos <= lim ? lim - pos : 0);
+            if (length > rem)
+                throw new BufferOverflowException();
+
+            long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
+            try {
+#if[!byte]
+                if (order() != ByteOrder.nativeOrder())
+                    UNSAFE.copySwapMemory(src,
+                                          srcOffset,
+                                          null,
+                                          ix(pos),
+                                          (long)length << $LG_BYTES_PER_VALUE$,
+                                          (long)1 << $LG_BYTES_PER_VALUE$);
+                else
+#end[!byte]
+                    UNSAFE.copyMemory(src,
+                                      srcOffset,
+                                      null,
+                                      ix(pos),
+                                      (long)length << $LG_BYTES_PER_VALUE$);
+            } finally {
+                Reference.reachabilityFence(this);
+            }
+            position(pos + length);
+        } else {
+            super.put(src, offset, length);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        try {
+            UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
+        position(rem);
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public boolean isDirect() {
+        return true;
+    }
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+
+#if[char]
+
+    public String toString(int start, int end) {
+        if ((end > limit()) || (start > end))
+            throw new IndexOutOfBoundsException();
+        try {
+            int len = end - start;
+            char[] ca = new char[len];
+            CharBuffer cb = CharBuffer.wrap(ca);
+            CharBuffer db = this.duplicate();
+            db.position(start);
+            db.limit(end);
+            cb.put(db);
+            return new String(ca);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        int pos = position();
+        int lim = limit();
+        assert (pos <= lim);
+        pos = (pos <= lim ? pos : lim);
+        int len = lim - pos;
+
+        if ((start < 0) || (end > len) || (start > end))
+            throw new IndexOutOfBoundsException();
+        return new DirectCharBuffer$RW$$BO$(this,
+                                            -1,
+                                            pos + start,
+                                            pos + end,
+                                            capacity(),
+                                            offset);
+    }
+
+#end[char]
+
+
+
+#if[!byte]
+
+    public ByteOrder order() {
+#if[boS]
+        return ((ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boS]
+#if[boU]
+        return ((ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN)
+                ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN);
+#end[boU]
+    }
+
+#end[!byte]
+
+#if[char]
+    ByteOrder charRegionOrder() {
+        return order();
+    }
+#end[char]
+
+
+#if[byte]
+    // #BIN
+    //
+    // Binary-data access methods  for short, char, int, long, float,
+    // and double will be inserted here
+
+#end[byte]
+
+}
\ No newline at end of file
diff --git a/ojluni/src/main/java/java/nio/DirectByteBuffer.java b/ojluni/src/main/java/java/nio/DirectByteBuffer.java
index 3e06011..7d883a3 100644
--- a/ojluni/src/main/java/java/nio/DirectByteBuffer.java
+++ b/ojluni/src/main/java/java/nio/DirectByteBuffer.java
@@ -167,6 +167,18 @@
         return new DirectByteBuffer(memoryRef, -1, 0, rem, rem, off, isReadOnly);
     }
 
+    ByteBuffer slice(int pos, int lim) {
+        if (!memoryRef.isAccessible) {
+            throw new IllegalStateException("buffer is inaccessible");
+        }
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = (pos <= lim ? lim - pos : 0);
+        int off = pos + offset;
+        assert (off >= 0);
+        return new DirectByteBuffer(memoryRef, -1, 0, rem, rem, off, isReadOnly);
+    }
+
     @Override
     public final ByteBuffer duplicate() {
         if (memoryRef.isFreed) {
diff --git a/ojluni/src/main/java/java/nio/Heap-X-Buffer.java.template b/ojluni/src/main/java/java/nio/Heap-X-Buffer.java.template
new file mode 100644
index 0000000..6304292
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/Heap-X-Buffer.java.template
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+/**
+#if[rw]
+ * A read/write Heap$Type$Buffer.
+#else[rw]
+ * A read-only Heap$Type$Buffer.  This class extends the corresponding
+ * read/write class, overriding the mutation methods to throw a {@link
+ * ReadOnlyBufferException} and overriding the view-buffer methods to return an
+ * instance of this class rather than of the superclass.
+#end[rw]
+ */
+
+class Heap$Type$Buffer$RW$
+    extends {#if[ro]?Heap}$Type$Buffer
+{
+    // Cached array base offset
+    private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
+
+    // Cached array base offset
+    private static final long ARRAY_INDEX_SCALE = UNSAFE.arrayIndexScale($type$[].class);
+
+    // For speed these fields are actually declared in X-Buffer;
+    // these declarations are here as documentation
+    /*
+#if[rw]
+    protected final $type$[] hb;
+    protected final int offset;
+#end[rw]
+    */
+
+    Heap$Type$Buffer$RW$(int cap, int lim) {            // package-private
+#if[rw]
+        super(-1, 0, lim, cap, new $type$[cap], 0);
+        /*
+        hb = new $type$[cap];
+        offset = 0;
+        */
+        this.address = ARRAY_BASE_OFFSET;
+#else[rw]
+        super(cap, lim);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
+#if[rw]
+        super(-1, off, off + len, buf.length, buf, 0);
+        /*
+        hb = buf;
+        offset = 0;
+        */
+        this.address = ARRAY_BASE_OFFSET;
+#else[rw]
+        super(buf, off, len);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    protected Heap$Type$Buffer$RW$($type$[] buf,
+                                   int mark, int pos, int lim, int cap,
+                                   int off)
+    {
+#if[rw]
+        super(mark, pos, lim, cap, buf, off);
+        /*
+        hb = buf;
+        offset = off;
+        */
+        this.address = ARRAY_BASE_OFFSET + off * ARRAY_INDEX_SCALE;
+#else[rw]
+        super(buf, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
+#end[rw]
+    }
+
+    public $Type$Buffer slice() {
+        return new Heap$Type$Buffer$RW$(hb,
+                                        -1,
+                                        0,
+                                        this.remaining(),
+                                        this.remaining(),
+                                        this.position() + offset);
+    }
+
+#if[byte]
+    $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Heap$Type$Buffer$RW$(hb,
+                                        -1,
+                                        0,
+                                        rem,
+                                        rem,
+                                        pos + offset);
+    }
+#end[byte]
+
+    public $Type$Buffer duplicate() {
+        return new Heap$Type$Buffer$RW$(hb,
+                                        this.markValue(),
+                                        this.position(),
+                                        this.limit(),
+                                        this.capacity(),
+                                        offset);
+    }
+
+    public $Type$Buffer asReadOnlyBuffer() {
+#if[rw]
+        return new Heap$Type$BufferR(hb,
+                                     this.markValue(),
+                                     this.position(),
+                                     this.limit(),
+                                     this.capacity(),
+                                     offset);
+#else[rw]
+        return duplicate();
+#end[rw]
+    }
+
+#if[rw]
+
+    protected int ix(int i) {
+        return i + offset;
+    }
+
+#if[byte]
+    private long byteOffset(long i) {
+        return address + i;
+    }
+#end[byte]
+
+    public $type$ get() {
+        return hb[ix(nextGetIndex())];
+    }
+
+    public $type$ get(int i) {
+        return hb[ix(checkIndex(i))];
+    }
+
+#if[streamableType]
+    $type$ getUnchecked(int i) {
+	return hb[ix(i)];
+    }
+#end[streamableType]
+
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+        checkBounds(offset, length, dst.length);
+        if (length > remaining())
+            throw new BufferUnderflowException();
+        System.arraycopy(hb, ix(position()), dst, offset, length);
+        position(position() + length);
+        return this;
+    }
+
+    public boolean isDirect() {
+        return false;
+    }
+
+#end[rw]
+
+    public boolean isReadOnly() {
+        return {#if[rw]?false:true};
+    }
+
+    public $Type$Buffer put($type$ x) {
+#if[rw]
+        hb[ix(nextPutIndex())] = x;
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put(int i, $type$ x) {
+#if[rw]
+        hb[ix(checkIndex(i))] = x;
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+#if[rw]
+        checkBounds(offset, length, src.length);
+        if (length > remaining())
+            throw new BufferOverflowException();
+        System.arraycopy(src, offset, hb, ix(position()), length);
+        position(position() + length);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer put($Type$Buffer src) {
+#if[rw]
+        if (src instanceof Heap$Type$Buffer) {
+            if (src == this)
+                throw createSameBufferException();
+            Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
+            int n = sb.remaining();
+            if (n > remaining())
+                throw new BufferOverflowException();
+            System.arraycopy(sb.hb, sb.ix(sb.position()),
+                             hb, ix(position()), n);
+            sb.position(sb.position() + n);
+            position(position() + n);
+        } else if (src.isDirect()) {
+            int n = src.remaining();
+            if (n > remaining())
+                throw new BufferOverflowException();
+            src.get(hb, ix(position()), n);
+            position(position() + n);
+        } else {
+            super.put(src);
+        }
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer compact() {
+#if[rw]
+        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
+        position(remaining());
+        limit(capacity());
+        discardMark();
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+
+
+#if[byte]
+
+    byte _get(int i) {                          // package-private
+        return hb[i];
+    }
+
+    void _put(int i, byte b) {                  // package-private
+#if[rw]
+        hb[i] = b;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    // char
+
+#if[rw]
+
+    public char getChar() {
+        return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
+    }
+
+    public char getChar(int i) {
+        return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putChar(char x) {
+#if[rw]
+        UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putChar(int i, char x) {
+#if[rw]
+        UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public CharBuffer asCharBuffer() {
+        int size = this.remaining() >> 1;
+        long addr = address + position();
+        return (bigEndian
+                ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               addr))
+                : (CharBuffer)(new ByteBufferAsCharBuffer$RW$L(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               addr)));
+    }
+
+
+    // short
+
+#if[rw]
+
+    public short getShort() {
+        return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
+    }
+
+    public short getShort(int i) {
+        return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putShort(short x) {
+#if[rw]
+        UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putShort(int i, short x) {
+#if[rw]
+        UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public ShortBuffer asShortBuffer() {
+        int size = this.remaining() >> 1;
+        long addr = address + position();
+        return (bigEndian
+                ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 addr))
+                : (ShortBuffer)(new ByteBufferAsShortBuffer$RW$L(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 addr)));
+    }
+
+
+    // int
+
+#if[rw]
+
+    public int getInt() {
+        return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
+    }
+
+    public int getInt(int i) {
+        return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putInt(int x) {
+#if[rw]
+        UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putInt(int i, int x) {
+#if[rw]
+        UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public IntBuffer asIntBuffer() {
+        int size = this.remaining() >> 2;
+        long addr = address + position();
+        return (bigEndian
+                ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
+                                                             -1,
+                                                             0,
+                                                             size,
+                                                             size,
+                                                             addr))
+                : (IntBuffer)(new ByteBufferAsIntBuffer$RW$L(this,
+                                                             -1,
+                                                             0,
+                                                             size,
+                                                             size,
+                                                             addr)));
+    }
+
+
+    // long
+
+#if[rw]
+
+    public long getLong() {
+        return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
+    }
+
+    public long getLong(int i) {
+        return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putLong(long x) {
+#if[rw]
+        UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putLong(int i, long x) {
+#if[rw]
+        UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public LongBuffer asLongBuffer() {
+        int size = this.remaining() >> 3;
+        long addr = address + position();
+        return (bigEndian
+                ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               addr))
+                : (LongBuffer)(new ByteBufferAsLongBuffer$RW$L(this,
+                                                               -1,
+                                                               0,
+                                                               size,
+                                                               size,
+                                                               addr)));
+    }
+
+
+    // float
+
+#if[rw]
+
+    public float getFloat() {
+        int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
+        return Float.intBitsToFloat(x);
+    }
+
+    public float getFloat(int i) {
+        int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
+        return Float.intBitsToFloat(x);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putFloat(float x) {
+#if[rw]
+        int y = Float.floatToRawIntBits(x);
+        UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putFloat(int i, float x) {
+#if[rw]
+        int y = Float.floatToRawIntBits(x);
+        UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public FloatBuffer asFloatBuffer() {
+        int size = this.remaining() >> 2;
+        long addr = address + position();
+        return (bigEndian
+                ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 addr))
+                : (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$L(this,
+                                                                 -1,
+                                                                 0,
+                                                                 size,
+                                                                 size,
+                                                                 addr)));
+    }
+
+
+    // double
+
+#if[rw]
+
+    public double getDouble() {
+        long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
+        return Double.longBitsToDouble(x);
+    }
+
+    public double getDouble(int i) {
+        long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
+        return Double.longBitsToDouble(x);
+    }
+
+#end[rw]
+
+    public $Type$Buffer putDouble(double x) {
+#if[rw]
+        long y = Double.doubleToRawLongBits(x);
+        UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public $Type$Buffer putDouble(int i, double x) {
+#if[rw]
+        long y = Double.doubleToRawLongBits(x);
+        UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
+        return this;
+#else[rw]
+        throw new ReadOnlyBufferException();
+#end[rw]
+    }
+
+    public DoubleBuffer asDoubleBuffer() {
+        int size = this.remaining() >> 3;
+        long addr = address + position();
+        return (bigEndian
+                ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
+                                                                   -1,
+                                                                   0,
+                                                                   size,
+                                                                   size,
+                                                                   addr))
+                : (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$L(this,
+                                                                   -1,
+                                                                   0,
+                                                                   size,
+                                                                   size,
+                                                                   addr)));
+    }
+
+
+#end[byte]
+
+
+#if[char]
+
+    String toString(int start, int end) {               // package-private
+        try {
+            return new String(hb, start + offset, end - start);
+        } catch (StringIndexOutOfBoundsException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+
+    // --- Methods to support CharSequence ---
+
+    public CharBuffer subSequence(int start, int end) {
+        if ((start < 0)
+            || (end > length())
+            || (start > end))
+            throw new IndexOutOfBoundsException();
+        int pos = position();
+        return new HeapCharBuffer$RW$(hb,
+                                      -1,
+                                      pos + start,
+                                      pos + end,
+                                      capacity(),
+                                      offset);
+    }
+
+#end[char]
+
+
+#if[!byte]
+
+    public ByteOrder order() {
+        return ByteOrder.nativeOrder();
+    }
+#end[!byte]
+#if[char]
+
+    ByteOrder charRegionOrder() {
+        return order();
+    }
+#end[char]
+}
\ No newline at end of file
diff --git a/ojluni/src/main/java/java/nio/HeapByteBuffer.java b/ojluni/src/main/java/java/nio/HeapByteBuffer.java
index 4666638..b9d332b 100644
--- a/ojluni/src/main/java/java/nio/HeapByteBuffer.java
+++ b/ojluni/src/main/java/java/nio/HeapByteBuffer.java
@@ -81,6 +81,19 @@
                 isReadOnly);
     }
 
+    ByteBuffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new HeapByteBuffer(hb,
+                                  -1,
+                                  0,
+                                  rem,
+                                  rem,
+                                  pos + offset,
+                                  isReadOnly);
+    }
+
     @Override
     public ByteBuffer duplicate() {
         return new HeapByteBuffer(hb,
diff --git a/ojluni/src/main/java/java/nio/X-Buffer-bin.java.template b/ojluni/src/main/java/java/nio/X-Buffer-bin.java.template
new file mode 100644
index 0000000..490f165
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/X-Buffer-bin.java.template
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+class XXX {
+
+#begin
+
+    /**
+     * Relative <i>get</i> method for reading $a$ $type$ value.
+     *
+     * <p> Reads the next $nbytes$ bytes at this buffer's current position,
+     * composing them into $a$ $type$ value according to the current byte order,
+     * and then increments the position by $nbytes$.  </p>
+     *
+     * @return  The $type$ value at the buffer's current position
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than $nbytes$ bytes
+     *          remaining in this buffer
+     */
+    public abstract $type$ get$Type$();
+
+    /**
+     * Relative <i>put</i> method for writing $a$ $type$
+     * value&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
+     * current byte order, into this buffer at the current position, and then
+     * increments the position by $nbytes$.  </p>
+     *
+     * @param  value
+     *         The $type$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there are fewer than $nbytes$ bytes
+     *          remaining in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract ByteBuffer put$Type$($type$ value);
+
+    /**
+     * Absolute <i>get</i> method for reading $a$ $type$ value.
+     *
+     * <p> Reads $nbytes$ bytes at the given index, composing them into a
+     * $type$ value according to the current byte order.  </p>
+     *
+     * @param  index
+     *         The index from which the bytes will be read
+     *
+     * @return  The $type$ value at the given index
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code index} is negative
+     *          or not smaller than the buffer's limit,
+     *          minus $nbytesButOne$
+     */
+    public abstract $type$ get$Type$(int index);
+
+    /**
+     * Absolute <i>put</i> method for writing $a$ $type$
+     * value&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes $nbytes$ bytes containing the given $type$ value, in the
+     * current byte order, into this buffer at the given index.  </p>
+     *
+     * @param  index
+     *         The index at which the bytes will be written
+     *
+     * @param  value
+     *         The $type$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code index} is negative
+     *          or not smaller than the buffer's limit,
+     *          minus $nbytesButOne$
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract ByteBuffer put$Type$(int index, $type$ value);
+
+    /**
+     * Creates a view of this byte buffer as $a$ $type$ buffer.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer divided by
+     * $nbytes$, its mark will be undefined, and its byte order will be that
+     * of the byte buffer at the moment the view is created.  The new buffer
+     * will be direct if, and only if, this buffer is direct, and it will be
+     * read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @return  A new $type$ buffer
+     */
+    public abstract $Type$Buffer as$Type$Buffer();
+
+#end
+
+}
\ No newline at end of file
diff --git a/ojluni/src/main/java/java/nio/X-Buffer.java.template b/ojluni/src/main/java/java/nio/X-Buffer.java.template
new file mode 100644
index 0000000..888e5fa
--- /dev/null
+++ b/ojluni/src/main/java/java/nio/X-Buffer.java.template
@@ -0,0 +1,1803 @@
+/*
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#warn This file is preprocessed before being compiled
+
+package java.nio;
+
+#if[char]
+import java.io.IOException;
+#end[char]
+#if[streamableType]
+import java.util.Spliterator;
+import java.util.stream.StreamSupport;
+import java.util.stream.$Streamtype$Stream;
+#end[streamableType]
+
+import jdk.internal.util.ArraysSupport;
+
+/**
+ * $A$ $type$ buffer.
+ *
+ * <p> This class defines {#if[byte]?six:four} categories of operations upon
+ * $type$ buffers:
+ *
+ * <ul>
+ *
+ *   <li><p> Absolute and relative {@link #get() <i>get</i>} and
+ *   {@link #put($type$) <i>put</i>} methods that read and write
+ *   single $type$s; </p></li>
+ *
+ *   <li><p> Relative {@link #get($type$[]) <i>bulk get</i>}
+ *   methods that transfer contiguous sequences of $type$s from this buffer
+ *   into an array; {#if[!byte]?and}</p></li>
+ *
+ *   <li><p> Relative {@link #put($type$[]) <i>bulk put</i>}
+ *   methods that transfer contiguous sequences of $type$s from $a$
+ *   $type$ array{#if[char]?,&#32;a&#32;string,} or some other $type$
+ *   buffer into this buffer;{#if[!byte]?&#32;and} </p></li>
+ *
+#if[byte]
+ *
+ *   <li><p> Absolute and relative {@link #getChar() <i>get</i>}
+ *   and {@link #putChar(char) <i>put</i>} methods that read and
+ *   write values of other primitive types, translating them to and from
+ *   sequences of bytes in a particular byte order; </p></li>
+ *
+ *   <li><p> Methods for creating <i><a href="#views">view buffers</a></i>,
+ *   which allow a byte buffer to be viewed as a buffer containing values of
+ *   some other primitive type; and </p></li>
+ *
+#end[byte]
+ *
+ *   <li><p> A method for {@link #compact compacting}
+ *   $a$ $type$ buffer.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> $Type$ buffers can be created either by {@link #allocate
+ * <i>allocation</i>}, which allocates space for the buffer's
+ *
+#if[byte]
+ *
+ * content, or by {@link #wrap($type$[]) <i>wrapping</i>} an
+ * existing $type$ array {#if[char]?or&#32;string} into a buffer.
+ *
+#else[byte]
+ *
+ * content, by {@link #wrap($type$[]) <i>wrapping</i>} an existing
+ * $type$ array {#if[char]?or&#32;string} into a buffer, or by creating a
+ * <a href="ByteBuffer.html#views"><i>view</i></a> of an existing byte buffer.
+ *
+#end[byte]
+ *
+#if[byte]
+ *
+ * <a id="direct"></a>
+ * <h2> Direct <i>vs.</i> non-direct buffers </h2>
+ *
+ * <p> A byte buffer is either <i>direct</i> or <i>non-direct</i>.  Given a
+ * direct byte buffer, the Java virtual machine will make a best effort to
+ * perform native I/O operations directly upon it.  That is, it will attempt to
+ * avoid copying the buffer's content to (or from) an intermediate buffer
+ * before (or after) each invocation of one of the underlying operating
+ * system's native I/O operations.
+ *
+ * <p> A direct byte buffer may be created by invoking the {@link
+ * #allocateDirect(int) allocateDirect} factory method of this class.  The
+ * buffers returned by this method typically have somewhat higher allocation
+ * and deallocation costs than non-direct buffers.  The contents of direct
+ * buffers may reside outside of the normal garbage-collected heap, and so
+ * their impact upon the memory footprint of an application might not be
+ * obvious.  It is therefore recommended that direct buffers be allocated
+ * primarily for large, long-lived buffers that are subject to the underlying
+ * system's native I/O operations.  In general it is best to allocate direct
+ * buffers only when they yield a measureable gain in program performance.
+ *
+ * <p> A direct byte buffer may also be created by {@link
+ * java.nio.channels.FileChannel#map mapping} a region of a file
+ * directly into memory.  An implementation of the Java platform may optionally
+ * support the creation of direct byte buffers from native code via JNI.  If an
+ * instance of one of these kinds of buffers refers to an inaccessible region
+ * of memory then an attempt to access that region will not change the buffer's
+ * content and will cause an unspecified exception to be thrown either at the
+ * time of the access or at some later time.
+ *
+ * <p> Whether a byte buffer is direct or non-direct may be determined by
+ * invoking its {@link #isDirect isDirect} method.  This method is provided so
+ * that explicit buffer management can be done in performance-critical code.
+ *
+ *
+ * <a id="bin"></a>
+ * <h2> Access to binary data </h2>
+ *
+ * <p> This class defines methods for reading and writing values of all other
+ * primitive types, except {@code boolean}.  Primitive values are translated
+ * to (or from) sequences of bytes according to the buffer's current byte
+ * order, which may be retrieved and modified via the {@link #order order}
+ * methods.  Specific byte orders are represented by instances of the {@link
+ * ByteOrder} class.  The initial order of a byte buffer is always {@link
+ * ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+ *
+ * <p> For access to heterogeneous binary data, that is, sequences of values of
+ * different types, this class defines a family of absolute and relative
+ * <i>get</i> and <i>put</i> methods for each type.  For 32-bit floating-point
+ * values, for example, this class defines:
+ *
+ * <blockquote><pre>
+ * float  {@link #getFloat()}
+ * float  {@link #getFloat(int) getFloat(int index)}
+ *  void  {@link #putFloat(float) putFloat(float f)}
+ *  void  {@link #putFloat(int,float) putFloat(int index, float f)}</pre></blockquote>
+ *
+ * <p> Corresponding methods are defined for the types {@code char,
+ * short, int, long}, and {@code double}.  The index
+ * parameters of the absolute <i>get</i> and <i>put</i> methods are in terms of
+ * bytes rather than of the type being read or written.
+ *
+ * <a id="views"></a>
+ *
+ * <p> For access to homogeneous binary data, that is, sequences of values of
+ * the same type, this class defines methods that can create <i>views</i> of a
+ * given byte buffer.  A <i>view buffer</i> is simply another buffer whose
+ * content is backed by the byte buffer.  Changes to the byte buffer's content
+ * will be visible in the view buffer, and vice versa; the two buffers'
+ * position, limit, and mark values are independent.  The {@link
+ * #asFloatBuffer() asFloatBuffer} method, for example, creates an instance of
+ * the {@link FloatBuffer} class that is backed by the byte buffer upon which
+ * the method is invoked.  Corresponding view-creation methods are defined for
+ * the types {@code char, short, int, long}, and {@code double}.
+ *
+ * <p> View buffers have three important advantages over the families of
+ * type-specific <i>get</i> and <i>put</i> methods described above:
+ *
+ * <ul>
+ *
+ *   <li><p> A view buffer is indexed not in terms of bytes but rather in terms
+ *   of the type-specific size of its values;  </p></li>
+ *
+ *   <li><p> A view buffer provides relative bulk <i>get</i> and <i>put</i>
+ *   methods that can transfer contiguous sequences of values between a buffer
+ *   and an array or some other buffer of the same type; and  </p></li>
+ *
+ *   <li><p> A view buffer is potentially much more efficient because it will
+ *   be direct if, and only if, its backing byte buffer is direct.  </p></li>
+ *
+ * </ul>
+ *
+ * <p> The byte order of a view buffer is fixed to be that of its byte buffer
+ * at the time that the view is created.  </p>
+ *
+#end[byte]
+*
+#if[!byte]
+ *
+ * <p> Like a byte buffer, $a$ $type$ buffer is either <a
+ * href="ByteBuffer.html#direct"><i>direct</i> or <i>non-direct</i></a>.  A
+ * $type$ buffer created via the {@code wrap} methods of this class will
+ * be non-direct.  $A$ $type$ buffer created as a view of a byte buffer will
+ * be direct if, and only if, the byte buffer itself is direct.  Whether or not
+ * $a$ $type$ buffer is direct may be determined by invoking the {@link
+ * #isDirect isDirect} method.  </p>
+ *
+#end[!byte]
+*
+#if[char]
+ *
+ * <p> This class implements the {@link CharSequence} interface so that
+ * character buffers may be used wherever character sequences are accepted, for
+ * example in the regular-expression package {@link java.util.regex}.
+ * </p>
+ *
+#end[char]
+ *
+#if[byte]
+ * <h2> Invocation chaining </h2>
+#end[byte]
+ *
+ * <p> Methods in this class that do not otherwise have a value to return are
+ * specified to return the buffer upon which they are invoked.  This allows
+ * method invocations to be chained.
+ *
+#if[byte]
+ *
+ * The sequence of statements
+ *
+ * <blockquote><pre>
+ * bb.putInt(0xCAFEBABE);
+ * bb.putShort(3);
+ * bb.putShort(45);</pre></blockquote>
+ *
+ * can, for example, be replaced by the single statement
+ *
+ * <blockquote><pre>
+ * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);</pre></blockquote>
+ *
+#end[byte]
+#if[char]
+ *
+ * The sequence of statements
+ *
+ * <blockquote><pre>
+ * cb.put("text/");
+ * cb.put(subtype);
+ * cb.put("; charset=");
+ * cb.put(enc);</pre></blockquote>
+ *
+ * can, for example, be replaced by the single statement
+ *
+ * <blockquote><pre>
+ * cb.put("text/").put(subtype).put("; charset=").put(enc);</pre></blockquote>
+ *
+#end[char]
+ *
+ *
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @since 1.4
+ */
+
+public abstract class $Type$Buffer
+    extends Buffer
+    implements Comparable<$Type$Buffer>{#if[char]?, Appendable, CharSequence, Readable}
+{
+
+    // These fields are declared here rather than in Heap-X-Buffer in order to
+    // reduce the number of virtual method invocations needed to access these
+    // values, which is especially costly when coding small buffers.
+    //
+    final $type$[] hb;                  // Non-null only for heap buffers
+    final int offset;
+    boolean isReadOnly;
+
+    // Creates a new buffer with the given mark, position, limit, capacity,
+    // backing array, and array offset
+    //
+    $Type$Buffer(int mark, int pos, int lim, int cap,   // package-private
+                 $type$[] hb, int offset)
+    {
+        super(mark, pos, lim, cap);
+        this.hb = hb;
+        this.offset = offset;
+    }
+
+    // Creates a new buffer with the given mark, position, limit, and capacity
+    //
+    $Type$Buffer(int mark, int pos, int lim, int cap) { // package-private
+        this(mark, pos, lim, cap, null, 0);
+    }
+
+    @Override
+    Object base() {
+        return hb;
+    }
+
+#if[byte]
+
+    /**
+     * Allocates a new direct $type$ buffer.
+     *
+     * <p> The new buffer's position will be zero, its limit will be its
+     * capacity, its mark will be undefined, each of its elements will be
+     * initialized to zero, and its byte order will be
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.  Whether or not it has a
+     * {@link #hasArray backing array} is unspecified.
+     *
+     * @param  capacity
+     *         The new buffer's capacity, in $type$s
+     *
+     * @return  The new $type$ buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code capacity} is a negative integer
+     */
+    public static $Type$Buffer allocateDirect(int capacity) {
+        return new Direct$Type$Buffer(capacity);
+    }
+
+#end[byte]
+
+    /**
+     * Allocates a new $type$ buffer.
+     *
+     * <p> The new buffer's position will be zero, its limit will be its
+     * capacity, its mark will be undefined, each of its elements will be
+     * initialized to zero, and its byte order will be
+#if[byte]
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+#else[byte]
+     * the {@link ByteOrder#nativeOrder native order} of the underlying
+     * hardware.
+#end[byte]
+     * It will have a {@link #array backing array}, and its
+     * {@link #arrayOffset array offset} will be zero.
+     *
+     * @param  capacity
+     *         The new buffer's capacity, in $type$s
+     *
+     * @return  The new $type$ buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the {@code capacity} is a negative integer
+     */
+    public static $Type$Buffer allocate(int capacity) {
+        if (capacity < 0)
+            throw createCapacityException(capacity);
+        return new Heap$Type$Buffer(capacity, capacity);
+    }
+
+    /**
+     * Wraps $a$ $type$ array into a buffer.
+     *
+     * <p> The new buffer will be backed by the given $type$ array;
+     * that is, modifications to the buffer will cause the array to be modified
+     * and vice versa.  The new buffer's capacity will be
+     * {@code array.length}, its position will be {@code offset}, its limit
+     * will be {@code offset + length}, its mark will be undefined, and its
+     * byte order will be
+#if[byte]
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+#else[byte]
+     * the {@link ByteOrder#nativeOrder native order} of the underlying
+     * hardware.
+#end[byte]
+     * Its {@link #array backing array} will be the given array, and
+     * its {@link #arrayOffset array offset} will be zero.  </p>
+     *
+     * @param  array
+     *         The array that will back the new buffer
+     *
+     * @param  offset
+     *         The offset of the subarray to be used; must be non-negative and
+     *         no larger than {@code array.length}.  The new buffer's position
+     *         will be set to this value.
+     *
+     * @param  length
+     *         The length of the subarray to be used;
+     *         must be non-negative and no larger than
+     *         {@code array.length - offset}.
+     *         The new buffer's limit will be set to {@code offset + length}.
+     *
+     * @return  The new $type$ buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the {@code offset} and {@code length}
+     *          parameters do not hold
+     */
+    public static $Type$Buffer wrap($type$[] array,
+                                    int offset, int length)
+    {
+        try {
+            return new Heap$Type$Buffer(array, offset, length);
+        } catch (IllegalArgumentException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Wraps $a$ $type$ array into a buffer.
+     *
+     * <p> The new buffer will be backed by the given $type$ array;
+     * that is, modifications to the buffer will cause the array to be modified
+     * and vice versa.  The new buffer's capacity and limit will be
+     * {@code array.length}, its position will be zero, its mark will be
+     * undefined, and its byte order will be
+#if[byte]
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+#else[byte]
+     * the {@link ByteOrder#nativeOrder native order} of the underlying
+     * hardware.
+#end[byte]
+     * Its {@link #array backing array} will be the given array, and its
+     * {@link #arrayOffset array offset} will be zero.  </p>
+     *
+     * @param  array
+     *         The array that will back this buffer
+     *
+     * @return  The new $type$ buffer
+     */
+    public static $Type$Buffer wrap($type$[] array) {
+        return wrap(array, 0, array.length);
+    }
+
+#if[char]
+
+    /**
+     * Attempts to read characters into the specified character buffer.
+     * The buffer is used as a repository of characters as-is: the only
+     * changes made are the results of a put operation. No flipping or
+     * rewinding of the buffer is performed.
+     *
+     * @param target the buffer to read characters into
+     * @return The number of characters added to the buffer, or
+     *         -1 if this source of characters is at its end
+     * @throws IOException if an I/O error occurs
+     * @throws NullPointerException if target is null
+     * @throws ReadOnlyBufferException if target is a read only buffer
+     * @since 1.5
+     */
+    public int read(CharBuffer target) throws IOException {
+        // Determine the number of bytes n that can be transferred
+        int targetRemaining = target.remaining();
+        int remaining = remaining();
+        if (remaining == 0)
+            return -1;
+        int n = Math.min(remaining, targetRemaining);
+        int limit = limit();
+        // Set source limit to prevent target overflow
+        if (targetRemaining < remaining)
+            limit(position() + n);
+        try {
+            if (n > 0)
+                target.put(this);
+        } finally {
+            limit(limit); // restore real limit
+        }
+        return n;
+    }
+
+    /**
+     * Wraps a character sequence into a buffer.
+     *
+     * <p> The content of the new, read-only buffer will be the content of the
+     * given character sequence.  The buffer's capacity will be
+     * {@code csq.length()}, its position will be {@code start}, its limit
+     * will be {@code end}, and its mark will be undefined.  </p>
+     *
+     * @param  csq
+     *         The character sequence from which the new character buffer is to
+     *         be created
+     *
+     * @param  start
+     *         The index of the first character to be used;
+     *         must be non-negative and no larger than {@code csq.length()}.
+     *         The new buffer's position will be set to this value.
+     *
+     * @param  end
+     *         The index of the character following the last character to be
+     *         used; must be no smaller than {@code start} and no larger
+     *         than {@code csq.length()}.
+     *         The new buffer's limit will be set to this value.
+     *
+     * @return  The new character buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the {@code start} and {@code end}
+     *          parameters do not hold
+     */
+    public static CharBuffer wrap(CharSequence csq, int start, int end) {
+        try {
+            return new StringCharBuffer(csq, start, end);
+        } catch (IllegalArgumentException x) {
+            throw new IndexOutOfBoundsException();
+        }
+    }
+
+    /**
+     * Wraps a character sequence into a buffer.
+     *
+     * <p> The content of the new, read-only buffer will be the content of the
+     * given character sequence.  The new buffer's capacity and limit will be
+     * {@code csq.length()}, its position will be zero, and its mark will be
+     * undefined.  </p>
+     *
+     * @param  csq
+     *         The character sequence from which the new character buffer is to
+     *         be created
+     *
+     * @return  The new character buffer
+     */
+    public static CharBuffer wrap(CharSequence csq) {
+        return wrap(csq, 0, csq.length());
+    }
+
+#end[char]
+
+    /**
+     * Creates a new $type$ buffer whose content is a shared subsequence of
+     * this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position.  Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of $type$s remaining in this buffer, its mark will be
+     * undefined, and its byte order will be
+#if[byte]
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+#else[byte]
+     * identical to that of this buffer.
+#end[byte]
+     * The new buffer will be direct if, and only if, this buffer is direct, and
+     * it will be read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @return  The new $type$ buffer
+#if[byte]
+     *
+     * @see #alignedSlice(int)
+#end[byte]
+     */
+    @Override
+    public abstract $Type$Buffer slice();
+
+    /**
+     * Creates a new $type$ buffer that shares this buffer's content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer, and vice
+     * versa; the two buffers' position, limit, and mark values will be
+     * independent.
+     *
+     * <p> The new buffer's capacity, limit, position,
+#if[byte]
+     * and mark values will be identical to those of this buffer, and its byte
+     * order will be {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+#else[byte]
+     * mark values, and byte order will be identical to those of this buffer.
+#end[byte]
+     * The new buffer will be direct if, and only if, this buffer is direct, and
+     * it will be read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @return  The new $type$ buffer
+     */
+    @Override
+    public abstract $Type$Buffer duplicate();
+
+    /**
+     * Creates a new, read-only $type$ buffer that shares this buffer's
+     * content.
+     *
+     * <p> The content of the new buffer will be that of this buffer.  Changes
+     * to this buffer's content will be visible in the new buffer; the new
+     * buffer itself, however, will be read-only and will not allow the shared
+     * content to be modified.  The two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's capacity, limit, position,
+#if[byte]
+     * and mark values will be identical to those of this buffer, and its byte
+     * order will be {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+#else[byte]
+     * mark values, and byte order will be identical to those of this buffer.
+#end[byte]
+     *
+     * <p> If this buffer is itself read-only then this method behaves in
+     * exactly the same way as the {@link #duplicate duplicate} method.  </p>
+     *
+     * @return  The new, read-only $type$ buffer
+     */
+    public abstract $Type$Buffer asReadOnlyBuffer();
+
+
+    // -- Singleton get/put methods --
+
+    /**
+     * Relative <i>get</i> method.  Reads the $type$ at this buffer's
+     * current position, and then increments the position.
+     *
+     * @return  The $type$ at the buffer's current position
+     *
+     * @throws  BufferUnderflowException
+     *          If the buffer's current position is not smaller than its limit
+     */
+    public abstract $type$ get();
+
+    /**
+     * Relative <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes the given $type$ into this buffer at the current
+     * position, and then increments the position. </p>
+     *
+     * @param  $x$
+     *         The $type$ to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If this buffer's current position is not smaller than its limit
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer put($type$ $x$);
+
+    /**
+     * Absolute <i>get</i> method.  Reads the $type$ at the given
+     * index.
+     *
+     * @param  index
+     *         The index from which the $type$ will be read
+     *
+     * @return  The $type$ at the given index
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code index} is negative
+     *          or not smaller than the buffer's limit
+     */
+    public abstract $type$ get(int index);
+
+#if[streamableType]
+    /**
+     * Absolute <i>get</i> method.  Reads the $type$ at the given
+     * index without any validation of the index.
+     *
+     * @param  index
+     *         The index from which the $type$ will be read
+     *
+     * @return  The $type$ at the given index
+     */
+    abstract $type$ getUnchecked(int index);   // package-private
+#end[streamableType]
+
+    /**
+     * Absolute <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Writes the given $type$ into this buffer at the given
+     * index. </p>
+     *
+     * @param  index
+     *         The index at which the $type$ will be written
+     *
+     * @param  $x$
+     *         The $type$ value to be written
+     *
+     * @return  This buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code index} is negative
+     *          or not smaller than the buffer's limit
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer put(int index, $type$ $x$);
+
+
+    // -- Bulk get operations --
+
+    /**
+     * Relative bulk <i>get</i> method.
+     *
+     * <p> This method transfers $type$s from this buffer into the given
+     * destination array.  If there are fewer $type$s remaining in the
+     * buffer than are required to satisfy the request, that is, if
+     * {@code length}&nbsp;{@code >}&nbsp;{@code remaining()}, then no
+     * $type$s are transferred and a {@link BufferUnderflowException} is
+     * thrown.
+     *
+     * <p> Otherwise, this method copies {@code length} $type$s from this
+     * buffer into the given array, starting at the current position of this
+     * buffer and at the given offset in the array.  The position of this
+     * buffer is then incremented by {@code length}.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <code>src.get(dst,&nbsp;off,&nbsp;len)</code> has exactly the same effect as
+     * the loop
+     *
+     * <pre>{@code
+     *     for (int i = off; i < off + len; i++)
+     *         dst[i] = src.get();
+     * }</pre>
+     *
+     * except that it first checks that there are sufficient $type$s in
+     * this buffer and it is potentially much more efficient.
+     *
+     * @param  dst
+     *         The array into which $type$s are to be written
+     *
+     * @param  offset
+     *         The offset within the array of the first $type$ to be
+     *         written; must be non-negative and no larger than
+     *         {@code dst.length}
+     *
+     * @param  length
+     *         The maximum number of $type$s to be written to the given
+     *         array; must be non-negative and no larger than
+     *         {@code dst.length - offset}
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than {@code length} $type$s
+     *          remaining in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the {@code offset} and {@code length}
+     *          parameters do not hold
+     */
+    public $Type$Buffer get($type$[] dst, int offset, int length) {
+        checkBounds(offset, length, dst.length);
+        if (length > remaining())
+            throw new BufferUnderflowException();
+        int end = offset + length;
+        for (int i = offset; i < end; i++)
+            dst[i] = get();
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>get</i> method.
+     *
+     * <p> This method transfers $type$s from this buffer into the given
+     * destination array.  An invocation of this method of the form
+     * {@code src.get(a)} behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     src.get(a, 0, a.length) </pre>
+     *
+     * @param   dst
+     *          The destination array
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferUnderflowException
+     *          If there are fewer than {@code length} $type$s
+     *          remaining in this buffer
+     */
+    public $Type$Buffer get($type$[] dst) {
+        return get(dst, 0, dst.length);
+    }
+
+
+    // -- Bulk put operations --
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the $type$s remaining in the given source
+     * buffer into this buffer.  If there are more $type$s remaining in the
+     * source buffer than in this buffer, that is, if
+     * {@code src.remaining()}&nbsp;{@code >}&nbsp;{@code remaining()},
+     * then no $type$s are transferred and a {@link
+     * BufferOverflowException} is thrown.
+     *
+     * <p> Otherwise, this method copies
+     * <i>n</i>&nbsp;=&nbsp;{@code src.remaining()} $type$s from the given
+     * buffer into this buffer, starting at each buffer's current position.
+     * The positions of both buffers are then incremented by <i>n</i>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * {@code dst.put(src)} has exactly the same effect as the loop
+     *
+     * <pre>
+     *     while (src.hasRemaining())
+     *         dst.put(src.get()); </pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient.
+     *
+     * @param  src
+     *         The source buffer from which $type$s are to be read;
+     *         must not be this buffer
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *          for the remaining $type$s in the source buffer
+     *
+     * @throws  IllegalArgumentException
+     *          If the source buffer is this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put($Type$Buffer src) {
+        if (src == this)
+            throw createSameBufferException();
+        if (isReadOnly())
+            throw new ReadOnlyBufferException();
+        int n = src.remaining();
+        if (n > remaining())
+            throw new BufferOverflowException();
+        for (int i = 0; i < n; i++)
+            put(src.get());
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers $type$s into this buffer from the given
+     * source array.  If there are more $type$s to be copied from the array
+     * than remain in this buffer, that is, if
+     * {@code length}&nbsp;{@code >}&nbsp;{@code remaining()}, then no
+     * $type$s are transferred and a {@link BufferOverflowException} is
+     * thrown.
+     *
+     * <p> Otherwise, this method copies {@code length} $type$s from the
+     * given array into this buffer, starting at the given offset in the array
+     * and at the current position of this buffer.  The position of this buffer
+     * is then incremented by {@code length}.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <code>dst.put(src,&nbsp;off,&nbsp;len)</code> has exactly the same effect as
+     * the loop
+     *
+     * <pre>{@code
+     *     for (int i = off; i < off + len; i++)
+     *         dst.put(a[i]);
+     * }</pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient.
+     *
+     * @param  src
+     *         The array from which $type$s are to be read
+     *
+     * @param  offset
+     *         The offset within the array of the first $type$ to be read;
+     *         must be non-negative and no larger than {@code array.length}
+     *
+     * @param  length
+     *         The number of $type$s to be read from the given array;
+     *         must be non-negative and no larger than
+     *         {@code array.length - offset}
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the {@code offset} and {@code length}
+     *          parameters do not hold
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put($type$[] src, int offset, int length) {
+        checkBounds(offset, length, src.length);
+        if (length > remaining())
+            throw new BufferOverflowException();
+        int end = offset + length;
+        for (int i = offset; i < end; i++)
+            this.put(src[i]);
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the entire content of the given source
+     * $type$ array into this buffer.  An invocation of this method of the
+     * form {@code dst.put(a)} behaves in exactly the same way as the
+     * invocation
+     *
+     * <pre>
+     *     dst.put(a, 0, a.length) </pre>
+     *
+     * @param   src
+     *          The source array
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public final $Type$Buffer put($type$[] src) {
+        return put(src, 0, src.length);
+    }
+
+#if[char]
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers $type$s from the given string into this
+     * buffer.  If there are more $type$s to be copied from the string than
+     * remain in this buffer, that is, if
+     * <code>end&nbsp;-&nbsp;start</code>&nbsp;{@code >}&nbsp;{@code remaining()},
+     * then no $type$s are transferred and a {@link
+     * BufferOverflowException} is thrown.
+     *
+     * <p> Otherwise, this method copies
+     * <i>n</i>&nbsp;=&nbsp;{@code end}&nbsp;-&nbsp;{@code start} $type$s
+     * from the given string into this buffer, starting at the given
+     * {@code start} index and at the current position of this buffer.  The
+     * position of this buffer is then incremented by <i>n</i>.
+     *
+     * <p> In other words, an invocation of this method of the form
+     * <code>dst.put(src,&nbsp;start,&nbsp;end)</code> has exactly the same effect
+     * as the loop
+     *
+     * <pre>{@code
+     *     for (int i = start; i < end; i++)
+     *         dst.put(src.charAt(i));
+     * }</pre>
+     *
+     * except that it first checks that there is sufficient space in this
+     * buffer and it is potentially much more efficient.
+     *
+     * @param  src
+     *         The string from which $type$s are to be read
+     *
+     * @param  start
+     *         The offset within the string of the first $type$ to be read;
+     *         must be non-negative and no larger than
+     *         {@code string.length()}
+     *
+     * @param  end
+     *         The offset within the string of the last $type$ to be read,
+     *         plus one; must be non-negative and no larger than
+     *         {@code string.length()}
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on the {@code start} and {@code end}
+     *          parameters do not hold
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public $Type$Buffer put(String src, int start, int end) {
+        checkBounds(start, end - start, src.length());
+        if (isReadOnly())
+            throw new ReadOnlyBufferException();
+        if (end - start > remaining())
+            throw new BufferOverflowException();
+        for (int i = start; i < end; i++)
+            this.put(src.charAt(i));
+        return this;
+    }
+
+    /**
+     * Relative bulk <i>put</i> method&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> This method transfers the entire content of the given source string
+     * into this buffer.  An invocation of this method of the form
+     * {@code dst.put(s)} behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put(s, 0, s.length()) </pre>
+     *
+     * @param   src
+     *          The source string
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public final $Type$Buffer put(String src) {
+        return put(src, 0, src.length());
+    }
+
+#end[char]
+
+
+    // -- Other stuff --
+
+    /**
+     * Tells whether or not this buffer is backed by an accessible $type$
+     * array.
+     *
+     * <p> If this method returns {@code true} then the {@link #array() array}
+     * and {@link #arrayOffset() arrayOffset} methods may safely be invoked.
+     * </p>
+     *
+     * @return  {@code true} if, and only if, this buffer
+     *          is backed by an array and is not read-only
+     */
+    public final boolean hasArray() {
+        return (hb != null) && !isReadOnly;
+    }
+
+    /**
+     * Returns the $type$ array that backs this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> Modifications to this buffer's content will cause the returned
+     * array's content to be modified, and vice versa.
+     *
+     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
+     * method in order to ensure that this buffer has an accessible backing
+     * array.  </p>
+     *
+     * @return  The array that backs this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is backed by an array but is read-only
+     *
+     * @throws  UnsupportedOperationException
+     *          If this buffer is not backed by an accessible array
+     */
+    public final $type$[] array() {
+        if (hb == null)
+            throw new UnsupportedOperationException();
+        if (isReadOnly)
+            throw new ReadOnlyBufferException();
+        return hb;
+    }
+
+    /**
+     * Returns the offset within this buffer's backing array of the first
+     * element of the buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> If this buffer is backed by an array then buffer position <i>p</i>
+     * corresponds to array index <i>p</i>&nbsp;+&nbsp;{@code arrayOffset()}.
+     *
+     * <p> Invoke the {@link #hasArray hasArray} method before invoking this
+     * method in order to ensure that this buffer has an accessible backing
+     * array.  </p>
+     *
+     * @return  The offset within this buffer's array
+     *          of the first element of the buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is backed by an array but is read-only
+     *
+     * @throws  UnsupportedOperationException
+     *          If this buffer is not backed by an accessible array
+     */
+    public final int arrayOffset() {
+        if (hb == null)
+            throw new UnsupportedOperationException();
+        if (isReadOnly)
+            throw new ReadOnlyBufferException();
+        return offset;
+    }
+
+    // -- Covariant return type overrides
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+#if[!byte]
+    final
+#end[!byte]
+    $Type$Buffer position(int newPosition) {
+        super.position(newPosition);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+#if[!byte]
+    final
+#end[!byte]
+    $Type$Buffer limit(int newLimit) {
+        super.limit(newLimit);
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+#if[!byte]
+    final
+#end[!byte]
+    $Type$Buffer mark() {
+        super.mark();
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+#if[!byte]
+    final
+#end[!byte]
+    $Type$Buffer reset() {
+        super.reset();
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+#if[!byte]
+    final
+#end[!byte]
+    $Type$Buffer clear() {
+        super.clear();
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+#if[!byte]
+    final
+#end[!byte]
+    $Type$Buffer flip() {
+        super.flip();
+        return this;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public
+#if[!byte]
+    final
+#end[!byte]
+    $Type$Buffer rewind() {
+        super.rewind();
+        return this;
+    }
+
+    /**
+     * Compacts this buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> The $type$s between the buffer's current position and its limit,
+     * if any, are copied to the beginning of the buffer.  That is, the
+     * $type$ at index <i>p</i>&nbsp;=&nbsp;{@code position()} is copied
+     * to index zero, the $type$ at index <i>p</i>&nbsp;+&nbsp;1 is copied
+     * to index one, and so forth until the $type$ at index
+     * {@code limit()}&nbsp;-&nbsp;1 is copied to index
+     * <i>n</i>&nbsp;=&nbsp;{@code limit()}&nbsp;-&nbsp;{@code 1}&nbsp;-&nbsp;<i>p</i>.
+     * The buffer's position is then set to <i>n+1</i> and its limit is set to
+     * its capacity.  The mark, if defined, is discarded.
+     *
+     * <p> The buffer's position is set to the number of $type$s copied,
+     * rather than to zero, so that an invocation of this method can be
+     * followed immediately by an invocation of another relative <i>put</i>
+     * method. </p>
+     *
+#if[byte]
+     *
+     * <p> Invoke this method after writing data from a buffer in case the
+     * write was incomplete.  The following loop, for example, copies bytes
+     * from one channel to another via the buffer {@code buf}:
+     *
+     * <blockquote><pre>{@code
+     *   buf.clear();          // Prepare buffer for use
+     *   while (in.read(buf) >= 0 || buf.position != 0) {
+     *       buf.flip();
+     *       out.write(buf);
+     *       buf.compact();    // In case of partial write
+     *   }
+     * }</pre></blockquote>
+     *
+#end[byte]
+     *
+     * @return  This buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     */
+    public abstract $Type$Buffer compact();
+
+    /**
+     * Tells whether or not this $type$ buffer is direct.
+     *
+     * @return  {@code true} if, and only if, this buffer is direct
+     */
+    public abstract boolean isDirect();
+
+#if[!char]
+
+    /**
+     * Returns a string summarizing the state of this buffer.
+     *
+     * @return  A summary string
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append(getClass().getName());
+        sb.append("[pos=");
+        sb.append(position());
+        sb.append(" lim=");
+        sb.append(limit());
+        sb.append(" cap=");
+        sb.append(capacity());
+        sb.append("]");
+        return sb.toString();
+    }
+
+#end[!char]
+
+
+    // ## Should really use unchecked accessors here for speed
+
+    /**
+     * Returns the current hash code of this buffer.
+     *
+     * <p> The hash code of a $type$ buffer depends only upon its remaining
+     * elements; that is, upon the elements from {@code position()} up to, and
+     * including, the element at {@code limit()}&nbsp;-&nbsp;{@code 1}.
+     *
+     * <p> Because buffer hash codes are content-dependent, it is inadvisable
+     * to use buffers as keys in hash maps or similar data structures unless it
+     * is known that their contents will not change.  </p>
+     *
+     * @return  The current hash code of this buffer
+     */
+    public int hashCode() {
+        int h = 1;
+        int p = position();
+        for (int i = limit() - 1; i >= p; i--)
+#if[int]
+            h = 31 * h + get(i);
+#else[int]
+            h = 31 * h + (int)get(i);
+#end[int]
+        return h;
+    }
+
+    /**
+     * Tells whether or not this buffer is equal to another object.
+     *
+     * <p> Two $type$ buffers are equal if, and only if,
+     *
+     * <ol>
+     *
+     *   <li><p> They have the same element type,  </p></li>
+     *
+     *   <li><p> They have the same number of remaining elements, and
+     *   </p></li>
+     *
+     *   <li><p> The two sequences of remaining elements, considered
+     *   independently of their starting positions, are pointwise equal.
+#if[floatingPointType]
+     *   This method considers two $type$ elements {@code a} and {@code b}
+     *   to be equal if
+     *   {@code (a == b) || ($Fulltype$.isNaN(a) && $Fulltype$.isNaN(b))}.
+     *   The values {@code -0.0} and {@code +0.0} are considered to be
+     *   equal, unlike {@link $Fulltype$#equals(Object)}.
+#end[floatingPointType]
+     *   </p></li>
+     *
+     * </ol>
+     *
+     * <p> A $type$ buffer is not equal to any other type of object.  </p>
+     *
+     * @param  ob  The object to which this buffer is to be compared
+     *
+     * @return  {@code true} if, and only if, this buffer is equal to the
+     *           given object
+     */
+    public boolean equals(Object ob) {
+        if (this == ob)
+            return true;
+        if (!(ob instanceof $Type$Buffer))
+            return false;
+        $Type$Buffer that = ($Type$Buffer)ob;
+        if (this.remaining() != that.remaining())
+            return false;
+        return BufferMismatch.mismatch(this, this.position(),
+                                       that, that.position(),
+                                       this.remaining()) < 0;
+    }
+
+    /**
+     * Compares this buffer to another.
+     *
+     * <p> Two $type$ buffers are compared by comparing their sequences of
+     * remaining elements lexicographically, without regard to the starting
+     * position of each sequence within its corresponding buffer.
+#if[floatingPointType]
+     * Pairs of {@code $type$} elements are compared as if by invoking
+     * {@link $Fulltype$#compare($type$,$type$)}, except that
+     * {@code -0.0} and {@code 0.0} are considered to be equal.
+     * {@code $Fulltype$.NaN} is considered by this method to be equal
+     * to itself and greater than all other {@code $type$} values
+     * (including {@code $Fulltype$.POSITIVE_INFINITY}).
+#else[floatingPointType]
+     * Pairs of {@code $type$} elements are compared as if by invoking
+     * {@link $Fulltype$#compare($type$,$type$)}.
+#end[floatingPointType]
+     *
+     * <p> A $type$ buffer is not comparable to any other type of object.
+     *
+     * @return  A negative integer, zero, or a positive integer as this buffer
+     *          is less than, equal to, or greater than the given buffer
+     */
+    public int compareTo($Type$Buffer that) {
+        int i = BufferMismatch.mismatch(this, this.position(),
+                                        that, that.position(),
+                                        Math.min(this.remaining(), that.remaining()));
+        if (i >= 0) {
+            return compare(this.get(this.position() + i), that.get(that.position() + i));
+        }
+        return this.remaining() - that.remaining();
+    }
+
+    private static int compare($type$ x, $type$ y) {
+#if[floatingPointType]
+        return ((x < y)  ? -1 :
+                (x > y)  ? +1 :
+                (x == y) ?  0 :
+                $Fulltype$.isNaN(x) ? ($Fulltype$.isNaN(y) ? 0 : +1) : -1);
+#else[floatingPointType]
+        return $Fulltype$.compare(x, y);
+#end[floatingPointType]
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between this
+     * buffer and a given buffer.  The index is relative to the
+     * {@link #position() position} of each buffer and will be in the range of
+     * 0 (inclusive) up to the smaller of the {@link #remaining() remaining}
+     * elements in each buffer (exclusive).
+     *
+     * <p> If the two buffers share a common prefix then the returned index is
+     * the length of the common prefix and it follows that there is a mismatch
+     * between the two buffers at that index within the respective buffers.
+     * If one buffer is a proper prefix of the other then the returned index is
+     * the smaller of the remaining elements in each buffer, and it follows that
+     * the index is only valid for the buffer with the larger number of
+     * remaining elements.
+     * Otherwise, there is no mismatch.
+     *
+     * @param  that
+     *         The byte buffer to be tested for a mismatch with this buffer
+     *
+     * @return  The relative index of the first mismatch between this and the
+     *          given buffer, otherwise -1 if no mismatch.
+     *
+     * @since 11
+     */
+    public int mismatch($Type$Buffer that) {
+        int length = Math.min(this.remaining(), that.remaining());
+        int r = BufferMismatch.mismatch(this, this.position(),
+                                        that, that.position(),
+                                        length);
+        return (r == -1 && this.remaining() != that.remaining()) ? length : r;
+    }
+
+    // -- Other char stuff --
+
+#if[char]
+
+    /**
+     * Returns a string containing the characters in this buffer.
+     *
+     * <p> The first character of the resulting string will be the character at
+     * this buffer's position, while the last character will be the character
+     * at index {@code limit()}&nbsp;-&nbsp;1.  Invoking this method does not
+     * change the buffer's position. </p>
+     *
+     * @return  The specified string
+     */
+    public String toString() {
+        return toString(position(), limit());
+    }
+
+    abstract String toString(int start, int end);       // package-private
+
+
+    // --- Methods to support CharSequence ---
+
+    /**
+     * Returns the length of this character buffer.
+     *
+     * <p> When viewed as a character sequence, the length of a character
+     * buffer is simply the number of characters between the position
+     * (inclusive) and the limit (exclusive); that is, it is equivalent to
+     * {@code remaining()}. </p>
+     *
+     * @return  The length of this character buffer
+     */
+    public final int length() {
+        return remaining();
+    }
+
+    /**
+     * Reads the character at the given index relative to the current
+     * position.
+     *
+     * @param  index
+     *         The index of the character to be read, relative to the position;
+     *         must be non-negative and smaller than {@code remaining()}
+     *
+     * @return  The character at index
+     *          <code>position()&nbsp;+&nbsp;index</code>
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on {@code index} do not hold
+     */
+    public final char charAt(int index) {
+        return get(position() + checkIndex(index, 1));
+    }
+
+    /**
+     * Creates a new character buffer that represents the specified subsequence
+     * of this buffer, relative to the current position.
+     *
+     * <p> The new buffer will share this buffer's content; that is, if the
+     * content of this buffer is mutable then modifications to one buffer will
+     * cause the other to be modified.  The new buffer's capacity will be that
+     * of this buffer, its position will be
+     * {@code position()}&nbsp;+&nbsp;{@code start}, and its limit will be
+     * {@code position()}&nbsp;+&nbsp;{@code end}.  The new buffer will be
+     * direct if, and only if, this buffer is direct, and it will be read-only
+     * if, and only if, this buffer is read-only.  </p>
+     *
+     * @param  start
+     *         The index, relative to the current position, of the first
+     *         character in the subsequence; must be non-negative and no larger
+     *         than {@code remaining()}
+     *
+     * @param  end
+     *         The index, relative to the current position, of the character
+     *         following the last character in the subsequence; must be no
+     *         smaller than {@code start} and no larger than
+     *         {@code remaining()}
+     *
+     * @return  The new character buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If the preconditions on {@code start} and {@code end}
+     *          do not hold
+     */
+    public abstract CharBuffer subSequence(int start, int end);
+
+
+    // --- Methods to support Appendable ---
+
+    /**
+     * Appends the specified character sequence  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form {@code dst.append(csq)}
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put(csq.toString()) </pre>
+     *
+     * <p> Depending on the specification of {@code toString} for the
+     * character sequence {@code csq}, the entire sequence may not be
+     * appended.  For instance, invoking the {@link $Type$Buffer#toString()
+     * toString} method of a character buffer will return a subsequence whose
+     * content depends upon the buffer's position and limit.
+     *
+     * @param  csq
+     *         The character sequence to append.  If {@code csq} is
+     *         {@code null}, then the four characters {@code "null"} are
+     *         appended to this character buffer.
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append(CharSequence csq) {
+        if (csq == null)
+            return put("null");
+        else
+            return put(csq.toString());
+    }
+
+    /**
+     * Appends a subsequence of the  specified character sequence  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form {@code dst.append(csq, start,
+     * end)} when {@code csq} is not {@code null}, behaves in exactly the
+     * same way as the invocation
+     *
+     * <pre>
+     *     dst.put(csq.subSequence(start, end).toString()) </pre>
+     *
+     * @param  csq
+     *         The character sequence from which a subsequence will be
+     *         appended.  If {@code csq} is {@code null}, then characters
+     *         will be appended as if {@code csq} contained the four
+     *         characters {@code "null"}.
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  IndexOutOfBoundsException
+     *          If {@code start} or {@code end} are negative, {@code start}
+     *          is greater than {@code end}, or {@code end} is greater than
+     *          {@code csq.length()}
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append(CharSequence csq, int start, int end) {
+        CharSequence cs = (csq == null ? "null" : csq);
+        return put(cs.subSequence(start, end).toString());
+    }
+
+    /**
+     * Appends the specified $type$  to this
+     * buffer&nbsp;&nbsp;<i>(optional operation)</i>.
+     *
+     * <p> An invocation of this method of the form {@code dst.append($x$)}
+     * behaves in exactly the same way as the invocation
+     *
+     * <pre>
+     *     dst.put($x$) </pre>
+     *
+     * @param  $x$
+     *         The 16-bit $type$ to append
+     *
+     * @return  This buffer
+     *
+     * @throws  BufferOverflowException
+     *          If there is insufficient space in this buffer
+     *
+     * @throws  ReadOnlyBufferException
+     *          If this buffer is read-only
+     *
+     * @since  1.5
+     */
+    public $Type$Buffer append($type$ $x$) {
+        return put($x$);
+    }
+
+#end[char]
+
+
+    // -- Other byte stuff: Access to binary data --
+
+#if[!byte]
+
+    /**
+     * Retrieves this buffer's byte order.
+     *
+     * <p> The byte order of $a$ $type$ buffer created by allocation or by
+     * wrapping an existing {@code $type$} array is the {@link
+     * ByteOrder#nativeOrder native order} of the underlying
+     * hardware.  The byte order of $a$ $type$ buffer created as a <a
+     * href="ByteBuffer.html#views">view</a> of a byte buffer is that of the
+     * byte buffer at the moment that the view is created.  </p>
+     *
+     * @return  This buffer's byte order
+     */
+    public abstract ByteOrder order();
+
+#end[!byte]
+
+#if[char]
+    // The order or null if the buffer does not cover a memory region,
+    // such as StringCharBuffer
+    abstract ByteOrder charRegionOrder();
+#end[char]
+
+#if[byte]
+
+    boolean bigEndian                                   // package-private
+        = true;
+    boolean nativeByteOrder                             // package-private
+        = (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN);
+
+    /**
+     * Retrieves this buffer's byte order.
+     *
+     * <p> The byte order is used when reading or writing multibyte values, and
+     * when creating buffers that are views of this byte buffer.  The order of
+     * a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN
+     * BIG_ENDIAN}.  </p>
+     *
+     * @return  This buffer's byte order
+     */
+    public final ByteOrder order() {
+        return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+    }
+
+    /**
+     * Modifies this buffer's byte order.
+     *
+     * @param  bo
+     *         The new byte order,
+     *         either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
+     *         or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}
+     *
+     * @return  This buffer
+     */
+    public final $Type$Buffer order(ByteOrder bo) {
+        bigEndian = (bo == ByteOrder.BIG_ENDIAN);
+        nativeByteOrder =
+            (bigEndian == (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN));
+        return this;
+    }
+
+    /**
+     * Returns the memory address, pointing to the byte at the given index,
+     * modulus the given unit size.
+     *
+     * <p> A return value greater than zero indicates the address of the byte at
+     * the index is misaligned for the unit size, and the value's quantity
+     * indicates how much the index should be rounded up or down to locate a
+     * byte at an aligned address.  Otherwise, a value of {@code 0} indicates
+     * that the address of the byte at the index is aligned for the unit size.
+     *
+     * @apiNote
+     * This method may be utilized to determine if unit size bytes from an
+     * index can be accessed atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  index
+     *         The index to query for alignment offset, must be non-negative, no
+     *         upper bounds check is performed
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The indexed byte's memory address modulus the unit size
+     *
+     * @throws IllegalArgumentException
+     *         If the index is negative or the unit size is not a power of
+     *         {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable alignment offset
+     *         values for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignedSlice(int)
+     * @since 9
+     */
+    public final int alignmentOffset(int index, int unitSize) {
+        if (index < 0)
+            throw new IllegalArgumentException("Index less than zero: " + index);
+        if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
+            throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
+        if (unitSize > 8 && !isDirect())
+            throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
+
+        return (int) ((address + index) % unitSize);
+    }
+
+    /**
+     * Creates a new byte buffer whose content is a shared and aligned
+     * subsequence of this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position rounded up to the index of the nearest aligned byte for the
+     * given unit size, and end at this buffer's limit rounded down to the index
+     * of the nearest aligned byte for the given unit size.
+     * If rounding results in out-of-bound values then the new buffer's capacity
+     * and limit will be zero.  If rounding is within bounds the following
+     * expressions will be true for a new buffer {@code nb} and unit size
+     * {@code unitSize}:
+     * <pre>{@code
+     * nb.alignmentOffset(0, unitSize) == 0
+     * nb.alignmentOffset(nb.limit(), unitSize) == 0
+     * }</pre>
+     *
+     * <p> Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer or fewer subject to
+     * alignment, its mark will be undefined, and its byte order will be
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+     *
+     * The new buffer will be direct if, and only if, this buffer is direct, and
+     * it will be read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @apiNote
+     * This method may be utilized to create a new buffer where unit size bytes
+     * from index, that is a multiple of the unit size, may be accessed
+     * atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The new byte buffer
+     *
+     * @throws IllegalArgumentException
+     *         If the unit size not a power of {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable aligned slices
+     *         for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignmentOffset(int, int)
+     * @see #slice()
+     * @since 9
+     */
+    public final ByteBuffer alignedSlice(int unitSize) {
+        int pos = position();
+        int lim = limit();
+
+        int pos_mod = alignmentOffset(pos, unitSize);
+        int lim_mod = alignmentOffset(lim, unitSize);
+
+        // Round up the position to align with unit size
+        int aligned_pos = (pos_mod > 0)
+            ? pos + (unitSize - pos_mod)
+            : pos;
+
+        // Round down the limit to align with unit size
+        int aligned_lim = lim - lim_mod;
+
+        if (aligned_pos > lim || aligned_lim < pos) {
+            aligned_pos = aligned_lim = pos;
+        }
+
+        return slice(aligned_pos, aligned_lim);
+    }
+
+    abstract ByteBuffer slice(int pos, int lim);
+
+    // #BIN
+    //
+    // Binary-data access methods  for short, char, int, long, float,
+    // and double will be inserted here
+
+#end[byte]
+
+#if[streamableType]
+
+#if[char]
+    @Override
+#end[char]
+    public $Streamtype$Stream $type$s() {
+        return StreamSupport.$streamtype$Stream(() -> new $Type$BufferSpliterator(this),
+            Buffer.SPLITERATOR_CHARACTERISTICS, false);
+    }
+
+#end[streamableType]
+
+}
\ No newline at end of file
diff --git a/ojluni/src/main/java/java/nio/channels/Channels.java b/ojluni/src/main/java/java/nio/channels/Channels.java
index 1d11262..b033a81 100644
--- a/ojluni/src/main/java/java/nio/channels/Channels.java
+++ b/ojluni/src/main/java/java/nio/channels/Channels.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.UnsupportedCharsetException;
 import java.nio.channels.spi.AbstractInterruptibleChannel;
+import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 import sun.nio.ch.ChannelInputStream;
 import sun.nio.cs.StreamDecoder;
@@ -49,8 +50,8 @@
  * Utility methods for channels and streams.
  *
  * <p> This class defines static methods that support the interoperation of the
- * stream classes of the <tt>{@link java.io}</tt> package with the channel
- * classes of this package.  </p>
+ * stream classes of the {@link java.io} package with the channel classes
+ * of this package.  </p>
  *
  *
  * @author Mark Reinhold
@@ -61,12 +62,7 @@
 
 public final class Channels {
 
-    private Channels() { }              // No instantiation
-
-    private static void checkNotNull(Object o, String name) {
-        if (o == null)
-            throw new NullPointerException("\"" + name + "\" is null!");
-    }
+    private Channels() { throw new Error("no instances"); }
 
     /**
      * Write all remaining bytes in buffer to the given channel.
@@ -92,7 +88,7 @@
         throws IOException
     {
         if (ch instanceof SelectableChannel) {
-            SelectableChannel sc = (SelectableChannel)ch;
+            SelectableChannel sc = (SelectableChannel) ch;
             synchronized (sc.blockingLock()) {
                 if (!sc.isBlocking())
                     throw new IllegalBlockingModeException();
@@ -108,7 +104,7 @@
     /**
      * Constructs a stream that reads bytes from the given channel.
      *
-     * <p> The <tt>read</tt> methods of the resulting stream will throw an
+     * <p> The {@code read} methods of the resulting stream will throw an
      * {@link IllegalBlockingModeException} if invoked while the underlying
      * channel is in non-blocking mode.  The stream will not be buffered, and
      * it will not support the {@link InputStream#mark mark} or {@link
@@ -122,14 +118,14 @@
      * @return  A new input stream
      */
     public static InputStream newInputStream(ReadableByteChannel ch) {
-        checkNotNull(ch, "ch");
-        return new sun.nio.ch.ChannelInputStream(ch);
+        Objects.requireNonNull(ch, "ch");
+        return new ChannelInputStream(ch);
     }
 
     /**
      * Constructs a stream that writes bytes to the given channel.
      *
-     * <p> The <tt>write</tt> methods of the resulting stream will throw an
+     * <p> The {@code write} methods of the resulting stream will throw an
      * {@link IllegalBlockingModeException} if invoked while the underlying
      * channel is in non-blocking mode.  The stream will not be buffered.  The
      * stream will be safe for access by multiple concurrent threads.  Closing
@@ -140,46 +136,49 @@
      *
      * @return  A new output stream
      */
-    public static OutputStream newOutputStream(final WritableByteChannel ch) {
-        checkNotNull(ch, "ch");
+    public static OutputStream newOutputStream(WritableByteChannel ch) {
+        Objects.requireNonNull(ch, "ch");
 
         return new OutputStream() {
 
-                private ByteBuffer bb = null;
-                private byte[] bs = null;       // Invoker's previous array
-                private byte[] b1 = null;
+            private ByteBuffer bb;
+            private byte[] bs;       // Invoker's previous array
+            private byte[] b1;
 
-                public synchronized void write(int b) throws IOException {
-                   if (b1 == null)
-                        b1 = new byte[1];
-                    b1[0] = (byte)b;
-                    this.write(b1);
-                }
+            @Override
+            public synchronized void write(int b) throws IOException {
+                if (b1 == null)
+                    b1 = new byte[1];
+                b1[0] = (byte) b;
+                this.write(b1);
+            }
 
-                public synchronized void write(byte[] bs, int off, int len)
+            @Override
+            public synchronized void write(byte[] bs, int off, int len)
                     throws IOException
-                {
-                    if ((off < 0) || (off > bs.length) || (len < 0) ||
-                        ((off + len) > bs.length) || ((off + len) < 0)) {
-                        throw new IndexOutOfBoundsException();
-                    } else if (len == 0) {
-                        return;
-                    }
-                    ByteBuffer bb = ((this.bs == bs)
-                                     ? this.bb
-                                     : ByteBuffer.wrap(bs));
-                    bb.limit(Math.min(off + len, bb.capacity()));
-                    bb.position(off);
-                    this.bb = bb;
-                    this.bs = bs;
-                    Channels.writeFully(ch, bb);
+            {
+                if ((off < 0) || (off > bs.length) || (len < 0) ||
+                    ((off + len) > bs.length) || ((off + len) < 0)) {
+                    throw new IndexOutOfBoundsException();
+                } else if (len == 0) {
+                    return;
                 }
+                ByteBuffer bb = ((this.bs == bs)
+                                 ? this.bb
+                                 : ByteBuffer.wrap(bs));
+                bb.limit(Math.min(off + len, bb.capacity()));
+                bb.position(off);
+                this.bb = bb;
+                this.bs = bs;
+                Channels.writeFully(ch, bb);
+            }
 
-                public void close() throws IOException {
-                    ch.close();
-                }
+            @Override
+            public void close() throws IOException {
+                ch.close();
+            }
 
-            };
+        };
     }
 
     /**
@@ -197,13 +196,13 @@
      *
      * @since 1.7
      */
-    public static InputStream newInputStream(final AsynchronousByteChannel ch) {
-        checkNotNull(ch, "ch");
+    public static InputStream newInputStream(AsynchronousByteChannel ch) {
+        Objects.requireNonNull(ch, "ch");
         return new InputStream() {
 
-            private ByteBuffer bb = null;
-            private byte[] bs = null;           // Invoker's previous array
-            private byte[] b1 = null;
+            private ByteBuffer bb;
+            private byte[] bs;           // Invoker's previous array
+            private byte[] b1;
 
             @Override
             public synchronized int read() throws IOException {
@@ -217,13 +216,14 @@
 
             @Override
             public synchronized int read(byte[] bs, int off, int len)
-                throws IOException
+                    throws IOException
             {
                 if ((off < 0) || (off > bs.length) || (len < 0) ||
                     ((off + len) > bs.length) || ((off + len) < 0)) {
                     throw new IndexOutOfBoundsException();
-                } else if (len == 0)
+                } else if (len == 0) {
                     return 0;
+                }
 
                 ByteBuffer bb = ((this.bs == bs)
                                  ? this.bb
@@ -271,25 +271,25 @@
      *
      * @since 1.7
      */
-    public static OutputStream newOutputStream(final AsynchronousByteChannel ch) {
-        checkNotNull(ch, "ch");
+    public static OutputStream newOutputStream(AsynchronousByteChannel ch) {
+        Objects.requireNonNull(ch, "ch");
         return new OutputStream() {
 
-            private ByteBuffer bb = null;
-            private byte[] bs = null;   // Invoker's previous array
-            private byte[] b1 = null;
+            private ByteBuffer bb;
+            private byte[] bs;   // Invoker's previous array
+            private byte[] b1;
 
             @Override
             public synchronized void write(int b) throws IOException {
-               if (b1 == null)
+                if (b1 == null)
                     b1 = new byte[1];
-                b1[0] = (byte)b;
+                b1[0] = (byte) b;
                 this.write(b1);
             }
 
             @Override
             public synchronized void write(byte[] bs, int off, int len)
-                throws IOException
+                    throws IOException
             {
                 if ((off < 0) || (off > bs.length) || (len < 0) ||
                     ((off + len) > bs.length) || ((off + len) < 0)) {
@@ -344,12 +344,11 @@
      *
      * @return  A new readable byte channel
      */
-    public static ReadableByteChannel newChannel(final InputStream in) {
-        checkNotNull(in, "in");
+    public static ReadableByteChannel newChannel(InputStream in) {
+        Objects.requireNonNull(in, "in");
 
-        if (in instanceof FileInputStream &&
-            FileInputStream.class.equals(in.getClass())) {
-            return ((FileInputStream)in).getChannel();
+        if (in.getClass() == FileInputStream.class) {
+            return ((FileInputStream) in).getChannel();
         }
 
         return new ReadableByteChannelImpl(in);
@@ -359,17 +358,21 @@
         extends AbstractInterruptibleChannel    // Not really interruptible
         implements ReadableByteChannel
     {
-        InputStream in;
+        private final InputStream in;
         private static final int TRANSFER_SIZE = 8192;
-        private byte buf[] = new byte[0];
-        private boolean open = true;
-        private Object readLock = new Object();
+        private byte[] buf = new byte[0];
+        private final Object readLock = new Object();
 
         ReadableByteChannelImpl(InputStream in) {
             this.in = in;
         }
 
+        @Override
         public int read(ByteBuffer dst) throws IOException {
+            if (!isOpen()) {
+                throw new ClosedChannelException();
+            }
+
             int len = dst.remaining();
             int totalRead = 0;
             int bytesRead = 0;
@@ -400,9 +403,9 @@
             }
         }
 
+        @Override
         protected void implCloseChannel() throws IOException {
             in.close();
-            open = false;
         }
     }
 
@@ -420,7 +423,7 @@
      * @return  A new writable byte channel
      */
     public static WritableByteChannel newChannel(final OutputStream out) {
-        checkNotNull(out, "out");
+        Objects.requireNonNull(out, "out");
         return new WritableByteChannelImpl(out);
     }
 
@@ -428,17 +431,21 @@
         extends AbstractInterruptibleChannel    // Not really interruptible
         implements WritableByteChannel
     {
-        OutputStream out;
+        private final OutputStream out;
         private static final int TRANSFER_SIZE = 8192;
-        private byte buf[] = new byte[0];
-        private boolean open = true;
-        private Object writeLock = new Object();
+        private byte[] buf = new byte[0];
+        private final Object writeLock = new Object();
 
         WritableByteChannelImpl(OutputStream out) {
             this.out = out;
         }
 
+        @Override
         public int write(ByteBuffer src) throws IOException {
+            if (!isOpen()) {
+                throw new ClosedChannelException();
+            }
+
             int len = src.remaining();
             int totalWritten = 0;
             synchronized (writeLock) {
@@ -460,9 +467,9 @@
             }
         }
 
+        @Override
         protected void implCloseChannel() throws IOException {
             out.close();
-            open = false;
         }
     }
 
@@ -474,7 +481,7 @@
      * given decoder.
      *
      * <p> The resulting stream will contain an internal input buffer of at
-     * least <tt>minBufferCap</tt> bytes.  The stream's <tt>read</tt> methods
+     * least {@code minBufferCap} bytes.  The stream's {@code read} methods
      * will, as needed, fill the buffer by reading bytes from the underlying
      * channel; if the channel is in non-blocking mode when bytes are to be
      * read then an {@link IllegalBlockingModeException} will be thrown.  The
@@ -490,7 +497,7 @@
      *
      * @param  minBufferCap
      *         The minimum capacity of the internal byte buffer,
-     *         or <tt>-1</tt> if an implementation-dependent
+     *         or {@code -1} if an implementation-dependent
      *         default capacity is to be used
      *
      * @return  A new reader
@@ -499,7 +506,7 @@
                                    CharsetDecoder dec,
                                    int minBufferCap)
     {
-        checkNotNull(ch, "ch");
+        Objects.requireNonNull(ch, "ch");
         return StreamDecoder.forDecoder(ch, dec.reset(), minBufferCap);
     }
 
@@ -509,16 +516,15 @@
      *
      * <p> An invocation of this method of the form
      *
-     * <blockquote><pre>
-     * Channels.newReader(ch, csname)</pre></blockquote>
+     * <pre> {@code
+     *     Channels.newReader(ch, csname)
+     * } </pre>
      *
      * behaves in exactly the same way as the expression
      *
-     * <blockquote><pre>
-     * Channels.newReader(ch,
-     *                    Charset.forName(csName)
-     *                        .newDecoder(),
-     *                    -1);</pre></blockquote>
+     * <pre> {@code
+     *     Channels.newReader(ch, Charset.forName(csName))
+     * } </pre>
      *
      * @param  ch
      *         The channel from which bytes will be read
@@ -535,16 +541,48 @@
     public static Reader newReader(ReadableByteChannel ch,
                                    String csName)
     {
-        checkNotNull(csName, "csName");
+        Objects.requireNonNull(csName, "csName");
         return newReader(ch, Charset.forName(csName).newDecoder(), -1);
     }
 
     /**
+     * Constructs a reader that decodes bytes from the given channel according
+     * to the given charset.
+     *
+     * <p> An invocation of this method of the form
+     *
+     * <pre> {@code
+     *     Channels.newReader(ch, charset)
+     * } </pre>
+     *
+     * behaves in exactly the same way as the expression
+     *
+     * <pre> {@code
+     *     Channels.newReader(ch, Charset.forName(csName).newDecoder(), -1)
+     * } </pre>
+     *
+     * <p> The reader's default action for malformed-input and unmappable-character
+     * errors is to {@linkplain java.nio.charset.CodingErrorAction#REPORT report}
+     * them. When more control over the error handling is required, the constructor
+     * that takes a {@linkplain java.nio.charset.CharsetDecoder} should be used.
+     *
+     * @param  ch The channel from which bytes will be read
+     *
+     * @param  charset The charset to be used
+     *
+     * @return  A new reader
+     */
+    public static Reader newReader(ReadableByteChannel ch, Charset charset) {
+        Objects.requireNonNull(charset, "charset");
+        return newReader(ch, charset.newDecoder(), -1);
+    }
+
+    /**
      * Constructs a writer that encodes characters using the given encoder and
      * writes the resulting bytes to the given channel.
      *
      * <p> The resulting stream will contain an internal output buffer of at
-     * least <tt>minBufferCap</tt> bytes.  The stream's <tt>write</tt> methods
+     * least {@code minBufferCap} bytes.  The stream's {@code write} methods
      * will, as needed, flush the buffer by writing bytes to the underlying
      * channel; if the channel is in non-blocking mode when bytes are to be
      * written then an {@link IllegalBlockingModeException} will be thrown.
@@ -559,16 +597,16 @@
      *
      * @param  minBufferCap
      *         The minimum capacity of the internal byte buffer,
-     *         or <tt>-1</tt> if an implementation-dependent
+     *         or {@code -1} if an implementation-dependent
      *         default capacity is to be used
      *
      * @return  A new writer
      */
-    public static Writer newWriter(final WritableByteChannel ch,
-                                   final CharsetEncoder enc,
-                                   final int minBufferCap)
+    public static Writer newWriter(WritableByteChannel ch,
+                                   CharsetEncoder enc,
+                                   int minBufferCap)
     {
-        checkNotNull(ch, "ch");
+        Objects.requireNonNull(ch, "ch");
         return StreamEncoder.forEncoder(ch, enc.reset(), minBufferCap);
     }
 
@@ -578,16 +616,15 @@
      *
      * <p> An invocation of this method of the form
      *
-     * <blockquote><pre>
-     * Channels.newWriter(ch, csname)</pre></blockquote>
+     * <pre> {@code
+     *     Channels.newWriter(ch, csname)
+     * } </pre>
      *
      * behaves in exactly the same way as the expression
      *
-     * <blockquote><pre>
-     * Channels.newWriter(ch,
-     *                    Charset.forName(csName)
-     *                        .newEncoder(),
-     *                    -1);</pre></blockquote>
+     * <pre> {@code
+     *     Channels.newWriter(ch, Charset.forName(csName))
+     * } </pre>
      *
      * @param  ch
      *         The channel to which bytes will be written
@@ -604,7 +641,41 @@
     public static Writer newWriter(WritableByteChannel ch,
                                    String csName)
     {
-        checkNotNull(csName, "csName");
+        Objects.requireNonNull(csName, "csName");
         return newWriter(ch, Charset.forName(csName).newEncoder(), -1);
     }
+
+    /**
+     * Constructs a writer that encodes characters according to the given
+     * charset and writes the resulting bytes to the given channel.
+     *
+     * <p> An invocation of this method of the form
+     *
+     * <pre> {@code
+     *     Channels.newWriter(ch, charset)
+     * } </pre>
+     *
+     * behaves in exactly the same way as the expression
+     *
+     * <pre> {@code
+     *     Channels.newWriter(ch, Charset.forName(csName).newEncoder(), -1)
+     * } </pre>
+     *
+     * <p> The writer's default action for malformed-input and unmappable-character
+     * errors is to {@linkplain java.nio.charset.CodingErrorAction#REPORT report}
+     * them. When more control over the error handling is required, the constructor
+     * that takes a {@linkplain java.nio.charset.CharsetEncoder} should be used.
+     *
+     * @param  ch
+     *         The channel to which bytes will be written
+     *
+     * @param  charset
+     *         The charset to be used
+     *
+     * @return  A new writer
+     */
+    public static Writer newWriter(WritableByteChannel ch, Charset charset) {
+        Objects.requireNonNull(charset, "charset");
+        return newWriter(ch, charset.newEncoder(), -1);
+}
 }
diff --git a/ojluni/src/main/java/java/nio/channels/SelectionKey.java b/ojluni/src/main/java/java/nio/channels/SelectionKey.java
index 00ea670..2a96d3d 100644
--- a/ojluni/src/main/java/java/nio/channels/SelectionKey.java
+++ b/ojluni/src/main/java/java/nio/channels/SelectionKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,6 @@
 package java.nio.channels;
 
 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-import java.io.IOException;
-
 
 /**
  * A token representing the registration of a {@link SelectableChannel} with a
@@ -42,7 +40,7 @@
  * next selection operation.  The validity of a key may be tested by invoking
  * its {@link #isValid isValid} method.
  *
- * <a name="opsets"></a>
+ * <a id="opsets"></a>
  *
  * <p> A selection key contains two <i>operation sets</i> represented as
  * integer values.  Each bit of an operation set denotes a category of
@@ -88,15 +86,9 @@
  * attached via the {@link #attach attach} method and then later retrieved via
  * the {@link #attachment() attachment} method.
  *
- * <p> Selection keys are safe for use by multiple concurrent threads.  The
- * operations of reading and writing the interest set will, in general, be
- * synchronized with certain operations of the selector.  Exactly how this
- * synchronization is performed is implementation-dependent: In a naive
- * implementation, reading or writing the interest set may block indefinitely
- * if a selection operation is already in progress; in a high-performance
- * implementation, reading or writing the interest set may block briefly, if at
- * all.  In any case, a selection operation will always use the interest-set
- * value that was current at the moment that the operation began.  </p>
+ * <p> Selection keys are safe for use by multiple concurrent threads.  A
+ * selection operation will always use the interest-set value that was current
+ * at the moment that the operation began.  </p>
  *
  *
  * @author Mark Reinhold
@@ -139,7 +131,7 @@
      * <p> A key is valid upon creation and remains so until it is cancelled,
      * its channel is closed, or its selector is closed.  </p>
      *
-     * @return  <tt>true</tt> if, and only if, this key is valid
+     * @return  {@code true} if, and only if, this key is valid
      */
     public abstract boolean isValid();
 
@@ -166,10 +158,7 @@
      * Retrieves this key's interest set.
      *
      * <p> It is guaranteed that the returned set will only contain operation
-     * bits that are valid for this key's channel.
-     *
-     * <p> This method may be invoked at any time.  Whether or not it blocks,
-     * and for how long, is implementation-dependent.  </p>
+     * bits that are valid for this key's channel. </p>
      *
      * @return  This key's interest set
      *
@@ -181,8 +170,10 @@
     /**
      * Sets this key's interest set to the given value.
      *
-     * <p> This method may be invoked at any time.  Whether or not it blocks,
-     * and for how long, is implementation-dependent.  </p>
+     * <p> This method may be invoked at any time.  If this method is invoked
+     * while a selection operation is in progress then it has no effect upon
+     * that operation; the change to the key's interest set will be seen by the
+     * next selection operation.
      *
      * @param  ops  The new interest set
      *
@@ -199,6 +190,83 @@
     public abstract SelectionKey interestOps(int ops);
 
     /**
+     * Atomically sets this key's interest set to the bitwise union ("or") of
+     * the existing interest set and the given value. This method is guaranteed
+     * to be atomic with respect to other concurrent calls to this method or to
+     * {@link #interestOpsAnd(int)}.
+     *
+     * <p> This method may be invoked at any time.  If this method is invoked
+     * while a selection operation is in progress then it has no effect upon
+     * that operation; the change to the key's interest set will be seen by the
+     * next selection operation.
+     *
+     * @implSpec The default implementation synchronizes on this key and invokes
+     * {@code interestOps()} and {@code interestOps(int)} to retrieve and set
+     * this key's interest set.
+     *
+     * @param  ops  The interest set to apply
+     *
+     * @return  The previous interest set
+     *
+     * @throws  IllegalArgumentException
+     *          If a bit in the set does not correspond to an operation that
+     *          is supported by this key's channel, that is, if
+     *          {@code (ops & ~channel().validOps()) != 0}
+     *
+     * @throws  CancelledKeyException
+     *          If this key has been cancelled
+     *
+     * @since 11
+     */
+    public int interestOpsOr(int ops) {
+        synchronized (this) {
+            int oldVal = interestOps();
+            interestOps(oldVal | ops);
+            return oldVal;
+        }
+    }
+
+    /**
+     * Atomically sets this key's interest set to the bitwise intersection ("and")
+     * of the existing interest set and the given value. This method is guaranteed
+     * to be atomic with respect to other concurrent calls to this method or to
+     * {@link #interestOpsOr(int)}.
+     *
+     * <p> This method may be invoked at any time.  If this method is invoked
+     * while a selection operation is in progress then it has no effect upon
+     * that operation; the change to the key's interest set will be seen by the
+     * next selection operation.
+     *
+     * @apiNote Unlike the {@code interestOps(int)} and {@code interestOpsOr(int)}
+     * methods, this method does not throw {@code IllegalArgumentException} when
+     * invoked with bits in the interest set that do not correspond to an
+     * operation that is supported by this key's channel. This is to allow
+     * operation bits in the interest set to be cleared using bitwise complement
+     * values, e.g., {@code interestOpsAnd(~SelectionKey.OP_READ)} will remove
+     * the {@code OP_READ} from the interest set without affecting other bits.
+     *
+     * @implSpec The default implementation synchronizes on this key and invokes
+     * {@code interestOps()} and {@code interestOps(int)} to retrieve and set
+     * this key's interest set.
+     *
+     * @param  ops  The interest set to apply
+     *
+     * @return  The previous interest set
+     *
+     * @throws  CancelledKeyException
+     *          If this key has been cancelled
+     *
+     * @since 11
+     */
+    public int interestOpsAnd(int ops) {
+        synchronized (this) {
+            int oldVal = interestOps();
+            interestOps(oldVal & ops);
+            return oldVal;
+        }
+    }
+
+    /**
      * Retrieves this key's ready-operation set.
      *
      * <p> It is guaranteed that the returned set will only contain operation
@@ -218,12 +286,12 @@
      * Operation-set bit for read operations.
      *
      * <p> Suppose that a selection key's interest set contains
-     * <tt>OP_READ</tt> at the start of a <a
+     * {@code OP_READ} at the start of a <a
      * href="Selector.html#selop">selection operation</a>.  If the selector
      * detects that the corresponding channel is ready for reading, has reached
      * end-of-stream, has been remotely shut down for further reading, or has
-     * an error pending, then it will add <tt>OP_READ</tt> to the key's
-     * ready-operation set and add the key to its selected-key&nbsp;set.  </p>
+     * an error pending, then it will add {@code OP_READ} to the key's
+     * ready-operation set.  </p>
      */
     public static final int OP_READ = 1 << 0;
 
@@ -231,12 +299,11 @@
      * Operation-set bit for write operations.
      *
      * <p> Suppose that a selection key's interest set contains
-     * <tt>OP_WRITE</tt> at the start of a <a
+     * {@code OP_WRITE} at the start of a <a
      * href="Selector.html#selop">selection operation</a>.  If the selector
      * detects that the corresponding channel is ready for writing, has been
      * remotely shut down for further writing, or has an error pending, then it
-     * will add <tt>OP_WRITE</tt> to the key's ready set and add the key to its
-     * selected-key&nbsp;set.  </p>
+     * will add {@code OP_WRITE} to the key's ready set.  </p>
      */
     public static final int OP_WRITE = 1 << 2;
 
@@ -244,12 +311,11 @@
      * Operation-set bit for socket-connect operations.
      *
      * <p> Suppose that a selection key's interest set contains
-     * <tt>OP_CONNECT</tt> at the start of a <a
+     * {@code OP_CONNECT} at the start of a <a
      * href="Selector.html#selop">selection operation</a>.  If the selector
      * detects that the corresponding socket channel is ready to complete its
      * connection sequence, or has an error pending, then it will add
-     * <tt>OP_CONNECT</tt> to the key's ready set and add the key to its
-     * selected-key&nbsp;set.  </p>
+     * {@code OP_CONNECT} to the key's ready set.  </p>
      */
     public static final int OP_CONNECT = 1 << 3;
 
@@ -257,19 +323,18 @@
      * Operation-set bit for socket-accept operations.
      *
      * <p> Suppose that a selection key's interest set contains
-     * <tt>OP_ACCEPT</tt> at the start of a <a
+     * {@code OP_ACCEPT} at the start of a <a
      * href="Selector.html#selop">selection operation</a>.  If the selector
      * detects that the corresponding server-socket channel is ready to accept
      * another connection, or has an error pending, then it will add
-     * <tt>OP_ACCEPT</tt> to the key's ready set and add the key to its
-     * selected-key&nbsp;set.  </p>
+     * {@code OP_ACCEPT} to the key's ready set.  </p>
      */
     public static final int OP_ACCEPT = 1 << 4;
 
     /**
      * Tests whether this key's channel is ready for reading.
      *
-     * <p> An invocation of this method of the form <tt>k.isReadable()</tt>
+     * <p> An invocation of this method of the form {@code k.isReadable()}
      * behaves in exactly the same way as the expression
      *
      * <blockquote><pre>{@code
@@ -277,9 +342,9 @@
      * }</pre></blockquote>
      *
      * <p> If this key's channel does not support read operations then this
-     * method always returns <tt>false</tt>.  </p>
+     * method always returns {@code false}.  </p>
      *
-     * @return  <tt>true</tt> if, and only if,
+     * @return  {@code true} if, and only if,
                 {@code readyOps() & OP_READ} is nonzero
      *
      * @throws  CancelledKeyException
@@ -292,7 +357,7 @@
     /**
      * Tests whether this key's channel is ready for writing.
      *
-     * <p> An invocation of this method of the form <tt>k.isWritable()</tt>
+     * <p> An invocation of this method of the form {@code k.isWritable()}
      * behaves in exactly the same way as the expression
      *
      * <blockquote><pre>{@code
@@ -300,9 +365,9 @@
      * }</pre></blockquote>
      *
      * <p> If this key's channel does not support write operations then this
-     * method always returns <tt>false</tt>.  </p>
+     * method always returns {@code false}.  </p>
      *
-     * @return  <tt>true</tt> if, and only if,
+     * @return  {@code true} if, and only if,
      *          {@code readyOps() & OP_WRITE} is nonzero
      *
      * @throws  CancelledKeyException
@@ -316,7 +381,7 @@
      * Tests whether this key's channel has either finished, or failed to
      * finish, its socket-connection operation.
      *
-     * <p> An invocation of this method of the form <tt>k.isConnectable()</tt>
+     * <p> An invocation of this method of the form {@code k.isConnectable()}
      * behaves in exactly the same way as the expression
      *
      * <blockquote><pre>{@code
@@ -324,9 +389,9 @@
      * }</pre></blockquote>
      *
      * <p> If this key's channel does not support socket-connect operations
-     * then this method always returns <tt>false</tt>.  </p>
+     * then this method always returns {@code false}.  </p>
      *
-     * @return  <tt>true</tt> if, and only if,
+     * @return  {@code true} if, and only if,
      *          {@code readyOps() & OP_CONNECT} is nonzero
      *
      * @throws  CancelledKeyException
@@ -340,7 +405,7 @@
      * Tests whether this key's channel is ready to accept a new socket
      * connection.
      *
-     * <p> An invocation of this method of the form <tt>k.isAcceptable()</tt>
+     * <p> An invocation of this method of the form {@code k.isAcceptable()}
      * behaves in exactly the same way as the expression
      *
      * <blockquote><pre>{@code
@@ -348,9 +413,9 @@
      * }</pre></blockquote>
      *
      * <p> If this key's channel does not support socket-accept operations then
-     * this method always returns <tt>false</tt>.  </p>
+     * this method always returns {@code false}.  </p>
      *
-     * @return  <tt>true</tt> if, and only if,
+     * @return  {@code true} if, and only if,
      *          {@code readyOps() & OP_ACCEPT} is nonzero
      *
      * @throws  CancelledKeyException
@@ -363,7 +428,7 @@
 
     // -- Attachments --
 
-    private volatile Object attachment = null;
+    private volatile Object attachment;
 
     private static final AtomicReferenceFieldUpdater<SelectionKey,Object>
         attachmentUpdater = AtomicReferenceFieldUpdater.newUpdater(
@@ -376,13 +441,13 @@
      * <p> An attached object may later be retrieved via the {@link #attachment()
      * attachment} method.  Only one object may be attached at a time; invoking
      * this method causes any previous attachment to be discarded.  The current
-     * attachment may be discarded by attaching <tt>null</tt>.  </p>
+     * attachment may be discarded by attaching {@code null}.  </p>
      *
      * @param  ob
-     *         The object to be attached; may be <tt>null</tt>
+     *         The object to be attached; may be {@code null}
      *
      * @return  The previously-attached object, if any,
-     *          otherwise <tt>null</tt>
+     *          otherwise {@code null}
      */
     public final Object attach(Object ob) {
         return attachmentUpdater.getAndSet(this, ob);
@@ -392,7 +457,7 @@
      * Retrieves the current attachment.
      *
      * @return  The object currently attached to this key,
-     *          or <tt>null</tt> if there is no attachment
+     *          or {@code null} if there is no attachment
      */
     public final Object attachment() {
         return attachment;
diff --git a/ojluni/src/main/java/java/nio/channels/Selector.java b/ojluni/src/main/java/java/nio/channels/Selector.java
index ea72acb..4fb98f3 100644
--- a/ojluni/src/main/java/java/nio/channels/Selector.java
+++ b/ojluni/src/main/java/java/nio/channels/Selector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,9 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.Objects;
 import java.util.Set;
+import java.util.function.Consumer;
 
 
 /**
@@ -42,7 +44,7 @@
  * method of a custom selector provider.  A selector remains open until it is
  * closed via its {@link #close close} method.
  *
- * <a name="ks"></a>
+ * <a id="ks"></a>
  *
  * <p> A selectable channel's registration with a selector is represented by a
  * {@link SelectionKey} object.  A selector maintains three sets of selection
@@ -56,7 +58,8 @@
  *
  *   <li><p> The <i>selected-key set</i> is the set of keys such that each
  *   key's channel was detected to be ready for at least one of the operations
- *   identified in the key's interest set during a prior selection operation.
+ *   identified in the key's interest set during a prior selection operation
+ *   that adds keys or updates keys in the set.
  *   This set is returned by the {@link #selectedKeys() selectedKeys} method.
  *   The selected-key set is always a subset of the key set. </p></li>
  *
@@ -77,22 +80,42 @@
  * <p> A key is added to its selector's cancelled-key set when it is cancelled,
  * whether by closing its channel or by invoking its {@link SelectionKey#cancel
  * cancel} method.  Cancelling a key will cause its channel to be deregistered
- * during the next selection operation, at which time the key will removed from
- * all of the selector's key sets.
+ * during the next selection operation, at which time the key will be removed
+ * from all of the selector's key sets.
  *
- * <a name="sks"></a><p> Keys are added to the selected-key set by selection
+ * <a id="sks"></a><p> Keys are added to the selected-key set by selection
  * operations.  A key may be removed directly from the selected-key set by
  * invoking the set's {@link java.util.Set#remove(java.lang.Object) remove}
  * method or by invoking the {@link java.util.Iterator#remove() remove} method
- * of an {@link java.util.Iterator iterator} obtained from the
- * set.  Keys are never removed from the selected-key set in any other way;
- * they are not, in particular, removed as a side effect of selection
- * operations.  Keys may not be added directly to the selected-key set. </p>
+ * of an {@link java.util.Iterator iterator} obtained from the set.
+ * All keys may be removed from the selected-key set by invoking the set's
+ * {@link java.util.Set#clear() clear} method.  Keys may not be added directly
+ * to the selected-key set. </p>
  *
- *
- * <a name="selop"></a>
+ * <a id="selop"></a>
  * <h2>Selection</h2>
  *
+ * <p> A selection operation queries the underlying operating system for an
+ * update as to the readiness of each registered channel to perform any of the
+ * operations identified by its key's interest set.  There are two forms of
+ * selection operation:
+ *
+ * <ol>
+ *
+ *   <li><p> The {@link #select()}, {@link #select(long)}, and {@link #selectNow()}
+ *   methods add the keys of channels ready to perform an operation to the
+ *   selected-key set, or update the ready-operation set of keys already in the
+ *   selected-key set. </p></li>
+ *
+ *   <li><p> The {@link #select(Consumer)}, {@link #select(Consumer, long)}, and
+ *   {@link #selectNow(Consumer)} methods perform an <i>action</i> on the key
+ *   of each channel that is ready to perform an operation.  These methods do
+ *   not add to the selected-key set. </p></li>
+ *
+ * </ol>
+ *
+ * <h3>Selection operations that add to the selected-key set</h3>
+ *
  * <p> During each selection operation, keys may be added to and removed from a
  * selector's selected-key set and may be removed from its key and
  * cancelled-key sets.  Selection is performed by the {@link #select()}, {@link
@@ -142,14 +165,53 @@
  * difference between the three selection methods. </p>
  *
  *
+ * <h3>Selection operations that perform an action on selected keys</h3>
+ *
+ * <p> During each selection operation, keys may be removed from the selector's
+ * key, selected-key, and cancelled-key sets.  Selection is performed by the
+ * {@link #select(Consumer)}, {@link #select(Consumer,long)}, and {@link
+ * #selectNow(Consumer)} methods, and involves three steps:  </p>
+ *
+ * <ol>
+ *
+ *   <li><p> Each key in the cancelled-key set is removed from each key set of
+ *   which it is a member, and its channel is deregistered.  This step leaves
+ *   the cancelled-key set empty. </p></li>
+ *
+ *   <li><p> The underlying operating system is queried for an update as to the
+ *   readiness of each remaining channel to perform any of the operations
+ *   identified by its key's interest set as of the moment that the selection
+ *   operation began.
+ *
+ *   <p> For a channel that is ready for at least one such operation, the
+ *   ready-operation set of the channel's key is set to identify exactly the
+ *   operations for which the channel is ready and the <i>action</i> specified
+ *   to the {@code select} method is invoked to consume the channel's key.  Any
+ *   readiness information previously recorded in the ready set is discarded
+ *   prior to invoking the <i>action</i>.
+ *
+ *   <p> Alternatively, where a channel is ready for more than one operation,
+ *   the <i>action</i> may be invoked more than once with the channel's key and
+ *   ready-operation set modified to a subset of the operations for which the
+ *   channel is ready.  Where the <i>action</i> is invoked more than once for
+ *   the same key then its ready-operation set never contains operation bits
+ *   that were contained in the set at previous calls to the <i>action</i>
+ *   in the same selection operation.  </p></li>
+ *
+ *   <li><p> If any keys were added to the cancelled-key set while step (2) was
+ *   in progress then they are processed as in step (1). </p></li>
+ *
+ * </ol>
+ *
+ *
  * <h2>Concurrency</h2>
  *
- * <p> Selectors are themselves safe for use by multiple concurrent threads;
- * their key sets, however, are not.
+ * <p> A Selector and its key set are safe for use by multiple concurrent
+ * threads.  Its selected-key set and cancelled-key set, however, are not.
  *
- * <p> The selection operations synchronize on the selector itself, on the key
- * set, and on the selected-key set, in that order.  They also synchronize on
- * the cancelled-key set during steps (1) and (3) above.
+ * <p> The selection operations synchronize on the selector itself, on the
+ * selected-key set, in that order.  They also synchronize on the cancelled-key
+ * set during steps (1) and (3) above.
  *
  * <p> Changes made to the interest sets of a selector's keys while a
  * selection operation is in progress have no effect upon that operation; they
@@ -157,13 +219,12 @@
  *
  * <p> Keys may be cancelled and channels may be closed at any time.  Hence the
  * presence of a key in one or more of a selector's key sets does not imply
- * that the key is valid or that its channel is open.  Application code should
+ * that the key is valid or that its channel is open. Application code should
  * be careful to synchronize and check these conditions as necessary if there
  * is any possibility that another thread will cancel a key or close a channel.
  *
- * <p> A thread blocked in one of the {@link #select()} or {@link
- * #select(long)} methods may be interrupted by some other thread in one of
- * three ways:
+ * <p> A thread blocked in a selection operation may be interrupted by some
+ * other thread in one of three ways:
  *
  * <ul>
  *
@@ -180,20 +241,27 @@
  *
  * </ul>
  *
- * <p> The {@link #close close} method synchronizes on the selector and all
- * three key sets in the same order as in a selection operation.
+ * <p> The {@link #close close} method synchronizes on the selector and its
+ * selected-key set in the same order as in a selection operation.
  *
- * <a name="ksc"></a>
+ * <a id="ksc"></a>
+ * <p> A Selector's key set is safe for use by multiple concurrent threads.
+ * Retrieval operations from the key set do not generally block and so may
+ * overlap with new registrations that add to the set, or with the cancellation
+ * steps of selection operations that remove keys from the set.  Iterators and
+ * spliterators return elements reflecting the state of the set at some point at
+ * or since the creation of the iterator/spliterator.  They do not throw
+ * {@link java.util.ConcurrentModificationException ConcurrentModificationException}.
  *
- * <p> A selector's key and selected-key sets are not, in general, safe for use
- * by multiple concurrent threads.  If such a thread might modify one of these
- * sets directly then access should be controlled by synchronizing on the set
- * itself.  The iterators returned by these sets' {@link
- * java.util.Set#iterator() iterator} methods are <i>fail-fast:</i> If the set
- * is modified after the iterator is created, in any way except by invoking the
- * iterator's own {@link java.util.Iterator#remove() remove} method, then a
- * {@link java.util.ConcurrentModificationException} will be thrown. </p>
- *
+ * <a id="sksc"></a>
+ * <p> A selector's selected-key set is not, in general, safe for use by
+ * multiple concurrent threads.  If such a thread might modify the set directly
+ * then access should be controlled by synchronizing on the set itself.  The
+ * iterators returned by the set's {@link java.util.Set#iterator() iterator}
+ * methods are <i>fail-fast:</i> If the set is modified after the iterator is
+ * created, in any way except by invoking the iterator's own {@link
+ * java.util.Iterator#remove() remove} method, then a {@link
+ * java.util.ConcurrentModificationException} will be thrown. </p>
  *
  * @author Mark Reinhold
  * @author JSR-51 Expert Group
@@ -230,7 +298,7 @@
     /**
      * Tells whether or not this selector is open.
      *
-     * @return <tt>true</tt> if, and only if, this selector is open
+     * @return {@code true} if, and only if, this selector is open
      */
     public abstract boolean isOpen();
 
@@ -249,7 +317,8 @@
      * attempt to modify the key set will cause an {@link
      * UnsupportedOperationException} to be thrown.
      *
-     * <p> The key set is <a href="#ksc">not thread-safe</a>. </p>
+     * <p> The set is <a href="#ksc">safe</a> for use by multiple concurrent
+     * threads.  </p>
      *
      * @return  This selector's key set
      *
@@ -265,7 +334,7 @@
      * selected-key set.  Any attempt to add an object to the key set will
      * cause an {@link UnsupportedOperationException} to be thrown.
      *
-     * <p> The selected-key set is <a href="#ksc">not thread-safe</a>. </p>
+     * <p> The selected-key set is <a href="#sksc">not thread-safe</a>.  </p>
      *
      * @return  This selector's selected-key set
      *
@@ -309,7 +378,7 @@
      * <p> This method does not offer real-time guarantees: It schedules the
      * timeout as if by invoking the {@link Object#wait(long)} method. </p>
      *
-     * @param  timeout  If positive, block for up to <tt>timeout</tt>
+     * @param  timeout  If positive, block for up to {@code timeout}
      *                  milliseconds, more or less, while waiting for a
      *                  channel to become ready; if zero, block indefinitely;
      *                  must not be negative
@@ -326,8 +395,7 @@
      * @throws  IllegalArgumentException
      *          If the value of the timeout argument is negative
      */
-    public abstract int select(long timeout)
-        throws IOException;
+    public abstract int select(long timeout) throws IOException;
 
     /**
      * Selects a set of keys whose corresponding channels are ready for I/O
@@ -350,18 +418,188 @@
     public abstract int select() throws IOException;
 
     /**
+     * Selects and performs an action on the keys whose corresponding channels
+     * are ready for I/O operations.
+     *
+     * <p> This method performs a blocking <a href="#selop">selection
+     * operation</a>.  It wakes up from querying the operating system only when
+     * at least one channel is selected, this selector's {@link #wakeup wakeup}
+     * method is invoked, the current thread is interrupted, or the given
+     * timeout period expires, whichever comes first.
+     *
+     * <p> The specified <i>action</i>'s {@link Consumer#accept(Object) accept}
+     * method is invoked with the key for each channel that is ready to perform
+     * an operation identified by its key's interest set.  The {@code accept}
+     * method may be invoked more than once for the same key but with the
+     * ready-operation set containing a subset of the operations for which the
+     * channel is ready (as described above).  The {@code accept} method is
+     * invoked while synchronized on the selector and its selected-key set.
+     * Great care must be taken to avoid deadlocking with other threads that
+     * also synchronize on these objects.  Selection operations are not reentrant
+     * in general and consequently the <i>action</i> should take great care not
+     * to attempt a selection operation on the same selector.  The behavior when
+     * attempting a reentrant selection operation is implementation specific and
+     * therefore not specified.  If the <i>action</i> closes the selector then
+     * {@code ClosedSelectorException} is thrown when the action completes.
+     * The <i>action</i> is not prohibited from closing channels registered with
+     * the selector, nor prohibited from cancelling keys or changing a key's
+     * interest set.  If a channel is selected but its key is cancelled or its
+     * interest set changed before the <i>action</i> is performed on the key
+     * then it is implementation specific as to whether the <i>action</i> is
+     * invoked (it may be invoked with an {@link SelectionKey#isValid() invalid}
+     * key).  Exceptions thrown by the action are relayed to the caller.
+     *
+     * <p> This method does not offer real-time guarantees: It schedules the
+     * timeout as if by invoking the {@link Object#wait(long)} method.
+     *
+     * @implSpec The default implementation removes all keys from the
+     * selected-key set, invokes {@link #select(long) select(long)} with the
+     * given timeout and then performs the action for each key added to the
+     * selected-key set.  The default implementation does not detect the action
+     * performing a reentrant selection operation.  The selected-key set may
+     * or may not be empty on completion of the default implementation.
+     *
+     * @param  action   The action to perform
+     *
+     * @param  timeout  If positive, block for up to {@code timeout}
+     *                  milliseconds, more or less, while waiting for a
+     *                  channel to become ready; if zero, block indefinitely;
+     *                  must not be negative
+     *
+     * @return  The number of unique keys consumed, possibly zero
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @throws  ClosedSelectorException
+     *          If this selector is closed or is closed by the action
+     *
+     * @throws  IllegalArgumentException
+     *          If the value of the timeout argument is negative
+     *
+     * @since 11
+     */
+    public int select(Consumer<SelectionKey> action, long timeout)
+        throws IOException
+    {
+        if (timeout < 0)
+            throw new IllegalArgumentException("Negative timeout");
+        return doSelect(Objects.requireNonNull(action), timeout);
+    }
+
+    /**
+     * Selects and performs an action on the keys whose corresponding channels
+     * are ready for I/O operations.
+     *
+     * <p> This method performs a blocking <a href="#selop">selection
+     * operation</a>.  It wakes up from querying the operating system only when
+     * at least one channel is selected, this selector's {@link #wakeup wakeup}
+     * method is invoked, or the current thread is interrupted, whichever comes
+     * first.
+     *
+     * <p> This method is equivalent to invoking the 2-arg
+     * {@link #select(Consumer, long) select} method with a timeout of {@code 0}
+     * to block indefinitely.  </p>
+     *
+     * @implSpec The default implementation invokes the 2-arg {@code select}
+     * method with a timeout of {@code 0}.
+     *
+     * @param  action   The action to perform
+     *
+     * @return  The number of unique keys consumed, possibly zero
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @throws  ClosedSelectorException
+     *          If this selector is closed or is closed by the action
+     *
+     * @since 11
+     */
+    public int select(Consumer<SelectionKey> action) throws IOException {
+        return select(action, 0);
+    }
+
+    /**
+     * Selects and performs an action on the keys whose corresponding channels
+     * are ready for I/O operations.
+     *
+     * <p> This method performs a non-blocking <a href="#selop">selection
+     * operation</a>.
+     *
+     * <p> Invoking this method clears the effect of any previous invocations
+     * of the {@link #wakeup wakeup} method.  </p>
+     *
+     * @implSpec The default implementation removes all keys from the
+     * selected-key set, invokes {@link #selectNow() selectNow()} and then
+     * performs the action for each key added to the selected-key set.  The
+     * default implementation does not detect the action performing a reentrant
+     * selection operation.  The selected-key set may or may not be empty on
+     * completion of the default implementation.
+     *
+     * @param  action   The action to perform
+     *
+     * @return  The number of unique keys consumed, possibly zero
+     *
+     * @throws  IOException
+     *          If an I/O error occurs
+     *
+     * @throws  ClosedSelectorException
+     *          If this selector is closed or is closed by the action
+     *
+     * @since 11
+     */
+    public int selectNow(Consumer<SelectionKey> action) throws IOException {
+        return doSelect(Objects.requireNonNull(action), -1);
+    }
+
+    /**
+     * Default implementation of select(Consumer) and selectNow(Consumer).
+     */
+    private int doSelect(Consumer<SelectionKey> action, long timeout)
+        throws IOException
+    {
+        synchronized (this) {
+            Set<SelectionKey> selectedKeys = selectedKeys();
+            synchronized (selectedKeys) {
+                selectedKeys.clear();
+                int numKeySelected;
+                if (timeout < 0) {
+                    numKeySelected = selectNow();
+                } else {
+                    numKeySelected = select(timeout);
+                }
+
+                // copy selected-key set as action may remove keys
+                Set<SelectionKey> keysToConsume = Set.copyOf(selectedKeys);
+                assert keysToConsume.size() == numKeySelected;
+                selectedKeys.clear();
+
+                // invoke action for each selected key
+                keysToConsume.forEach(k -> {
+                    action.accept(k);
+                    if (!isOpen())
+                        throw new ClosedSelectorException();
+                });
+
+                return numKeySelected;
+            }
+        }
+    }
+
+
+    /**
      * Causes the first selection operation that has not yet returned to return
      * immediately.
      *
-     * <p> If another thread is currently blocked in an invocation of the
-     * {@link #select()} or {@link #select(long)} methods then that invocation
-     * will return immediately.  If no selection operation is currently in
-     * progress then the next invocation of one of these methods will return
-     * immediately unless the {@link #selectNow()} method is invoked in the
-     * meantime.  In any case the value returned by that invocation may be
-     * non-zero.  Subsequent invocations of the {@link #select()} or {@link
-     * #select(long)} methods will block as usual unless this method is invoked
-     * again in the meantime.
+     * <p> If another thread is currently blocked in a selection operation then
+     * that invocation will return immediately.  If no selection operation is
+     * currently in progress then the next invocation of a selection operation
+     * will return immediately unless {@link #selectNow()} or {@link
+     * #selectNow(Consumer)} is invoked in the meantime.  In any case the value
+     * returned by that invocation may be non-zero.  Subsequent selection
+     * operations will block as usual unless this method is invoked again in the
+     * meantime.
      *
      * <p> Invoking this method more than once between two successive selection
      * operations has the same effect as invoking it just once.  </p>
@@ -392,5 +630,4 @@
      *          If an I/O error occurs
      */
     public abstract void close() throws IOException;
-
 }
diff --git a/ojluni/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java b/ojluni/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
index 0de212d..d389df3 100644
--- a/ojluni/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
+++ b/ojluni/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,14 @@
 package java.nio.channels.spi;
 
 import java.io.IOException;
-import java.nio.channels.*;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+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;
 
 
 /**
@@ -67,8 +74,8 @@
     // Lock for registration and configureBlocking operations
     private final Object regLock = new Object();
 
-    // Blocking mode, protected by regLock
-    boolean blocking = true;
+    // True when non-blocking, need regLock to change;
+    private volatile boolean nonBlocking;
 
     /**
      * Initializes a new instance of this class.
@@ -101,7 +108,7 @@
                 if (keys[i] == null)
                     break;
         } else if (keys == null) {
-            keys =  new SelectionKey[3];
+            keys = new SelectionKey[2];
         } else {
             // Grow key array
             int n = keys.length * 2;
@@ -116,14 +123,14 @@
     }
 
     private SelectionKey findKey(Selector sel) {
-        synchronized (keyLock) {
-            if (keys == null)
-                return null;
-            for (int i = 0; i < keys.length; i++)
-                if ((keys[i] != null) && (keys[i].selector() == sel))
-                    return keys[i];
+        assert Thread.holdsLock(keyLock);
+        if (keys == null)
             return null;
-        }
+        for (int i = 0; i < keys.length; i++)
+            if ((keys[i] != null) && (keys[i].selector() == sel))
+                return keys[i];
+        return null;
+
     }
 
     void removeKey(SelectionKey k) {                    // package-private
@@ -159,7 +166,9 @@
     }
 
     public final SelectionKey keyFor(Selector sel) {
-        return findKey(sel);
+        synchronized (keyLock) {
+            return findKey(sel);
+        }
     }
 
     /**
@@ -188,32 +197,31 @@
      *
      * @throws  IllegalArgumentException {@inheritDoc}
      */
-    public final SelectionKey register(Selector sel, int ops,
-                                       Object att)
+    public final SelectionKey register(Selector sel, int ops, Object att)
         throws ClosedChannelException
     {
+        if ((ops & ~validOps()) != 0)
+            throw new IllegalArgumentException();
+        if (!isOpen())
+            throw new ClosedChannelException();
         synchronized (regLock) {
-            if (!isOpen())
-                throw new ClosedChannelException();
-            if ((ops & ~validOps()) != 0)
-                throw new IllegalArgumentException();
-            if (blocking)
+            if (isBlocking())
                 throw new IllegalBlockingModeException();
-            SelectionKey k = findKey(sel);
-            if (k != null) {
-                k.interestOps(ops);
-                k.attach(att);
-            }
-            if (k == null) {
-                // New registration
-                synchronized (keyLock) {
-                    if (!isOpen())
-                        throw new ClosedChannelException();
+            synchronized (keyLock) {
+                // re-check if channel has been closed
+                if (!isOpen())
+                    throw new ClosedChannelException();
+                SelectionKey k = findKey(sel);
+                if (k != null) {
+                    k.attach(att);
+                    k.interestOps(ops);
+                } else {
+                    // New registration
                     k = ((AbstractSelector)sel).register(this, ops, att);
                     addKey(k);
                 }
+                return k;
             }
-            return k;
         }
     }
 
@@ -232,12 +240,20 @@
      */
     protected final void implCloseChannel() throws IOException {
         implCloseSelectableChannel();
+
+        // clone keys to avoid calling cancel when holding keyLock
+        SelectionKey[] copyOfKeys = null;
         synchronized (keyLock) {
-            int count = (keys == null) ? 0 : keys.length;
-            for (int i = 0; i < count; i++) {
-                SelectionKey k = keys[i];
-                if (k != null)
-                    k.cancel();
+            if (keys != null) {
+                copyOfKeys = keys.clone();
+            }
+        }
+
+        if (copyOfKeys != null) {
+            for (SelectionKey k : copyOfKeys) {
+                if (k != null) {
+                    k.cancel();   // invalidate and adds key to cancelledKey set
+                }
             }
         }
     }
@@ -264,9 +280,7 @@
     // -- Blocking --
 
     public final boolean isBlocking() {
-        synchronized (regLock) {
-            return blocking;
-        }
+        return !nonBlocking;
     }
 
     public final Object blockingLock() {
@@ -287,12 +301,13 @@
         synchronized (regLock) {
             if (!isOpen())
                 throw new ClosedChannelException();
-            if (blocking == block)
-                return this;
-            if (block && haveValidKeys())
-                throw new IllegalBlockingModeException();
-            implConfigureBlocking(block);
-            blocking = block;
+            boolean blocking = !nonBlocking;
+            if (block != blocking) {
+                if (block && haveValidKeys())
+                    throw new IllegalBlockingModeException();
+                implConfigureBlocking(block);
+                nonBlocking = !block;
+            }
         }
         return this;
     }
@@ -305,8 +320,8 @@
      * changing the blocking mode.  This method is only invoked if the new mode
      * is different from the current mode.  </p>
      *
-     * @param  block  If <tt>true</tt> then this channel will be placed in
-     *                blocking mode; if <tt>false</tt> then it will be placed
+     * @param  block  If {@code true} then this channel will be placed in
+     *                blocking mode; if {@code false} then it will be placed
      *                non-blocking mode
      *
      * @throws IOException
diff --git a/ojluni/src/main/java/java/nio/channels/spi/AbstractSelector.java b/ojluni/src/main/java/java/nio/channels/spi/AbstractSelector.java
index 09e3b61..9aab22f 100644
--- a/ojluni/src/main/java/java/nio/channels/spi/AbstractSelector.java
+++ b/ojluni/src/main/java/java/nio/channels/spi/AbstractSelector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,9 +43,9 @@
  * after, respectively, invoking an I/O operation that might block
  * indefinitely.  In order to ensure that the {@link #end end} method is always
  * invoked, these methods should be used within a
- * <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block:
+ * {@code try}&nbsp;...&nbsp;{@code finally} block:
  *
- * <blockquote><pre>
+ * <blockquote><pre id="be">
  * try {
  *     begin();
  *     // Perform blocking I/O operation here
@@ -70,7 +70,7 @@
     extends Selector
 {
 
-    private AtomicBoolean selectorOpen = new AtomicBoolean(true);
+    private final AtomicBoolean selectorOpen = new AtomicBoolean(true);
 
     // The provider that created this selector
     private final SelectorProvider provider;
@@ -197,7 +197,7 @@
      * Marks the beginning of an I/O operation that might block indefinitely.
      *
      * <p> This method should be invoked in tandem with the {@link #end end}
-     * method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
+     * method, using a {@code try}&nbsp;...&nbsp;{@code finally} block as
      * shown <a href="#be">above</a>, in order to implement interruption for
      * this selector.
      *
@@ -223,7 +223,7 @@
      * Marks the end of an I/O operation that might block indefinitely.
      *
      * <p> This method should be invoked in tandem with the {@link #begin begin}
-     * method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
+     * method, using a {@code try}&nbsp;...&nbsp;{@code finally} block as
      * shown <a href="#be">above</a>, in order to implement interruption for
      * this selector.  </p>
      */
diff --git a/ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java b/ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java
index 464b4fc..6a77d3d 100644
--- a/ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java
+++ b/ojluni/src/main/java/java/nio/channels/spi/AsynchronousChannelProvider.java
@@ -64,7 +64,7 @@
      *
      * @throws  SecurityException
      *          If a security manager has been installed and it denies
-     *          {@link RuntimePermission}<tt>("asynchronousChannelProvider")</tt>
+     *          {@link RuntimePermission}{@code ("asynchronousChannelProvider")}
      */
     protected AsynchronousChannelProvider() {
         this(checkPermission());
@@ -76,7 +76,7 @@
 
         private static AsynchronousChannelProvider load() {
             return AccessController
-                .doPrivileged(new PrivilegedAction<AsynchronousChannelProvider>() {
+                .doPrivileged(new PrivilegedAction<>() {
                     public AsynchronousChannelProvider run() {
                         AsynchronousChannelProvider p;
                         p = loadProviderFromProperty();
@@ -94,9 +94,10 @@
             if (cn == null)
                 return null;
             try {
-                Class<?> c = Class.forName(cn, true,
-                                           ClassLoader.getSystemClassLoader());
-                return (AsynchronousChannelProvider)c.newInstance();
+                @SuppressWarnings("deprecation")
+                Object tmp = Class.forName(cn, true,
+                                           ClassLoader.getSystemClassLoader()).newInstance();
+                return (AsynchronousChannelProvider)tmp;
             } catch (ClassNotFoundException x) {
                 throw new ServiceConfigurationError(null, x);
             } catch (IllegalAccessException x) {
@@ -137,7 +138,7 @@
      * <ol>
      *
      *   <li><p> If the system property
-     *   <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> is defined
+     *   {@code java.nio.channels.spi.AsynchronousChannelProvider} is defined
      *   then it is taken to be the fully-qualified name of a concrete provider class.
      *   The class is loaded and instantiated; if this process fails then an
      *   unspecified error is thrown.  </p></li>
@@ -145,8 +146,8 @@
      *   <li><p> If a provider class has been installed in a jar file that is
      *   visible to the system class loader, and that jar file contains a
      *   provider-configuration file named
-     *   <tt>java.nio.channels.spi.AsynchronousChannelProvider</tt> in the resource
-     *   directory <tt>META-INF/services</tt>, then the first class name
+     *   {@code java.nio.channels.spi.AsynchronousChannelProvider} in the resource
+     *   directory {@code META-INF/services}, then the first class name
      *   specified in that file is taken.  The class is loaded and
      *   instantiated; if this process fails then an unspecified error is
      *   thrown.  </p></li>
diff --git a/ojluni/src/main/java/java/nio/channels/spi/SelectorProvider.java b/ojluni/src/main/java/java/nio/channels/spi/SelectorProvider.java
index 2dbef05..c162eed 100644
--- a/ojluni/src/main/java/java/nio/channels/spi/SelectorProvider.java
+++ b/ojluni/src/main/java/java/nio/channels/spi/SelectorProvider.java
@@ -46,7 +46,7 @@
  * #provider() provider} method.  The first invocation of that method will locate
  * the default provider as specified below.
  *
- * <p> The system-wide default provider is used by the static <tt>open</tt>
+ * <p> The system-wide default provider is used by the static {@code open}
  * methods of the {@link java.nio.channels.DatagramChannel#open
  * DatagramChannel}, {@link java.nio.channels.Pipe#open Pipe}, {@link
  * java.nio.channels.Selector#open Selector}, {@link
@@ -54,7 +54,7 @@
  * java.nio.channels.SocketChannel#open SocketChannel} classes.  It is also
  * used by the {@link java.lang.System#inheritedChannel System.inheritedChannel()}
  * method. A program may make use of a provider other than the default provider
- * by instantiating that provider and then directly invoking the <tt>open</tt>
+ * by instantiating that provider and then directly invoking the {@code open}
  * methods defined in this class.
  *
  * <p> All of the methods in this class are safe for use by multiple concurrent
@@ -71,17 +71,23 @@
     private static final Object lock = new Object();
     private static SelectorProvider provider = null;
 
+    private static Void checkPermission() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+            sm.checkPermission(new RuntimePermission("selectorProvider"));
+        return null;
+    }
+    private SelectorProvider(Void ignore) { }
+
     /**
      * Initializes a new instance of this class.
      *
      * @throws  SecurityException
      *          If a security manager has been installed and it denies
-     *          {@link RuntimePermission}<tt>("selectorProvider")</tt>
+     *          {@link RuntimePermission}{@code ("selectorProvider")}
      */
     protected SelectorProvider() {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null)
-            sm.checkPermission(new RuntimePermission("selectorProvider"));
+        this(checkPermission());
     }
 
     private static boolean loadProviderFromProperty() {
@@ -89,9 +95,10 @@
         if (cn == null)
             return false;
         try {
-            Class<?> c = Class.forName(cn, true,
-                                       ClassLoader.getSystemClassLoader());
-            provider = (SelectorProvider)c.newInstance();
+            @SuppressWarnings("deprecation")
+            Object tmp = Class.forName(cn, true,
+                                       ClassLoader.getSystemClassLoader()).newInstance();
+            provider = (SelectorProvider)tmp;
             return true;
         } catch (ClassNotFoundException x) {
             throw new ServiceConfigurationError(null, x);
@@ -136,7 +143,7 @@
      * <ol>
      *
      *   <li><p> If the system property
-     *   <tt>java.nio.channels.spi.SelectorProvider</tt> is defined then it is
+     *   {@code java.nio.channels.spi.SelectorProvider} is defined then it is
      *   taken to be the fully-qualified name of a concrete provider class.
      *   The class is loaded and instantiated; if this process fails then an
      *   unspecified error is thrown.  </p></li>
@@ -144,8 +151,8 @@
      *   <li><p> If a provider class has been installed in a jar file that is
      *   visible to the system class loader, and that jar file contains a
      *   provider-configuration file named
-     *   <tt>java.nio.channels.spi.SelectorProvider</tt> in the resource
-     *   directory <tt>META-INF/services</tt>, then the first class name
+     *   {@code java.nio.channels.spi.SelectorProvider} in the resource
+     *   directory {@code META-INF/services}, then the first class name
      *   specified in that file is taken.  The class is loaded and
      *   instantiated; if this process fails then an unspecified error is
      *   thrown.  </p></li>
@@ -166,7 +173,7 @@
             if (provider != null)
                 return provider;
             return AccessController.doPrivileged(
-                new PrivilegedAction<SelectorProvider>() {
+                new PrivilegedAction<>() {
                     public SelectorProvider run() {
                             if (loadProviderFromProperty())
                                 return provider;
@@ -299,14 +306,14 @@
      * returned. Subsequent invocations of this method return the same
      * channel. </p>
      *
-     * @return  The inherited channel, if any, otherwise <tt>null</tt>.
+     * @return  The inherited channel, if any, otherwise {@code null}.
      *
      * @throws  IOException
      *          If an I/O error occurs
      *
      * @throws  SecurityException
      *          If a security manager has been installed and it denies
-     *          {@link RuntimePermission}<tt>("inheritedChannel")</tt>
+     *          {@link RuntimePermission}{@code ("inheritedChannel")}
      *
      * @since 1.5
      */
diff --git a/ojluni/src/main/java/java/nio/charset/package-info.java b/ojluni/src/main/java/java/nio/charset/package-info.java
index 1fc81e0..046606a 100644
--- a/ojluni/src/main/java/java/nio/charset/package-info.java
+++ b/ojluni/src/main/java/java/nio/charset/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,61 +24,72 @@
  */
 
 /**
- * Defines charsets, decoders, and encoders, for translating between bytes and
- * Unicode characters.
+ * Defines charsets, decoders, and encoders, for translating between
+ * bytes and Unicode characters.
  *
- * <blockquote><table cellspacing=1 cellpadding=0 summary="Summary of charsets, decoders, and encoders in this package">
- *  <tr><th><p align="left">Class name</p></th><th><p align="left">Description</p></th></tr>
- *   <tr><td valign=top><tt>{@link java.nio.charset.Charset}</tt></td>
- *       <td>A named mapping between characters<br>and bytes</td></tr>
- *   <tr><td valign=top><tt>{@link java.nio.charset.CharsetDecoder}</tt></td>
+ * <table class="striped" style="margin-left:2em; text-align:left">
+ *     <caption style="display:none">Summary of charsets, decoders, and encoders in this package</caption>
+ *  <thead>
+ *  <tr><th scope="col">Class name</th>
+ *      <th scope="col">Description
+ *  </thead>
+ *  <tbody>
+ *   <tr><th scope="row">{@link java.nio.charset.Charset}</th>
+ *       <td>A named mapping between characters and bytes</td></tr>
+ *   <tr><th scope="row">{@link java.nio.charset.CharsetDecoder}</th>
  *       <td>Decodes bytes into characters</td></tr>
- *   <tr><td valign=top><tt>{@link java.nio.charset.CharsetEncoder}&nbsp;&nbsp;</tt></td>
+ *   <tr><th scope="row">{@link java.nio.charset.CharsetEncoder}</th>
  *       <td>Encodes characters into bytes</td></tr>
- *   <tr><td valign=top><tt>{@link java.nio.charset.CoderResult}&nbsp;&nbsp;</tt></td>
+ *   <tr><th scope="row">{@link java.nio.charset.CoderResult}</th>
  *       <td>Describes coder results</td></tr>
- *   <tr><td valign=top><tt>{@link java.nio.charset.CodingErrorAction}&nbsp;&nbsp;</tt></td>
- *       <td>Describes actions to take when<br>coding errors are detected</td></tr>
+ *   <tr><th scope="row">{@link java.nio.charset.CodingErrorAction}</th>
+ *       <td>Describes actions to take when coding errors are detected</td></tr>
+ * </tbody>
+ * </table>
  *
- * </table></blockquote>
+ * <p> A <i>charset</i> is named mapping between sequences of
+ * sixteen-bit Unicode characters and sequences of bytes, in the sense
+ * defined in <a
+ * href="http://www.ietf.org/rfc/rfc2278.txt"><i>RFC&nbsp;2278</i></a>.
+ * A <i>decoder</i> is an engine which transforms bytes in a specific
+ * charset into characters, and an <i>encoder</i> is an engine which
+ * transforms characters into bytes.  Encoders and decoders operate on
+ * byte and character buffers.  They are collectively referred to as
+ * <i>coders</i>.
  *
- * <p> A <i>charset</i> is named mapping between sequences of sixteen-bit Unicode
- * characters and sequences of bytes, in the sense defined in <a
- * href="http://www.ietf.org/rfc/rfc2278.txt"><i>RFC&nbsp;2278</i></a>.  A
- * <i>decoder</i> is an engine which transforms bytes in a specific charset into
- * characters, and an <i>encoder</i> is an engine which transforms characters into
- * bytes.  Encoders and decoders operate on byte and character buffers.  They are
- * collectively referred to as <i>coders</i>.
+ * <p> The {@link java.nio.charset.Charset} class defines methods for
+ * creating coders for a given charset and for retrieving the various
+ * names associated with a charset.  It also defines static methods
+ * for testing whether a particular charset is supported, for locating
+ * charset instances by name, and for constructing a map that contains
+ * every charset for which support is available in the current Java
+ * virtual machine.
  *
- * <p> The {@link java.nio.charset.Charset} class defines methods for creating
- * coders for a given charset and for retrieving the various names associated with
- * a charset.  It also defines static methods for testing whether a particular
- * charset is supported, for locating charset instances by name, and for
- * constructing a map that contains every charset for which support is available
- * in the current Java virtual machine.
+ * <p> Most users will not use these classes directly; instead they
+ * will use the existing charset-related constructors and methods in
+ * the {@link java.lang.String} class, together with the existing
+ * {@link java.io.InputStreamReader} and {@link
+ * java.io.OutputStreamWriter} classes, all of whose implementations
+ * have been reworked to make use of the charset facilities defined in
+ * this package.  A small number of changes have been made to the
+ * {@link java.io.InputStreamReader} and {@link
+ * java.io.OutputStreamWriter} classes in order to allow explicit
+ * charset objects to be specified in the construction of instances of
+ * those classes.
  *
- * <p> Most users will not use these classes directly; instead they will use the
- * existing charset-related constructors and methods in the {@link
- * java.lang.String} class, together with the existing {@link
- * java.io.InputStreamReader} and {@link java.io.OutputStreamWriter} classes, all
- * of whose implementations have been reworked to make use of the charset
- * facilities defined in this package.  A small number of changes have been made
- * to the {@link java.io.InputStreamReader} and {@link java.io.OutputStreamWriter}
- * classes in order to allow explicit charset objects to be specified in the
- * construction of instances of those classes.
+ * <p> Support for new charsets can be made available via the
+ * interface defined in the {@link
+ * java.nio.charset.spi.CharsetProvider} class in the {@link
+ * java.nio.charset.spi} package.
  *
- * <p> Support for new charsets can be made available via the interface defined in
- * the {@link java.nio.charset.spi.CharsetProvider} class in the <tt>{@link
- * java.nio.charset.spi}</tt> package.
- *
- * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
- * or method in any class or interface in this package will cause a {@link
- * java.lang.NullPointerException NullPointerException} to be thrown.
+ * <p> Unless otherwise noted, passing a {@code null} argument to a
+ * constructor or method in any class or interface in this package
+ * will cause a {@link java.lang.NullPointerException
+ * NullPointerException} to be thrown.
  *
  *
  * @since 1.4
  * @author Mark Reinhold
  * @author JSR-51 Expert Group
  */
-
 package java.nio.charset;
diff --git a/ojluni/src/main/java/java/nio/file/AtomicMoveNotSupportedException.java b/ojluni/src/main/java/java/nio/file/AtomicMoveNotSupportedException.java
index 27947c3..5849565 100644
--- a/ojluni/src/main/java/java/nio/file/AtomicMoveNotSupportedException.java
+++ b/ojluni/src/main/java/java/nio/file/AtomicMoveNotSupportedException.java
@@ -45,7 +45,7 @@
      * @param   target
      *          a string identifying the target file or {@code null} if not known
      * @param   reason
-     *          a reason message with additional information
+     *          a reason message with additional information or {@code null}
      */
     public AtomicMoveNotSupportedException(String source,
                                            String target,
diff --git a/ojluni/src/main/java/java/nio/file/ClosedFileSystemException.java b/ojluni/src/main/java/java/nio/file/ClosedFileSystemException.java
index 82cf096..60d4551 100644
--- a/ojluni/src/main/java/java/nio/file/ClosedFileSystemException.java
+++ b/ojluni/src/main/java/java/nio/file/ClosedFileSystemException.java
@@ -28,6 +28,8 @@
 /**
  * Unchecked exception thrown when an attempt is made to invoke an operation on
  * a file and the file system is closed.
+ *
+ * @since 1.7
  */
 
 public class ClosedFileSystemException
diff --git a/ojluni/src/main/java/java/nio/file/ClosedWatchServiceException.java b/ojluni/src/main/java/java/nio/file/ClosedWatchServiceException.java
index 3995b6d..4990a7a 100644
--- a/ojluni/src/main/java/java/nio/file/ClosedWatchServiceException.java
+++ b/ojluni/src/main/java/java/nio/file/ClosedWatchServiceException.java
@@ -28,6 +28,8 @@
 /**
  * Unchecked exception thrown when an attempt is made to invoke an operation on
  * a watch service that is closed.
+ *
+ * @since 1.7
  */
 
 public class ClosedWatchServiceException
diff --git a/ojluni/src/main/java/java/nio/file/FileStore.java b/ojluni/src/main/java/java/nio/file/FileStore.java
index 2b14a4b..06d4f11 100644
--- a/ojluni/src/main/java/java/nio/file/FileStore.java
+++ b/ojluni/src/main/java/java/nio/file/FileStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -112,6 +112,31 @@
     public abstract long getUsableSpace() throws IOException;
 
     /**
+     * Returns the number of bytes per block in this file store.
+     *
+     * <p> File storage is typically organized into discrete sequences of bytes
+     * called <i>blocks</i>. A block is the smallest storage unit of a file store.
+     * Every read and write operation is performed on a multiple of blocks.
+     *
+     * @implSpec The implementation in this class throws an
+     *         {@code UnsupportedOperationException}.
+     *
+     * @return  a positive value representing the block size of this file store,
+     *          in bytes
+     *
+     * @throws  IOException
+     *          if an I/O error occurs
+     *
+     * @throws  UnsupportedOperationException
+     *          if the operation is not supported
+     *
+     * @since 10
+     */
+    public long getBlockSize() throws IOException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Returns the number of unallocated bytes in the file store.
      *
      * <p> The returned number of unallocated bytes is a hint, but not a
@@ -208,7 +233,7 @@
      * @param   attribute
      *          the attribute to read
 
-     * @return  the attribute value; {@code null} may be a valid valid for some
+     * @return  the attribute value; {@code null} may be valid for some
      *          attributes
      *
      * @throws  UnsupportedOperationException
diff --git a/ojluni/src/main/java/java/nio/file/FileSystem.java b/ojluni/src/main/java/java/nio/file/FileSystem.java
index 755d64f..f1944b4 100644
--- a/ojluni/src/main/java/java/nio/file/FileSystem.java
+++ b/ojluni/src/main/java/java/nio/file/FileSystem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -202,7 +202,7 @@
      *
      * <p> In the case of the default provider, and a security manager is
      * installed, the security manager is invoked to check {@link
-     * RuntimePermission}<tt>("getFileStoreAttributes")</tt>. If denied, then
+     * RuntimePermission}{@code ("getFileStoreAttributes")}. If denied, then
      * no file stores are returned by the iterator. In addition, the security
      * manager's {@link SecurityManager#checkRead(String)} method is invoked to
      * check read access to the file store's <em>top-most</em> directory. If
@@ -315,37 +315,43 @@
      * representation of the path is matched using a limited pattern language
      * that resembles regular expressions but with a simpler syntax. For example:
      *
-     * <blockquote>
-     * <table border="0" summary="Pattern Language">
+     * <table class="striped" style="text-align:left; margin-left:2em">
+     * <caption style="display:none">Pattern Language</caption>
+     * <thead>
      * <tr>
-     *   <td>{@code *.java}</td>
+     *   <th scope="col">Example
+     *   <th scope="col">Description
+     * </tr>
+     * </thead>
+     * <tbody>
+     * <tr>
+     *   <th scope="row">{@code *.java}</th>
      *   <td>Matches a path that represents a file name ending in {@code .java}</td>
      * </tr>
      * <tr>
-     *   <td>{@code *.*}</td>
+     *   <th scope="row">{@code *.*}</th>
      *   <td>Matches file names containing a dot</td>
      * </tr>
      * <tr>
-     *   <td>{@code *.{java,class}}</td>
+     *   <th scope="row">{@code *.{java,class}}</th>
      *   <td>Matches file names ending with {@code .java} or {@code .class}</td>
      * </tr>
      * <tr>
-     *   <td>{@code foo.?}</td>
+     *   <th scope="row">{@code foo.?}</th>
      *   <td>Matches file names starting with {@code foo.} and a single
      *   character extension</td>
      * </tr>
      * <tr>
-     *   <td><tt>&#47;home&#47;*&#47;*</tt>
-     *   <td>Matches <tt>&#47;home&#47;gus&#47;data</tt></td>
+     *   <th scope="row"><code>&#47;home&#47;*&#47;*</code>
+     *   <td>Matches <code>&#47;home&#47;gus&#47;data</code></td>
      * </tr>
      * <tr>
-     *   <td><tt>&#47;home&#47;**</tt>
-     *   <td>Matches <tt>&#47;home&#47;gus</tt> and
-     *   <tt>&#47;home&#47;gus&#47;data</tt></td>
+     *   <th scope="row"><code>&#47;home&#47;**</code>
+     *   <td>Matches <code>&#47;home&#47;gus</code> and
+     *   <code>&#47;home&#47;gus&#47;data</code></td>
      * </tr>
-     *
+     * </tbody>
      * </table>
-     * </blockquote>
      *
      * <p> The following rules are used to interpret glob patterns:
      *
@@ -385,7 +391,7 @@
      *   character is used to separate the subpatterns. Groups cannot be nested.
      *   </p></li>
      *
-     *   <li><p> Leading period<tt>&#47;</tt>dot characters in file name are
+     *   <li><p> Leading period<code>&#47;</code>dot characters in file name are
      *   treated as regular characters in match operations. For example,
      *   the {@code "*"} glob pattern matches file name {@code ".login"}.
      *   The {@link Files#isHidden} method may be used to test whether a file
diff --git a/ojluni/src/main/java/java/nio/file/FileSystemAlreadyExistsException.java b/ojluni/src/main/java/java/nio/file/FileSystemAlreadyExistsException.java
index e305542..5877410 100644
--- a/ojluni/src/main/java/java/nio/file/FileSystemAlreadyExistsException.java
+++ b/ojluni/src/main/java/java/nio/file/FileSystemAlreadyExistsException.java
@@ -28,6 +28,8 @@
 /**
  * Runtime exception thrown when an attempt is made to create a file system that
  * already exists.
+ *
+ * @since 1.7
  */
 
 public class FileSystemAlreadyExistsException
diff --git a/ojluni/src/main/java/java/nio/file/FileSystemNotFoundException.java b/ojluni/src/main/java/java/nio/file/FileSystemNotFoundException.java
index 1c0ee4c..e50eafb 100644
--- a/ojluni/src/main/java/java/nio/file/FileSystemNotFoundException.java
+++ b/ojluni/src/main/java/java/nio/file/FileSystemNotFoundException.java
@@ -27,6 +27,8 @@
 
 /**
  * Runtime exception thrown when a file system cannot be found.
+ *
+ * @since 1.7
  */
 
 public class FileSystemNotFoundException
diff --git a/ojluni/src/main/java/java/nio/file/FileTreeIterator.java b/ojluni/src/main/java/java/nio/file/FileTreeIterator.java
index 63b4dc7..c748e32 100644
--- a/ojluni/src/main/java/java/nio/file/FileTreeIterator.java
+++ b/ojluni/src/main/java/java/nio/file/FileTreeIterator.java
@@ -31,11 +31,10 @@
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import java.util.Objects;
 import java.nio.file.FileTreeWalker.Event;
 
 /**
- * An {@code Iterator to iterate over the nodes of a file tree.
+ * An {@code Iterator} to iterate over the nodes of a file tree.
  *
  * <pre>{@code
  *     try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
@@ -62,7 +61,7 @@
      * @throws  SecurityException
      *          if the security manager denies access to the starting file
      * @throws  NullPointerException
-     *          if {@code start} or {@code options} is {@ocde null} or
+     *          if {@code start} or {@code options} is {@code null} or
      *          the options array contains a {@code null} element
      */
     FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
diff --git a/ojluni/src/main/java/java/nio/file/FileTreeWalker.java b/ojluni/src/main/java/java/nio/file/FileTreeWalker.java
index b0cf0d3..f1ad8d0 100644
--- a/ojluni/src/main/java/java/nio/file/FileTreeWalker.java
+++ b/ojluni/src/main/java/java/nio/file/FileTreeWalker.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -168,10 +168,10 @@
      * @throws  IllegalArgumentException
      *          if {@code maxDepth} is negative
      * @throws  ClassCastException
-     *          if (@code options} contains an element that is not a
+     *          if {@code options} contains an element that is not a
      *          {@code FileVisitOption}
      * @throws  NullPointerException
-     *          if {@code options} is {@ocde null} or the options
+     *          if {@code options} is {@code null} or the options
      *          array contains a {@code null} element
      */
     FileTreeWalker(Collection<FileVisitOption> options, int maxDepth) {
@@ -353,12 +353,13 @@
                 }
             }
 
-            // no next entry so close and pop directory, creating corresponding event
+            // no next entry so close and pop directory,
+            // creating corresponding event
             if (entry == null) {
                 try {
                     top.stream().close();
                 } catch (IOException e) {
-                    if (ioe != null) {
+                    if (ioe == null) {
                         ioe = e;
                     } else {
                         ioe.addSuppressed(e);
diff --git a/ojluni/src/main/java/java/nio/file/InvalidPathException.java b/ojluni/src/main/java/java/nio/file/InvalidPathException.java
index 2c62865..2dc3597 100644
--- a/ojluni/src/main/java/java/nio/file/InvalidPathException.java
+++ b/ojluni/src/main/java/java/nio/file/InvalidPathException.java
@@ -29,6 +29,8 @@
  * Unchecked exception thrown when path string cannot be converted into a
  * {@link Path} because the path string contains invalid characters, or
  * the path string is invalid for other file system specific reasons.
+ *
+ * @since 1.7
  */
 
 public class InvalidPathException
@@ -46,13 +48,13 @@
      * @param  input   the input string
      * @param  reason  a string explaining why the input was rejected
      * @param  index   the index at which the error occurred,
-     *                 or <tt>-1</tt> if the index is not known
+     *                 or {@code -1} if the index is not known
      *
      * @throws  NullPointerException
-     *          if either the input or reason strings are <tt>null</tt>
+     *          if either the input or reason strings are {@code null}
      *
      * @throws  IllegalArgumentException
-     *          if the error index is less than <tt>-1</tt>
+     *          if the error index is less than {@code -1}
      */
     public InvalidPathException(String input, String reason, int index) {
         super(reason);
@@ -66,13 +68,13 @@
 
     /**
      * Constructs an instance from the given input string and reason.  The
-     * resulting object will have an error index of <tt>-1</tt>.
+     * resulting object will have an error index of {@code -1}.
      *
      * @param  input   the input string
      * @param  reason  a string explaining why the input was rejected
      *
      * @throws  NullPointerException
-     *          if either the input or reason strings are <tt>null</tt>
+     *          if either the input or reason strings are {@code null}
      */
     public InvalidPathException(String input, String reason) {
         this(input, reason, -1);
@@ -98,7 +100,7 @@
 
     /**
      * Returns an index into the input string of the position at which the
-     * error occurred, or <tt>-1</tt> if this position is not known.
+     * error occurred, or {@code -1} if this position is not known.
      *
      * @return  the error index
      */
@@ -109,15 +111,15 @@
     /**
      * Returns a string describing the error.  The resulting string
      * consists of the reason string followed by a colon character
-     * (<tt>':'</tt>), a space, and the input string.  If the error index is
-     * defined then the string <tt>" at index "</tt> followed by the index, in
+     * ({@code ':'}), a space, and the input string.  If the error index is
+     * defined then the string {@code " at index "} followed by the index, in
      * decimal, is inserted after the reason string and before the colon
      * character.
      *
      * @return  a string describing the error
      */
     public String getMessage() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append(getReason());
         if (index > -1) {
             sb.append(" at index ");
diff --git a/ojluni/src/main/java/java/nio/file/LinkPermission.java b/ojluni/src/main/java/java/nio/file/LinkPermission.java
index bf54e16..c838549 100644
--- a/ojluni/src/main/java/java/nio/file/LinkPermission.java
+++ b/ojluni/src/main/java/java/nio/file/LinkPermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,15 +33,18 @@
  * <p> The following table provides a summary description of what the permission
  * allows, and discusses the risks of granting code the permission.
  *
- * <table border=1 cellpadding=5
- *        summary="Table shows permission target name, what the permission allows, and associated risks">
+ * <table class="striped">
+ * <caption style="display:none">Table shows permission target name, what the permission allows, and associated risks</caption>
+ * <thead>
  * <tr>
- * <th>Permission Target Name</th>
- * <th>What the Permission Allows</th>
- * <th>Risks of Allowing this Permission</th>
+ * <th scope="col">Permission Target Name</th>
+ * <th scope="col">What the Permission Allows</th>
+ * <th scope="col">Risks of Allowing this Permission</th>
  * </tr>
+ * </thead>
+ * <tbody>
  * <tr>
- *   <td>hard</td>
+ *   <th scope="row">hard</th>
  *   <td> Ability to add an existing file to a directory. This is sometimes
  *   known as creating a link, or hard link. </td>
  *   <td> Extreme care should be taken when granting this permission. It allows
@@ -49,12 +52,13 @@
  *   attacker access to all files. </td>
  * </tr>
  * <tr>
- *   <td>symbolic</td>
+ *   <th scope="row">symbolic</th>
  *   <td> Ability to create symbolic links. </td>
  *   <td> Extreme care should be taken when granting this permission. It allows
  *   linking to any file or directory in the file system thus allowing the
  *   attacker to access to all files. </td>
  * </tr>
+ * </tbody>
  * </table>
  *
  * @since 1.7
@@ -100,7 +104,7 @@
     public LinkPermission(String name, String actions) {
         super(name);
         checkName(name);
-        if (actions != null && actions.length() > 0) {
+        if (actions != null && !actions.isEmpty()) {
             throw new IllegalArgumentException("actions: " + actions);
         }
     }
diff --git a/ojluni/src/main/java/java/nio/file/ProviderMismatchException.java b/ojluni/src/main/java/java/nio/file/ProviderMismatchException.java
index 0220d6e..9e628cb 100644
--- a/ojluni/src/main/java/java/nio/file/ProviderMismatchException.java
+++ b/ojluni/src/main/java/java/nio/file/ProviderMismatchException.java
@@ -29,6 +29,8 @@
  * Unchecked exception thrown when an attempt is made to invoke a method on an
  * object created by one file system provider with a parameter created by a
  * different file system provider.
+ *
+ * @since 1.7
  */
 public class ProviderMismatchException
     extends java.lang.IllegalArgumentException
diff --git a/ojluni/src/main/java/java/nio/file/ProviderNotFoundException.java b/ojluni/src/main/java/java/nio/file/ProviderNotFoundException.java
index 8fa0cef..41f9819 100644
--- a/ojluni/src/main/java/java/nio/file/ProviderNotFoundException.java
+++ b/ojluni/src/main/java/java/nio/file/ProviderNotFoundException.java
@@ -27,6 +27,8 @@
 
 /**
  * Runtime exception thrown when a provider of the required type cannot be found.
+ *
+ * @since 1.7
  */
 
 public class ProviderNotFoundException
diff --git a/ojluni/src/main/java/java/nio/file/ReadOnlyFileSystemException.java b/ojluni/src/main/java/java/nio/file/ReadOnlyFileSystemException.java
index 9b25e5f..0b9d42a 100644
--- a/ojluni/src/main/java/java/nio/file/ReadOnlyFileSystemException.java
+++ b/ojluni/src/main/java/java/nio/file/ReadOnlyFileSystemException.java
@@ -28,6 +28,8 @@
 /**
  * Unchecked exception thrown when an attempt is made to update an object
  * associated with a {@link FileSystem#isReadOnly() read-only} {@code FileSystem}.
+ *
+ * @since 1.7
  */
 
 public class ReadOnlyFileSystemException
diff --git a/ojluni/src/main/java/java/nio/file/SecureDirectoryStream.java b/ojluni/src/main/java/java/nio/file/SecureDirectoryStream.java
index 064618b..8cfaea3 100644
--- a/ojluni/src/main/java/java/nio/file/SecureDirectoryStream.java
+++ b/ojluni/src/main/java/java/nio/file/SecureDirectoryStream.java
@@ -115,7 +115,7 @@
      * channel.
      *
      * @param   path
-     *          the path of the file to open open or create
+     *          the path of the file to open or create
      * @param   options
      *          options specifying how the file is opened
      * @param   attrs
diff --git a/ojluni/src/main/java/java/nio/file/attribute/AclEntry.java b/ojluni/src/main/java/java/nio/file/attribute/AclEntry.java
index b008494..01e625a 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/AclEntry.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/AclEntry.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
  *    {@link AclEntryPermission permissions}
  *    </p></li>
  *
- *    <li><p> The {@link #flags flags} component is a set of {@link AclEntryFlag
+ *    <li><p> The {@link #flags() flags} component is a set of {@link AclEntryFlag
  *    flags} to indicate how entries are inherited and propagated </p></li>
  * </ol>
  *
@@ -306,7 +306,7 @@
      * @return the permissions component
      */
     public Set<AclEntryPermission> permissions() {
-        return new HashSet<AclEntryPermission>(perms);
+        return new HashSet<>(perms);
     }
 
     /**
@@ -317,7 +317,7 @@
      * @return the flags component
      */
     public Set<AclEntryFlag> flags() {
-        return new HashSet<AclEntryFlag>(flags);
+        return new HashSet<>(flags);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/nio/file/attribute/AclFileAttributeView.java b/ojluni/src/main/java/java/nio/file/attribute/AclFileAttributeView.java
index 129d0ee..6db57e2 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/AclFileAttributeView.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/AclFileAttributeView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -94,19 +94,24 @@
  * <p> Where dynamic access to file attributes is required, the attributes
  * supported by this attribute view are as follows:
  * <blockquote>
- * <table border="1" cellpadding="8" summary="Supported attributes">
+ * <table class="striped">
+ * <caption style="display:none">Supported attributes</caption>
+ * <thead>
  *   <tr>
- *     <th> Name </th>
- *     <th> Type </th>
+ *     <th scope="col"> Name </th>
+ *     <th scope="col"> Type </th>
  *   </tr>
+ * </thead>
+ * <tbody>
  *   <tr>
- *     <td> "acl" </td>
+ *     <th scope="row"> "acl" </th>
  *     <td> {@link List}&lt;{@link AclEntry}&gt; </td>
  *   </tr>
  *   <tr>
- *     <td> "owner" </td>
+ *     <th scope="row"> "owner" </th>
  *     <td> {@link UserPrincipal} </td>
  *   </tr>
+ * </tbody>
  * </table>
  * </blockquote>
  *
@@ -165,7 +170,7 @@
      *          if an I/O error occurs
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
-     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          installed, and it denies {@link RuntimePermission}{@code ("accessUserInformation")}
      *          or its {@link SecurityManager#checkRead(String) checkRead} method
      *          denies read access to the file.
      */
@@ -201,7 +206,7 @@
      *          if an I/O error occurs or the ACL is invalid
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
-     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          installed, it denies {@link RuntimePermission}{@code ("accessUserInformation")}
      *          or its {@link SecurityManager#checkWrite(String) checkWrite}
      *          method denies write access to the file.
      */
diff --git a/ojluni/src/main/java/java/nio/file/attribute/BasicFileAttributeView.java b/ojluni/src/main/java/java/nio/file/attribute/BasicFileAttributeView.java
index bfa3fdc..a6b3e41 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/BasicFileAttributeView.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/BasicFileAttributeView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,47 +41,52 @@
  * <p> Where dynamic access to file attributes is required, the attributes
  * supported by this attribute view have the following names and types:
  * <blockquote>
- *  <table border="1" cellpadding="8" summary="Supported attributes">
+ *  <table class="striped">
+ *  <caption style="display:none">Supported attributes</caption>
+ *  <thead>
  *   <tr>
- *     <th> Name </th>
- *     <th> Type </th>
+ *     <th scope="col"> Name </th>
+ *     <th scope="col"> Type </th>
  *   </tr>
+ *  </thead>
+ *  <tbody>
  *  <tr>
- *     <td> "lastModifiedTime" </td>
+ *     <th scope="row"> "lastModifiedTime" </th>
  *     <td> {@link FileTime} </td>
  *   </tr>
  *   <tr>
- *     <td> "lastAccessTime" </td>
+ *     <th scope="row"> "lastAccessTime" </th>
  *     <td> {@link FileTime} </td>
  *   </tr>
  *   <tr>
- *     <td> "creationTime" </td>
+ *     <th scope="row"> "creationTime" </th>
  *     <td> {@link FileTime} </td>
  *   </tr>
  *   <tr>
- *     <td> "size" </td>
+ *     <th scope="row"> "size" </th>
  *     <td> {@link Long} </td>
  *   </tr>
  *   <tr>
- *     <td> "isRegularFile" </td>
+ *     <th scope="row"> "isRegularFile" </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
  *   <tr>
- *     <td> "isDirectory" </td>
+ *     <th scope="row"> "isDirectory" </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
  *   <tr>
- *     <td> "isSymbolicLink" </td>
+ *     <th scope="row"> "isSymbolicLink" </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
  *   <tr>
- *     <td> "isOther" </td>
+ *     <th scope="row"> "isOther" </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
  *   <tr>
- *     <td> "fileKey" </td>
+ *     <th scope="row"> "fileKey" </th>
  *     <td> {@link Object} </td>
  *   </tr>
+ * </tbody>
  * </table>
  * </blockquote>
  *
diff --git a/ojluni/src/main/java/java/nio/file/attribute/DosFileAttributeView.java b/ojluni/src/main/java/java/nio/file/attribute/DosFileAttributeView.java
index c12d8a0..0c600fb 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/DosFileAttributeView.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/DosFileAttributeView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,27 +41,32 @@
  * BasicFileAttributeView}, and in addition, the following attributes are
  * supported:
  * <blockquote>
- * <table border="1" cellpadding="8" summary="Supported attributes">
+ * <table class="striped">
+ * <caption style="display:none">Supported attributes</caption>
+ * <thead>
  *   <tr>
- *     <th> Name </th>
- *     <th> Type </th>
+ *     <th scope="col"> Name </th>
+ *     <th scope="col"> Type </th>
  *   </tr>
+ * </thead>
+ * <tbody>
  *   <tr>
- *     <td> readonly </td>
+ *     <th scope="row"> readonly </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
  *   <tr>
- *     <td> hidden </td>
+ *     <th scope="row"> hidden </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
  *   <tr>
- *     <td> system </td>
+ *     <th scope="row"> system </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
  *   <tr>
- *     <td> archive </td>
+ *     <th scope="row"> archive </th>
  *     <td> {@link Boolean} </td>
  *   </tr>
+ * </tbody>
  * </table>
  * </blockquote>
  *
diff --git a/ojluni/src/main/java/java/nio/file/attribute/FileOwnerAttributeView.java b/ojluni/src/main/java/java/nio/file/attribute/FileOwnerAttributeView.java
index f18caaf..82d0d1b 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/FileOwnerAttributeView.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/FileOwnerAttributeView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
     /**
      * Read the file owner.
      *
-     * <p> It it implementation specific if the file owner can be a {@link
+     * <p> It is implementation specific if the file owner can be a {@link
      * GroupPrincipal group}.
      *
      * @return  the file owner
@@ -69,7 +69,7 @@
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
      *          installed, and it denies {@link
-     *          RuntimePermission}<tt>("accessUserInformation")</tt> or its
+     *          RuntimePermission}{@code ("accessUserInformation")} or its
      *          {@link SecurityManager#checkRead(String) checkRead} method
      *          denies read access to the file.
      */
@@ -78,7 +78,7 @@
     /**
      * Updates the file owner.
      *
-     * <p> It it implementation specific if the file owner can be a {@link
+     * <p> It is implementation specific if the file owner can be a {@link
      * GroupPrincipal group}. To ensure consistent and correct behavior
      * across platforms it is recommended that this method should only be used
      * to set the file owner to a user principal that is not a group.
@@ -93,7 +93,7 @@
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
      *          installed, and it denies {@link
-     *          RuntimePermission}<tt>("accessUserInformation")</tt> or its
+     *          RuntimePermission}{@code ("accessUserInformation")} or its
      *          {@link SecurityManager#checkWrite(String) checkWrite} method
      *          denies write access to the file.
      */
diff --git a/ojluni/src/main/java/java/nio/file/attribute/PosixFileAttributeView.java b/ojluni/src/main/java/java/nio/file/attribute/PosixFileAttributeView.java
index 25466f2..7e294d8 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/PosixFileAttributeView.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/PosixFileAttributeView.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,19 +74,24 @@
  * BasicFileAttributeView} and {@link FileOwnerAttributeView}, and in addition,
  * the following attributes are supported:
  * <blockquote>
- * <table border="1" cellpadding="8" summary="Supported attributes">
+ * <table class="striped">
+ * <caption style="display:none">Supported attributes</caption>
+ * <thead>
  *   <tr>
- *     <th> Name </th>
- *     <th> Type </th>
+ *     <th scope="col"> Name </th>
+ *     <th scope="col"> Type </th>
  *   </tr>
+ * </thead>
+ * <tbody>
  *  <tr>
- *     <td> "permissions" </td>
+ *     <th scope="row"> "permissions" </th>
  *     <td> {@link Set}&lt;{@link PosixFilePermission}&gt; </td>
  *   </tr>
  *   <tr>
- *     <td> "group" </td>
+ *     <th scope="row"> "group" </th>
  *     <td> {@link GroupPrincipal} </td>
  *   </tr>
+ * </tbody>
  * </table>
  * </blockquote>
  *
@@ -149,7 +154,8 @@
      * @throws  IOException                {@inheritDoc}
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
-     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          installed, and it denies
+     *          {@link RuntimePermission}{@code ("accessUserInformation")}
      *          or its {@link SecurityManager#checkRead(String) checkRead} method
      *          denies read access to the file.
      */
@@ -169,7 +175,8 @@
      *          if an I/O error occurs
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
-     *          installed, and it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          installed, and it denies
+     *          {@link RuntimePermission}{@code ("accessUserInformation")}
      *          or its {@link SecurityManager#checkWrite(String) checkWrite}
      *          method denies write access to the file.
      */
@@ -185,7 +192,8 @@
      *          if an I/O error occurs
      * @throws  SecurityException
      *          In the case of the default provider, and a security manager is
-     *          installed, it denies {@link RuntimePermission}<tt>("accessUserInformation")</tt>
+     *          installed, it denies
+     *          {@link RuntimePermission}{@code ("accessUserInformation")}
      *          or its {@link SecurityManager#checkWrite(String) checkWrite}
      *          method denies write access to the file.
      */
diff --git a/ojluni/src/main/java/java/nio/file/attribute/PosixFilePermissions.java b/ojluni/src/main/java/java/nio/file/attribute/PosixFilePermissions.java
index 45a866a..c98b69d 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/PosixFilePermissions.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/PosixFilePermissions.java
@@ -160,13 +160,13 @@
     {
         // copy set and check for nulls (CCE will be thrown if an element is not
         // a PosixFilePermission)
-        perms = new HashSet<PosixFilePermission>(perms);
+        perms = new HashSet<>(perms);
         for (PosixFilePermission p: perms) {
             if (p == null)
                 throw new NullPointerException();
         }
         final Set<PosixFilePermission> value = perms;
-        return new FileAttribute<Set<PosixFilePermission>>() {
+        return new FileAttribute<>() {
             @Override
             public String name() {
                 return "posix:permissions";
diff --git a/ojluni/src/main/java/java/nio/file/attribute/UserDefinedFileAttributeView.java b/ojluni/src/main/java/java/nio/file/attribute/UserDefinedFileAttributeView.java
index 56e7135..ffd89b9 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/UserDefinedFileAttributeView.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/UserDefinedFileAttributeView.java
@@ -89,7 +89,7 @@
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
      *          installed, and it denies {@link
-     *          RuntimePermission}<tt>("accessUserDefinedAttributes")</tt>
+     *          RuntimePermission}{@code ("accessUserDefinedAttributes")}
      *          or its {@link SecurityManager#checkRead(String) checkRead} method
      *          denies read access to the file.
      */
@@ -110,7 +110,7 @@
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
      *          installed, and it denies {@link
-     *          RuntimePermission}<tt>("accessUserDefinedAttributes")</tt>
+     *          RuntimePermission}{@code ("accessUserDefinedAttributes")}
      *          or its {@link SecurityManager#checkRead(String) checkRead} method
      *          denies read access to the file.
      */
@@ -156,7 +156,7 @@
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
      *          installed, and it denies {@link
-     *          RuntimePermission}<tt>("accessUserDefinedAttributes")</tt>
+     *          RuntimePermission}{@code ("accessUserDefinedAttributes")}
      *          or its {@link SecurityManager#checkRead(String) checkRead} method
      *          denies read access to the file.
      *
@@ -206,7 +206,7 @@
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
      *          installed, and it denies {@link
-     *          RuntimePermission}<tt>("accessUserDefinedAttributes")</tt>
+     *          RuntimePermission}{@code ("accessUserDefinedAttributes")}
      *          or its {@link SecurityManager#checkWrite(String) checkWrite}
      *          method denies write access to the file.
      */
@@ -223,7 +223,7 @@
      * @throws  SecurityException
      *          In the case of the default provider, a security manager is
      *          installed, and it denies {@link
-     *          RuntimePermission}<tt>("accessUserDefinedAttributes")</tt>
+     *          RuntimePermission}{@code ("accessUserDefinedAttributes")}
      *          or its {@link SecurityManager#checkWrite(String) checkWrite}
      *          method denies write access to the file.
      */
diff --git a/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalLookupService.java b/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalLookupService.java
index c3f3bef..64e2660 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalLookupService.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalLookupService.java
@@ -72,7 +72,8 @@
      *          if an I/O error occurs
      * @throws  SecurityException
      *          In the case of the default provider, and a security manager is
-     *          installed, it checks {@link RuntimePermission}<tt>("lookupUserInformation")</tt>
+     *          installed, it checks
+     *          {@link RuntimePermission}{@code ("lookupUserInformation")}
      */
     public abstract UserPrincipal lookupPrincipalByName(String name)
         throws IOException;
@@ -97,7 +98,8 @@
      *          if an I/O error occurs
      * @throws  SecurityException
      *          In the case of the default provider, and a security manager is
-     *          installed, it checks {@link RuntimePermission}<tt>("lookupUserInformation")</tt>
+     *          installed, it checks
+     *          {@link RuntimePermission}{@code ("lookupUserInformation")}
      */
     public abstract GroupPrincipal lookupPrincipalByGroupName(String group)
         throws IOException;
diff --git a/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalNotFoundException.java b/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalNotFoundException.java
index 5cf0ab0..563b339 100644
--- a/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalNotFoundException.java
+++ b/ojluni/src/main/java/java/nio/file/attribute/UserPrincipalNotFoundException.java
@@ -54,7 +54,7 @@
 
     /**
      * Returns the user principal name if this exception was created with the
-     * user principal name that was not found, otherwise <tt>null</tt>.
+     * user principal name that was not found, otherwise {@code null}.
      *
      * @return  the user principal name or {@code null}
      */
diff --git a/ojluni/src/main/java/java/nio/package-info.java b/ojluni/src/main/java/java/nio/package-info.java
index b466dc4..c743a05 100644
--- a/ojluni/src/main/java/java/nio/package-info.java
+++ b/ojluni/src/main/java/java/nio/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,8 @@
  */
 
 /**
- * Defines buffers, which are containers for data, and provides an overview of the
- * other NIO packages.
+ * Defines buffers, which are containers for data, and provides an
+ * overview of the other NIO packages.
  *
  *
  * <p> The central abstractions of the NIO APIs are: </p>
@@ -35,102 +35,121 @@
  *   <li><p> <a href="#buffers"><i>Buffers</i></a>, which are containers for data;
  *   </p></li>
  *
- *   <li><p> <a href="charset/package-summary.html"><i>Charsets</i></a> and their
- *   associated <i>decoders</i> and <i>encoders</i>, <br> which translate between
- *   bytes and Unicode characters; </p></li>
+ *   <li><p> <a
+ *   href="charset/package-summary.html"><i>Charsets</i></a> and their
+ *   associated <i>decoders</i> and <i>encoders</i>, <br> which
+ *   translate between bytes and Unicode characters; </p></li>
  *
- *   <li><p> <a href="channels/package-summary.html"><i>Channels</i></a> of
- *   various types, which represent connections <br> to entities capable of
- *   performing I/O operations; and </p></li>
+ *   <li><p> <a
+ *   href="channels/package-summary.html"><i>Channels</i></a> of
+ *   various types, which represent connections <br> to entities
+ *   capable of performing I/O operations; and </p></li>
  *
- *   <li><p> <i>Selectors</i> and <i>selection keys</i>, which together with <br>
- *   <i>selectable channels</i> define a <a
- *   href="channels/package-summary.html#multiplex">multiplexed, non-blocking <br>
- *   I/O</a>&nbsp;facility.  </p></li>
+ *   <li><p> <i>Selectors</i> and <i>selection keys</i>, which
+ *   together with <br> <i>selectable channels</i> define a <a
+ *   href="channels/package-summary.html#multiplex">multiplexed,
+ *   non-blocking <br> I/O</a> facility.  </p></li>
  *
- * </ul>
+ *  </ul>
  *
- * <p> The <tt>java.nio</tt> package defines the buffer classes, which are used
- * throughout the NIO APIs.  The charset API is defined in the {@link
- * java.nio.charset} package, and the channel and selector APIs are defined in the
- * {@link java.nio.channels} package.  Each of these subpackages has its own
- * service-provider (SPI) subpackage, the contents of which can be used to extend
- * the platform's default implementations or to construct alternative
- * implementations.
+ * <p> The {@code java.nio} package defines the buffer classes, which
+ * are used throughout the NIO APIs.  The charset API is defined in
+ * the {@link java.nio.charset} package, and the channel and selector
+ * APIs are defined in the {@link java.nio.channels} package.  Each of
+ * these subpackages has its own service-provider (SPI) subpackage,
+ * the contents of which can be used to extend the platform's default
+ * implementations or to construct alternative implementations.
  *
+ * <a id="buffers"> </a>
  *
- * <a name="buffers">
- *
- * <blockquote><table cellspacing=1 cellpadding=0 summary="Description of the various buffers">
- *   <tr><th><p align="left">Buffers</p></th><th><p align="left">Description</p></th></tr>
- *   <tr><td valign=top><tt>{@link java.nio.Buffer}</tt></td>
+ * <table class="striped" style="margin-left:2em; text-align:left">
+ *     <caption style="display:none">Description of the various buffers</caption>
+ *   <thead>
+ *   <tr><th scope="col">Buffers</th>
+ *       <th scope="col">Description</th></tr>
+ *   </thead>
+ *   <tbody>
+ *   <tr><th scope="row">{@link java.nio.Buffer}</th>
  *       <td>Position, limit, and capacity;
- *           <br>clear, flip, rewind, and mark/reset</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.ByteBuffer}</tt></td>
- *       <td>Get/put, compact, views; allocate,&nbsp;wrap</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;&nbsp;&nbsp;{@link java.nio.MappedByteBuffer}&nbsp;&nbsp;</tt></td>
+ *           clear, flip, rewind, and mark/reset</td></tr>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:1em">{@link java.nio.ByteBuffer}</span></th>
+ *       <td>Get/put, compact, views; allocate, wrap</td></tr>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:2em">{@link java.nio.MappedByteBuffer}</span></th>
  *       <td>A byte buffer mapped to a file</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.CharBuffer}</tt></td>
- *       <td>Get/put, compact; allocate,&nbsp;wrap</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.DoubleBuffer}</tt></td>
- *       <td>&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;'</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.FloatBuffer}</tt></td>
- *       <td>&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;'</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.IntBuffer}</tt></td>
- *       <td>&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;'</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.LongBuffer}</tt></td>
- *       <td>&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;'</td></tr>
- *   <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.ShortBuffer}</tt></td>
- *       <td>&nbsp;&nbsp;&nbsp;&nbsp;'&nbsp;'</td></tr>
- *   <tr><td valign=top><tt>{@link java.nio.ByteOrder}</tt></td>
- *       <td>Typesafe enumeration for&nbsp;byte&nbsp;orders</td></tr>
- * </table></blockquote>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:1em">{@link java.nio.CharBuffer}</span></th>
+ *       <td>Get/put, compact; allocate, wrap</td></tr>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:1em">{@link java.nio.DoubleBuffer}</span></th>
+ *       <td>Get/put, compact; allocate, wrap</td></tr>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:1em">{@link java.nio.FloatBuffer}</span></th>
+ *       <td>Get/put, compact; allocate, wrap</td></tr>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:1em">{@link java.nio.IntBuffer}</span></th>
+ *       <td>Get/put, compact; allocate, wrap</td></tr>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:1em">{@link java.nio.LongBuffer}</span></th>
+ *       <td>Get/put, compact; allocate, wrap</td></tr>
+ *   <tr><th scope="row">
+ *         <span style="padding-left:1em">{@link java.nio.ShortBuffer}</span></th>
+ *       <td>Get/put, compact; allocate, wrap</td></tr>
+ *   <tr><th scope="row">{@link java.nio.ByteOrder}</th>
+ *       <td>Typesafe enumeration for byte orders</td></tr>
+ * </tbody>
+ * </table>
  *
- * <p> A <i>buffer</i> is a container for a fixed amount of data of a specific
- * primitive type.  In addition to its content a buffer has a <i>position</i>,
- * which is the index of the next element to be read or written, and a
- * <i>limit</i>, which is the index of the first element that should not be read
- * or written.  The base {@link java.nio.Buffer} class defines these properties as
- * well as methods for <i>clearing</i>, <i>flipping</i>, and <i>rewinding</i>, for
- * <i>marking</i> the current position, and for <i>resetting</i> the position to
- * the previous mark.
+ * <p> A <i>buffer</i> is a container for a fixed amount of data of a
+ * specific primitive type.  In addition to its content a buffer has a
+ * <i>position</i>, which is the index of the next element to be read
+ * or written, and a <i>limit</i>, which is the index of the first
+ * element that should not be read or written.  The base {@link
+ * java.nio.Buffer} class defines these properties as well as methods
+ * for <i>clearing</i>, <i>flipping</i>, and <i>rewinding</i>, for
+ * <i>marking</i> the current position, and for <i>resetting</i> the
+ * position to the previous mark.
  *
- * <p> There is a buffer class for each non-boolean primitive type.  Each class
- * defines a family of <i>get</i> and <i>put</i> methods for moving data out of
- * and in to a buffer, methods for <i>compacting</i>, <i>duplicating</i>, and
- * <i>slicing</i> a buffer, and static methods for <i>allocating</i> a new buffer
- * as well as for <i>wrapping</i> an existing array into a buffer.
+ * <p> There is a buffer class for each non-boolean primitive type.
+ * Each class defines a family of <i>get</i> and <i>put</i> methods
+ * for moving data out of and in to a buffer, methods for
+ * <i>compacting</i>, <i>duplicating</i>, and <i>slicing</i> a buffer,
+ * and static methods for <i>allocating</i> a new buffer as well as
+ * for <i>wrapping</i> an existing array into a buffer.
  *
- * <p> Byte buffers are distinguished in that they can be used as the sources and
- * targets of I/O operations.  They also support several features not found in the
- * other buffer classes:
+ * <p> Byte buffers are distinguished in that they can be used as the
+ * sources and targets of I/O operations.  They also support several
+ * features not found in the other buffer classes:
  *
  * <ul>
  *
- *   <li><p> A byte buffer can be allocated as a <a href="ByteBuffer.html#direct">
- *   <i>direct</i></a> buffer, in which case the Java virtual machine will make a
- *   best effort to perform native I/O operations directly upon it.  </p></li>
+ *   <li><p> A byte buffer can be allocated as a <a
+ *   href="ByteBuffer.html#direct"> <i>direct</i></a> buffer, in which
+ *   case the Java virtual machine will make a best effort to perform
+ *   native I/O operations directly upon it.  </p></li>
  *
  *   <li><p> A byte buffer can be created by {@link
- *   java.nio.channels.FileChannel#map </code><i>mapping</i><code>} a region of a
- *   file directly into memory, in which case a few additional file-related
- *   operations defined in the {@link java.nio.MappedByteBuffer} class are
- *   available.  </p></li>
+ *   java.nio.channels.FileChannel#map <i>mapping</i>} a region of a
+ *   file directly into memory, in which case a few additional
+ *   file-related operations defined in the {@link
+ *   java.nio.MappedByteBuffer} class are available.  </p></li>
  *
- *   <li><p> A byte buffer provides access to its content as either a heterogeneous
- *   or homogeneous sequence of <a href="ByteBuffer.html#bin">binary data</i></a>
- *   of any non-boolean primitive type, in either big-endian or little-endian <a
- *   href="ByteOrder.html">byte order</a>.  </p></li>
+ *   <li><p> A byte buffer provides access to its content as either a
+ *   heterogeneous or homogeneous sequence of <a
+ *   href="ByteBuffer.html#bin"><i>binary data</i></a> of any
+ *   non-boolean primitive type, in either big-endian or little-endian
+ *   <a href="ByteOrder.html">byte order</a>.  </p></li>
  *
  * </ul>
  *
- * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
- * or method in any class or interface in this package will cause a {@link
- * java.lang.NullPointerException NullPointerException} to be thrown.
+ * <p> Unless otherwise noted, passing a {@code null} argument to a
+ * constructor or method in any class or interface in this package
+ * will cause a {@link java.lang.NullPointerException
+ * NullPointerException} to be thrown.
  *
  * @since 1.4
  * @author Mark Reinhold
  * @author JSR-51 Expert Group
  */
-
 package java.nio;
diff --git a/ojluni/src/main/java/java/security/AccessControlException.java b/ojluni/src/main/java/java/security/AccessControlException.java
index a4f2a78..3d654ee 100644
--- a/ojluni/src/main/java/java/security/AccessControlException.java
+++ b/ojluni/src/main/java/java/security/AccessControlException.java
@@ -38,6 +38,7 @@
  *
  * @author Li Gong
  * @author Roland Schemers
+ * @since 1.2
  */
 
 public class AccessControlException extends SecurityException {
diff --git a/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java b/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java
index 4cab0c3..7222b44 100644
--- a/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java
+++ b/ojluni/src/main/java/java/security/AlgorithmParameterGenerator.java
@@ -99,7 +99,7 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
  * AlgorithmParameterGenerator section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -164,7 +164,7 @@
      * @param algorithm the name of the algorithm this
      * parameter generator is associated with.
      * See the AlgorithmParameterGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -206,7 +206,7 @@
      * @param algorithm the name of the algorithm this
      * parameter generator is associated with.
      * See the AlgorithmParameterGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -252,7 +252,7 @@
      * @param algorithm the string name of the algorithm this
      * parameter generator is associated with.
      * See the AlgorithmParameterGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameterGenerator">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/java/security/AlgorithmParameters.java b/ojluni/src/main/java/java/security/AlgorithmParameters.java
index 989159e..fd1966f1 100644
--- a/ojluni/src/main/java/java/security/AlgorithmParameters.java
+++ b/ojluni/src/main/java/java/security/AlgorithmParameters.java
@@ -153,7 +153,7 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
  * AlgorithmParameters section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -223,7 +223,7 @@
      *
      * @param algorithm the name of the algorithm requested.
      * See the AlgorithmParameters section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -265,7 +265,7 @@
      *
      * @param algorithm the name of the algorithm requested.
      * See the AlgorithmParameters section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -314,7 +314,7 @@
      *
      * @param algorithm the name of the algorithm requested.
      * See the AlgorithmParameters section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#AlgorithmParameters">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/java/security/Certificate.java b/ojluni/src/main/java/java/security/Certificate.java
index 489c6d6..28690e2 100644
--- a/ojluni/src/main/java/java/security/Certificate.java
+++ b/ojluni/src/main/java/java/security/Certificate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,13 +56,13 @@
  * the certificate and satisfy itself of its validity.
  *
  * @author Benjamin Renaud
- * @deprecated A new certificate handling package is created in the Java platform.
- *             This Certificate interface is entirely deprecated and
- *             is here to allow for a smooth transition to the new
- *             package.
+ * @since 1.1
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by
+ *     {@code java.security.cert.Certificate} and related classes.
  * @see java.security.cert.Certificate
  */
-@Deprecated
+@Deprecated(since="1.2", forRemoval=true)
 public interface Certificate {
 
     /**
diff --git a/ojluni/src/main/java/java/security/DigestException.java b/ojluni/src/main/java/java/security/DigestException.java
index 2327c98..f275530 100644
--- a/ojluni/src/main/java/java/security/DigestException.java
+++ b/ojluni/src/main/java/java/security/DigestException.java
@@ -29,6 +29,7 @@
  * This is the generic Message Digest exception.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 public class DigestException extends GeneralSecurityException {
 
diff --git a/ojluni/src/main/java/java/security/DigestInputStream.java b/ojluni/src/main/java/java/security/DigestInputStream.java
index a1bf55a..a76ebda 100644
--- a/ojluni/src/main/java/java/security/DigestInputStream.java
+++ b/ojluni/src/main/java/java/security/DigestInputStream.java
@@ -52,13 +52,14 @@
  * {@link MessageDigest}),
  * so that in order to compute intermediate digests, a caller should
  * retain a handle onto the digest object, and clone it for each
- * digest to be computed, leaving the orginal digest untouched.
+ * digest to be computed, leaving the original digest untouched.
  *
  * @see MessageDigest
  *
  * @see DigestOutputStream
  *
  * @author Benjamin Renaud
+ * @since 1.2
  */
 
 public class DigestInputStream extends FilterInputStream {
diff --git a/ojluni/src/main/java/java/security/DigestOutputStream.java b/ojluni/src/main/java/java/security/DigestOutputStream.java
index 619faec..e941673 100644
--- a/ojluni/src/main/java/java/security/DigestOutputStream.java
+++ b/ojluni/src/main/java/java/security/DigestOutputStream.java
@@ -51,6 +51,7 @@
  * @see DigestInputStream
  *
  * @author Benjamin Renaud
+ * @since 1.2
  */
 public class DigestOutputStream extends FilterOutputStream {
 
diff --git a/ojluni/src/main/java/java/security/DomainCombiner.java b/ojluni/src/main/java/java/security/DomainCombiner.java
index e9c010f..d844939 100644
--- a/ojluni/src/main/java/java/security/DomainCombiner.java
+++ b/ojluni/src/main/java/java/security/DomainCombiner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/security/GeneralSecurityException.java b/ojluni/src/main/java/java/security/GeneralSecurityException.java
index dc9ea06..69ee8ea 100644
--- a/ojluni/src/main/java/java/security/GeneralSecurityException.java
+++ b/ojluni/src/main/java/java/security/GeneralSecurityException.java
@@ -31,6 +31,7 @@
  * security-related exception classes that extend from it.
  *
  * @author Jan Luehe
+ * @since 1.2
  */
 
 public class GeneralSecurityException extends Exception {
diff --git a/ojluni/src/main/java/java/security/Guard.java b/ojluni/src/main/java/java/security/Guard.java
index abafb58..f64a0d9 100644
--- a/ojluni/src/main/java/java/security/Guard.java
+++ b/ojluni/src/main/java/java/security/Guard.java
@@ -38,6 +38,7 @@
  *
  * @author Roland Schemers
  * @author Li Gong
+ * @since 1.2
  */
 
 public interface Guard {
diff --git a/ojluni/src/main/java/java/security/GuardedObject.java b/ojluni/src/main/java/java/security/GuardedObject.java
index a275ddf..a2bf3f7 100644
--- a/ojluni/src/main/java/java/security/GuardedObject.java
+++ b/ojluni/src/main/java/java/security/GuardedObject.java
@@ -44,6 +44,7 @@
  *
  * @author Roland Schemers
  * @author Li Gong
+ * @since 1.2
  */
 
 public class GuardedObject implements java.io.Serializable {
diff --git a/ojluni/src/main/java/java/security/Identity.java b/ojluni/src/main/java/java/security/Identity.java
index e63131e..e6b2e80 100644
--- a/ojluni/src/main/java/java/security/Identity.java
+++ b/ojluni/src/main/java/java/security/Identity.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,12 +52,14 @@
  * @see Principal
  *
  * @author Benjamin Renaud
- * @deprecated This class is no longer used. Its functionality has been
- * replaced by {@code java.security.KeyStore}, the
- * {@code java.security.cert} package, and
- * {@code java.security.Principal}.
+ * @since 1.1
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by
+ *     {@code java.security.KeyStore}, the {@code java.security.cert} package,
+ *     and {@code java.security.Principal}.
  */
-@Deprecated
+@Deprecated(since="1.2", forRemoval=true)
+@SuppressWarnings("removal")
 public abstract class Identity implements Principal, Serializable {
 
     /** use serialVersionUID from JDK 1.1.x for interoperability */
@@ -186,7 +188,7 @@
 
         check("setIdentityPublicKey");
         this.publicKey = key;
-        certificates = new Vector<Certificate>();
+        certificates = new Vector<>();
     }
 
     /**
@@ -249,7 +251,7 @@
         check("addIdentityCertificate");
 
         if (certificates == null) {
-            certificates = new Vector<Certificate>();
+            certificates = new Vector<>();
         }
         if (publicKey != null) {
             if (!keyEquals(publicKey, certificate.getPublicKey())) {
diff --git a/ojluni/src/main/java/java/security/IdentityScope.java b/ojluni/src/main/java/java/security/IdentityScope.java
index 61d37cb..9dddd56 100644
--- a/ojluni/src/main/java/java/security/IdentityScope.java
+++ b/ojluni/src/main/java/java/security/IdentityScope.java
@@ -63,6 +63,8 @@
  * {@code java.security.Principal}.
  */
 @Deprecated
+// Android-added: Identity is deprecated too, no need to warn here.
+@SuppressWarnings("removal")
 public abstract
 class IdentityScope extends Identity {
 
diff --git a/ojluni/src/main/java/java/security/InvalidAlgorithmParameterException.java b/ojluni/src/main/java/java/security/InvalidAlgorithmParameterException.java
index 559a8be..9636fcb 100644
--- a/ojluni/src/main/java/java/security/InvalidAlgorithmParameterException.java
+++ b/ojluni/src/main/java/java/security/InvalidAlgorithmParameterException.java
@@ -65,7 +65,7 @@
     }
 
     /**
-     * Creates a {@code InvalidAlgorithmParameterException} with the
+     * Creates an {@code InvalidAlgorithmParameterException} with the
      * specified detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
@@ -80,7 +80,7 @@
     }
 
     /**
-     * Creates a {@code InvalidAlgorithmParameterException} with the
+     * Creates an {@code InvalidAlgorithmParameterException} with the
      * specified cause and a detail message of
      * {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
diff --git a/ojluni/src/main/java/java/security/InvalidKeyException.java b/ojluni/src/main/java/java/security/InvalidKeyException.java
index 35fc64c..5349796 100644
--- a/ojluni/src/main/java/java/security/InvalidKeyException.java
+++ b/ojluni/src/main/java/java/security/InvalidKeyException.java
@@ -31,6 +31,7 @@
  * length, uninitialized, etc).
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public class InvalidKeyException extends KeyException {
@@ -58,7 +59,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeyException} with the specified
+     * Creates an {@code InvalidKeyException} with the specified
      * detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
@@ -73,7 +74,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeyException} with the specified cause
+     * Creates an {@code InvalidKeyException} with the specified cause
      * and a detail message of {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
      * {@code cause}).
diff --git a/ojluni/src/main/java/java/security/InvalidParameterException.java b/ojluni/src/main/java/java/security/InvalidParameterException.java
index a095f90..18d413e 100644
--- a/ojluni/src/main/java/java/security/InvalidParameterException.java
+++ b/ojluni/src/main/java/java/security/InvalidParameterException.java
@@ -31,6 +31,7 @@
  * to a method.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public class InvalidParameterException extends IllegalArgumentException {
diff --git a/ojluni/src/main/java/java/security/Key.java b/ojluni/src/main/java/java/security/Key.java
index c0c63d7..ff5611e 100644
--- a/ojluni/src/main/java/java/security/Key.java
+++ b/ojluni/src/main/java/java/security/Key.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,7 +63,7 @@
  * </pre>
  *
  * For more information, see
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280:
  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>.
  *
  * <LI>A Format
@@ -82,7 +82,7 @@
  * <p> A Key should use KeyRep as its serialized representation.
  * Note that a serialized Key may contain sensitive information
  * which should not be exposed in untrusted environments.  See the
- * <a href="../../../platform/serialization/spec/security.html">
+ * <a href="{@docRoot}/../specs/serialization/security.html">
  * Security Appendix</a>
  * of the Serialization Specification for more information.
  *
@@ -97,6 +97,7 @@
  * @see Signer
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public interface Key extends java.io.Serializable {
@@ -113,10 +114,10 @@
     /**
      * Returns the standard algorithm name for this key. For
      * example, "DSA" would indicate that this key is a DSA key.
-     * See Appendix A in the <a href=
-     * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
-     * Java Cryptography Architecture API Specification &amp; Reference </a>
-     * for information about standard algorithm names.
+     * See the <a href=
+     * "{@docRoot}/../specs/security/standard-names.html">
+     * Java Security Standard Algorithm Names</a> document
+     * for more information.
      *
      * @return the name of the algorithm associated with this key.
      */
diff --git a/ojluni/src/main/java/java/security/KeyException.java b/ojluni/src/main/java/java/security/KeyException.java
index 59cdd6f..b8b87d9 100644
--- a/ojluni/src/main/java/java/security/KeyException.java
+++ b/ojluni/src/main/java/java/security/KeyException.java
@@ -33,6 +33,7 @@
  * @see KeyManagementException
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public class KeyException extends GeneralSecurityException {
diff --git a/ojluni/src/main/java/java/security/KeyFactory.java b/ojluni/src/main/java/java/security/KeyFactory.java
index f687d61..716f62d 100644
--- a/ojluni/src/main/java/java/security/KeyFactory.java
+++ b/ojluni/src/main/java/java/security/KeyFactory.java
@@ -100,7 +100,7 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
  * KeyFactory section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -178,7 +178,7 @@
      *
      * @param algorithm the name of the requested key algorithm.
      * See the KeyFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -209,7 +209,7 @@
      *
      * @param algorithm the name of the requested key algorithm.
      * See the KeyFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -250,7 +250,7 @@
      *
      * @param algorithm the name of the requested key algorithm.
      * See the KeyFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/java/security/KeyManagementException.java b/ojluni/src/main/java/java/security/KeyManagementException.java
index be212b9..fe1ab3e 100644
--- a/ojluni/src/main/java/java/security/KeyManagementException.java
+++ b/ojluni/src/main/java/java/security/KeyManagementException.java
@@ -38,6 +38,7 @@
  * </ul>
  *
  * @author Benjamin Renaud
+ * @since 1.1
  *
  * @see Key
  * @see KeyException
diff --git a/ojluni/src/main/java/java/security/KeyPair.java b/ojluni/src/main/java/java/security/KeyPair.java
index 6147a16..1d9e164 100644
--- a/ojluni/src/main/java/java/security/KeyPair.java
+++ b/ojluni/src/main/java/java/security/KeyPair.java
@@ -36,6 +36,7 @@
  * @see PrivateKey
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public final class KeyPair implements java.io.Serializable {
diff --git a/ojluni/src/main/java/java/security/KeyPairGenerator.java b/ojluni/src/main/java/java/security/KeyPairGenerator.java
index 1c4c2cb..842bee0 100644
--- a/ojluni/src/main/java/java/security/KeyPairGenerator.java
+++ b/ojluni/src/main/java/java/security/KeyPairGenerator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,12 +70,12 @@
  * associated with each of the keys.
  *
  * <p>If the algorithm is the <i>DSA</i> algorithm, and the keysize (modulus
- * size) is 512, 768, or 1024, then the <i>Sun</i> provider uses a set of
+ * size) is 512, 768, 1024, or 2048, then the <i>Sun</i> provider uses a set of
  * precomputed values for the {@code p}, {@code q}, and
  * {@code g} parameters. If the modulus size is not one of the above
  * values, the <i>Sun</i> provider creates a new set of parameters. Other
  * providers might have precomputed parameter sets for more than just the
- * three modulus sizes mentioned above. Still others might not have a list of
+ * modulus sizes mentioned above. Still others might not have a list of
  * precomputed parameters at all and instead always create new parameter sets.
  *
  * <li><b>Algorithm-Specific Initialization</b>
@@ -83,7 +83,7 @@
  * exists (e.g., so-called <i>community parameters</i> in DSA), there are two
  * {@link #initialize(java.security.spec.AlgorithmParameterSpec)
  * initialize} methods that have an {@code AlgorithmParameterSpec}
- * argument. One also has a {@code SecureRandom} argument, while the
+ * argument. One also has a {@code SecureRandom} argument, while
  * the other uses the {@code SecureRandom}
  * implementation of the highest-priority installed provider as the source
  * of randomness. (If none of the installed providers supply an implementation
@@ -133,11 +133,12 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator">
+ * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
  * KeyPairGenerator section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  *
  * @see java.security.spec.AlgorithmParameterSpec
  */
@@ -162,8 +163,8 @@
      *
      * @param algorithm the standard string name of the algorithm.
      * See the KeyPairGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      */
     protected KeyPairGenerator(String algorithm) {
@@ -173,8 +174,8 @@
     /**
      * Returns the standard name of the algorithm for this key pair generator.
      * See the KeyPairGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @return the standard string name of the algorithm.
@@ -218,22 +219,33 @@
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
+     * @implNote
+     * The JDK Reference Implementation additionally uses the
+     * {@code jdk.security.provider.preferred}
+     * {@link Security#getProperty(String) Security} property to determine
+     * the preferred provider order for the specified algorithm. This
+     * may be different than the order of providers returned by
+     * {@link Security#getProviders() Security.getProviders()}.
+     *
      * @param algorithm the standard string name of the algorithm.
      * See the KeyPairGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
-     * @return the new KeyPairGenerator object.
+     * @return the new {@code KeyPairGenerator} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          KeyPairGeneratorSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code KeyPairGeneratorSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static KeyPairGenerator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         List<Service> list =
                 GetInstance.getServices("KeyPairGenerator", algorithm);
         Iterator<Service> t = list.iterator();
@@ -276,29 +288,32 @@
      *
      * @param algorithm the standard string name of the algorithm.
      * See the KeyPairGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the string name of the provider.
      *
-     * @return the new KeyPairGenerator object.
+     * @return the new {@code KeyPairGenerator} object
      *
-     * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static KeyPairGenerator getInstance(String algorithm,
             String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         // Android-added: Check for Bouncy Castle deprecation
         Providers.checkBouncyCastleDeprecation(provider, "KeyPairGenerator", algorithm);
         Instance instance = GetInstance.getInstance("KeyPairGenerator",
@@ -317,19 +332,22 @@
      *
      * @param algorithm the standard string name of the algorithm.
      * See the KeyPairGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keypairgenerator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the provider.
      *
-     * @return the new KeyPairGenerator object.
+     * @return the new {@code KeyPairGenerator} object
      *
-     * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -337,6 +355,7 @@
      */
     public static KeyPairGenerator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         // Android-added: Check for Bouncy Castle deprecation
         Providers.checkBouncyCastleDeprecation(provider, "KeyPairGenerator", algorithm);
         Instance instance = GetInstance.getInstance("KeyPairGenerator",
@@ -412,7 +431,7 @@
      * of randomness.
      * (If none of the installed providers supply an implementation of
      * {@code SecureRandom}, a system-provided source of randomness is
-     * used.).
+     * used.)
      *
      * <p>This concrete method has been added to this previously-defined
      * abstract class.
@@ -574,9 +593,9 @@
 
         private Iterator<Service> serviceIterator;
 
-        private final static int I_NONE   = 1;
-        private final static int I_SIZE   = 2;
-        private final static int I_PARAMS = 3;
+        private static final int I_NONE   = 1;
+        private static final int I_SIZE   = 2;
+        private static final int I_PARAMS = 3;
 
         private int initType;
         private int initKeySize;
diff --git a/ojluni/src/main/java/java/security/KeyPairGeneratorSpi.java b/ojluni/src/main/java/java/security/KeyPairGeneratorSpi.java
index dfe8c04..a5dba15 100644
--- a/ojluni/src/main/java/java/security/KeyPairGeneratorSpi.java
+++ b/ojluni/src/main/java/java/security/KeyPairGeneratorSpi.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@
  * of 1024 bits.
  *
  * @author Benjamin Renaud
+ * @since 1.2
  *
  *
  * @see KeyPairGenerator
diff --git a/ojluni/src/main/java/java/security/KeyRep.java b/ojluni/src/main/java/java/security/KeyRep.java
index 0b1412c..9d53635 100644
--- a/ojluni/src/main/java/java/security/KeyRep.java
+++ b/ojluni/src/main/java/java/security/KeyRep.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
  *
  * Note that a serialized Key may contain sensitive information
  * which should not be exposed in untrusted environments.  See the
- * <a href="../../../platform/serialization/spec/security.html">
+ * <a href="{@docRoot}/../specs/serialization/security.html">
  * Security Appendix</a>
  * of the Serialization Specification for more information.
  *
@@ -112,8 +112,6 @@
     /**
      * Construct the alternate Key class.
      *
-     * <p>
-     *
      * @param type either one of Type.SECRET, Type.PUBLIC, or Type.PRIVATE
      * @param algorithm the algorithm returned from
      *          {@code Key.getAlgorithm()}
@@ -157,8 +155,6 @@
      * encoded key bytes, and generates a private key from the spec
      * </ul>
      *
-     * <p>
-     *
      * @return the resolved Key object
      *
      * @exception ObjectStreamException if the Type/format
diff --git a/ojluni/src/main/java/java/security/KeyStore.java b/ojluni/src/main/java/java/security/KeyStore.java
index 924f14f..9e9aa20 100644
--- a/ojluni/src/main/java/java/security/KeyStore.java
+++ b/ojluni/src/main/java/java/security/KeyStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,8 @@
 import javax.security.auth.DestroyFailedException;
 import javax.security.auth.callback.*;
 
+import sun.security.util.Debug;
+
 /**
  * This class represents a storage facility for cryptographic
  * keys and certificates.
@@ -90,9 +92,23 @@
  * be used (in a variety of formats).
  *
  * <p> Typical ways to request a KeyStore object include
+ * specifying an existing keystore file,
  * relying on the default type and providing a specific keystore type.
  *
  * <ul>
+ * <li>To specify an existing keystore file:
+ * <pre>
+ *    // get keystore password
+ *    char[] password = getPassword();
+ *
+ *    // probe the keystore file and load the keystore entries
+ *    KeyStore ks = KeyStore.getInstance(new File("keyStoreName"), password);
+ *</pre>
+ * The system will probe the specified file to determine its keystore type
+ * and return a keystore implementation with its entries already loaded.
+ * When this approach is used there is no need to call the keystore's
+ * {@link #load(java.io.InputStream, char[]) load} method.
+ *
  * <li>To rely on the default type:
  * <pre>
  *    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
@@ -104,7 +120,7 @@
  *      KeyStore ks = KeyStore.getInstance("JKS");
  * </pre>
  * The system will return the most preferred implementation of the
- * specified keystore type available in the environment. <p>
+ * specified keystore type available in the environment.
  * </ul>
  *
  * <p> Before a keystore can be accessed, it must be
@@ -195,7 +211,7 @@
  * </table>
  *
  * These types are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
  * KeyStore section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -210,6 +226,7 @@
 
 public class KeyStore {
 
+    private static final Debug kdebug = Debug.getInstance("keystore");
     // BEGIN Android-removed: this debugging mechanism is not supported in Android.
     /*
     private static final Debug pdebug =
@@ -311,9 +328,8 @@
          * @param protectionAlgorithm the encryption algorithm name, for
          *     example, {@code PBEWithHmacSHA256AndAES_256}.
          *     See the Cipher section in the <a href=
-         * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
-         * Java Cryptography Architecture Standard Algorithm Name
-         * Documentation</a>
+         * "{@docRoot}/../specs/security/standard-names.html#cipher-algorithm-names">
+         * Java Security Standard Algorithm Names Specification</a>
          *     for information about standard encryption algorithm names.
          * @param protectionParameters the encryption algorithm parameter
          *     specification, which may be {@code null}
@@ -451,7 +467,8 @@
 
         /**
          * Retrieves the attributes associated with an entry.
-         * <p>
+         *
+         * @implSpec
          * The default implementation returns an empty {@code Set}.
          *
          * @return an unmodifiable {@code Set} of attributes, possibly empty
@@ -635,7 +652,6 @@
 
         /**
          * Retrieves the attributes associated with an entry.
-         * <p>
          *
          * @return an unmodifiable {@code Set} of attributes, possibly empty
          *
@@ -726,7 +742,6 @@
 
         /**
          * Retrieves the attributes associated with an entry.
-         * <p>
          *
          * @return an unmodifiable {@code Set} of attributes, possibly empty
          *
@@ -810,7 +825,6 @@
 
         /**
          * Retrieves the attributes associated with an entry.
-         * <p>
          *
          * @return an unmodifiable {@code Set} of attributes, possibly empty
          *
@@ -868,11 +882,11 @@
      *
      * @param type the type of keystore.
      * See the KeyStore section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keystore-types">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard keystore types.
      *
-     * @return a keystore object of the specified type.
+     * @return a keystore object of the specified type
      *
      * @exception KeyStoreException if no Provider supports a
      *          KeyStoreSpi implementation for the
@@ -906,13 +920,13 @@
      *
      * @param type the type of keystore.
      * See the KeyStore section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keystore-types">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard keystore types.
      *
      * @param provider the name of the provider.
      *
-     * @return a keystore object of the specified type.
+     * @return a keystore object of the specified type
      *
      * @exception KeyStoreException if a KeyStoreSpi
      *          implementation for the specified type is not
@@ -949,19 +963,22 @@
      *
      * @param type the type of keystore.
      * See the KeyStore section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keystore-types">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard keystore types.
      *
      * @param provider the provider.
      *
-     * @return a keystore object of the specified type.
+     * @return a keystore object of the specified type
      *
-     * @exception KeyStoreException if KeyStoreSpi
-     *          implementation for the specified type is not available
-     *          from the specified Provider object.
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws KeyStoreException if {@code KeyStoreSpi}
+     *         implementation for the specified type is not available
+     *         from the specified {@code Provider} object
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see Provider
      *
@@ -970,8 +987,12 @@
     public static KeyStore getInstance(String type, Provider provider)
         throws KeyStoreException
     {
+        // Android-removed: move non-null check to after provider == null check (b/216552850)
+        // Objects.requireNonNull(type, "null type name");
         if (provider == null)
             throw new IllegalArgumentException("missing provider");
+        // Android-added: move non-null check to after provider == null check (b/216552850)
+        Objects.requireNonNull(type, "null type name");
         try {
             Object[] objs = Security.getImpl(type, "KeyStore", provider);
             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
@@ -999,9 +1020,9 @@
      * if no such property exists.
      * @see java.security.Security security properties
      */
-    public final static String getDefaultType() {
+    public static final String getDefaultType() {
         String kstype;
-        kstype = AccessController.doPrivileged(new PrivilegedAction<String>() {
+        kstype = AccessController.doPrivileged(new PrivilegedAction<>() {
             public String run() {
                 return Security.getProperty(KEYSTORE_TYPE);
             }
@@ -1632,6 +1653,197 @@
     }
 
     /**
+     * Returns a loaded keystore object of the appropriate keystore type.
+     * First the keystore type is determined by probing the specified file.
+     * Then a keystore object is instantiated and loaded using the data from
+     * that file.
+     *
+     * <p>
+     * A password may be given to unlock the keystore
+     * (e.g. the keystore resides on a hardware token device),
+     * or to check the integrity of the keystore data.
+     * If a password is not given for integrity checking,
+     * then integrity checking is not performed.
+     *
+     * <p>
+     * This method traverses the list of registered security
+     * {@linkplain Provider providers}, starting with the most
+     * preferred Provider.
+     * For each {@link KeyStoreSpi} implementation supported by a
+     * Provider, it invokes the {@link
+     * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
+     * determine if it supports the specified keystore.
+     * A new KeyStore object is returned that encapsulates the KeyStoreSpi
+     * implementation from the first Provider that supports the specified file.
+     *
+     * <p> Note that the list of registered providers may be retrieved via
+     * the {@link Security#getProviders() Security.getProviders()} method.
+     *
+     * @param  file the keystore file
+     * @param  password the keystore password, which may be {@code null}
+     *
+     * @return a keystore object loaded with keystore data
+     *
+     * @throws KeyStoreException if no Provider supports a KeyStoreSpi
+     *             implementation for the specified keystore file.
+     * @throws IOException if there is an I/O or format problem with the
+     *             keystore data, if a password is required but not given,
+     *             or if the given password was incorrect. If the error is
+     *             due to a wrong password, the {@link Throwable#getCause cause}
+     *             of the {@code IOException} should be an
+     *             {@code UnrecoverableKeyException}.
+     * @throws NoSuchAlgorithmException if the algorithm used to check the
+     *             integrity of the keystore cannot be found.
+     * @throws CertificateException if any of the certificates in the
+     *             keystore could not be loaded.
+     * @throws IllegalArgumentException if file does not exist or does not
+     *             refer to a normal file.
+     * @throws NullPointerException if file is {@code null}.
+     * @throws SecurityException if a security manager exists and its
+     *             {@link java.lang.SecurityManager#checkRead} method denies
+     *             read access to the specified file.
+     *
+     * @see Provider
+     *
+     * @since 9
+     */
+    public static final KeyStore getInstance(File file, char[] password)
+        throws KeyStoreException, IOException, NoSuchAlgorithmException,
+            CertificateException {
+        return getInstance(file, password, null, true);
+    }
+
+    /**
+     * Returns a loaded keystore object of the appropriate keystore type.
+     * First the keystore type is determined by probing the specified file.
+     * Then a keystore object is instantiated and loaded using the data from
+     * that file.
+     * A {@code LoadStoreParameter} may be supplied which specifies how to
+     * unlock the keystore data or perform an integrity check.
+     *
+     * <p>
+     * This method traverses the list of registered security {@linkplain
+     * Provider providers}, starting with the most preferred Provider.
+     * For each {@link KeyStoreSpi} implementation supported by a
+     * Provider, it invokes the {@link
+     * KeyStoreSpi#engineProbe(InputStream) engineProbe} method to
+     * determine if it supports the specified keystore.
+     * A new KeyStore object is returned that encapsulates the KeyStoreSpi
+     * implementation from the first Provider that supports the specified file.
+     *
+     * <p> Note that the list of registered providers may be retrieved via
+     * the {@link Security#getProviders() Security.getProviders()} method.
+     *
+     * @param  file the keystore file
+     * @param  param the {@code LoadStoreParameter} that specifies how to load
+     *             the keystore, which may be {@code null}
+     *
+     * @return a keystore object loaded with keystore data
+     *
+     * @throws KeyStoreException if no Provider supports a KeyStoreSpi
+     *             implementation for the specified keystore file.
+     * @throws IOException if there is an I/O or format problem with the
+     *             keystore data. If the error is due to an incorrect
+     *             {@code ProtectionParameter} (e.g. wrong password)
+     *             the {@link Throwable#getCause cause} of the
+     *             {@code IOException} should be an
+     *             {@code UnrecoverableKeyException}.
+     * @throws NoSuchAlgorithmException if the algorithm used to check the
+     *             integrity of the keystore cannot be found.
+     * @throws CertificateException if any of the certificates in the
+     *             keystore could not be loaded.
+     * @throws IllegalArgumentException if file does not exist or does not
+     *             refer to a normal file, or if param is not recognized.
+     * @throws NullPointerException if file is {@code null}.
+     * @throws SecurityException if a security manager exists and its
+     *             {@link java.lang.SecurityManager#checkRead} method denies
+     *             read access to the specified file.
+     *
+     * @see Provider
+     *
+     * @since 9
+     */
+    public static final KeyStore getInstance(File file,
+        LoadStoreParameter param) throws KeyStoreException, IOException,
+            NoSuchAlgorithmException, CertificateException {
+        return getInstance(file, null, param, false);
+    }
+
+    // Used by getInstance(File, char[]) & getInstance(File, LoadStoreParameter)
+    private static final KeyStore getInstance(File file, char[] password,
+        LoadStoreParameter param, boolean hasPassword)
+            throws KeyStoreException, IOException, NoSuchAlgorithmException,
+                CertificateException {
+
+        if (file == null) {
+            throw new NullPointerException();
+        }
+
+        if (file.isFile() == false) {
+            throw new IllegalArgumentException(
+                "File does not exist or it does not refer to a normal file: " +
+                    file);
+        }
+
+        KeyStore keystore = null;
+
+        try (DataInputStream dataStream =
+            new DataInputStream(
+                new BufferedInputStream(
+                    new FileInputStream(file)))) {
+
+            dataStream.mark(Integer.MAX_VALUE);
+
+            // Detect the keystore type
+            for (String type : Security.getAlgorithms("KeyStore")) {
+                Object[] objs = null;
+
+                try {
+                    objs = Security.getImpl(type, "KeyStore", (String)null);
+
+                    KeyStoreSpi impl = (KeyStoreSpi)objs[0];
+                    if (impl.engineProbe(dataStream)) {
+
+                        if (kdebug != null) {
+                            kdebug.println(type + " keystore detected: " +
+                                file);
+                        }
+
+                        keystore = new KeyStore(impl, (Provider)objs[1], type);
+                        break;
+                    }
+                } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+                    // ignore
+                    if (kdebug != null) {
+                        kdebug.println(type + " not found - " + e);
+                    }
+                } catch (IOException e) {
+                    // ignore
+                    if (kdebug != null) {
+                        kdebug.println("I/O error in " + file + " - " + e);
+                    }
+                }
+                dataStream.reset(); // prepare the stream for the next probe
+            }
+
+            // Load the keystore data
+            if (keystore != null) {
+                dataStream.reset(); // prepare the stream for loading
+                if (hasPassword) {
+                    keystore.load(dataStream, password);
+                } else {
+                    keystore.keyStoreSpi.engineLoad(dataStream, param);
+                    keystore.initialized = true;
+                }
+                return keystore;
+            }
+        }
+
+        throw new KeyStoreException("Unrecognized keystore format. "
+                + "Please load it with a specified type");
+    }
+
+    /**
      * A description of a to-be-instantiated KeyStore object.
      *
      * <p>An instance of this class encapsulates the information needed to
@@ -1646,7 +1858,7 @@
      * @see javax.net.ssl.KeyStoreBuilderParameters
      * @since 1.5
      */
-    public static abstract class Builder {
+    public abstract static class Builder {
 
         // maximum times to try the callbackhandler if the password is wrong
         static final int MAX_CALLBACK_TRIES = 3;
@@ -1751,7 +1963,7 @@
          * by invoking the CallbackHandler.
          *
          * <p>Subsequent calls to {@link #getKeyStore} return the same object
-         * as the initial call. If the initial call to failed with a
+         * as the initial call. If the initial call failed with a
          * KeyStoreException, subsequent calls also throw a
          * KeyStoreException.
          *
@@ -1798,6 +2010,50 @@
                 AccessController.getContext());
         }
 
+        /**
+         * Returns a new Builder object.
+         *
+         * <p>The first call to the {@link #getKeyStore} method on the returned
+         * builder will create a KeyStore using {@code file} to detect the
+         * keystore type and then call its {@link KeyStore#load load()} method.
+         * It uses the same algorithm to determine the keystore type as
+         * described in {@link KeyStore#getInstance(File, LoadStoreParameter)}.
+         * The {@code inputStream} argument is constructed from {@code file}.
+         * If {@code protection} is a {@code PasswordProtection}, the password
+         * is obtained by calling the {@code getPassword} method.
+         * Otherwise, if {@code protection} is a
+         * {@code CallbackHandlerProtection},
+         * the password is obtained by invoking the CallbackHandler.
+         *
+         * <p>Subsequent calls to {@link #getKeyStore} return the same object
+         * as the initial call. If the initial call failed with a
+         * KeyStoreException, subsequent calls also throw a KeyStoreException.
+         *
+         * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
+         * will return a {@link KeyStore.PasswordProtection PasswordProtection}
+         * object encapsulating the password that was used to invoke the
+         * {@code load} method.
+         *
+         * <p><em>Note</em> that the {@link #getKeyStore} method is executed
+         * within the {@link AccessControlContext} of the code invoking this
+         * method.
+         *
+         * @return a new Builder object
+         * @param file the File that contains the KeyStore data
+         * @param protection the ProtectionParameter securing the KeyStore data
+         * @throws NullPointerException if file or protection is null
+         * @throws IllegalArgumentException if protection is not an instance
+         *   of either PasswordProtection or CallbackHandlerProtection; or
+         *   if file does not exist or does not refer to a normal file
+         *
+         * @since 9
+         */
+        public static Builder newInstance(File file,
+            ProtectionParameter protection) {
+
+            return newInstance("", null, file, protection);
+        }
+
         private static final class FileBuilder extends Builder {
 
             private final String type;
@@ -1855,42 +2111,46 @@
                     }
                     public KeyStore run0() throws Exception {
                         KeyStore ks;
-                        if (provider == null) {
-                            ks = KeyStore.getInstance(type);
-                        } else {
-                            ks = KeyStore.getInstance(type, provider);
-                        }
-                        InputStream in = null;
                         char[] password = null;
-                        try {
-                            in = new FileInputStream(file);
-                            if (protection instanceof PasswordProtection) {
-                                password =
+
+                        // Acquire keystore password
+                        if (protection instanceof PasswordProtection) {
+                            password =
                                 ((PasswordProtection)protection).getPassword();
-                                keyProtection = protection;
-                            } else {
-                                CallbackHandler handler =
-                                    ((CallbackHandlerProtection)protection)
+                            keyProtection = protection;
+                        } else {
+                            CallbackHandler handler =
+                                ((CallbackHandlerProtection)protection)
                                     .getCallbackHandler();
-                                PasswordCallback callback = new PasswordCallback
-                                    ("Password for keystore " + file.getName(),
+                            PasswordCallback callback = new PasswordCallback
+                                ("Password for keystore " + file.getName(),
                                     false);
-                                handler.handle(new Callback[] {callback});
-                                password = callback.getPassword();
-                                if (password == null) {
-                                    throw new KeyStoreException("No password" +
-                                                                " provided");
-                                }
-                                callback.clearPassword();
-                                keyProtection = new PasswordProtection(password);
+                            handler.handle(new Callback[] {callback});
+                            password = callback.getPassword();
+                            if (password == null) {
+                                throw new KeyStoreException("No password" +
+                                                            " provided");
                             }
-                            ks.load(in, password);
-                            return ks;
-                        } finally {
-                            if (in != null) {
-                                in.close();
+                            callback.clearPassword();
+                            keyProtection = new PasswordProtection(password);
+                        }
+
+                        if (type.isEmpty()) {
+                            // Instantiate keystore and load keystore data
+                            ks = KeyStore.getInstance(file, password);
+                        } else {
+                            // Instantiate keystore
+                            if (provider == null) {
+                                ks = KeyStore.getInstance(type);
+                            } else {
+                                ks = KeyStore.getInstance(type, provider);
+                            }
+                            // Load keystore data
+                            try (InputStream in = new FileInputStream(file)) {
+                                ks.load(in, password);
                             }
                         }
+                        return ks;
                     }
                 };
                 try {
@@ -2036,5 +2296,4 @@
             return protection;
         }
     }
-
 }
diff --git a/ojluni/src/main/java/java/security/KeyStoreSpi.java b/ojluni/src/main/java/java/security/KeyStoreSpi.java
index 531a983..2866b50 100644
--- a/ojluni/src/main/java/java/security/KeyStoreSpi.java
+++ b/ojluni/src/main/java/java/security/KeyStoreSpi.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -380,6 +380,12 @@
     public void engineLoad(KeyStore.LoadStoreParameter param)
                 throws IOException, NoSuchAlgorithmException,
                 CertificateException {
+        engineLoad(null, param);
+    }
+
+    void engineLoad(InputStream stream, KeyStore.LoadStoreParameter param)
+                throws IOException, NoSuchAlgorithmException,
+                CertificateException {
 
         if (param == null) {
             engineLoad((InputStream)null, (char[])null);
@@ -447,13 +453,34 @@
                         KeyStore.ProtectionParameter protParam)
                 throws KeyStoreException, NoSuchAlgorithmException,
                 UnrecoverableEntryException {
-
-        if (!engineContainsAlias(alias)) {
+        // Android-changed: add null check previously always done here inside engineContainsAlias
+        // if (!engineContainsAlias(alias)) {
+        if (alias == null) {
             return null;
         }
 
+        // BEGIN Android-added: Figure out the type of entry once
+        // To avoid many redundant calls that for some providers like
+        // AndroidKeyStoreSpi are costly since it performs
+        // binder transactions everytime we call engineIsKeyEntry or
+        // engineContainsAlias methods and rely on the knowledge
+        // that the only two types of entries are keys or certificates.
+        boolean isCertificateEntry;
+        if (!engineIsKeyEntry(alias)){
+            if (!engineContainsAlias(alias)) {
+                return null;
+            }
+            // If it is not a key then it has to be a certificate
+            isCertificateEntry = true;
+        } else {
+            isCertificateEntry = false;
+        }
+        // END Android-added: Figure out the type of entry once
+
         if (protParam == null) {
-            if (engineIsCertificateEntry(alias)) {
+            // Android-changed: Use cached value
+            // if (engineIsCertificateEntry(alias)) {
+            if (isCertificateEntry) {
                 return new KeyStore.TrustedCertificateEntry
                                 (engineGetCertificate(alias));
             // Android-removed: Allow access to entries with no password.
@@ -465,10 +492,12 @@
 
         // Android-changed: Add protParam == null to allow access to entries with no password.
         if ((protParam == null) || protParam instanceof KeyStore.PasswordProtection) {
-            if (engineIsCertificateEntry(alias)) {
+            if (isCertificateEntry) {
                 throw new UnsupportedOperationException
                     ("trusted certificate entries are not password-protected");
-            } else if (engineIsKeyEntry(alias)) {
+                // Android-changed: avoid redundant check
+                // else if (engineIsKeyEntry(alias)) {
+            } else {
                 // Android-changed: Allow access to entries with no password.
                 // KeyStore.PasswordProtection pp =
                 //         (KeyStore.PasswordProtection)protParam;
@@ -584,4 +613,29 @@
         }
         return false;
     }
+
+    /**
+     * Probes the specified input stream to determine whether it contains a
+     * keystore that is supported by this implementation, or not.
+     *
+     * @implSpec
+     * This method returns false by default. Keystore implementations should
+     * override this method to peek at the data stream directly or to use other
+     * content detection mechanisms.
+     *
+     * @param  stream the keystore data to be probed
+     *
+     * @return true if the keystore data is supported, otherwise false
+     *
+     * @throws IOException if there is an I/O problem with the keystore data.
+     * @throws NullPointerException if stream is {@code null}.
+     *
+     * @since 9
+     */
+    public boolean engineProbe(InputStream stream) throws IOException {
+        if (stream == null) {
+            throw new NullPointerException("input stream must not be null");
+        }
+        return false;
+    }
 }
diff --git a/ojluni/src/main/java/java/security/MessageDigest.java b/ojluni/src/main/java/java/security/MessageDigest.java
index 996339e..ff0951c 100644
--- a/ojluni/src/main/java/java/security/MessageDigest.java
+++ b/ojluni/src/main/java/java/security/MessageDigest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
 import java.nio.ByteBuffer;
 
 import sun.security.jca.Providers;
+import javax.crypto.SecretKey;
 
 /**
  * This MessageDigest class provides applications the functionality of a
@@ -59,7 +60,7 @@
  * and catching the CloneNotSupportedException:
  *
  * <pre>{@code
- * MessageDigest md = MessageDigest.getInstance("SHA");
+ * MessageDigest md = MessageDigest.getInstance("SHA-256");
  *
  * try {
  *     md.update(toChapter1);
@@ -120,11 +121,12 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest">
+ * "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
  * MessageDigest section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  *
  * @see DigestInputStream
  * @see DigestOutputStream
@@ -155,8 +157,8 @@
      *
      * @param algorithm the standard name of the digest algorithm.
      * See the MessageDigest section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      */
     protected MessageDigest(String algorithm) {
@@ -176,22 +178,34 @@
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
+     * @implNote
+     * The JDK Reference Implementation additionally uses the
+     * {@code jdk.security.provider.preferred}
+     * {@link Security#getProperty(String) Security} property to determine
+     * the preferred provider order for the specified algorithm. This
+     * may be different than the order of providers returned by
+     * {@link Security#getProviders() Security.getProviders()}.
+     *
      * @param algorithm the name of the algorithm requested.
      * See the MessageDigest section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
-     * @return a Message Digest object that implements the specified algorithm.
+     * @return a {@code MessageDigest} object that implements the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          MessageDigestSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code MessageDigestSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static MessageDigest getInstance(String algorithm)
     throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         try {
             MessageDigest md;
             Object[] objs = Security.getImpl(algorithm, "MessageDigest",
@@ -232,30 +246,34 @@
      *
      * @param algorithm the name of the algorithm requested.
      * See the MessageDigest section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the name of the provider.
      *
-     * @return a MessageDigest object that implements the specified algorithm.
+     * @return a {@code MessageDigest} object that implements the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if a MessageDigestSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code MessageDigestSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static MessageDigest getInstance(String algorithm, String provider)
         throws NoSuchAlgorithmException, NoSuchProviderException
     {
-        if (provider == null || provider.length() == 0)
+        Objects.requireNonNull(algorithm, "null algorithm name");
+        if (provider == null || provider.isEmpty())
             throw new IllegalArgumentException("missing provider");
         // Android-added: Check for Bouncy Castle deprecation
         Providers.checkBouncyCastleDeprecation(provider, "MessageDigest", algorithm);
@@ -283,19 +301,23 @@
      *
      * @param algorithm the name of the algorithm requested.
      * See the MessageDigest section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the provider.
      *
-     * @return a MessageDigest object that implements the specified algorithm.
+     * @return a {@code MessageDigest} object that implements the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if a MessageDigestSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws NoSuchAlgorithmException if a {@code MessageDigestSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -305,6 +327,7 @@
                                             Provider provider)
         throws NoSuchAlgorithmException
     {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (provider == null)
             throw new IllegalArgumentException("missing provider");
         // Android-added: Check for Bouncy Castle deprecation
@@ -448,6 +471,10 @@
         return digest();
     }
 
+    private String getProviderName() {
+        return (provider == null) ? "(no provider)" : provider.getName();
+    }
+
     /**
      * Returns a string representation of this message digest object.
      */
@@ -456,7 +483,7 @@
         StringBuilder builder = new StringBuilder();
         builder.append(algorithm);
         builder.append(" Message Digest from ");
-        builder.append(provider.getName());
+        builder.append(getProviderName());
         builder.append(", ");
 
         switch (state) {
@@ -473,7 +500,14 @@
     }
 
     /**
-     * Compares two digests for equality. Does a simple byte compare.
+     * Compares two digests for equality. Two digests are equal if they have
+     * the same length and all bytes at corresponding positions are equal.
+     *
+     * @implNote
+     * All bytes in {@code digesta} are examined to determine equality.
+     * The calculation time depends only on the length of {@code digesta}.
+     * It does not depend on the length of {@code digestb} or the contents
+     * of {@code digesta} and {@code digestb}.
      *
      * @param digesta one of the digests to compare.
      *
@@ -486,14 +520,22 @@
         if (digesta == null || digestb == null) {
             return false;
         }
-        if (digesta.length != digestb.length) {
-            return false;
+
+        int lenA = digesta.length;
+        int lenB = digestb.length;
+
+        if (lenB == 0) {
+            return lenA == 0;
         }
 
         int result = 0;
+        result |= lenA - lenB;
+
         // time-constant comparison
-        for (int i = 0; i < digesta.length; i++) {
-            result |= digesta[i] ^ digestb[i];
+        for (int i = 0; i < lenA; i++) {
+            // If i >= lenB, indexB is 0; otherwise, i.
+            int indexB = ((i - lenB) >>> 31) * i;
+            result |= digesta[i] ^ digestb[indexB];
         }
         return result == 0;
     }
@@ -509,10 +551,10 @@
     /**
      * Returns a string that identifies the algorithm, independent of
      * implementation details. The name should be a standard
-     * Java Security name (such as "SHA", "MD5", and so on).
+     * Java Security name (such as "SHA-256").
      * See the MessageDigest section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#messagedigest-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @return the name of the algorithm
@@ -630,6 +672,19 @@
             digestSpi.engineUpdate(input);
         }
 
+        // BEGIN Android-removed: SecretKey updates are not yet supported.
+        /*
+        public void engineUpdate(SecretKey key) throws InvalidKeyException {
+            if (digestSpi instanceof MessageDigestSpi2) {
+                ((MessageDigestSpi2)digestSpi).engineUpdate(key);
+            } else {
+                throw new UnsupportedOperationException
+                ("Digest does not support update of SecretKey object");
+            }
+        }
+        */
+        // END Android-removed: SecretKey updates are not yet supported.
+
         protected byte[] engineDigest() {
             return digestSpi.engineDigest();
         }
diff --git a/ojluni/src/main/java/java/security/MessageDigestSpi.java b/ojluni/src/main/java/java/security/MessageDigestSpi.java
index 0d5ace1..699e8c2 100644
--- a/ojluni/src/main/java/java/security/MessageDigestSpi.java
+++ b/ojluni/src/main/java/java/security/MessageDigestSpi.java
@@ -43,6 +43,7 @@
  * <p> Implementations are free to implement the Cloneable interface.
  *
  * @author Benjamin Renaud
+ * @since 1.2
  *
  *
  * @see MessageDigest
diff --git a/ojluni/src/main/java/java/security/NoSuchAlgorithmException.java b/ojluni/src/main/java/java/security/NoSuchAlgorithmException.java
index 951e44e..24455d3 100644
--- a/ojluni/src/main/java/java/security/NoSuchAlgorithmException.java
+++ b/ojluni/src/main/java/java/security/NoSuchAlgorithmException.java
@@ -30,6 +30,7 @@
  * requested but is not available in the environment.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public class NoSuchAlgorithmException extends GeneralSecurityException {
diff --git a/ojluni/src/main/java/java/security/NoSuchProviderException.java b/ojluni/src/main/java/java/security/NoSuchProviderException.java
index 9874adb..e2f9265 100644
--- a/ojluni/src/main/java/java/security/NoSuchProviderException.java
+++ b/ojluni/src/main/java/java/security/NoSuchProviderException.java
@@ -30,6 +30,7 @@
  * requested but is not available in the environment.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public class NoSuchProviderException extends GeneralSecurityException {
diff --git a/ojluni/src/main/java/java/security/PKCS12Attribute.java b/ojluni/src/main/java/java/security/PKCS12Attribute.java
index e389862..4a8ebfb 100644
--- a/ojluni/src/main/java/java/security/PKCS12Attribute.java
+++ b/ojluni/src/main/java/java/security/PKCS12Attribute.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
         Pattern.compile("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2})+$");
     private String name;
     private String value;
-    private byte[] encoded;
+    private final byte[] encoded;
     private int hashValue = -1;
 
     /**
@@ -85,7 +85,8 @@
         // Validate value
         int length = value.length();
         String[] values;
-        if (value.charAt(0) == '[' && value.charAt(length - 1) == ']') {
+        if (length > 1 &&
+                value.charAt(0) == '[' && value.charAt(length - 1) == ']') {
             values = value.substring(1, length - 1).split(", ");
         } else {
             values = new String[]{ value };
@@ -198,7 +199,7 @@
         if (!(obj instanceof PKCS12Attribute)) {
             return false;
         }
-        return Arrays.equals(encoded, ((PKCS12Attribute) obj).getEncoded());
+        return Arrays.equals(encoded, ((PKCS12Attribute) obj).encoded);
     }
 
     /**
@@ -209,10 +210,11 @@
      */
     @Override
     public int hashCode() {
-        if (hashValue == -1) {
-            Arrays.hashCode(encoded);
+        int h = hashValue;
+        if (h == -1) {
+            hashValue = h = Arrays.hashCode(encoded);
         }
-        return hashValue;
+        return h;
     }
 
     /**
@@ -252,6 +254,9 @@
     private void parse(byte[] encoded) throws IOException {
         DerInputStream attributeValue = new DerInputStream(encoded);
         DerValue[] attrSeq = attributeValue.getSequence(2);
+        if (attrSeq.length != 2) {
+            throw new IOException("Invalid length for PKCS12Attribute");
+        }
         ObjectIdentifier type = attrSeq[0].getOID();
         DerInputStream attrContent =
             new DerInputStream(attrSeq[1].toByteArray());
diff --git a/ojluni/src/main/java/java/security/Principal.java b/ojluni/src/main/java/java/security/Principal.java
index a538e70..40ee260 100644
--- a/ojluni/src/main/java/java/security/Principal.java
+++ b/ojluni/src/main/java/java/security/Principal.java
@@ -35,6 +35,7 @@
  * @see java.security.cert.X509Certificate
  *
  * @author Li Gong
+ * @since 1.1
  */
 public interface Principal {
 
@@ -74,7 +75,8 @@
     /**
      * Returns true if the specified subject is implied by this principal.
      *
-     * <p>The default implementation of this method returns true if
+     * @implSpec
+     * The default implementation of this method returns true if
      * {@code subject} is non-null and contains at least one principal that
      * is equal to this principal.
      *
diff --git a/ojluni/src/main/java/java/security/PrivateKey.java b/ojluni/src/main/java/java/security/PrivateKey.java
index 7d8a7ea..0bc933b 100644
--- a/ojluni/src/main/java/java/security/PrivateKey.java
+++ b/ojluni/src/main/java/java/security/PrivateKey.java
@@ -54,6 +54,7 @@
  *
  * @author Benjamin Renaud
  * @author Josh Bloch
+ * @since 1.1
  */
 
 public interface PrivateKey extends Key, javax.security.auth.Destroyable {
diff --git a/ojluni/src/main/java/java/security/PrivilegedActionException.java b/ojluni/src/main/java/java/security/PrivilegedActionException.java
index b1eb28f..ddfb89d 100644
--- a/ojluni/src/main/java/java/security/PrivilegedActionException.java
+++ b/ojluni/src/main/java/java/security/PrivilegedActionException.java
@@ -47,6 +47,7 @@
  * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
  * method, as well as the aforementioned "legacy method."
  *
+ * @since 1.2
  * @see PrivilegedExceptionAction
  * @see AccessController#doPrivileged(PrivilegedExceptionAction)
  * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext)
diff --git a/ojluni/src/main/java/java/security/ProtectionDomain.java b/ojluni/src/main/java/java/security/ProtectionDomain.java
index 9e117a6..47e9fb1 100644
--- a/ojluni/src/main/java/java/security/ProtectionDomain.java
+++ b/ojluni/src/main/java/java/security/ProtectionDomain.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/security/ProviderException.java b/ojluni/src/main/java/java/security/ProviderException.java
index b372ee7..48c3638 100644
--- a/ojluni/src/main/java/java/security/ProviderException.java
+++ b/ojluni/src/main/java/java/security/ProviderException.java
@@ -32,6 +32,7 @@
  * throw specialized, provider-specific runtime errors.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 public class ProviderException extends RuntimeException {
 
diff --git a/ojluni/src/main/java/java/security/PublicKey.java b/ojluni/src/main/java/java/security/PublicKey.java
index df49807..986f9d0 100644
--- a/ojluni/src/main/java/java/security/PublicKey.java
+++ b/ojluni/src/main/java/java/security/PublicKey.java
@@ -34,6 +34,7 @@
  * See, for example, the DSAPublicKey interface in
  * {@code java.security.interfaces}.
  *
+ * @since 1.1
  * @see Key
  * @see PrivateKey
  * @see Certificate
diff --git a/ojluni/src/main/java/java/security/SecureRandom.java b/ojluni/src/main/java/java/security/SecureRandom.java
index 4da178d..79e3840 100644
--- a/ojluni/src/main/java/java/security/SecureRandom.java
+++ b/ojluni/src/main/java/java/security/SecureRandom.java
@@ -151,7 +151,7 @@
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
      * <p> See the SecureRandom section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
@@ -189,7 +189,7 @@
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
      * <p> See the SecureRandom section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
@@ -278,7 +278,7 @@
      *
      * @param algorithm the name of the RNG algorithm.
      * See the SecureRandom section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
@@ -321,7 +321,7 @@
      *
      * @param algorithm the name of the RNG algorithm.
      * See the SecureRandom section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
@@ -369,7 +369,7 @@
      *
      * @param algorithm the name of the RNG algorithm.
      * See the SecureRandom section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecureRandom">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
diff --git a/ojluni/src/main/java/java/security/Security.java b/ojluni/src/main/java/java/security/Security.java
index ab1cc1d..bb853a6 100644
--- a/ojluni/src/main/java/java/security/Security.java
+++ b/ojluni/src/main/java/java/security/Security.java
@@ -207,7 +207,7 @@
     /**
      * Gets a specified property for an algorithm. The algorithm name
      * should be a standard name. See the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -443,7 +443,7 @@
      * </ul>
      *
      * <p> See the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard cryptographic service names, standard
      * algorithm names and standard attribute names.
diff --git a/ojluni/src/main/java/java/security/SecurityPermission.java b/ojluni/src/main/java/java/security/SecurityPermission.java
index f02755c..a4eefcc 100644
--- a/ojluni/src/main/java/java/security/SecurityPermission.java
+++ b/ojluni/src/main/java/java/security/SecurityPermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/security/Signature.java b/ojluni/src/main/java/java/security/Signature.java
index a09409f..bbe9640 100644
--- a/ojluni/src/main/java/java/security/Signature.java
+++ b/ojluni/src/main/java/java/security/Signature.java
@@ -238,7 +238,7 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
  * Signature section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -298,7 +298,7 @@
      *
      * @param algorithm the standard string name of the algorithm.
      * See the Signature section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      */
@@ -338,7 +338,7 @@
      *
      * @param algorithm the standard name of the algorithm requested.
      * See the Signature section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -464,7 +464,7 @@
      *
      * @param algorithm the name of the algorithm requested.
      * See the Signature section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -516,7 +516,7 @@
      *
      * @param algorithm the name of the algorithm requested.
      * See the Signature section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Signature">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/java/security/SignatureException.java b/ojluni/src/main/java/java/security/SignatureException.java
index 2e1fa59..7788e12 100644
--- a/ojluni/src/main/java/java/security/SignatureException.java
+++ b/ojluni/src/main/java/java/security/SignatureException.java
@@ -29,6 +29,7 @@
  * This is the generic Signature exception.
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 
 public class SignatureException extends GeneralSecurityException {
diff --git a/ojluni/src/main/java/java/security/SignedObject.java b/ojluni/src/main/java/java/security/SignedObject.java
index 9ac864e..e14c0fa 100644
--- a/ojluni/src/main/java/java/security/SignedObject.java
+++ b/ojluni/src/main/java/java/security/SignedObject.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,13 +81,12 @@
  * verification in an attempt to bypass a security check.
  *
  * <p> The signature algorithm can be, among others, the NIST standard
- * DSA, using DSA and SHA-1.  The algorithm is specified using the
+ * DSA, using DSA and SHA-256.  The algorithm is specified using the
  * same convention as that for signatures. The DSA algorithm using the
- * SHA-1 message digest algorithm can be specified, for example, as
- * "SHA/DSA" or "SHA-1/DSA" (they are equivalent).  In the case of
- * RSA, there are multiple choices for the message digest algorithm,
- * so the signing algorithm could be specified as, for example,
- * "MD2/RSA", "MD5/RSA" or "SHA-1/RSA".  The algorithm name must be
+ * SHA-256 message digest algorithm can be specified, for example, as
+ * "SHA256withDSA".  In the case of
+ * RSA the signing algorithm could be specified as, for example,
+ * "SHA256withRSA".  The algorithm name must be
  * specified, as there is no default.
  *
  * <p> The name of the Cryptography Package Provider is designated
@@ -114,6 +113,7 @@
  * @see Signature
  *
  * @author Li Gong
+ * @since 1.2
  */
 
 public final class SignedObject implements Serializable {
diff --git a/ojluni/src/main/java/java/security/Signer.java b/ojluni/src/main/java/java/security/Signer.java
index 077538d..56d3780 100644
--- a/ojluni/src/main/java/java/security/Signer.java
+++ b/ojluni/src/main/java/java/security/Signer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,13 +38,15 @@
  * @see Identity
  *
  * @author Benjamin Renaud
+ * @since 1.1
  *
- * @deprecated This class is no longer used. Its functionality has been
- * replaced by {@code java.security.KeyStore}, the
- * {@code java.security.cert} package, and
- * {@code java.security.Principal}.
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by
+ *     {@code java.security.KeyStore}, the {@code java.security.cert} package,
+ *     and {@code java.security.Principal}.
  */
-@Deprecated
+@Deprecated(since="1.2", forRemoval=true)
+@SuppressWarnings("removal")
 public abstract class Signer extends Identity {
 
     private static final long serialVersionUID = -1763464102261361480L;
diff --git a/ojluni/src/main/java/java/security/Timestamp.java b/ojluni/src/main/java/java/security/Timestamp.java
index f66d288..668a611 100644
--- a/ojluni/src/main/java/java/security/Timestamp.java
+++ b/ojluni/src/main/java/java/security/Timestamp.java
@@ -141,7 +141,7 @@
      *         its signer's certificate.
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("(");
         sb.append("timestamp: " + timestamp);
         List<? extends Certificate> certs = signerCertPath.getCertificates();
diff --git a/ojluni/src/main/java/java/security/UnresolvedPermission.java b/ojluni/src/main/java/java/security/UnresolvedPermission.java
index 6f3bf4a..7e535da 100644
--- a/ojluni/src/main/java/java/security/UnresolvedPermission.java
+++ b/ojluni/src/main/java/java/security/UnresolvedPermission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/security/UnresolvedPermissionCollection.java b/ojluni/src/main/java/java/security/UnresolvedPermissionCollection.java
index 7633648..bd4fb75 100644
--- a/ojluni/src/main/java/java/security/UnresolvedPermissionCollection.java
+++ b/ojluni/src/main/java/java/security/UnresolvedPermissionCollection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,13 @@
 
 package java.security;
 
-import java.util.*;
-import java.io.ObjectStreamField;
-import java.io.ObjectOutputStream;
-import java.io.ObjectInputStream;
 import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * A UnresolvedPermissionCollection stores a collection
@@ -41,6 +43,7 @@
  *
  *
  * @author Roland Schemers
+ * @since 1.2
  *
  * @serial include
  */
@@ -54,14 +57,14 @@
      * of the same type.
      * Not serialized; see serialization section at end of class.
      */
-    private transient Map<String, List<UnresolvedPermission>> perms;
+    private transient ConcurrentHashMap<String, List<UnresolvedPermission>> perms;
 
     /**
      * Create an empty UnresolvedPermissionCollection object.
      *
      */
     public UnresolvedPermissionCollection() {
-        perms = new HashMap<String, List<UnresolvedPermission>>(11);
+        perms = new ConcurrentHashMap<>(11);
     }
 
     /**
@@ -70,25 +73,32 @@
      *
      * @param permission the Permission object to add.
      */
-
-    public void add(Permission permission)
-    {
+    @Override
+    public void add(Permission permission) {
         if (! (permission instanceof UnresolvedPermission))
             throw new IllegalArgumentException("invalid permission: "+
                                                permission);
         UnresolvedPermission up = (UnresolvedPermission) permission;
 
-        List<UnresolvedPermission> v;
-        synchronized (this) {
-            v = perms.get(up.getName());
-            if (v == null) {
-                v = new ArrayList<UnresolvedPermission>();
-                perms.put(up.getName(), v);
+        // Add permission to map. NOTE: cannot use lambda for
+        // remappingFunction parameter until JDK-8076596 is fixed.
+        perms.compute(up.getName(),
+            new java.util.function.BiFunction<>() {
+                @Override
+                public List<UnresolvedPermission> apply(String key,
+                                        List<UnresolvedPermission> oldValue) {
+                    if (oldValue == null) {
+                        List<UnresolvedPermission> v =
+                            new CopyOnWriteArrayList<>();
+                        v.add(up);
+                        return v;
+                    } else {
+                        oldValue.add(up);
+                        return oldValue;
+                    }
+                }
             }
-        }
-        synchronized (v) {
-            v.add(up);
-        }
+        );
     }
 
     /**
@@ -96,17 +106,15 @@
      * and return the List containing them.
      */
     List<UnresolvedPermission> getUnresolvedPermissions(Permission p) {
-        synchronized (this) {
-            return perms.get(p.getClass().getName());
-        }
+        return perms.get(p.getClass().getName());
     }
 
     /**
      * always returns false for unresolved permissions
      *
      */
-    public boolean implies(Permission permission)
-    {
+    @Override
+    public boolean implies(Permission permission) {
         return false;
     }
 
@@ -116,18 +124,14 @@
      *
      * @return an enumeration of all the UnresolvedPermission objects.
      */
-
+    @Override
     public Enumeration<Permission> elements() {
         List<Permission> results =
             new ArrayList<>(); // where results are stored
 
         // Get iterator of Map values (which are lists of permissions)
-        synchronized (this) {
-            for (List<UnresolvedPermission> l : perms.values()) {
-                synchronized (l) {
-                    results.addAll(l);
-                }
-            }
+        for (List<UnresolvedPermission> l : perms.values()) {
+            results.addAll(l);
         }
 
         return Collections.enumeration(results);
@@ -164,19 +168,14 @@
             new Hashtable<>(perms.size()*2);
 
         // Convert each entry (List) into a Vector
-        synchronized (this) {
-            Set<Map.Entry<String, List<UnresolvedPermission>>> set = perms.entrySet();
-            for (Map.Entry<String, List<UnresolvedPermission>> e : set) {
-                // Convert list into Vector
-                List<UnresolvedPermission> list = e.getValue();
-                Vector<UnresolvedPermission> vec = new Vector<>(list.size());
-                synchronized (list) {
-                    vec.addAll(list);
-                }
+        Set<Map.Entry<String, List<UnresolvedPermission>>> set = perms.entrySet();
+        for (Map.Entry<String, List<UnresolvedPermission>> e : set) {
+            // Convert list into Vector
+            List<UnresolvedPermission> list = e.getValue();
+            Vector<UnresolvedPermission> vec = new Vector<>(list);
 
-                // Add to Hashtable being serialized
-                permissions.put(e.getKey(), vec);
-            }
+            // Add to Hashtable being serialized
+            permissions.put(e.getKey(), vec);
         }
 
         // Write out serializable fields
@@ -203,15 +202,14 @@
         Hashtable<String, Vector<UnresolvedPermission>> permissions =
                 (Hashtable<String, Vector<UnresolvedPermission>>)
                 gfields.get("permissions", null);
-        perms = new HashMap<String, List<UnresolvedPermission>>(permissions.size()*2);
+        perms = new ConcurrentHashMap<>(permissions.size()*2);
 
         // Convert each entry (Vector) into a List
         Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
         for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
             // Convert Vector into ArrayList
             Vector<UnresolvedPermission> vec = e.getValue();
-            List<UnresolvedPermission> list = new ArrayList<>(vec.size());
-            list.addAll(vec);
+            List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec);
 
             // Add to Hashtable being serialized
             perms.put(e.getKey(), list);
diff --git a/ojluni/src/main/java/java/security/acl/Acl.java b/ojluni/src/main/java/java/security/acl/Acl.java
index b9cf004..9384078 100644
--- a/ojluni/src/main/java/java/security/acl/Acl.java
+++ b/ojluni/src/main/java/java/security/acl/Acl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,11 +68,7 @@
  *
  * The {@code  java.security.acl } package provides the
  * interfaces to the ACL and related data structures (ACL entries,
- * groups, permissions, etc.), and the {@code  sun.security.acl }
- * classes provide a default implementation of the interfaces. For
- * example, {@code  java.security.acl.Acl } provides the
- * interface to an ACL and the {@code  sun.security.acl.AclImpl }
- * class provides the default implementation of the interface.<p>
+ * groups, permissions, etc.).<p>
  *
  * The {@code  java.security.acl.Acl } interface extends the
  * {@code  java.security.acl.Owner } interface. The Owner
@@ -86,8 +82,15 @@
  * @see java.security.acl.Acl#getPermissions
  *
  * @author Satish Dharmaraj
+ * @since 1.1
+ *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
 
+@Deprecated(since="9", forRemoval=true)
+@SuppressWarnings("removal")
 public interface Acl extends Owner {
 
     /**
diff --git a/ojluni/src/main/java/java/security/acl/AclEntry.java b/ojluni/src/main/java/java/security/acl/AclEntry.java
index cd9675f..1d64eb0 100644
--- a/ojluni/src/main/java/java/security/acl/AclEntry.java
+++ b/ojluni/src/main/java/java/security/acl/AclEntry.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,14 @@
  * @see java.security.acl.Acl
  *
  * @author      Satish Dharmaraj
+ * @since 1.1
+ *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
+@Deprecated(since="9", forRemoval=true)
+@SuppressWarnings("removal")
 public interface AclEntry extends Cloneable {
 
     /**
diff --git a/ojluni/src/main/java/java/security/acl/AclNotFoundException.java b/ojluni/src/main/java/java/security/acl/AclNotFoundException.java
index 6f08e17..882bfdf 100644
--- a/ojluni/src/main/java/java/security/acl/AclNotFoundException.java
+++ b/ojluni/src/main/java/java/security/acl/AclNotFoundException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,13 @@
  * non-existent ACL (Access Control List).
  *
  * @author      Satish Dharmaraj
+ * @since 1.1
+ *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
+@Deprecated(since="9", forRemoval=true)
 public class AclNotFoundException extends Exception {
 
     private static final long serialVersionUID = 5684295034092681791L;
diff --git a/ojluni/src/main/java/java/security/acl/Group.java b/ojluni/src/main/java/java/security/acl/Group.java
index ebd9c44..534f6cb 100644
--- a/ojluni/src/main/java/java/security/acl/Group.java
+++ b/ojluni/src/main/java/java/security/acl/Group.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,13 @@
  * Principal or Group.
  *
  * @author      Satish Dharmaraj
+ * @since 1.1
+ *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
+@Deprecated(since="9", forRemoval=true)
 public interface Group extends Principal {
 
     /**
diff --git a/ojluni/src/main/java/java/security/acl/LastOwnerException.java b/ojluni/src/main/java/java/security/acl/LastOwnerException.java
index 196c8f1..3582e0a 100644
--- a/ojluni/src/main/java/java/security/acl/LastOwnerException.java
+++ b/ojluni/src/main/java/java/security/acl/LastOwnerException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,13 @@
  * @see java.security.acl.Owner#deleteOwner
  *
  * @author Satish Dharmaraj
+ * @since 1.1
+ *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
+@Deprecated(since="9", forRemoval=true)
 public class LastOwnerException extends Exception {
 
     private static final long serialVersionUID = -5141997548211140359L;
diff --git a/ojluni/src/main/java/java/security/acl/NotOwnerException.java b/ojluni/src/main/java/java/security/acl/NotOwnerException.java
index 0a4b04b..fc5b155 100644
--- a/ojluni/src/main/java/java/security/acl/NotOwnerException.java
+++ b/ojluni/src/main/java/java/security/acl/NotOwnerException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,13 @@
  * the object, but the Principal attempting the modification is not an owner.
  *
  * @author      Satish Dharmaraj
+ * @since 1.1
+ *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
+@Deprecated(since="9", forRemoval=true)
 public class NotOwnerException extends Exception {
 
     private static final long serialVersionUID = -5555597911163362399L;
diff --git a/ojluni/src/main/java/java/security/acl/Owner.java b/ojluni/src/main/java/java/security/acl/Owner.java
index 2f649d4..b7af16d 100644
--- a/ojluni/src/main/java/java/security/acl/Owner.java
+++ b/ojluni/src/main/java/java/security/acl/Owner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,15 @@
  * interface.) The initial owner Principal should be specified as an
  * argument to the constructor of the class implementing this interface.
  *
+ * @since 1.1
  * @see java.security.acl.Acl
  *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
+@Deprecated(since="9", forRemoval=true)
+@SuppressWarnings("removal")
 public interface Owner {
 
     /**
diff --git a/ojluni/src/main/java/java/security/acl/Permission.java b/ojluni/src/main/java/java/security/acl/Permission.java
index 72412de..992e8cf 100644
--- a/ojluni/src/main/java/java/security/acl/Permission.java
+++ b/ojluni/src/main/java/java/security/acl/Permission.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,11 @@
 // See comments in java.lang.SecurityManager for details.
 /**
  * Legacy security code; do not use.
+ *
+ * @deprecated This class is deprecated and subject to removal in a future
+ *     version of Java SE. It has been replaced by {@code java.security.Policy}
+ *     and related classes since 1.2.
  */
+@Deprecated(since="9", forRemoval=true)
 public interface Permission {
 }
diff --git a/ojluni/src/main/java/java/security/cert/CRL.java b/ojluni/src/main/java/java/security/cert/CRL.java
index f8083c7..e149c30 100644
--- a/ojluni/src/main/java/java/security/cert/CRL.java
+++ b/ojluni/src/main/java/java/security/cert/CRL.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,9 +52,9 @@
      * Creates a CRL of the specified type.
      *
      * @param type the standard name of the CRL type.
-     * See Appendix A in the <a href=
-     * "../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
-     * Java Cryptography Architecture API Specification &amp; Reference </a>
+     * See the <a href=
+     * "{@docRoot}/../specs/security/standard-names.html">
+     * Java Security Standard Algorithm Names</a> document
      * for information about standard CRL types.
      */
     protected CRL(String type) {
diff --git a/ojluni/src/main/java/java/security/cert/CRLException.java b/ojluni/src/main/java/java/security/cert/CRLException.java
index 7a85431..4b648e9 100644
--- a/ojluni/src/main/java/java/security/cert/CRLException.java
+++ b/ojluni/src/main/java/java/security/cert/CRLException.java
@@ -31,6 +31,7 @@
  * CRL (Certificate Revocation List) Exception.
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 public class CRLException extends GeneralSecurityException {
 
diff --git a/ojluni/src/main/java/java/security/cert/CRLReason.java b/ojluni/src/main/java/java/security/cert/CRLReason.java
index ac0b9e9..79d4729 100644
--- a/ojluni/src/main/java/java/security/cert/CRLReason.java
+++ b/ojluni/src/main/java/java/security/cert/CRLReason.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,8 @@
 
 /**
  * The CRLReason enumeration specifies the reason that a certificate
- * is revoked, as defined in <a href="http://www.ietf.org/rfc/rfc3280.txt">
- * RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL
+ * is revoked, as defined in <a href="http://tools.ietf.org/html/rfc5280">
+ * RFC 5280: Internet X.509 Public Key Infrastructure Certificate and CRL
  * Profile</a>.
  *
  * @author Sean Mullan
diff --git a/ojluni/src/main/java/java/security/cert/CertPath.java b/ojluni/src/main/java/java/security/cert/CertPath.java
index fa88c39..295c5aa 100644
--- a/ojluni/src/main/java/java/security/cert/CertPath.java
+++ b/ojluni/src/main/java/java/security/cert/CertPath.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,9 +91,9 @@
  * <li>{@code PkiPath}</li>
  * </ul>
  * These encodings are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings">
+ * "{@docRoot}/../specs/security/standard-names.html#certpath-encodings">
  * CertPath Encodings section</a> of the
- * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ * Java Security Standard Algorithm Names Specification.
  * Consult the release documentation for your implementation to see if any
  * other encodings are supported.
  * <p>
@@ -220,7 +220,7 @@
      * @return a string representation of this certification path
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         Iterator<? extends Certificate> stringIterator =
                                         getCertificates().iterator();
 
diff --git a/ojluni/src/main/java/java/security/cert/CertPathBuilder.java b/ojluni/src/main/java/java/security/cert/CertPathBuilder.java
index 2d54292..46d5c77 100644
--- a/ojluni/src/main/java/java/security/cert/CertPathBuilder.java
+++ b/ojluni/src/main/java/java/security/cert/CertPathBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
 import java.security.PrivilegedAction;
 import java.security.Provider;
 import java.security.Security;
-import sun.security.util.Debug;
+import java.util.Objects;
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
@@ -66,26 +66,15 @@
  * CertPathBuilderResult cpbr = cpb.build(params);
  * </pre>
  *
- * <p> Android provides the following {@code CertPathBuilder} algorithms:
- * <table>
- *   <thead>
- *     <tr>
- *       <th>Algorithm</th>
- *       <th>Supported API Levels</th>
- *     </tr>
- *   </thead>
- *   <tbody>
- *     <tr>
- *       <td>PKIX</td>
- *       <td>1+</td>
- *     </tr>
- *   </tbody>
- * </table>
- *
+ * <p>Every implementation of the Java platform is required to support the
+ * following standard {@code CertPathBuilder} algorithm:
+ * <ul>
+ * <li>{@code PKIX}</li>
+ * </ul>
  * This algorithm is described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder">
+ * "{@docRoot}/../specs/security/standard-names.html#certpathbuilder-algorithms">
  * CertPathBuilder section</a> of the
- * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ * Java Security Standard Algorithm Names Specification.
  * Consult the release documentation for your implementation to see if any
  * other algorithms are supported.
  *
@@ -153,23 +142,34 @@
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
+     * @implNote
+     * The JDK Reference Implementation additionally uses the
+     * {@code jdk.security.provider.preferred}
+     * {@link Security#getProperty(String) Security} property to determine
+     * the preferred provider order for the specified algorithm. This
+     * may be different than the order of providers returned by
+     * {@link Security#getProviders() Security.getProviders()}.
+     *
      * @param algorithm the name of the requested {@code CertPathBuilder}
      *  algorithm.  See the CertPathBuilder section in the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     *  "{@docRoot}/../specs/security/standard-names.html#certpathbuilder-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @return a {@code CertPathBuilder} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @throws NoSuchAlgorithmException if no Provider supports a
-     *          CertPathBuilderSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code CertPathBuilderSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathBuilder getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathBuilder",
             CertPathBuilderSpi.class, algorithm);
         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
@@ -190,29 +190,32 @@
      *
      * @param algorithm the name of the requested {@code CertPathBuilder}
      *  algorithm.  See the CertPathBuilder section in the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     *  "{@docRoot}/../specs/security/standard-names.html#certpathbuilder-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the name of the provider.
      *
      * @return a {@code CertPathBuilder} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @throws NoSuchAlgorithmException if a CertPathBuilderSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null} or empty
+     *
+     * @throws NoSuchAlgorithmException if a {@code CertPathBuilderSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null or empty.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathBuilder getInstance(String algorithm, String provider)
            throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathBuilder",
             CertPathBuilderSpi.class, algorithm, provider);
         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
@@ -230,26 +233,29 @@
      *
      * @param algorithm the name of the requested {@code CertPathBuilder}
      *  algorithm.  See the CertPathBuilder section in the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathBuilder">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     *  "{@docRoot}/../specs/security/standard-names.html#certpathbuilder-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the provider.
      *
      * @return a {@code CertPathBuilder} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if a CertPathBuilderSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null}
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null.
+     * @throws NoSuchAlgorithmException if a {@code CertPathBuilderSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathBuilder getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathBuilder",
             CertPathBuilderSpi.class, algorithm, provider);
         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
@@ -310,9 +316,9 @@
      * by the {@code certpathbuilder.type} security property, or the string
      * {@literal "PKIX"} if no such property exists.
      */
-    public final static String getDefaultType() {
+    public static final String getDefaultType() {
         String cpbtype =
-            AccessController.doPrivileged(new PrivilegedAction<String>() {
+            AccessController.doPrivileged(new PrivilegedAction<>() {
                 public String run() {
                     return Security.getProperty(CPB_TYPE);
                 }
diff --git a/ojluni/src/main/java/java/security/cert/CertPathHelperImpl.java b/ojluni/src/main/java/java/security/cert/CertPathHelperImpl.java
index fd9e111..24507e2 100644
--- a/ojluni/src/main/java/java/security/cert/CertPathHelperImpl.java
+++ b/ojluni/src/main/java/java/security/cert/CertPathHelperImpl.java
@@ -49,7 +49,7 @@
      * the methods in this class. This ensures that the helper is initialized
      * prior to a tunneled call from the Sun provider.
      */
-    synchronized static void initialize() {
+    static synchronized void initialize() {
         if (CertPathHelper.instance == null) {
             CertPathHelper.instance = new CertPathHelperImpl();
         }
diff --git a/ojluni/src/main/java/java/security/cert/CertPathValidator.java b/ojluni/src/main/java/java/security/cert/CertPathValidator.java
index bcb3488..57efedd 100644
--- a/ojluni/src/main/java/java/security/cert/CertPathValidator.java
+++ b/ojluni/src/main/java/java/security/cert/CertPathValidator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
 import java.security.PrivilegedAction;
 import java.security.Provider;
 import java.security.Security;
-import sun.security.util.Debug;
+import java.util.Objects;
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
@@ -68,26 +68,17 @@
  * CertPathValidatorResult cpvr = cpv.validate(path, params);
  * </pre>
  *
- * <p> Android provides the following {@code CertPathValidator} algorithms:
- * <table>
- *   <thead>
- *     <tr>
- *       <th>Algorithm</th>
- *       <th>Supported API Levels</th>
- *     </tr>
- *   </thead>
- *   <tbody>
- *     <tr>
- *       <td>PKIX</td>
- *       <td>1+</td>
- *     </tr>
- *   </tbody>
- * </table>
- *
+ * <p>Every implementation of the Java platform is required to support the
+ * following standard {@code CertPathValidator} algorithm:
+ * <ul>
+ * <li>{@code PKIX}</li>
+ * </ul>
  * This algorithm is described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator">
+ * "{@docRoot}/../specs/security/standard-names.html#certpathvalidator-algorithms">
  * CertPathValidator section</a> of the
- * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ * Java Security Standard Algorithm Names Specification.
+ * Consult the release documentation for your implementation to see if any
+ * other algorithms are supported.
  *
  * <p>
  * <b>Concurrent Access</b>
@@ -152,23 +143,34 @@
      * <p> Note that the list of registered providers may be retrieved via
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
+     * @implNote
+     * The JDK Reference Implementation additionally uses the
+     * {@code jdk.security.provider.preferred}
+     * {@link Security#getProperty(String) Security} property to determine
+     * the preferred provider order for the specified algorithm. This
+     * may be different than the order of providers returned by
+     * {@link Security#getProviders() Security.getProviders()}.
+     *
      * @param algorithm the name of the requested {@code CertPathValidator}
-     *  algorithm. See the CertPathValidator section in the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * algorithm. See the CertPathValidator section in the <a href=
+     * "{@docRoot}/../specs/security/standard-names.html#certpathvalidator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @return a {@code CertPathValidator} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          CertPathValidatorSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code CertPathValidatorSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathValidator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathValidator",
             CertPathValidatorSpi.class, algorithm);
         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
@@ -188,31 +190,34 @@
      * the {@link Security#getProviders() Security.getProviders()} method.
      *
      * @param algorithm the name of the requested {@code CertPathValidator}
-     *  algorithm. See the CertPathValidator section in the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * algorithm. See the CertPathValidator section in the <a href=
+     * "{@docRoot}/../specs/security/standard-names.html#certpathvalidator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the name of the provider.
      *
      * @return a {@code CertPathValidator} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null} or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code CertPathValidatorSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathValidator getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathValidator",
             CertPathValidatorSpi.class, algorithm, provider);
         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
@@ -230,26 +235,29 @@
      *
      * @param algorithm the name of the requested {@code CertPathValidator}
      * algorithm. See the CertPathValidator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathValidator">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#certpathvalidator-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the provider.
      *
      * @return a {@code CertPathValidator} object that implements the
-     *          specified algorithm.
+     *          specified algorithm
      *
-     * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null}
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null.
+     * @throws NoSuchAlgorithmException if a {@code CertPathValidatorSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified Provider object
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathValidator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathValidator",
             CertPathValidatorSpi.class, algorithm, provider);
         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
@@ -320,9 +328,9 @@
      * by the {@code certpathvalidator.type} security property, or the string
      * {@literal "PKIX"} if no such property exists.
      */
-    public final static String getDefaultType() {
+    public static final String getDefaultType() {
         String cpvtype =
-            AccessController.doPrivileged(new PrivilegedAction<String>() {
+            AccessController.doPrivileged(new PrivilegedAction<>() {
                 public String run() {
                     return Security.getProperty(CPV_TYPE);
                 }
diff --git a/ojluni/src/main/java/java/security/cert/CertStore.java b/ojluni/src/main/java/java/security/cert/CertStore.java
index 7cfd0d2..0d7675c 100644
--- a/ojluni/src/main/java/java/security/cert/CertStore.java
+++ b/ojluni/src/main/java/java/security/cert/CertStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 import java.security.Provider;
 import java.security.Security;
 import java.util.Collection;
+import java.util.Objects;
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
@@ -60,26 +61,17 @@
  * and CRLs stored in one or more directories using the LDAP protocol and the
  * schema as defined in the RFC service attribute.
  *
- * <p> Android provides the following <code>CertStore</code> types:
- * <table>
- *   <thead>
- *     <tr>
- *       <th>Algorithm</th>
- *       <th>Supported API Levels</th>
- *     </tr>
- *   </thead>
- *   <tbody>
- *     <tr>
- *       <td>Collection</td>
- *       <td>1+</td>
- *     </tr>
- *   </tbody>
- * </table>
- *
+ * <p> Every implementation of the Java platform is required to support the
+ * following standard {@code CertStore} type:
+ * <ul>
+ * <li>{@code Collection}</li>
+ * </ul>
  * This type is described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore">
+ * "{@docRoot}/../specs/security/standard-names.html#certstore-types">
  * CertStore section</a> of the
- * Java Cryptography Architecture Standard Algorithm Name Documentation.
+ * Java Security Standard Algorithm Names Specification.
+ * Consult the release documentation for your implementation to see if any
+ * other types are supported.
  *
  * <p>
  * <b>Concurrent Access</b>
@@ -210,29 +202,40 @@
      * Note that the specified {@code CertStoreParameters} object is
      * cloned.
      *
+     * @implNote
+     * The JDK Reference Implementation additionally uses the
+     * {@code jdk.security.provider.preferred}
+     * {@link Security#getProperty(String) Security} property to determine
+     * the preferred provider order for the specified algorithm. This
+     * may be different than the order of providers returned by
+     * {@link Security#getProviders() Security.getProviders()}.
+     *
      * @param type the name of the requested {@code CertStore} type.
      * See the CertStore section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#certstore-types">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard types.
      *
      * @param params the initialization parameters (may be {@code null}).
      *
      * @return a {@code CertStore} object that implements the specified
-     *          {@code CertStore} type.
-     *
-     * @throws NoSuchAlgorithmException if no Provider supports a
-     *          CertStoreSpi implementation for the specified type.
+     *          {@code CertStore} type
      *
      * @throws InvalidAlgorithmParameterException if the specified
-     *          initialization parameters are inappropriate for this
-     *          {@code CertStore}.
+     *         initialization parameters are inappropriate for this
+     *         {@code CertStore}
+     *
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code CertStoreSpi} implementation for the specified type
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertStore getInstance(String type, CertStoreParameters params)
             throws InvalidAlgorithmParameterException,
             NoSuchAlgorithmException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertStore",
                 CertStoreSpi.class, type, params);
@@ -244,7 +247,8 @@
     }
 
     private static CertStore handleException(NoSuchAlgorithmException e)
-            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+            throws NoSuchAlgorithmException,
+            InvalidAlgorithmParameterException {
         Throwable cause = e.getCause();
         if (cause instanceof InvalidAlgorithmParameterException) {
             throw (InvalidAlgorithmParameterException)cause;
@@ -272,8 +276,8 @@
      *
      * @param type the requested {@code CertStore} type.
      * See the CertStore section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#certstore-types">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard types.
      *
      * @param params the initialization parameters (may be {@code null}).
@@ -281,21 +285,23 @@
      * @param provider the name of the provider.
      *
      * @return a {@code CertStore} object that implements the
-     *          specified type.
+     *          specified type
      *
-     * @throws NoSuchAlgorithmException if a CertStoreSpi
-     *          implementation for the specified type is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null} or empty
      *
      * @throws InvalidAlgorithmParameterException if the specified
-     *          initialization parameters are inappropriate for this
-     *          {@code CertStore}.
+     *         initialization parameters are inappropriate for this
+     *         {@code CertStore}
+     *
+     * @throws NoSuchAlgorithmException if a {@code CertStoreSpi}
+     *         implementation for the specified type is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null or empty.
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
@@ -303,6 +309,7 @@
             CertStoreParameters params, String provider)
             throws InvalidAlgorithmParameterException,
             NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertStore",
                 CertStoreSpi.class, type, params, provider);
@@ -330,8 +337,8 @@
      *
      * @param type the requested {@code CertStore} type.
      * See the CertStore section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertStore">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#certstore-types">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard types.
      *
      * @param params the initialization parameters (may be {@code null}).
@@ -339,24 +346,27 @@
      * @param provider the provider.
      *
      * @return a {@code CertStore} object that implements the
-     *          specified type.
+     *          specified type
      *
-     * @exception NoSuchAlgorithmException if a CertStoreSpi
-     *          implementation for the specified type is not available
-     *          from the specified Provider object.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         null
      *
      * @throws InvalidAlgorithmParameterException if the specified
-     *          initialization parameters are inappropriate for this
-     *          {@code CertStore}
+     *         initialization parameters are inappropriate for this
+     *         {@code CertStore}
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null.
+     * @throws NoSuchAlgorithmException if a {@code CertStoreSpi}
+     *         implementation for the specified type is not available
+     *         from the specified Provider object
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertStore getInstance(String type, CertStoreParameters params,
             Provider provider) throws NoSuchAlgorithmException,
             InvalidAlgorithmParameterException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertStore",
                 CertStoreSpi.class, type, params, provider);
@@ -416,9 +426,9 @@
      * {@code certstore.type} security property, or the string
      * {@literal "LDAP"} if no such property exists.
      */
-    public final static String getDefaultType() {
+    public static final String getDefaultType() {
         String cstype;
-        cstype = AccessController.doPrivileged(new PrivilegedAction<String>() {
+        cstype = AccessController.doPrivileged(new PrivilegedAction<>() {
             public String run() {
                 return Security.getProperty(CERTSTORE_TYPE);
             }
diff --git a/ojluni/src/main/java/java/security/cert/Certificate.java b/ojluni/src/main/java/java/security/cert/Certificate.java
index 4056416..ad72e63 100644
--- a/ojluni/src/main/java/java/security/cert/Certificate.java
+++ b/ojluni/src/main/java/java/security/cert/Certificate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
  * An identity certificate is a binding of a principal to a public key which
  * is vouched for by another principal.  (A principal represents
  * an entity such as an individual user, a group, or a corporation.)
- *<p>
+ * <p>
  * This class is an abstraction for certificates that have different
  * formats but important common uses.  For example, different types of
  * certificates, such as X.509 and PGP, share general certificate
@@ -57,6 +57,7 @@
  * @see CertificateFactory
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 
 public abstract class Certificate implements java.io.Serializable {
@@ -74,8 +75,8 @@
      *
      * @param type the standard name of the certificate type.
      * See the CertificateFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#certificatefactory-types">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard certificate types.
      */
     protected Certificate(String type) {
@@ -248,9 +249,7 @@
          * Construct the alternate Certificate class with the Certificate
          * type and Certificate encoding bytes.
          *
-         * <p>
-         *
-         * @param type the standard name of the Certificate type. <p>
+         * @param type the standard name of the Certificate type.
          *
          * @param data the Certificate data.
          */
@@ -262,8 +261,6 @@
         /**
          * Resolve the Certificate Object.
          *
-         * <p>
-         *
          * @return the resolved Certificate Object
          *
          * @throws java.io.ObjectStreamException if the Certificate
diff --git a/ojluni/src/main/java/java/security/cert/CertificateEncodingException.java b/ojluni/src/main/java/java/security/cert/CertificateEncodingException.java
index 618ee0a..c30b96c 100644
--- a/ojluni/src/main/java/java/security/cert/CertificateEncodingException.java
+++ b/ojluni/src/main/java/java/security/cert/CertificateEncodingException.java
@@ -30,6 +30,7 @@
  * occurs while attempting to encode a certificate.
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 public class CertificateEncodingException extends CertificateException {
 
diff --git a/ojluni/src/main/java/java/security/cert/CertificateException.java b/ojluni/src/main/java/java/security/cert/CertificateException.java
index f663054..ce73103 100644
--- a/ojluni/src/main/java/java/security/cert/CertificateException.java
+++ b/ojluni/src/main/java/java/security/cert/CertificateException.java
@@ -31,6 +31,7 @@
  * This exception indicates one of a variety of certificate problems.
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  * @see Certificate
  */
 public class CertificateException extends GeneralSecurityException {
diff --git a/ojluni/src/main/java/java/security/cert/CertificateExpiredException.java b/ojluni/src/main/java/java/security/cert/CertificateExpiredException.java
index 9de0c23..635a32f 100644
--- a/ojluni/src/main/java/java/security/cert/CertificateExpiredException.java
+++ b/ojluni/src/main/java/java/security/cert/CertificateExpiredException.java
@@ -32,6 +32,7 @@
  * of the certificate.
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 public class CertificateExpiredException extends CertificateException {
 
diff --git a/ojluni/src/main/java/java/security/cert/CertificateFactory.java b/ojluni/src/main/java/java/security/cert/CertificateFactory.java
index e34fddd..a47b788 100644
--- a/ojluni/src/main/java/java/security/cert/CertificateFactory.java
+++ b/ojluni/src/main/java/java/security/cert/CertificateFactory.java
@@ -127,9 +127,9 @@
  * </table>
  *
  * The type and encodings are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory">
  * CertificateFactory section</a> and the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings">
  * CertPath Encodings section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -188,7 +188,7 @@
      *
      * @param type the name of the requested certificate type.
      * See the CertificateFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard certificate types.
      *
@@ -226,7 +226,7 @@
      *
      * @param type the certificate type.
      * See the CertificateFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard certificate types.
      *
@@ -272,7 +272,7 @@
      *
      * @param type the certificate type.
      * See the CertificateFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertificateFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard certificate types.
      * @param provider the provider.
@@ -370,7 +370,7 @@
      * Returns an iteration of the {@code CertPath} encodings supported
      * by this certificate factory, with the default encoding first. See
      * the CertPath Encodings section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard encoding names and their formats.
      * <p>
@@ -410,7 +410,7 @@
      * the data read from the {@code InputStream} inStream. The data
      * is assumed to be in the specified encoding. See
      * the CertPath Encodings section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathEncodings">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard encoding names and their formats.
      *
diff --git a/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java b/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java
index 691777d..0b1bb33 100644
--- a/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java
+++ b/ojluni/src/main/java/java/security/cert/CertificateFactorySpi.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -183,8 +183,8 @@
      * Returns an iteration of the {@code CertPath} encodings supported
      * by this certificate factory, with the default encoding first. See
      * the CertPath Encodings section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#CertPathEncodings">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#certpath-encodings">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard encoding names.
      * <p>
      * Attempts to modify the returned {@code Iterator} via its
diff --git a/ojluni/src/main/java/java/security/cert/CertificateNotYetValidException.java b/ojluni/src/main/java/java/security/cert/CertificateNotYetValidException.java
index e8722bd..75f3e15 100644
--- a/ojluni/src/main/java/java/security/cert/CertificateNotYetValidException.java
+++ b/ojluni/src/main/java/java/security/cert/CertificateNotYetValidException.java
@@ -32,6 +32,7 @@
  * validity period.
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 public class CertificateNotYetValidException extends CertificateException {
 
diff --git a/ojluni/src/main/java/java/security/cert/CertificateParsingException.java b/ojluni/src/main/java/java/security/cert/CertificateParsingException.java
index 06a7d60..36fa965 100644
--- a/ojluni/src/main/java/java/security/cert/CertificateParsingException.java
+++ b/ojluni/src/main/java/java/security/cert/CertificateParsingException.java
@@ -31,6 +31,7 @@
  * are found in the Certificate.
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 public class CertificateParsingException extends CertificateException {
 
diff --git a/ojluni/src/main/java/java/security/cert/CollectionCertStoreParameters.java b/ojluni/src/main/java/java/security/cert/CollectionCertStoreParameters.java
index 12bd358..e6ca943 100644
--- a/ojluni/src/main/java/java/security/cert/CollectionCertStoreParameters.java
+++ b/ojluni/src/main/java/java/security/cert/CollectionCertStoreParameters.java
@@ -132,7 +132,7 @@
      * @return a formatted string describing the parameters
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("CollectionCertStoreParameters: [\n");
         sb.append("  collection: " + coll + "\n");
         sb.append("]");
diff --git a/ojluni/src/main/java/java/security/cert/LDAPCertStoreParameters.java b/ojluni/src/main/java/java/security/cert/LDAPCertStoreParameters.java
index 96fe9cd..4ff590d 100644
--- a/ojluni/src/main/java/java/security/cert/LDAPCertStoreParameters.java
+++ b/ojluni/src/main/java/java/security/cert/LDAPCertStoreParameters.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,12 @@
  * <p>
  * This class is used to provide necessary configuration parameters (server
  * name and port number) to implementations of the LDAP {@code CertStore}
- * algorithm.
+ * algorithm. However, if you are retrieving certificates or CRLs from
+ * an ldap URI as specified by RFC 5280, use the
+ * {@link java.security.cert.URICertStoreParameters URICertStoreParameters}
+ * instead as the URI may contain additional information such as the
+ * distinguished name that will help the LDAP CertStore find the specific
+ * certificates and CRLs.
  * <p>
  * <b>Concurrent Access</b>
  * <p>
@@ -138,7 +143,7 @@
      * @return a formatted string describing the parameters
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("LDAPCertStoreParameters: [\n");
 
         sb.append("  serverName: " + serverName + "\n");
diff --git a/ojluni/src/main/java/java/security/cert/PKIXBuilderParameters.java b/ojluni/src/main/java/java/security/cert/PKIXBuilderParameters.java
index b33e1f8..51cf21e 100644
--- a/ojluni/src/main/java/java/security/cert/PKIXBuilderParameters.java
+++ b/ojluni/src/main/java/java/security/cert/PKIXBuilderParameters.java
@@ -189,7 +189,7 @@
      * @return a formatted string describing the parameters
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("[\n");
         sb.append(super.toString());
         sb.append("  Maximum Path Length: " + maxPathLength + "\n");
diff --git a/ojluni/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java b/ojluni/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
index 3255a3b..01cedff 100644
--- a/ojluni/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
+++ b/ojluni/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
@@ -107,7 +107,7 @@
      *         {@code PKIXCertPathBuilderResult}
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("PKIXCertPathBuilderResult: [\n");
         sb.append("  Certification Path: " + certPath + "\n");
         sb.append("  Trust Anchor: " + getTrustAnchor().toString() + "\n");
diff --git a/ojluni/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java b/ojluni/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
index b40cd39..3ba1e33 100644
--- a/ojluni/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
+++ b/ojluni/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
@@ -148,7 +148,7 @@
      *         {@code PKIXCertPathValidatorResult}
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("PKIXCertPathValidatorResult: [\n");
         sb.append("  Trust Anchor: " + trustAnchor.toString() + "\n");
         sb.append("  Policy Tree: " + String.valueOf(policyTree) + "\n");
diff --git a/ojluni/src/main/java/java/security/cert/PKIXParameters.java b/ojluni/src/main/java/java/security/cert/PKIXParameters.java
index 4d8a344..4bc453c 100644
--- a/ojluni/src/main/java/java/security/cert/PKIXParameters.java
+++ b/ojluni/src/main/java/java/security/cert/PKIXParameters.java
@@ -120,8 +120,8 @@
         setTrustAnchors(trustAnchors);
 
         this.unmodInitialPolicies = Collections.<String>emptySet();
-        this.certPathCheckers = new ArrayList<PKIXCertPathChecker>();
-        this.certStores = new ArrayList<CertStore>();
+        this.certPathCheckers = new ArrayList<>();
+        this.certStores = new ArrayList<>();
     }
 
     /**
@@ -144,7 +144,7 @@
         if (keystore == null)
             throw new NullPointerException("the keystore parameter must be " +
                 "non-null");
-        Set<TrustAnchor> hashSet = new HashSet<TrustAnchor>();
+        Set<TrustAnchor> hashSet = new HashSet<>();
         Enumeration<String> aliases = keystore.aliases();
         while (aliases.hasMoreElements()) {
             String alias = aliases.nextElement();
@@ -156,8 +156,8 @@
         }
         setTrustAnchors(hashSet);
         this.unmodInitialPolicies = Collections.<String>emptySet();
-        this.certPathCheckers = new ArrayList<PKIXCertPathChecker>();
-        this.certStores = new ArrayList<CertStore>();
+        this.certPathCheckers = new ArrayList<>();
+        this.certStores = new ArrayList<>();
     }
 
     /**
@@ -207,7 +207,7 @@
             }
         }
         this.unmodTrustAnchors = Collections.unmodifiableSet
-                (new HashSet<TrustAnchor>(trustAnchors));
+                (new HashSet<>(trustAnchors));
     }
 
     /**
@@ -256,7 +256,7 @@
                         + "of type java.lang.String");
             }
             this.unmodInitialPolicies =
-                Collections.unmodifiableSet(new HashSet<String>(initialPolicies));
+                Collections.unmodifiableSet(new HashSet<>(initialPolicies));
         } else
             this.unmodInitialPolicies = Collections.<String>emptySet();
     }
@@ -280,7 +280,7 @@
      */
     public void setCertStores(List<CertStore> stores) {
         if (stores == null) {
-            this.certStores = new ArrayList<CertStore>();
+            this.certStores = new ArrayList<>();
         } else {
             for (Iterator<CertStore> i = stores.iterator(); i.hasNext();) {
                 if (!(i.next() instanceof CertStore)) {
@@ -288,7 +288,7 @@
                         + "of type java.security.cert.CertStore");
                 }
             }
-            this.certStores = new ArrayList<CertStore>(stores);
+            this.certStores = new ArrayList<>(stores);
         }
     }
 
@@ -316,7 +316,7 @@
      */
     public List<CertStore> getCertStores() {
         return Collections.unmodifiableList
-                (new ArrayList<CertStore>(this.certStores));
+                (new ArrayList<>(this.certStores));
     }
 
     /**
@@ -544,14 +544,13 @@
      */
     public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) {
         if (checkers != null) {
-            List<PKIXCertPathChecker> tmpList =
-                        new ArrayList<PKIXCertPathChecker>();
+            List<PKIXCertPathChecker> tmpList = new ArrayList<>();
             for (PKIXCertPathChecker checker : checkers) {
                 tmpList.add((PKIXCertPathChecker)checker.clone());
             }
             this.certPathCheckers = tmpList;
         } else {
-            this.certPathCheckers = new ArrayList<PKIXCertPathChecker>();
+            this.certPathCheckers = new ArrayList<>();
         }
     }
 
@@ -567,7 +566,7 @@
      * @see #setCertPathCheckers
      */
     public List<PKIXCertPathChecker> getCertPathCheckers() {
-        List<PKIXCertPathChecker> tmpList = new ArrayList<PKIXCertPathChecker>();
+        List<PKIXCertPathChecker> tmpList = new ArrayList<>();
         for (PKIXCertPathChecker ck : certPathCheckers) {
             tmpList.add((PKIXCertPathChecker)ck.clone());
         }
@@ -667,11 +666,11 @@
 
             // must clone these because addCertStore, et al. modify them
             if (certStores != null) {
-                copy.certStores = new ArrayList<CertStore>(certStores);
+                copy.certStores = new ArrayList<>(certStores);
             }
             if (certPathCheckers != null) {
                 copy.certPathCheckers =
-                    new ArrayList<PKIXCertPathChecker>(certPathCheckers.size());
+                    new ArrayList<>(certPathCheckers.size());
                 for (PKIXCertPathChecker checker : certPathCheckers) {
                     copy.certPathCheckers.add(
                                     (PKIXCertPathChecker)checker.clone());
@@ -693,7 +692,7 @@
      * @return a formatted string describing the parameters.
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("[\n");
 
         /* start with trusted anchor info */
diff --git a/ojluni/src/main/java/java/security/cert/PKIXReason.java b/ojluni/src/main/java/java/security/cert/PKIXReason.java
index d58ded9..e9c4872 100644
--- a/ojluni/src/main/java/java/security/cert/PKIXReason.java
+++ b/ojluni/src/main/java/java/security/cert/PKIXReason.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 /**
  * The {@code PKIXReason} enumerates the potential PKIX-specific reasons
  * that an X.509 certification path may be invalid according to the PKIX
- * (RFC 3280) standard. These reasons are in addition to those of the
+ * (RFC 5280) standard. These reasons are in addition to those of the
  * {@code CertPathValidatorException.BasicReason} enumeration.
  *
  * @since 1.7
diff --git a/ojluni/src/main/java/java/security/cert/PKIXRevocationChecker.java b/ojluni/src/main/java/java/security/cert/PKIXRevocationChecker.java
index 620291e..6b052af 100644
--- a/ojluni/src/main/java/java/security/cert/PKIXRevocationChecker.java
+++ b/ojluni/src/main/java/java/security/cert/PKIXRevocationChecker.java
@@ -87,13 +87,15 @@
  * necessary locking. Multiple threads each manipulating separate objects
  * need not synchronize.
  *
- * <p>See RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate Status Protocol -
- * OCSP, RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation
- * List (CRL) Profile (Android note: this paragraph was originally in a malformed "see" tag below,
- * moved here for correct construction of the docs).
- *
  * @since 1.8
-
+ *
+ * // Android-changed: Changed invalid `@`see to "See".
+ * See <a href="http://www.ietf.org/rfc/rfc2560.txt"><i>RFC&nbsp;2560: X.509
+ * Internet Public Key Infrastructure Online Certificate Status Protocol -
+ * OCSP</i></a>, <br><a
+ * href="http://www.ietf.org/rfc/rfc5280.txt"><i>RFC&nbsp;5280: Internet X.509
+ * Public Key Infrastructure Certificate and Certificate Revocation List (CRL)
+ * Profile</i></a>
  */
 public abstract class PKIXRevocationChecker extends PKIXCertPathChecker {
     private URI ocspResponder;
@@ -169,7 +171,7 @@
     {
         this.ocspExtensions = (extensions == null)
                               ? Collections.<Extension>emptyList()
-                              : new ArrayList<Extension>(extensions);
+                              : new ArrayList<>(extensions);
     }
 
     /**
@@ -231,7 +233,7 @@
     public void setOptions(Set<Option> options) {
         this.options = (options == null)
                        ? Collections.<Option>emptySet()
-                       : new HashSet<Option>(options);
+                       : new HashSet<>(options);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/security/cert/PolicyQualifierInfo.java b/ojluni/src/main/java/java/security/cert/PolicyQualifierInfo.java
index ec06a88..a21761c 100644
--- a/ojluni/src/main/java/java/security/cert/PolicyQualifierInfo.java
+++ b/ojluni/src/main/java/java/security/cert/PolicyQualifierInfo.java
@@ -27,7 +27,7 @@
 
 import java.io.IOException;
 
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.DerValue;
 
 /**
@@ -161,7 +161,7 @@
         if (pqiString != null)
             return pqiString;
         HexDumpEncoder enc = new HexDumpEncoder();
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("PolicyQualifierInfo: [\n");
         sb.append("  qualifierID: " + mId + "\n");
         sb.append("  qualifier: " +
diff --git a/ojluni/src/main/java/java/security/cert/TrustAnchor.java b/ojluni/src/main/java/java/security/cert/TrustAnchor.java
index c98bf81..8b765a2 100644
--- a/ojluni/src/main/java/java/security/cert/TrustAnchor.java
+++ b/ojluni/src/main/java/java/security/cert/TrustAnchor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,7 +78,7 @@
      * The name constraints are specified as a byte array. This byte array
      * should contain the DER encoded form of the name constraints, as they
      * would appear in the NameConstraints structure defined in
-     * <a href="http://www.ietf.org/rfc/rfc3280">RFC 3280</a>
+     * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>
      * and X.509. The ASN.1 definition of this structure appears below.
      *
      * <pre>{@code
@@ -140,7 +140,7 @@
      * <p>
      * The name constraints are specified as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #TrustAnchor(X509Certificate, byte[])
@@ -179,7 +179,7 @@
      * <p>
      * The name constraints are specified as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #TrustAnchor(X509Certificate, byte[])
@@ -294,7 +294,7 @@
      * <p>
      * The name constraints are returned as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #TrustAnchor(X509Certificate, byte[])
@@ -317,7 +317,7 @@
      * @return a formatted string describing the {@code TrustAnchor}
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("[\n");
         if (pubKey != null) {
             sb.append("  Trusted CA Public Key: " + pubKey.toString() + "\n");
diff --git a/ojluni/src/main/java/java/security/cert/URICertStoreParameters.java b/ojluni/src/main/java/java/security/cert/URICertStoreParameters.java
new file mode 100644
index 0000000..d8b0548
--- /dev/null
+++ b/ojluni/src/main/java/java/security/cert/URICertStoreParameters.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.cert;
+
+import java.net.URI;
+
+/**
+ * Parameters used as input for {@code CertStore} algorithms which use
+ * information contained in a URI to retrieve certificates and CRLs.
+ * <p>
+ * This class is used to provide necessary configuration parameters
+ * through a URI as defined in RFC 5280 to implementations of
+ * {@code CertStore} algorithms.
+ * <p>
+ * <b>Concurrent Access</b>
+ * <p>
+ * Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single
+ * object concurrently should synchronize amongst themselves and
+ * provide the necessary locking. Multiple threads each manipulating
+ * separate objects need not synchronize.
+ *
+ * @since       9
+ * @see         CertStore
+ * @see         java.net.URI
+ */
+public final class URICertStoreParameters implements CertStoreParameters {
+
+    /**
+     * The uri, cannot be null
+     */
+    private final URI uri;
+
+    /*
+     * Hash code for this parameters.
+     */
+    private int myhash = -1;
+
+    /**
+     * Creates an instance of {@code URICertStoreParameters} with the
+     * specified URI.
+     *
+     * @param uri the URI which contains configuration information.
+     * @throws NullPointerException if {@code uri} is null
+     */
+    public URICertStoreParameters(URI uri) {
+        if (uri == null) {
+            throw new NullPointerException();
+        }
+        this.uri = uri;
+    }
+
+    /**
+     * Returns the URI used to construct this
+     * {@code URICertStoreParameters} object.
+     *
+     * @return the URI.
+     */
+    public URI getURI() {
+        return uri;
+    }
+
+    /**
+     * Returns a copy of this object. Changes to the copy will not affect
+     * the original and vice versa.
+     *
+     * @return the copy
+     */
+    @Override
+    public URICertStoreParameters clone() {
+        try {
+            return new URICertStoreParameters(uri);
+        } catch (NullPointerException e) {
+            /* Cannot happen */
+            throw new InternalError(e.toString(), e);
+        }
+    }
+
+    /**
+     * Returns a hash code value for this parameters object.
+     * The hash code is generated using the URI supplied at construction.
+     *
+     * @return a hash code value for this parameters.
+     */
+    @Override
+    public int hashCode() {
+        if (myhash == -1) {
+            myhash = uri.hashCode()*7;
+        }
+        return myhash;
+    }
+
+    /**
+     * Compares the specified object with this parameters object for equality.
+     * Two URICertStoreParameters are considered equal if the URIs used
+     * to construct them are equal.
+     *
+     * @param p the object to test for equality with this parameters.
+     *
+     * @return true if the specified object is equal to this parameters object.
+     */
+    @Override
+    public boolean equals(Object p) {
+        if (p == null || (!(p instanceof URICertStoreParameters))) {
+            return false;
+        }
+
+        if (p == this) {
+            return true;
+        }
+
+        URICertStoreParameters other = (URICertStoreParameters)p;
+        return uri.equals(other.getURI());
+    }
+
+    /**
+     * Returns a formatted string describing the parameters
+     * including the URI used to construct this object.
+     *
+     * @return a formatted string describing the parameters
+     */
+    @Override
+    public String toString() {
+        return "URICertStoreParameters: " + uri.toString();
+    }
+}
diff --git a/ojluni/src/main/java/java/security/cert/X509CRLEntry.java b/ojluni/src/main/java/java/security/cert/X509CRLEntry.java
index 268fa81..4028738 100644
--- a/ojluni/src/main/java/java/security/cert/X509CRLEntry.java
+++ b/ojluni/src/main/java/java/security/cert/X509CRLEntry.java
@@ -62,6 +62,7 @@
  * @see X509Extension
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 
 public abstract class X509CRLEntry implements X509Extension {
diff --git a/ojluni/src/main/java/java/security/cert/X509CRLSelector.java b/ojluni/src/main/java/java/security/cert/X509CRLSelector.java
index face5ff..e589150 100644
--- a/ojluni/src/main/java/java/security/cert/X509CRLSelector.java
+++ b/ojluni/src/main/java/java/security/cert/X509CRLSelector.java
@@ -52,7 +52,7 @@
  * {@link CertStore#getCRLs CertStore.getCRLs} or some similar
  * method.
  * <p>
- * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * Please refer to <a href="http://tools.ietf.org/html/rfc5280">RFC 5280:
  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>
  * for definitions of the X.509 CRL fields and extensions mentioned below.
  * <p>
@@ -124,8 +124,8 @@
             issuerX500Principals = null;
         } else {
             // clone
-            issuerX500Principals = new HashSet<X500Principal>(issuers);
-            issuerNames = new HashSet<Object>();
+            issuerX500Principals = new HashSet<>(issuers);
+            issuerNames = new HashSet<>();
             for (X500Principal p : issuerX500Principals) {
                 issuerNames.add(p.getEncoded());
             }
@@ -288,10 +288,10 @@
      */
     private void addIssuerNameInternal(Object name, X500Principal principal) {
         if (issuerNames == null) {
-            issuerNames = new HashSet<Object>();
+            issuerNames = new HashSet<>();
         }
         if (issuerX500Principals == null) {
-            issuerX500Principals = new HashSet<X500Principal>();
+            issuerX500Principals = new HashSet<>();
         }
         issuerNames.add(name);
         issuerX500Principals.add(principal);
@@ -311,7 +311,7 @@
     private static HashSet<Object> cloneAndCheckIssuerNames(Collection<?> names)
         throws IOException
     {
-        HashSet<Object> namesCopy = new HashSet<Object>();
+        HashSet<Object> namesCopy = new HashSet<>();
         Iterator<?> i = names.iterator();
         while (i.hasNext()) {
             Object nameObject = i.next();
@@ -363,7 +363,7 @@
      */
     private static HashSet<X500Principal> parseIssuerNames(Collection<Object> names)
     throws IOException {
-        HashSet<X500Principal> x500Principals = new HashSet<X500Principal>();
+        HashSet<X500Principal> x500Principals = new HashSet<>();
         for (Iterator<Object> t = names.iterator(); t.hasNext(); ) {
             Object nameObject = t.next();
             if (nameObject instanceof String) {
@@ -566,7 +566,7 @@
      *         {@code X509CRLSelector}.
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("X509CRLSelector: [\n");
         if (issuerNames != null) {
             sb.append("  IssuerNames:\n");
@@ -705,9 +705,9 @@
             X509CRLSelector copy = (X509CRLSelector)super.clone();
             if (issuerNames != null) {
                 copy.issuerNames =
-                        new HashSet<Object>(issuerNames);
+                        new HashSet<>(issuerNames);
                 copy.issuerX500Principals =
-                        new HashSet<X500Principal>(issuerX500Principals);
+                        new HashSet<>(issuerX500Principals);
             }
             return copy;
         } catch (CloneNotSupportedException e) {
diff --git a/ojluni/src/main/java/java/security/cert/X509CertSelector.java b/ojluni/src/main/java/java/security/cert/X509CertSelector.java
index 4a1ff7e..268bd42 100644
--- a/ojluni/src/main/java/java/security/cert/X509CertSelector.java
+++ b/ojluni/src/main/java/java/security/cert/X509CertSelector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
 import java.util.*;
 import javax.security.auth.x500.X500Principal;
 
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
 import sun.security.util.Debug;
 import sun.security.util.DerInputStream;
 import sun.security.util.DerValue;
@@ -65,7 +65,7 @@
  * number. Other unique combinations include the issuer, subject,
  * subjectKeyIdentifier and/or the subjectPublicKey criteria.
  * <p>
- * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * Please refer to <a href="http://tools.ietf.org/html/rfc5280">RFC 5280:
  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a> for
  * definitions of the X.509 certificate extensions mentioned below.
  * <p>
@@ -87,7 +87,7 @@
 
     private static final Debug debug = Debug.getInstance("certpath");
 
-    private final static ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
+    private static final ObjectIdentifier ANY_EXTENDED_KEY_USAGE =
         ObjectIdentifier.newInternal(new int[] {2, 5, 29, 37, 0});
 
     static {
@@ -619,8 +619,8 @@
             keyPurposeOIDSet = null;
         } else {
             this.keyPurposeSet =
-                Collections.unmodifiableSet(new HashSet<String>(keyPurposeSet));
-            keyPurposeOIDSet = new HashSet<ObjectIdentifier>();
+                Collections.unmodifiableSet(new HashSet<>(keyPurposeSet));
+            keyPurposeOIDSet = new HashSet<>();
             for (String s : this.keyPurposeSet) {
                 keyPurposeOIDSet.add(new ObjectIdentifier(s));
             }
@@ -728,7 +728,7 @@
      * The name is provided in string format.
      * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI
      * names use the well-established string formats for those types (subject to
-     * the restrictions included in RFC 3280). IPv4 address names are
+     * the restrictions included in RFC 5280). IPv4 address names are
      * supplied using dotted quad notation. OID address names are represented
      * as a series of nonnegative integers separated by periods. And
      * directory names (distinguished names) are supplied in RFC 2253 format.
@@ -746,7 +746,7 @@
      * String form of some distinguished names.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string form (not {@code null})
      * @throws IOException if a parsing error occurs
      */
@@ -770,7 +770,7 @@
      * <p>
      * The name is provided as a byte array. This byte array should contain
      * the DER encoded name, as it would appear in the GeneralName structure
-     * defined in RFC 3280 and X.509. The encoded byte array should only contain
+     * defined in RFC 5280 and X.509. The encoded byte array should only contain
      * the encoded value of the name, and should not include the tag associated
      * with the name in the GeneralName structure. The ASN.1 definition of this
      * structure appears below.
@@ -806,7 +806,7 @@
      * must contain the specified subjectAlternativeName.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string or byte array form
      * @throws IOException if a parsing error occurs
      */
@@ -815,12 +815,12 @@
         // First, ensure that the name parses
         GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
         if (subjectAlternativeNames == null) {
-            subjectAlternativeNames = new HashSet<List<?>>();
+            subjectAlternativeNames = new HashSet<>();
         }
         if (subjectAlternativeGeneralNames == null) {
-            subjectAlternativeGeneralNames = new HashSet<GeneralNameInterface>();
+            subjectAlternativeGeneralNames = new HashSet<>();
         }
-        List<Object> list = new ArrayList<Object>(2);
+        List<Object> list = new ArrayList<>(2);
         list.add(Integer.valueOf(type));
         list.add(name);
         subjectAlternativeNames.add(list);
@@ -845,7 +845,7 @@
      * @throws IOException if a parsing error occurs
      */
     private static Set<GeneralNameInterface> parseNames(Collection<List<?>> names) throws IOException {
-        Set<GeneralNameInterface> genNames = new HashSet<GeneralNameInterface>();
+        Set<GeneralNameInterface> genNames = new HashSet<>();
         for (List<?> nameList : names) {
             if (nameList.size() != 2) {
                 throw new IOException("name list size not 2");
@@ -995,7 +995,7 @@
      * <p>
      * The name constraints are specified as a byte array. This byte array
      * should contain the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 definition of this structure appears below.
      *
      * <pre>{@code
@@ -1096,10 +1096,10 @@
         } else {
             // Snapshot set and parse it
             Set<String> tempSet = Collections.unmodifiableSet
-                                        (new HashSet<String>(certPolicySet));
+                                        (new HashSet<>(certPolicySet));
             /* Convert to Vector of ObjectIdentifiers */
             Iterator<String> i = tempSet.iterator();
-            Vector<CertificatePolicyId> polIdVector = new Vector<CertificatePolicyId>();
+            Vector<CertificatePolicyId> polIdVector = new Vector<>();
             while (i.hasNext()) {
                 Object o = i.next();
                 if (!(o instanceof String)) {
@@ -1197,7 +1197,7 @@
      * <p>
      * The name is provided in string format. RFC 822, DNS, and URI names
      * use the well-established string formats for those types (subject to
-     * the restrictions included in RFC 3280). IPv4 address names are
+     * the restrictions included in RFC 5280). IPv4 address names are
      * supplied using dotted quad notation. OID address names are represented
      * as a series of nonnegative integers separated by periods. And
      * directory names (distinguished names) are supplied in RFC 2253 format.
@@ -1214,7 +1214,7 @@
      * String form of some distinguished names.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string form
      * @throws IOException if a parsing error occurs
      */
@@ -1234,7 +1234,7 @@
      * <p>
      * The name is provided as a byte array. This byte array should contain
      * the DER encoded name, as it would appear in the GeneralName structure
-     * defined in RFC 3280 and X.509. The ASN.1 definition of this structure
+     * defined in RFC 5280 and X.509. The ASN.1 definition of this structure
      * appears in the documentation for
      * {@link #addSubjectAlternativeName(int type, byte [] name)
      * addSubjectAlternativeName(int type, byte [] name)}.
@@ -1243,7 +1243,7 @@
      * subsequent modifications.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name a byte array containing the name in ASN.1 DER encoded form
      * @throws IOException if a parsing error occurs
      */
@@ -1258,7 +1258,7 @@
      * the specified pathToName.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string or byte array form
      * @throws IOException if an encoding error occurs (incorrect form for DN)
      */
@@ -1267,10 +1267,10 @@
         // First, ensure that the name parses
         GeneralNameInterface tempName = makeGeneralNameInterface(type, name);
         if (pathToGeneralNames == null) {
-            pathToNames = new HashSet<List<?>>();
-            pathToGeneralNames = new HashSet<GeneralNameInterface>();
+            pathToNames = new HashSet<>();
+            pathToGeneralNames = new HashSet<>();
         }
-        List<Object> list = new ArrayList<Object>(2);
+        List<Object> list = new ArrayList<>(2);
         list.add(Integer.valueOf(type));
         list.add(name);
         pathToNames.add(list);
@@ -1671,10 +1671,10 @@
      */
     private static Set<List<?>> cloneAndCheckNames(Collection<List<?>> names) throws IOException {
         // Copy the Lists and Collection
-        Set<List<?>> namesCopy = new HashSet<List<?>>();
+        Set<List<?>> namesCopy = new HashSet<>();
         for (List<?> o : names)
         {
-            namesCopy.add(new ArrayList<Object>(o));
+            namesCopy.add(new ArrayList<>(o));
         }
 
         // Check the contents of the Lists and clone any byte arrays
@@ -1715,7 +1715,7 @@
      * <p>
      * The name constraints are returned as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
@@ -1811,7 +1811,7 @@
      *         {@code CertSelector}
      */
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("X509CertSelector: [\n");
         if (x509Cert != null) {
             sb.append("  Certificate: " + x509Cert.toString() + "\n");
@@ -2238,7 +2238,7 @@
                     + subjectPublicKeyAlgID + ", xcert subjectPublicKeyAlgID = "
                     + algID.getOID());
             }
-            if (!subjectPublicKeyAlgID.equals((Object)algID.getOID())) {
+            if (!subjectPublicKeyAlgID.equals(algID.getOID())) {
                 if (debug != null) {
                     debug.println("X509CertSelector.match: "
                         + "subject public key alg IDs don't match");
@@ -2397,7 +2397,7 @@
              * Convert the Vector of PolicyInformation to a Vector
              * of CertificatePolicyIds for easier comparison.
              */
-            List<CertificatePolicyId> policyIDs = new ArrayList<CertificatePolicyId>(policies.size());
+            List<CertificatePolicyId> policyIDs = new ArrayList<>(policies.size());
             for (PolicyInformation info : policies) {
                 policyIDs.add(info.getPolicyIdentifier());
             }
diff --git a/ojluni/src/main/java/java/security/cert/X509Extension.java b/ojluni/src/main/java/java/security/cert/X509Extension.java
index 0346960..b8aa25f 100644
--- a/ojluni/src/main/java/java/security/cert/X509Extension.java
+++ b/ojluni/src/main/java/java/security/cert/X509Extension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,7 @@
  * be handled by a <em>Class</em> that understands the extension.
  *
  * @author Hemma Prafullchandra
+ * @since 1.2
  */
 
 public interface X509Extension {
@@ -152,30 +153,35 @@
      * by periods.
      *
      * <p>For example:<br>
-     * <table border=groove summary="Examples of OIDs and extension names">
+     * <table class="striped">
+     * <caption style="display:none">Examples of OIDs and extension names</caption>
+     * <thead>
      * <tr>
-     * <th>OID <em>(Object Identifier)</em></th>
-     * <th>Extension Name</th></tr>
-     * <tr><td>2.5.29.14</td>
+     * <th scope="col">OID <em>(Object Identifier)</em></th>
+     * <th scope="col">Extension Name</th></tr>
+     * </thead>
+     * <tbody style="text-align:left">
+     * <tr><th scope="row">2.5.29.14</th>
      * <td>SubjectKeyIdentifier</td></tr>
-     * <tr><td>2.5.29.15</td>
+     * <tr><th scope="row">2.5.29.15</th>
      * <td>KeyUsage</td></tr>
-     * <tr><td>2.5.29.16</td>
+     * <tr><th scope="row">2.5.29.16</th>
      * <td>PrivateKeyUsage</td></tr>
-     * <tr><td>2.5.29.17</td>
+     * <tr><th scope="row">2.5.29.17</th>
      * <td>SubjectAlternativeName</td></tr>
-     * <tr><td>2.5.29.18</td>
+     * <tr><th scope="row">2.5.29.18</th>
      * <td>IssuerAlternativeName</td></tr>
-     * <tr><td>2.5.29.19</td>
+     * <tr><th scope="row">2.5.29.19</th>
      * <td>BasicConstraints</td></tr>
-     * <tr><td>2.5.29.30</td>
+     * <tr><th scope="row">2.5.29.30</th>
      * <td>NameConstraints</td></tr>
-     * <tr><td>2.5.29.33</td>
+     * <tr><th scope="row">2.5.29.33</th>
      * <td>PolicyMappings</td></tr>
-     * <tr><td>2.5.29.35</td>
+     * <tr><th scope="row">2.5.29.35</th>
      * <td>AuthorityKeyIdentifier</td></tr>
-     * <tr><td>2.5.29.36</td>
+     * <tr><th scope="row">2.5.29.36</th>
      * <td>PolicyConstraints</td></tr>
+     * </tbody>
      * </table>
      *
      * @param oid the Object Identifier value for the extension.
diff --git a/ojluni/src/main/java/java/security/cert/package-info.java b/ojluni/src/main/java/java/security/cert/package-info.java
index 4830455..58f5fb7 100644
--- a/ojluni/src/main/java/java/security/cert/package-info.java
+++ b/ojluni/src/main/java/java/security/cert/package-info.java
@@ -32,14 +32,14 @@
  * <h2>Package Specification</h2>
  *
  * <ul>
- *   <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">
+ *   <li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
  *     <b>Java&trade;
  *     Cryptography Architecture (JCA) Reference Guide</b></a>
  *   <li>RFC 5280: Internet X.509 Public Key Infrastructure Certificate and
  *     Certificate Revocation List (CRL) Profile
  *   <li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate
  *     Status Protocol - OCSP
- *   <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html">
+ *   <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
  *     <b>Java&trade;
  *     Cryptography Architecture Standard Algorithm Name
  *     Documentation</b></a></li>
@@ -52,10 +52,10 @@
  *   <li><a href="http://www.ietf.org/rfc/rfc5280.txt">
  *     http://www.ietf.org/rfc/rfc5280.txt</a>
  *   <li><a href=
- *     "https://docs.oracle.com/javase/8/docs/technotes/guides/security/certpath/CertPathProgGuide.html">
+ *     "{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html">
  *     <b>Java&trade;
  *     PKI Programmer's Guide</b></a>
- *   <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/cert3.html">
+ *   <li><a href="{@docRoot}/../technotes/guides/security/cert3.html">
  *     <b>X.509 Certificates and Certificate Revocation Lists (CRLs)</b></a>
  * </ul>
  *
diff --git a/ojluni/src/main/java/java/security/interfaces/DSAKey.java b/ojluni/src/main/java/java/security/interfaces/DSAKey.java
index d78b3e1..64ac8c4 100644
--- a/ojluni/src/main/java/java/security/interfaces/DSAKey.java
+++ b/ojluni/src/main/java/java/security/interfaces/DSAKey.java
@@ -35,6 +35,7 @@
  *
  * @author Benjamin Renaud
  * @author Josh Bloch
+ * @since 1.1
  */
 public interface DSAKey {
 
diff --git a/ojluni/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java b/ojluni/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
index e50cfd2..96e55eb 100644
--- a/ojluni/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
+++ b/ojluni/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,9 +32,12 @@
  *
  * <p>The {@code initialize} methods may each be called any number
  * of times. If no {@code initialize} method is called on a
- * DSAKeyPairGenerator, the default is to generate 1024-bit keys, using
- * precomputed p, q and g parameters and an instance of SecureRandom as
- * the random bit source.
+ * DSAKeyPairGenerator, each provider that implements this interface
+ * should supply (and document) a default initialization. Note that
+ * defaults may vary across different providers. Additionally, the default
+ * value for a provider may change in a future version. Therefore, it is
+ * recommended to explicitly initialize the DSAKeyPairGenerator instead
+ * of relying on provider-specific defaults.
  *
  * <p>Users wishing to indicate DSA-specific parameters, and to generate a key
  * pair suitable for use with the DSA algorithm typically
@@ -45,16 +48,17 @@
  * KeyPairGenerator {@code getInstance} method with "DSA"
  * as its argument.
  *
- * <li>Initialize the generator by casting the result to a DSAKeyPairGenerator
- * and calling one of the
- * {@code initialize} methods from this DSAKeyPairGenerator interface.
+ * <li>Check if the returned key pair generator is an instance of
+ * DSAKeyPairGenerator before casting the result to a DSAKeyPairGenerator
+ * and calling one of the {@code initialize} methods from this
+ * DSAKeyPairGenerator interface.
  *
  * <li>Generate a key pair by calling the {@code generateKeyPair}
- * method from the KeyPairGenerator class.
+ * method of the KeyPairGenerator class.
  *
  * </ol>
  *
- * <p>Note: it is not always necessary to do do algorithm-specific
+ * <p>Note: it is not always necessary to do algorithm-specific
  * initialization for a DSA key pair generator. That is, it is not always
  * necessary to call an {@code initialize} method in this interface.
  * Algorithm-independent initialization using the {@code initialize} method
@@ -63,8 +67,9 @@
  * parameters.
  *
  * <p>Note: Some earlier implementations of this interface may not support
- * larger sizes of DSA parameters such as 2048 and 3072-bit.
+ * larger values of DSA parameters such as 3072-bit.
  *
+ * @since 1.1
  * @see java.security.KeyPairGenerator
  */
 public interface DSAKeyPairGenerator {
@@ -96,8 +101,7 @@
      * p, q and g parameters. If it is false, the method uses precomputed
      * parameters for the modulus length requested. If there are no
      * precomputed parameters for that modulus length, an exception will be
-     * thrown. It is guaranteed that there will always be
-     * default parameters for modulus lengths of 512 and 1024 bits.
+     * thrown.
      *
      * @param modlen the modulus length in bits. Valid values are any
      * multiple of 64 between 512 and 1024, inclusive, 2048, and 3072.
diff --git a/ojluni/src/main/java/java/security/interfaces/DSAParams.java b/ojluni/src/main/java/java/security/interfaces/DSAParams.java
index 8c46ed5..2eafe87 100644
--- a/ojluni/src/main/java/java/security/interfaces/DSAParams.java
+++ b/ojluni/src/main/java/java/security/interfaces/DSAParams.java
@@ -38,6 +38,7 @@
  *
  * @author Benjamin Renaud
  * @author Josh Bloch
+ * @since 1.1
  */
 public interface DSAParams {
 
diff --git a/ojluni/src/main/java/java/security/interfaces/DSAPrivateKey.java b/ojluni/src/main/java/java/security/interfaces/DSAPrivateKey.java
index 81ab358..b23a5c1 100644
--- a/ojluni/src/main/java/java/security/interfaces/DSAPrivateKey.java
+++ b/ojluni/src/main/java/java/security/interfaces/DSAPrivateKey.java
@@ -37,6 +37,7 @@
  * @see DSAPublicKey
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 public interface DSAPrivateKey extends DSAKey, java.security.PrivateKey {
 
diff --git a/ojluni/src/main/java/java/security/interfaces/DSAPublicKey.java b/ojluni/src/main/java/java/security/interfaces/DSAPublicKey.java
index e56b795..fb4a2f3 100644
--- a/ojluni/src/main/java/java/security/interfaces/DSAPublicKey.java
+++ b/ojluni/src/main/java/java/security/interfaces/DSAPublicKey.java
@@ -37,6 +37,7 @@
  * @see DSAPrivateKey
  *
  * @author Benjamin Renaud
+ * @since 1.1
  */
 public interface DSAPublicKey extends DSAKey, java.security.PublicKey {
 
diff --git a/ojluni/src/main/java/java/security/interfaces/EdECKey.java b/ojluni/src/main/java/java/security/interfaces/EdECKey.java
new file mode 100644
index 0000000..bec29ee
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/EdECKey.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.security.spec.NamedParameterSpec;
+
+/**
+ * An interface for an elliptic curve public/private key as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
+ * keys represented by {@code ECKey}, and they are intended for use with
+ * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
+ * This interface allows access to the algorithm parameters associated with
+ * the key.
+ *
+ * @since 15
+ */
+public interface EdECKey {
+    /**
+     * Returns the algorithm parameters associated with the key.
+     *
+     * @return the associated algorithm parameters.
+     */
+    NamedParameterSpec getParams();
+}
diff --git a/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java b/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java
new file mode 100644
index 0000000..826b526
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.security.PrivateKey;
+import java.util.Optional;
+
+/**
+ * An interface for an elliptic curve private key as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
+ * keys represented by {@code ECPrivateKey}, and they are intended for use
+ * with algorithms based on RFC 8032 such as the EdDSA {@code Signature}
+ * algorithm.
+ * <p>
+ * An Edwards-Curve private key is a bit string. This interface only supports bit
+ * string lengths that are a multiple of 8, and the key is represented using
+ * a byte array.
+ *
+ * @since 15
+ */
+public interface EdECPrivateKey extends EdECKey, PrivateKey {
+
+    /**
+     * Get a copy of the byte array representing the private key. This method
+     * may return an empty {@code Optional} if the implementation is not
+     * willing to produce the private key value.
+     *
+     * @return an {@code Optional} containing the private key byte array.
+     * If the key is not available, then an empty {@code Optional}.
+     */
+    Optional<byte[]> getBytes();
+}
diff --git a/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java b/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java
new file mode 100644
index 0000000..d2e2641
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.security.PublicKey;
+import java.security.spec.EdECPoint;
+
+/**
+ * An interface for an elliptic curve public key as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These keys are distinct from the
+ * keys represented by {@code ECPublicKey}, and they are intended for use with
+ * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
+ * <p>
+ * An Edwards-Curve public key is a point on the curve, which is represented using an
+ * EdECPoint.
+ *
+ * @since 15
+ */
+public interface EdECPublicKey extends EdECKey, PublicKey {
+
+    /**
+     * Get the point representing the public key.
+     *
+     * @return the {@code EdECPoint} representing the public key.
+     */
+    EdECPoint getPoint();
+}
diff --git a/ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java b/ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
index f85d96a..fd42c5c 100644
--- a/ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
+++ b/ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,8 +30,8 @@
 
 /**
  * The interface to an RSA multi-prime private key, as defined in the
- * PKCS#1 v2.1, using the <i>Chinese Remainder Theorem</i>
- * (CRT) information values.
+ * <a href="https://tools.ietf.org/rfc/rfc8017.txt">PKCS#1 v2.2</a> standard,
+ * using the <i>Chinese Remainder Theorem</i> (CRT) information values.
  *
  * @author Valerie Peng
  *
diff --git a/ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java b/ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
index 0408fea..e6acef1 100644
--- a/ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
+++ b/ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,10 +28,12 @@
 import java.math.BigInteger;
 
 /**
- * The interface to an RSA private key, as defined in the PKCS#1 standard,
+ * The interface to an RSA private key, as defined in the
+ * <a href="https://tools.ietf.org/rfc/rfc8017.txt">PKCS#1 v2.2</a> standard,
  * using the <i>Chinese Remainder Theorem</i> (CRT) information values.
  *
  * @author Jan Luehe
+ * @since 1.2
  *
  *
  * @see RSAPrivateKey
diff --git a/ojluni/src/main/java/java/security/interfaces/RSAPrivateKey.java b/ojluni/src/main/java/java/security/interfaces/RSAPrivateKey.java
index 5d69ad6..390da4e 100644
--- a/ojluni/src/main/java/java/security/interfaces/RSAPrivateKey.java
+++ b/ojluni/src/main/java/java/security/interfaces/RSAPrivateKey.java
@@ -31,6 +31,7 @@
  * The interface to an RSA private key.
  *
  * @author Jan Luehe
+ * @since 1.2
  *
  *
  * @see RSAPrivateCrtKey
diff --git a/ojluni/src/main/java/java/security/interfaces/RSAPublicKey.java b/ojluni/src/main/java/java/security/interfaces/RSAPublicKey.java
index a698c05..f195306 100644
--- a/ojluni/src/main/java/java/security/interfaces/RSAPublicKey.java
+++ b/ojluni/src/main/java/java/security/interfaces/RSAPublicKey.java
@@ -31,6 +31,7 @@
  * The interface to an RSA public key.
  *
  * @author Jan Luehe
+ * @since 1.2
  *
  */
 
diff --git a/ojluni/src/main/java/java/security/interfaces/XECKey.java b/ojluni/src/main/java/java/security/interfaces/XECKey.java
new file mode 100644
index 0000000..7412daa
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/XECKey.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * An interface for an elliptic curve public/private key as defined by
+ * RFC 7748. These keys are distinct from the keys represented by
+ * {@code ECKey}, and they are intended for use with algorithms based on RFC
+ * 7748 such as the XDH {@code KeyAgreement} algorithm. This interface allows
+ * access to the algorithm parameters associated with the key.
+ *
+ * @since 11
+ */
+public interface XECKey {
+    /**
+     * Returns the algorithm parameters associated
+     * with the key.
+     *
+     * @return the associated algorithm parameters
+     */
+    AlgorithmParameterSpec getParams();
+}
+
diff --git a/ojluni/src/main/java/java/security/interfaces/XECPrivateKey.java b/ojluni/src/main/java/java/security/interfaces/XECPrivateKey.java
new file mode 100644
index 0000000..5476777
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/XECPrivateKey.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.security.PrivateKey;
+import java.util.Optional;
+
+/**
+ * An interface for an elliptic curve private key as defined by RFC 7748.
+ * These keys are distinct from the keys represented by {@code ECPrivateKey},
+ * and they are intended for use with algorithms based on RFC 7748 such as the
+ * XDH {@code KeyAgreement} algorithm.
+ *
+ * An XEC private key is an encoded scalar value as described in RFC 7748.
+ * The decoding procedure defined in this RFC includes an operation that forces
+ * certain bits of the key to either 1 or 0. This operation is known as
+ * "pruning" or "clamping" the private key. Arrays returned by this interface
+ * are unpruned, and implementations will need to prune the array before
+ * using it in any numerical operations.
+ *
+ * @since 11
+ */
+public interface XECPrivateKey extends XECKey, PrivateKey {
+
+    /**
+     * Get the scalar value encoded as an unpruned byte array. A new copy of
+     * the array is returned each time this method is called.
+     *
+     * @return the unpruned encoded scalar value, or an empty Optional if the
+     *     scalar cannot be extracted (e.g. if the provider is a hardware token
+     *     and the private key is not allowed to leave the crypto boundary).
+     */
+    Optional<byte[]> getScalar();
+}
+
diff --git a/ojluni/src/main/java/java/security/interfaces/XECPublicKey.java b/ojluni/src/main/java/java/security/interfaces/XECPublicKey.java
new file mode 100644
index 0000000..6ec200b
--- /dev/null
+++ b/ojluni/src/main/java/java/security/interfaces/XECPublicKey.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.interfaces;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+
+/**
+ * An interface for an elliptic curve public key as defined by RFC 7748.
+ * These keys are distinct from the keys represented by {@code ECPublicKey},
+ * and they are intended for use with algorithms based on RFC 7748 such as the
+ * XDH {@code KeyAgreement} algorithm.
+ *
+ * An XEC public key is a particular point on the curve, which is represented
+ * using only its u-coordinate as described in RFC 7748. A u-coordinate is an
+ * element of the field of integers modulo some value that is determined by
+ * the algorithm parameters. This field element is represented by a BigInteger
+ * which may hold any value. That is, the BigInteger is not restricted to the
+ * range of canonical field elements.
+ *
+ * @since 11
+ */
+public interface XECPublicKey extends XECKey, PublicKey {
+
+    /**
+     * Get the u coordinate of the point.
+     *
+     * @return the u-coordinate, represented using a BigInteger which may hold
+     *          any value
+     */
+    BigInteger getU();
+
+}
+
diff --git a/ojluni/src/main/java/java/security/interfaces/package-info.java b/ojluni/src/main/java/java/security/interfaces/package-info.java
index 8942340..54c9397 100644
--- a/ojluni/src/main/java/java/security/interfaces/package-info.java
+++ b/ojluni/src/main/java/java/security/interfaces/package-info.java
@@ -43,7 +43,7 @@
  * to these cryptographic provider developer guides:
  * <ul>
  *   <li><a href=
- *     "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html">
+ *     "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html">
  *     <b>How to Implement a Provider for the
  *     Java&trade; Cryptography Architecture
  *     </b></a></li>
@@ -63,7 +63,7 @@
  * <ul>
  *   <li>
  *     <a href=
- *       "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">
+ *       "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
  *       <b>Java&trade;
  *       Cryptography Architecture API Specification and Reference
  *       </b></a></li>
diff --git a/ojluni/src/main/java/java/security/package-info.java b/ojluni/src/main/java/java/security/package-info.java
index 60e9b4b..2c8205b 100644
--- a/ojluni/src/main/java/java/security/package-info.java
+++ b/ojluni/src/main/java/java/security/package-info.java
@@ -46,14 +46,14 @@
  * <h2>Package Specification</h2>
  *
  * <ul>
- *   <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">
+ *   <li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
  *     <b>Java&trade;
  *     Cryptography Architecture (JCA) Reference Guide</b></a></li>
  *
  *   <li>PKCS #8: Private-Key Information Syntax Standard, Version 1.2,
  *     November 1993</li>
  *
- *   <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html">
+ *   <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
  *     <b>Java&trade;
  *     Cryptography Architecture Standard Algorithm Name
  *     Documentation</b></a></li>
@@ -64,44 +64,44 @@
  * For further documentation, please see:
  * <ul>
  *   <li><a href=
- *     "https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc.html">
+ *     "{@docRoot}/../technotes/guides/security/spec/security-spec.doc.html">
  *     <b>Java&trade;
  *     SE Platform Security Architecture</b></a></li>
  *
  *   <li><a href=
- *     "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html">
+ *     "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html">
  *     <b>How to Implement a Provider in the
  *     Java&trade; Cryptography Architecture
  *     </b></a></li>
  *
  *   <li><a href=
- *     "https://docs.oracle.com/javase/8/docs/technotes/guides/security/PolicyFiles.html"><b>
+ *     "{@docRoot}/../technotes/guides/security/PolicyFiles.html"><b>
  *     Default Policy Implementation and Policy File Syntax
  *     </b></a></li>
  *
  *   <li><a href=
- *     "https://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html"><b>
+ *     "{@docRoot}/../technotes/guides/security/permissions.html"><b>
  *     Permissions in the
  *     Java&trade; SE Development Kit (JDK)
  *     </b></a></li>
  *
  *   <li><a href=
- *     "https://docs.oracle.com/javase/8/docs/technotes/guides/security/SecurityToolsSummary.html"><b>
+ *     "{@docRoot}/../technotes/guides/security/SecurityToolsSummary.html"><b>
  *     Summary of Tools for
  *     Java&trade; Platform Security
  *     </b></a></li>
  *
  *   <li><b>keytool</b>
- *     (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html">
+ *     (<a href="{@docRoot}/../technotes/tools/unix/keytool.html">
  *       for Solaris/Linux</a>)
- *     (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html">
+ *     (<a href="{@docRoot}/../technotes/tools/windows/keytool.html">
  *       for Windows</a>)
  *     </li>
  *
  *   <li><b>jarsigner</b>
- *     (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jarsigner.html">
+ *     (<a href="{@docRoot}/../technotes/tools/unix/jarsigner.html">
  *       for Solaris/Linux</a>)
- *     (<a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html">
+ *     (<a href="{@docRoot}/../technotes/tools/windows/jarsigner.html">
  *       for Windows</a>)
  *     </li>
  *
diff --git a/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java b/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java
index 4f3f63b..ae9ed6b 100644
--- a/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java
+++ b/ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,8 @@
  *
  * @since 1.5
  */
-public class ECGenParameterSpec implements AlgorithmParameterSpec {
-
-    private String name;
+// Android-added: implements AlgorithmParameterSpec in order to maintain backwards compatibility.
+public class ECGenParameterSpec extends NamedParameterSpec implements AlgorithmParameterSpec {
 
     /**
      * Creates a parameter specification for EC parameter
@@ -44,25 +43,27 @@
      * {@code stdName} in order to generate the corresponding
      * (precomputed) elliptic curve domain parameters. For the
      * list of supported names, please consult the documentation
-     * of provider whose implementation will be used.
+     * of the provider whose implementation will be used.
+     *
      * @param stdName the standard name of the to-be-generated EC
-     * domain parameters.
-     * @exception NullPointerException if {@code stdName}
-     * is null.
+     *                domain parameters.
+     * @throws NullPointerException if {@code stdName}
+     *                              is null.
      */
     public ECGenParameterSpec(String stdName) {
-        if (stdName == null) {
-            throw new NullPointerException("stdName is null");
-        }
-        this.name = stdName;
+        super(stdName);
     }
 
+
     /**
      * Returns the standard or predefined name of the
      * to-be-generated EC domain parameters.
      * @return the standard or predefined name.
      */
+    // Android-added: function overridden in order to maintain backwards compatibility.
+    @Override
     public String getName() {
-        return name;
+      return super.getName();
     }
 }
+
diff --git a/ojluni/src/main/java/java/security/spec/EdECPoint.java b/ojluni/src/main/java/java/security/spec/EdECPoint.java
new file mode 100644
index 0000000..cb080f8
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/EdECPoint.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Objects;
+
+/**
+ * An elliptic curve point used to specify keys as defined by
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>. These points are distinct from the
+ * points represented by {@code ECPoint}, and they are intended for use with
+ * algorithms based on RFC 8032 such as the EdDSA {@code Signature} algorithm.
+ * <p>
+ * An EdEC point is specified by its y-coordinate value and a boolean that
+ * indicates whether the x-coordinate is odd. The y-coordinate is an
+ * element of the field of integers modulo some value p that is determined by
+ * the algorithm parameters. This field element is represented by a
+ * {@code BigInteger}, and implementations that consume objects of this class
+ * may reject integer values which are not in the range [0, p).
+ *
+ * @since 15
+ */
+
+public final class EdECPoint {
+
+    private final boolean xOdd;
+    private final BigInteger y;
+
+    /**
+     * Construct an EdECPoint.
+     *
+     * @param xOdd whether the x-coordinate is odd.
+     * @param y the y-coordinate, represented using a {@code BigInteger}.
+     *
+     * @throws NullPointerException if {@code y} is null.
+     */
+    public EdECPoint(boolean xOdd, BigInteger y) {
+
+        Objects.requireNonNull(y, "y must not be null");
+
+        this.xOdd = xOdd;
+        this.y = y;
+    }
+
+    /**
+     * Get whether the x-coordinate of the point is odd.
+     *
+     * @return a boolean indicating whether the x-coordinate is odd.
+     */
+    public boolean isXOdd() {
+        return xOdd;
+    }
+
+    /**
+     * Get the y-coordinate of the point.
+     *
+     * @return the y-coordinate, represented using a {@code BigInteger}.
+     */
+    public BigInteger getY() {
+        return y;
+    }
+}
diff --git a/ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java b/ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java
new file mode 100644
index 0000000..370dfc9
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+/**
+ * A class representing elliptic curve private keys as defined in
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>, including the curve and other
+ * algorithm parameters. The private key is a bit string represented using
+ * a byte array. This class only supports bit string lengths that are a
+ * multiple of 8.
+ *
+ * @since 15
+ */
+public final class EdECPrivateKeySpec implements KeySpec {
+
+    private final NamedParameterSpec params;
+    private final byte[] bytes;
+
+    /**
+     * Construct a private key spec using the supplied parameters and
+     * bit string.
+     *
+     * @param params the algorithm parameters.
+     * @param bytes the key as a byte array. This array is copied
+     *              to protect against subsequent modification.
+     *
+     * @throws NullPointerException if {@code params} or {@code bytes}
+     *                              is null.
+     */
+    public EdECPrivateKeySpec(NamedParameterSpec params, byte[] bytes) {
+        Objects.requireNonNull(params, "params must not be null");
+        Objects.requireNonNull(bytes, "bytes must not be null");
+
+        this.params = params;
+        this.bytes = bytes.clone();
+    }
+
+    /**
+     * Get the algorithm parameters that define the curve and other settings.
+     *
+     * @return the algorithm parameters.
+     */
+    public NamedParameterSpec getParams() {
+        return params;
+    }
+
+    /**
+     * Get the byte array representing the private key. A new copy of the array
+     * is returned each time this method is called.
+     *
+     * @return the private key as a byte array.
+     */
+    public byte[] getBytes() {
+        return bytes.clone();
+    }
+}
diff --git a/ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java b/ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java
new file mode 100644
index 0000000..fc52b3b
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+/**
+ * A class representing elliptic curve public keys as defined in
+ * <a href="https://tools.ietf.org/html/rfc8032">RFC 8032: Edwards-Curve
+ * Digital Signature Algorithm (EdDSA)</a>, including the curve and other
+ * algorithm parameters. The public key is a point on the curve, which is
+ * represented using an {@code EdECPoint}.
+ *
+ * @since 15
+ */
+public final class EdECPublicKeySpec implements KeySpec {
+
+    private final NamedParameterSpec params;
+    private final EdECPoint point;
+
+    /**
+     * Construct a public key spec using the supplied parameters and
+     * point.
+     *
+     * @param params the algorithm parameters.
+     * @param point the point representing the public key.
+     *
+     * @throws NullPointerException if {@code params} or {@code point}
+     *                              is null.
+     */
+    public EdECPublicKeySpec(NamedParameterSpec params, EdECPoint point) {
+        Objects.requireNonNull(params, "params must not be null");
+        Objects.requireNonNull(point, "point must not be null");
+
+        this.params = params;
+        this.point = point;
+    }
+
+    /**
+     * Get the algorithm parameters that define the curve and other settings.
+     *
+     * @return the parameters.
+     */
+    public NamedParameterSpec getParams() {
+        return params;
+    }
+
+    /**
+     * Get the point representing the public key.
+     *
+     * @return the {@code EdECPoint} representing the public key.
+     */
+    public EdECPoint getPoint() {
+        return point;
+    }
+}
diff --git a/ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java b/ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java
index 4655c4a..4439e00 100644
--- a/ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java
+++ b/ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java
@@ -63,7 +63,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeySpecException} with the specified
+     * Creates an {@code InvalidKeySpecException} with the specified
      * detail message and cause.
      *
      * @param message the detail message (which is saved for later retrieval
@@ -78,7 +78,7 @@
     }
 
     /**
-     * Creates a {@code InvalidKeySpecException} with the specified cause
+     * Creates an {@code InvalidKeySpecException} with the specified cause
      * and a detail message of {@code (cause==null ? null : cause.toString())}
      * (which typically contains the class and detail message of
      * {@code cause}).
diff --git a/ojluni/src/main/java/java/security/spec/NamedParameterSpec.java b/ojluni/src/main/java/java/security/spec/NamedParameterSpec.java
new file mode 100644
index 0000000..9090567
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/NamedParameterSpec.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+/**
+ * This class is used to specify any algorithm parameters that are determined
+ * by a standard name. This class also holds constants for standard parameter
+ * set names. The names of these constants exactly match the corresponding
+ * parameter set name. For example, NamedParameterSpec.X25519 represents the
+ * parameter set identified by the string "X25519". These strings are defined
+ * in the <a href=
+ * "{@docRoot}/../specs/security/standard-names.html#parameterspec-names">
+ *          Java Security Standard Algorithm Names Specification</a>.
+ *
+ * @since 11
+ *
+ */
+public class NamedParameterSpec implements AlgorithmParameterSpec {
+
+   /**
+    * The X25519 parameters
+    */
+    public static final NamedParameterSpec X25519
+        = new NamedParameterSpec("X25519");
+   /**
+    * The X448 parameters
+    */
+    public static final NamedParameterSpec X448
+        = new NamedParameterSpec("X448");
+
+    /**
+     * The Ed25519 parameters
+     *
+     * @since 15
+     */
+    public static final NamedParameterSpec ED25519
+        = new NamedParameterSpec("Ed25519");
+
+    /**
+     * The Ed448 parameters
+     *
+     * @since 15
+     */
+    public static final NamedParameterSpec ED448
+        = new NamedParameterSpec("Ed448");
+
+    private String name;
+
+    /**
+     * Creates a parameter specification using a standard (or predefined)
+     * name {@code stdName}. For the
+     * list of supported names, please consult the documentation
+     * of the provider whose implementation will be used.
+     *
+     * @param stdName the standard name of the algorithm parameters. See the
+     *        ParameterSpec Names section in the
+     *        <a href=
+     *        "{@docRoot}/../specs/security/standard-names.html#parameterspec-names">
+     *        Java Security Standard Algorithm Names Specification</a> for
+     *        information about standard names.
+     *
+     * @throws NullPointerException if {@code stdName} is null.
+     */
+    public NamedParameterSpec(String stdName) {
+        Objects.requireNonNull(stdName, "stdName must not be null");
+
+        this.name = stdName;
+    }
+
+    /**
+     * Returns the standard name that determines the algorithm parameters.
+     * @return the standard name.
+     */
+    public String getName() {
+        return name;
+    }
+}
diff --git a/ojluni/src/main/java/java/security/spec/XECPrivateKeySpec.java b/ojluni/src/main/java/java/security/spec/XECPrivateKeySpec.java
new file mode 100644
index 0000000..02687b5
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/XECPrivateKeySpec.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.util.Objects;
+
+/**
+ * A class representing elliptic curve private keys as defined in RFC 7748,
+ * including the curve and other algorithm parameters. The private key is
+ * represented as an encoded scalar value. The decoding procedure defined in
+ * the RFC includes an operation that forces certain bits of the key to either
+ * 1 or 0. This operation is known as "pruning" or "clamping" the private key.
+ * All arrays in this spec are unpruned, and implementations will need to prune
+ * the array before using it in any numerical operations.
+ *
+ * @since 11
+ */
+public class XECPrivateKeySpec implements KeySpec {
+
+    private final AlgorithmParameterSpec params;
+    private final byte[] scalar;
+
+    /**
+     * Construct a private key spec using the supplied parameters and
+     * encoded scalar value.
+     *
+     * @param params the algorithm parameters
+     * @param scalar the unpruned encoded scalar value. This array is copied
+     *               to protect against subsequent modification.
+     *
+     * @throws NullPointerException if {@code params} or {@code scalar}
+     *                              is null.
+     */
+    public XECPrivateKeySpec(AlgorithmParameterSpec params, byte[] scalar) {
+        Objects.requireNonNull(params, "params must not be null");
+        Objects.requireNonNull(scalar, "scalar must not be null");
+
+        this.params = params;
+        this.scalar = scalar.clone();
+    }
+
+    /**
+     * Get the algorithm parameters that define the curve and other settings.
+     *
+     * @return the algorithm parameters
+     */
+    public AlgorithmParameterSpec getParams() {
+        return params;
+    }
+
+    /**
+     * Get the scalar value encoded as an unpruned byte array. A new copy of
+     * the array is returned each time this method is called.
+     *
+     * @return the unpruned encoded scalar value
+     */
+    public byte[] getScalar() {
+        return scalar.clone();
+    }
+}
diff --git a/ojluni/src/main/java/java/security/spec/XECPublicKeySpec.java b/ojluni/src/main/java/java/security/spec/XECPublicKeySpec.java
new file mode 100644
index 0000000..162cf10
--- /dev/null
+++ b/ojluni/src/main/java/java/security/spec/XECPublicKeySpec.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.security.spec;
+
+import java.math.BigInteger;
+import java.util.Objects;
+
+/**
+ * A class representing elliptic curve public keys as defined in RFC 7748,
+ * including the curve and other algorithm parameters. The public key is a
+ * particular point on the curve, which is represented using only its
+ * u-coordinate. A u-coordinate is an element of the field of integers modulo
+ * some value that is determined by the algorithm parameters. This field
+ * element is represented by a BigInteger which may hold any value. That is,
+ * the BigInteger is not restricted to the range of canonical field elements.
+ *
+ * @since 11
+ */
+public class XECPublicKeySpec implements KeySpec {
+
+    private final AlgorithmParameterSpec params;
+    private final BigInteger u;
+
+    /**
+     * Construct a public key spec using the supplied parameters and
+     * u coordinate.
+     *
+     * @param params the algorithm parameters
+     * @param u the u-coordinate of the point, represented using a BigInteger
+     *          which may hold any value
+     *
+     * @throws NullPointerException if {@code params} or {@code u}
+     *                              is null.
+     */
+    public XECPublicKeySpec(AlgorithmParameterSpec params, BigInteger u) {
+        Objects.requireNonNull(params, "params must not be null");
+        Objects.requireNonNull(u, "u must not be null");
+
+        this.params = params;
+        this.u = u;
+    }
+
+    /**
+     * Get the algorithm parameters that define the curve and other settings.
+     *
+     * @return the parameters
+     */
+    public AlgorithmParameterSpec getParams() {
+        return params;
+    }
+
+    /**
+     * Get the u coordinate of the point.
+     *
+     * @return the u-coordinate, represented using a BigInteger which may hold
+     *          any value
+     */
+    public BigInteger getU() {
+        return u;
+    }
+}
diff --git a/ojluni/src/main/java/java/security/spec/package-info.java b/ojluni/src/main/java/java/security/spec/package-info.java
index 68f0b8e..cb39308 100644
--- a/ojluni/src/main/java/java/security/spec/package-info.java
+++ b/ojluni/src/main/java/java/security/spec/package-info.java
@@ -56,13 +56,13 @@
  * <ul>
  *   <li>
  *     <a href=
- *       "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">
+ *       "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
  *       <b>Java&trade;
  *       Cryptography Architecture API Specification and Reference
  *       </b></a></li>
  *   <li>
  *     <a href=
- *       "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html">
+ *       "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html">
  *       <b>How to Implement a Provider for the
  *       Java&trade; Cryptography Architecture
  *       </b></a></li>
diff --git a/ojluni/src/main/java/java/text/AttributedString.java b/ojluni/src/main/java/java/text/AttributedString.java
index fa398e9..2e6e0e7 100644
--- a/ojluni/src/main/java/java/text/AttributedString.java
+++ b/ojluni/src/main/java/java/text/AttributedString.java
@@ -48,21 +48,18 @@
  */
 
 public class AttributedString {
-
-    // since there are no vectors of int, we have to use arrays.
-    // We allocate them in chunks of 10 elements so we don't have to allocate all the time.
-    private static final int ARRAY_SIZE_INCREMENT = 10;
-
     // field holding the text
     String text;
 
-    // fields holding run attribute information
-    // run attributes are organized by run
-    int runArraySize;               // current size of the arrays
-    int runCount;                   // actual number of runs, <= runArraySize
-    int runStarts[];                // start index for each run
-    Vector<Attribute> runAttributes[];         // vector of attribute keys for each run
-    Vector<Object> runAttributeValues[];    // parallel vector of attribute values for each run
+    // Fields holding run attribute information.
+    // Run attributes are organized by run.
+    // Arrays are always of equal lengths (the current capacity).
+    // Since there are no vectors of int, we have to use arrays.
+    private static final int INITIAL_CAPACITY = 10;
+    int runCount;                   // actual number of runs, <= current capacity
+    int[] runStarts;                // start index for each run
+    Vector<Attribute>[] runAttributes;   // vector of attribute keys for each run
+    Vector<Object>[] runAttributeValues; // parallel vector of attribute values for each run
 
     /**
      * Constructs an AttributedString instance with the given
@@ -88,7 +85,7 @@
 
             text = buffer.toString();
 
-            if (text.length() > 0) {
+            if (!text.isEmpty()) {
                 // Determine the runs, creating a new run when the attributes
                 // differ.
                 int offset = 0;
@@ -147,7 +144,7 @@
         }
         this.text = text;
 
-        if (text.length() == 0) {
+        if (text.isEmpty()) {
             if (attributes.isEmpty())
                 return;
             throw new IllegalArgumentException("Can't add attribute to 0-length text");
@@ -243,11 +240,11 @@
             throw new IllegalArgumentException("Invalid substring range");
 
         // Copy the given string
-        StringBuffer textBuffer = new StringBuffer();
+        StringBuilder textBuilder = new StringBuilder();
         text.setIndex(beginIndex);
         for (char c = text.current(); text.getIndex() < endIndex; c = text.next())
-            textBuffer.append(c);
-        this.text = textBuffer.toString();
+            textBuilder.append(c);
+        this.text = textBuilder.toString();
 
         if (beginIndex == endIndex)
             return;
@@ -335,7 +332,7 @@
      * @param beginIndex Index of the first character of the range.
      * @param endIndex Index of the character following the last character of the range.
      * @exception NullPointerException if <code>attribute</code> is null.
-     * @exception IllegalArgumentException if beginIndex is less then 0, endIndex is
+     * @exception IllegalArgumentException if beginIndex is less than 0, endIndex is
      * greater than the length of the string, or beginIndex and endIndex together don't
      * define a non-empty subrange of the string.
      */
@@ -360,7 +357,7 @@
      * @param endIndex Index of the character following the last
      * character of the range.
      * @exception NullPointerException if <code>attributes</code> is null.
-     * @exception IllegalArgumentException if beginIndex is less then
+     * @exception IllegalArgumentException if beginIndex is less than
      * 0, endIndex is greater than the length of the string, or
      * beginIndex and endIndex together don't define a non-empty
      * subrange of the string and the attributes parameter is not an
@@ -416,18 +413,17 @@
 
     private final void createRunAttributeDataVectors() {
         // use temporary variables so things remain consistent in case of an exception
-        int newRunStarts[] = new int[ARRAY_SIZE_INCREMENT];
+        int[] newRunStarts = new int[INITIAL_CAPACITY];
 
         @SuppressWarnings("unchecked")
-        Vector<Attribute> newRunAttributes[] = (Vector<Attribute>[]) new Vector<?>[ARRAY_SIZE_INCREMENT];
+        Vector<Attribute>[] newRunAttributes = (Vector<Attribute>[]) new Vector<?>[INITIAL_CAPACITY];
 
         @SuppressWarnings("unchecked")
-        Vector<Object> newRunAttributeValues[] = (Vector<Object>[]) new Vector<?>[ARRAY_SIZE_INCREMENT];
+        Vector<Object>[] newRunAttributeValues = (Vector<Object>[]) new Vector<?>[INITIAL_CAPACITY];
 
         runStarts = newRunStarts;
         runAttributes = newRunAttributes;
         runAttributeValues = newRunAttributeValues;
-        runArraySize = ARRAY_SIZE_INCREMENT;
         runCount = 1; // assume initial run starting at index 0
     }
 
@@ -465,25 +461,22 @@
 
         // we'll have to break up a run
         // first, make sure we have enough space in our arrays
-        if (runCount == runArraySize) {
-            int newArraySize = runArraySize + ARRAY_SIZE_INCREMENT;
-            int newRunStarts[] = new int[newArraySize];
+        int currentCapacity = runStarts.length;
+        if (runCount == currentCapacity) {
+            // We need to resize - we grow capacity by 25%.
+            int newCapacity = currentCapacity + (currentCapacity >> 2);
 
-            @SuppressWarnings("unchecked")
-            Vector<Attribute> newRunAttributes[] = (Vector<Attribute>[]) new Vector<?>[newArraySize];
+            // use temporary variables so things remain consistent in case of an exception
+            int[] newRunStarts =
+                Arrays.copyOf(runStarts, newCapacity);
+            Vector<Attribute>[] newRunAttributes =
+                Arrays.copyOf(runAttributes, newCapacity);
+            Vector<Object>[] newRunAttributeValues =
+                Arrays.copyOf(runAttributeValues, newCapacity);
 
-            @SuppressWarnings("unchecked")
-            Vector<Object> newRunAttributeValues[] = (Vector<Object>[]) new Vector<?>[newArraySize];
-
-            for (int i = 0; i < runArraySize; i++) {
-                newRunStarts[i] = runStarts[i];
-                newRunAttributes[i] = runAttributes[i];
-                newRunAttributeValues[i] = runAttributeValues[i];
-            }
             runStarts = newRunStarts;
             runAttributes = newRunAttributes;
             runAttributeValues = newRunAttributeValues;
-            runArraySize = newArraySize;
         }
 
         // make copies of the attribute information of the old run that the new one used to be part of
@@ -587,7 +580,7 @@
      * @param beginIndex the index of the first character
      * @param endIndex the index of the character following the last character
      * @return an iterator providing access to the text and its attributes
-     * @exception IllegalArgumentException if beginIndex is less then 0,
+     * @exception IllegalArgumentException if beginIndex is less than 0,
      * endIndex is greater than the length of the string, or beginIndex is
      * greater than endIndex.
      */
@@ -674,7 +667,7 @@
     }
 
     // returns whether the two objects are either both null or equal
-    private final static boolean valuesMatch(Object value1, Object value2) {
+    private static final boolean valuesMatch(Object value1, Object value2) {
         if (value1 == null) {
             return value2 == null;
         } else {
@@ -739,7 +732,7 @@
 
     // the iterator class associated with this string class
 
-    final private class AttributedStringIterator implements AttributedCharacterIterator {
+    private final class AttributedStringIterator implements AttributedCharacterIterator {
 
         // note on synchronization:
         // we don't synchronize on the iterator, assuming that an iterator is only used in one thread.
@@ -1052,7 +1045,7 @@
 
     // the map class associated with this string class, giving access to the attributes of one run
 
-    final private class AttributeMap extends AbstractMap<Attribute,Object> {
+    private final class AttributeMap extends AbstractMap<Attribute,Object> {
 
         int runIndex;
         int beginIndex;
diff --git a/ojluni/src/main/java/java/text/Bidi.java b/ojluni/src/main/java/java/text/Bidi.java
index 70e29aa..19bcd50 100644
--- a/ojluni/src/main/java/java/text/Bidi.java
+++ b/ojluni/src/main/java/java/text/Bidi.java
@@ -216,6 +216,12 @@
      */
     public Bidi createLineBidi(int lineStart, int lineLimit) {
         // BEGIN Android-changed: add explict argument checks and use ICU Bidi class.
+        /*
+        AttributedString astr = new AttributedString("");
+        Bidi newBidi = new Bidi(astr.getIterator());
+
+        return bidiBase.setLine(this, bidiBase, newBidi, newBidi.bidiBase, lineStart, lineLimit);
+        */
         if (lineStart < 0 || lineLimit < 0 || lineStart > lineLimit || lineLimit > getLength()) {
             throw new IllegalArgumentException("Invalid ranges (start=" + lineStart + ", " +
                                                "limit=" + lineLimit + ", length=" + getLength() + ")");
diff --git a/ojluni/src/main/java/java/text/BreakIterator.java b/ojluni/src/main/java/java/text/BreakIterator.java
index a875ec1..55df18b 100644
--- a/ojluni/src/main/java/java/text/BreakIterator.java
+++ b/ojluni/src/main/java/java/text/BreakIterator.java
@@ -70,19 +70,19 @@
  * (word, line, sentence, and so on). You must use a different iterator
  * for each unit boundary analysis you wish to perform.
  *
- * <p><a name="line"></a>
+ * <p><a id="line"></a>
  * Line boundary analysis determines where a text string can be
  * broken when line-wrapping. The mechanism correctly handles
  * punctuation and hyphenated words. Actual line breaking needs
  * to also consider the available line width and is handled by
  * higher-level software.
  *
- * <p><a name="sentence"></a>
+ * <p><a id="sentence"></a>
  * Sentence boundary analysis allows selection with correct interpretation
  * of periods within numbers and abbreviations, and trailing punctuation
  * marks such as quotation marks and parentheses.
  *
- * <p><a name="word"></a>
+ * <p><a id="word"></a>
  * Word boundary analysis is used by search and replace functions, as
  * well as within text editing applications that allow the user to
  * select words with a double click. Word selection provides correct
@@ -90,7 +90,7 @@
  * words. Characters that are not part of a word, such as symbols
  * or punctuation marks, have word-breaks on both sides.
  *
- * <p><a name="character"></a>
+ * <p><a id="character"></a>
  * Character boundary analysis allows users to interact with characters
  * as they expect to, for example, when moving the cursor through a text
  * string. Character boundary analysis provides correct navigation
@@ -223,6 +223,7 @@
  * and the next is a word; otherwise, it's the material between words.)
  * </blockquote>
  *
+ * @since 1.1
  * @see CharacterIterator
  *
  */
diff --git a/ojluni/src/main/java/java/text/CalendarBuilder.java b/ojluni/src/main/java/java/text/CalendarBuilder.java
index a8246b6..cb30a35 100644
--- a/ojluni/src/main/java/java/text/CalendarBuilder.java
+++ b/ojluni/src/main/java/java/text/CalendarBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package java.text;
 
 import java.util.Calendar;
+import java.util.StringJoiner;
 import static java.util.GregorianCalendar.*;
 
 /**
@@ -146,19 +147,13 @@
     }
 
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("CalendarBuilder:[");
+        StringJoiner sj = new StringJoiner(",", "CalendarBuilder:[", "]");
         for (int i = 0; i < field.length; i++) {
             if (isSet(i)) {
-                sb.append(i).append('=').append(field[MAX_FIELD + i]).append(',');
+                sj.add(i + "=" + field[MAX_FIELD + i]);
             }
         }
-        int lastIndex = sb.length() - 1;
-        if (sb.charAt(lastIndex) == ',') {
-            sb.setLength(lastIndex);
-        }
-        sb.append(']');
-        return sb.toString();
+        return sj.toString();
     }
 
     static int toISODayOfWeek(int calendarDayOfWeek) {
diff --git a/ojluni/src/main/java/java/text/CharacterIterator.java b/ojluni/src/main/java/java/text/CharacterIterator.java
index efa7ab4..b6e5e8b 100644
--- a/ojluni/src/main/java/java/text/CharacterIterator.java
+++ b/ojluni/src/main/java/java/text/CharacterIterator.java
@@ -98,6 +98,7 @@
  * }
  * }</pre>
  *
+ * @since 1.1
  * @see StringCharacterIterator
  * @see AttributedCharacterIterator
  */
diff --git a/ojluni/src/main/java/java/text/ChoiceFormat.java b/ojluni/src/main/java/java/text/ChoiceFormat.java
index 3baaa90..4306629 100644
--- a/ojluni/src/main/java/java/text/ChoiceFormat.java
+++ b/ojluni/src/main/java/java/text/ChoiceFormat.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -151,7 +151,7 @@
  * }</pre>
  * </blockquote>
  *
- * <h3><a name="synchronization">Synchronization</a></h3>
+ * <h3><a id="synchronization">Synchronization</a></h3>
  *
  * <p>
  * Choice formats are not synchronized.
@@ -163,6 +163,7 @@
  * @see          DecimalFormat
  * @see          MessageFormat
  * @author       Mark Davis
+ * @since 1.1
  */
 public class ChoiceFormat extends NumberFormat {
 
@@ -172,6 +173,8 @@
     /**
      * Sets the pattern.
      * @param newPattern See the class description.
+     * @exception NullPointerException if {@code newPattern}
+     *            is {@code null}
      */
     public void applyPattern(String newPattern) {
         StringBuffer[] segments = new StringBuffer[2];
@@ -199,27 +202,26 @@
                 segments[part].append(ch);
             } else if (ch == '<' || ch == '#' || ch == '\u2264') {
                 if (segments[0].length() == 0) {
-                    throw new IllegalArgumentException();
+                    throw new IllegalArgumentException("Each interval must"
+                            + " contain a number before a format");
                 }
-                try {
-                    String tempBuffer = segments[0].toString();
-                    if (tempBuffer.equals("\u221E")) {
-                        startValue = Double.POSITIVE_INFINITY;
-                    } else if (tempBuffer.equals("-\u221E")) {
-                        startValue = Double.NEGATIVE_INFINITY;
-                    } else {
-                        // Android-changed: avoid object instantiation followed by unboxing.
-                        startValue = Double.parseDouble(segments[0].toString());
-                    }
-                } catch (Exception e) {
-                    throw new IllegalArgumentException();
+
+                String tempBuffer = segments[0].toString();
+                if (tempBuffer.equals("\u221E")) {
+                    startValue = Double.POSITIVE_INFINITY;
+                } else if (tempBuffer.equals("-\u221E")) {
+                    startValue = Double.NEGATIVE_INFINITY;
+                } else {
+                    startValue = Double.parseDouble(tempBuffer);
                 }
+
                 if (ch == '<' && startValue != Double.POSITIVE_INFINITY &&
                         startValue != Double.NEGATIVE_INFINITY) {
                     startValue = nextDouble(startValue);
                 }
                 if (startValue <= oldStartValue) {
-                    throw new IllegalArgumentException();
+                    throw new IllegalArgumentException("Incorrect order of"
+                            + " intervals, must be in ascending order");
                 }
                 segments[0].setLength(0);
                 part = 1;
@@ -260,7 +262,7 @@
      * @return the pattern string
      */
     public String toPattern() {
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         for (int i = 0; i < choiceLimits.length; ++i) {
             if (i != 0) {
                 result.append('|');
@@ -273,7 +275,7 @@
             double tryLess = Math.abs(Math.IEEEremainder(less, 1.0d));
 
             if (tryLessOrEqual < tryLess) {
-                result.append(""+choiceLimits[i]);
+                result.append(choiceLimits[i]);
                 result.append('#');
             } else {
                 if (choiceLimits[i] == Double.POSITIVE_INFINITY) {
@@ -281,7 +283,7 @@
                 } else if (choiceLimits[i] == Double.NEGATIVE_INFINITY) {
                     result.append("-\u221E");
                 } else {
-                    result.append(""+less);
+                    result.append(less);
                 }
                 result.append('<');
             }
@@ -310,6 +312,8 @@
      * Constructs with limits and corresponding formats based on the pattern.
      *
      * @param newPattern the new pattern string
+     * @exception NullPointerException if {@code newPattern} is
+     *            {@code null}
      * @see #applyPattern
      */
     public ChoiceFormat(String newPattern)  {
@@ -321,6 +325,8 @@
      *
      * @param limits limits in ascending order
      * @param formats corresponding format strings
+     * @exception NullPointerException if {@code limits} or {@code formats}
+     *            is {@code null}
      * @see #setChoices
      */
     public ChoiceFormat(double[] limits, String[] formats) {
@@ -340,6 +346,8 @@
      * When formatting with object Y,
      * if the object is a NumberFormat, then ((NumberFormat) Y).format(X)
      * is called. Otherwise Y.toString() is called.
+     * @exception NullPointerException if {@code limits} or
+     *            {@code formats} is {@code null}
      */
     public void setChoices(double[] limits, String formats[]) {
         if (limits.length != formats.length) {
@@ -389,6 +397,8 @@
      * @param number number to be formatted and substituted.
      * @param toAppendTo where text is appended.
      * @param status ignore no useful status is returned.
+     * @exception NullPointerException if {@code toAppendTo}
+     *            is {@code null}
      */
    public StringBuffer format(double number, StringBuffer toAppendTo,
                                FieldPosition status) {
@@ -417,6 +427,9 @@
      * status.index is unchanged and status.errorIndex is set to the
      * first index of the character that caused the parse to fail.
      * @return A Number representing the value of the number parsed.
+     * @exception NullPointerException if {@code status} is {@code null}
+     *            or if {@code text} is {@code null} and the list of
+     *            choice strings is not empty.
      */
     public Number parse(String text, ParsePosition status) {
         // find the best number (defined as the one with the longest parse)
@@ -440,7 +453,7 @@
         if (status.index == start) {
             status.errorIndex = furthest;
         }
-        return new Double(bestNumber);
+        return Double.valueOf(bestNumber);
     }
 
     /**
@@ -493,7 +506,7 @@
     }
 
     /**
-     * Equality comparision between two
+     * Equality comparison between two
      */
     public boolean equals(Object obj) {
         if (obj == null) return false;
diff --git a/ojluni/src/main/java/java/text/CollationElementIterator.java b/ojluni/src/main/java/java/text/CollationElementIterator.java
index 17ce8c7..7d17496 100644
--- a/ojluni/src/main/java/java/text/CollationElementIterator.java
+++ b/ojluni/src/main/java/java/text/CollationElementIterator.java
@@ -100,6 +100,7 @@
  * @see                Collator
  * @see                RuleBasedCollator
  * @author             Helena Shih, Laura Werner, Richard Gillam
+ * @since 1.1
  */
 public final class CollationElementIterator
 {
@@ -107,9 +108,28 @@
      * Null order which indicates the end of string is reached by the
      * cursor.
      */
-    public final static int NULLORDER = 0xffffffff;
+    public static final int NULLORDER = 0xffffffff;
 
-    // Android-removed: internal constructors.
+    // BEGIN Android-removed: internal constructors.
+    /*
+     * CollationElementIterator constructor.  This takes the source string and
+     * the collation object.  The cursor will walk thru the source string based
+     * on the predefined collation rules.  If the source string is empty,
+     * NULLORDER will be returned on the calls to next().
+     * @param sourceText the source string.
+     * @param owner the collation object.
+     *
+    CollationElementIterator(String sourceText, RuleBasedCollator owner) {
+        this.owner = owner;
+        ordering = owner.getTables();
+        if (!sourceText.isEmpty()) {
+            NormalizerBase.Mode mode =
+                CollatorUtilities.toNormalizerMode(owner.getDecomposition());
+            text = new NormalizerBase(sourceText, mode);
+        }
+    }
+    */
+    // END Android-removed: internal constructors.
 
     // Android-added: ICU iterator to delegate to.
     private android.icu.text.CollationElementIterator icuIterator;
@@ -179,7 +199,7 @@
      * @param order the collation element
      * @return the element's primary component
      */
-    public final static int primaryOrder(int order)
+    public static final int primaryOrder(int order)
     {
         // Android-changed: delegate to ICU CollationElementIterator.
         return android.icu.text.CollationElementIterator.primaryOrder(order);
@@ -189,7 +209,7 @@
      * @param order the collation element
      * @return the element's secondary component
      */
-    public final static short secondaryOrder(int order)
+    public static final short secondaryOrder(int order)
     {
         // Android-changed: delegate to ICU CollationElementIterator.
        return (short) android.icu.text.CollationElementIterator.secondaryOrder(order);
@@ -199,7 +219,7 @@
      * @param order the collation element
      * @return the element's tertiary component
      */
-    public final static short tertiaryOrder(int order)
+    public static final short tertiaryOrder(int order)
     {
         // Android-changed: delegate to ICU CollationElementIterator.
         return (short) android.icu.text.CollationElementIterator.tertiaryOrder(order);
@@ -286,5 +306,255 @@
         icuIterator.setText(source);
     }
 
-    // Android-removed: private helper methods and fields.
+    // BEGIN Android-removed: private helper methods and fields.
+    /*
+    //============================================================
+    // privates
+    //============================================================
+
+    /**
+     * Determine if a character is a Thai vowel (which sorts after
+     * its base consonant).
+     *
+    private static final boolean isThaiPreVowel(int ch) {
+        return (ch >= 0x0e40) && (ch <= 0x0e44);
+    }
+
+    /**
+     * Determine if a character is a Thai base consonant
+     *
+    private static final boolean isThaiBaseConsonant(int ch) {
+        return (ch >= 0x0e01) && (ch <= 0x0e2e);
+    }
+
+    /**
+     * Determine if a character is a Lao vowel (which sorts after
+     * its base consonant).
+     *
+    private static final boolean isLaoPreVowel(int ch) {
+        return (ch >= 0x0ec0) && (ch <= 0x0ec4);
+    }
+
+    /**
+     * Determine if a character is a Lao base consonant
+     *
+    private static final boolean isLaoBaseConsonant(int ch) {
+        return (ch >= 0x0e81) && (ch <= 0x0eae);
+    }
+
+    /**
+     * This method produces a buffer which contains the collation
+     * elements for the two characters, with colFirst's values preceding
+     * another character's.  Presumably, the other character precedes colFirst
+     * in logical order (otherwise you wouldn't need this method would you?).
+     * The assumption is that the other char's value(s) have already been
+     * computed.  If this char has a single element it is passed to this
+     * method as lastValue, and lastExpansion is null.  If it has an
+     * expansion it is passed in lastExpansion, and colLastValue is ignored.
+     *
+    private int[] makeReorderedBuffer(int colFirst,
+                                      int lastValue,
+                                      int[] lastExpansion,
+                                      boolean forward) {
+
+        int[] result;
+
+        int firstValue = ordering.getUnicodeOrder(colFirst);
+        if (firstValue >= RuleBasedCollator.CONTRACTCHARINDEX) {
+            firstValue = forward? nextContractChar(colFirst) : prevContractChar(colFirst);
+        }
+
+        int[] firstExpansion = null;
+        if (firstValue >= RuleBasedCollator.EXPANDCHARINDEX) {
+            firstExpansion = ordering.getExpandValueList(firstValue);
+        }
+
+        if (!forward) {
+            int temp1 = firstValue;
+            firstValue = lastValue;
+            lastValue = temp1;
+            int[] temp2 = firstExpansion;
+            firstExpansion = lastExpansion;
+            lastExpansion = temp2;
+        }
+
+        if (firstExpansion == null && lastExpansion == null) {
+            result = new int [2];
+            result[0] = firstValue;
+            result[1] = lastValue;
+        }
+        else {
+            int firstLength = firstExpansion==null? 1 : firstExpansion.length;
+            int lastLength = lastExpansion==null? 1 : lastExpansion.length;
+            result = new int[firstLength + lastLength];
+
+            if (firstExpansion == null) {
+                result[0] = firstValue;
+            }
+            else {
+                System.arraycopy(firstExpansion, 0, result, 0, firstLength);
+            }
+
+            if (lastExpansion == null) {
+                result[firstLength] = lastValue;
+            }
+            else {
+                System.arraycopy(lastExpansion, 0, result, firstLength, lastLength);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     *  Check if a comparison order is ignorable.
+     *  @return true if a character is ignorable, false otherwise.
+     *
+    static final boolean isIgnorable(int order)
+    {
+        return ((primaryOrder(order) == 0) ? true : false);
+    }
+
+    /**
+     * Get the ordering priority of the next contracting character in the
+     * string.
+     * @param ch the starting character of a contracting character token
+     * @return the next contracting character's ordering.  Returns NULLORDER
+     * if the end of string is reached.
+     *
+    private int nextContractChar(int ch)
+    {
+        // First get the ordering of this single character,
+        // which is always the first element in the list
+        Vector<EntryPair> list = ordering.getContractValues(ch);
+        EntryPair pair = list.firstElement();
+        int order = pair.value;
+
+        // find out the length of the longest contracting character sequence in the list.
+        // There's logic in the builder code to make sure the longest sequence is always
+        // the last.
+        pair = list.lastElement();
+        int maxLength = pair.entryName.length();
+
+        // (the Normalizer is cloned here so that the seeking we do in the next loop
+        // won't affect our real position in the text)
+        NormalizerBase tempText = (NormalizerBase)text.clone();
+
+        // extract the next maxLength characters in the string (we have to do this using the
+        // Normalizer to ensure that our offsets correspond to those the rest of the
+        // iterator is using) and store it in "fragment".
+        tempText.previous();
+        key.setLength(0);
+        int c = tempText.next();
+        while (maxLength > 0 && c != NormalizerBase.DONE) {
+            if (Character.isSupplementaryCodePoint(c)) {
+                key.append(Character.toChars(c));
+                maxLength -= 2;
+            } else {
+                key.append((char)c);
+                --maxLength;
+            }
+            c = tempText.next();
+        }
+        String fragment = key.toString();
+        // now that we have that fragment, iterate through this list looking for the
+        // longest sequence that matches the characters in the actual text.  (maxLength
+        // is used here to keep track of the length of the longest sequence)
+        // Upon exit from this loop, maxLength will contain the length of the matching
+        // sequence and order will contain the collation-element value corresponding
+        // to this sequence
+        maxLength = 1;
+        for (int i = list.size() - 1; i > 0; i--) {
+            pair = list.elementAt(i);
+            if (!pair.fwd)
+                continue;
+
+            if (fragment.startsWith(pair.entryName) && pair.entryName.length()
+                    > maxLength) {
+                maxLength = pair.entryName.length();
+                order = pair.value;
+            }
+        }
+
+        // seek our current iteration position to the end of the matching sequence
+        // and return the appropriate collation-element value (if there was no matching
+        // sequence, we're already seeked to the right position and order already contains
+        // the correct collation-element value for the single character)
+        while (maxLength > 1) {
+            c = text.next();
+            maxLength -= Character.charCount(c);
+        }
+        return order;
+    }
+
+    /**
+     * Get the ordering priority of the previous contracting character in the
+     * string.
+     * @param ch the starting character of a contracting character token
+     * @return the next contracting character's ordering.  Returns NULLORDER
+     * if the end of string is reached.
+     *
+    private int prevContractChar(int ch)
+    {
+        // This function is identical to nextContractChar(), except that we've
+        // switched things so that the next() and previous() calls on the Normalizer
+        // are switched and so that we skip entry pairs with the fwd flag turned on
+        // rather than off.  Notice that we still use append() and startsWith() when
+        // working on the fragment.  This is because the entry pairs that are used
+        // in reverse iteration have their names reversed already.
+        Vector<EntryPair> list = ordering.getContractValues(ch);
+        EntryPair pair = list.firstElement();
+        int order = pair.value;
+
+        pair = list.lastElement();
+        int maxLength = pair.entryName.length();
+
+        NormalizerBase tempText = (NormalizerBase)text.clone();
+
+        tempText.next();
+        key.setLength(0);
+        int c = tempText.previous();
+        while (maxLength > 0 && c != NormalizerBase.DONE) {
+            if (Character.isSupplementaryCodePoint(c)) {
+                key.append(Character.toChars(c));
+                maxLength -= 2;
+            } else {
+                key.append((char)c);
+                --maxLength;
+            }
+            c = tempText.previous();
+        }
+        String fragment = key.toString();
+
+        maxLength = 1;
+        for (int i = list.size() - 1; i > 0; i--) {
+            pair = list.elementAt(i);
+            if (pair.fwd)
+                continue;
+
+            if (fragment.startsWith(pair.entryName) && pair.entryName.length()
+                    > maxLength) {
+                maxLength = pair.entryName.length();
+                order = pair.value;
+            }
+        }
+
+        while (maxLength > 1) {
+            c = text.previous();
+            maxLength -= Character.charCount(c);
+        }
+        return order;
+    }
+
+    static final int UNMAPPEDCHARVALUE = 0x7FFF0000;
+
+    private NormalizerBase text = null;
+    private int[] buffer = null;
+    private int expIndex = 0;
+    private StringBuffer key = new StringBuffer(5);
+    private int swapOrder = 0;
+    private RBCollationTables ordering;
+    private RuleBasedCollator owner;
+    */
+    // END Android-removed: private helper methods and fields.
 }
diff --git a/ojluni/src/main/java/java/text/CollationKey.java b/ojluni/src/main/java/java/text/CollationKey.java
index d4c7751..318f3c4 100644
--- a/ojluni/src/main/java/java/text/CollationKey.java
+++ b/ojluni/src/main/java/java/text/CollationKey.java
@@ -95,6 +95,7 @@
  * @see          Collator
  * @see          RuleBasedCollator
  * @author       Helena Shih
+ * @since 1.1
  */
 
 public abstract class CollationKey implements Comparable<CollationKey> {
@@ -108,7 +109,7 @@
      * zero if this is greater than target.
      * @see java.text.Collator#compare
      */
-    abstract public int compareTo(CollationKey target);
+    public abstract int compareTo(CollationKey target);
 
     /**
      * Returns the String that this CollationKey represents.
@@ -128,7 +129,7 @@
      *
      * @return a byte array representation of the CollationKey
      */
-    abstract public byte[] toByteArray();
+    public abstract byte[] toByteArray();
 
 
   /**
@@ -145,5 +146,5 @@
         this.source = source;
     }
 
-    final private String source;
+    private final String source;
 }
diff --git a/ojluni/src/main/java/java/text/Collator.java b/ojluni/src/main/java/java/text/Collator.java
index e7fc8b7..b1e255c 100644
--- a/ojluni/src/main/java/java/text/Collator.java
+++ b/ojluni/src/main/java/java/text/Collator.java
@@ -83,7 +83,7 @@
  * comparisons. Four strengths are provided: <code>PRIMARY</code>,
  * <code>SECONDARY</code>, <code>TERTIARY</code>, and <code>IDENTICAL</code>.
  * The exact assignment of strengths to language features is
- * locale dependant.  For example, in Czech, "e" and "f" are considered
+ * locale dependent.  For example, in Czech, "e" and "f" are considered
  * primary differences, while "e" and "&#283;" are secondary differences,
  * "e" and "E" are tertiary differences and "e" and "e" are identical.
  * The following shows how both case and accents could be ignored for
@@ -118,6 +118,7 @@
  * @see         CollationElementIterator
  * @see         Locale
  * @author      Helena Shih, Laura Werner, Richard Gillam
+ * @since 1.1
  */
 
 public abstract class Collator
@@ -126,36 +127,36 @@
     /**
      * Collator strength value.  When set, only PRIMARY differences are
      * considered significant during comparison. The assignment of strengths
-     * to language features is locale dependant. A common example is for
+     * to language features is locale dependent. A common example is for
      * different base letters ("a" vs "b") to be considered a PRIMARY difference.
      * @see java.text.Collator#setStrength
      * @see java.text.Collator#getStrength
      */
-    public final static int PRIMARY = 0;
+    public static final int PRIMARY = 0;
     /**
      * Collator strength value.  When set, only SECONDARY and above differences are
      * considered significant during comparison. The assignment of strengths
-     * to language features is locale dependant. A common example is for
+     * to language features is locale dependent. A common example is for
      * different accented forms of the same base letter ("a" vs "\u00E4") to be
      * considered a SECONDARY difference.
      * @see java.text.Collator#setStrength
      * @see java.text.Collator#getStrength
      */
-    public final static int SECONDARY = 1;
+    public static final int SECONDARY = 1;
     /**
      * Collator strength value.  When set, only TERTIARY and above differences are
      * considered significant during comparison. The assignment of strengths
-     * to language features is locale dependant. A common example is for
+     * to language features is locale dependent. A common example is for
      * case differences ("a" vs "A") to be considered a TERTIARY difference.
      * @see java.text.Collator#setStrength
      * @see java.text.Collator#getStrength
      */
-    public final static int TERTIARY = 2;
+    public static final int TERTIARY = 2;
 
     /**
      * Collator strength value.  When set, all differences are
      * considered significant during comparison. The assignment of strengths
-     * to language features is locale dependant. A common example is for control
+     * to language features is locale dependent. A common example is for control
      * characters ("&#092;u0001" vs "&#092;u0002") to be considered equal at the
      * PRIMARY, SECONDARY, and TERTIARY levels but different at the IDENTICAL
      * level.  Additionally, differences between pre-composed accents such as
@@ -163,7 +164,7 @@
      * (A, combining-grave) will be considered significant at the IDENTICAL
      * level if decomposition is set to NO_DECOMPOSITION.
      */
-    public final static int IDENTICAL = 3;
+    public static final int IDENTICAL = 3;
 
     /**
      * Decomposition mode value. With NO_DECOMPOSITION
@@ -173,7 +174,7 @@
      * @see java.text.Collator#getDecomposition
      * @see java.text.Collator#setDecomposition
      */
-    public final static int NO_DECOMPOSITION = 0;
+    public static final int NO_DECOMPOSITION = 0;
 
     /**
      * Decomposition mode value. With CANONICAL_DECOMPOSITION
@@ -188,7 +189,7 @@
      * @see java.text.Collator#getDecomposition
      * @see java.text.Collator#setDecomposition
      */
-    public final static int CANONICAL_DECOMPOSITION = 1;
+    public static final int CANONICAL_DECOMPOSITION = 1;
 
     /**
      * Decomposition mode value. With FULL_DECOMPOSITION
@@ -207,7 +208,7 @@
      * @see java.text.Collator#getDecomposition
      * @see java.text.Collator#setDecomposition
      */
-    public final static int FULL_DECOMPOSITION = 2;
+    public static final int FULL_DECOMPOSITION = 2;
 
     /**
      * Gets the Collator for the current default locale.
@@ -475,7 +476,7 @@
      * Generates the hash code for this Collator.
      */
     @Override
-    abstract public int hashCode();
+    public abstract int hashCode();
 
     /**
      * Default constructor.  This constructor is
@@ -486,6 +487,8 @@
     protected Collator()
     {
         // Android-changed: Switched to ICU.
+        // strength = TERTIARY;
+        // decmp = CANONICAL_DECOMPOSITION;
         icuColl = android.icu.text.RuleBasedCollator.getInstance(Locale.getDefault());
     }
 
@@ -497,5 +500,34 @@
         this.icuColl = icuColl;
     }
 
-    // Android-removed: Fields and constants.
-}
+    // BEGIN Android-removed: Fields and constants.
+    /*
+    private int strength = 0;
+    private int decmp = 0;
+    private static final ConcurrentMap<Locale, SoftReference<Collator>> cache
+            = new ConcurrentHashMap<>();
+
+    //
+    // FIXME: These three constants should be removed.
+    //
+    /**
+     * LESS is returned if source string is compared to be less than target
+     * string in the compare() method.
+     * @see java.text.Collator#compare
+     *
+    static final int LESS = -1;
+    /**
+     * EQUAL is returned if source string is compared to be equal to target
+     * string in the compare() method.
+     * @see java.text.Collator#compare
+     *
+    static final int EQUAL = 0;
+    /**
+     * GREATER is returned if source string is compared to be greater than
+     * target string in the compare() method.
+     * @see java.text.Collator#compare
+     *
+    static final int GREATER = 1;
+    */
+    // END Android-removed: Fields and constants.
+ }
diff --git a/ojluni/src/main/java/java/text/DateFormat.java b/ojluni/src/main/java/java/text/DateFormat.java
index 8622c2f..40214bc 100644
--- a/ojluni/src/main/java/java/text/DateFormat.java
+++ b/ojluni/src/main/java/java/text/DateFormat.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,11 @@
 import java.util.TimeZone;
 import libcore.icu.ICU;
 
+// Android-removed: Remove javadoc related to "tz", "rg" and "ca" Locale extension.
+// The "tz" extension isn't supported until the Calendar class is upgraded to version 11.
+// The "ca" extension isn't supported, because Android's java.text supports Gregorian calendar only.
+// The "rg" extension isn't supported until https://unicode-org.atlassian.net/browse/ICU-21831
+// is resolved, because java.text.* stack relies on ICU on resource resolution.
 /**
  * {@code DateFormat} is an abstract class for date/time formatting subclasses which
  * formats and parses dates or time in a language-independent manner.
@@ -56,7 +61,6 @@
  * formatting (i.e., date &rarr; text), parsing (text &rarr; date), and
  * normalization.  The date is represented as a <code>Date</code> object or
  * as the milliseconds since January 1, 1970, 00:00:00 GMT.
- *
  * <p>{@code DateFormat} provides many class methods for obtaining default date/time
  * formatters based on the default or a given locale and a number of formatting
  * styles. The formatting styles include {@link #FULL}, {@link #LONG}, {@link #MEDIUM}, and {@link #SHORT}. More
@@ -93,6 +97,7 @@
  * DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
  * }</pre>
  * </blockquote>
+ *
  * <p>You can use a DateFormat to parse also.
  * <blockquote>
  * <pre>{@code
@@ -129,7 +134,7 @@
  * on the screen.
  * </ul>
  *
- * <h3><a name="synchronization">Synchronization</a></h3>
+ * <h3><a id="synchronization">Synchronization</a></h3>
  *
  * <p>
  * Date formats are not synchronized.
@@ -137,6 +142,25 @@
  * If multiple threads access a format concurrently, it must be synchronized
  * externally.
  *
+ * @implSpec
+ * <ul><li>The {@link #format(Date, StringBuffer, FieldPosition)} and
+ * {@link #parse(String, ParsePosition)} methods may throw
+ * {@code NullPointerException}, if any of their parameter is {@code null}.
+ * The subclass may provide its own implementation and specification about
+ * {@code NullPointerException}.</li>
+ * <li>The {@link #setCalendar(Calendar)}, {@link
+ * #setNumberFormat(NumberFormat)} and {@link #setTimeZone(TimeZone)} methods
+ * do not throw {@code NullPointerException} when their parameter is
+ * {@code null}, but any subsequent operations on the same instance may throw
+ * {@code NullPointerException}.</li>
+ * <li>The {@link #getCalendar()}, {@link #getNumberFormat()} and
+ * {@link getTimeZone()} methods may return {@code null}, if the respective
+ * values of this instance is set to {@code null} through the corresponding
+ * setter methods. For Example: {@link #getTimeZone()} may return {@code null},
+ * if the {@code TimeZone} value of this instance is set as
+ * {@link #setTimeZone(java.util.TimeZone) setTimeZone(null)}.</li>
+ * </ul>
+ *
  * @see          Format
  * @see          NumberFormat
  * @see          SimpleDateFormat
@@ -144,6 +168,7 @@
  * @see          java.util.GregorianCalendar
  * @see          java.util.TimeZone
  * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
+ * @since 1.1
  */
 public abstract class DateFormat extends Format {
 
@@ -171,127 +196,128 @@
      * Useful constant for ERA field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int ERA_FIELD = 0;
+    public static final int ERA_FIELD = 0;
     /**
      * Useful constant for YEAR field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int YEAR_FIELD = 1;
+    public static final int YEAR_FIELD = 1;
     /**
      * Useful constant for MONTH field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int MONTH_FIELD = 2;
+    public static final int MONTH_FIELD = 2;
     /**
      * Useful constant for DATE field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int DATE_FIELD = 3;
+    public static final int DATE_FIELD = 3;
     /**
      * Useful constant for one-based HOUR_OF_DAY field alignment.
      * Used in FieldPosition of date/time formatting.
      * HOUR_OF_DAY1_FIELD is used for the one-based 24-hour clock.
      * For example, 23:59 + 01:00 results in 24:59.
      */
-    public final static int HOUR_OF_DAY1_FIELD = 4;
+    public static final int HOUR_OF_DAY1_FIELD = 4;
     /**
      * Useful constant for zero-based HOUR_OF_DAY field alignment.
      * Used in FieldPosition of date/time formatting.
      * HOUR_OF_DAY0_FIELD is used for the zero-based 24-hour clock.
      * For example, 23:59 + 01:00 results in 00:59.
      */
-    public final static int HOUR_OF_DAY0_FIELD = 5;
+    public static final int HOUR_OF_DAY0_FIELD = 5;
     /**
      * Useful constant for MINUTE field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int MINUTE_FIELD = 6;
+    public static final int MINUTE_FIELD = 6;
     /**
      * Useful constant for SECOND field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int SECOND_FIELD = 7;
+    public static final int SECOND_FIELD = 7;
     /**
      * Useful constant for MILLISECOND field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int MILLISECOND_FIELD = 8;
+    public static final int MILLISECOND_FIELD = 8;
     /**
      * Useful constant for DAY_OF_WEEK field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int DAY_OF_WEEK_FIELD = 9;
+    public static final int DAY_OF_WEEK_FIELD = 9;
     /**
      * Useful constant for DAY_OF_YEAR field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int DAY_OF_YEAR_FIELD = 10;
+    public static final int DAY_OF_YEAR_FIELD = 10;
     /**
      * Useful constant for DAY_OF_WEEK_IN_MONTH field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
+    public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
     /**
      * Useful constant for WEEK_OF_YEAR field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int WEEK_OF_YEAR_FIELD = 12;
+    public static final int WEEK_OF_YEAR_FIELD = 12;
     /**
      * Useful constant for WEEK_OF_MONTH field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int WEEK_OF_MONTH_FIELD = 13;
+    public static final int WEEK_OF_MONTH_FIELD = 13;
     /**
      * Useful constant for AM_PM field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int AM_PM_FIELD = 14;
+    public static final int AM_PM_FIELD = 14;
     /**
      * Useful constant for one-based HOUR field alignment.
      * Used in FieldPosition of date/time formatting.
      * HOUR1_FIELD is used for the one-based 12-hour clock.
      * For example, 11:30 PM + 1 hour results in 12:30 AM.
      */
-    public final static int HOUR1_FIELD = 15;
+    public static final int HOUR1_FIELD = 15;
     /**
      * Useful constant for zero-based HOUR field alignment.
      * Used in FieldPosition of date/time formatting.
      * HOUR0_FIELD is used for the zero-based 12-hour clock.
      * For example, 11:30 PM + 1 hour results in 00:30 AM.
      */
-    public final static int HOUR0_FIELD = 16;
+    public static final int HOUR0_FIELD = 16;
     /**
      * Useful constant for TIMEZONE field alignment.
      * Used in FieldPosition of date/time formatting.
      */
-    public final static int TIMEZONE_FIELD = 17;
+    public static final int TIMEZONE_FIELD = 17;
 
     // Proclaim serial compatibility with 1.1 FCS
     private static final long serialVersionUID = 7218322306649953788L;
 
     /**
-     * Overrides Format.
-     * Formats a time object into a time string. Examples of time objects
-     * are a time value expressed in milliseconds and a Date object.
-     * @param obj must be a Number or a Date.
-     * @param toAppendTo the string buffer for the returning time string.
-     * @return the string buffer passed in as toAppendTo, with formatted text appended.
-     * @param fieldPosition keeps track of the position of the field
-     * within the returned string.
-     * On input: an alignment field,
-     * if desired. On output: the offsets of the alignment field. For
-     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
-     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
-     * begin index and end index of fieldPosition will be set to
-     * 0 and 4, respectively.
-     * Notice that if the same time field appears
-     * more than once in a pattern, the fieldPosition will be set for the first
-     * occurrence of that time field. For instance, formatting a Date to
-     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
-     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
-     * the begin index and end index of fieldPosition will be set to
-     * 5 and 8, respectively, for the first occurrence of the timezone
-     * pattern character 'z'.
+     * Formats the given {@code Object} into a date-time string. The formatted
+     * string is appended to the given {@code StringBuffer}.
+     *
+     * @param obj Must be a {@code Date} or a {@code Number} representing a
+     * millisecond offset from the <a href="../util/Calendar.html#Epoch">Epoch</a>.
+     * @param toAppendTo The string buffer for the returning date-time string.
+     * @param fieldPosition keeps track on the position of the field within
+     * the returned string. For example, given a date-time text
+     * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
+     * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
+     * {@code fieldPosition} will be set to 0 and 4, respectively.
+     * Notice that if the same date-time field appears more than once in a
+     * pattern, the {@code fieldPosition} will be set for the first occurrence
+     * of that date-time field. For instance, formatting a {@code Date} to the
+     * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
+     * pattern {@code "h a z (zzzz)"} and the alignment field
+     * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
+     * {@code fieldPosition} will be set to 5 and 8, respectively, for the
+     * first occurrence of the timezone pattern character {@code 'z'}.
+     * @return the string buffer passed in as {@code toAppendTo},
+     *         with formatted text appended.
+     * @exception IllegalArgumentException if the {@code Format} cannot format
+     *            the given {@code obj}.
      * @see java.text.Format
      */
     public final StringBuffer format(Object obj, StringBuffer toAppendTo,
@@ -307,34 +333,35 @@
     }
 
     /**
-     * Formats a Date into a date/time string.
-     * @param date a Date to be formatted into a date/time string.
-     * @param toAppendTo the string buffer for the returning date/time string.
-     * @param fieldPosition keeps track of the position of the field
-     * within the returned string.
-     * On input: an alignment field,
-     * if desired. On output: the offsets of the alignment field. For
-     * example, given a time text "1996.07.10 AD at 15:08:56 PDT",
-     * if the given fieldPosition is DateFormat.YEAR_FIELD, the
-     * begin index and end index of fieldPosition will be set to
-     * 0 and 4, respectively.
-     * Notice that if the same time field appears
-     * more than once in a pattern, the fieldPosition will be set for the first
-     * occurrence of that time field. For instance, formatting a Date to
-     * the time string "1 PM PDT (Pacific Daylight Time)" using the pattern
-     * "h a z (zzzz)" and the alignment field DateFormat.TIMEZONE_FIELD,
-     * the begin index and end index of fieldPosition will be set to
-     * 5 and 8, respectively, for the first occurrence of the timezone
-     * pattern character 'z'.
-     * @return the string buffer passed in as toAppendTo, with formatted text appended.
+     * Formats a {@link Date} into a date-time string. The formatted
+     * string is appended to the given {@code StringBuffer}.
+     *
+     * @param date a Date to be formatted into a date-time string.
+     * @param toAppendTo the string buffer for the returning date-time string.
+     * @param fieldPosition keeps track on the position of the field within
+     * the returned string. For example, given a date-time text
+     * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
+     * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
+     * {@code fieldPosition} will be set to 0 and 4, respectively.
+     * Notice that if the same date-time field appears more than once in a
+     * pattern, the {@code fieldPosition} will be set for the first occurrence
+     * of that date-time field. For instance, formatting a {@code Date} to the
+     * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
+     * pattern {@code "h a z (zzzz)"} and the alignment field
+     * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
+     * {@code fieldPosition} will be set to 5 and 8, respectively, for the
+     * first occurrence of the timezone pattern character {@code 'z'}.
+     * @return the string buffer passed in as {@code toAppendTo}, with formatted
+     * text appended.
      */
     public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
                                         FieldPosition fieldPosition);
 
     /**
-     * Formats a Date into a date/time string.
-     * @param date the time value to be formatted into a time string.
-     * @return the formatted time string.
+      * Formats a {@link Date} into a date-time string.
+      *
+      * @param date the time value to be formatted into a date-time string.
+      * @return the formatted date-time string.
      */
     public final String format(Date date)
     {
@@ -414,7 +441,7 @@
      *            index information as described above.
      * @return A <code>Date</code> parsed from the string. In case of
      *         error, returns null.
-     * @exception NullPointerException if <code>pos</code> is null.
+     * @throws NullPointerException if {@code source} or {@code pos} is null.
      */
     public Object parseObject(String source, ParsePosition pos) {
         return parse(source, pos);
@@ -451,7 +478,7 @@
      * @see java.util.Locale.Category#FORMAT
      * @return a time formatter.
      */
-    public final static DateFormat getTimeInstance()
+    public static final DateFormat getTimeInstance()
     {
         return get(DEFAULT, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
     }
@@ -468,7 +495,7 @@
      * SHORT for "h:mm a" in the US locale.
      * @return a time formatter.
      */
-    public final static DateFormat getTimeInstance(int style)
+    public static final DateFormat getTimeInstance(int style)
     {
         return get(style, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
     }
@@ -481,7 +508,7 @@
      * @param aLocale the given locale.
      * @return a time formatter.
      */
-    public final static DateFormat getTimeInstance(int style,
+    public static final DateFormat getTimeInstance(int style,
                                                  Locale aLocale)
     {
         return get(style, 0, 1, aLocale);
@@ -497,7 +524,7 @@
      * @see java.util.Locale.Category#FORMAT
      * @return a date formatter.
      */
-    public final static DateFormat getDateInstance()
+    public static final DateFormat getDateInstance()
     {
         return get(0, DEFAULT, 2, Locale.getDefault(Locale.Category.FORMAT));
     }
@@ -514,7 +541,7 @@
      * SHORT for "M/d/yy" in the US locale.
      * @return a date formatter.
      */
-    public final static DateFormat getDateInstance(int style)
+    public static final DateFormat getDateInstance(int style)
     {
         return get(0, style, 2, Locale.getDefault(Locale.Category.FORMAT));
     }
@@ -527,7 +554,7 @@
      * @param aLocale the given locale.
      * @return a date formatter.
      */
-    public final static DateFormat getDateInstance(int style,
+    public static final DateFormat getDateInstance(int style,
                                                  Locale aLocale)
     {
         return get(0, style, 2, aLocale);
@@ -543,7 +570,7 @@
      * @see java.util.Locale.Category#FORMAT
      * @return a date/time formatter.
      */
-    public final static DateFormat getDateTimeInstance()
+    public static final DateFormat getDateTimeInstance()
     {
         return get(DEFAULT, DEFAULT, 3, Locale.getDefault(Locale.Category.FORMAT));
     }
@@ -562,7 +589,7 @@
      * SHORT for "h:mm a" in the US locale.
      * @return a date/time formatter.
      */
-    public final static DateFormat getDateTimeInstance(int dateStyle,
+    public static final DateFormat getDateTimeInstance(int dateStyle,
                                                        int timeStyle)
     {
         return get(timeStyle, dateStyle, 3, Locale.getDefault(Locale.Category.FORMAT));
@@ -576,7 +603,7 @@
      * @param aLocale the given locale.
      * @return a date/time formatter.
      */
-    public final static DateFormat
+    public static final DateFormat
         getDateTimeInstance(int dateStyle, int timeStyle, Locale aLocale)
     {
         return get(timeStyle, dateStyle, 3, aLocale);
@@ -588,7 +615,7 @@
      *
      * @return a date/time formatter
      */
-    public final static DateFormat getInstance() {
+    public static final DateFormat getInstance() {
         return getDateTimeInstance(SHORT, SHORT);
     }
 
@@ -946,107 +973,107 @@
         /**
          * Constant identifying the era field.
          */
-        public final static Field ERA = new Field("era", Calendar.ERA);
+        public static final Field ERA = new Field("era", Calendar.ERA);
 
         /**
          * Constant identifying the year field.
          */
-        public final static Field YEAR = new Field("year", Calendar.YEAR);
+        public static final Field YEAR = new Field("year", Calendar.YEAR);
 
         /**
          * Constant identifying the month field.
          */
-        public final static Field MONTH = new Field("month", Calendar.MONTH);
+        public static final Field MONTH = new Field("month", Calendar.MONTH);
 
         /**
          * Constant identifying the day of month field.
          */
-        public final static Field DAY_OF_MONTH = new
+        public static final Field DAY_OF_MONTH = new
                             Field("day of month", Calendar.DAY_OF_MONTH);
 
         /**
          * Constant identifying the hour of day field, where the legal values
          * are 1 to 24.
          */
-        public final static Field HOUR_OF_DAY1 = new Field("hour of day 1",-1);
+        public static final Field HOUR_OF_DAY1 = new Field("hour of day 1",-1);
 
         /**
          * Constant identifying the hour of day field, where the legal values
          * are 0 to 23.
          */
-        public final static Field HOUR_OF_DAY0 = new
+        public static final Field HOUR_OF_DAY0 = new
                Field("hour of day", Calendar.HOUR_OF_DAY);
 
         /**
          * Constant identifying the minute field.
          */
-        public final static Field MINUTE =new Field("minute", Calendar.MINUTE);
+        public static final Field MINUTE =new Field("minute", Calendar.MINUTE);
 
         /**
          * Constant identifying the second field.
          */
-        public final static Field SECOND =new Field("second", Calendar.SECOND);
+        public static final Field SECOND =new Field("second", Calendar.SECOND);
 
         /**
          * Constant identifying the millisecond field.
          */
-        public final static Field MILLISECOND = new
+        public static final Field MILLISECOND = new
                 Field("millisecond", Calendar.MILLISECOND);
 
         /**
          * Constant identifying the day of week field.
          */
-        public final static Field DAY_OF_WEEK = new
+        public static final Field DAY_OF_WEEK = new
                 Field("day of week", Calendar.DAY_OF_WEEK);
 
         /**
          * Constant identifying the day of year field.
          */
-        public final static Field DAY_OF_YEAR = new
+        public static final Field DAY_OF_YEAR = new
                 Field("day of year", Calendar.DAY_OF_YEAR);
 
         /**
          * Constant identifying the day of week field.
          */
-        public final static Field DAY_OF_WEEK_IN_MONTH =
+        public static final Field DAY_OF_WEEK_IN_MONTH =
                      new Field("day of week in month",
                                             Calendar.DAY_OF_WEEK_IN_MONTH);
 
         /**
          * Constant identifying the week of year field.
          */
-        public final static Field WEEK_OF_YEAR = new
+        public static final Field WEEK_OF_YEAR = new
               Field("week of year", Calendar.WEEK_OF_YEAR);
 
         /**
          * Constant identifying the week of month field.
          */
-        public final static Field WEEK_OF_MONTH = new
+        public static final Field WEEK_OF_MONTH = new
             Field("week of month", Calendar.WEEK_OF_MONTH);
 
         /**
          * Constant identifying the time of day indicator
          * (e.g. "a.m." or "p.m.") field.
          */
-        public final static Field AM_PM = new
+        public static final Field AM_PM = new
                             Field("am pm", Calendar.AM_PM);
 
         /**
          * Constant identifying the hour field, where the legal values are
          * 1 to 12.
          */
-        public final static Field HOUR1 = new Field("hour 1", -1);
+        public static final Field HOUR1 = new Field("hour 1", -1);
 
         /**
          * Constant identifying the hour field, where the legal values are
          * 0 to 11.
          */
-        public final static Field HOUR0 = new
+        public static final Field HOUR0 = new
                             Field("hour", Calendar.HOUR);
 
         /**
          * Constant identifying the time zone field.
          */
-        public final static Field TIME_ZONE = new Field("time zone", -1);
+        public static final Field TIME_ZONE = new Field("time zone", -1);
     }
 }
diff --git a/ojluni/src/main/java/java/text/DateFormatSymbols.java b/ojluni/src/main/java/java/text/DateFormatSymbols.java
index de10644..ba7464e 100644
--- a/ojluni/src/main/java/java/text/DateFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DateFormatSymbols.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,9 @@
 import libcore.icu.LocaleData;
 import libcore.icu.TimeZoneNames;
 
+// Android-removed: Remove javadoc related to "rg" Locale extension.
+// The "rg" extension isn't supported until https://unicode-org.atlassian.net/browse/ICU-21831
+// is resolved, because java.text.* stack relies on ICU on resource resolution.
 /**
  * <code>DateFormatSymbols</code> is a public class for encapsulating
  * localizable date-time formatting data, such as the names of the
@@ -98,6 +101,7 @@
  * @see          SimpleDateFormat
  * @see          java.util.SimpleTimeZone
  * @author       Chen-Lieh Huang
+ * @since 1.1
  */
 public class DateFormatSymbols implements Serializable, Cloneable {
 
@@ -213,7 +217,7 @@
      * </ul>
      * The zone ID is <em>not</em> localized; it's one of the valid IDs of
      * the {@link java.util.TimeZone TimeZone} class that are not
-     * <a href="../java/util/TimeZone.html#CustomID">custom IDs</a>.
+     * <a href="../util/TimeZone.html#CustomID">custom IDs</a>.
      * All other entries are localized names.
      * @see java.util.TimeZone
      * @serial
@@ -468,6 +472,12 @@
 
     /**
      * Gets month strings. For example: "January", "February", etc.
+     * An array with either 12 or 13 elements will be returned depending
+     * on whether or not {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER}
+     * is supported. Use
+     * {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
+     * etc. to index the result array.
      *
      * <p>If the language requires different forms for formatting and
      * stand-alone usages, this method returns month names in the
@@ -479,6 +489,8 @@
      * Calendar Elements in the Unicode Locale Data Markup Language
      * (LDML) specification</a> for more details.
      *
+     * @implSpec This method returns 13 elements since
+     * {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER} is supported.
      * @return the month strings.
      */
     public String[] getMonths() {
@@ -487,7 +499,9 @@
 
     /**
      * Sets month strings. For example: "January", "February", etc.
-     * @param newMonths the new month strings.
+     * @param newMonths the new month strings. The array should
+     * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
      */
     public void setMonths(String[] newMonths) {
         months = Arrays.copyOf(newMonths, newMonths.length);
@@ -496,9 +510,15 @@
 
     /**
      * Gets short month strings. For example: "Jan", "Feb", etc.
+     * An array with either 12 or 13 elements will be returned depending
+     * on whether or not {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER}
+     * is supported. Use
+     * {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY},
+     * etc. to index the result array.
      *
      * <p>If the language requires different forms for formatting and
-     * stand-alone usages, This method returns short month names in
+     * stand-alone usages, this method returns short month names in
      * the formatting form. For example, the preferred abbreviation
      * for January in the Catalan language is <em>de gen.</em> in the
      * formatting form, while it is <em>gen.</em> in the stand-alone
@@ -507,6 +527,8 @@
      * Calendar Elements in the Unicode Locale Data Markup Language
      * (LDML) specification</a> for more details.
      *
+     * @implSpec This method returns 13 elements since
+     * {@link java.util.Calendar#UNDECIMBER Calendar.UNDECIMBER} is supported.
      * @return the short month strings.
      */
     public String[] getShortMonths() {
@@ -515,7 +537,9 @@
 
     /**
      * Sets short month strings. For example: "Jan", "Feb", etc.
-     * @param newShortMonths the new short month strings.
+     * @param newShortMonths the new short month strings. The array should
+     * be indexed by {@link java.util.Calendar#JANUARY Calendar.JANUARY},
+     * {@link java.util.Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
      */
     public void setShortMonths(String[] newShortMonths) {
         shortMonths = Arrays.copyOf(newShortMonths, newShortMonths.length);
@@ -524,8 +548,10 @@
 
     /**
      * Gets weekday strings. For example: "Sunday", "Monday", etc.
-     * @return the weekday strings. Use <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc. to index the result array.
+     * @return the weekday strings. Use
+     * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index
+     * the result array.
      */
     public String[] getWeekdays() {
         return Arrays.copyOf(weekdays, weekdays.length);
@@ -534,8 +560,8 @@
     /**
      * Sets weekday strings. For example: "Sunday", "Monday", etc.
      * @param newWeekdays the new weekday strings. The array should
-     * be indexed by <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc.
+     * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc.
      */
     public void setWeekdays(String[] newWeekdays) {
         weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
@@ -544,8 +570,10 @@
 
     /**
      * Gets short weekday strings. For example: "Sun", "Mon", etc.
-     * @return the short weekday strings. Use <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc. to index the result array.
+     * @return the short weekday strings. Use
+     * {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc. to index
+     * the result array.
      */
     public String[] getShortWeekdays() {
         return Arrays.copyOf(shortWeekdays, shortWeekdays.length);
@@ -554,8 +582,8 @@
     /**
      * Sets short weekday strings. For example: "Sun", "Mon", etc.
      * @param newShortWeekdays the new short weekday strings. The array should
-     * be indexed by <code>Calendar.SUNDAY</code>,
-     * <code>Calendar.MONDAY</code>, etc.
+     * be indexed by {@link java.util.Calendar#SUNDAY Calendar.SUNDAY},
+     * {@link java.util.Calendar#MONDAY Calendar.MONDAY}, etc.
      */
     public void setShortWeekdays(String[] newShortWeekdays) {
         shortWeekdays = Arrays.copyOf(newShortWeekdays, newShortWeekdays.length);
@@ -750,7 +778,9 @@
             // Android-changed: Don't include zone strings in hashCode to avoid populating it.
             // hashCode = 11 * hashCode + Arrays.deepHashCode(getZoneStringsWrapper());
             hashCode = 11 * hashCode + Objects.hashCode(localPatternChars);
-            cachedHashCode = hashCode;
+            if (hashCode != 0) {
+                cachedHashCode = hashCode;
+            }
         }
 
         return hashCode;
@@ -805,12 +835,12 @@
     private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
         = new ConcurrentHashMap<>(3);
 
-    private transient int lastZoneIndex = 0;
+    private transient int lastZoneIndex;
 
     /**
      * Cached hash code
      */
-    transient volatile int cachedHashCode = 0;
+    transient volatile int cachedHashCode;
 
     // Android-changed: update comment to describe local modification.
     /**
diff --git a/ojluni/src/main/java/java/text/DecimalFormat.java b/ojluni/src/main/java/java/text/DecimalFormat.java
index 1dc430c..34d1d63 100644
--- a/ojluni/src/main/java/java/text/DecimalFormat.java
+++ b/ojluni/src/main/java/java/text/DecimalFormat.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,7 @@
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import libcore.icu.DecimalFormatData;
 import libcore.icu.LocaleData;
 import android.icu.math.MathContext;
 
@@ -172,75 +173,79 @@
  * are not localized.
  *
  * <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0 summary="Chart showing symbol,
- *  location, localized, and meaning.">
- *     <tr style="background-color: rgb(204, 204, 255);">
- *          <th align=left>Symbol
- *          <th align=left>Location
- *          <th align=left>Localized?
- *          <th align=left>Meaning
- *     <tr valign=top>
- *          <td><code>0</code>
+ * <table class="striped">
+ * <caption style="display:none">Chart showing symbol, location, localized, and meaning.</caption>
+ * <thead>
+ *     <tr>
+ *          <th scope="col" style="text-align:left">Symbol
+ *          <th scope="col" style="text-align:left">Location
+ *          <th scope="col" style="text-align:left">Localized?
+ *          <th scope="col" style="text-align:left">Meaning
+ * </thead>
+ * <tbody>
+ *     <tr style="vertical-align:top">
+ *          <th scope="row"><code>0</code>
  *          <td>Number
  *          <td>Yes
  *          <td>Digit
- *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *          <td><code>#</code>
+ *     <tr style="vertical-align: top">
+ *          <th scope="row"><code>#</code>
  *          <td>Number
  *          <td>Yes
  *          <td>Digit, zero shows as absent
- *     <tr valign=top>
- *          <td><code>.</code>
+ *     <tr style="vertical-align:top">
+ *          <th scope="row"><code>.</code>
  *          <td>Number
  *          <td>Yes
  *          <td>Decimal separator or monetary decimal separator
- *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *          <td><code>-</code>
+ *     <tr style="vertical-align: top">
+ *          <th scope="row"><code>-</code>
  *          <td>Number
  *          <td>Yes
  *          <td>Minus sign
- *     <tr valign=top>
- *          <td><code>,</code>
+ *     <tr style="vertical-align:top">
+ *          <th scope="row"><code>,</code>
  *          <td>Number
  *          <td>Yes
  *          <td>Grouping separator
- *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *          <td><code>E</code>
+ *     <tr style="vertical-align: top">
+ *          <th scope="row"><code>E</code>
  *          <td>Number
  *          <td>Yes
  *          <td>Separates mantissa and exponent in scientific notation.
  *              <em>Need not be quoted in prefix or suffix.</em>
- *     <tr valign=top>
- *          <td><code>;</code>
+ *     <tr style="vertical-align:top">
+ *          <th scope="row"><code>;</code>
  *          <td>Subpattern boundary
  *          <td>Yes
  *          <td>Separates positive and negative subpatterns
- *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *          <td><code>%</code>
+ *     <tr style="vertical-align: top">
+ *          <th scope="row"><code>%</code>
  *          <td>Prefix or suffix
  *          <td>Yes
  *          <td>Multiply by 100 and show as percentage
- *     <tr valign=top>
- *          <td><code>&#92;u2030</code>
+ *     <tr style="vertical-align:top">
+ *          <th scope="row"><code>&#92;u2030</code>
  *          <td>Prefix or suffix
  *          <td>Yes
  *          <td>Multiply by 1000 and show as per mille value
- *     <tr style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *          <td><code>&#164;</code> (<code>&#92;u00A4</code>)
+ *     <tr style="vertical-align: top">
+ *          <th scope="row"><code>&#164;</code> (<code>&#92;u00A4</code>)
  *          <td>Prefix or suffix
  *          <td>No
  *          <td>Currency sign, replaced by currency symbol.  If
  *              doubled, replaced by international currency symbol.
  *              If present in a pattern, the monetary decimal separator
  *              is used instead of the decimal separator.
- *     <tr valign=top>
- *          <td><code>'</code>
+ *     <tr style="vertical-align:top">
+ *          <th scope="row"><code>'</code>
  *          <td>Prefix or suffix
  *          <td>No
  *          <td>Used to quote special characters in a prefix or suffix,
  *              for example, <code>"'#'#"</code> formats 123 to
  *              <code>"#123"</code>.  To create a single quote
  *              itself, use two in a row: <code>"# o''clock"</code>.
+ * </tbody>
  * </table>
  * </blockquote>
  *
@@ -327,7 +332,7 @@
  * and <code>isParseIntegerOnly()</code> are false.
  * </ul>
  *
- * <h4><a name="synchronization">Synchronization</a></h4>
+ * <h4><a id="synchronization">Synchronization</a></h4>
  *
  * <p>
  * Decimal formats are generally not synchronized.
@@ -371,12 +376,13 @@
  * }
  * }</pre></blockquote>
  *
- * @see          <a href="https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
+ * @see          <a href="http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html">Java Tutorial</a>
  * @see          NumberFormat
  * @see          DecimalFormatSymbols
  * @see          ParsePosition
  * @author       Mark Davis
  * @author       Alan Liu
+ * @since 1.1
  */
 public class DecimalFormat extends NumberFormat {
 
@@ -415,7 +421,7 @@
         }
         String[] all = adapter.getLocaleResources(def).getNumberPatterns();
         */
-        String pattern = LocaleData.get(def).numberPattern;
+        String pattern = DecimalFormatData.getInstance(def).getNumberPattern();
         // END Android-changed: Use ICU LocaleData. Remove SPI LocaleProviderAdapter.
 
         // Always applyPattern after the symbols are set
@@ -608,8 +614,14 @@
      * @param number     the number to format
      * @param toAppendTo the <code>StringBuffer</code> to which the formatted
      *                   text is to be appended
-     * @param pos        On input: an alignment field, if desired.
-     *                   On output: the offsets of the alignment field.
+     * @param pos        keeps track on the position of the field within the
+     *                   returned string. For example, for formatting a number
+     *                   {@code 1234567.89} in {@code Locale.US} locale,
+     *                   if the given {@code fieldPosition} is
+     *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                   and end index of {@code fieldPosition} will be set
+     *                   to 0 and 9, respectively for the output string
+     *                   {@code 1,234,567.89}.
      * @return           the value passed in as <code>toAppendTo</code>
      * @exception        IllegalArgumentException if <code>number</code> is
      *                   null or not an instance of <code>Number</code>.
@@ -645,8 +657,16 @@
      * Formats a double to produce a string.
      * @param number    The double to format
      * @param result    where the text is to be appended
-     * @param fieldPosition    On input: an alignment field, if desired.
-     * On output: the offsets of the alignment field.
+     * @param fieldPosition    keeps track on the position of the field within
+     *                         the returned string. For example, for formatting
+     *                         a number {@code 1234567.89} in {@code Locale.US}
+     *                         locale, if the given {@code fieldPosition} is
+     *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                         and end index of {@code fieldPosition} will be set
+     *                         to 0 and 9, respectively for the output string
+     *                         {@code 1,234,567.89}.
+     * @exception NullPointerException if {@code result} or
+     *            {@code fieldPosition} is {@code null}
      * @exception ArithmeticException if rounding is needed with rounding
      *            mode being set to RoundingMode.UNNECESSARY
      * @return The formatted number string
@@ -778,8 +798,16 @@
      * Format a long to produce a string.
      * @param number    The long to format
      * @param result    where the text is to be appended
-     * @param fieldPosition    On input: an alignment field, if desired.
-     * On output: the offsets of the alignment field.
+     * @param fieldPosition    keeps track on the position of the field within
+     *                         the returned string. For example, for formatting
+     *                         a number {@code 123456789} in {@code Locale.US}
+     *                         locale, if the given {@code fieldPosition} is
+     *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                         and end index of {@code fieldPosition} will be set
+     *                         to 0 and 11, respectively for the output string
+     *                         {@code 123,456,789}.
+     * @exception       NullPointerException if {@code result} or
+     *                  {@code fieldPosition} is {@code null}
      * @exception       ArithmeticException if rounding is needed with rounding
      *                  mode being set to RoundingMode.UNNECESSARY
      * @return The formatted number string
@@ -881,8 +909,14 @@
      * Formats a BigDecimal to produce a string.
      * @param number    The BigDecimal to format
      * @param result    where the text is to be appended
-     * @param fieldPosition    On input: an alignment field, if desired.
-     * On output: the offsets of the alignment field.
+     * @param fieldPosition    keeps track on the position of the field within
+     *                         the returned string. For example, for formatting
+     *                         a number {@code 1234567.89} in {@code Locale.US}
+     *                         locale, if the given {@code fieldPosition} is
+     *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                         and end index of {@code fieldPosition} will be set
+     *                         to 0 and 9, respectively for the output string
+     *                         {@code 1,234,567.89}.
      * @return The formatted number string
      * @exception        ArithmeticException if rounding is needed with rounding
      *                   mode being set to RoundingMode.UNNECESSARY
@@ -949,8 +983,14 @@
      * Format a BigInteger to produce a string.
      * @param number    The BigInteger to format
      * @param result    where the text is to be appended
-     * @param fieldPosition    On input: an alignment field, if desired.
-     * On output: the offsets of the alignment field.
+     * @param fieldPosition    keeps track on the position of the field within
+     *                         the returned string. For example, for formatting
+     *                         a number {@code 123456789} in {@code Locale.US}
+     *                         locale, if the given {@code fieldPosition} is
+     *                         {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                         and end index of {@code fieldPosition} will be set
+     *                         to 0 and 11, respectively for the output string
+     *                         {@code 123,456,789}.
      * @return The formatted number string
      * @exception        ArithmeticException if rounding is needed with rounding
      *                   mode being set to RoundingMode.UNNECESSARY
@@ -1200,7 +1240,8 @@
      *     Decimal  : min = 0. max = 3.
      *
      *
-    private void checkAndSetFastPathStatus() {
+     *
+    private boolean checkAndSetFastPathStatus() {
 
         boolean fastPathWasOn = isFastPath;
 
@@ -1230,12 +1271,27 @@
         } else
             isFastPath = false;
 
+        resetFastPathData(fastPathWasOn);
+        fastPathCheckNeeded = false;
+
+        /*
+         * Returns true after successfully checking the fast path condition and
+         * setting the fast path data. The return value is used by the
+         * fastFormat() method to decide whether to call the resetFastPathData
+         * method to reinitialize fast path data or is it already initialized
+         * in this method.
+         *
+        return true;
+    }
+
+    private void resetFastPathData(boolean fastPathWasOn) {
         // Since some instance properties may have changed while still falling
         // in the fast-path case, we need to reinitialize fastPathData anyway.
         if (isFastPath) {
             // We need to instantiate fastPathData if not already done.
-            if (fastPathData == null)
+            if (fastPathData == null) {
                 fastPathData = new FastPathData();
+            }
 
             // Sets up the locale specific constants used when formatting.
             // '0' is our default representation of zero.
@@ -1243,22 +1299,25 @@
             fastPathData.groupingChar = symbols.getGroupingSeparator();
 
             // Sets up fractional constants related to currency/decimal pattern.
-            fastPathData.fractionalMaxIntBound = (isCurrencyFormat) ? 99 : 999;
-            fastPathData.fractionalScaleFactor = (isCurrencyFormat) ? 100.0d : 1000.0d;
+            fastPathData.fractionalMaxIntBound = (isCurrencyFormat)
+                    ? 99 : 999;
+            fastPathData.fractionalScaleFactor = (isCurrencyFormat)
+                    ? 100.0d : 1000.0d;
 
             // Records the need for adding prefix or suffix
-            fastPathData.positiveAffixesRequired =
-                (positivePrefix.length() != 0) || (positiveSuffix.length() != 0);
-            fastPathData.negativeAffixesRequired =
-                (negativePrefix.length() != 0) || (negativeSuffix.length() != 0);
+            fastPathData.positiveAffixesRequired
+                    = !positivePrefix.isEmpty() || !positiveSuffix.isEmpty();
+            fastPathData.negativeAffixesRequired
+                    = !negativePrefix.isEmpty() || !negativeSuffix.isEmpty();
 
             // Creates a cached char container for result, with max possible size.
             int maxNbIntegralDigits = 10;
             int maxNbGroups = 3;
-            int containerSize =
-                Math.max(positivePrefix.length(), negativePrefix.length()) +
-                maxNbIntegralDigits + maxNbGroups + 1 + maximumFractionDigits +
-                Math.max(positiveSuffix.length(), negativeSuffix.length());
+            int containerSize
+                    = Math.max(positivePrefix.length(), negativePrefix.length())
+                    + maxNbIntegralDigits + maxNbGroups + 1
+                    + maximumFractionDigits
+                    + Math.max(positiveSuffix.length(), negativeSuffix.length());
 
             fastPathData.fastPathContainer = new char[containerSize];
 
@@ -1270,17 +1329,18 @@
 
             // Sets up fixed index positions for integral and fractional digits.
             // Sets up decimal point in cached result container.
-            int longestPrefixLength =
-                Math.max(positivePrefix.length(), negativePrefix.length());
-            int decimalPointIndex =
-                maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
+            int longestPrefixLength
+                    = Math.max(positivePrefix.length(),
+                            negativePrefix.length());
+            int decimalPointIndex
+                    = maxNbIntegralDigits + maxNbGroups + longestPrefixLength;
 
-            fastPathData.integralLastIndex    = decimalPointIndex - 1;
+            fastPathData.integralLastIndex = decimalPointIndex - 1;
             fastPathData.fractionalFirstIndex = decimalPointIndex + 1;
-            fastPathData.fastPathContainer[decimalPointIndex] =
-                isCurrencyFormat ?
-                symbols.getMonetaryDecimalSeparator() :
-                symbols.getDecimalSeparator();
+            fastPathData.fastPathContainer[decimalPointIndex]
+                    = isCurrencyFormat
+                            ? symbols.getMonetaryDecimalSeparator()
+                            : symbols.getDecimalSeparator();
 
         } else if (fastPathWasOn) {
             // Previous state was fast-path and is no more.
@@ -1291,8 +1351,6 @@
             fastPathData.charsPositivePrefix = null;
             fastPathData.charsNegativePrefix = null;
         }
-
-        fastPathCheckNeeded = false;
     }
 
     /**
@@ -1786,9 +1844,11 @@
      * @return the formatted result for {@code d} as a string.
      *
     String fastFormat(double d) {
+        boolean isDataSet = false;
         // (Re-)Evaluates fast-path status if needed.
-        if (fastPathCheckNeeded)
-            checkAndSetFastPathStatus();
+        if (fastPathCheckNeeded) {
+            isDataSet = checkAndSetFastPathStatus();
+        }
 
         if (!isFastPath )
             // DecimalFormat instance is not in a fast-path state.
@@ -1812,9 +1872,21 @@
         if (d > MAX_INT_AS_DOUBLE)
             // Filters out values that are outside expected fast-path range
             return null;
-        else
+        else {
+            if (!isDataSet) {
+                /*
+                 * If the fast path data is not set through
+                 * checkAndSetFastPathStatus() and fulfil the
+                 * fast path conditions then reset the data
+                 * directly through resetFastPathData()
+                 *
+                resetFastPathData(isFastPath);
+            }
             fastDoubleFormat(d, negative);
 
+        }
+
+
         // Returns a new string from updated fastPathContainer.
         return new String(fastPathData.fastPathContainer,
                           fastPathData.firstUsedIndex,
@@ -2150,7 +2222,7 @@
                         Format.Field signAttribute) {
         int start = result.length();
 
-        if (string.length() > 0) {
+        if (!string.isEmpty()) {
             result.append(string);
             for (int counter = 0, max = positions.length; counter < max;
                  counter++) {
@@ -2233,7 +2305,7 @@
         // special case NaN
         if (text.regionMatches(pos.index, symbols.getNaN(), 0, symbols.getNaN().length())) {
             pos.index = pos.index + symbols.getNaN().length();
-            return new Double(Double.NaN);
+            return Double.valueOf(Double.NaN);
         }
 
         boolean[] status = new boolean[STATUS_LENGTH];
@@ -2244,19 +2316,19 @@
         // special case INFINITY
         if (status[STATUS_INFINITE]) {
             if (status[STATUS_POSITIVE] == (multiplier >= 0)) {
-                return new Double(Double.POSITIVE_INFINITY);
+                return Double.valueOf(Double.POSITIVE_INFINITY);
             } else {
-                return new Double(Double.NEGATIVE_INFINITY);
+                return Double.valueOf(Double.NEGATIVE_INFINITY);
             }
         }
 
         if (multiplier == 0) {
             if (digitList.isZero()) {
-                return new Double(Double.NaN);
+                return Double.valueOf(Double.NaN);
             } else if (status[STATUS_POSITIVE]) {
-                return new Double(Double.POSITIVE_INFINITY);
+                return Double.valueOf(Double.POSITIVE_INFINITY);
             } else {
-                return new Double(Double.NEGATIVE_INFINITY);
+                return Double.valueOf(Double.NEGATIVE_INFINITY);
             }
         }
 
@@ -2330,8 +2402,8 @@
                             !isParseIntegerOnly();
             }
 
-            return gotDouble ?
-                (Number)new Double(doubleResult) : (Number)new Long(longResult);
+            // cast inside of ?: because of binary numeric promotion, JLS 15.25
+            return gotDouble ? (Number)doubleResult : (Number)longResult;
         }
         */
         if (pos.index < 0 || pos.index >= text.length()) {
@@ -3306,7 +3378,7 @@
                     } else {
                         string = symbols.getCurrencySymbol();
                     }
-                    if (string.length() > 0) {
+                    if (!string.isEmpty()) {
                         if (positions == null) {
                             positions = new ArrayList<>(2);
                         }
@@ -3603,13 +3675,6 @@
         isCurrencyFormat = false;
         useExponentialNotation = false;
 
-        // Two variables are used to record the subrange of the pattern
-        // occupied by phase 1.  This is used during the processing of the
-        // second pattern (the one representing negative numbers) to ensure
-        // that no deviation exists in phase 1 between the two patterns.
-        int phaseOneStart = 0;
-        int phaseOneLength = 0;
-
         int start = 0;
         for (int j = 1; j >= 0 && start < pattern.length(); --j) {
             boolean inQuote = false;
@@ -3660,9 +3725,6 @@
                             ch == groupingSeparator ||
                             ch == decimalSeparator) {
                             phase = 1;
-                            if (j == 1) {
-                                phaseOneStart = pos;
-                            }
                             --pos; // Reprocess this character
                             continue;
                         } else if (ch == CURRENCY_SIGN) {
@@ -3733,17 +3795,29 @@
                     break;
 
                 case 1:
-                    // Phase one must be identical in the two sub-patterns. We
-                    // enforce this by doing a direct comparison. While
-                    // processing the first sub-pattern, we just record its
-                    // length. While processing the second, we compare
-                    // characters.
-                    if (j == 1) {
-                        ++phaseOneLength;
-                    } else {
-                        if (--phaseOneLength == 0) {
-                            phase = 2;
-                            affix = suffix;
+                    // The negative subpattern (j = 0) serves only to specify the
+                    // negative prefix and suffix, so all the phase 1 characters
+                    // e.g. digits, zeroDigit, groupingSeparator,
+                    // decimalSeparator, exponent are ignored
+                    if (j == 0) {
+                        while (pos < pattern.length()) {
+                            char negPatternChar = pattern.charAt(pos);
+                            if (negPatternChar == digit
+                                    || negPatternChar == zeroDigit
+                                    || negPatternChar == groupingSeparator
+                                    || negPatternChar == decimalSeparator) {
+                                ++pos;
+                            } else if (pattern.regionMatches(pos, exponent,
+                                    0, exponent.length())) {
+                                pos = pos + exponent.length();
+                            } else {
+                                // Not a phase 1 character, consider it as
+                                // suffix and parse it in phase 2
+                                --pos; //process it again in outer loop
+                                phase = 2;
+                                affix = suffix;
+                                break;
+                            }
                         }
                         continue;
                     }
@@ -3797,7 +3871,6 @@
                          while (pos < pattern.length() &&
                                pattern.charAt(pos) == zeroDigit) {
                             ++minExponentDigits;
-                            ++phaseOneLength;
                             ++pos;
                         }
 
@@ -3816,7 +3889,6 @@
                         phase = 2;
                         affix = suffix;
                         --pos;
-                        --phaseOneLength;
                         continue;
                     }
                     break;
@@ -3887,7 +3959,7 @@
             }
         }
 
-        if (pattern.length() == 0) {
+        if (pattern.isEmpty()) {
             posPrefixPattern = posSuffixPattern = "";
             setMinimumIntegerDigits(0);
             setMaximumIntegerDigits(MAXIMUM_INTEGER_DIGITS);
diff --git a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
index a65a079..c0e4a32 100644
--- a/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DecimalFormatSymbols.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,9 +46,13 @@
 import java.io.Serializable;
 import java.util.Currency;
 import java.util.Locale;
+import libcore.icu.DecimalFormatData;
 import libcore.icu.ICU;
 import libcore.icu.LocaleData;
 
+// Android-removed: Remove javadoc related to "rg" Locale extension.
+// The "rg" extension isn't supported until https://unicode-org.atlassian.net/browse/ICU-21831
+// is resolved, because java.text.* stack relies on ICU on resource resolution.
 /**
  * This class represents the set of symbols (such as the decimal separator,
  * the grouping separator, and so on) needed by <code>DecimalFormat</code>
@@ -61,6 +65,7 @@
  * @see          DecimalFormat
  * @author       Mark Davis
  * @author       Alan Liu
+ * @since 1.1
  */
 
 public class DecimalFormatSymbols implements Cloneable, Serializable {
@@ -398,6 +403,7 @@
      */
     public String getCurrencySymbol()
     {
+        initializeCurrency(locale);
         return currencySymbol;
     }
 
@@ -410,6 +416,7 @@
      */
     public void setCurrencySymbol(String currency)
     {
+        initializeCurrency(locale);
         currencySymbol = currency;
         // Android-added: reset cachedIcuDFS.
         cachedIcuDFS = null;
@@ -424,6 +431,7 @@
      */
     public String getInternationalCurrencySymbol()
     {
+        initializeCurrency(locale);
         return intlCurrencySymbol;
     }
 
@@ -445,6 +453,7 @@
      */
     public void setInternationalCurrencySymbol(String currencyCode)
     {
+        initializeCurrency(locale);
         intlCurrencySymbol = currencyCode;
         currency = null;
         if (currencyCode != null) {
@@ -468,6 +477,7 @@
      * @since 1.4
      */
     public Currency getCurrency() {
+        initializeCurrency(locale);
         return currency;
     }
 
@@ -487,6 +497,7 @@
         if (currency == null) {
             throw new NullPointerException();
         }
+        initializeCurrency(locale);
         this.currency = currency;
         intlCurrencySymbol = currency.getCurrencyCode();
         currencySymbol = currency.getSymbol(locale);
@@ -530,14 +541,15 @@
     {
         return exponential;
     }
-  /**
-   * Returns the string used to separate the mantissa from the exponent.
-   * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
-   *
-   * @return the exponent separator string
-   * @see #setExponentSeparator(java.lang.String)
-   * @since 1.6
-   */
+
+    /**
+     * Returns the string used to separate the mantissa from the exponent.
+     * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
+     *
+     * @return the exponent separator string
+     * @see #setExponentSeparator(java.lang.String)
+     * @since 1.6
+     */
     public String getExponentSeparator()
     {
         return exponentialSeparator;
@@ -553,22 +565,22 @@
         cachedIcuDFS = null;
     }
 
-  /**
-   * Sets the string used to separate the mantissa from the exponent.
-   * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
-   *
-   * @param exp the exponent separator string
-   * @exception NullPointerException if <code>exp</code> is null
-   * @see #getExponentSeparator()
-   * @since 1.6
-   */
+    /**
+     * Sets the string used to separate the mantissa from the exponent.
+     * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
+     *
+     * @param exp the exponent separator string
+     * @exception NullPointerException if <code>exp</code> is null
+     * @see #getExponentSeparator()
+     * @since 1.6
+     */
     public void setExponentSeparator(String exp)
     {
         if (exp == null) {
             throw new NullPointerException();
         }
         exponentialSeparator = exp;
-     }
+    }
 
 
     //------------------------------------------------------------
@@ -607,7 +619,7 @@
         patternSeparator == other.patternSeparator &&
         infinity.equals(other.infinity) &&
         NaN.equals(other.NaN) &&
-        currencySymbol.equals(other.currencySymbol) &&
+        getCurrencySymbol().equals(other.getCurrencySymbol()) && // possible currency init occurs here
         intlCurrencySymbol.equals(other.intlCurrencySymbol) &&
         currency == other.currency &&
         monetarySeparator == other.monetarySeparator &&
@@ -631,9 +643,6 @@
             result = result * 37 + patternSeparator;
             result = result * 37 + infinity.hashCode();
             result = result * 37 + NaN.hashCode();
-            result = result * 37 + currencySymbol.hashCode();
-            result = result * 37 + intlCurrencySymbol.hashCode();
-            result = result * 37 + currency.hashCode();
             result = result * 37 + monetarySeparator;
             result = result * 37 + exponentialSeparator.hashCode();
             result = result * 37 + locale.hashCode();
@@ -649,37 +658,40 @@
 
         // BEGIN Android-changed: Removed use of DecimalFormatSymbolsProvider. Switched to ICU.
         /*
+        // check for region override
+        Locale override = locale.getUnicodeLocaleType("nu") == null ?
+            CalendarDataUtility.findRegionOverride(locale) :
+            locale;
+
         // get resource bundle data
-        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
+        LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, override);
         // Avoid potential recursions
         if (!(adapter instanceof ResourceBundleBasedAdapter)) {
             adapter = LocaleProviderAdapter.getResourceBundleBased();
         }
-        Object[] data = adapter.getLocaleResources(locale).getDecimalFormatSymbolsData();
+        Object[] data = adapter.getLocaleResources(override).getDecimalFormatSymbolsData();
+        String[] numberElements = (String[]) data[0];
         */
         if (locale == null) {
             throw new NullPointerException("locale");
         }
         locale = LocaleData.mapInvalidAndNullLocales(locale);
-        LocaleData localeData = LocaleData.get(locale);
-        Object[] data = new Object[3];
+        DecimalFormatData decimalFormatData = DecimalFormatData.getInstance(locale);
         String[] values = new String[11];
-        values[0] = String.valueOf(localeData.decimalSeparator);
-        values[1] = String.valueOf(localeData.groupingSeparator);
-        values[2] = String.valueOf(localeData.patternSeparator);
-        values[3] = localeData.percent;
-        values[4] = String.valueOf(localeData.zeroDigit);
+        values[0] = String.valueOf(decimalFormatData.getDecimalSeparator());
+        values[1] = String.valueOf(decimalFormatData.getGroupingSeparator());
+        values[2] = String.valueOf(decimalFormatData.getPatternSeparator());
+        values[3] = decimalFormatData.getPercent();
+        values[4] = String.valueOf(decimalFormatData.getZeroDigit());
         values[5] = "#";
-        values[6] = localeData.minusSign;
-        values[7] = localeData.exponentSeparator;
-        values[8] = localeData.perMill;
-        values[9] = localeData.infinity;
-        values[10] = localeData.NaN;
-        data[0] = values;
+        values[6] = decimalFormatData.getMinusSign();
+        values[7] = decimalFormatData.getExponentSeparator();
+        values[8] = decimalFormatData.getPerMill();
+        values[9] = decimalFormatData.getInfinity();
+        values[10] = decimalFormatData.getNaN();
+        String[] numberElements = values;
         // END Android-changed: Removed use of DecimalFormatSymbolsProvider. Switched to ICU.
 
-        String[] numberElements = (String[]) data[0];
-
         // Android-changed: Added maybeStripMarkers
         decimalSeparator = numberElements[0].charAt(0);
         groupingSeparator = numberElements[1].charAt(0);
@@ -694,18 +706,51 @@
         infinity  = numberElements[9];
         NaN = numberElements[10];
 
+        // Android-removed: Removed use of DecimalFormatSymbolsProvider. Switched to ICU.
+        // Upstream tries to re-use the strings from the cache, but Android doesn't have
+        // LocaleProviderAdapter to cache the strings.
+        // intlCurrencySymbol = (String) data[1];
+        // currencySymbol = (String) data[2];
+
+        // Currently the monetary decimal separator is the same as the
+        // standard decimal separator for all locales that we support.
+        // If that changes, add a new entry to NumberElements.
+        monetarySeparator = decimalSeparator;
+    }
+
+    /**
+     * Lazy initialization for currency related fields
+     */
+    private void initializeCurrency(Locale locale) {
+        if (currencyInitialized) {
+            return;
+        }
+
         // Try to obtain the currency used in the locale's country.
         // Check for empty country string separately because it's a valid
         // country ID for Locale (and used for the C locale), but not a valid
         // ISO 3166 country code, and exceptions are expensive.
-        if (locale.getCountry().length() > 0) {
+        if (!locale.getCountry().isEmpty()) {
             try {
                 currency = Currency.getInstance(locale);
             } catch (IllegalArgumentException e) {
                 // use default values below for compatibility
             }
         }
+
         if (currency != null) {
+            // BEGIN Android-changed: Removed use of DecimalFormatSymbolsProvider. Switched to ICU.
+            // Android doesn't have DecimalFormatSymbolsProvider to cache the values.
+            // Thus, simplify the code not loading from the cache.
+            /*
+            // get resource bundle data
+            LocaleProviderAdapter adapter =
+                LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
+            // Avoid potential recursions
+            if (!(adapter instanceof ResourceBundleBasedAdapter)) {
+                adapter = LocaleProviderAdapter.getResourceBundleBased();
+            }
+            Object[] data = adapter.getLocaleResources(locale).getDecimalFormatSymbolsData();
             intlCurrencySymbol = currency.getCurrencyCode();
             if (data[1] != null && data[1] == intlCurrencySymbol) {
                 currencySymbol = (String) data[2];
@@ -714,6 +759,10 @@
                 data[1] = intlCurrencySymbol;
                 data[2] = currencySymbol;
             }
+            */
+            intlCurrencySymbol = currency.getCurrencyCode();
+            currencySymbol = currency.getSymbol(locale);
+            // END Android-changed: Removed use of DecimalFormatSymbolsProvider. Switched to ICU.
         } else {
             // default values
             intlCurrencySymbol = "XXX";
@@ -723,10 +772,8 @@
             }
             currencySymbol = "\u00A4";
         }
-        // Currently the monetary decimal separator is the same as the
-        // standard decimal separator for all locales that we support.
-        // If that changes, add a new entry to NumberElements.
-        monetarySeparator = decimalSeparator;
+
+        currencyInitialized = true;
     }
 
     // Android-changed: maybeStripMarkers added in b/26207216, fixed in b/32465689.
@@ -772,6 +819,7 @@
             return cachedIcuDFS;
         }
 
+        initializeCurrency(this.locale);
         cachedIcuDFS = new android.icu.text.DecimalFormatSymbols(this.locale);
         // Do not localize plus sign. See "Special Pattern Characters" section in DecimalFormat.
         // http://b/67034519
@@ -804,7 +852,7 @@
 
         try {
             cachedIcuDFS.setCurrency(
-                    android.icu.util.Currency.getInstance(currency.getCurrencyCode()));
+                    android.icu.util.Currency.getInstance(getCurrency().getCurrencyCode()));
         } catch (NullPointerException e) {
             currency = Currency.getInstance("XXX");
         }
@@ -918,7 +966,7 @@
      * default serialization will work properly if this object is streamed out again.
      * Initializes the currency from the intlCurrencySymbol field.
      *
-     * @since JDK 1.1.6
+     * @since  1.1.6
      */
     private void readObject(ObjectInputStream stream)
             throws IOException, ClassNotFoundException {
@@ -971,10 +1019,13 @@
             setExponentSeparator((String) fields.get("exponentialSeparator", "E"));
         }
 
-        try {
-            currency = Currency.getInstance(intlCurrencySymbol);
-        } catch (IllegalArgumentException e) {
-            currency = null;
+        if (intlCurrencySymbol != null) {
+            try {
+                currency = Currency.getInstance(intlCurrencySymbol);
+                currencyInitialized = true;
+            } catch (IllegalArgumentException e) {
+                currency = null;
+            }
         }
         // END Android-changed: Android specific serialization code.
     }
@@ -1073,7 +1124,7 @@
     /**
      * The decimal separator used when formatting currency values.
      * @serial
-     * @since JDK 1.1.6
+     * @since  1.1.6
      * @see #getMonetaryDecimalSeparator
      */
     private  char    monetarySeparator; // Field new in JDK 1.1.6
@@ -1087,20 +1138,20 @@
      * The intent is that this will be added to the API in the future.
      *
      * @serial
-     * @since JDK 1.1.6
+     * @since  1.1.6
      */
     private  char    exponential;       // Field new in JDK 1.1.6
 
-  /**
-   * The string used to separate the mantissa from the exponent.
-   * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
-   * <p>
-   * If both <code>exponential</code> and <code>exponentialSeparator</code>
-   * exist, this <code>exponentialSeparator</code> has the precedence.
-   *
-   * @serial
-   * @since 1.6
-   */
+    /**
+     * The string used to separate the mantissa from the exponent.
+     * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
+     * <p>
+     * If both <code>exponential</code> and <code>exponentialSeparator</code>
+     * exist, this <code>exponentialSeparator</code> has the precedence.
+     *
+     * @serial
+     * @since 1.6
+     */
     private  String    exponentialSeparator;       // Field new in JDK 1.6
 
     /**
@@ -1113,6 +1164,7 @@
 
     // currency; only the ISO code is serialized.
     private transient Currency currency;
+    private transient volatile boolean currencyInitialized;
 
     // Proclaim JDK 1.1 FCS compatibility
     static final long serialVersionUID = 5772796243397350300L;
@@ -1143,7 +1195,7 @@
      * is always written.
      *
      * @serial
-     * @since JDK 1.1.6
+     * @since  1.1.6
      */
     private int serialVersionOnStream = currentSerialVersion;
 
diff --git a/ojluni/src/main/java/java/text/FieldPosition.java b/ojluni/src/main/java/java/text/FieldPosition.java
index 955221d..7a6e2a5 100644
--- a/ojluni/src/main/java/java/text/FieldPosition.java
+++ b/ojluni/src/main/java/java/text/FieldPosition.java
@@ -68,6 +68,7 @@
  * <code>formatToCharacterIterator</code>.
  *
  * @author      Mark Davis
+ * @since 1.1
  * @see         java.text.Format
  */
 public class FieldPosition {
diff --git a/ojluni/src/main/java/java/text/Format.java b/ojluni/src/main/java/java/text/Format.java
index 74fcc37..be324eb 100644
--- a/ojluni/src/main/java/java/text/Format.java
+++ b/ojluni/src/main/java/java/text/Format.java
@@ -115,7 +115,7 @@
  * the field. For examples of these constants, see <code>ERA_FIELD</code> and its
  * friends in {@link DateFormat}.
  *
- * <h4><a name="synchronization">Synchronization</a></h4>
+ * <h4><a id="synchronization">Synchronization</a></h4>
  *
  * <p>
  * Formats are generally not synchronized.
@@ -129,6 +129,7 @@
  * @see          java.text.DateFormat
  * @see          java.text.MessageFormat
  * @author       Mark Davis
+ * @since 1.1
  */
 public abstract class Format implements Serializable, Cloneable {
 
@@ -225,7 +226,7 @@
      *            index information as described above.
      * @return An <code>Object</code> parsed from the string. In case of
      *         error, returns null.
-     * @exception NullPointerException if <code>pos</code> is null.
+     * @throws NullPointerException if {@code source} or {@code pos} is null.
      */
     public abstract Object parseObject (String source, ParsePosition pos);
 
@@ -237,6 +238,7 @@
      * @return An <code>Object</code> parsed from the string.
      * @exception ParseException if the beginning of the specified string
      *            cannot be parsed.
+     * @throws NullPointerException if {@code source} is null.
      */
     public Object parseObject(String source) throws ParseException {
         ParsePosition pos = new ParsePosition(0);
diff --git a/ojluni/src/main/java/java/text/MergeCollation.java b/ojluni/src/main/java/java/text/MergeCollation.java
index bd541a5..1bfcbf0 100644
--- a/ojluni/src/main/java/java/text/MergeCollation.java
+++ b/ojluni/src/main/java/java/text/MergeCollation.java
@@ -92,7 +92,7 @@
         int i;
         for (i = 0; i < patterns.size(); ++i) {
             PatternEntry entry = patterns.get(i);
-            if (entry.extension.length() != 0) {
+            if (!entry.extension.isEmpty()) {
                 if (extList == null)
                     extList = new ArrayList<>();
                 extList.add(entry);
@@ -122,7 +122,7 @@
     private final PatternEntry findLastWithNoExtension(int i) {
         for (--i;i >= 0; --i) {
             PatternEntry entry = patterns.get(i);
-            if (entry.extension.length() == 0) {
+            if (entry.extension.isEmpty()) {
                 return entry;
             }
         }
@@ -329,8 +329,8 @@
                 PatternEntry e = patterns.get(i);
                 if (e.chars.regionMatches(0,entry.chars,0,
                                               e.chars.length())) {
-                    excessChars.append(entry.chars.substring(e.chars.length(),
-                                                            entry.chars.length()));
+                    excessChars.append(entry.chars, e.chars.length(),
+                            entry.chars.length());
                     break;
                 }
             }
diff --git a/ojluni/src/main/java/java/text/MessageFormat.java b/ojluni/src/main/java/java/text/MessageFormat.java
index 4a48e9c..bcf115f 100644
--- a/ojluni/src/main/java/java/text/MessageFormat.java
+++ b/ojluni/src/main/java/java/text/MessageFormat.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
  * behavior is defined by the pattern that you provide as well as the
  * subformats used for inserted arguments.
  *
- * <h3><a name="patterns">Patterns and Their Interpretation</a></h3>
+ * <h3><a id="patterns">Patterns and Their Interpretation</a></h3>
  *
  * <code>MessageFormat</code> uses patterns of the following form:
  * <blockquote><pre>
@@ -147,73 +147,78 @@
  * shown in the table are illegal. A <i>SubformatPattern</i> must
  * be a valid pattern string for the {@code Format} subclass used.
  *
- * <table border=1 summary="Shows how FormatType and FormatStyle values map to Format instances">
+ * <table class="plain">
+ * <caption style="display:none">Shows how FormatType and FormatStyle values map to Format instances</caption>
+ * <thead>
  *    <tr>
- *       <th id="ft" class="TableHeadingColor">FormatType
- *       <th id="fs" class="TableHeadingColor">FormatStyle
- *       <th id="sc" class="TableHeadingColor">Subformat Created
+ *       <th scope="col" class="TableHeadingColor">FormatType
+ *       <th scope="col" class="TableHeadingColor">FormatStyle
+ *       <th scope="col" class="TableHeadingColor">Subformat Created
+ * </thead>
+ * <tbody>
  *    <tr>
- *       <td headers="ft"><i>(none)</i>
- *       <td headers="fs"><i>(none)</i>
- *       <td headers="sc"><code>null</code>
+ *       <th scope="row" style="text-weight: normal"><i>(none)</i>
+ *       <th scope="row" style="text-weight: normal"><i>(none)</i>
+ *       <td>{@code null}
  *    <tr>
- *       <td headers="ft" rowspan=5><code>number</code>
- *       <td headers="fs"><i>(none)</i>
- *       <td headers="sc">{@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())}
+ *       <th scope="row" style="text-weight: normal" rowspan=5>{@code number}
+ *       <th scope="row" style="text-weight: normal"><i>(none)</i>
+ *       <td>{@link NumberFormat#getInstance(Locale) NumberFormat.getInstance}{@code (getLocale())}
  *    <tr>
- *       <td headers="fs"><code>integer</code>
- *       <td headers="sc">{@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code integer}
+ *       <td>{@link NumberFormat#getIntegerInstance(Locale) NumberFormat.getIntegerInstance}{@code (getLocale())}
  *    <tr>
- *       <td headers="fs"><code>currency</code>
- *       <td headers="sc">{@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code currency}
+ *       <td>{@link NumberFormat#getCurrencyInstance(Locale) NumberFormat.getCurrencyInstance}{@code (getLocale())}
  *    <tr>
- *       <td headers="fs"><code>percent</code>
- *       <td headers="sc">{@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code percent}
+ *       <td>{@link NumberFormat#getPercentInstance(Locale) NumberFormat.getPercentInstance}{@code (getLocale())}
  *    <tr>
- *       <td headers="fs"><i>SubformatPattern</i>
- *       <td headers="sc">{@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))}
+ *       <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ *       <td>{@code new} {@link DecimalFormat#DecimalFormat(String,DecimalFormatSymbols) DecimalFormat}{@code (subformatPattern,} {@link DecimalFormatSymbols#getInstance(Locale) DecimalFormatSymbols.getInstance}{@code (getLocale()))}
  *    <tr>
- *       <td headers="ft" rowspan=6><code>date</code>
- *       <td headers="fs"><i>(none)</i>
- *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal" rowspan=6>{@code date}
+ *       <th scope="row" style="text-weight: normal"><i>(none)</i>
+ *       <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>short</code>
- *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code short}
+ *       <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>medium</code>
- *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code medium}
+ *       <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>long</code>
- *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code long}
+ *       <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>full</code>
- *       <td headers="sc">{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code full}
+ *       <td>{@link DateFormat#getDateInstance(int,Locale) DateFormat.getDateInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><i>SubformatPattern</i>
- *       <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
+ *       <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ *       <td>{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
  *    <tr>
- *       <td headers="ft" rowspan=6><code>time</code>
- *       <td headers="fs"><i>(none)</i>
- *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal" rowspan=6>{@code time}
+ *       <th scope="row" style="text-weight: normal"><i>(none)</i>
+ *       <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>short</code>
- *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code short}
+ *       <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#SHORT}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>medium</code>
- *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code medium}
+ *       <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#DEFAULT}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>long</code>
- *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code long}
+ *       <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#LONG}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><code>full</code>
- *       <td headers="sc">{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
+ *       <th scope="row" style="text-weight: normal">{@code full}
+ *       <td>{@link DateFormat#getTimeInstance(int,Locale) DateFormat.getTimeInstance}{@code (}{@link DateFormat#FULL}{@code , getLocale())}
  *    <tr>
- *       <td headers="fs"><i>SubformatPattern</i>
- *       <td headers="sc">{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
+ *       <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ *       <td>{@code new} {@link SimpleDateFormat#SimpleDateFormat(String,Locale) SimpleDateFormat}{@code (subformatPattern, getLocale())}
  *    <tr>
- *       <td headers="ft"><code>choice</code>
- *       <td headers="fs"><i>SubformatPattern</i>
- *       <td headers="sc">{@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)}
+ *       <th scope="row" style="text-weight: normal">{@code choice}
+ *       <th scope="row" style="text-weight: normal"><i>SubformatPattern</i>
+ *       <td>{@code new} {@link ChoiceFormat#ChoiceFormat(String) ChoiceFormat}{@code (subformatPattern)}
+ * </tbody>
  * </table>
  *
  * <h4>Usage Information</h4>
@@ -322,7 +327,7 @@
  * // result now equals {new String("z")}
  * </pre></blockquote>
  *
- * <h4><a name="synchronization">Synchronization</a></h4>
+ * <h4><a id="synchronization">Synchronization</a></h4>
  *
  * <p>
  * Message formats are not synchronized.
@@ -340,6 +345,7 @@
  * @see          SimpleDateFormat
  *
  * @author       Mark Davis
+ * @since 1.1
  */
 
 public class MessageFormat extends Format {
@@ -357,6 +363,8 @@
      *
      * @param pattern the pattern for this message format
      * @exception IllegalArgumentException if the pattern is invalid
+     * @exception NullPointerException if {@code pattern} is
+     *            {@code null}
      */
     public MessageFormat(String pattern) {
         this.locale = Locale.getDefault(Locale.Category.FORMAT);
@@ -374,6 +382,8 @@
      * @param pattern the pattern for this message format
      * @param locale the locale for this message format
      * @exception IllegalArgumentException if the pattern is invalid
+     * @exception NullPointerException if {@code pattern} is
+     *            {@code null}
      * @since 1.4
      */
     public MessageFormat(String pattern, Locale locale) {
@@ -421,6 +431,8 @@
      *
      * @param pattern the pattern for this message format
      * @exception IllegalArgumentException if the pattern is invalid
+     * @exception NullPointerException if {@code pattern} is
+     *            {@code null}
      */
     @SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
     public void applyPattern(String pattern) {
@@ -690,11 +702,8 @@
      *            larger than the number of format elements in the pattern string
      */
     public void setFormat(int formatElementIndex, Format newFormat) {
-        // Android-added: prevent setting unused formatters.
         if (formatElementIndex > maxOffset) {
-            // Note: maxOffset is maximum index, not the length.
-            throw new ArrayIndexOutOfBoundsException(
-                    "maxOffset=" + maxOffset + "; formatElementIndex=" + formatElementIndex);
+            throw new ArrayIndexOutOfBoundsException(formatElementIndex);
         }
         formats[formatElementIndex] = newFormat;
     }
@@ -767,45 +776,46 @@
      * argument is <i>unavailable</i> if <code>arguments</code> is
      * <code>null</code> or has fewer than argumentIndex+1 elements.
      *
-     * <table border=1 summary="Examples of subformat,argument,and formatted text">
+     * <table class="plain">
+     * <caption style="display:none">Examples of subformat,argument,and formatted text</caption>
+     * <thead>
      *    <tr>
-     *       <th>Subformat
-     *       <th>Argument
-     *       <th>Formatted Text
+     *       <th scope="col">Subformat
+     *       <th scope="col">Argument
+     *       <th scope="col">Formatted Text
+     * </thead>
+     * <tbody>
      *    <tr>
-     *       <td><i>any</i>
-     *       <td><i>unavailable</i>
+     *       <th scope="row" style="text-weight-normal" rowspan=2><i>any</i>
+     *       <th scope="row" style="text-weight-normal"><i>unavailable</i>
      *       <td><code>"{" + argumentIndex + "}"</code>
      *    <tr>
-     *       <td><i>any</i>
-     *       <td><code>null</code>
+     *       <th scope="row" style="text-weight-normal"><code>null</code>
      *       <td><code>"null"</code>
      *    <tr>
-     *       <td><code>instanceof ChoiceFormat</code>
-     *       <td><i>any</i>
+     *       <th scope="row" style="text-weight-normal"><code>instanceof ChoiceFormat</code>
+     *       <th scope="row" style="text-weight-normal"><i>any</i>
      *       <td><code>subformat.format(argument).indexOf('{') &gt;= 0 ?<br>
      *           (new MessageFormat(subformat.format(argument), getLocale())).format(argument) :
      *           subformat.format(argument)</code>
      *    <tr>
-     *       <td><code>!= null</code>
-     *       <td><i>any</i>
+     *       <th scope="row" style="text-weight-normal"><code>!= null</code>
+     *       <th scope="row" style="text-weight-normal"><i>any</i>
      *       <td><code>subformat.format(argument)</code>
      *    <tr>
-     *       <td><code>null</code>
-     *       <td><code>instanceof Number</code>
+     *       <th scope="row" style="text-weight-normal" rowspan=4><code>null</code>
+     *       <th scope="row" style="text-weight-normal"><code>instanceof Number</code>
      *       <td><code>NumberFormat.getInstance(getLocale()).format(argument)</code>
      *    <tr>
-     *       <td><code>null</code>
-     *       <td><code>instanceof Date</code>
+     *       <th scope="row" style="text-weight-normal"><code>instanceof Date</code>
      *       <td><code>DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, getLocale()).format(argument)</code>
      *    <tr>
-     *       <td><code>null</code>
-     *       <td><code>instanceof String</code>
+     *       <th scope="row" style="text-weight-normal"><code>instanceof String</code>
      *       <td><code>argument</code>
      *    <tr>
-     *       <td><code>null</code>
-     *       <td><i>any</i>
+     *       <th scope="row" style="text-weight-normal"><i>any</i>
      *       <td><code>argument.toString()</code>
+     * </tbody>
      * </table>
      * <p>
      * If <code>pos</code> is non-null, and refers to
@@ -814,13 +824,14 @@
      *
      * @param arguments an array of objects to be formatted and substituted.
      * @param result where text is appended.
-     * @param pos On input: an alignment field, if desired.
-     *            On output: the offsets of the alignment field.
+     * @param pos keeps track on the position of the first replaced argument
+                  in the output string.
      * @return the string buffer passed in as {@code result}, with formatted
      * text appended
      * @exception IllegalArgumentException if an argument in the
      *            <code>arguments</code> array is not of the type
      *            expected by the format element(s) that use it.
+     * @exception NullPointerException if {@code result} is {@code null}
      */
     public final StringBuffer format(Object[] arguments, StringBuffer result,
                                      FieldPosition pos)
@@ -842,6 +853,7 @@
      *            or if an argument in the <code>arguments</code> array
      *            is not of the type expected by the format element(s)
      *            that use it.
+     * @exception NullPointerException if {@code pattern} is {@code null}
      */
     public static String format(String pattern, Object ... arguments) {
         MessageFormat temp = new MessageFormat(pattern);
@@ -860,11 +872,12 @@
      *
      * @param arguments an array of objects to be formatted and substituted.
      * @param result where text is appended.
-     * @param pos On input: an alignment field, if desired.
-     *            On output: the offsets of the alignment field.
+     * @param pos keeps track on the position of the first replaced argument
+     *            in the output string.
      * @exception IllegalArgumentException if an argument in the
      *            <code>arguments</code> array is not of the type
      *            expected by the format element(s) that use it.
+     * @exception NullPointerException if {@code result} is {@code null}
      */
     public final StringBuffer format(Object arguments, StringBuffer result,
                                      FieldPosition pos)
@@ -954,6 +967,8 @@
      * @param source the string to parse
      * @param pos    the parse position
      * @return an array of parsed objects
+     * @exception NullPointerException if {@code pos} is {@code null}
+     *            for a non-null {@code source} string.
      */
     public Object[] parse(String source, ParsePosition pos) {
         if (source == null) {
@@ -1075,7 +1090,7 @@
      *            index information as described above.
      * @return An <code>Object</code> array parsed from the string. In case of
      *         error, returns null.
-     * @exception NullPointerException if <code>pos</code> is null.
+     * @throws NullPointerException if {@code pos} is null.
      */
     public Object parseObject(String source, ParsePosition pos) {
         return parse(source, pos);
@@ -1175,7 +1190,7 @@
          * indicating the index in the <code>arguments</code> array of the
          * argument from which the text was generated.
          */
-        public final static Field ARGUMENT =
+        public static final Field ARGUMENT =
                            new Field("message argument field");
     }
 
@@ -1228,11 +1243,11 @@
     private int maxOffset = -1;
 
     /**
-     * Internal routine used by format. If <code>characterIterators</code> is
-     * non-null, AttributedCharacterIterator will be created from the
-     * subformats as necessary. If <code>characterIterators</code> is null
-     * and <code>fp</code> is non-null and identifies
-     * <code>Field.MESSAGE_ARGUMENT</code>, the location of
+     * Internal routine used by format. If {@code characterIterators} is
+     * {@code non-null}, AttributedCharacterIterator will be created from the
+     * subformats as necessary. If {@code characterIterators} is {@code null}
+     * and {@code fp} is {@code non-null} and identifies
+     * {@code Field.ARGUMENT} as the field attribute, the location of
      * the first replaced argument will be set in it.
      *
      * @exception IllegalArgumentException if an argument in the
@@ -1246,7 +1261,7 @@
         int lastOffset = 0;
         int last = result.length();
         for (int i = 0; i <= maxOffset; ++i) {
-            result.append(pattern.substring(lastOffset, offsets[i]));
+            result.append(pattern, lastOffset, offsets[i]);
             lastOffset = offsets[i];
             int argumentNumber = argumentNumbers[i];
             if (arguments == null || argumentNumber >= arguments.length) {
@@ -1315,7 +1330,7 @@
                         }
                         arg = null;
                     }
-                    if (arg != null && arg.length() > 0) {
+                    if (arg != null && !arg.isEmpty()) {
                         result.append(arg);
                         characterIterators.add(
                                  createAttributedCharacterIterator(
@@ -1339,7 +1354,7 @@
                 }
             }
         }
-        result.append(pattern.substring(lastOffset, pattern.length()));
+        result.append(pattern, lastOffset, pattern.length());
         if (characterIterators != null && last != result.length()) {
             characterIterators.add(createAttributedCharacterIterator(
                                    result.substring(last)));
@@ -1461,7 +1476,7 @@
 
         // now get the format
         Format newFormat = null;
-        if (segments[SEG_TYPE].length() != 0) {
+        if (!segments[SEG_TYPE].isEmpty()) {
             int type = findKeyword(segments[SEG_TYPE], TYPE_KEYWORDS);
             switch (type) {
             case TYPE_NULL:
diff --git a/ojluni/src/main/java/java/text/Normalizer.java b/ojluni/src/main/java/java/text/Normalizer.java
index f1e77ff..0a196ed 100644
--- a/ojluni/src/main/java/java/text/Normalizer.java
+++ b/ojluni/src/main/java/java/text/Normalizer.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/text/NumberFormat.java b/ojluni/src/main/java/java/text/NumberFormat.java
index 9ad44ed..cee91ff 100644
--- a/ojluni/src/main/java/java/text/NumberFormat.java
+++ b/ojluni/src/main/java/java/text/NumberFormat.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,9 +52,13 @@
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
+import libcore.icu.DecimalFormatData;
 import libcore.icu.ICU;
 import libcore.icu.LocaleData;
 
+// Android-removed: Remove javadoc related to "rg" Locale extension.
+// The "rg" extension isn't supported until https://unicode-org.atlassian.net/browse/ICU-21831
+// is resolved, because java.text.* stack relies on ICU on resource resolution.
 /**
  * <code>NumberFormat</code> is the abstract base class for all number
  * formats. This class provides the interface for formatting and parsing
@@ -94,7 +98,12 @@
  * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
  * }</pre>
  * </blockquote>
- * You can also use a <code>NumberFormat</code> to parse numbers:
+ *
+ * <p>If the locale contains "nu" (numbers)
+ * <a href="../util/Locale.html#def_locale_extension">Unicode extensions</a>,
+ * the decimal digits, and/or the country used for formatting are overridden.
+ *
+ * <p>You can also use a {@code NumberFormat} to parse numbers:
  * <blockquote>
  * <pre>{@code
  * myNumber = nf.parse(myString);
@@ -164,7 +173,7 @@
  *      numbers: "(12)" for -12.
  * </ol>
  *
- * <h3><a name="synchronization">Synchronization</a></h3>
+ * <h3><a id="synchronization">Synchronization</a></h3>
  *
  * <p>
  * Number formats are generally not synchronized.
@@ -172,10 +181,29 @@
  * If multiple threads access a format concurrently, it must be synchronized
  * externally.
  *
+ * @implSpec The {@link #format(double, StringBuffer, FieldPosition)},
+ * {@link #format(long, StringBuffer, FieldPosition)} and
+ * {@link #parse(String, ParsePosition)} methods may throw
+ * {@code NullPointerException}, if any of their parameter is {@code null}.
+ * The subclass may provide its own implementation and specification about
+ * {@code NullPointerException}.
+ *
+ * <p>
+ * The default implementation provides rounding modes defined
+ * in {@link java.math.RoundingMode} for formatting numbers. It
+ * uses the {@linkplain java.math.RoundingMode#HALF_EVEN
+ * round half-even algorithm}. To change the rounding mode use
+ * {@link #setRoundingMode(java.math.RoundingMode) setRoundingMode}.
+ * The {@code NumberFormat} returned by the static factory methods is
+ * configured to round floating point numbers using half-even
+ * rounding (see {@link java.math.RoundingMode#HALF_EVEN
+ * RoundingMode.HALF_EVEN}) for formatting.
+ *
  * @see          DecimalFormat
  * @see          ChoiceFormat
  * @author       Mark Davis
  * @author       Helena Shih
+ * @since 1.1
  */
 public abstract class NumberFormat extends Format  {
 
@@ -219,8 +247,14 @@
      * @param number     the number to format
      * @param toAppendTo the <code>StringBuffer</code> to which the formatted
      *                   text is to be appended
-     * @param pos        On input: an alignment field, if desired.
-     *                   On output: the offsets of the alignment field.
+     * @param pos        keeps track on the position of the field within the
+     *                   returned string. For example, for formatting a number
+     *                   {@code 1234567.89} in {@code Locale.US} locale,
+     *                   if the given {@code fieldPosition} is
+     *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                   and end index of {@code fieldPosition} will be set
+     *                   to 0 and 9, respectively for the output string
+     *                   {@code 1,234,567.89}.
      * @return           the value passed in as <code>toAppendTo</code>
      * @exception        IllegalArgumentException if <code>number</code> is
      *                   null or not an instance of <code>Number</code>.
@@ -269,7 +303,7 @@
      *            index information as described above.
      * @return A <code>Number</code> parsed from the string. In case of
      *         error, returns null.
-     * @exception NullPointerException if <code>pos</code> is null.
+     * @throws NullPointerException if {@code source} or {@code pos} is null.
      */
     @Override
     public final Object parseObject(String source, ParsePosition pos) {
@@ -313,7 +347,14 @@
      * @param number     the double number to format
      * @param toAppendTo the StringBuffer to which the formatted text is to be
      *                   appended
-     * @param pos        the field position
+     * @param pos        keeps track on the position of the field within the
+     *                   returned string. For example, for formatting a number
+     *                   {@code 1234567.89} in {@code Locale.US} locale,
+     *                   if the given {@code fieldPosition} is
+     *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                   and end index of {@code fieldPosition} will be set
+     *                   to 0 and 9, respectively for the output string
+     *                   {@code 1,234,567.89}.
      * @return the formatted StringBuffer
      * @exception        ArithmeticException if rounding is needed with rounding
      *                   mode being set to RoundingMode.UNNECESSARY
@@ -329,7 +370,14 @@
      * @param number     the long number to format
      * @param toAppendTo the StringBuffer to which the formatted text is to be
      *                   appended
-     * @param pos        the field position
+     * @param pos        keeps track on the position of the field within the
+     *                   returned string. For example, for formatting a number
+     *                   {@code 123456789} in {@code Locale.US} locale,
+     *                   if the given {@code fieldPosition} is
+     *                   {@link NumberFormat#INTEGER_FIELD}, the begin index
+     *                   and end index of {@code fieldPosition} will be set
+     *                   to 0 and 11, respectively for the output string
+     *                   {@code 123,456,789}.
      * @return the formatted StringBuffer
      * @exception        ArithmeticException if rounding is needed with rounding
      *                   mode being set to RoundingMode.UNNECESSARY
@@ -383,7 +431,7 @@
      * For example in the English locale, with ParseIntegerOnly true, the
      * string "1234." would be parsed as the integer value 1234 and parsing
      * would stop at the "." character.  Of course, the exact format accepted
-     * by the parse operation is locale dependant and determined by sub-classes
+     * by the parse operation is locale dependent and determined by sub-classes
      * of NumberFormat.
      *
      * @return {@code true} if numbers should be parsed as integers only;
@@ -415,7 +463,7 @@
      * @return the {@code NumberFormat} instance for general-purpose number
      * formatting
      */
-    public final static NumberFormat getInstance() {
+    public static final NumberFormat getInstance() {
         return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
     }
 
@@ -444,7 +492,7 @@
      * @see java.util.Locale#getDefault(java.util.Locale.Category)
      * @see java.util.Locale.Category#FORMAT
      */
-    public final static NumberFormat getNumberInstance() {
+    public static final NumberFormat getNumberInstance() {
         return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
     }
 
@@ -477,7 +525,7 @@
      * @return a number format for integer values
      * @since 1.4
      */
-    public final static NumberFormat getIntegerInstance() {
+    public static final NumberFormat getIntegerInstance() {
         return getInstance(Locale.getDefault(Locale.Category.FORMAT), INTEGERSTYLE);
     }
 
@@ -509,7 +557,7 @@
      * @see java.util.Locale#getDefault(java.util.Locale.Category)
      * @see java.util.Locale.Category#FORMAT
      */
-    public final static NumberFormat getCurrencyInstance() {
+    public static final NumberFormat getCurrencyInstance() {
         return getInstance(Locale.getDefault(Locale.Category.FORMAT), CURRENCYSTYLE);
     }
 
@@ -534,7 +582,7 @@
      * @see java.util.Locale#getDefault(java.util.Locale.Category)
      * @see java.util.Locale.Category#FORMAT
      */
-    public final static NumberFormat getPercentInstance() {
+    public static final NumberFormat getPercentInstance() {
         return getInstance(Locale.getDefault(Locale.Category.FORMAT), PERCENTSTYLE);
     }
 
@@ -609,7 +657,7 @@
      * Returns true if grouping is used in this format. For example, in the
      * English locale, with grouping on, the number 1234567 might be formatted
      * as "1,234,567". The grouping separator as well as the size of each group
-     * is locale dependant and is determined by sub-classes of NumberFormat.
+     * is locale dependent and is determined by sub-classes of NumberFormat.
      *
      * @return {@code true} if grouping is used;
      *         {@code false} otherwise
@@ -837,10 +885,10 @@
                                        desiredLocale, choice);
         */
         String[] numberPatterns = new String[3];
-        LocaleData data = LocaleData.get(desiredLocale);
-        numberPatterns[NUMBERSTYLE] = data.numberPattern;
-        numberPatterns[CURRENCYSTYLE] = data.currencyPattern;
-        numberPatterns[PERCENTSTYLE] = data.percentPattern;
+        DecimalFormatData data = DecimalFormatData.getInstance(desiredLocale);
+        numberPatterns[NUMBERSTYLE] = data.getNumberPattern();
+        numberPatterns[CURRENCYSTYLE] = data.getCurrencyPattern();
+        numberPatterns[PERCENTSTYLE] = data.getPercentPattern();
 
         // Note: the following lines are from NumberFormatProviderImpl upstream.
         DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(desiredLocale);
diff --git a/ojluni/src/main/java/java/text/ParseException.java b/ojluni/src/main/java/java/text/ParseException.java
index f9ad001..264c480 100644
--- a/ojluni/src/main/java/java/text/ParseException.java
+++ b/ojluni/src/main/java/java/text/ParseException.java
@@ -45,6 +45,7 @@
  * @see java.text.Format
  * @see java.text.FieldPosition
  * @author      Mark Davis
+ * @since 1.1
  */
 public
 class ParseException extends Exception {
diff --git a/ojluni/src/main/java/java/text/ParsePosition.java b/ojluni/src/main/java/java/text/ParsePosition.java
index be3ffce..85e5c9d 100644
--- a/ojluni/src/main/java/java/text/ParsePosition.java
+++ b/ojluni/src/main/java/java/text/ParsePosition.java
@@ -51,6 +51,7 @@
  * records the current position.
  *
  * @author      Mark Davis
+ * @since 1.1
  * @see         java.text.Format
  */
 
diff --git a/ojluni/src/main/java/java/text/PatternEntry.java b/ojluni/src/main/java/java/text/PatternEntry.java
index 07af4b8..3e065df 100644
--- a/ojluni/src/main/java/java/text/PatternEntry.java
+++ b/ojluni/src/main/java/java/text/PatternEntry.java
@@ -141,7 +141,7 @@
         if (showWhiteSpace)
             toAddTo.append(' ');
         appendQuoted(chars,toAddTo);
-        if (showExtension && extension.length() != 0) {
+        if (showExtension && !extension.isEmpty()) {
             toAddTo.append('/');
             appendQuoted(extension,toAddTo);
         }
diff --git a/ojluni/src/main/java/java/text/RuleBasedCollator.java b/ojluni/src/main/java/java/text/RuleBasedCollator.java
index a3234c8..00d4702 100644
--- a/ojluni/src/main/java/java/text/RuleBasedCollator.java
+++ b/ojluni/src/main/java/java/text/RuleBasedCollator.java
@@ -241,6 +241,7 @@
  * @see        Collator
  * @see        CollationElementIterator
  * @author     Helena Shih, Laura Werner, Richard Gillam
+ * @since 1.1
  */
 public class RuleBasedCollator extends Collator{
     // Android-added: protected constructor taking an ICU RuleBasedCollator.
@@ -415,5 +416,28 @@
         return (android.icu.text.RuleBasedCollator) icuColl;
     }
 
-    // Android-removed: private constants and fields.
+    // BEGIN Android-removed: private constants and fields.
+    /*
+    // ==============================================================
+    // private
+    // ==============================================================
+
+    static final int CHARINDEX = 0x70000000;  // need look up in .commit()
+    static final int EXPANDCHARINDEX = 0x7E000000; // Expand index follows
+    static final int CONTRACTCHARINDEX = 0x7F000000;  // contract indexes follow
+    static final int UNMAPPED = 0xFFFFFFFF;
+
+    private static final int COLLATIONKEYOFFSET = 1;
+
+    private RBCollationTables tables = null;
+
+    // Internal objects that are cached across calls so that they don't have to
+    // be created/destroyed on every call to compare() and getCollationKey()
+    private StringBuffer primResult = null;
+    private StringBuffer secResult = null;
+    private StringBuffer terResult = null;
+    private CollationElementIterator sourceCursor = null;
+    private CollationElementIterator targetCursor = null;
+    */
+    // END Android-removed: private constants and fields.
 }
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index 36a4601..24eb458 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,8 @@
 import java.util.TimeZone;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import libcore.icu.LocaleData;
 
+import libcore.icu.SimpleDateFormatData;
 import sun.util.calendar.CalendarUtils;
 
 import static java.text.DateFormatSymbols.*;
@@ -104,168 +104,173 @@
  * <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to
  * <code>'z'</code> are reserved):
  * <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0 summary="Chart shows pattern letters, date/time component, presentation, and examples.">
- *     <tr style="background-color: rgb(204, 204, 255);">
- *         <th align=left>Letter
- *         <th align=left>Date or Time Component
- *         <th align=left>Presentation
- *         <th align=left>Examples
- *         <th align=left>Supported (API Levels)
+ * <table class="striped">
+ * <caption style="display:none">Chart shows pattern letters, date/time component, presentation, and examples.</caption>
+ * <thead>
  *     <tr>
- *         <td><code>G</code>
+ *         <th scope="col" style="text-align:left">Letter
+ *         <th scope="col" style="text-align:left">Date or Time Component
+ *         <th scope="col" style="text-align:left">Presentation
+ *         <th scope="col" style="text-align:left">Examples
+ *         <th scope="col" style="text-align:left">Supported (API Levels)
+ * </thead>
+ * <tbody>
+ *     <tr>
+ *         <th scope="row"><code>G</code>
  *         <td>Era designator
  *         <td><a href="#text">Text</a>
  *         <td><code>AD</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>y</code>
+ *     <tr>
+ *         <th scope="row"><code>y</code>
  *         <td>Year
  *         <td><a href="#year">Year</a>
  *         <td><code>1996</code>; <code>96</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>Y</code>
+ *         <th scope="row"><code>Y</code>
  *         <td>Week year
  *         <td><a href="#year">Year</a>
  *         <td><code>2009</code>; <code>09</code>
  *         <td>24+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>M</code>
+ *     <tr>
+ *         <th scope="row"><code>M</code>
  *         <td>Month in year (context sensitive)
  *         <td><a href="#month">Month</a>
  *         <td><code>July</code>; <code>Jul</code>; <code>07</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>L</code>
+ *         <th scope="row"><code>L</code>
  *         <td>Month in year (standalone form)
  *         <td><a href="#month">Month</a>
  *         <td><code>July</code>; <code>Jul</code>; <code>07</code>
  *         <td>TBD</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>w</code>
+ *     <tr>
+ *         <th scope="row"><code>w</code>
  *         <td>Week in year
  *         <td><a href="#number">Number</a>
  *         <td><code>27</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>W</code>
+ *         <th scope="row"><code>W</code>
  *         <td>Week in month
  *         <td><a href="#number">Number</a>
  *         <td><code>2</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>D</code>
+ *     <tr>
+ *         <th scope="row"><code>D</code>
  *         <td>Day in year
  *         <td><a href="#number">Number</a>
  *         <td><code>189</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>d</code>
+ *         <th scope="row"><code>d</code>
  *         <td>Day in month
  *         <td><a href="#number">Number</a>
  *         <td><code>10</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>F</code>
+ *     <tr>
+ *         <th scope="row"><code>F</code>
  *         <td>Day of week in month
  *         <td><a href="#number">Number</a>
  *         <td><code>2</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>E</code>
+ *         <th scope="row"><code>E</code>
  *         <td>Day name in week
  *         <td><a href="#text">Text</a>
  *         <td><code>Tuesday</code>; <code>Tue</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>u</code>
+ *     <tr>
+ *         <th scope="row"><code>u</code>
  *         <td>Day number of week (1 = Monday, ..., 7 = Sunday)
  *         <td><a href="#number">Number</a>
  *         <td><code>1</code>
  *         <td>24+</td>
  *     <tr>
- *         <td><code>a</code>
+ *         <th scope="row"><code>a</code>
  *         <td>Am/pm marker
  *         <td><a href="#text">Text</a>
  *         <td><code>PM</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>H</code>
+ *     <tr>
+ *         <th scope="row"><code>H</code>
  *         <td>Hour in day (0-23)
  *         <td><a href="#number">Number</a>
  *         <td><code>0</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>k</code>
+ *         <th scope="row"><code>k</code>
  *         <td>Hour in day (1-24)
  *         <td><a href="#number">Number</a>
  *         <td><code>24</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>K</code>
+ *     <tr>
+ *         <th scope="row"><code>K</code>
  *         <td>Hour in am/pm (0-11)
  *         <td><a href="#number">Number</a>
  *         <td><code>0</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>h</code>
+ *         <th scope="row"><code>h</code>
  *         <td>Hour in am/pm (1-12)
  *         <td><a href="#number">Number</a>
  *         <td><code>12</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>m</code>
+ *     <tr>
+ *         <th scope="row"><code>m</code>
  *         <td>Minute in hour
  *         <td><a href="#number">Number</a>
  *         <td><code>30</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>s</code>
+ *         <th scope="row"><code>s</code>
  *         <td>Second in minute
  *         <td><a href="#number">Number</a>
  *         <td><code>55</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>S</code>
+ *     <tr>
+ *         <th scope="row"><code>S</code>
  *         <td>Millisecond
  *         <td><a href="#number">Number</a>
  *         <td><code>978</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>z</code>
+ *         <th scope="row"><code>z</code>
  *         <td>Time zone
  *         <td><a href="#timezone">General time zone</a>
  *         <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code>
  *         <td>1+</td>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>Z</code>
+ *     <tr>
+ *         <th scope="row"><code>Z</code>
  *         <td>Time zone
  *         <td><a href="#rfc822timezone">RFC 822 time zone</a>
  *         <td><code>-0800</code>
  *         <td>1+</td>
  *     <tr>
- *         <td><code>X</code>
+ *         <th scope="row"><code>X</code>
  *         <td>Time zone
  *         <td><a href="#iso8601timezone">ISO 8601 time zone</a>
  *         <td><code>-08</code>; <code>-0800</code>;  <code>-08:00</code>
  *         <td>24+</td>
+ * </tbody>
  * </table>
  * </blockquote>
  * Pattern letters are usually repeated, as their number determines the
  * exact presentation:
  * <ul>
- * <li><strong><a name="text">Text:</a></strong>
+ * <li><strong><a id="text">Text:</a></strong>
  *     For formatting, if the number of pattern letters is 4 or more,
  *     the full form is used; otherwise a short or abbreviated form
  *     is used if available.
  *     For parsing, both forms are accepted, independent of the number
  *     of pattern letters.</li>
- * <li><strong><a name="number">Number:</a></strong>
+ * <li><strong><a id="number">Number:</a></strong>
  *     For formatting, the number of pattern letters is the minimum
  *     number of digits, and shorter numbers are zero-padded to this amount.
  *     For parsing, the number of pattern letters is ignored unless
  *     it's needed to separate two adjacent fields.</li>
- * <li><strong><a name="year">Year:</a></strong>
+ * <li><strong><a id="year">Year:</a></strong>
  *     If the formatter's {@link #getCalendar() Calendar} is the Gregorian
  *     calendar, the following rules are applied.
  *     <ul>
@@ -306,26 +311,33 @@
  *     DateFormat#getCalendar() getCalendar()}.{@link
  *     java.util.Calendar#isWeekDateSupported()
  *     isWeekDateSupported()}.</li>
- * <li><strong><a name="month">Month:</a></strong>
+ * <li><strong><a id="month">Month:</a></strong>
  *     If the number of pattern letters is 3 or more, the month is
  *     interpreted as <a href="#text">text</a>; otherwise,
  *     it is interpreted as a <a href="#number">number</a>.
  *     <ul>
  *     <li>Letter <em>M</em> produces context-sensitive month names, such as the
- *         embedded form of names. If a {@code DateFormatSymbols} has been set
- *         explicitly with constructor {@link #SimpleDateFormat(String,
- *         DateFormatSymbols)} or method {@link
+ *         embedded form of names. Letter <em>M</em> is context-sensitive in the
+ *         sense that when it is used in the standalone pattern, for example,
+ *         "MMMM", it gives the standalone form of a month name and when it is
+ *         used in the pattern containing other field(s), for example, "d MMMM",
+ *         it gives the format form of a month name. For example, January in the
+ *         Catalan language is "de gener" in the format form while it is "gener"
+ *         in the standalone form. In this case, "MMMM" will produce "gener" and
+ *         the month part of the "d MMMM" will produce "de gener". If a
+ *         {@code DateFormatSymbols} has been set explicitly with constructor
+ *         {@link #SimpleDateFormat(String,DateFormatSymbols)} or method {@link
  *         #setDateFormatSymbols(DateFormatSymbols)}, the month names given by
  *         the {@code DateFormatSymbols} are used.</li>
  *     <li>Letter <em>L</em> produces the standalone form of month names.</li>
  *     </ul>
  *     <br></li>
- * <li><strong><a name="timezone">General time zone:</a></strong>
+ * <li><strong><a id="timezone">General time zone:</a></strong>
  *     Time zones are interpreted as <a href="#text">text</a> if they have
  *     names. For time zones representing a GMT offset value, the
  *     following syntax is used:
  *     <pre>
- *     <a name="GMTOffsetTimeZone"><i>GMTOffsetTimeZone:</i></a>
+ *     <a id="GMTOffsetTimeZone"><i>GMTOffsetTimeZone:</i></a>
  *             <code>GMT</code> <i>Sign</i> <i>Hours</i> <code>:</code> <i>Minutes</i>
  *     <i>Sign:</i> one of
  *             <code>+ -</code>
@@ -341,7 +353,7 @@
  *     from the Basic Latin block of the Unicode standard.
  *     <p>For parsing, <a href="#rfc822timezone">RFC 822 time zones</a> are also
  *     accepted.</li>
- * <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
+ * <li><strong><a id="rfc822timezone">RFC 822 time zone:</a></strong>
  *     For formatting, the RFC 822 4-digit time zone format is used:
  *
  *     <pre>
@@ -354,7 +366,7 @@
  *
  *     <p>For parsing, <a href="#timezone">general time zones</a> are also
  *     accepted.
- * <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong>
+ * <li><strong><a id="iso8601timezone">ISO 8601 Time zone:</a></strong>
  *     The number of pattern letters designates the format for both formatting
  *     and parsing as follows:
  *     <pre>
@@ -399,47 +411,52 @@
  * the U.S. locale. The given date and time are 2001-07-04 12:08:56 local time
  * in the U.S. Pacific Time time zone.
  * <blockquote>
- * <table border=0 cellspacing=3 cellpadding=0 summary="Examples of date and time patterns interpreted in the U.S. locale">
- *     <tr style="background-color: rgb(204, 204, 255);">
- *         <th align=left>Date and Time Pattern
- *         <th align=left>Result
+ * <table class="striped">
+ * <caption style="display:none">Examples of date and time patterns interpreted in the U.S. locale</caption>
+ * <thead>
  *     <tr>
- *         <td><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code>
+ *         <th scope="col" style="text-align:left">Date and Time Pattern
+ *         <th scope="col" style="text-align:left">Result
+ * </thead>
+ * <tbody>
+ *     <tr>
+ *         <th scope="row"><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code>
  *         <td><code>2001.07.04 AD at 12:08:56 PDT</code>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>"EEE, MMM d, ''yy"</code>
+ *     <tr>
+ *         <th scope="row"><code>"EEE, MMM d, ''yy"</code>
  *         <td><code>Wed, Jul 4, '01</code>
  *     <tr>
- *         <td><code>"h:mm a"</code>
+ *         <th scope="row"><code>"h:mm a"</code>
  *         <td><code>12:08 PM</code>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>"hh 'o''clock' a, zzzz"</code>
+ *     <tr>
+ *         <th scope="row"><code>"hh 'o''clock' a, zzzz"</code>
  *         <td><code>12 o'clock PM, Pacific Daylight Time</code>
  *     <tr>
- *         <td><code>"K:mm a, z"</code>
+ *         <th scope="row"><code>"K:mm a, z"</code>
  *         <td><code>0:08 PM, PDT</code>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>"yyyyy.MMMM.dd GGG hh:mm aaa"</code>
+ *     <tr>
+ *         <th scope="row"><code>"yyyyy.MMMM.dd GGG hh:mm aaa"</code>
  *         <td><code>02001.July.04 AD 12:08 PM</code>
  *     <tr>
- *         <td><code>"EEE, d MMM yyyy HH:mm:ss Z"</code>
+ *         <th scope="row"><code>"EEE, d MMM yyyy HH:mm:ss Z"</code>
  *         <td><code>Wed, 4 Jul 2001 12:08:56 -0700</code>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>"yyMMddHHmmssZ"</code>
+ *     <tr>
+ *         <th scope="row"><code>"yyMMddHHmmssZ"</code>
  *         <td><code>010704120856-0700</code>
  *     <tr>
- *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
+ *         <th scope="row"><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
  *         <td><code>2001-07-04T12:08:56.235-0700</code>
- *     <tr style="background-color: rgb(238, 238, 255);">
- *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
+ *     <tr>
+ *         <th scope="row"><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
  *         <td><code>2001-07-04T12:08:56.235-07:00</code>
  *     <tr>
- *         <td><code>"YYYY-'W'ww-u"</code>
+ *         <th scope="row"><code>"YYYY-'W'ww-u"</code>
  *         <td><code>2001-W27-3</code>
+ * </tbody>
  * </table>
  * </blockquote>
  *
- * <h4><a name="synchronization">Synchronization</a></h4>
+ * <h4><a id="synchronization">Synchronization</a></h4>
  *
  * <p>
  * Date formats are not synchronized.
@@ -447,12 +464,13 @@
  * If multiple threads access a format concurrently, it must be synchronized
  * externally.
  *
- * @see          <a href="https://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html">Java Tutorial</a>
+ * @see          <a href="http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html">Java Tutorial</a>
  * @see          java.util.Calendar
  * @see          java.util.TimeZone
  * @see          DateFormat
  * @see          DateFormatSymbols
  * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
+ * @since 1.1
  */
 public class SimpleDateFormat extends DateFormat {
 
@@ -477,7 +495,7 @@
      * and the highest allowable <code>serialVersionOnStream</code>
      * is written.
      * @serial
-     * @since JDK1.1.4
+     * @since 1.1.4
      */
     private int serialVersionOnStream = currentSerialVersion;
 
@@ -492,19 +510,19 @@
      * Saved numberFormat and pattern.
      * @see SimpleDateFormat#checkNegativeNumberExpression
      */
-    transient private NumberFormat originalNumberFormat;
-    transient private String originalNumberPattern;
+    private transient NumberFormat originalNumberFormat;
+    private transient String originalNumberPattern;
 
     /**
      * The minus sign to be used with format and parse.
      */
-    transient private char minusSign = '-';
+    private transient char minusSign = '-';
 
     /**
      * True when a negative sign follows a number.
      * (True as default in Arabic.)
      */
-    transient private boolean hasFollowingMinusSign = false;
+    private transient boolean hasFollowingMinusSign = false;
 
     // BEGIN Android-removed: App compat for formatting pattern letter M.
     // OpenJDK forces the standalone form of month when patterns contain pattern M only.
@@ -514,27 +532,27 @@
     /**
      * True if standalone form needs to be used.
      *
-    transient private boolean forceStandaloneForm = false;
+    private transient boolean forceStandaloneForm = false;
     */
     // END Android-removed: App compat for formatting pattern letter M.
 
     /**
      * The compiled pattern.
      */
-    transient private char[] compiledPattern;
+    private transient char[] compiledPattern;
 
     /**
      * Tags for the compiled pattern.
      */
-    private final static int TAG_QUOTE_ASCII_CHAR       = 100;
-    private final static int TAG_QUOTE_CHARS            = 101;
+    private static final int TAG_QUOTE_ASCII_CHAR       = 100;
+    private static final int TAG_QUOTE_CHARS            = 101;
 
     /**
      * Locale dependent digit zero.
      * @see #zeroPaddingNumber
      * @see java.text.DecimalFormatSymbols#getZeroDigit
      */
-    transient private char zeroDigit;
+    private transient char zeroDigit;
 
     /**
      * The symbols used by this formatter for week names, month names,
@@ -549,11 +567,11 @@
      * <code>defaultCenturyStart</code>, which may be any date.  May
      * not be null.
      * @serial
-     * @since JDK1.1.4
+     * @since 1.1.4
      */
     private Date defaultCenturyStart;
 
-    transient private int defaultCenturyStartYear;
+    private transient int defaultCenturyStartYear;
 
     private static final int MILLIS_PER_MINUTE = 60 * 1000;
 
@@ -624,17 +642,17 @@
     }
 
     private static String getDateTimeFormat(int timeStyle, int dateStyle, Locale locale) {
-        LocaleData localeData = LocaleData.get(locale);
+        SimpleDateFormatData data = SimpleDateFormatData.getInstance(locale);
         if ((timeStyle >= 0) && (dateStyle >= 0)) {
             Object[] dateTimeArgs = {
-                localeData.getDateFormat(dateStyle),
-                localeData.getTimeFormat(timeStyle),
+                    data.getDateFormat(dateStyle),
+                    data.getTimeFormat(timeStyle),
             };
             return MessageFormat.format("{0} {1}", dateTimeArgs);
         } else if (timeStyle >= 0) {
-            return localeData.getTimeFormat(timeStyle);
+            return data.getTimeFormat(timeStyle);
         } else if (dateStyle >= 0) {
-            return localeData.getDateFormat(dateStyle);
+            return data.getDateFormat(dateStyle);
         } else {
             throw new IllegalArgumentException("No date or time style specified");
         }
@@ -737,7 +755,7 @@
             // However, the calendar should use the current default TimeZone.
             // If this is not contained in the locale zone strings, then the zone
             // will be formatted using generic GMT+/-H:MM nomenclature.
-            calendar = Calendar.getInstance(TimeZone.getDefault(), loc);
+            calendar = Calendar.getInstance(loc);
         }
     }
 
@@ -1015,6 +1033,7 @@
      * @param startDate During parsing, two digit years will be placed in the range
      * <code>startDate</code> to <code>startDate + 100 years</code>.
      * @see #get2DigitYearStart
+     * @throws NullPointerException if {@code startDate} is {@code null}.
      * @since 1.2
      */
     public void set2DigitYearStart(Date startDate) {
@@ -1040,10 +1059,21 @@
      *
      * @param date the date-time value to be formatted into a date-time string.
      * @param toAppendTo where the new date-time text is to be appended.
-     * @param pos the formatting position. On input: an alignment field,
-     * if desired. On output: the offsets of the alignment field.
+     * @param pos keeps track on the position of the field within
+     * the returned string. For example, given a date-time text
+     * {@code "1996.07.10 AD at 15:08:56 PDT"}, if the given {@code fieldPosition}
+     * is {@link DateFormat#YEAR_FIELD}, the begin index and end index of
+     * {@code fieldPosition} will be set to 0 and 4, respectively.
+     * Notice that if the same date-time field appears more than once in a
+     * pattern, the {@code fieldPosition} will be set for the first occurrence
+     * of that date-time field. For instance, formatting a {@code Date} to the
+     * date-time string {@code "1 PM PDT (Pacific Daylight Time)"} using the
+     * pattern {@code "h a z (zzzz)"} and the alignment field
+     * {@link DateFormat#TIMEZONE_FIELD}, the begin index and end index of
+     * {@code fieldPosition} will be set to 5 and 8, respectively, for the
+     * first occurrence of the timezone pattern character {@code 'z'}.
      * @return the formatted date-time string.
-     * @exception NullPointerException if the given {@code date} is {@code null}.
+     * @exception NullPointerException if any of the parameters is {@code null}.
      */
     @Override
     public StringBuffer format(Date date, StringBuffer toAppendTo,
@@ -1790,22 +1820,18 @@
 
                 if (i < compiledPattern.length) {
                     int nextTag = compiledPattern[i] >>> 8;
-                    if (!(nextTag == TAG_QUOTE_ASCII_CHAR ||
-                          nextTag == TAG_QUOTE_CHARS)) {
-                        obeyCount = true;
-                    }
+                    int nextCount = compiledPattern[i] & 0xff;
+                    obeyCount = shouldObeyCount(nextTag, nextCount);
 
                     if (hasFollowingMinusSign &&
                         (nextTag == TAG_QUOTE_ASCII_CHAR ||
                          nextTag == TAG_QUOTE_CHARS)) {
-                        int c;
-                        if (nextTag == TAG_QUOTE_ASCII_CHAR) {
-                            c = compiledPattern[i] & 0xff;
-                        } else {
-                            c = compiledPattern[i+1];
+
+                        if (nextTag != TAG_QUOTE_ASCII_CHAR) {
+                            nextCount = compiledPattern[i+1];
                         }
 
-                        if (c == minusSign) {
+                        if (nextCount == minusSign) {
                             useFollowingMinusSignAsDelimiter = true;
                         }
                     }
@@ -1848,6 +1874,36 @@
         return parsedDate;
     }
 
+    /* If the next tag/pattern is a <Numeric_Field> then the parser
+     * should consider the count of digits while parsing the contigous digits
+     * for the current tag/pattern
+     */
+    private boolean shouldObeyCount(int tag, int count) {
+        switch (tag) {
+            case PATTERN_MONTH:
+            case PATTERN_MONTH_STANDALONE:
+                return count <= 2;
+            case PATTERN_YEAR:
+            case PATTERN_DAY_OF_MONTH:
+            case PATTERN_HOUR_OF_DAY1:
+            case PATTERN_HOUR_OF_DAY0:
+            case PATTERN_MINUTE:
+            case PATTERN_SECOND:
+            case PATTERN_MILLISECOND:
+            case PATTERN_DAY_OF_YEAR:
+            case PATTERN_DAY_OF_WEEK_IN_MONTH:
+            case PATTERN_WEEK_OF_YEAR:
+            case PATTERN_WEEK_OF_MONTH:
+            case PATTERN_HOUR1:
+            case PATTERN_HOUR0:
+            case PATTERN_WEEK_YEAR:
+            case PATTERN_ISO_DAY_OF_WEEK:
+                return true;
+            default:
+                return false;
+        }
+    }
+
     /**
      * Private code-size reduction function used by subParse.
      * @param text the time text being parsed.
@@ -1952,6 +2008,17 @@
             // Checking long and short zones [1 & 2],
             // and long and short daylight [3 & 4].
             String zoneName = zoneNames[i];
+            // Android-removed: App compat. Don't retrieve more data when data missing in DFS.
+            //  It may have risk of app compat issue, and no significant benefit on Android because
+            //  the DFS and TimeZoneNameUtility will both come from ICU / CLDR on Android.
+            /*
+            if (zoneName.isEmpty()) {
+                // fill in by retrieving single name
+                zoneName = TimeZoneNameUtility.retrieveDisplayName(
+                                zoneNames[0], i >= 3, i % 2, locale);
+                zoneNames[i] = zoneName;
+            }
+            */
             if (text.regionMatches(true, start,
                                    zoneName, 0, zoneName.length())) {
                 return i;
@@ -2254,6 +2321,7 @@
             if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
                 patternCharIndex == PATTERN_HOUR1 ||
                 (patternCharIndex == PATTERN_MONTH && count <= 2) ||
+                (patternCharIndex == PATTERN_MONTH_STANDALONE && count <= 2) ||
                 patternCharIndex == PATTERN_YEAR ||
                 patternCharIndex == PATTERN_WEEK_YEAR) {
                 // It would be good to unify this with the obeyCount logic below,
@@ -2374,6 +2442,21 @@
                         return index;
                     }
                 }
+                break parsing;
+
+            case PATTERN_MONTH_STANDALONE: // 'L'
+                if (count <= 2) {
+                    // Don't want to parse the month if it is a string
+                    // while pattern uses numeric style: L or LL
+                    //[we computed 'value' above.]
+                    calb.set(Calendar.MONTH, value - 1);
+                    return pos.index;
+                }
+                Map<String, Integer> maps = getDisplayNamesMap(field, locale);
+                if ((index = matchString(text, start, field, maps, calb)) > 0) {
+                    return index;
+                }
+                break parsing;
             */
             {
                 final int idx = parseMonth(text, count, value, start, field, pos,
@@ -2936,7 +3019,7 @@
     /**
      * After reading an object from the input stream, the format
      * pattern in the object is verified.
-     * <p>
+     *
      * @exception InvalidObjectException if the pattern is invalid
      */
     private void readObject(ObjectInputStream stream)
diff --git a/ojluni/src/main/java/java/text/StringCharacterIterator.java b/ojluni/src/main/java/java/text/StringCharacterIterator.java
index 66b5be6..b5d510c 100644
--- a/ojluni/src/main/java/java/text/StringCharacterIterator.java
+++ b/ojluni/src/main/java/java/text/StringCharacterIterator.java
@@ -47,6 +47,7 @@
  * entire <code>String</code>.
  *
  * @see CharacterIterator
+ * @since 1.1
  */
 
 public final class StringCharacterIterator implements CharacterIterator
diff --git a/ojluni/src/main/java/java/time/Clock.java b/ojluni/src/main/java/java/time/Clock.java
index b112784..37e723e 100644
--- a/ojluni/src/main/java/java/time/Clock.java
+++ b/ojluni/src/main/java/java/time/Clock.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,12 +61,15 @@
  */
 package java.time;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import static java.time.LocalTime.NANOS_PER_MINUTE;
 import static java.time.LocalTime.NANOS_PER_SECOND;
-
+import static java.time.LocalTime.NANOS_PER_MILLI;
 import java.io.Serializable;
 import java.util.Objects;
 import java.util.TimeZone;
+import jdk.internal.misc.VM;
 
 /**
  * A clock providing access to the current instant, date and time using a time-zone.
@@ -124,10 +127,13 @@
  * document whether or not they do support serialization.
  *
  * @implNote
- * The clock implementation provided here is based on {@link System#currentTimeMillis()}.
- * That method provides little to no guarantee about the accuracy of the clock.
- * Applications requiring a more accurate clock must implement this abstract class
- * themselves using a different external clock, such as an NTP server.
+ * The clock implementation provided here is based on the same underlying clock
+ * as {@link System#currentTimeMillis()}, but may have a precision finer than
+ * milliseconds if available.
+ * However, little to no guarantee is provided about the accuracy of the
+ * underlying clock. Applications requiring a more accurate clock must implement
+ * this abstract class themselves using a different external clock, such as an
+ * NTP server.
  *
  * @since 1.8
  */
@@ -152,7 +158,7 @@
      * @return a clock that uses the best available system clock in the UTC zone, not null
      */
     public static Clock systemUTC() {
-        return new SystemClock(ZoneOffset.UTC);
+        return SystemClock.UTC;
     }
 
     /**
@@ -179,7 +185,7 @@
     }
 
     /**
-     * Obtains a clock that returns the current instant using best available
+     * Obtains a clock that returns the current instant using the best available
      * system clock.
      * <p>
      * This clock is based on the best available system clock.
@@ -195,13 +201,41 @@
      */
     public static Clock system(ZoneId zone) {
         Objects.requireNonNull(zone, "zone");
+        if (zone == ZoneOffset.UTC) {
+            return SystemClock.UTC;
+        }
         return new SystemClock(zone);
     }
 
     //-------------------------------------------------------------------------
     /**
+     * Obtains a clock that returns the current instant ticking in whole milliseconds
+     * using the best available system clock.
+     * <p>
+     * This clock will always have the nano-of-second field truncated to milliseconds.
+     * This ensures that the visible time ticks in whole milliseconds.
+     * The underlying clock is the best available system clock, equivalent to
+     * using {@link #system(ZoneId)}.
+     * <p>
+     * Implementations may use a caching strategy for performance reasons.
+     * As such, it is possible that the start of the millisecond observed via this
+     * clock will be later than that observed directly via the underlying clock.
+     * <p>
+     * The returned implementation is immutable, thread-safe and {@code Serializable}.
+     * It is equivalent to {@code tick(system(zone), Duration.ofMillis(1))}.
+     *
+     * @param zone  the time-zone to use to convert the instant to date-time, not null
+     * @return a clock that ticks in whole milliseconds using the specified zone, not null
+     * @since 9
+     */
+    public static Clock tickMillis(ZoneId zone) {
+        return new TickClock(system(zone), NANOS_PER_MILLI);
+    }
+
+    //-------------------------------------------------------------------------
+    /**
      * Obtains a clock that returns the current instant ticking in whole seconds
-     * using best available system clock.
+     * using the best available system clock.
      * <p>
      * This clock will always have the nano-of-second field set to zero.
      * This ensures that the visible time ticks in whole seconds.
@@ -224,7 +258,7 @@
 
     /**
      * Obtains a clock that returns the current instant ticking in whole minutes
-     * using best available system clock.
+     * using the best available system clock.
      * <p>
      * This clock will always have the nano-of-second and second-of-minute fields set to zero.
      * This ensures that the visible time ticks in whole minutes.
@@ -446,10 +480,24 @@
      */
     static final class SystemClock extends Clock implements Serializable {
         private static final long serialVersionUID = 6740630888130243051L;
+        private static final long OFFSET_SEED =
+                System.currentTimeMillis()/1000 - 1024; // initial offest
+        static final SystemClock UTC = new SystemClock(ZoneOffset.UTC);
+
         private final ZoneId zone;
+        // We don't actually need a volatile here.
+        // We don't care if offset is set or read concurrently by multiple
+        // threads - we just need a value which is 'recent enough' - in other
+        // words something that has been updated at least once in the last
+        // 2^32 secs (~136 years). And even if we by chance see an invalid
+        // offset, the worst that can happen is that we will get a -1 value
+        // from getNanoTimeAdjustment, forcing us to update the offset
+        // once again.
+        private transient long offset;
 
         SystemClock(ZoneId zone) {
             this.zone = zone;
+            this.offset = OFFSET_SEED;
         }
         @Override
         public ZoneId getZone() {
@@ -464,11 +512,50 @@
         }
         @Override
         public long millis() {
+            // System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset)
+            // use the same time source - System.currentTimeMillis() simply
+            // limits the resolution to milliseconds.
+            // So we take the faster path and call System.currentTimeMillis()
+            // directly - in order to avoid the performance penalty of
+            // VM.getNanoTimeAdjustment(offset) which is less efficient.
             return System.currentTimeMillis();
         }
         @Override
         public Instant instant() {
-            return Instant.ofEpochMilli(millis());
+            // Take a local copy of offset. offset can be updated concurrently
+            // by other threads (even if we haven't made it volatile) so we will
+            // work with a local copy.
+            long localOffset = offset;
+            long adjustment = VM.getNanoTimeAdjustment(localOffset);
+
+            if (adjustment == -1) {
+                // -1 is a sentinel value returned by VM.getNanoTimeAdjustment
+                // when the offset it is given is too far off the current UTC
+                // time. In principle, this should not happen unless the
+                // JVM has run for more than ~136 years (not likely) or
+                // someone is fiddling with the system time, or the offset is
+                // by chance at 1ns in the future (very unlikely).
+                // We can easily recover from all these conditions by bringing
+                // back the offset in range and retry.
+
+                // bring back the offset in range. We use -1024 to make
+                // it more unlikely to hit the 1ns in the future condition.
+                localOffset = System.currentTimeMillis()/1000 - 1024;
+
+                // retry
+                adjustment = VM.getNanoTimeAdjustment(localOffset);
+
+                if (adjustment == -1) {
+                    // Should not happen: we just recomputed a new offset.
+                    // It should have fixed the issue.
+                    throw new InternalError("Offset " + localOffset + " is not in range");
+                } else {
+                    // OK - recovery succeeded. Update the offset for the
+                    // next call...
+                    offset = localOffset;
+                }
+            }
+            return Instant.ofEpochSecond(localOffset, adjustment);
         }
         @Override
         public boolean equals(Object obj) {
@@ -485,6 +572,12 @@
         public String toString() {
             return "SystemClock[" + zone + "]";
         }
+        private void readObject(ObjectInputStream is)
+                throws IOException, ClassNotFoundException {
+            // ensure that offset is initialized
+            is.defaultReadObject();
+            offset = OFFSET_SEED;
+        }
     }
 
     //-----------------------------------------------------------------------
@@ -493,7 +586,7 @@
      * This is typically used for testing.
      */
     static final class FixedClock extends Clock implements Serializable {
-       private static final long serialVersionUID = 7430389292664866958L;
+        private static final long serialVersionUID = 7430389292664866958L;
         private final Instant instant;
         private final ZoneId zone;
 
@@ -543,7 +636,7 @@
      * Implementation of a clock that adds an offset to an underlying clock.
      */
     static final class OffsetClock extends Clock implements Serializable {
-       private static final long serialVersionUID = 2007484719125426256L;
+        private static final long serialVersionUID = 2007484719125426256L;
         private final Clock baseClock;
         private final Duration offset;
 
diff --git a/ojluni/src/main/java/java/time/DayOfWeek.java b/ojluni/src/main/java/java/time/DayOfWeek.java
index ee49f8a..43dc3aa 100644
--- a/ojluni/src/main/java/java/time/DayOfWeek.java
+++ b/ojluni/src/main/java/java/time/DayOfWeek.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/Instant.java b/ojluni/src/main/java/java/time/Instant.java
index c87ac18..e507b35 100644
--- a/ojluni/src/main/java/java/time/Instant.java
+++ b/ojluni/src/main/java/java/time/Instant.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -305,7 +305,7 @@
      * This method allows an arbitrary number of nanoseconds to be passed in.
      * The factory will alter the values of the second and nanosecond in order
      * to ensure that the stored nanosecond is in the range 0 to 999,999,999.
-     * For example, the following will result in the exactly the same instant:
+     * For example, the following will result in exactly the same instant:
      * <pre>
      *  Instant.ofEpochSecond(3, 1);
      *  Instant.ofEpochSecond(4, -999_999_999);
@@ -336,7 +336,7 @@
      */
     public static Instant ofEpochMilli(long epochMilli) {
         long secs = Math.floorDiv(epochMilli, 1000);
-        int mos = (int)Math.floorMod(epochMilli, 1000);
+        int mos = Math.floorMod(epochMilli, 1000);
         return create(secs, mos * 1000_000);
     }
 
@@ -555,7 +555,6 @@
                 case NANO_OF_SECOND: return nanos;
                 case MICRO_OF_SECOND: return nanos / 1000;
                 case MILLI_OF_SECOND: return nanos / 1000_000;
-                case INSTANT_SECONDS: INSTANT_SECONDS.checkValidIntValue(seconds);
             }
             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
         }
@@ -605,7 +604,7 @@
      * <p>
      * The epoch second count is a simple incrementing count of seconds where
      * second 0 is 1970-01-01T00:00:00Z.
-     * The nanosecond part of the day is returned by {@code getNanosOfSecond}.
+     * The nanosecond part is returned by {@link #getNano}.
      *
      * @return the seconds from the epoch of 1970-01-01T00:00:00Z
      */
@@ -618,7 +617,7 @@
      * of the second.
      * <p>
      * The nanosecond-of-second value measures the total number of nanoseconds from
-     * the second returned by {@code getEpochSecond}.
+     * the second returned by {@link #getEpochSecond}.
      *
      * @return the nanoseconds within the second, always positive, never exceeds 999,999,999
      */
@@ -752,7 +751,7 @@
             throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
         }
         long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos;
-        long result = (nod / dur) * dur;
+        long result = Math.floorDiv(nod, dur) * dur;
         return plusNanos(result - nod);
     }
 
@@ -793,33 +792,33 @@
      * The supported fields behave as follows:
      * <ul>
      * <li>{@code NANOS} -
-     *  Returns a {@code Instant} with the specified number of nanoseconds added.
+     *  Returns an {@code Instant} with the specified number of nanoseconds added.
      *  This is equivalent to {@link #plusNanos(long)}.
      * <li>{@code MICROS} -
-     *  Returns a {@code Instant} with the specified number of microseconds added.
+     *  Returns an {@code Instant} with the specified number of microseconds added.
      *  This is equivalent to {@link #plusNanos(long)} with the amount
      *  multiplied by 1,000.
      * <li>{@code MILLIS} -
-     *  Returns a {@code Instant} with the specified number of milliseconds added.
+     *  Returns an {@code Instant} with the specified number of milliseconds added.
      *  This is equivalent to {@link #plusNanos(long)} with the amount
      *  multiplied by 1,000,000.
      * <li>{@code SECONDS} -
-     *  Returns a {@code Instant} with the specified number of seconds added.
+     *  Returns an {@code Instant} with the specified number of seconds added.
      *  This is equivalent to {@link #plusSeconds(long)}.
      * <li>{@code MINUTES} -
-     *  Returns a {@code Instant} with the specified number of minutes added.
+     *  Returns an {@code Instant} with the specified number of minutes added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 60.
      * <li>{@code HOURS} -
-     *  Returns a {@code Instant} with the specified number of hours added.
+     *  Returns an {@code Instant} with the specified number of hours added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 3,600.
      * <li>{@code HALF_DAYS} -
-     *  Returns a {@code Instant} with the specified number of half-days added.
+     *  Returns an {@code Instant} with the specified number of half-days added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 43,200 (12 hours).
      * <li>{@code DAYS} -
-     *  Returns a {@code Instant} with the specified number of days added.
+     *  Returns an {@code Instant} with the specified number of days added.
      *  This is equivalent to {@link #plusSeconds(long)} with the amount
      *  multiplied by 86,400 (24 hours).
      * </ul>
@@ -952,7 +951,7 @@
     /**
      * Returns a copy of this instant with the specified amount subtracted.
      * <p>
-     * This returns a {@code Instant}, based on this one, with the amount
+     * This returns an {@code Instant}, based on this one, with the amount
      * in terms of the unit subtracted. If it is not possible to subtract the amount,
      * because the unit is not supported or for some other reason, an exception is thrown.
      * <p>
@@ -1100,7 +1099,7 @@
      * complete units between the two instants.
      * The {@code Temporal} passed to this method is converted to a
      * {@code Instant} using {@link #from(TemporalAccessor)}.
-     * For example, the amount in days between two dates can be calculated
+     * For example, the amount in seconds between two dates can be calculated
      * using {@code startInstant.until(endInstant, SECONDS)}.
      * <p>
      * There are two equivalent ways of using this method.
diff --git a/ojluni/src/main/java/java/time/LocalDate.java b/ojluni/src/main/java/java/time/LocalDate.java
index c23b270..17325d5 100644
--- a/ojluni/src/main/java/java/time/LocalDate.java
+++ b/ojluni/src/main/java/java/time/LocalDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,6 +74,7 @@
 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
 import static java.time.temporal.ChronoField.YEAR;
 
+import dalvik.annotation.codegen.CovariantReturnType;
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
@@ -82,6 +83,7 @@
 import java.io.Serializable;
 import java.time.chrono.ChronoLocalDate;
 import java.time.chrono.Era;
+import java.time.chrono.IsoEra;
 import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
@@ -100,6 +102,8 @@
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
 import java.util.Objects;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
 
 // Android-changed: removed ValueBased paragraph.
 /**
@@ -141,6 +145,10 @@
      * This could be used by an application as a "far future" date.
      */
     public static final LocalDate MAX = LocalDate.of(Year.MAX_VALUE, 12, 31);
+    /**
+     * The epoch year {@code LocalDate}, '1970-01-01'.
+     */
+    public static final LocalDate EPOCH = LocalDate.of(1970, 1, 1);
 
     /**
      * Serialization version.
@@ -214,12 +222,8 @@
      */
     public static LocalDate now(Clock clock) {
         Objects.requireNonNull(clock, "clock");
-        // inline to avoid creating object and Instant checks
         final Instant now = clock.instant();  // called once
-        ZoneOffset offset = clock.getZone().getRules().getOffset(now);
-        long epochSec = now.getEpochSecond() + offset.getTotalSeconds();  // overflow caught later
-        long epochDay = Math.floorDiv(epochSec, SECONDS_PER_DAY);
-        return LocalDate.ofEpochDay(epochDay);
+        return ofInstant(now, clock.getZone());
     }
 
     //-----------------------------------------------------------------------
@@ -294,6 +298,31 @@
 
     //-----------------------------------------------------------------------
     /**
+     * Obtains an instance of {@code LocalDate} from an {@code Instant} and zone ID.
+     * <p>
+     * This creates a local date based on the specified instant.
+     * First, the offset from UTC/Greenwich is obtained using the zone ID and instant,
+     * which is simple as there is only one valid offset for each instant.
+     * Then, the instant and offset are used to calculate the local date.
+     *
+     * @param instant  the instant to create the date from, not null
+     * @param zone  the time-zone, which may be an offset, not null
+     * @return the local date, not null
+     * @throws DateTimeException if the result exceeds the supported range
+     * @since 9
+     */
+    public static LocalDate ofInstant(Instant instant, ZoneId zone) {
+        Objects.requireNonNull(instant, "instant");
+        Objects.requireNonNull(zone, "zone");
+        ZoneRules rules = zone.getRules();
+        ZoneOffset offset = rules.getOffset(instant);
+        long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
+        long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);
+        return ofEpochDay(localEpochDay);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
      * Obtains an instance of {@code LocalDate} from the epoch day count.
      * <p>
      * This returns a {@code LocalDate} with the specified epoch-day.
@@ -305,6 +334,7 @@
      * @throws DateTimeException if the epoch day exceeds the supported date range
      */
     public static LocalDate ofEpochDay(long epochDay) {
+        EPOCH_DAY.checkValidValue(epochDay);
         long zeroDay = epochDay + DAYS_0000_TO_1970;
         // find the march-based year
         zeroDay -= 60;  // adjust to 0000-03-01 so leap day is at end of four year cycle
@@ -594,7 +624,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date, except {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH}
-     * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
+     * which are too large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
@@ -706,15 +736,14 @@
      * Users of this class should typically ignore this method as it exists primarily
      * to fulfill the {@link ChronoLocalDate} contract where it is necessary to support
      * the Japanese calendar system.
-     * <p>
-     * The returned era will be a singleton capable of being compared with the constants
-     * in {@link IsoChronology} using the {@code ==} operator.
      *
-     * @return the {@code IsoChronology} era constant applicable at this date, not null
+     * @return the IsoEra applicable at this date, not null
      */
     @Override // override for Javadoc
+    // Android-changed: To match OpenJDK 11 API, this API returns IsoEra type after Android T.
+    @CovariantReturnType(returnType = java.time.chrono.IsoEra.class, presentAfter = 33)
     public Era getEra() {
-        return ChronoLocalDate.super.getEra();
+        return (getYear() >= 1 ? IsoEra.CE : IsoEra.BCE);
     }
 
     /**
@@ -796,7 +825,7 @@
      * @return the day-of-week, not null
      */
     public DayOfWeek getDayOfWeek() {
-        int dow0 = (int)Math.floorMod(toEpochDay() + 3, 7);
+        int dow0 = Math.floorMod(toEpochDay() + 3, 7);
         return DayOfWeek.of(dow0 + 1);
     }
 
@@ -1299,7 +1328,7 @@
         long monthCount = year * 12L + (month - 1);
         long calcMonths = monthCount + monthsToAdd;  // safe overflow
         int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));
-        int newMonth = (int)Math.floorMod(calcMonths, 12) + 1;
+        int newMonth = Math.floorMod(calcMonths, 12) + 1;
         return resolvePreviousValid(newYear, newMonth, day);
     }
 
@@ -1341,6 +1370,23 @@
         if (daysToAdd == 0) {
             return this;
         }
+        long dom = day + daysToAdd;
+        if (dom > 0) {
+            if (dom <= 28) {
+                return new LocalDate(year, month, (int) dom);
+            } else if (dom <= 59) { // 59th Jan is 28th Feb, 59th Feb is 31st Mar
+                long monthLen = lengthOfMonth();
+                if (dom <= monthLen) {
+                    return new LocalDate(year, month, (int) dom);
+                } else if (month < 12) {
+                    return new LocalDate(year, month + 1, (int) (dom - monthLen));
+                } else {
+                    YEAR.checkValidValue(year + 1);
+                    return new LocalDate(year + 1, 1, (int) (dom - monthLen));
+                }
+            }
+        }
+
         long mjDay = Math.addExact(toEpochDay(), daysToAdd);
         return LocalDate.ofEpochDay(mjDay);
     }
@@ -1671,6 +1717,89 @@
     }
 
     /**
+     * Returns a sequential ordered stream of dates. The returned stream starts from this date
+     * (inclusive) and goes to {@code endExclusive} (exclusive) by an incremental step of 1 day.
+     * <p>
+     * This method is equivalent to {@code datesUntil(endExclusive, Period.ofDays(1))}.
+     *
+     * @param endExclusive  the end date, exclusive, not null
+     * @return a sequential {@code Stream} for the range of {@code LocalDate} values
+     * @throws IllegalArgumentException if end date is before this date
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive) {
+        long end = endExclusive.toEpochDay();
+        long start = toEpochDay();
+        if (end < start) {
+            throw new IllegalArgumentException(endExclusive + " < " + this);
+        }
+        return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay);
+    }
+
+    /**
+     * Returns a sequential ordered stream of dates by given incremental step. The returned stream
+     * starts from this date (inclusive) and goes to {@code endExclusive} (exclusive).
+     * <p>
+     * The n-th date which appears in the stream is equal to {@code this.plus(step.multipliedBy(n))}
+     * (but the result of step multiplication never overflows). For example, if this date is
+     * {@code 2015-01-31}, the end date is {@code 2015-05-01} and the step is 1 month, then the
+     * stream contains {@code 2015-01-31}, {@code 2015-02-28}, {@code 2015-03-31}, and
+     * {@code 2015-04-30}.
+     *
+     * @param endExclusive  the end date, exclusive, not null
+     * @param step  the non-zero, non-negative {@code Period} which represents the step.
+     * @return a sequential {@code Stream} for the range of {@code LocalDate} values
+     * @throws IllegalArgumentException if step is zero, or {@code step.getDays()} and
+     *             {@code step.toTotalMonths()} have opposite sign, or end date is before this date
+     *             and step is positive, or end date is after this date and step is negative
+     * @since 9
+     */
+    public Stream<LocalDate> datesUntil(LocalDate endExclusive, Period step) {
+        if (step.isZero()) {
+            throw new IllegalArgumentException("step is zero");
+        }
+        long end = endExclusive.toEpochDay();
+        long start = toEpochDay();
+        long until = end - start;
+        long months = step.toTotalMonths();
+        long days = step.getDays();
+        if ((months < 0 && days > 0) || (months > 0 && days < 0)) {
+            throw new IllegalArgumentException("period months and days are of opposite sign");
+        }
+        if (until == 0) {
+            return Stream.empty();
+        }
+        int sign = months > 0 || days > 0 ? 1 : -1;
+        if (sign < 0 ^ until < 0) {
+            throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this);
+        }
+        if (months == 0) {
+            long steps = (until - sign) / days; // non-negative
+            return LongStream.rangeClosed(0, steps).mapToObj(
+                    n -> LocalDate.ofEpochDay(start + n * days));
+        }
+        // 48699/1600 = 365.2425/12, no overflow, non-negative result
+        long steps = until * 1600 / (months * 48699 + days * 1600) + 1;
+        long addMonths = months * steps;
+        long addDays = days * steps;
+        long maxAddMonths = months > 0 ? MAX.getProlepticMonth() - getProlepticMonth()
+                : getProlepticMonth() - MIN.getProlepticMonth();
+        // adjust steps estimation
+        if (addMonths * sign > maxAddMonths
+                || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
+            steps--;
+            addMonths -= months;
+            addDays -= days;
+            if (addMonths * sign > maxAddMonths
+                    || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) {
+                steps--;
+            }
+        }
+        return LongStream.rangeClosed(0, steps).mapToObj(
+                n -> this.plusMonths(months * n).plusDays(days * n));
+    }
+
+    /**
      * Formats this date using the specified formatter.
      * <p>
      * This date will be passed to the formatter to produce a string.
@@ -1840,6 +1969,29 @@
         return total - DAYS_0000_TO_1970;
     }
 
+    /**
+     * Converts this {@code LocalDate} to the number of seconds since the epoch
+     * of 1970-01-01T00:00:00Z.
+     * <p>
+     * This combines this local date with the specified time and
+     * offset to calculate the epoch-second value, which is the
+     * number of elapsed seconds from 1970-01-01T00:00:00Z.
+     * Instants on the time-line after the epoch are positive, earlier
+     * are negative.
+     *
+     * @param time the local time, not null
+     * @param offset the zone offset, not null
+     * @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative
+     * @since 9
+     */
+    public long toEpochSecond(LocalTime time, ZoneOffset offset) {
+        Objects.requireNonNull(time, "time");
+        Objects.requireNonNull(offset, "offset");
+        long secs = toEpochDay() * SECONDS_PER_DAY + time.toSecondOfDay();
+        secs -= offset.getTotalSeconds();
+        return secs;
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Compares this date to another date.
diff --git a/ojluni/src/main/java/java/time/LocalDateTime.java b/ojluni/src/main/java/java/time/LocalDateTime.java
index 5821ffd..ee0b7d8 100644
--- a/ojluni/src/main/java/java/time/LocalDateTime.java
+++ b/ojluni/src/main/java/java/time/LocalDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -412,7 +412,7 @@
         NANO_OF_SECOND.checkValidValue(nanoOfSecond);
         long localSecond = epochSecond + offset.getTotalSeconds();  // overflow caught later
         long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);
-        int secsOfDay = (int)Math.floorMod(localSecond, SECONDS_PER_DAY);
+        int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
         LocalDate date = LocalDate.ofEpochDay(localEpochDay);
         LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + nanoOfSecond);
         return new LocalDateTime(date, time);
@@ -659,7 +659,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
      * {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH} which are too large to fit in
-     * an {@code int} and throw a {@code DateTimeException}.
+     * an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
@@ -1401,8 +1401,8 @@
      * </ol>
      * <p>
      * For example, 2008-02-29 (leap year) minus one year would result in the
-     * invalid date 2009-02-29 (standard year). Instead of returning an invalid
-     * result, the last valid day of the month, 2009-02-28, is selected instead.
+     * invalid date 2007-02-29 (standard year). Instead of returning an invalid
+     * result, the last valid day of the month, 2007-02-28, is selected instead.
      * <p>
      * This instance is immutable and unaffected by this method call.
      *
@@ -1425,8 +1425,8 @@
      * </ol>
      * <p>
      * For example, 2007-03-31 minus one month would result in the invalid date
-     * 2007-04-31. Instead of returning an invalid result, the last valid day
-     * of the month, 2007-04-30, is selected instead.
+     * 2007-02-31. Instead of returning an invalid result, the last valid day
+     * of the month, 2007-02-28, is selected instead.
      * <p>
      * This instance is immutable and unaffected by this method call.
      *
diff --git a/ojluni/src/main/java/java/time/Month.java b/ojluni/src/main/java/java/time/Month.java
index 57382cd..1a0d9ee 100644
--- a/ojluni/src/main/java/java/time/Month.java
+++ b/ojluni/src/main/java/java/time/Month.java
@@ -379,7 +379,7 @@
 
     //-----------------------------------------------------------------------
     /**
-     * Returns the month-of-year that is the specified number of quarters after this one.
+     * Returns the month-of-year that is the specified number of months after this one.
      * <p>
      * The calculation rolls around the end of the year from December to January.
      * The specified period may be negative.
diff --git a/ojluni/src/main/java/java/time/MonthDay.java b/ojluni/src/main/java/java/time/MonthDay.java
index 50bc2c8..e1a8d4d 100644
--- a/ojluni/src/main/java/java/time/MonthDay.java
+++ b/ojluni/src/main/java/java/time/MonthDay.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/OffsetDateTime.java b/ojluni/src/main/java/java/time/OffsetDateTime.java
index c2c8e0a..f9b6205 100644
--- a/ojluni/src/main/java/java/time/OffsetDateTime.java
+++ b/ojluni/src/main/java/java/time/OffsetDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,7 +101,7 @@
  * {@code OffsetDateTime} is an immutable representation of a date-time with an offset.
  * This class stores all date and time fields, to a precision of nanoseconds,
  * as well as the offset from UTC/Greenwich. For example, the value
- * "2nd October 2007 at 13:45.30.123456789 +02:00" can be stored in an {@code OffsetDateTime}.
+ * "2nd October 2007 at 13:45:30.123456789 +02:00" can be stored in an {@code OffsetDateTime}.
  * <p>
  * {@code OffsetDateTime}, {@link java.time.ZonedDateTime} and {@link java.time.Instant} all store an instant
  * on the time-line to nanosecond precision.
@@ -570,7 +570,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
      * {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too
-     * large to fit in an {@code int} and throw a {@code DateTimeException}.
+     * large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
@@ -1387,8 +1387,8 @@
      * </ol>
      * <p>
      * For example, 2008-02-29 (leap year) minus one year would result in the
-     * invalid date 2009-02-29 (standard year). Instead of returning an invalid
-     * result, the last valid day of the month, 2009-02-28, is selected instead.
+     * invalid date 2007-02-29 (standard year). Instead of returning an invalid
+     * result, the last valid day of the month, 2007-02-28, is selected instead.
      * <p>
      * This instance is immutable and unaffected by this method call.
      *
@@ -1411,8 +1411,8 @@
      * </ol>
      * <p>
      * For example, 2007-03-31 minus one month would result in the invalid date
-     * 2007-04-31. Instead of returning an invalid result, the last valid day
-     * of the month, 2007-04-30, is selected instead.
+     * 2007-02-31. Instead of returning an invalid result, the last valid day
+     * of the month, 2007-02-28, is selected instead.
      * <p>
      * This instance is immutable and unaffected by this method call.
      *
@@ -1431,7 +1431,7 @@
      * the month and year fields as necessary to ensure the result remains valid.
      * The result is only invalid if the maximum/minimum year is exceeded.
      * <p>
-     * For example, 2008-12-31 minus one week would result in 2009-01-07.
+     * For example, 2009-01-07 minus one week would result in 2008-12-31.
      * <p>
      * This instance is immutable and unaffected by this method call.
      *
@@ -1450,7 +1450,7 @@
      * month and year fields as necessary to ensure the result remains valid.
      * The result is only invalid if the maximum/minimum year is exceeded.
      * <p>
-     * For example, 2008-12-31 minus one day would result in 2009-01-01.
+     * For example, 2009-01-01 minus one day would result in 2008-12-31.
      * <p>
      * This instance is immutable and unaffected by this method call.
      *
diff --git a/ojluni/src/main/java/java/time/OffsetTime.java b/ojluni/src/main/java/java/time/OffsetTime.java
index c54b926..5fc9942 100644
--- a/ojluni/src/main/java/java/time/OffsetTime.java
+++ b/ojluni/src/main/java/java/time/OffsetTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,7 +101,7 @@
  * viewed as hour-minute-second-offset.
  * This class stores all time fields, to a precision of nanoseconds,
  * as well as a zone offset.
- * For example, the value "13:45.30.123456789+02:00" can be stored
+ * For example, the value "13:45:30.123456789+02:00" can be stored
  * in an {@code OffsetTime}.
  *
  * @implSpec
@@ -252,7 +252,7 @@
         ZoneRules rules = zone.getRules();
         ZoneOffset offset = rules.getOffset(instant);
         long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();  // overflow caught later
-        int secsOfDay = (int) Math.floorMod(localSecond, SECONDS_PER_DAY);
+        int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
         LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
         return new OffsetTime(time, offset);
     }
@@ -475,7 +475,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this time, except {@code NANO_OF_DAY} and {@code MICRO_OF_DAY}
-     * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
+     * which are too large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
@@ -1226,6 +1226,28 @@
         return nod - offsetNanos;
     }
 
+    /**
+     * Converts this {@code OffsetTime} to the number of seconds since the epoch
+     * of 1970-01-01T00:00:00Z.
+     * <p>
+     * This combines this offset time with the specified date to calculate the
+     * epoch-second value, which is the number of elapsed seconds from
+     * 1970-01-01T00:00:00Z.
+     * Instants on the time-line after the epoch are positive, earlier
+     * are negative.
+     *
+     * @param date the localdate, not null
+     * @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative
+     * @since 9
+     */
+    public long toEpochSecond(LocalDate date) {
+        Objects.requireNonNull(date, "date");
+        long epochDay = date.toEpochDay();
+        long secs = epochDay * 86400 + time.toSecondOfDay();
+        secs -= offset.getTotalSeconds();
+        return secs;
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Compares this {@code OffsetTime} to another time.
@@ -1252,7 +1274,6 @@
      *
      * @param other  the other time to compare to, not null
      * @return the comparator value, negative if less, positive if greater
-     * @throws NullPointerException if {@code other} is null
      */
     @Override
     public int compareTo(OffsetTime other) {
diff --git a/ojluni/src/main/java/java/time/Period.java b/ojluni/src/main/java/java/time/Period.java
index f264994..aaffdd6 100644
--- a/ojluni/src/main/java/java/time/Period.java
+++ b/ojluni/src/main/java/java/time/Period.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,8 +83,6 @@
 import java.time.temporal.TemporalQueries;
 import java.time.temporal.TemporalUnit;
 import java.time.temporal.UnsupportedTemporalTypeException;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.regex.Matcher;
@@ -146,8 +144,7 @@
     /**
      * The set of supported units.
      */
-    private static final List<TemporalUnit> SUPPORTED_UNITS =
-            Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS));
+    private static final List<TemporalUnit> SUPPORTED_UNITS = List.of(YEARS, MONTHS, DAYS);
 
     /**
      * The number of years.
@@ -323,17 +320,17 @@
         Objects.requireNonNull(text, "text");
         Matcher matcher = PATTERN.matcher(text);
         if (matcher.matches()) {
-            int negate = ("-".equals(matcher.group(1)) ? -1 : 1);
-            String yearMatch = matcher.group(2);
-            String monthMatch = matcher.group(3);
-            String weekMatch = matcher.group(4);
-            String dayMatch = matcher.group(5);
-            if (yearMatch != null || monthMatch != null || dayMatch != null || weekMatch != null) {
+            int negate = (charMatch(text, matcher.start(1), matcher.end(1), '-') ? -1 : 1);
+            int yearStart = matcher.start(2), yearEnd = matcher.end(2);
+            int monthStart = matcher.start(3), monthEnd = matcher.end(3);
+            int weekStart = matcher.start(4), weekEnd = matcher.end(4);
+            int dayStart = matcher.start(5), dayEnd = matcher.end(5);
+            if (yearStart >= 0 || monthStart >= 0 || weekStart >= 0 || dayStart >= 0) {
                 try {
-                    int years = parseNumber(text, yearMatch, negate);
-                    int months = parseNumber(text, monthMatch, negate);
-                    int weeks = parseNumber(text, weekMatch, negate);
-                    int days = parseNumber(text, dayMatch, negate);
+                    int years = parseNumber(text, yearStart, yearEnd, negate);
+                    int months = parseNumber(text, monthStart, monthEnd, negate);
+                    int weeks = parseNumber(text, weekStart, weekEnd, negate);
+                    int days = parseNumber(text, dayStart, dayEnd, negate);
                     days = Math.addExact(days, Math.multiplyExact(weeks, 7));
                     return create(years, months, days);
                 } catch (NumberFormatException ex) {
@@ -344,11 +341,15 @@
         throw new DateTimeParseException("Text cannot be parsed to a Period", text, 0);
     }
 
-    private static int parseNumber(CharSequence text, String str, int negate) {
-        if (str == null) {
+    private static boolean charMatch(CharSequence text, int start, int end, char c) {
+        return (start >= 0 && end == start + 1 && text.charAt(start) == c);
+    }
+
+    private static int parseNumber(CharSequence text, int start, int end, int negate) {
+        if (start < 0 || end < 0) {
             return 0;
         }
-        int val = Integer.parseInt(str);
+        int val = Integer.parseInt(text, start, end, 10);
         try {
             return Math.multiplyExact(val, negate);
         } catch (ArithmeticException ex) {
@@ -811,7 +812,7 @@
      * Returns a copy of this period with the years and months normalized.
      * <p>
      * This normalizes the years and months units, leaving the days unit unchanged.
-     * The months unit is adjusted to have an absolute value less than 11,
+     * The months unit is adjusted to have an absolute value less than 12,
      * with the years unit being adjusted to compensate. For example, a period of
      * "1 Year and 15 months" will be normalized to "2 years and 3 months".
      * <p>
diff --git a/ojluni/src/main/java/java/time/Year.java b/ojluni/src/main/java/java/time/Year.java
index a1d5679..b477e7d 100644
--- a/ojluni/src/main/java/java/time/Year.java
+++ b/ojluni/src/main/java/java/time/Year.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/YearMonth.java b/ojluni/src/main/java/java/time/YearMonth.java
index 582a9d8..30b7a58 100644
--- a/ojluni/src/main/java/java/time/YearMonth.java
+++ b/ojluni/src/main/java/java/time/YearMonth.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -844,7 +844,7 @@
         long monthCount = year * 12L + (month - 1);
         long calcMonths = monthCount + monthsToAdd;  // safe overflow
         int newYear = YEAR.checkValidIntValue(Math.floorDiv(calcMonths, 12));
-        int newMonth = (int)Math.floorMod(calcMonths, 12) + 1;
+        int newMonth = Math.floorMod(calcMonths, 12) + 1;
         return with(newYear, newMonth);
     }
 
diff --git a/ojluni/src/main/java/java/time/ZoneId.java b/ojluni/src/main/java/java/time/ZoneId.java
index 11e34e0..17bd039 100644
--- a/ojluni/src/main/java/java/time/ZoneId.java
+++ b/ojluni/src/main/java/java/time/ZoneId.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,14 +76,15 @@
 import java.time.zone.ZoneRules;
 import java.time.zone.ZoneRulesException;
 import java.time.zone.ZoneRulesProvider;
-import java.util.Collections;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.TimeZone;
 
+import static java.util.Map.entry;
+
 // Android-changed: removed ValueBased paragraph.
 // Android-changed: removed {@link ZoneRulesProvider}.
 /**
@@ -215,39 +216,36 @@
      * </ul>
      * The map is unmodifiable.
      */
-    public static final Map<String, String> SHORT_IDS;
-    static {
-        Map<String, String> map = new HashMap<>(64);
-        map.put("ACT", "Australia/Darwin");
-        map.put("AET", "Australia/Sydney");
-        map.put("AGT", "America/Argentina/Buenos_Aires");
-        map.put("ART", "Africa/Cairo");
-        map.put("AST", "America/Anchorage");
-        map.put("BET", "America/Sao_Paulo");
-        map.put("BST", "Asia/Dhaka");
-        map.put("CAT", "Africa/Harare");
-        map.put("CNT", "America/St_Johns");
-        map.put("CST", "America/Chicago");
-        map.put("CTT", "Asia/Shanghai");
-        map.put("EAT", "Africa/Addis_Ababa");
-        map.put("ECT", "Europe/Paris");
-        map.put("IET", "America/Indiana/Indianapolis");
-        map.put("IST", "Asia/Kolkata");
-        map.put("JST", "Asia/Tokyo");
-        map.put("MIT", "Pacific/Apia");
-        map.put("NET", "Asia/Yerevan");
-        map.put("NST", "Pacific/Auckland");
-        map.put("PLT", "Asia/Karachi");
-        map.put("PNT", "America/Phoenix");
-        map.put("PRT", "America/Puerto_Rico");
-        map.put("PST", "America/Los_Angeles");
-        map.put("SST", "Pacific/Guadalcanal");
-        map.put("VST", "Asia/Ho_Chi_Minh");
-        map.put("EST", "-05:00");
-        map.put("MST", "-07:00");
-        map.put("HST", "-10:00");
-        SHORT_IDS = Collections.unmodifiableMap(map);
-    }
+    public static final Map<String, String> SHORT_IDS = Map.ofEntries(
+        entry("ACT", "Australia/Darwin"),
+        entry("AET", "Australia/Sydney"),
+        entry("AGT", "America/Argentina/Buenos_Aires"),
+        entry("ART", "Africa/Cairo"),
+        entry("AST", "America/Anchorage"),
+        entry("BET", "America/Sao_Paulo"),
+        entry("BST", "Asia/Dhaka"),
+        entry("CAT", "Africa/Harare"),
+        entry("CNT", "America/St_Johns"),
+        entry("CST", "America/Chicago"),
+        entry("CTT", "Asia/Shanghai"),
+        entry("EAT", "Africa/Addis_Ababa"),
+        entry("ECT", "Europe/Paris"),
+        entry("IET", "America/Indiana/Indianapolis"),
+        entry("IST", "Asia/Kolkata"),
+        entry("JST", "Asia/Tokyo"),
+        entry("MIT", "Pacific/Apia"),
+        entry("NET", "Asia/Yerevan"),
+        entry("NST", "Pacific/Auckland"),
+        entry("PLT", "Asia/Karachi"),
+        entry("PNT", "America/Phoenix"),
+        entry("PRT", "America/Puerto_Rico"),
+        entry("PST", "America/Los_Angeles"),
+        entry("SST", "Pacific/Guadalcanal"),
+        entry("VST", "Asia/Ho_Chi_Minh"),
+        entry("EST", "-05:00"),
+        entry("MST", "-07:00"),
+        entry("HST", "-10:00")
+    );
     /**
      * Serialization version.
      */
@@ -282,7 +280,7 @@
      * @return a modifiable copy of the set of zone IDs, not null
      */
     public static Set<String> getAvailableZoneIds() {
-        return ZoneRulesProvider.getAvailableZoneIds();
+        return new HashSet<String>(ZoneRulesProvider.getAvailableZoneIds());
     }
 
     //-----------------------------------------------------------------------
@@ -305,8 +303,7 @@
     public static ZoneId of(String zoneId, Map<String, String> aliasMap) {
         Objects.requireNonNull(zoneId, "zoneId");
         Objects.requireNonNull(aliasMap, "aliasMap");
-        String id = aliasMap.get(zoneId);
-        id = (id != null ? id : zoneId);
+        String id = Objects.requireNonNullElse(aliasMap.get(zoneId), zoneId);
         return of(id);
     }
 
@@ -370,7 +367,7 @@
     public static ZoneId ofOffset(String prefix, ZoneOffset offset) {
         Objects.requireNonNull(prefix, "prefix");
         Objects.requireNonNull(offset, "offset");
-        if (prefix.length() == 0) {
+        if (prefix.isEmpty()) {
             return offset;
         }
 
diff --git a/ojluni/src/main/java/java/time/ZoneOffset.java b/ojluni/src/main/java/java/time/ZoneOffset.java
index 4dfb94d..615ef64 100644
--- a/ojluni/src/main/java/java/time/ZoneOffset.java
+++ b/ojluni/src/main/java/java/time/ZoneOffset.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -144,7 +144,7 @@
      */
     public static final ZoneOffset UTC = ZoneOffset.ofTotalSeconds(0);
     /**
-     * Constant for the maximum supported offset.
+     * Constant for the minimum supported offset.
      */
     public static final ZoneOffset MIN = ZoneOffset.ofTotalSeconds(-MAX_SECONDS);
     /**
@@ -369,15 +369,15 @@
         } else if ((minutes > 0 && seconds < 0) || (minutes < 0 && seconds > 0)) {
             throw new DateTimeException("Zone offset minutes and seconds must have the same sign");
         }
-        if (Math.abs(minutes) > 59) {
-            throw new DateTimeException("Zone offset minutes not in valid range: abs(value) " +
-                    Math.abs(minutes) + " is not in the range 0 to 59");
+        if (minutes < -59 || minutes > 59) {
+            throw new DateTimeException("Zone offset minutes not in valid range: value " +
+                    minutes + " is not in the range -59 to 59");
         }
-        if (Math.abs(seconds) > 59) {
-            throw new DateTimeException("Zone offset seconds not in valid range: abs(value) " +
-                    Math.abs(seconds) + " is not in the range 0 to 59");
+        if (seconds < -59 || seconds > 59) {
+            throw new DateTimeException("Zone offset seconds not in valid range: value " +
+                    seconds + " is not in the range -59 to 59");
         }
-        if (Math.abs(hours) == 18 && (Math.abs(minutes) > 0 || Math.abs(seconds) > 0)) {
+        if (Math.abs(hours) == 18 && (minutes | seconds) != 0) {
             throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
         }
     }
@@ -405,7 +405,7 @@
      * @throws DateTimeException if the offset is not in the required range
      */
     public static ZoneOffset ofTotalSeconds(int totalSeconds) {
-        if (Math.abs(totalSeconds) > MAX_SECONDS) {
+        if (totalSeconds < -MAX_SECONDS || totalSeconds > MAX_SECONDS) {
             throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
         }
         if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) {
@@ -690,11 +690,12 @@
      * The comparison is "consistent with equals", as defined by {@link Comparable}.
      *
      * @param other  the other date to compare to, not null
-     * @return the comparator value, negative if less, postive if greater
+     * @return the comparator value, negative if less, positive if greater
      * @throws NullPointerException if {@code other} is null
      */
     @Override
     public int compareTo(ZoneOffset other) {
+        // abs(totalSeconds) <= MAX_SECONDS, so no overflow can happen here
         return other.totalSeconds - totalSeconds;
     }
 
diff --git a/ojluni/src/main/java/java/time/ZonedDateTime.java b/ojluni/src/main/java/java/time/ZonedDateTime.java
index 4af3bda..cc37c19 100644
--- a/ojluni/src/main/java/java/time/ZonedDateTime.java
+++ b/ojluni/src/main/java/java/time/ZonedDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -464,6 +464,7 @@
      * @param offset  the zone offset, not null
      * @param zone  the time-zone, not null
      * @return the zoned date-time, not null
+     * @throws DateTimeException if the combination of arguments is invalid
      */
     public static ZonedDateTime ofStrict(LocalDateTime localDateTime, ZoneOffset offset, ZoneId zone) {
         Objects.requireNonNull(localDateTime, "localDateTime");
@@ -786,7 +787,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
      * {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too
-     * large to fit in an {@code int} and throw a {@code DateTimeException}.
+     * large to fit in an {@code int} and throw an {@code UnsupportedTemporalTypeException}.
      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
@@ -1700,13 +1701,18 @@
      * Note that this is a different approach to that used by days, months and years,
      * thus adding one day is not the same as adding 24 hours.
      * <p>
-     * For example, consider a time-zone where the spring DST cutover means that the
-     * local times 01:00 to 01:59 occur twice changing from offset +02:00 to +01:00.
+     * For example, consider a time-zone, such as 'Europe/Paris', where the
+     * Autumn DST cutover means that the local times 02:00 to 02:59 occur twice
+     * changing from offset +02:00 in summer to +01:00 in winter.
      * <ul>
-     * <li>Adding one hour to 00:30+02:00 will result in 01:30+02:00
-     * <li>Adding one hour to 01:30+02:00 will result in 01:30+01:00
-     * <li>Adding one hour to 01:30+01:00 will result in 02:30+01:00
-     * <li>Adding three hours to 00:30+02:00 will result in 02:30+01:00
+     * <li>Adding one hour to 01:30+02:00 will result in 02:30+02:00
+     *     (both in summer time)
+     * <li>Adding one hour to 02:30+02:00 will result in 02:30+01:00
+     *     (moving from summer to winter time)
+     * <li>Adding one hour to 02:30+01:00 will result in 03:30+01:00
+     *     (both in winter time)
+     * <li>Adding three hours to 01:30+02:00 will result in 03:30+01:00
+     *     (moving from summer to winter time)
      * </ul>
      * <p>
      * This instance is immutable and unaffected by this method call.
@@ -1941,13 +1947,18 @@
      * Note that this is a different approach to that used by days, months and years,
      * thus subtracting one day is not the same as adding 24 hours.
      * <p>
-     * For example, consider a time-zone where the spring DST cutover means that the
-     * local times 01:00 to 01:59 occur twice changing from offset +02:00 to +01:00.
+     * For example, consider a time-zone, such as 'Europe/Paris', where the
+     * Autumn DST cutover means that the local times 02:00 to 02:59 occur twice
+     * changing from offset +02:00 in summer to +01:00 in winter.
      * <ul>
-     * <li>Subtracting one hour from 02:30+01:00 will result in 01:30+02:00
-     * <li>Subtracting one hour from 01:30+01:00 will result in 01:30+02:00
-     * <li>Subtracting one hour from 01:30+02:00 will result in 00:30+01:00
-     * <li>Subtracting three hours from 02:30+01:00 will result in 00:30+02:00
+     * <li>Subtracting one hour from 03:30+01:00 will result in 02:30+01:00
+     *     (both in winter time)
+     * <li>Subtracting one hour from 02:30+01:00 will result in 02:30+02:00
+     *     (moving from winter to summer time)
+     * <li>Subtracting one hour from 02:30+02:00 will result in 01:30+02:00
+     *     (both in summer time)
+     * <li>Subtracting three hours from 03:30+01:00 will result in 01:30+02:00
+     *     (moving from winter to summer time)
      * </ul>
      * <p>
      * This instance is immutable and unaffected by this method call.
diff --git a/ojluni/src/main/java/java/time/chrono/AbstractChronology.java b/ojluni/src/main/java/java/time/chrono/AbstractChronology.java
index c2e91d7..a32ecb7 100644
--- a/ojluni/src/main/java/java/time/chrono/AbstractChronology.java
+++ b/ojluni/src/main/java/java/time/chrono/AbstractChronology.java
@@ -127,36 +127,6 @@
 public abstract class AbstractChronology implements Chronology {
 
     /**
-     * ChronoLocalDate order constant.
-     */
-    static final Comparator<ChronoLocalDate> DATE_ORDER =
-        (Comparator<ChronoLocalDate> & Serializable) (date1, date2) -> {
-            return Long.compare(date1.toEpochDay(), date2.toEpochDay());
-        };
-    /**
-     * ChronoLocalDateTime order constant.
-     */
-    static final Comparator<ChronoLocalDateTime<? extends ChronoLocalDate>> DATE_TIME_ORDER =
-        (Comparator<ChronoLocalDateTime<? extends ChronoLocalDate>> & Serializable) (dateTime1, dateTime2) -> {
-            int cmp = Long.compare(dateTime1.toLocalDate().toEpochDay(), dateTime2.toLocalDate().toEpochDay());
-            if (cmp == 0) {
-                cmp = Long.compare(dateTime1.toLocalTime().toNanoOfDay(), dateTime2.toLocalTime().toNanoOfDay());
-            }
-            return cmp;
-        };
-    /**
-     * ChronoZonedDateTime order constant.
-     */
-    static final Comparator<ChronoZonedDateTime<?>> INSTANT_ORDER =
-            (Comparator<ChronoZonedDateTime<?>> & Serializable) (dateTime1, dateTime2) -> {
-                int cmp = Long.compare(dateTime1.toEpochSecond(), dateTime2.toEpochSecond());
-                if (cmp == 0) {
-                    cmp = Long.compare(dateTime1.toLocalTime().getNano(), dateTime2.toLocalTime().getNano());
-                }
-                return cmp;
-            };
-
-    /**
      * Map of available calendars by ID.
      */
     private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_ID = new ConcurrentHashMap<>();
diff --git a/ojluni/src/main/java/java/time/chrono/ChronoLocalDate.java b/ojluni/src/main/java/java/time/chrono/ChronoLocalDate.java
index 5848e94..fb69386 100644
--- a/ojluni/src/main/java/java/time/chrono/ChronoLocalDate.java
+++ b/ojluni/src/main/java/java/time/chrono/ChronoLocalDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,6 +66,7 @@
 import static java.time.temporal.ChronoField.YEAR;
 import static java.time.temporal.ChronoUnit.DAYS;
 
+import java.io.Serializable;
 import java.time.DateTimeException;
 import java.time.LocalDate;
 import java.time.LocalTime;
@@ -256,7 +257,9 @@
      * @see #isEqual
      */
     static Comparator<ChronoLocalDate> timeLineOrder() {
-        return AbstractChronology.DATE_ORDER;
+        return (Comparator<ChronoLocalDate> & Serializable) (date1, date2) -> {
+            return Long.compare(date1.toEpochDay(), date2.toEpochDay());
+        };
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/main/java/java/time/chrono/ChronoLocalDateImpl.java b/ojluni/src/main/java/java/time/chrono/ChronoLocalDateImpl.java
index 8fe8d19..3d236ff 100644
--- a/ojluni/src/main/java/java/time/chrono/ChronoLocalDateImpl.java
+++ b/ojluni/src/main/java/java/time/chrono/ChronoLocalDateImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -110,7 +110,7 @@
  *        int year = date.get(ChronoField.YEAR);
  *        System.out.printf("  Today is %s %s %d-%s-%d%n", date.getChronology().getID(),
  *                dow, day, month, year);
-
+ *
  *        // Print today's date and the last day of the year
  *        ChronoLocalDate now1 = Chronology.of("Hijrah").dateNow();
  *        ChronoLocalDate first = now1.with(ChronoField.DAY_OF_MONTH, 1)
diff --git a/ojluni/src/main/java/java/time/chrono/ChronoLocalDateTime.java b/ojluni/src/main/java/java/time/chrono/ChronoLocalDateTime.java
index ce77f4d..51637c2 100644
--- a/ojluni/src/main/java/java/time/chrono/ChronoLocalDateTime.java
+++ b/ojluni/src/main/java/java/time/chrono/ChronoLocalDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,6 +66,7 @@
 import static java.time.temporal.ChronoUnit.FOREVER;
 import static java.time.temporal.ChronoUnit.NANOS;
 
+import java.io.Serializable;
 import java.time.DateTimeException;
 import java.time.Instant;
 import java.time.LocalDateTime;
@@ -136,7 +137,13 @@
      * @see #isEqual
      */
     static Comparator<ChronoLocalDateTime<?>> timeLineOrder() {
-        return AbstractChronology.DATE_TIME_ORDER;
+        return (Comparator<ChronoLocalDateTime<? extends ChronoLocalDate>> & Serializable) (dateTime1, dateTime2) -> {
+            int cmp = Long.compare(dateTime1.toLocalDate().toEpochDay(), dateTime2.toLocalDate().toEpochDay());
+            if (cmp == 0) {
+                cmp = Long.compare(dateTime1.toLocalTime().toNanoOfDay(), dateTime2.toLocalTime().toNanoOfDay());
+            }
+            return cmp;
+        };
     }
 
     //-----------------------------------------------------------------------
@@ -194,7 +201,7 @@
      *
      * @return the date part of this date-time, not null
      */
-    D toLocalDate() ;
+    D toLocalDate();
 
     /**
      * Gets the local time part of this date-time.
diff --git a/ojluni/src/main/java/java/time/chrono/ChronoPeriodImpl.java b/ojluni/src/main/java/java/time/chrono/ChronoPeriodImpl.java
index 911144d..646af14 100644
--- a/ojluni/src/main/java/java/time/chrono/ChronoPeriodImpl.java
+++ b/ojluni/src/main/java/java/time/chrono/ChronoPeriodImpl.java
@@ -77,8 +77,6 @@
 import java.time.temporal.TemporalUnit;
 import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -105,8 +103,7 @@
     /**
      * The set of supported units.
      */
-    private static final List<TemporalUnit> SUPPORTED_UNITS =
-            Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS));
+    private static final List<TemporalUnit> SUPPORTED_UNITS = List.of(YEARS, MONTHS, DAYS);
 
     /**
      * The chronology.
diff --git a/ojluni/src/main/java/java/time/chrono/ChronoZonedDateTime.java b/ojluni/src/main/java/java/time/chrono/ChronoZonedDateTime.java
index cae9adc..eadcf9d 100644
--- a/ojluni/src/main/java/java/time/chrono/ChronoZonedDateTime.java
+++ b/ojluni/src/main/java/java/time/chrono/ChronoZonedDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,6 +66,7 @@
 import static java.time.temporal.ChronoUnit.FOREVER;
 import static java.time.temporal.ChronoUnit.NANOS;
 
+import java.io.Serializable;
 import java.time.DateTimeException;
 import java.time.Instant;
 import java.time.LocalTime;
@@ -137,7 +138,13 @@
      * @see #isEqual
      */
     static Comparator<ChronoZonedDateTime<?>> timeLineOrder() {
-        return AbstractChronology.INSTANT_ORDER;
+        return (Comparator<ChronoZonedDateTime<?>> & Serializable) (dateTime1, dateTime2) -> {
+                int cmp = Long.compare(dateTime1.toEpochSecond(), dateTime2.toEpochSecond());
+                if (cmp == 0) {
+                    cmp = Long.compare(dateTime1.toLocalTime().getNano(), dateTime2.toLocalTime().getNano());
+                }
+                return cmp;
+            };
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/main/java/java/time/chrono/Chronology.java b/ojluni/src/main/java/java/time/chrono/Chronology.java
index 0b2d2e1..f35f9b9 100644
--- a/ojluni/src/main/java/java/time/chrono/Chronology.java
+++ b/ojluni/src/main/java/java/time/chrono/Chronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,12 +61,17 @@
  */
 package java.time.chrono;
 
+import static java.time.temporal.ChronoField.HOUR_OF_DAY;
+import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
+import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
+
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalTime;
 import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.ResolverStyle;
 import java.time.format.TextStyle;
@@ -146,7 +151,7 @@
  * Each chronology must define a chronology ID that is unique within the system.
  * If the chronology represents a calendar system defined by the
  * CLDR specification then the calendar type is the concatenation of the
- * CLDR type and, if applicable, the CLDR variant,
+ * CLDR type and, if applicable, the CLDR variant.
  *
  * @implSpec
  * This interface must be implemented with care to ensure other classes operate correctly.
@@ -172,12 +177,12 @@
      *
      * @param temporal  the temporal to convert, not null
      * @return the chronology, not null
-     * @throws DateTimeException if unable to convert to an {@code Chronology}
+     * @throws DateTimeException if unable to convert to a {@code Chronology}
      */
     static Chronology from(TemporalAccessor temporal) {
         Objects.requireNonNull(temporal, "temporal");
         Chronology obj = temporal.query(TemporalQueries.chronology());
-        return (obj != null ? obj : IsoChronology.INSTANCE);
+        return Objects.requireNonNullElse(obj, IsoChronology.INSTANCE);
     }
 
     //-----------------------------------------------------------------------
@@ -198,7 +203,7 @@
      * For example, the locale "en-JP-u-ca-japanese" represents the English
      * language as used in Japan with the Japanese calendar system.
      * <p>
-     * This method finds the desired calendar system by in a manner equivalent
+     * This method finds the desired calendar system in a manner equivalent
      * to passing "ca" to {@link Locale#getUnicodeLocaleType(String)}.
      * If the "ca" key is not present, then {@code IsoChronology} is returned.
      * <p>
@@ -281,7 +286,7 @@
      * <p>
      * The calendar type is an identifier defined by the CLDR and
      * <em>Unicode Locale Data Markup Language (LDML)</em> specifications
-     * to uniquely identification a calendar.
+     * to uniquely identify a calendar.
      * The {@code getCalendarType} is the concatenation of the CLDR calendar type
      * and the variant, if applicable, is appended separated by "-".
      * The calendar type is used to lookup the {@code Chronology} using {@link #of(String)}.
@@ -538,7 +543,14 @@
      * <ul>
      * <li>a leap-year must imply a year-length longer than a non leap-year.
      * <li>a chronology that does not support the concept of a year must return false.
+     * <li>the correct result must be returned for all years within the
+     *     valid range of years for the chronology.
      * </ul>
+     * <p>
+     * Outside the range of valid years an implementation is free to return
+     * either a best guess or false.
+     * An implementation must not throw an exception, even if the year is
+     * outside the range of valid years.
      *
      * @param prolepticYear  the proleptic-year to check, not validated for range
      * @return true if the year is a leap year
@@ -705,6 +717,59 @@
         return new ChronoPeriodImpl(this, years, months, days);
     }
 
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
+     * <p>
+     * The number of seconds is calculated using the proleptic-year,
+     * month, day-of-month, hour, minute, second, and zoneOffset.
+     *
+     * @param prolepticYear the chronology proleptic-year
+     * @param month the chronology month-of-year
+     * @param dayOfMonth the chronology day-of-month
+     * @param hour the hour-of-day, from 0 to 23
+     * @param minute the minute-of-hour, from 0 to 59
+     * @param second the second-of-minute, from 0 to 59
+     * @param zoneOffset the zone offset, not null
+     * @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
+     * @throws DateTimeException if any of the values are out of range
+     * @since 9
+     */
+    public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
+        Objects.requireNonNull(zoneOffset, "zoneOffset");
+        HOUR_OF_DAY.checkValidValue(hour);
+        MINUTE_OF_HOUR.checkValidValue(minute);
+        SECOND_OF_MINUTE.checkValidValue(second);
+        long daysInSec = Math.multiplyExact(date(prolepticYear, month, dayOfMonth).toEpochDay(), 86400);
+        long timeinSec = (hour * 60 + minute) * 60 + second;
+        return Math.addExact(daysInSec, timeinSec - zoneOffset.getTotalSeconds());
+    }
+
+    /**
+     * Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
+     * <p>
+     * The number of seconds is calculated using the era, year-of-era,
+     * month, day-of-month, hour, minute, second, and zoneOffset.
+     *
+     * @param era  the era of the correct type for the chronology, not null
+     * @param yearOfEra the chronology year-of-era
+     * @param month the chronology month-of-year
+     * @param dayOfMonth the chronology day-of-month
+     * @param hour the hour-of-day, from 0 to 23
+     * @param minute the minute-of-hour, from 0 to 59
+     * @param second the second-of-minute, from 0 to 59
+     * @param zoneOffset the zone offset, not null
+     * @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
+     * @throws DateTimeException if any of the values are out of range
+     * @since 9
+     */
+    public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
+                                    int hour, int minute, int second, ZoneOffset zoneOffset) {
+        Objects.requireNonNull(era, "era");
+        return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset);
+    }
     //-----------------------------------------------------------------------
     /**
      * Compares this chronology to another chronology.
diff --git a/ojluni/src/main/java/java/time/chrono/Era.java b/ojluni/src/main/java/java/time/chrono/Era.java
index 0e3c533..5cf0968 100644
--- a/ojluni/src/main/java/java/time/chrono/Era.java
+++ b/ojluni/src/main/java/java/time/chrono/Era.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -310,8 +310,8 @@
      * The parameters control the style of the returned text and the locale.
      * <p>
      * If no textual mapping is found then the {@link #getValue() numeric value} is returned.
-     * <p>
-     * This default implementation is suitable for all implementations.
+     *
+     * @apiNote This default implementation is suitable for most implementations.
      *
      * @param style  the style of the text required, not null
      * @param locale  the locale to use, not null
diff --git a/ojluni/src/main/java/java/time/chrono/HijrahChronology.java b/ojluni/src/main/java/java/time/chrono/HijrahChronology.java
index e7b3554..6de5cc7 100644
--- a/ojluni/src/main/java/java/time/chrono/HijrahChronology.java
+++ b/ojluni/src/main/java/java/time/chrono/HijrahChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,15 +59,13 @@
 
 import static java.time.temporal.ChronoField.EPOCH_DAY;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
+import java.io.FilePermission;
 import java.io.InputStream;
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.security.AccessController;
-import java.security.PrivilegedActionException;
+import java.security.PrivilegedAction;
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.Instant;
@@ -82,7 +80,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.Properties;
 
 import sun.util.logging.PlatformLogger;
@@ -106,18 +103,19 @@
  *
  * <p>
  * CLDR and LDML identify variants:
- * <table cellpadding="2" summary="Variants of Hijrah Calendars">
+ * <table class="striped" style="text-align:left">
+ * <caption style="display:none">Variants of Hijrah Calendars</caption>
  * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left" >Chronology ID</th>
- * <th class="colFirst" align="left" >Calendar Type</th>
- * <th class="colFirst" align="left" >Locale extension, see {@link java.util.Locale}</th>
- * <th class="colLast" align="left" >Description</th>
+ * <tr>
+ * <th scope="col">Chronology ID</th>
+ * <th scope="col">Calendar Type</th>
+ * <th scope="col">Locale extension, see {@link java.util.Locale}</th>
+ * <th scope="col">Description</th>
  * </tr>
  * </thead>
  * <tbody>
- * <tr class="altColor">
- * <td>Hijrah-umalqura</td>
+ * <tr>
+ * <th scope="row">Hijrah-umalqura</th>
  * <td>islamic-umalqura</td>
  * <td>ca-islamic-umalqura</td>
  * <td>Islamic - Umm Al-Qura calendar of Saudi Arabia</td>
@@ -145,63 +143,43 @@
  * property resource that defines the {@code ID}, the {@code calendar type},
  * the start of the calendar, the alignment with the
  * ISO calendar, and the length of each month for a range of years.
- * The variants are identified in the {@code calendars.properties} file.
- * The new properties are prefixed with {@code "calendars.hijrah."}:
- * <table cellpadding="2" border="0" summary="Configuration of Hijrah Calendar Variants">
- * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left">Property Name</th>
- * <th class="colFirst" align="left">Property value</th>
- * <th class="colLast" align="left">Description </th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr class="altColor">
- * <td>calendars.hijrah.{ID}</td>
- * <td>The property resource defining the {@code {ID}} variant</td>
- * <td>The property resource is located with the {@code calendars.properties} file</td>
- * </tr>
- * <tr class="rowColor">
- * <td>calendars.hijrah.{ID}.type</td>
- * <td>The calendar type</td>
- * <td>LDML defines the calendar type names</td>
- * </tr>
- * </tbody>
- * </table>
+ * The variants are loaded by HijrahChronology as a resource from
+ * hijrah-config-&lt;calendar type&gt;.properties.
  * <p>
  * The Hijrah property resource is a set of properties that describe the calendar.
  * The syntax is defined by {@code java.util.Properties#load(Reader)}.
- * <table cellpadding="2" summary="Configuration of Hijrah Calendar">
+ * <table class="striped" style="text-align:left">
+ * <caption style="display:none">Configuration of Hijrah Calendar</caption>
  * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left" > Property Name</th>
- * <th class="colFirst" align="left" > Property value</th>
- * <th class="colLast" align="left" > Description </th>
+ * <tr>
+ * <th scope="col">Property Name</th>
+ * <th scope="col">Property value</th>
+ * <th scope="col">Description</th>
  * </tr>
  * </thead>
  * <tbody>
- * <tr class="altColor">
- * <td>id</td>
+ * <tr>
+ * <th scope="row">id</th>
  * <td>Chronology Id, for example, "Hijrah-umalqura"</td>
  * <td>The Id of the calendar in common usage</td>
  * </tr>
- * <tr class="rowColor">
- * <td>type</td>
+ * <tr>
+ * <th scope="row">type</th>
  * <td>Calendar type, for example, "islamic-umalqura"</td>
  * <td>LDML defines the calendar types</td>
  * </tr>
- * <tr class="altColor">
- * <td>version</td>
+ * <tr>
+ * <th scope="row">version</th>
  * <td>Version, for example: "1.8.0_1"</td>
  * <td>The version of the Hijrah variant data</td>
  * </tr>
- * <tr class="rowColor">
- * <td>iso-start</td>
+ * <tr>
+ * <th scope="row">iso-start</th>
  * <td>ISO start date, formatted as {@code yyyy-MM-dd}, for example: "1900-04-30"</td>
  * <td>The ISO date of the first day of the minimum Hijrah year.</td>
  * </tr>
- * <tr class="altColor">
- * <td>yyyy - a numeric 4 digit year, for example "1434"</td>
+ * <tr>
+ * <th scope="row">yyyy - a numeric 4 digit year, for example "1434"</th>
  * <td>The value is a sequence of 12 month lengths,
  * for example: "29 30 29 30 29 30 30 30 29 30 29 29"</td>
  * <td>The lengths of the 12 months of the year separated by whitespace.
@@ -279,91 +257,41 @@
      * Computed by {@link #createEpochMonths}.
      */
     private transient int maxYearLength;
-    /**
-     * A reference to the properties stored in
-     * ${java.home}/lib/calendars.properties
-     */
-    private final transient static Properties calendarProperties;
 
     /**
-     * Prefix of property names for Hijrah calendar variants.
+     * Prefix of resource names for Hijrah calendar variants.
      */
-    private static final String PROP_PREFIX = "calendar.hijrah.";
-    /**
-     * Suffix of property names containing the calendar type of a variant.
-     */
-    private static final String PROP_TYPE_SUFFIX = ".type";
+    private static final String RESOURCE_PREFIX = "hijrah-config-";
 
     /**
-     * Static initialization of the predefined calendars found in the
-     * lib/calendars.properties file.
+     * Suffix of resource names for Hijrah calendar variants.
+     */
+    private static final String RESOURCE_SUFFIX = ".properties";
+
+    /**
+     * Static initialization of the built-in calendars.
+     * The data is not loaded until it is used.
      */
     static {
-        try {
-            calendarProperties = sun.util.calendar.BaseCalendar.getCalendarProperties();
-        } catch (IOException ioe) {
-            throw new InternalError("Can't initialize lib/calendars.properties", ioe);
-        }
-
-        try {
-            INSTANCE = new HijrahChronology("Hijrah-umalqura");
-            // Register it by its aliases
-            AbstractChronology.registerChrono(INSTANCE, "Hijrah");
-            AbstractChronology.registerChrono(INSTANCE, "islamic");
-        } catch (DateTimeException ex) {
-            // Absence of Hijrah calendar is fatal to initializing this class.
-            PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
-            logger.severe("Unable to initialize Hijrah calendar: Hijrah-umalqura", ex);
-            throw new RuntimeException("Unable to initialize Hijrah-umalqura calendar", ex.getCause());
-        }
-        registerVariants();
+        INSTANCE = new HijrahChronology("Hijrah-umalqura", "islamic-umalqura");
+        // Register it by its aliases
+        AbstractChronology.registerChrono(INSTANCE, "Hijrah");
+        AbstractChronology.registerChrono(INSTANCE, "islamic");
     }
 
     /**
-     * For each Hijrah variant listed, create the HijrahChronology and register it.
-     * Exceptions during initialization are logged but otherwise ignored.
-     */
-    private static void registerVariants() {
-        for (String name : calendarProperties.stringPropertyNames()) {
-            if (name.startsWith(PROP_PREFIX)) {
-                String id = name.substring(PROP_PREFIX.length());
-                if (id.indexOf('.') >= 0) {
-                    continue;   // no name or not a simple name of a calendar
-                }
-                if (id.equals(INSTANCE.getId())) {
-                    continue;           // do not duplicate the default
-                }
-                try {
-                    // Create and register the variant
-                    HijrahChronology chrono = new HijrahChronology(id);
-                    AbstractChronology.registerChrono(chrono);
-                } catch (DateTimeException ex) {
-                    // Log error and continue
-                    PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
-                    logger.severe("Unable to initialize Hijrah calendar: " + id, ex);
-                }
-            }
-        }
-    }
-
-    /**
-     * Create a HijrahChronology for the named variant.
-     * The resource and calendar type are retrieved from properties
-     * in the {@code calendars.properties}.
-     * The property names are {@code "calendar.hijrah." + id}
-     * and  {@code "calendar.hijrah." + id + ".type"}
+     * Create a HijrahChronology for the named variant and type.
+     *
      * @param id the id of the calendar
-     * @throws DateTimeException if the calendar type is missing from the properties file.
-     * @throws IllegalArgumentException if the id is empty
+     * @param calType the typeId of the calendar
+     * @throws IllegalArgumentException if the id or typeId is empty
      */
-    private HijrahChronology(String id) throws DateTimeException {
+    private HijrahChronology(String id, String calType) {
         if (id.isEmpty()) {
             throw new IllegalArgumentException("calendar id is empty");
         }
-        String propName = PROP_PREFIX + id + PROP_TYPE_SUFFIX;
-        String calType = calendarProperties.getProperty(propName);
-        if (calType == null || calType.isEmpty()) {
-            throw new DateTimeException("calendarType is missing or empty for: " + propName);
+        if (calType.isEmpty()) {
+            throw new IllegalArgumentException("calendar typeId is empty");
         }
         this.typeId = id;
         this.calendarType = calType;
@@ -560,6 +488,16 @@
         return yearOfEra;
     }
 
+    /**
+     * Creates the HijrahEra object from the numeric value.
+     * The Hijrah calendar system has only one era covering the
+     * proleptic years greater than zero.
+     * This method returns the singleton HijrahEra for the value 1.
+     *
+     * @param eraValue  the era value
+     * @return the calendar system era, not null
+     * @throws DateTimeException if unable to create the era
+     */
     @Override
     public HijrahEra eraOf(int eraValue) {
         switch (eraValue) {
@@ -572,7 +510,7 @@
 
     @Override
     public List<Era> eras() {
-        return Arrays.<Era>asList(HijrahEra.values());
+        return List.of(HijrahEra.values());
     }
 
     //-----------------------------------------------------------------------
@@ -728,7 +666,7 @@
     }
 
     /**
-     * Return the maximum supported Hijrah ear.
+     * Return the maximum supported Hijrah year.
      *
      * @return the minimum
      */
@@ -865,22 +803,33 @@
     /**
      * Return the configuration properties from the resource.
      * <p>
-     * The default location of the variant configuration resource is:
+     * The location of the variant configuration resource is:
      * <pre>
-     *   "$java.home/lib/" + resource-name
+     *   "/java/time/chrono/hijrah-config-" + calendarType + ".properties"
      * </pre>
      *
-     * @param resource the name of the calendar property resource
+     * @param calendarType the calendarType of the calendar variant
      * @return a Properties containing the properties read from the resource.
      * @throws Exception if access to the property resource fails
      */
-    private static Properties readConfigProperties(final String resource) throws Exception {
-        // Android-changed: Load system resources.
-        Properties props = new Properties();
-        try (InputStream is = ClassLoader.getSystemResourceAsStream(resource)) {
+    private Properties readConfigProperties(final String calendarType) throws Exception {
+        String resourceName = RESOURCE_PREFIX + calendarType + RESOURCE_SUFFIX;
+        // BEGIN Android-changed: Load system resources.
+        /*
+        PrivilegedAction<InputStream> getResourceAction =  () -> HijrahChronology.class.getResourceAsStream(resourceName);
+        FilePermission perm1 = new FilePermission("<<ALL FILES>>", "read");
+        RuntimePermission perm2 = new RuntimePermission("accessSystemModules");
+        try (InputStream is = AccessController.doPrivileged(getResourceAction, null, perm1, perm2)) {
+        */
+        try (InputStream is = HijrahChronology.class.getResourceAsStream(resourceName)) {
+        // END Android-changed: Load system resources.
+            if (is == null) {
+                throw new RuntimeException("Hijrah calendar resource not found: /java/time/chrono/" + resourceName);
+            }
+            Properties props = new Properties();
             props.load(is);
+            return props;
         }
-        return props;
     }
 
     /**
@@ -896,9 +845,7 @@
      */
     private void loadCalendarData() {
         try {
-            String resourceName = calendarProperties.getProperty(PROP_PREFIX + typeId);
-            Objects.requireNonNull(resourceName, "Resource missing for calendar: " + PROP_PREFIX + typeId);
-            Properties props = readConfigProperties(resourceName);
+            Properties props = readConfigProperties(calendarType);
 
             Map<Integer, int[]> years = new HashMap<>();
             int minYear = Integer.MAX_VALUE;
@@ -927,7 +874,7 @@
                     default:
                         try {
                             // Everything else is either a year or invalid
-                            int year = Integer.valueOf(key);
+                            int year = Integer.parseInt(key);
                             int[] months = parseMonths((String) entry.getValue());
                             years.put(year, months);
                             maxYear = Math.max(maxYear, year);
@@ -1035,7 +982,7 @@
         }
         for (int i = 0; i < 12; i++) {
             try {
-                months[i] = Integer.valueOf(numbers[i]);
+                months[i] = Integer.parseInt(numbers[i]);
             } catch (NumberFormatException nfe) {
                 throw new IllegalArgumentException("bad key: " + numbers[i]);
             }
@@ -1057,9 +1004,9 @@
                 throw new IllegalArgumentException("date must be yyyy-MM-dd");
             }
             int[] ymd = new int[3];
-            ymd[0] = Integer.valueOf(string.substring(0, 4));
-            ymd[1] = Integer.valueOf(string.substring(5, 7));
-            ymd[2] = Integer.valueOf(string.substring(8, 10));
+            ymd[0] = Integer.parseInt(string, 0, 4, 10);
+            ymd[1] = Integer.parseInt(string, 5, 7, 10);
+            ymd[2] = Integer.parseInt(string, 8, 10, 10);
             return ymd;
         } catch (NumberFormatException ex) {
             throw new IllegalArgumentException("date must be yyyy-MM-dd", ex);
diff --git a/ojluni/src/main/java/java/time/chrono/HijrahDate.java b/ojluni/src/main/java/java/time/chrono/HijrahDate.java
index de2cb13..2ab5109 100644
--- a/ojluni/src/main/java/java/time/chrono/HijrahDate.java
+++ b/ojluni/src/main/java/java/time/chrono/HijrahDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -362,7 +362,7 @@
         if (field instanceof ChronoField) {
             switch ((ChronoField) field) {
                 case DAY_OF_WEEK: return getDayOfWeek();
-                case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((getDayOfWeek() - 1) % 7) + 1;
+                case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((dayOfMonth - 1) % 7) + 1;
                 case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
                 case DAY_OF_MONTH: return this.dayOfMonth;
                 case DAY_OF_YEAR: return this.getDayOfYear();
@@ -491,7 +491,7 @@
      * @return the day-of-week; computed from the epochday
      */
     private int getDayOfWeek() {
-        int dow0 = (int)Math.floorMod(toEpochDay() + 3, 7);
+        int dow0 = Math.floorMod(toEpochDay() + 3, 7);
         return dow0 + 1;
     }
 
diff --git a/ojluni/src/main/java/java/time/chrono/HijrahEra.java b/ojluni/src/main/java/java/time/chrono/HijrahEra.java
index 4390f69..0d79e7d 100644
--- a/ojluni/src/main/java/java/time/chrono/HijrahEra.java
+++ b/ojluni/src/main/java/java/time/chrono/HijrahEra.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,10 +64,13 @@
 import static java.time.temporal.ChronoField.ERA;
 
 import java.time.DateTimeException;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalField;
 import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
+import java.util.Locale;
 
 /**
  * An era in the Hijrah calendar system.
@@ -155,4 +158,18 @@
         return Era.super.range(field);
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * @param style {@inheritDoc}
+     * @param locale {@inheritDoc}
+     */
+    @Override
+    public String getDisplayName(TextStyle style, Locale locale) {
+        return new DateTimeFormatterBuilder()
+            .appendText(ERA, style)
+            .toFormatter(locale)
+            .withChronology(HijrahChronology.INSTANCE)
+            .format(HijrahDate.now());
+    }
 }
diff --git a/ojluni/src/main/java/java/time/chrono/IsoChronology.java b/ojluni/src/main/java/java/time/chrono/IsoChronology.java
index a9c79ff..18d7368 100644
--- a/ojluni/src/main/java/java/time/chrono/IsoChronology.java
+++ b/ojluni/src/main/java/java/time/chrono/IsoChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,14 +61,17 @@
  */
 package java.time.chrono;
 
-import java.io.InvalidObjectException;
 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
 import static java.time.temporal.ChronoField.ERA;
+import static java.time.temporal.ChronoField.HOUR_OF_DAY;
+import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
+import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
 import static java.time.temporal.ChronoField.YEAR;
 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
 
+import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.time.Clock;
@@ -79,14 +82,14 @@
 import java.time.Month;
 import java.time.Period;
 import java.time.Year;
-import java.time.ZoneId;
 import java.time.ZonedDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.format.ResolverStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.ValueRange;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -132,6 +135,8 @@
      */
     private static final long serialVersionUID = -1440403870442975015L;
 
+    private static final long DAYS_0000_TO_1970 = (146097 * 5L) - (30L * 365L + 7L); // taken from LocalDate
+
     /**
      * Restricted constructor.
      */
@@ -263,6 +268,94 @@
         return LocalDate.from(temporal);
     }
 
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
+     * <p>
+     * The number of seconds is calculated using the year,
+     * month, day-of-month, hour, minute, second, and zoneOffset.
+     *
+     * @param prolepticYear  the year, from MIN_YEAR to MAX_YEAR
+     * @param month  the month-of-year, from 1 to 12
+     * @param dayOfMonth  the day-of-month, from 1 to 31
+     * @param hour  the hour-of-day, from 0 to 23
+     * @param minute  the minute-of-hour, from 0 to 59
+     * @param second  the second-of-minute, from 0 to 59
+     * @param zoneOffset the zone offset, not null
+     * @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
+     * @throws DateTimeException if the value of any argument is out of range,
+     *         or if the day-of-month is invalid for the month-of-year
+     * @since 9
+     */
+    @Override
+    public long epochSecond(int prolepticYear, int month, int dayOfMonth,
+                            int hour, int minute, int second, ZoneOffset zoneOffset) {
+        YEAR.checkValidValue(prolepticYear);
+        MONTH_OF_YEAR.checkValidValue(month);
+        DAY_OF_MONTH.checkValidValue(dayOfMonth);
+        HOUR_OF_DAY.checkValidValue(hour);
+        MINUTE_OF_HOUR.checkValidValue(minute);
+        SECOND_OF_MINUTE.checkValidValue(second);
+        Objects.requireNonNull(zoneOffset, "zoneOffset");
+        if (dayOfMonth > 28) {
+            int dom = numberOfDaysOfMonth(prolepticYear, month);
+            if (dayOfMonth > dom) {
+                if (dayOfMonth == 29) {
+                    throw new DateTimeException("Invalid date 'February 29' as '" + prolepticYear + "' is not a leap year");
+                } else {
+                    throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");
+                }
+            }
+        }
+
+        long totalDays = 0;
+        int timeinSec = 0;
+        totalDays += 365L * prolepticYear;
+        if (prolepticYear >= 0) {
+            totalDays += (prolepticYear + 3L) / 4 - (prolepticYear + 99L) / 100 + (prolepticYear + 399L) / 400;
+        } else {
+            totalDays -= prolepticYear / -4 - prolepticYear / -100 + prolepticYear / -400;
+        }
+        totalDays += (367 * month - 362) / 12;
+        totalDays += dayOfMonth - 1;
+        if (month > 2) {
+            totalDays--;
+            if (IsoChronology.INSTANCE.isLeapYear(prolepticYear) == false) {
+                totalDays--;
+            }
+        }
+        totalDays -= DAYS_0000_TO_1970;
+        timeinSec = (hour * 60 + minute ) * 60 + second;
+        return Math.addExact(Math.multiplyExact(totalDays, 86400L), timeinSec - zoneOffset.getTotalSeconds());
+     }
+
+    /**
+     * Gets the number of days for the given month in the given year.
+     *
+     * @param year the year to represent, from MIN_YEAR to MAX_YEAR
+     * @param month the month-of-year to represent, from 1 to 12
+     * @return the number of days for the given month in the given year
+     */
+    private int numberOfDaysOfMonth(int year, int month) {
+        int dom;
+        switch (month) {
+            case 2:
+                dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
+                break;
+            case 4:
+            case 6:
+            case 9:
+            case 11:
+                dom = 30;
+                break;
+            default:
+                dom = 31;
+                break;
+        }
+        return dom;
+    }
+
+
     /**
      * Obtains an ISO local date-time from another date-time object.
      * <p>
@@ -398,7 +491,7 @@
 
     @Override
     public List<Era> eras() {
-        return Arrays.<Era>asList(IsoEra.values());
+        return List.of(IsoEra.values());
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/main/java/java/time/chrono/IsoEra.java b/ojluni/src/main/java/java/time/chrono/IsoEra.java
index bd29969..887d76f 100644
--- a/ojluni/src/main/java/java/time/chrono/IsoEra.java
+++ b/ojluni/src/main/java/java/time/chrono/IsoEra.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,26 +70,27 @@
  * A definition has therefore been created with two eras - 'Current era' (CE) for
  * years on or after 0001-01-01 (ISO), and 'Before current era' (BCE) for years before that.
  *
- * <table summary="ISO years and eras" cellpadding="2" cellspacing="3" border="0" >
+ * <table class="striped" style="text-align:left">
+ * <caption style="display:none">ISO years and eras</caption>
  * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left">year-of-era</th>
- * <th class="colFirst" align="left">era</th>
- * <th class="colLast" align="left">proleptic-year</th>
+ * <tr>
+ * <th scope="col">year-of-era</th>
+ * <th scope="col">era</th>
+ * <th scope="col">proleptic-year</th>
  * </tr>
  * </thead>
  * <tbody>
- * <tr class="rowColor">
- * <td>2</td><td>CE</td><td>2</td>
+ * <tr>
+ * <td>2</td><td>CE</td><th scope="row">2</th>
  * </tr>
- * <tr class="altColor">
- * <td>1</td><td>CE</td><td>1</td>
+ * <tr>
+ * <td>1</td><td>CE</td><th scope="row">1</th>
  * </tr>
- * <tr class="rowColor">
- * <td>1</td><td>BCE</td><td>0</td>
+ * <tr>
+ * <td>1</td><td>BCE</td><th scope="row">0</th>
  * </tr>
- * <tr class="altColor">
- * <td>2</td><td>BCE</td><td>-1</td>
+ * <tr>
+ * <td>2</td><td>BCE</td><th scope="row">-1</th>
  * </tr>
  * </tbody>
  * </table>
diff --git a/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java b/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java
index 034a3bc..0e487af 100644
--- a/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java
+++ b/ojluni/src/main/java/java/time/chrono/JapaneseChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,6 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
-import java.util.Arrays;
 import java.util.Calendar;
 import java.util.List;
 import java.util.Locale;
@@ -386,7 +385,7 @@
 
     @Override
     public List<Era> eras() {
-        return Arrays.<Era>asList(JapaneseEra.values());
+        return List.of(JapaneseEra.values());
     }
 
     JapaneseEra getCurrentEra() {
@@ -469,38 +468,38 @@
         return era.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1;
     }
 
-     private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map<TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
-         fieldValues.remove(ERA);
-         fieldValues.remove(YEAR_OF_ERA);
-         if (resolverStyle == ResolverStyle.LENIENT) {
-             int y = prolepticYearLenient(era, yoe);
-             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
-             long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
-             return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
-         }
-         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
-         int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
-         if (resolverStyle == ResolverStyle.SMART) {  // previous valid
-             if (yoe < 1) {
-                 throw new DateTimeException("Invalid YearOfEra: " + yoe);
-             }
-             int y = prolepticYearLenient(era, yoe);
-             JapaneseDate result;
-             try {
-                 result = date(y, moy, dom);
-             } catch (DateTimeException ex) {
-                 result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
-             }
-             // handle the era being changed
-             // only allow if the new date is in the same Jan-Dec as the era change
-             // determine by ensuring either original yoe or result yoe is 1
-             if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
-                 throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
-             }
-             return result;
-         }
-         return date(era, yoe, moy, dom);
-     }
+    private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map<TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
+        fieldValues.remove(ERA);
+        fieldValues.remove(YEAR_OF_ERA);
+        if (resolverStyle == ResolverStyle.LENIENT) {
+            int y = prolepticYearLenient(era, yoe);
+            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
+            long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
+            return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
+        }
+        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
+        int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
+        if (resolverStyle == ResolverStyle.SMART) {  // previous valid
+            if (yoe < 1) {
+                throw new DateTimeException("Invalid YearOfEra: " + yoe);
+            }
+            int y = prolepticYearLenient(era, yoe);
+            JapaneseDate result;
+            try {
+                result = date(y, moy, dom);
+            } catch (DateTimeException ex) {
+                result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
+            }
+            // handle the era being changed
+            // only allow if the new date is in the same Jan-Dec as the era change
+            // determine by ensuring either original yoe or result yoe is 1
+            if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) {
+                throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe);
+            }
+            return result;
+        }
+        return date(era, yoe, moy, dom);
+    }
 
     private ChronoLocalDate resolveYD(JapaneseEra era, int yoe, Map <TemporalField,Long> fieldValues, ResolverStyle resolverStyle) {
         fieldValues.remove(ERA);
diff --git a/ojluni/src/main/java/java/time/chrono/JapaneseDate.java b/ojluni/src/main/java/java/time/chrono/JapaneseDate.java
index 143c4a4..c638a31 100644
--- a/ojluni/src/main/java/java/time/chrono/JapaneseDate.java
+++ b/ojluni/src/main/java/java/time/chrono/JapaneseDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -432,10 +432,6 @@
                 field == ALIGNED_WEEK_OF_MONTH || field == ALIGNED_WEEK_OF_YEAR) {
             return false;
         }
-        // Android-changed: Apply upstream OpenJDK 9 compilation fix.
-        // Applied OpenJDK 9 change from http://hg.openjdk.java.net/jdk9/dev/jdk/rev/2b7b09c81bf1
-        // On OpenJDK 8, either version is supported and has the same behavior.
-        // return ChronoLocalDate.super.isSupported(field);
         return super.isSupported(field);
     }
 
diff --git a/ojluni/src/main/java/java/time/chrono/JapaneseEra.java b/ojluni/src/main/java/java/time/chrono/JapaneseEra.java
index 81805d0..83fcb94 100644
--- a/ojluni/src/main/java/java/time/chrono/JapaneseEra.java
+++ b/ojluni/src/main/java/java/time/chrono/JapaneseEra.java
@@ -237,10 +237,11 @@
      * @throws DateTimeException if the value is invalid
      */
     public static JapaneseEra of(int japaneseEra) {
-        if (japaneseEra < MEIJI.eraValue || japaneseEra + ERA_OFFSET > KNOWN_ERAS.length) {
+        int i = ordinal(japaneseEra);
+        if (i < 0 || i >= KNOWN_ERAS.length) {
             throw new DateTimeException("Invalid era: " + japaneseEra);
         }
-        return KNOWN_ERAS[ordinal(japaneseEra)];
+        return KNOWN_ERAS[i];
     }
 
     /**
diff --git a/ojluni/src/main/java/java/time/chrono/MinguoChronology.java b/ojluni/src/main/java/java/time/chrono/MinguoChronology.java
index 841884c..fd6fdc3 100644
--- a/ojluni/src/main/java/java/time/chrono/MinguoChronology.java
+++ b/ojluni/src/main/java/java/time/chrono/MinguoChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,7 +72,6 @@
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.ValueRange;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -306,7 +305,7 @@
 
     @Override
     public List<Era> eras() {
-        return Arrays.<Era>asList(MinguoEra.values());
+        return List.of(MinguoEra.values());
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/main/java/java/time/chrono/MinguoDate.java b/ojluni/src/main/java/java/time/chrono/MinguoDate.java
index 71e0a12..798c8f8 100644
--- a/ojluni/src/main/java/java/time/chrono/MinguoDate.java
+++ b/ojluni/src/main/java/java/time/chrono/MinguoDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/chrono/MinguoEra.java b/ojluni/src/main/java/java/time/chrono/MinguoEra.java
index fd96de1..048fcbf 100644
--- a/ojluni/src/main/java/java/time/chrono/MinguoEra.java
+++ b/ojluni/src/main/java/java/time/chrono/MinguoEra.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,12 @@
  */
 package java.time.chrono;
 
+import static java.time.temporal.ChronoField.ERA;
+
 import java.time.DateTimeException;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
+import java.util.Locale;
 
 /**
  * An era in the Minguo calendar system.
@@ -71,27 +76,28 @@
  * All previous years, zero or earlier in the proleptic count or one and greater
  * in the year-of-era count, are part of the 'Before Republic of China' era.
  *
- * <table summary="Minguo years and eras" cellpadding="2" cellspacing="3" border="0" >
+ * <table class="striped" style="text-align:left">
+ * <caption style="display:none">Minguo years and eras</caption>
  * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left">year-of-era</th>
- * <th class="colFirst" align="left">era</th>
- * <th class="colFirst" align="left">proleptic-year</th>
- * <th class="colLast" align="left">ISO proleptic-year</th>
+ * <tr>
+ * <th>year-of-era</th>
+ * <th>era</th>
+ * <th>proleptic-year</th>
+ * <th>ISO proleptic-year</th>
  * </tr>
  * </thead>
  * <tbody>
- * <tr class="rowColor">
- * <td>2</td><td>ROC</td><td>2</td><td>1913</td>
+ * <tr>
+ * <td>2</td><td>ROC</td><th scope="row">2</th><td>1913</td>
  * </tr>
- * <tr class="altColor">
- * <td>1</td><td>ROC</td><td>1</td><td>1912</td>
+ * <tr>
+ * <td>1</td><td>ROC</td><th scope="row">1</th><td>1912</td>
  * </tr>
- * <tr class="rowColor">
- * <td>1</td><td>BEFORE_ROC</td><td>0</td><td>1911</td>
+ * <tr>
+ * <td>1</td><td>BEFORE_ROC</td><th scope="row">0</th><td>1911</td>
  * </tr>
- * <tr class="altColor">
- * <td>2</td><td>BEFORE_ROC</td><td>-1</td><td>1910</td>
+ * <tr>
+ * <td>2</td><td>BEFORE_ROC</td><th scope="row">-1</th><td>1910</td>
  * </tr>
  * </tbody>
  * </table>
@@ -152,4 +158,19 @@
         return ordinal();
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * @param style {@inheritDoc}
+     * @param locale {@inheritDoc}
+     */
+    @Override
+    public String getDisplayName(TextStyle style, Locale locale) {
+        return new DateTimeFormatterBuilder()
+            .appendText(ERA, style)
+            .toFormatter(locale)
+            .withChronology(MinguoChronology.INSTANCE)
+            .format(this == ROC ? MinguoDate.of(1, 1, 1) : MinguoDate.of(0, 1, 1));
+    }
+
 }
diff --git a/ojluni/src/main/java/java/time/chrono/ThaiBuddhistChronology.java b/ojluni/src/main/java/java/time/chrono/ThaiBuddhistChronology.java
index 5b96c85..c6938b2 100644
--- a/ojluni/src/main/java/java/time/chrono/ThaiBuddhistChronology.java
+++ b/ojluni/src/main/java/java/time/chrono/ThaiBuddhistChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -342,7 +342,7 @@
 
     @Override
     public List<Era> eras() {
-        return Arrays.<Era>asList(ThaiBuddhistEra.values());
+        return List.of(ThaiBuddhistEra.values());
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/main/java/java/time/chrono/ThaiBuddhistDate.java b/ojluni/src/main/java/java/time/chrono/ThaiBuddhistDate.java
index cc58cea..21efbf7 100644
--- a/ojluni/src/main/java/java/time/chrono/ThaiBuddhistDate.java
+++ b/ojluni/src/main/java/java/time/chrono/ThaiBuddhistDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/chrono/ThaiBuddhistEra.java b/ojluni/src/main/java/java/time/chrono/ThaiBuddhistEra.java
index e3e6e86..35e42fc 100644
--- a/ojluni/src/main/java/java/time/chrono/ThaiBuddhistEra.java
+++ b/ojluni/src/main/java/java/time/chrono/ThaiBuddhistEra.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,12 @@
  */
 package java.time.chrono;
 
+import static java.time.temporal.ChronoField.ERA;
+
 import java.time.DateTimeException;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
+import java.util.Locale;
 
 /**
  * An era in the Thai Buddhist calendar system.
@@ -71,27 +76,28 @@
  * All previous years, zero or earlier in the proleptic count or one and greater
  * in the year-of-era count, are part of the 'Before Buddhist' era.
  *
- * <table summary="Buddhist years and eras" cellpadding="2" cellspacing="3" border="0" >
+ * <table class="striped" style="text-align:left">
+ * <caption style="display:none">Buddhist years and eras</caption>
  * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left">year-of-era</th>
- * <th class="colFirst" align="left">era</th>
- * <th class="colFirst" align="left">proleptic-year</th>
- * <th class="colLast" align="left">ISO proleptic-year</th>
+ * <tr>
+ * <th scope="col">year-of-era</th>
+ * <th scope="col">era</th>
+ * <th scope="col">proleptic-year</th>
+ * <th scope="col">ISO proleptic-year</th>
  * </tr>
  * </thead>
  * <tbody>
- * <tr class="rowColor">
- * <td>2</td><td>BE</td><td>2</td><td>-542</td>
+ * <tr>
+ * <td>2</td><td>BE</td><th scope="row">2</th><td>-542</td>
  * </tr>
- * <tr class="altColor">
- * <td>1</td><td>BE</td><td>1</td><td>-543</td>
+ * <tr>
+ * <td>1</td><td>BE</td><th scope="row">1</th><td>-543</td>
  * </tr>
- * <tr class="rowColor">
- * <td>1</td><td>BEFORE_BE</td><td>0</td><td>-544</td>
+ * <tr>
+ * <td>1</td><td>BEFORE_BE</td><th scope="row">0</th><td>-544</td>
  * </tr>
- * <tr class="altColor">
- * <td>2</td><td>BEFORE_BE</td><td>-1</td><td>-545</td>
+ * <tr>
+ * <td>2</td><td>BEFORE_BE</td><th scope="row">-1</th><td>-545</td>
  * </tr>
  * </tbody>
  * </table>
@@ -152,4 +158,19 @@
         return ordinal();
     }
 
+    /**
+     * {@inheritDoc}
+     *
+     * @param style {@inheritDoc}
+     * @param locale {@inheritDoc}
+     */
+    @Override
+    public String getDisplayName(TextStyle style, Locale locale) {
+        return new DateTimeFormatterBuilder()
+            .appendText(ERA, style)
+            .toFormatter(locale)
+            .withChronology(ThaiBuddhistChronology.INSTANCE)
+            .format(this == BE ? ThaiBuddhistDate.of(1, 1, 1) : ThaiBuddhistDate.of(0, 1, 1));
+    }
+
 }
diff --git a/ojluni/src/main/java/java/time/chrono/package-info.java b/ojluni/src/main/java/java/time/chrono/package-info.java
index 9273a77..c382fb1 100644
--- a/ojluni/src/main/java/java/time/chrono/package-info.java
+++ b/ojluni/src/main/java/java/time/chrono/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -95,7 +95,7 @@
  * <li>{@link java.time.chrono.ThaiBuddhistChronology Thai Buddhist calendar}</li>
  * </ul>
  *
- * <h3>Example</h3>
+ * <h2>Example</h2>
  * <p>
  * This example lists todays date for all of the available calendars.
  * </p>
@@ -155,7 +155,7 @@
  *                 first, last);
  *  </pre>
  *
- * <h3>Package specification</h3>
+ * <h2>Package specification</h2>
  * <p>
  * Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
  * in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
@@ -166,6 +166,6 @@
  * All calculations should check for numeric overflow and throw either an {@link java.lang.ArithmeticException}
  * or a {@link java.time.DateTimeException}.
  * </p>
- * @since JDK1.8
+ * @since 1.8
  */
 package java.time.chrono;
diff --git a/ojluni/src/main/java/java/time/format/DateTimeFormatter.java b/ojluni/src/main/java/java/time/format/DateTimeFormatter.java
index 57a0bf8..761cab7 100644
--- a/ojluni/src/main/java/java/time/format/DateTimeFormatter.java
+++ b/ojluni/src/main/java/java/time/format/DateTimeFormatter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,6 +80,7 @@
 import java.time.Period;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
+import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.Chronology;
 import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser;
@@ -95,7 +96,9 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
+import libcore.icu.ICU;
 
 /**
  * Formatter for printing and parsing date-time objects.
@@ -149,106 +152,107 @@
  * implementation of {@code java.text.Format}.
  *
  * <h3 id="predefined">Predefined Formatters</h3>
- * <table summary="Predefined Formatters" cellpadding="2" cellspacing="3" border="0" >
+ * <table class="striped" style="text-align:left">
+ * <caption>Predefined Formatters</caption>
  * <thead>
- * <tr class="tableSubHeadingColor">
- * <th class="colFirst" align="left">Formatter</th>
- * <th class="colFirst" align="left">Description</th>
- * <th class="colLast" align="left">Example</th>
+ * <tr>
+ * <th scope="col">Formatter</th>
+ * <th scope="col">Description</th>
+ * <th scope="col">Example</th>
  * </tr>
  * </thead>
  * <tbody>
- * <tr class="rowColor">
- * <td>{@link #ofLocalizedDate ofLocalizedDate(dateStyle)} </td>
+ * <tr>
+ * <th scope="row">{@link #ofLocalizedDate ofLocalizedDate(dateStyle)} </th>
  * <td> Formatter with date style from the locale </td>
  * <td> '2011-12-03'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ofLocalizedTime ofLocalizedTime(timeStyle)} </td>
+ * <tr>
+ * <th scope="row"> {@link #ofLocalizedTime ofLocalizedTime(timeStyle)} </th>
  * <td> Formatter with time style from the locale </td>
  * <td> '10:15:30'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #ofLocalizedDateTime ofLocalizedDateTime(dateTimeStyle)} </td>
+ * <tr>
+ * <th scope="row"> {@link #ofLocalizedDateTime ofLocalizedDateTime(dateTimeStyle)} </th>
  * <td> Formatter with a style for date and time from the locale</td>
  * <td> '3 Jun 2008 11:05:30'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ofLocalizedDateTime ofLocalizedDateTime(dateStyle,timeStyle)}
- * </td>
+ * <tr>
+ * <th scope="row"> {@link #ofLocalizedDateTime ofLocalizedDateTime(dateStyle,timeStyle)}
+ * </th>
  * <td> Formatter with date and time styles from the locale </td>
  * <td> '3 Jun 2008 11:05'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #BASIC_ISO_DATE}</td>
+ * <tr>
+ * <th scope="row"> {@link #BASIC_ISO_DATE}</th>
  * <td>Basic ISO date </td> <td>'20111203'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ISO_LOCAL_DATE}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_LOCAL_DATE}</th>
  * <td> ISO Local Date </td>
  * <td>'2011-12-03'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #ISO_OFFSET_DATE}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_OFFSET_DATE}</th>
  * <td> ISO Date with offset </td>
  * <td>'2011-12-03+01:00'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ISO_DATE}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_DATE}</th>
  * <td> ISO Date with or without offset </td>
  * <td> '2011-12-03+01:00'; '2011-12-03'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #ISO_LOCAL_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_LOCAL_TIME}</th>
  * <td> Time without offset </td>
  * <td>'10:15:30'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ISO_OFFSET_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_OFFSET_TIME}</th>
  * <td> Time with offset </td>
  * <td>'10:15:30+01:00'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #ISO_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_TIME}</th>
  * <td> Time with or without offset </td>
  * <td>'10:15:30+01:00'; '10:15:30'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ISO_LOCAL_DATE_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_LOCAL_DATE_TIME}</th>
  * <td> ISO Local Date and Time </td>
  * <td>'2011-12-03T10:15:30'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #ISO_OFFSET_DATE_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_OFFSET_DATE_TIME}</th>
  * <td> Date Time with Offset
- * </td><td>2011-12-03T10:15:30+01:00'</td>
+ * </td><td>'2011-12-03T10:15:30+01:00'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ISO_ZONED_DATE_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_ZONED_DATE_TIME}</th>
  * <td> Zoned Date Time </td>
  * <td>'2011-12-03T10:15:30+01:00[Europe/Paris]'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #ISO_DATE_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_DATE_TIME}</th>
  * <td> Date and time with ZoneId </td>
  * <td>'2011-12-03T10:15:30+01:00[Europe/Paris]'</td>
  * </tr>
- * <tr class="altColor">
- * <td> {@link #ISO_ORDINAL_DATE}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_ORDINAL_DATE}</th>
  * <td> Year and day of year </td>
  * <td>'2012-337'</td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #ISO_WEEK_DATE}</td>
+ * <tr>
+ * <th scope="row"> {@link #ISO_WEEK_DATE}</th>
  * <td> Year and Week </td>
- * <td>2012-W48-6'</td></tr>
- * <tr class="altColor">
- * <td> {@link #ISO_INSTANT}</td>
+ * <td>'2012-W48-6'</td></tr>
+ * <tr>
+ * <th scope="row"> {@link #ISO_INSTANT}</th>
  * <td> Date and Time of an Instant </td>
  * <td>'2011-12-03T10:15:30Z' </td>
  * </tr>
- * <tr class="rowColor">
- * <td> {@link #RFC_1123_DATE_TIME}</td>
+ * <tr>
+ * <th scope="row"> {@link #RFC_1123_DATE_TIME}</th>
  * <td> RFC 1123 / RFC 822 </td>
  * <td>'Tue, 3 Jun 2008 11:05:30 GMT'</td>
  * </tr>
@@ -274,54 +278,60 @@
  * <p>
  * All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The
  * following pattern letters are defined:
- * <pre>
- *  Symbol  Meaning                     Presentation      Examples
- *  ------  -------                     ------------      -------
- *   G       era                         text              AD; Anno Domini; A
- *   u       year                        year              2004; 04
- *   y       year-of-era                 year              2004; 04
- *   D       day-of-year                 number            189
- *   M/L     month-of-year               number/text       7; 07; Jul; July; J
- *   d       day-of-month                number            10
+ * <table class="striped">
+ * <caption>Pattern Letters and Symbols</caption>
+ * <thead>
+ *  <tr><th scope="col">Symbol</th>   <th scope="col">Meaning</th>         <th scope="col">Presentation</th> <th scope="col">Examples</th>
+ * </thead>
+ * <tbody>
+ *   <tr><th scope="row">G</th>       <td>era</td>                         <td>text</td>              <td>AD; Anno Domini; A</td>
+ *   <tr><th scope="row">u</th>       <td>year</td>                        <td>year</td>              <td>2004; 04</td>
+ *   <tr><th scope="row">y</th>       <td>year-of-era</td>                 <td>year</td>              <td>2004; 04</td>
+ *   <tr><th scope="row">D</th>       <td>day-of-year</td>                 <td>number</td>            <td>189</td>
+ *   <tr><th scope="row">M/L</th>     <td>month-of-year</td>               <td>number/text</td>       <td>7; 07; Jul; July; J</td>
+ *   <tr><th scope="row">d</th>       <td>day-of-month</td>                <td>number</td>            <td>10</td>
+ *   <tr><th scope="row">g</th>       <td>modified-julian-day</td>         <td>number</td>            <td>2451334</td>
  *
- *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
- *   Y       week-based-year             year              1996; 96
- *   w       week-of-week-based-year     number            27
- *   W       week-of-month               number            4
- *   E       day-of-week                 text              Tue; Tuesday; T
- *   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
- *   F       week-of-month               number            3
+ *   <tr><th scope="row">Q/q</th>     <td>quarter-of-year</td>             <td>number/text</td>       <td>3; 03; Q3; 3rd quarter</td>
+ *   <tr><th scope="row">Y</th>       <td>week-based-year</td>             <td>year</td>              <td>1996; 96</td>
+ *   <tr><th scope="row">w</th>       <td>week-of-week-based-year</td>     <td>number</td>            <td>27</td>
+ *   <tr><th scope="row">W</th>       <td>week-of-month</td>               <td>number</td>            <td>4</td>
+ *   <tr><th scope="row">E</th>       <td>day-of-week</td>                 <td>text</td>              <td>Tue; Tuesday; T</td>
+ *   <tr><th scope="row">e/c</th>     <td>localized day-of-week</td>       <td>number/text</td>       <td>2; 02; Tue; Tuesday; T</td>
+ *   <tr><th scope="row">F</th>       <td>day-of-week-in-month</td>        <td>number</td>            <td>3</td>
  *
- *   a       am-pm-of-day                text              PM
- *   h       clock-hour-of-am-pm (1-12)  number            12
- *   K       hour-of-am-pm (0-11)        number            0
- *   k       clock-hour-of-am-pm (1-24)  number            0
+ *   <tr><th scope="row">a</th>       <td>am-pm-of-day</td>                <td>text</td>              <td>PM</td>
+ *   <tr><th scope="row">h</th>       <td>clock-hour-of-am-pm (1-12)</td>  <td>number</td>            <td>12</td>
+ *   <tr><th scope="row">K</th>       <td>hour-of-am-pm (0-11)</td>        <td>number</td>            <td>0</td>
+ *   <tr><th scope="row">k</th>       <td>clock-hour-of-day (1-24)</td>    <td>number</td>            <td>24</td>
  *
- *   H       hour-of-day (0-23)          number            0
- *   m       minute-of-hour              number            30
- *   s       second-of-minute            number            55
- *   S       fraction-of-second          fraction          978
- *   A       milli-of-day                number            1234
- *   n       nano-of-second              number            987654321
- *   N       nano-of-day                 number            1234000000
+ *   <tr><th scope="row">H</th>       <td>hour-of-day (0-23)</td>          <td>number</td>            <td>0</td>
+ *   <tr><th scope="row">m</th>       <td>minute-of-hour</td>              <td>number</td>            <td>30</td>
+ *   <tr><th scope="row">s</th>       <td>second-of-minute</td>            <td>number</td>            <td>55</td>
+ *   <tr><th scope="row">S</th>       <td>fraction-of-second</td>          <td>fraction</td>          <td>978</td>
+ *   <tr><th scope="row">A</th>       <td>milli-of-day</td>                <td>number</td>            <td>1234</td>
+ *   <tr><th scope="row">n</th>       <td>nano-of-second</td>              <td>number</td>            <td>987654321</td>
+ *   <tr><th scope="row">N</th>       <td>nano-of-day</td>                 <td>number</td>            <td>1234000000</td>
  *
- *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
- *   z       time-zone name              zone-name         Pacific Standard Time; PST
- *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
- *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
- *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
- *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
+ *   <tr><th scope="row">V</th>       <td>time-zone ID</td>                <td>zone-id</td>           <td>America/Los_Angeles; Z; -08:30</td>
+ *   <tr><th scope="row">v</th>       <td>generic time-zone name</td>      <td>zone-name</td>         <td>Pacific Time; PT</td>
+ *   <tr><th scope="row">z</th>       <td>time-zone name</td>              <td>zone-name</td>         <td>Pacific Standard Time; PST</td>
+ *   <tr><th scope="row">O</th>       <td>localized zone-offset</td>       <td>offset-O</td>          <td>GMT+8; GMT+08:00; UTC-08:00</td>
+ *   <tr><th scope="row">X</th>       <td>zone-offset 'Z' for zero</td>    <td>offset-X</td>          <td>Z; -08; -0830; -08:30; -083015; -08:30:15</td>
+ *   <tr><th scope="row">x</th>       <td>zone-offset</td>                 <td>offset-x</td>          <td>+0000; -08; -0830; -08:30; -083015; -08:30:15</td>
+ *   <tr><th scope="row">Z</th>       <td>zone-offset</td>                 <td>offset-Z</td>          <td>+0000; -0800; -08:00</td>
  *
- *   p       pad next                    pad modifier      1
+ *   <tr><th scope="row">p</th>       <td>pad next</td>                    <td>pad modifier</td>      <td>1</td>
  *
- *   '       escape for text             delimiter
- *   ''      single quote                literal           '
- *   [       optional section start
- *   ]       optional section end
- *   #       reserved for future use
- *   {       reserved for future use
- *   }       reserved for future use
- * </pre>
+ *   <tr><th scope="row">'</th>       <td>escape for text</td>             <td>delimiter</td>         <td></td>
+ *   <tr><th scope="row">''</th>      <td>single quote</td>                <td>literal</td>           <td>'</td>
+ *   <tr><th scope="row">[</th>       <td>optional section start</td>      <td></td>                  <td></td>
+ *   <tr><th scope="row">]</th>       <td>optional section end</td>        <td></td>                  <td></td>
+ *   <tr><th scope="row">#</th>       <td>reserved for future use</td>     <td></td>                  <td></td>
+ *   <tr><th scope="row">{</th>       <td>reserved for future use</td>     <td></td>                  <td></td>
+ *   <tr><th scope="row">}</th>       <td>reserved for future use</td>     <td></td>                  <td></td>
+ * </tbody>
+ * </table>
  * <p>
  * The count of pattern letters determines the format.
  * <p>
@@ -363,9 +373,17 @@
  * letters throws {@code IllegalArgumentException}.
  * <p>
  * <b>Zone names</b>: This outputs the display name of the time-zone ID. If the
- * count of letters is one, two or three, then the short name is output. If the
- * count of letters is four, then the full name is output. Five or more letters
- * throws {@code IllegalArgumentException}.
+ * pattern letter is 'z' the output is the daylight savings aware zone name.
+ * If there is insufficient information to determine whether DST applies,
+ * the name ignoring daylight savings time will be used.
+ * If the count of letters is one, two or three, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Five or more letters throws {@code IllegalArgumentException}.
+ * <p>
+ * If the pattern letter is 'v' the output provides the zone name ignoring
+ * daylight savings time. If the count of letters is one, then the short name is output.
+ * If the count of letters is four, then the full name is output.
+ * Two, three and five or more letters throw {@code IllegalArgumentException}.
  * <p>
  * <b>Offset X and x</b>: This formats the offset based on the number of pattern
  * letters. One letter outputs just the hour, such as '+01', unless the minute
@@ -473,6 +491,17 @@
  * day-of-week was valid for the date.
  * <li>If an {@linkplain #parsedExcessDays() excess number of days}
  * was parsed then it is added to the date if a date is available.
+ * <li> If a second-based field is present, but {@code LocalTime} was not parsed,
+ * then the resolver ensures that milli, micro and nano second values are
+ * available to meet the contract of {@link ChronoField}.
+ * These will be set to zero if missing.
+ * <li>If both date and time were parsed and either an offset or zone is present,
+ * the field {@link ChronoField#INSTANT_SECONDS} is created.
+ * If an offset was parsed then the offset will be combined with the
+ * {@code LocalDateTime} to form the instant, with any zone ignored.
+ * If a {@code ZoneId} was parsed without an offset then the zone will be
+ * combined with the {@code LocalDateTime} to form the instant using the rules
+ * of {@link ChronoLocalDateTime#atZone(ZoneId)}.
  * </ol>
  *
  * @implSpec
@@ -521,7 +550,7 @@
      * For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
      * <p>
      * The formatter will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
-     * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
+     * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter.
      * Alternatively use the {@link #ofPattern(String, Locale)} variant of this method.
      * <p>
      * The returned formatter has no override chronology or zone.
@@ -545,7 +574,7 @@
      * For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
      * <p>
      * The formatter will use the specified locale.
-     * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
+     * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter.
      * <p>
      * The returned formatter has no override chronology or zone.
      * It uses {@link ResolverStyle#SMART SMART} resolver style.
@@ -607,6 +636,9 @@
      * The returned formatter has a chronology of ISO set to ensure dates in
      * other calendar systems are correctly converted.
      * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
+     * The {@code FULL} and {@code LONG} styles typically require a time-zone.
+     * When formatting using these styles, a {@code ZoneId} must be available,
+     * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
      *
      * @param timeStyle  the formatter style to obtain, not null
      * @return the time formatter, not null
@@ -635,6 +667,9 @@
      * The returned formatter has a chronology of ISO set to ensure dates in
      * other calendar systems are correctly converted.
      * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
+     * The {@code FULL} and {@code LONG} styles typically require a time-zone.
+     * When formatting using these styles, a {@code ZoneId} must be available,
+     * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
      *
      * @param dateTimeStyle  the formatter style to obtain, not null
      * @return the date-time formatter, not null
@@ -663,6 +698,9 @@
      * The returned formatter has a chronology of ISO set to ensure dates in
      * other calendar systems are correctly converted.
      * It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
+     * The {@code FULL} and {@code LONG} styles typically require a time-zone.
+     * When formatting using these styles, a {@code ZoneId} must be available,
+     * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
      *
      * @param dateStyle  the date formatter style to obtain, not null
      * @param timeStyle  the time formatter style to obtain, not null
@@ -911,6 +949,7 @@
      * <li>The {@link #ISO_LOCAL_DATE_TIME}
      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
      *  they will be handled even though this is not part of the ISO-8601 standard.
+     *  The offset parsing is lenient, which allows the minutes and seconds to be optional.
      *  Parsing is case insensitive.
      * </ul>
      * <p>
@@ -923,7 +962,9 @@
         ISO_OFFSET_DATE_TIME = new DateTimeFormatterBuilder()
                 .parseCaseInsensitive()
                 .append(ISO_LOCAL_DATE_TIME)
+                .parseLenient()
                 .appendOffsetId()
+                .parseStrict()
                 .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
     }
 
@@ -1099,7 +1140,7 @@
      * This returns an immutable formatter capable of formatting and parsing
      * the ISO-8601 instant format.
      * When formatting, the second-of-minute is always output.
-     * The nano-of-second outputs zero, three, six or nine digits digits as necessary.
+     * The nano-of-second outputs zero, three, six or nine digits as necessary.
      * When parsing, time to at least the seconds field is required.
      * Fractional seconds from zero to nine are parsed.
      * The localized decimal style is not used.
@@ -1148,6 +1189,7 @@
      * <li>If the offset is not available to format or parse then the format is complete.
      * <li>The {@link ZoneOffset#getId() offset ID} without colons. If the offset has
      *  seconds then they will be handled even though this is not part of the ISO-8601 standard.
+     *  The offset parsing is lenient, which allows the minutes and seconds to be optional.
      *  Parsing is case insensitive.
      * </ul>
      * <p>
@@ -1166,7 +1208,9 @@
                 .appendValue(MONTH_OF_YEAR, 2)
                 .appendValue(DAY_OF_MONTH, 2)
                 .optionalStart()
+                .parseLenient()
                 .appendOffset("+HHMMss", "Z")
+                .parseStrict()
                 .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
     }
 
@@ -1395,12 +1439,15 @@
         return locale;
     }
 
+    // Android-changed: Remove javadoc reference to #localizedBy(Locale)
     /**
      * Returns a copy of this formatter with a new locale.
      * <p>
      * This is used to lookup any part of the formatter needing specific
      * localization, such as the text or localized pattern.
      * <p>
+     * The locale is stored as passed in, without further processing.
+     * <p>
      * This instance is immutable and unaffected by this method call.
      *
      * @param locale  the new locale, not null
@@ -1413,6 +1460,53 @@
         return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
     }
 
+    // Android-changed: Remove "rg" extension support in the javadoc. See http://b/228322300.
+    /**
+     * Returns a copy of this formatter with localized values of the locale,
+     * calendar, decimal style and/or timezone, that superseded values in
+     * this formatter.
+     * <p>
+     * This is used to lookup any part of the formatter needing specific
+     * localization, such as the text or localized pattern. If the locale contains the
+     * "ca" (calendar), "nu" (numbering system) and/or
+     * "tz" (timezone)
+     * <a href="../../util/Locale.html#def_locale_extension">Unicode extensions</a>,
+     * the chronology, numbering system and/or the zone are overridden.
+     * <p>
+     * Unlike the {@link #withLocale withLocale} method, the call to this method may
+     * produce a different formatter depending on the order of method chaining with
+     * other withXXXX() methods.
+     * <p>
+     * This instance is immutable and unaffected by this method call.
+     *
+     * @param locale  the locale, not null
+     * @return a formatter based on this formatter with localized values of
+     *      the calendar, decimal style and/or timezone, that superseded values in this
+     *      formatter.
+     * @see #withLocale(Locale)
+     * @since 10
+     */
+    public DateTimeFormatter localizedBy(Locale locale) {
+        if (this.locale.equals(locale)) {
+            return this;
+        }
+
+        // Check for decimalStyle/chronology/timezone in locale object
+        Chronology c = locale.getUnicodeLocaleType("ca") != null ?
+                       Chronology.ofLocale(locale) : chrono;
+        DecimalStyle ds = locale.getUnicodeLocaleType("nu") != null ?
+                       DecimalStyle.of(locale) : decimalStyle;
+        String tzType = locale.getUnicodeLocaleType("tz");
+        ZoneId z  = tzType != null ?
+                    // Android changed: Use ICU on Android.
+                    // TimeZoneNameUtility.convertLDMLShortID(tzType)
+                    Optional.ofNullable(ICU.convertToTzId(tzType))
+                        .map(ZoneId::of)
+                        .orElse(zone) :
+                    zone;
+        return new DateTimeFormatter(printerParser, locale, ds, resolverStyle, resolverFields, c, z);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Gets the DecimalStyle to be used during formatting.
@@ -1648,6 +1742,7 @@
     public DateTimeFormatter withResolverFields(TemporalField... resolverFields) {
         Set<TemporalField> fields = null;
         if (resolverFields != null) {
+            // Set.of cannot be used because it is hostile to nulls and duplicate elements
             fields = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(resolverFields)));
         }
         if (Objects.equals(this.resolverFields, fields)) {
diff --git a/ojluni/src/main/java/java/time/format/DateTimeFormatterBuilder.java b/ojluni/src/main/java/java/time/format/DateTimeFormatterBuilder.java
index fff8d9a..921d73c 100644
--- a/ojluni/src/main/java/java/time/format/DateTimeFormatterBuilder.java
+++ b/ojluni/src/main/java/java/time/format/DateTimeFormatterBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
  *
  * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
  *
- * All rights hg qreserved.
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -76,6 +76,7 @@
 import static java.time.temporal.ChronoField.OFFSET_SECONDS;
 import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
 import static java.time.temporal.ChronoField.YEAR;
+import static java.time.temporal.ChronoField.ERA;
 
 import com.android.icu.util.ExtendedCalendar;
 
@@ -90,14 +91,18 @@
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.Chronology;
+import java.time.chrono.Era;
 import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeTextProvider.LocaleStore;
 import java.time.temporal.ChronoField;
 import java.time.temporal.IsoFields;
+import java.time.temporal.JulianFields;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQueries;
@@ -193,6 +198,7 @@
      */
     private int valueParserIndex = -1;
 
+    // Android-changed: Remove "rg" extension support in the javadoc. See http://b/228322300.
     /**
      * Gets the formatting pattern for date and time styles for a locale and chronology.
      * The locale and chronology are used to lookup the locale specific format
@@ -214,12 +220,16 @@
         }
 
         // BEGIN Android-changed: get format string from ICU.
-        // LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
-        //         .getLocaleResources(locale);
-        // String pattern = lr.getJavaTimeDateTimePattern(
-        //         convertStyle(timeStyle), convertStyle(dateStyle), chrono.getCalendarType());
-        ExtendedCalendar extendedCalendar = ICU.getExtendedCalendar(locale,
-                chrono.getCalendarType());
+        // LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, locale);
+        // JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider();
+        // String pattern = provider.getJavaTimeDateTimePattern(convertStyle(timeStyle),
+        //                  convertStyle(dateStyle), chrono.getCalendarType(),
+        //                  CalendarDataUtility.findRegionOverride(locale));
+
+        // "iso8601" calendar type doesn't work well for ICU due to http://b/206566562.
+        // Workaround the issue by using Gregorian calendar.
+        String calType = chrono instanceof IsoChronology ? "gregorian" : chrono.getCalendarType();
+        ExtendedCalendar extendedCalendar = ICU.getExtendedCalendar(locale, calType);
         String pattern = extendedCalendar.getDateTimePattern(convertStyle(dateStyle),
                 convertStyle(timeStyle));
         // Transform the pattern coming from ICU because DateTimeFormatter does not handle some date
@@ -667,6 +677,7 @@
     }
 
     //-----------------------------------------------------------------------
+    // Android changed: Fix the javadoc by adding # symbol before the method signature.
     /**
      * Appends the fractional value of a date-time field to the formatter.
      * <p>
@@ -681,8 +692,11 @@
      * No rounding occurs due to the maximum width - digits are simply dropped.
      * <p>
      * When parsing in strict mode, the number of parsed digits must be between
-     * the minimum and maximum width. When parsing in lenient mode, the minimum
-     * width is considered to be zero and the maximum is nine.
+     * the minimum and maximum width. In strict mode, if the minimum and maximum widths
+     * are equal and there is no decimal point then the parser will
+     * participate in adjacent value parsing, see
+     * {@link #appendValue(java.time.temporal.TemporalField, int)}. When parsing in lenient mode,
+     * the minimum width is considered to be zero and the maximum is nine.
      * <p>
      * If the value cannot be obtained then an exception will be thrown.
      * If the value is negative an exception will be thrown.
@@ -701,7 +715,12 @@
      */
     public DateTimeFormatterBuilder appendFraction(
             TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) {
-        appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint));
+        if (minWidth == maxWidth && decimalPoint == false) {
+            // adjacent parsing
+            appendValue(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint));
+        } else {
+            appendInternal(new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint));
+        }
         return this;
     }
 
@@ -789,11 +808,22 @@
         final LocaleStore store = new LocaleStore(map);
         DateTimeTextProvider provider = new DateTimeTextProvider() {
             @Override
+            public String getText(Chronology chrono, TemporalField field,
+                                  long value, TextStyle style, Locale locale) {
+                return store.getText(value, style);
+            }
+            @Override
             public String getText(TemporalField field, long value, TextStyle style, Locale locale) {
                 return store.getText(value, style);
             }
             @Override
-            public Iterator<Entry<String, Long>> getTextIterator(TemporalField field, TextStyle style, Locale locale) {
+            public Iterator<Entry<String, Long>> getTextIterator(Chronology chrono,
+                    TemporalField field, TextStyle style, Locale locale) {
+                return store.getTextIterator(style);
+            }
+            @Override
+            public Iterator<Entry<String, Long>> getTextIterator(TemporalField field,
+                    TextStyle style, Locale locale) {
                 return store.getTextIterator(style);
             }
         };
@@ -810,11 +840,11 @@
      * They are converted to a date-time with a zone-offset of UTC and formatted
      * using the standard ISO-8601 format.
      * With this method, formatting nano-of-second outputs zero, three, six
-     * or nine digits digits as necessary.
+     * or nine digits as necessary.
      * The localized decimal style is not used.
      * <p>
      * The instant is obtained using {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS}
-     * and optionally (@code NANO_OF_SECOND). The value of {@code INSTANT_SECONDS}
+     * and optionally {@code NANO_OF_SECOND}. The value of {@code INSTANT_SECONDS}
      * may be outside the maximum range of {@code LocalDateTime}.
      * <p>
      * The {@linkplain ResolverStyle resolver style} has no effect on instant parsing.
@@ -852,7 +882,7 @@
      * digits from zero to nine are accepted.
      * <p>
      * The instant is obtained using {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS}
-     * and optionally (@code NANO_OF_SECOND). The value of {@code INSTANT_SECONDS}
+     * and optionally {@code NANO_OF_SECOND}. The value of {@code INSTANT_SECONDS}
      * may be outside the maximum range of {@code LocalDateTime}.
      * <p>
      * The {@linkplain ResolverStyle resolver style} has no effect on instant parsing.
@@ -866,6 +896,7 @@
      * @param fractionalDigits  the number of fractional second digits to format with,
      *  from 0 to 9, or -1 to use as many digits as necessary
      * @return this, for chaining, not null
+     * @throws IllegalArgumentException if the number of fractional digits is invalid
      */
     public DateTimeFormatterBuilder appendInstant(int fractionalDigits) {
         if (fractionalDigits < -1 || fractionalDigits > 9) {
@@ -880,7 +911,9 @@
      * Appends the zone offset, such as '+01:00', to the formatter.
      * <p>
      * This appends an instruction to format/parse the offset ID to the builder.
-     * This is equivalent to calling {@code appendOffset("+HH:MM:ss", "Z")}.
+     * This is equivalent to calling {@code appendOffset("+HH:mm:ss", "Z")}.
+     * See {@link #appendOffset(String, String)} for details on formatting
+     * and parsing.
      *
      * @return this, for chaining, not null
      */
@@ -900,9 +933,18 @@
      * If the offset cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
-     * During parsing, the offset is parsed using the format defined below.
-     * If the offset cannot be parsed then an exception is thrown unless the
-     * section of the formatter is optional.
+     * When parsing in strict mode, the input must contain the mandatory
+     * and optional elements are defined by the specified pattern.
+     * If the offset cannot be parsed then an exception is thrown unless
+     * the section of the formatter is optional.
+     * <p>
+     * When parsing in lenient mode, only the hours are mandatory - minutes
+     * and seconds are optional. The colons are required if the specified
+     * pattern contains a colon. If the specified pattern is "+HH", the
+     * presence of colons is determined by whether the character after the
+     * hour digits is a colon or not.
+     * If the offset cannot be parsed then an exception is thrown unless
+     * the section of the formatter is optional.
      * <p>
      * The format of the offset is controlled by a pattern which must be one
      * of the following:
@@ -916,7 +958,28 @@
      * <li>{@code +HH:MM:ss} - hour and minute, with second if non-zero, with colon
      * <li>{@code +HHMMSS} - hour, minute and second, no colon
      * <li>{@code +HH:MM:SS} - hour, minute and second, with colon
+     * <li>{@code +HHmmss} - hour, with minute if non-zero or with minute and
+     * second if non-zero, no colon
+     * <li>{@code +HH:mm:ss} - hour, with minute if non-zero or with minute and
+     * second if non-zero, with colon
+     * <li>{@code +H} - hour only, ignoring minute and second
+     * <li>{@code +Hmm} - hour, with minute if non-zero, ignoring second, no colon
+     * <li>{@code +H:mm} - hour, with minute if non-zero, ignoring second, with colon
+     * <li>{@code +HMM} - hour and minute, ignoring second, no colon
+     * <li>{@code +H:MM} - hour and minute, ignoring second, with colon
+     * <li>{@code +HMMss} - hour and minute, with second if non-zero, no colon
+     * <li>{@code +H:MM:ss} - hour and minute, with second if non-zero, with colon
+     * <li>{@code +HMMSS} - hour, minute and second, no colon
+     * <li>{@code +H:MM:SS} - hour, minute and second, with colon
+     * <li>{@code +Hmmss} - hour, with minute if non-zero or with minute and
+     * second if non-zero, no colon
+     * <li>{@code +H:mm:ss} - hour, with minute if non-zero or with minute and
+     * second if non-zero, with colon
      * </ul>
+     * Patterns containing "HH" will format and parse a two digit hour,
+     * zero-padded if necessary. Patterns containing "H" will format with no
+     * zero-padding, and parse either one or two digits.
+     * In lenient mode, the parser will be greedy and parse the maximum digits possible.
      * The "no offset" text controls what text is printed when the total amount of
      * the offset fields to be output is zero.
      * Example values would be 'Z', '+00:00', 'UTC' or 'GMT'.
@@ -926,6 +989,7 @@
      * @param pattern  the pattern to use, not null
      * @param noOffsetText  the text to use when the offset is zero, not null
      * @return this, for chaining, not null
+     * @throws IllegalArgumentException if the pattern is invalid
      */
     public DateTimeFormatterBuilder appendOffset(String pattern, String noOffsetText) {
         appendInternal(new OffsetIdPrinterParser(pattern, noOffsetText));
@@ -955,7 +1019,7 @@
      * During parsing, the offset is parsed using the format defined above.
      * If the offset cannot be parsed then an exception is thrown unless the
      * section of the formatter is optional.
-     * <p>
+     *
      * @param style  the format style to use, not null
      * @return this, for chaining, not null
      * @throws IllegalArgumentException if style is neither {@link TextStyle#FULL
@@ -1146,10 +1210,11 @@
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
-     * will be the summer or winter time text as appropriate.
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap then
+     * the text will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1166,7 +1231,7 @@
      * @return this, for chaining, not null
      */
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle) {
-        appendInternal(new ZoneTextPrinterParser(textStyle, null));
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, false));
         return this;
     }
 
@@ -1182,10 +1247,11 @@
      * result of {@link ZoneOffset#getId()}.
      * If the zone is not an offset, the textual name will be looked up
      * for the locale set in the {@link DateTimeFormatter}.
-     * If the temporal object being printed represents an instant, then the text
+     * If the temporal object being printed represents an instant, or if it is a
+     * local date-time that is not in a daylight saving gap or overlap, then the text
      * will be the summer or winter time text as appropriate.
      * If the lookup for text does not find any suitable result, then the
-     * {@link ZoneId#getId() ID} will be printed instead.
+     * {@link ZoneId#getId() ID} will be printed.
      * If the zone cannot be obtained then an exception is thrown unless the
      * section of the formatter is optional.
      * <p>
@@ -1209,7 +1275,72 @@
     public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle,
                                                    Set<ZoneId> preferredZones) {
         Objects.requireNonNull(preferredZones, "preferredZones");
-        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones));
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, false));
+        return this;
+    }
+    //----------------------------------------------------------------------
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * During formatting, the zone is obtained using a mechanism equivalent
+     * to querying the temporal with {@link TemporalQueries#zoneId()}.
+     * If the zone is a {@code ZoneOffset} it will be printed using the
+     * result of {@link ZoneOffset#getId()}.
+     * If the zone is not an offset, the textual name will be looked up
+     * for the locale set in the {@link DateTimeFormatter}.
+     * If the lookup for text does not find any suitable result, then the
+     * {@link ZoneId#getId() ID} will be printed.
+     * If the zone cannot be obtained then an exception is thrown unless the
+     * section of the formatter is optional.
+     * <p>
+     * During parsing, either the textual zone name, the zone ID or the offset
+     * is accepted. Many textual zone names are not unique, such as CST can be
+     * for both "Central Standard Time" and "China Standard Time". In this
+     * situation, the zone id will be determined by the region information from
+     * formatter's  {@link DateTimeFormatter#getLocale() locale} and the standard
+     * zone id for that area, for example, America/New_York for the America Eastern zone.
+     * The {@link #appendGenericZoneText(TextStyle, Set)} may be used
+     * to specify a set of preferred {@link ZoneId} in this situation.
+     *
+     * @param textStyle  the text style to use, not null
+     * @return this, for chaining, not null
+     * @since 9
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, null, true));
+        return this;
+    }
+
+    /**
+     * Appends the generic time-zone name, such as 'Pacific Time', to the formatter.
+     * <p>
+     * This appends an instruction to format/parse the generic textual
+     * name of the zone to the builder. The generic name is the same throughout the whole
+     * year, ignoring any daylight saving changes. For example, 'Pacific Time' is the
+     * generic name, whereas 'Pacific Standard Time' and 'Pacific Daylight Time' are the
+     * specific names, see {@link #appendZoneText(TextStyle)}.
+     * <p>
+     * This method also allows a set of preferred {@link ZoneId} to be
+     * specified for parsing. The matched preferred zone id will be used if the
+     * textural zone name being parsed is not unique.
+     * <p>
+     * See {@link #appendGenericZoneText(TextStyle)} for details about
+     * formatting and parsing.
+     *
+     * @param textStyle  the text style to use, not null
+     * @param preferredZones  the set of preferred zone ids, not null
+     * @return this, for chaining, not null
+     * @since 9
+     */
+    public DateTimeFormatterBuilder appendGenericZoneText(TextStyle textStyle,
+                                                          Set<ZoneId> preferredZones) {
+        appendInternal(new ZoneTextPrinterParser(textStyle, preferredZones, true));
         return this;
     }
 
@@ -1269,6 +1400,9 @@
      * During formatting, the chronology is obtained from the temporal object
      * being formatted, which may have been overridden by
      * {@link DateTimeFormatter#withChronology(Chronology)}.
+     * The {@code FULL} and {@code LONG} styles typically require a time-zone.
+     * When formatting using these styles, a {@code ZoneId} must be available,
+     * either by using {@code ZonedDateTime} or {@link DateTimeFormatter#withZone}.
      * <p>
      * During parsing, if a chronology has already been parsed, then it is used.
      * Otherwise the default from {@code DateTimeFormatter.withChronology(Chronology)}
@@ -1316,7 +1450,7 @@
      */
     public DateTimeFormatterBuilder appendLiteral(String literal) {
         Objects.requireNonNull(literal, "literal");
-        if (literal.length() > 0) {
+        if (!literal.isEmpty()) {
             if (literal.length() == 1) {
                 appendInternal(new CharLiteralPrinterParser(literal.charAt(0)));
             } else {
@@ -1378,6 +1512,7 @@
      *   D       day-of-year                 number            189
      *   M/L     month-of-year               number/text       7; 07; Jul; July; J
      *   d       day-of-month                number            10
+     *   g       modified-julian-day         number            2451334
      *
      *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
      *   Y       week-based-year             year              1996; 96
@@ -1385,12 +1520,12 @@
      *   W       week-of-month               number            4
      *   E       day-of-week                 text              Tue; Tuesday; T
      *   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
-     *   F       week-of-month               number            3
+     *   F       day-of-week-in-month        number            3
      *
      *   a       am-pm-of-day                text              PM
      *   h       clock-hour-of-am-pm (1-12)  number            12
      *   K       hour-of-am-pm (0-11)        number            0
-     *   k       clock-hour-of-am-pm (1-24)  number            0
+     *   k       clock-hour-of-day (1-24)    number            24
      *
      *   H       hour-of-day (0-23)          number            0
      *   m       minute-of-hour              number            30
@@ -1401,11 +1536,12 @@
      *   N       nano-of-day                 number            1234000000
      *
      *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
+     *   v       generic time-zone name      zone-name         PT, Pacific Time
      *   z       time-zone name              zone-name         Pacific Standard Time; PST
      *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
-     *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
-     *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
-     *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
+     *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15
+     *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15
+     *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00
      *
      *   p       pad next                    pad modifier      1
      *
@@ -1432,37 +1568,37 @@
      *    GGGG    4      appendText(ChronoField.ERA, TextStyle.FULL)
      *    GGGGG   5      appendText(ChronoField.ERA, TextStyle.NARROW)
      *
-     *    u       1      appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL);
-     *    uu      2      appendValueReduced(ChronoField.YEAR, 2, 2000);
-     *    uuu     3      appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL);
-     *    u..u    4..n   appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD);
-     *    y       1      appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL);
-     *    yy      2      appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000);
-     *    yyy     3      appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL);
-     *    y..y    4..n   appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD);
+     *    u       1      appendValue(ChronoField.YEAR, 1, 19, SignStyle.NORMAL)
+     *    uu      2      appendValueReduced(ChronoField.YEAR, 2, 2000)
+     *    uuu     3      appendValue(ChronoField.YEAR, 3, 19, SignStyle.NORMAL)
+     *    u..u    4..n   appendValue(ChronoField.YEAR, n, 19, SignStyle.EXCEEDS_PAD)
+     *    y       1      appendValue(ChronoField.YEAR_OF_ERA, 1, 19, SignStyle.NORMAL)
+     *    yy      2      appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2000)
+     *    yyy     3      appendValue(ChronoField.YEAR_OF_ERA, 3, 19, SignStyle.NORMAL)
+     *    y..y    4..n   appendValue(ChronoField.YEAR_OF_ERA, n, 19, SignStyle.EXCEEDS_PAD)
      *    Y       1      append special localized WeekFields element for numeric week-based-year
-     *    YY      2      append special localized WeekFields element for reduced numeric week-based-year 2 digits;
-     *    YYY     3      append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL);
-     *    Y..Y    4..n   append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD);
+     *    YY      2      append special localized WeekFields element for reduced numeric week-based-year 2 digits
+     *    YYY     3      append special localized WeekFields element for numeric week-based-year (3, 19, SignStyle.NORMAL)
+     *    Y..Y    4..n   append special localized WeekFields element for numeric week-based-year (n, 19, SignStyle.EXCEEDS_PAD)
      *
-     *    Q       1      appendValue(IsoFields.QUARTER_OF_YEAR);
-     *    QQ      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2);
+     *    Q       1      appendValue(IsoFields.QUARTER_OF_YEAR)
+     *    QQ      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2)
      *    QQQ     3      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT)
      *    QQQQ    4      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL)
      *    QQQQQ   5      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW)
-     *    q       1      appendValue(IsoFields.QUARTER_OF_YEAR);
-     *    qq      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2);
+     *    q       1      appendValue(IsoFields.QUARTER_OF_YEAR)
+     *    qq      2      appendValue(IsoFields.QUARTER_OF_YEAR, 2)
      *    qqq     3      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.SHORT_STANDALONE)
      *    qqqq    4      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.FULL_STANDALONE)
      *    qqqqq   5      appendText(IsoFields.QUARTER_OF_YEAR, TextStyle.NARROW_STANDALONE)
      *
-     *    M       1      appendValue(ChronoField.MONTH_OF_YEAR);
-     *    MM      2      appendValue(ChronoField.MONTH_OF_YEAR, 2);
+     *    M       1      appendValue(ChronoField.MONTH_OF_YEAR)
+     *    MM      2      appendValue(ChronoField.MONTH_OF_YEAR, 2)
      *    MMM     3      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT)
      *    MMMM    4      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL)
      *    MMMMM   5      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW)
-     *    L       1      appendValue(ChronoField.MONTH_OF_YEAR);
-     *    LL      2      appendValue(ChronoField.MONTH_OF_YEAR, 2);
+     *    L       1      appendValue(ChronoField.MONTH_OF_YEAR)
+     *    LL      2      appendValue(ChronoField.MONTH_OF_YEAR, 2)
      *    LLL     3      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE)
      *    LLLL    4      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.FULL_STANDALONE)
      *    LLLLL   5      appendText(ChronoField.MONTH_OF_YEAR, TextStyle.NARROW_STANDALONE)
@@ -1473,9 +1609,10 @@
      *    d       1      appendValue(ChronoField.DAY_OF_MONTH)
      *    dd      2      appendValue(ChronoField.DAY_OF_MONTH, 2)
      *    D       1      appendValue(ChronoField.DAY_OF_YEAR)
-     *    DD      2      appendValue(ChronoField.DAY_OF_YEAR, 2)
+     *    DD      2      appendValue(ChronoField.DAY_OF_YEAR, 2, 3, SignStyle.NOT_NEGATIVE)
      *    DDD     3      appendValue(ChronoField.DAY_OF_YEAR, 3)
      *    F       1      appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH)
+     *    g..g    1..n   appendValue(JulianFields.MODIFIED_JULIAN_DAY, n, 19, SignStyle.NORMAL)
      *    E       1      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
      *    EE      2      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
      *    EEE     3      appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
@@ -1511,12 +1648,9 @@
      *    ss      2      appendValue(ChronoField.SECOND_OF_MINUTE, 2)
      *
      *    S..S    1..n   appendFraction(ChronoField.NANO_OF_SECOND, n, n, false)
-     *    A       1      appendValue(ChronoField.MILLI_OF_DAY)
-     *    A..A    2..n   appendValue(ChronoField.MILLI_OF_DAY, n)
-     *    n       1      appendValue(ChronoField.NANO_OF_SECOND)
-     *    n..n    2..n   appendValue(ChronoField.NANO_OF_SECOND, n)
-     *    N       1      appendValue(ChronoField.NANO_OF_DAY)
-     *    N..N    2..n   appendValue(ChronoField.NANO_OF_DAY, n)
+     *    A..A    1..n   appendValue(ChronoField.MILLI_OF_DAY, n, 19, SignStyle.NOT_NEGATIVE)
+     *    n..n    1..n   appendValue(ChronoField.NANO_OF_SECOND, n, 19, SignStyle.NOT_NEGATIVE)
+     *    N..N    1..n   appendValue(ChronoField.NANO_OF_DAY, n, 19, SignStyle.NOT_NEGATIVE)
      * </pre>
      * <p>
      * <b>Zone ID</b>: Pattern letters to output {@code ZoneId}.
@@ -1524,6 +1658,8 @@
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
      *    VV      2      appendZoneId()
+     *    v       1      appendGenericZoneText(TextStyle.SHORT)
+     *    vvvv    4      appendGenericZoneText(TextStyle.FULL)
      *    z       1      appendZoneText(TextStyle.SHORT)
      *    zz      2      appendZoneText(TextStyle.SHORT)
      *    zzz     3      appendZoneText(TextStyle.SHORT)
@@ -1534,8 +1670,8 @@
      * <pre>
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
-     *    O       1      appendLocalizedOffsetPrefixed(TextStyle.SHORT);
-     *    OOOO    4      appendLocalizedOffsetPrefixed(TextStyle.FULL);
+     *    O       1      appendLocalizedOffset(TextStyle.SHORT)
+     *    OOOO    4      appendLocalizedOffset(TextStyle.FULL)
      *    X       1      appendOffset("+HHmm","Z")
      *    XX      2      appendOffset("+HHMM","Z")
      *    XXX     3      appendOffset("+HH:MM","Z")
@@ -1549,7 +1685,7 @@
      *    Z       1      appendOffset("+HHMM","+0000")
      *    ZZ      2      appendOffset("+HHMM","+0000")
      *    ZZZ     3      appendOffset("+HHMM","+0000")
-     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL);
+     *    ZZZZ    4      appendLocalizedOffset(TextStyle.FULL)
      *    ZZZZZ   5      appendOffset("+HH:MM:ss","Z")
      * </pre>
      * <p>
@@ -1630,6 +1766,14 @@
                         throw new IllegalArgumentException("Pattern letter count must be 2: " + cur);
                     }
                     appendZoneId();
+                } else if (cur == 'v') {
+                    if (count == 1) {
+                        appendGenericZoneText(TextStyle.SHORT);
+                    } else if (count == 4) {
+                        appendGenericZoneText(TextStyle.FULL);
+                    } else {
+                        throw new IllegalArgumentException("Wrong number of  pattern letters: " + cur);
+                    }
                 } else if (cur == 'Z') {
                     if (count < 4) {
                         appendOffset("+HHMM", "+0000");
@@ -1664,16 +1808,20 @@
                     if (count > 1) {
                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
                     }
-                    appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+                    appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));
                 } else if (cur == 'w') {
                     // Fields defined by Locale
                     if (count > 2) {
                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
                     }
-                    appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+                    appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 2));
                 } else if (cur == 'Y') {
                     // Fields defined by Locale
-                    appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+                    if (count == 2) {
+                        appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 2));
+                    } else {
+                        appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 19));
+                    }
                 } else {
                     throw new IllegalArgumentException("Unknown pattern letter: " + cur);
                 }
@@ -1695,7 +1843,7 @@
                     throw new IllegalArgumentException("Pattern ends with an incomplete string literal: " + pattern);
                 }
                 String str = pattern.substring(start + 1, pos);
-                if (str.length() == 0) {
+                if (str.isEmpty()) {
                     appendLiteral('\'');
                 } else {
                     appendLiteral(str.replace("''", "'"));
@@ -1733,7 +1881,10 @@
                 }
                 break;
             case 'c':
-                if (count == 2) {
+                if (count == 1) {
+                    appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));
+                    break;
+                } else if (count == 2) {
                     throw new IllegalArgumentException("Invalid pattern \"cc\"");
                 }
                 /*fallthrough*/
@@ -1748,8 +1899,8 @@
                 switch (count) {
                     case 1:
                     case 2:
-                        if (cur == 'c' || cur == 'e') {
-                            appendInternal(new WeekBasedFieldPrinterParser(cur, count));
+                        if (cur == 'e') {
+                            appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));
                         } else if (cur == 'E') {
                             appendText(field, TextStyle.SHORT);
                         } else {
@@ -1825,12 +1976,20 @@
             case 'D':
                 if (count == 1) {
                     appendValue(field);
-                } else if (count <= 3) {
-                    appendValue(field, count);
+                } else if (count == 2 || count == 3) {
+                    appendValue(field, count, 3, SignStyle.NOT_NEGATIVE);
                 } else {
                     throw new IllegalArgumentException("Too many pattern letters: " + cur);
                 }
                 break;
+            case 'g':
+                appendValue(field, count, 19, SignStyle.NORMAL);
+                break;
+            case 'A':
+            case 'n':
+            case 'N':
+                appendValue(field, count, 19, SignStyle.NOT_NEGATIVE);
+                break;
             default:
                 if (count == 1) {
                     appendValue(field);
@@ -1869,9 +2028,12 @@
         FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY);              // LDML
         FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND);            // 310 (proposed for LDML)
         FIELD_MAP.put('N', ChronoField.NANO_OF_DAY);               // 310 (proposed for LDML)
+        FIELD_MAP.put('g', JulianFields.MODIFIED_JULIAN_DAY);
         // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4
         // 310 - Z - matches SimpleDateFormat and LDML
         // 310 - V - time-zone id, matches LDML
+        // 310 - v - general timezone names, not matching exactly with LDML because LDML specify to fall back
+        //           to 'VVVV' if general-nonlocation unavailable but here it's not falling back because of lack of data
         // 310 - p - prefix for padding
         // 310 - X - matches LDML, almost matches SDF for 1, exact match 2&3, extended 4&5
         // 310 - x - matches LDML
@@ -1879,8 +2041,6 @@
         // LDML - U - cycle year name, not supported by 310 yet
         // LDML - l - deprecated
         // LDML - j - not relevant
-        // LDML - g - modified-julian-day
-        // LDML - v,V - extended time-zone names
     }
 
     //-----------------------------------------------------------------------
@@ -2905,7 +3065,8 @@
 
         @Override
         public String toString() {
-            return "ReducedValue(" + field + "," + minWidth + "," + maxWidth + "," + (baseDate != null ? baseDate : baseValue) + ")";
+            return "ReducedValue(" + field + "," + minWidth + "," + maxWidth +
+                    "," + Objects.requireNonNullElse(baseDate, baseValue) + ")";
         }
     }
 
@@ -2913,10 +3074,7 @@
     /**
      * Prints and parses a numeric date-time field with optional padding.
      */
-    static final class FractionPrinterParser implements DateTimePrinterParser {
-        private final TemporalField field;
-        private final int minWidth;
-        private final int maxWidth;
+    static final class FractionPrinterParser extends NumberPrinterParser {
         private final boolean decimalPoint;
 
         /**
@@ -2928,6 +3086,7 @@
          * @param decimalPoint  whether to output the localized decimal point symbol
          */
         FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint) {
+            this(field, minWidth, maxWidth, decimalPoint, 0);
             Objects.requireNonNull(field, "field");
             if (field.range().isFixed() == false) {
                 throw new IllegalArgumentException("Field must have a fixed set of values: " + field);
@@ -2942,12 +3101,61 @@
                 throw new IllegalArgumentException("Maximum width must exceed or equal the minimum width but " +
                         maxWidth + " < " + minWidth);
             }
-            this.field = field;
-            this.minWidth = minWidth;
-            this.maxWidth = maxWidth;
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param field  the field to output, not null
+         * @param minWidth  the minimum width to output, from 0 to 9
+         * @param maxWidth  the maximum width to output, from 0 to 9
+         * @param decimalPoint  whether to output the localized decimal point symbol
+         * @param subsequentWidth the subsequentWidth for this instance
+         */
+        FractionPrinterParser(TemporalField field, int minWidth, int maxWidth, boolean decimalPoint, int subsequentWidth) {
+            super(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
             this.decimalPoint = decimalPoint;
         }
 
+        /**
+         * Returns a new instance with fixed width flag set.
+         *
+         * @return a new updated printer-parser, not null
+         */
+        @Override
+        FractionPrinterParser withFixedWidth() {
+            if (subsequentWidth == -1) {
+                return this;
+            }
+            return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, -1);
+        }
+
+        /**
+         * Returns a new instance with an updated subsequent width.
+         *
+         * @param subsequentWidth  the width of subsequent non-negative numbers, 0 or greater
+         * @return a new updated printer-parser, not null
+         */
+        @Override
+        FractionPrinterParser withSubsequentWidth(int subsequentWidth) {
+            return new FractionPrinterParser(field, minWidth, maxWidth, decimalPoint, this.subsequentWidth + subsequentWidth);
+        }
+
+        /**
+         * For FractionPrinterPrinterParser, the width is fixed if context is sttrict,
+         * minWidth equal to maxWidth and decimalpoint is absent.
+         * @param context the context
+         * @return if the field is fixed width
+         * @see DateTimeFormatterBuilder#appendValueFraction(java.time.temporal.TemporalField, int, int, boolean)
+         */
+        @Override
+        boolean isFixedWidth(DateTimeParseContext context) {
+            if (context.isStrict() && minWidth == maxWidth && decimalPoint == false) {
+                return true;
+            }
+            return false;
+        }
+
         @Override
         public boolean format(DateTimePrintContext context, StringBuilder buf) {
             Long value = context.getValue(field);
@@ -2980,8 +3188,8 @@
 
         @Override
         public int parse(DateTimeParseContext context, CharSequence text, int position) {
-            int effectiveMin = (context.isStrict() ? minWidth : 0);
-            int effectiveMax = (context.isStrict() ? maxWidth : 9);
+            int effectiveMin = (context.isStrict() || isFixedWidth(context) ? minWidth : 0);
+            int effectiveMax = (context.isStrict() || isFixedWidth(context) ? maxWidth : 9);
             int length = text.length();
             if (position == length) {
                 // valid if whole field is optional, invalid if minimum width
@@ -3146,6 +3354,16 @@
                         return context.setParsedField(field, entry.getValue(), position, position + itText.length());
                     }
                 }
+                if (field == ERA && !context.isStrict()) {
+                    // parse the possible era name from era.toString()
+                    List<Era> eras = chrono.eras();
+                    for (Era era : eras) {
+                        String name = era.toString();
+                        if (context.subSequenceEquals(name, 0, parseText, position, name.length())) {
+                            return context.setParsedField(field, era.getValue(), position, position + name.length());
+                        }
+                    }
+                }
                 if (context.isStrict()) {
                     return ~position;
                 }
@@ -3317,13 +3535,15 @@
      */
     static final class OffsetIdPrinterParser implements DateTimePrinterParser {
         static final String[] PATTERNS = new String[] {
-            "+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS",
+                "+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
+                "+H",  "+Hmm",  "+H:mm",  "+HMM",  "+H:MM",  "+HMMss",  "+H:MM:ss",  "+HMMSS",  "+H:MM:SS",  "+Hmmss",  "+H:mm:ss",
         };  // order used in pattern builder
         static final OffsetIdPrinterParser INSTANCE_ID_Z = new OffsetIdPrinterParser("+HH:MM:ss", "Z");
         static final OffsetIdPrinterParser INSTANCE_ID_ZERO = new OffsetIdPrinterParser("+HH:MM:ss", "0");
 
         private final String noOffsetText;
         private final int type;
+        private final int style;
 
         /**
          * Constructor.
@@ -3335,6 +3555,7 @@
             Objects.requireNonNull(pattern, "pattern");
             Objects.requireNonNull(noOffsetText, "noOffsetText");
             this.type = checkPattern(pattern);
+            this.style = type % 11;
             this.noOffsetText = noOffsetText;
         }
 
@@ -3347,6 +3568,14 @@
             throw new IllegalArgumentException("Invalid zone offset pattern: " + pattern);
         }
 
+        private boolean isPaddedHour() {
+            return type < 11;
+        }
+
+        private boolean isColon() {
+            return style > 0 && (style % 2) == 0;
+        }
+
         @Override
         public boolean format(DateTimePrintContext context, StringBuilder buf) {
             Long offsetSecs = context.getValue(OFFSET_SECONDS);
@@ -3362,15 +3591,17 @@
                 int absSeconds = Math.abs(totalSecs % 60);
                 int bufPos = buf.length();
                 int output = absHours;
-                buf.append(totalSecs < 0 ? "-" : "+")
-                    .append((char) (absHours / 10 + '0')).append((char) (absHours % 10 + '0'));
-                if (type >= 3 || (type >= 1 && absMinutes > 0)) {
-                    buf.append((type % 2) == 0 ? ":" : "")
-                        .append((char) (absMinutes / 10 + '0')).append((char) (absMinutes % 10 + '0'));
+                buf.append(totalSecs < 0 ? "-" : "+");
+                if (isPaddedHour() || absHours >= 10) {
+                    formatZeroPad(false, absHours, buf);
+                } else {
+                    buf.append((char) (absHours + '0'));
+                }
+                if ((style >= 3 && style <= 8) || (style >= 9 && absSeconds > 0) || (style >= 1 && absMinutes > 0)) {
+                    formatZeroPad(isColon(), absMinutes, buf);
                     output += absMinutes;
-                    if (type >= 7 || (type >= 5 && absSeconds > 0)) {
-                        buf.append((type % 2) == 0 ? ":" : "")
-                            .append((char) (absSeconds / 10 + '0')).append((char) (absSeconds % 10 + '0'));
+                    if (style == 7 || style == 8 || (style >= 5 && absSeconds > 0)) {
+                        formatZeroPad(isColon(), absSeconds, buf);
                         output += absSeconds;
                     }
                 }
@@ -3382,6 +3613,12 @@
             return true;
         }
 
+        private void formatZeroPad(boolean colon, int value, StringBuilder buf) {
+            buf.append(colon ? ":" : "")
+                    .append((char) (value / 10 + '0'))
+                    .append((char) (value % 10 + '0'));
+        }
+
         @Override
         public int parse(DateTimeParseContext context, CharSequence text, int position) {
             int length = text.length();
@@ -3404,58 +3641,210 @@
             if (sign == '+' || sign == '-') {
                 // starts
                 int negative = (sign == '-' ? -1 : 1);
+                boolean isColon = isColon();
+                boolean paddedHour = isPaddedHour();
                 int[] array = new int[4];
                 array[0] = position + 1;
-                if ((parseNumber(array, 1, text, true) ||
-                        parseNumber(array, 2, text, type >=3) ||
-                        parseNumber(array, 3, text, false)) == false) {
-                    // success
+                int parseType = type;
+                // select parse type when lenient
+                if (!context.isStrict()) {
+                    if (paddedHour) {
+                        if (isColon || (parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
+                            isColon = true; // needed in cases like ("+HH", "+01:01")
+                            parseType = 10;
+                        } else {
+                            parseType = 9;
+                        }
+                    } else {
+                        if (isColon || (parseType == 11 && length > position + 3 && (text.charAt(position + 2) == ':' || text.charAt(position + 3) == ':'))) {
+                            isColon = true;
+                            parseType = 21;  // needed in cases like ("+H", "+1:01")
+                        } else {
+                            parseType = 20;
+                        }
+                    }
+                }
+                // parse according to the selected pattern
+                switch (parseType) {
+                    case 0: // +HH
+                    case 11: // +H
+                        parseHour(text, paddedHour, array);
+                        break;
+                    case 1: // +HHmm
+                    case 2: // +HH:mm
+                    case 13: // +H:mm
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, false, array);
+                        break;
+                    case 3: // +HHMM
+                    case 4: // +HH:MM
+                    case 15: // +H:MM
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, true, array);
+                        break;
+                    case 5: // +HHMMss
+                    case 6: // +HH:MM:ss
+                    case 17: // +H:MM:ss
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, true, array);
+                        parseSecond(text, isColon, false, array);
+                        break;
+                    case 7: // +HHMMSS
+                    case 8: // +HH:MM:SS
+                    case 19: // +H:MM:SS
+                        parseHour(text, paddedHour, array);
+                        parseMinute(text, isColon, true, array);
+                        parseSecond(text, isColon, true, array);
+                        break;
+                    case 9: // +HHmmss
+                    case 10: // +HH:mm:ss
+                    case 21: // +H:mm:ss
+                        parseHour(text, paddedHour, array);
+                        parseOptionalMinuteSecond(text, isColon, array);
+                        break;
+                    case 12: // +Hmm
+                        parseVariableWidthDigits(text, 1, 4, array);
+                        break;
+                    case 14: // +HMM
+                        parseVariableWidthDigits(text, 3, 4, array);
+                        break;
+                    case 16: // +HMMss
+                        parseVariableWidthDigits(text, 3, 6, array);
+                        break;
+                    case 18: // +HMMSS
+                        parseVariableWidthDigits(text, 5, 6, array);
+                        break;
+                    case 20: // +Hmmss
+                        parseVariableWidthDigits(text, 1, 6, array);
+                        break;
+                }
+                if (array[0] > 0) {
+                    if (array[1] > 23 || array[2] > 59 || array[3] > 59) {
+                        throw new DateTimeException("Value out of range: Hour[0-23], Minute[0-59], Second[0-59]");
+                    }
                     long offsetSecs = negative * (array[1] * 3600L + array[2] * 60L + array[3]);
                     return context.setParsedField(OFFSET_SECONDS, offsetSecs, position, array[0]);
                 }
             }
             // handle special case of empty no offset text
             if (noOffsetLen == 0) {
-                return context.setParsedField(OFFSET_SECONDS, 0, position, position + noOffsetLen);
+                return context.setParsedField(OFFSET_SECONDS, 0, position, position);
             }
             return ~position;
         }
 
-        /**
-         * Parse a two digit zero-prefixed number.
-         *
-         * @param array  the array of parsed data, 0=pos,1=hours,2=mins,3=secs, not null
-         * @param arrayIndex  the index to parse the value into
-         * @param parseText  the offset ID, not null
-         * @param required  whether this number is required
-         * @return true if an error occurred
-         */
-        private boolean parseNumber(int[] array, int arrayIndex, CharSequence parseText, boolean required) {
-            if ((type + 3) / 2 < arrayIndex) {
-                return false;  // ignore seconds/minutes
+        private void parseHour(CharSequence parseText, boolean paddedHour, int[] array) {
+            if (paddedHour) {
+                // parse two digits
+                if (!parseDigits(parseText, false, 1, array)) {
+                    array[0] = ~array[0];
+                }
+            } else {
+                // parse one or two digits
+                parseVariableWidthDigits(parseText, 1, 2, array);
             }
+        }
+
+        private void parseMinute(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
+            if (!parseDigits(parseText, isColon, 2, array)) {
+                if (mandatory) {
+                    array[0] = ~array[0];
+                }
+            }
+        }
+
+        private void parseSecond(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
+            if (!parseDigits(parseText, isColon, 3, array)) {
+                if (mandatory) {
+                    array[0] = ~array[0];
+                }
+            }
+        }
+
+        private void parseOptionalMinuteSecond(CharSequence parseText, boolean isColon, int[] array) {
+            if (parseDigits(parseText, isColon, 2, array)) {
+                parseDigits(parseText, isColon, 3, array);
+            }
+        }
+
+        private boolean parseDigits(CharSequence parseText, boolean isColon, int arrayIndex, int[] array) {
             int pos = array[0];
-            if ((type % 2) == 0 && arrayIndex > 1) {
+            if (pos < 0) {
+                return true;
+            }
+            if (isColon && arrayIndex != 1) { //  ':' will precede only in case of minute/second
                 if (pos + 1 > parseText.length() || parseText.charAt(pos) != ':') {
-                    return required;
+                    return false;
                 }
                 pos++;
             }
             if (pos + 2 > parseText.length()) {
-                return required;
+                return false;
             }
             char ch1 = parseText.charAt(pos++);
             char ch2 = parseText.charAt(pos++);
             if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
-                return required;
+                return false;
             }
             int value = (ch1 - 48) * 10 + (ch2 - 48);
             if (value < 0 || value > 59) {
-                return required;
+                return false;
             }
             array[arrayIndex] = value;
             array[0] = pos;
-            return false;
+            return true;
+        }
+
+        private void parseVariableWidthDigits(CharSequence parseText, int minDigits, int maxDigits, int[] array) {
+            // scan the text to find the available number of digits up to maxDigits
+            // so long as the number available is minDigits or more, the input is valid
+            // then parse the number of available digits
+            int pos = array[0];
+            int available = 0;
+            char[] chars = new char[maxDigits];
+            for (int i = 0; i < maxDigits; i++) {
+                if (pos + 1  > parseText.length()) {
+                    break;
+                }
+                char ch = parseText.charAt(pos++);
+                if (ch < '0' || ch > '9') {
+                    pos--;
+                    break;
+                }
+                chars[i] = ch;
+                available++;
+            }
+            if (available < minDigits) {
+                array[0] = ~array[0];
+                return;
+            }
+            switch (available) {
+                case 1:
+                    array[1] = (chars[0] - 48);
+                    break;
+                case 2:
+                    array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
+                    break;
+                case 3:
+                    array[1] = (chars[0] - 48);
+                    array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
+                    break;
+                case 4:
+                    array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
+                    array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
+                    break;
+                case 5:
+                    array[1] = (chars[0] - 48);
+                    array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
+                    array[3] = ((chars[3] - 48) * 10 + (chars[4] - 48));
+                    break;
+                case 6:
+                    array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
+                    array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
+                    array[3] = ((chars[4] - 48) * 10 + (chars[5] - 48));
+                    break;
+            }
+            array[0] = pos;
         }
 
         @Override
@@ -3493,9 +3882,7 @@
                 return false;
             }
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                buf.append(gmtText);
-            }
+            buf.append(gmtText);
             int totalSecs = Math.toIntExact(offsetSecs);
             if (totalSecs != 0) {
                 int absHours = Math.abs((totalSecs / 3600) % 100);  // anything larger than 99 silently dropped
@@ -3539,14 +3926,12 @@
         @Override
         public int parse(DateTimeParseContext context, CharSequence text, int position) {
             int pos = position;
-            int end = pos + text.length();
+            int end = text.length();
             String gmtText = "GMT";  // TODO: get localized version of 'GMT'
-            if (gmtText != null) {
-                if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
+            if (!context.subSequenceEquals(text, pos, gmtText, 0, gmtText.length())) {
                     return ~position;
                 }
-                pos += gmtText.length();
-            }
+            pos += gmtText.length();
             // parse normal plus/minus offset
             int negative = 0;
             if (pos == end) {
@@ -3638,9 +4023,12 @@
         /** The preferred zoneid map */
         private Set<String> preferredZones;
 
-        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones) {
+        /**  Display in generic time-zone format. True in case of pattern letter 'v' */
+        private final boolean isGeneric;
+        ZoneTextPrinterParser(TextStyle textStyle, Set<ZoneId> preferredZones, boolean isGeneric) {
             super(TemporalQueries.zone(), "ZoneText(" + textStyle + ")");
             this.textStyle = Objects.requireNonNull(textStyle, "textStyle");
+            this.isGeneric = isGeneric;
             if (preferredZones != null && preferredZones.size() != 0) {
                 this.preferredZones = new HashSet<>();
                 for (ZoneId id : preferredZones) {
@@ -3758,11 +4146,21 @@
             String zname = zone.getId();
             if (!(zone instanceof ZoneOffset)) {
                 TemporalAccessor dt = context.getTemporal();
-                String name = getDisplayName(zname,
-                                             dt.isSupported(ChronoField.INSTANT_SECONDS)
-                                             ? (zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD)
-                                             : GENERIC,
-                                             context.getLocale());
+                int type = GENERIC;
+                if (!isGeneric) {
+                    if (dt.isSupported(ChronoField.INSTANT_SECONDS)) {
+                        type = zone.getRules().isDaylightSavings(Instant.from(dt)) ? DST : STD;
+                    } else if (dt.isSupported(ChronoField.EPOCH_DAY) &&
+                               dt.isSupported(ChronoField.NANO_OF_DAY)) {
+                        LocalDate date = LocalDate.ofEpochDay(dt.getLong(ChronoField.EPOCH_DAY));
+                        LocalTime time = LocalTime.ofNanoOfDay(dt.getLong(ChronoField.NANO_OF_DAY));
+                        LocalDateTime ldt = date.atTime(time);
+                        if (zone.getRules().getTransition(ldt) == null) {
+                            type = zone.getRules().isDaylightSavings(ldt.atZone(zone).toInstant()) ? DST : STD;
+                        }
+                    }
+                }
+                String name = getDisplayName(zname, type, context.getLocale());
                 if (name != null) {
                     zname = name;
                 }
@@ -3941,11 +4339,21 @@
                 char nextNextChar = text.charAt(position + 1);
                 if (context.charEquals(nextChar, 'U') && context.charEquals(nextNextChar, 'T')) {
                     if (length >= position + 3 && context.charEquals(text.charAt(position + 2), 'C')) {
-                        return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
+                        // There are localized zone texts that start with "UTC", e.g.
+                        // "UTC\u221210:00" (MINUS SIGN instead of HYPHEN-MINUS) in French.
+                        // Exclude those ZoneText cases.
+                        if (!(this instanceof ZoneTextPrinterParser)) {
+                            return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
+                        }
+                    } else {
+                        return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
                     }
-                    return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
                 } else if (context.charEquals(nextChar, 'G') && length >= position + 3 &&
                         context.charEquals(nextNextChar, 'M') && context.charEquals(text.charAt(position + 2), 'T')) {
+                    if (length >= position + 4 && context.charEquals(text.charAt(position + 3), '0')) {
+                        context.setParsed(ZoneId.of("GMT0"));
+                        return position + 4;
+                    }
                     return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
                 }
             }
@@ -3978,7 +4386,7 @@
          * @return the position after the parse
          */
         private int parseOffsetBased(DateTimeParseContext context, CharSequence text, int prefixPos, int position, OffsetIdPrinterParser parser) {
-            String prefix = text.toString().substring(prefixPos, position).toUpperCase();
+            String prefix = text.subSequence(prefixPos, position).toString().toUpperCase();
             if (position >= text.length()) {
                 context.setParsed(ZoneId.of(prefix));
                 return position;
@@ -4038,7 +4446,7 @@
             this.key = k;
             this.value = v;
             this.child = child;
-            if (k.length() == 0){
+            if (k.isEmpty()) {
                 c0 = 0xffff;
             } else {
                 c0 = key.charAt(0);
@@ -4432,7 +4840,7 @@
             // String name = DateTimeTextProvider.getLocalizedResource(key, locale);
             LocaleDisplayNames displayNames = LocaleDisplayNames.getInstance(ULocale.forLocale(locale));
             String name = displayNames.keyValueDisplayName("calendar", chrono.getCalendarType());
-            return name != null ? name : chrono.getId();
+            return Objects.requireNonNullElseGet(name, () -> chrono.getId());
         }
     }
 
@@ -4506,12 +4914,13 @@
     //-----------------------------------------------------------------------
     /**
      * Prints or parses a localized pattern from a localized field.
-     * The specific formatter and parameters is not selected until the
+     * The specific formatter and parameters is not selected until
      * the field is to be printed or parsed.
      * The locale is needed to select the proper WeekFields from which
      * the field for day-of-week, week-of-month, or week-of-year is selected.
+     * Hence the inherited field NumberPrinterParser.field is unused.
      */
-    static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {
+    static final class WeekBasedFieldPrinterParser extends NumberPrinterParser {
         private char chr;
         private int count;
 
@@ -4520,12 +4929,55 @@
          *
          * @param chr the pattern format letter that added this PrinterParser.
          * @param count the repeat count of the format letter
+         * @param minWidth  the minimum field width, from 1 to 19
+         * @param maxWidth  the maximum field width, from minWidth to 19
          */
-        WeekBasedFieldPrinterParser(char chr, int count) {
+        WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth) {
+            this(chr, count, minWidth, maxWidth, 0);
+        }
+
+        /**
+         * Constructor.
+         *
+         * @param chr the pattern format letter that added this PrinterParser.
+         * @param count the repeat count of the format letter
+         * @param minWidth  the minimum field width, from 1 to 19
+         * @param maxWidth  the maximum field width, from minWidth to 19
+         * @param subsequentWidth  the width of subsequent non-negative numbers, 0 or greater,
+         * -1 if fixed width due to active adjacent parsing
+         */
+        WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth,
+                int subsequentWidth) {
+            super(null, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
             this.chr = chr;
             this.count = count;
         }
 
+        /**
+         * Returns a new instance with fixed width flag set.
+         *
+         * @return a new updated printer-parser, not null
+         */
+        @Override
+        WeekBasedFieldPrinterParser withFixedWidth() {
+            if (subsequentWidth == -1) {
+                return this;
+            }
+            return new WeekBasedFieldPrinterParser(chr, count, minWidth, maxWidth, -1);
+        }
+
+        /**
+         * Returns a new instance with an updated subsequent width.
+         *
+         * @param subsequentWidth  the width of subsequent non-negative numbers, 0 or greater
+         * @return a new updated printer-parser, not null
+         */
+        @Override
+        WeekBasedFieldPrinterParser withSubsequentWidth(int subsequentWidth) {
+            return new WeekBasedFieldPrinterParser(chr, count, minWidth, maxWidth,
+                    this.subsequentWidth + subsequentWidth);
+        }
+
         @Override
         public boolean format(DateTimePrintContext context, StringBuilder buf) {
             return printerParser(context.getLocale()).format(context, buf);
@@ -4550,10 +5002,12 @@
                 case 'Y':
                     field = weekDef.weekBasedYear();
                     if (count == 2) {
-                        return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE, 0);
+                        return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE,
+                                this.subsequentWidth);
                     } else {
                         return new NumberPrinterParser(field, count, 19,
-                                (count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD, -1);
+                                (count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD,
+                                this.subsequentWidth);
                     }
                 case 'e':
                 case 'c':
@@ -4568,7 +5022,8 @@
                 default:
                     throw new IllegalStateException("unreachable");
             }
-            return new NumberPrinterParser(field, (count == 2 ? 2 : 1), 2, SignStyle.NOT_NEGATIVE);
+            return new NumberPrinterParser(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE,
+                    this.subsequentWidth);
         }
 
         @Override
diff --git a/ojluni/src/main/java/java/time/format/DateTimeParseContext.java b/ojluni/src/main/java/java/time/format/DateTimeParseContext.java
index e3ca5e9..6b8dd98 100644
--- a/ojluni/src/main/java/java/time/format/DateTimeParseContext.java
+++ b/ojluni/src/main/java/java/time/format/DateTimeParseContext.java
@@ -399,7 +399,7 @@
      */
     void addChronoChangedListener(Consumer<Chronology> listener) {
         if (chronoListeners == null) {
-            chronoListeners = new ArrayList<Consumer<Chronology>>();
+            chronoListeners = new ArrayList<>();
         }
         chronoListeners.add(listener);
     }
diff --git a/ojluni/src/main/java/java/time/format/DateTimePrintContext.java b/ojluni/src/main/java/java/time/format/DateTimePrintContext.java
index 543a317..0faec56 100644
--- a/ojluni/src/main/java/java/time/format/DateTimePrintContext.java
+++ b/ojluni/src/main/java/java/time/format/DateTimePrintContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -146,7 +146,7 @@
         if (overrideZone != null) {
             // if have zone and instant, calculation is simple, defaulting chrono if necessary
             if (temporal.isSupported(INSTANT_SECONDS)) {
-                Chronology chrono = (effectiveChrono != null ? effectiveChrono : IsoChronology.INSTANCE);
+                Chronology chrono = Objects.requireNonNullElse(effectiveChrono, IsoChronology.INSTANCE);
                 return chrono.zonedDateTime(Instant.from(temporal), overrideZone);
             }
             // block changing zone on OffsetTime, and similar problem cases
@@ -218,6 +218,13 @@
                 }
                 return query.queryFrom(this);
             }
+
+            @Override
+            public String toString() {
+                return temporal +
+                        (effectiveChrono != null ? " with chronology " + effectiveChrono : "") +
+                        (effectiveZone != null ? " with zone " + effectiveZone : "");
+            }
         };
     }
 
@@ -279,7 +286,8 @@
     <R> R getValue(TemporalQuery<R> query) {
         R result = temporal.query(query);
         if (result == null && optional == 0) {
-            throw new DateTimeException("Unable to extract value: " + temporal.getClass());
+            throw new DateTimeException("Unable to extract " +
+                    query + " from temporal " + temporal);
         }
         return result;
     }
@@ -294,14 +302,10 @@
      * @throws DateTimeException if the field is not available and the section is not optional
      */
     Long getValue(TemporalField field) {
-        try {
-            return temporal.getLong(field);
-        } catch (DateTimeException ex) {
-            if (optional > 0) {
-                return null;
-            }
-            throw ex;
+        if (optional > 0 && !temporal.isSupported(field)) {
+            return null;
         }
+        return temporal.getLong(field);
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/main/java/java/time/format/DateTimeTextProvider.java b/ojluni/src/main/java/java/time/format/DateTimeTextProvider.java
index 490d91f..d11da68 100644
--- a/ojluni/src/main/java/java/time/format/DateTimeTextProvider.java
+++ b/ojluni/src/main/java/java/time/format/DateTimeTextProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -114,6 +114,9 @@
         }
     };
 
+    // Singleton instance
+    private static final DateTimeTextProvider INSTANCE = new DateTimeTextProvider();
+
     DateTimeTextProvider() {}
 
     /**
@@ -122,7 +125,7 @@
      * @return the provider, not null
      */
     static DateTimeTextProvider getInstance() {
-        return new DateTimeTextProvider();
+        return INSTANCE;
     }
 
     /**
@@ -351,25 +354,40 @@
 
         if (field == MONTH_OF_YEAR) {
             for (TextStyle textStyle : TextStyle.values()) {
-                Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
-                        "gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale);
                 Map<Long, String> map = new HashMap<>();
-                if (displayNames != null) {
-                    for (Entry<String, Integer> entry : displayNames.entrySet()) {
-                        map.put((long) (entry.getValue() + 1), entry.getKey());
-                    }
-
-                } else {
-                    // Narrow names may have duplicated names, such as "J" for January, Jun, July.
-                    // Get names one by one in that case.
+                // Narrow names may have duplicated names, such as "J" for January, June, July.
+                // Get names one by one in that case.
+                if ((textStyle.equals(TextStyle.NARROW) ||
+                        textStyle.equals(TextStyle.NARROW_STANDALONE))) {
                     for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) {
                         String name;
                         name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
-                                "gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale);
+                                "gregory", Calendar.MONTH,
+                                month, textStyle.toCalendarStyle(), locale);
                         if (name == null) {
                             break;
                         }
-                        map.put((long) (month + 1), name);
+                        map.put((month + 1L), name);
+                    }
+                } else {
+                    Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
+                            "gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale);
+                    if (displayNames != null) {
+                        for (Entry<String, Integer> entry : displayNames.entrySet()) {
+                            map.put((long)(entry.getValue() + 1), entry.getKey());
+                        }
+                    } else {
+                        // Although probability is very less, but if other styles have duplicate names.
+                        // Get names one by one in that case.
+                        for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) {
+                            String name;
+                            name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
+                                    "gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale);
+                            if (name == null) {
+                                break;
+                            }
+                            map.put((month + 1L), name);
+                        }
                     }
                 }
                 if (!map.isEmpty()) {
@@ -381,26 +399,41 @@
 
         if (field == DAY_OF_WEEK) {
             for (TextStyle textStyle : TextStyle.values()) {
-                Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
-                        "gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale);
                 Map<Long, String> map = new HashMap<>();
-                if (displayNames != null) {
-                    for (Entry<String, Integer> entry : displayNames.entrySet()) {
-                        map.put((long)toWeekDay(entry.getValue()), entry.getKey());
-                    }
-
-                } else {
-                    // Narrow names may have duplicated names, such as "S" for Sunday and Saturday.
-                    // Get names one by one in that case.
+                // Narrow names may have duplicated names, such as "S" for Sunday and Saturday.
+                // Get names one by one in that case.
+                if ((textStyle.equals(TextStyle.NARROW) ||
+                        textStyle.equals(TextStyle.NARROW_STANDALONE))) {
                     for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) {
                         String name;
                         name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
-                            "gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale);
+                                "gregory", Calendar.DAY_OF_WEEK,
+                                wday, textStyle.toCalendarStyle(), locale);
                         if (name == null) {
                             break;
                         }
                         map.put((long)toWeekDay(wday), name);
                     }
+                } else {
+                    Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
+                            "gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale);
+                    if (displayNames != null) {
+                        for (Entry<String, Integer> entry : displayNames.entrySet()) {
+                            map.put((long)toWeekDay(entry.getValue()), entry.getKey());
+                        }
+                    } else {
+                        // Although probability is very less, but if other styles have duplicate names.
+                        // Get names one by one in that case.
+                        for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) {
+                            String name;
+                            name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
+                                    "gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale);
+                            if (name == null) {
+                                break;
+                            }
+                            map.put((long)toWeekDay(wday), name);
+                        }
+                    }
                 }
                 if (!map.isEmpty()) {
                     styleMap.put(textStyle, map);
@@ -513,7 +546,8 @@
     // @SuppressWarnings("unchecked")
     // static <T> T getLocalizedResource(String key, Locale locale) {
     //     LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
-    //                                 .getLocaleResources(locale);
+    //                                 .getLocaleResources(
+    //                                     CalendarDataUtility.findRegionOverride(locale));
     //     ResourceBundle rb = lr.getJavaTimeFormatData();
     //     return rb.containsKey(key) ? (T) rb.getObject(key) : null;
     // }
diff --git a/ojluni/src/main/java/java/time/format/DecimalStyle.java b/ojluni/src/main/java/java/time/format/DecimalStyle.java
index 484f2f2..632eac5 100644
--- a/ojluni/src/main/java/java/time/format/DecimalStyle.java
+++ b/ojluni/src/main/java/java/time/format/DecimalStyle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -143,10 +143,15 @@
         return of(Locale.getDefault(Locale.Category.FORMAT));
     }
 
+    // Android-changed: Remove "rg" extension support in the javadoc. See http://b/228322300.
     /**
      * Obtains the DecimalStyle for the specified locale.
      * <p>
      * This method provides access to locale sensitive decimal style symbols.
+     * If the locale contains "nu" (Numbering System)
+     * <a href="../../util/Locale.html#def_locale_extension">
+     * Unicode extensions</a>, returned instance will reflect the values specified with
+     * those extensions.
      *
      * @param locale  the locale, not null
      * @return the decimal style, not null
@@ -211,7 +216,6 @@
      *
      * @param zeroDigit  the character for zero
      * @return  a copy with a new character that represents zero, not null
-
      */
     public DecimalStyle withZeroDigit(char zeroDigit) {
         if (zeroDigit == this.zeroDigit) {
diff --git a/ojluni/src/main/java/java/time/format/Parsed.java b/ojluni/src/main/java/java/time/format/Parsed.java
index 1eb8845..a2a75fa 100644
--- a/ojluni/src/main/java/java/time/format/Parsed.java
+++ b/ojluni/src/main/java/java/time/format/Parsed.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -216,7 +216,16 @@
             return (R) (date != null ? LocalDate.from(date) : null);
         } else if (query == TemporalQueries.localTime()) {
             return (R) time;
-        } else if (query == TemporalQueries.zone() || query == TemporalQueries.offset()) {
+        } else if (query == TemporalQueries.offset()) {
+            Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
+            if (offsetSecs != null) {
+                return (R) ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
+            }
+            if (zone instanceof ZoneOffset) {
+                return (R)zone;
+            }
+            return query.queryFrom(this);
+        } else if (query == TemporalQueries.zone()) {
             return query.queryFrom(this);
         } else if (query == TemporalQueries.precision()) {
             return null;  // not a complete date/time
@@ -585,15 +594,16 @@
 
     private void resolveInstant() {
         // add instant seconds if we have date, time and zone
+        // Offset (if present) will be given priority over the zone.
         if (date != null && time != null) {
-            if (zone != null) {
-                long instant = date.atTime(time).atZone(zone).getLong(ChronoField.INSTANT_SECONDS);
+            Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
+            if (offsetSecs != null) {
+                ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
+                long instant = date.atTime(time).atZone(offset).toEpochSecond();
                 fieldValues.put(INSTANT_SECONDS, instant);
             } else {
-                Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
-                if (offsetSecs != null) {
-                    ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
-                    long instant = date.atTime(time).atZone(offset).getLong(ChronoField.INSTANT_SECONDS);
+                if (zone != null) {
+                    long instant = date.atTime(time).atZone(zone).toEpochSecond();
                     fieldValues.put(INSTANT_SECONDS, instant);
                 }
             }
diff --git a/ojluni/src/main/java/java/time/format/TextStyle.java b/ojluni/src/main/java/java/time/format/TextStyle.java
index ed65d27..27a6f91 100644
--- a/ojluni/src/main/java/java/time/format/TextStyle.java
+++ b/ojluni/src/main/java/java/time/format/TextStyle.java
@@ -82,6 +82,8 @@
  *
  * @implSpec
  * This is immutable and thread-safe enum.
+ *
+ * @since 1.8
  */
 public enum TextStyle {
     // ordered from large to small
diff --git a/ojluni/src/main/java/java/time/format/ZoneName.java b/ojluni/src/main/java/java/time/format/ZoneName.java
index daecb6e..df0b8af 100644
--- a/ojluni/src/main/java/java/time/format/ZoneName.java
+++ b/ojluni/src/main/java/java/time/format/ZoneName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,8 @@
  * appropriate zone id for the particular locale.
  * <p>
  * The zid<->metazone mappings are based on CLDR metaZones.xml.
- * The alias mappings are based on Link entries in tzdb data files.
+ * The alias mappings are based on Link entries in tzdb data files and
+ * CLDR's supplementalMetadata.xml.
  */
 class ZoneName {
 
diff --git a/ojluni/src/main/java/java/time/format/package-info.java b/ojluni/src/main/java/java/time/format/package-info.java
index 140bb6d..d4f1ce7 100644
--- a/ojluni/src/main/java/java/time/format/package-info.java
+++ b/ojluni/src/main/java/java/time/format/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@
  * {@link java.time.format.DecimalStyle DecimalStyle}.
  * </p>
  *
- * <h3>Package specification</h3>
+ * <h2>Package specification</h2>
  * <p>
  * Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
  * in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
@@ -90,6 +90,6 @@
  * All calculations should check for numeric overflow and throw either an {@link java.lang.ArithmeticException}
  * or a {@link java.time.DateTimeException}.
  * </p>
- * @since JDK1.8
+ * @since 1.8
  */
 package java.time.format;
diff --git a/ojluni/src/main/java/java/time/package-info.java b/ojluni/src/main/java/java/time/package-info.java
index ea160ff..be783ba 100644
--- a/ojluni/src/main/java/java/time/package-info.java
+++ b/ojluni/src/main/java/java/time/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,7 +90,7 @@
  * The calendar neutral API should be reserved for interactions with users.
  * </p>
  *
- * <h3>Dates and Times</h3>
+ * <h2>Dates and Times</h2>
  * <p>
  * {@link java.time.Instant} is essentially a numeric timestamp.
  * The current Instant can be retrieved from a {@link java.time.Clock}.
@@ -118,7 +118,7 @@
  * The widespread use of time-zones tends to add considerable complexity to an application.
  * </p>
  *
- * <h3>Duration and Period</h3>
+ * <h2>Duration and Period</h2>
  * <p>
  * Beyond dates and times, the API also allows the storage of periods and durations of time.
  * A {@link java.time.Duration} is a simple measure of time along the time-line in nanoseconds.
@@ -126,7 +126,7 @@
  * to humans, such as years or days.
  * </p>
  *
- * <h3>Additional value types</h3>
+ * <h2>Additional value types</h2>
  * <p>
  * {@link java.time.Month} stores a month on its own.
  * This stores a single month-of-year in isolation, such as 'DECEMBER'.
@@ -160,7 +160,7 @@
  * but contains less information than a full time-zone.
  * </p>
  *
- * <h3>Package specification</h3>
+ * <h2>Package specification</h2>
  * <p>
  * Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
  * in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
@@ -172,7 +172,7 @@
  * or a {@link java.time.DateTimeException}.
  * </p>
  *
- * <h3>Design notes (non normative)</h3>
+ * <h2>Design notes (non normative)</h2>
  * <p>
  * The API has been designed to reject null early and to be clear about this behavior.
  * A key exception is any method that takes an object and returns a boolean, for the purpose
@@ -283,6 +283,6 @@
  *
  * </pre>
  *
- * @since JDK1.8
+ * @since 1.8
  */
 package java.time;
diff --git a/ojluni/src/main/java/java/time/temporal/ChronoField.java b/ojluni/src/main/java/java/time/temporal/ChronoField.java
index e1e8250..3438c41 100644
--- a/ojluni/src/main/java/java/time/temporal/ChronoField.java
+++ b/ojluni/src/main/java/java/time/temporal/ChronoField.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,17 @@
 import static java.time.temporal.ChronoUnit.WEEKS;
 import static java.time.temporal.ChronoUnit.YEARS;
 
+import java.time.DayOfWeek;
+import java.time.Instant;
+import java.time.Year;
+import java.time.ZoneOffset;
+import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.Chronology;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.ResourceBundle;
+import sun.util.locale.provider.CalendarDataUtility;
+
 /**
  * A standard set of fields.
  * <p>
@@ -269,6 +280,8 @@
      * In lenient mode the value is not validated. It is combined with
      * {@code AMPM_OF_DAY} to form {@code HOUR_OF_DAY} by multiplying
      * the {AMPM_OF_DAY} value by 12.
+     * <p>
+     * See {@link #CLOCK_HOUR_OF_AMPM} for the related field that counts hours from 1 to 12.
      */
     HOUR_OF_AMPM("HourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(0, 11)),
     /**
@@ -283,6 +296,8 @@
      * 0 to 12 in smart mode. In lenient mode the value is not validated.
      * The field is converted to an {@code HOUR_OF_AMPM} with the same value,
      * unless the value is 12, in which case it is converted to 0.
+     * <p>
+     * See {@link #HOUR_OF_AMPM} for the related field that counts hours from 0 to 11.
      */
     CLOCK_HOUR_OF_AMPM("ClockHourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(1, 12)),
     /**
@@ -298,12 +313,14 @@
      * {@code NANO_OF_SECOND} to produce a {@code LocalTime}.
      * In lenient mode, any excess days are added to the parsed date, or
      * made available via {@link java.time.format.DateTimeFormatter#parsedExcessDays()}.
+     * <p>
+     * See {@link #CLOCK_HOUR_OF_DAY} for the related field that counts hours from 1 to 24.
      */
     HOUR_OF_DAY("HourOfDay", HOURS, DAYS, ValueRange.of(0, 23), "hour"),
     /**
      * The clock-hour-of-day.
      * <p>
-     * This counts the hour within the AM/PM, from 1 to 24.
+     * This counts the hour within the day, from 1 to 24.
      * This is the hour that would be observed on a 24-hour analog wall clock.
      * This field has the same meaning for all calendar systems.
      * <p>
@@ -312,6 +329,8 @@
      * 0 to 24 in smart mode. In lenient mode the value is not validated.
      * The field is converted to an {@code HOUR_OF_DAY} with the same value,
      * unless the value is 24, in which case it is converted to 0.
+     * <p>
+     * See {@link #HOUR_OF_DAY} for the related field that counts hours from 0 to 23.
      */
     CLOCK_HOUR_OF_DAY("ClockHourOfDay", HOURS, DAYS, ValueRange.of(1, 24)),
     /**
@@ -418,8 +437,11 @@
      * <p>
      * This field is strictly defined to have the same meaning in all calendar systems.
      * This is necessary to ensure interoperation between calendars.
+     * <p>
+     * Range of EpochDay is between (LocalDate.MIN.toEpochDay(), LocalDate.MAX.toEpochDay())
+     * both inclusive.
      */
-    EPOCH_DAY("EpochDay", DAYS, FOREVER, ValueRange.of((long) (Year.MIN_VALUE * 365.25), (long) (Year.MAX_VALUE * 365.25))),
+    EPOCH_DAY("EpochDay", DAYS, FOREVER, ValueRange.of(-365243219162L, 365241780471L)),
     /**
      * The aligned week within a month.
      * <p>
@@ -619,7 +641,16 @@
             return name;
         }
 
-        // Android-changed: use ICU names.
+        // BEGIN Android-changed: use ICU names.
+        /*
+        LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
+                                    .getLocaleResources(
+                                        CalendarDataUtility
+                                            .findRegionOverride(locale));
+        ResourceBundle rb = lr.getJavaTimeFormatData();
+        String key = "field." + displayNameKey;
+        return rb.containsKey(key) ? rb.getString(key) : name;
+         */
         DateTimePatternGenerator generator = DateTimePatternGenerator
                 .getInstance(ULocale.forLocale(locale));
         String icuName = generator.getAppendItemName(getIcuFieldNumber(this));
@@ -652,6 +683,7 @@
             default:
                 throw new IllegalArgumentException("Unexpected ChronoField " + field.name());
         }
+        // END Android-changed: use ICU names.
     }
 
     @Override
diff --git a/ojluni/src/main/java/java/time/temporal/ChronoUnit.java b/ojluni/src/main/java/java/time/temporal/ChronoUnit.java
index c704327..8f94e06 100644
--- a/ojluni/src/main/java/java/time/temporal/ChronoUnit.java
+++ b/ojluni/src/main/java/java/time/temporal/ChronoUnit.java
@@ -184,8 +184,8 @@
      * Artificial unit that represents the concept of forever.
      * This is primarily used with {@link TemporalField} to represent unbounded fields
      * such as the year or era.
-     * The estimated duration of the era is artificially defined as the largest duration
-     * supported by {@code Duration}.
+     * The estimated duration of this unit is artificially defined as the largest duration
+     * supported by {@link Duration}.
      */
     FOREVER("Forever", Duration.ofSeconds(Long.MAX_VALUE, 999_999_999));
 
diff --git a/ojluni/src/main/java/java/time/temporal/IsoFields.java b/ojluni/src/main/java/java/time/temporal/IsoFields.java
index 20b2cfd..1457617 100644
--- a/ojluni/src/main/java/java/time/temporal/IsoFields.java
+++ b/ojluni/src/main/java/java/time/temporal/IsoFields.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -82,6 +82,9 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.ResourceBundle;
+
+import sun.util.locale.provider.CalendarDataUtility;
 
 /**
  * Fields and units specific to the ISO-8601 calendar system,
@@ -101,7 +104,7 @@
  * The complete date is expressed using three fields:
  * <ul>
  * <li>{@link #DAY_OF_QUARTER DAY_OF_QUARTER} - the day within the quarter, from 1 to 90, 91 or 92
- * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the week within the week-based-year
+ * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the quarter within the year, from 1 to 4
  * <li>{@link ChronoField#YEAR YEAR} - the standard ISO year
  * </ul>
  *
@@ -135,15 +138,19 @@
  * <p>
  * For example:
  *
- * <table cellpadding="0" cellspacing="3" border="0" style="text-align: left; width: 50%;">
+ * <table class=striped style="text-align: left">
  * <caption>Examples of Week based Years</caption>
- * <tr><th>Date</th><th>Day-of-week</th><th>Field values</th></tr>
- * <tr><th>2008-12-28</th><td>Sunday</td><td>Week 52 of week-based-year 2008</td></tr>
- * <tr><th>2008-12-29</th><td>Monday</td><td>Week 1 of week-based-year 2009</td></tr>
- * <tr><th>2008-12-31</th><td>Wednesday</td><td>Week 1 of week-based-year 2009</td></tr>
- * <tr><th>2009-01-01</th><td>Thursday</td><td>Week 1 of week-based-year 2009</td></tr>
- * <tr><th>2009-01-04</th><td>Sunday</td><td>Week 1 of week-based-year 2009</td></tr>
- * <tr><th>2009-01-05</th><td>Monday</td><td>Week 2 of week-based-year 2009</td></tr>
+ * <thead>
+ * <tr><th scope="col">Date</th><th scope="col">Day-of-week</th><th scope="col">Field values</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><th scope="row">2008-12-28</th><td>Sunday</td><td>Week 52 of week-based-year 2008</td></tr>
+ * <tr><th scope="row">2008-12-29</th><td>Monday</td><td>Week 1 of week-based-year 2009</td></tr>
+ * <tr><th scope="row">2008-12-31</th><td>Wednesday</td><td>Week 1 of week-based-year 2009</td></tr>
+ * <tr><th scope="row">2009-01-01</th><td>Thursday</td><td>Week 1 of week-based-year 2009</td></tr>
+ * <tr><th scope="row">2009-01-04</th><td>Sunday</td><td>Week 1 of week-based-year 2009</td></tr>
+ * <tr><th scope="row">2009-01-05</th><td>Monday</td><td>Week 2 of week-based-year 2009</td></tr>
+ * </tbody>
  * </table>
  *
  * @implSpec
@@ -401,6 +408,12 @@
                 long moy = temporal.getLong(MONTH_OF_YEAR);
                 return ((moy + 2) / 3);
             }
+            public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
+                if (isSupportedBy(temporal) == false) {
+                    throw new UnsupportedTemporalTypeException("Unsupported field: QuarterOfYear");
+                }
+                return super.rangeRefinedBy(temporal);
+            }
             @SuppressWarnings("unchecked")
             @Override
             public <R extends Temporal> R adjustInto(R temporal, long newValue) {
@@ -418,12 +431,21 @@
             @Override
             public String getDisplayName(Locale locale) {
                 Objects.requireNonNull(locale, "locale");
-                // Android-changed: Use ICU name values.
+                // BEGIN Android-changed: Use ICU name values.
+                /*
+                LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
+                                            .getLocaleResources(
+                                                CalendarDataUtility
+                                                    .findRegionOverride(locale));
+                ResourceBundle rb = lr.getJavaTimeFormatData();
+                return rb.containsKey("field.week") ? rb.getString("field.week") : toString();
+                 */
                 DateTimePatternGenerator dateTimePatternGenerator = DateTimePatternGenerator
                         .getInstance(ULocale.forLocale(locale));
                 String icuName = dateTimePatternGenerator
                         .getAppendItemName(DateTimePatternGenerator.WEEK_OF_YEAR);
                 return icuName != null && !icuName.isEmpty() ? icuName : toString();
+                // END Android-changed: Use ICU name values.
             }
 
             @Override
@@ -530,6 +552,12 @@
                 }
                 return getWeekBasedYear(LocalDate.from(temporal));
             }
+            public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
+                if (isSupportedBy(temporal) == false) {
+                    throw new UnsupportedTemporalTypeException("Unsupported field: WeekBasedYear");
+                }
+                return super.rangeRefinedBy(temporal);
+            }
             @SuppressWarnings("unchecked")
             @Override
             public <R extends Temporal> R adjustInto(R temporal, long newValue) {
@@ -572,9 +600,6 @@
         //-------------------------------------------------------------------------
         private static final int[] QUARTER_DAYS = {0, 90, 181, 273, 0, 91, 182, 274};
 
-        private static boolean isIso(TemporalAccessor temporal) {
-            return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
-        }
 
         private static void ensureIso(TemporalAccessor temporal) {
             if (isIso(temporal) == false) {
@@ -682,7 +707,7 @@
 
         @Override
         public boolean isSupportedBy(Temporal temporal) {
-            return temporal.isSupported(EPOCH_DAY);
+            return temporal.isSupported(EPOCH_DAY) && isIso(temporal);
         }
 
         @SuppressWarnings("unchecked")
@@ -693,9 +718,8 @@
                     return (R) temporal.with(WEEK_BASED_YEAR,
                             Math.addExact(temporal.get(WEEK_BASED_YEAR), amount));
                 case QUARTER_YEARS:
-                    // no overflow (256 is multiple of 4)
-                    return (R) temporal.plus(amount / 256, YEARS)
-                            .plus((amount % 256) * 3, MONTHS);
+                    return (R) temporal.plus(amount / 4, YEARS)
+                            .plus((amount % 4) * 3, MONTHS);
                 default:
                     throw new IllegalStateException("Unreachable");
             }
@@ -722,4 +746,8 @@
             return name;
         }
     }
+
+    static boolean isIso(TemporalAccessor temporal) {
+        return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
+    }
 }
diff --git a/ojluni/src/main/java/java/time/temporal/JulianFields.java b/ojluni/src/main/java/java/time/temporal/JulianFields.java
index 3270379..7fc501c 100644
--- a/ojluni/src/main/java/java/time/temporal/JulianFields.java
+++ b/ojluni/src/main/java/java/time/temporal/JulianFields.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -117,7 +117,13 @@
      *
      * <h3>Astronomical and Scientific Notes</h3>
      * The standard astronomical definition uses a fraction to indicate the time-of-day,
-     * thus 3.25 would represent the time 18:00, since days start at midday.
+     * where each day is counted from midday to midday. For example,
+     * a fraction of 0 represents midday, a fraction of 0.25
+     * represents 18:00, a fraction of 0.5 represents midnight and a fraction
+     * of 0.75 represents 06:00.
+     * <p>
+     * By contrast, this implementation has no fractional part, and counts
+     * days from midnight to midnight.
      * This implementation uses an integer and days starting at midnight.
      * The integer value for the Julian Day Number is the astronomical Julian Day value at midday
      * of the date in question.
diff --git a/ojluni/src/main/java/java/time/temporal/Temporal.java b/ojluni/src/main/java/java/time/temporal/Temporal.java
index f7064aa..75ce67d 100644
--- a/ojluni/src/main/java/java/time/temporal/Temporal.java
+++ b/ojluni/src/main/java/java/time/temporal/Temporal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/temporal/TemporalAccessor.java b/ojluni/src/main/java/java/time/temporal/TemporalAccessor.java
index 5e8b61e..347e69d 100644
--- a/ojluni/src/main/java/java/time/temporal/TemporalAccessor.java
+++ b/ojluni/src/main/java/java/time/temporal/TemporalAccessor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/temporal/TemporalAdjusters.java b/ojluni/src/main/java/java/time/temporal/TemporalAdjusters.java
index 0180c81..e72b510 100644
--- a/ojluni/src/main/java/java/time/temporal/TemporalAdjusters.java
+++ b/ojluni/src/main/java/java/time/temporal/TemporalAdjusters.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -313,7 +313,7 @@
 
     /**
      * Returns the day-of-week in month adjuster, which returns a new date
-     * in the same month with the ordinal day-of-week.
+     * with the ordinal day-of-week based on the month.
      * This is used for expressions like the 'second Tuesday in March'.
      * <p>
      * The ISO calendar system behaves as follows:<br>
diff --git a/ojluni/src/main/java/java/time/temporal/TemporalField.java b/ojluni/src/main/java/java/time/temporal/TemporalField.java
index a82255a..a93caa6 100644
--- a/ojluni/src/main/java/java/time/temporal/TemporalField.java
+++ b/ojluni/src/main/java/java/time/temporal/TemporalField.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/temporal/TemporalQueries.java b/ojluni/src/main/java/java/time/temporal/TemporalQueries.java
index 6b1777a..9df66bb 100644
--- a/ojluni/src/main/java/java/time/temporal/TemporalQueries.java
+++ b/ojluni/src/main/java/java/time/temporal/TemporalQueries.java
@@ -341,58 +341,118 @@
     /**
      * A strict query for the {@code ZoneId}.
      */
-    static final TemporalQuery<ZoneId> ZONE_ID = (temporal) ->
-        temporal.query(TemporalQueries.ZONE_ID);
+    static final TemporalQuery<ZoneId> ZONE_ID = new TemporalQuery<>() {
+        @Override
+        public ZoneId queryFrom(TemporalAccessor temporal) {
+            return temporal.query(TemporalQueries.ZONE_ID);
+        }
+
+        @Override
+        public String toString() {
+            return "ZoneId";
+        }
+    };
 
     /**
      * A query for the {@code Chronology}.
      */
-    static final TemporalQuery<Chronology> CHRONO = (temporal) ->
-        temporal.query(TemporalQueries.CHRONO);
+    static final TemporalQuery<Chronology> CHRONO = new TemporalQuery<>() {
+        @Override
+        public Chronology queryFrom(TemporalAccessor temporal) {
+            return temporal.query(TemporalQueries.CHRONO);
+        }
+
+        @Override
+        public String toString() {
+            return "Chronology";
+        }
+    };
+
 
     /**
      * A query for the smallest supported unit.
      */
-    static final TemporalQuery<TemporalUnit> PRECISION = (temporal) ->
-        temporal.query(TemporalQueries.PRECISION);
+    static final TemporalQuery<TemporalUnit> PRECISION = new TemporalQuery<>() {
+        @Override
+        public TemporalUnit queryFrom(TemporalAccessor temporal) {
+            return temporal.query(TemporalQueries.PRECISION);
+        }
+
+        @Override
+        public String toString() {
+            return "Precision";
+        }
+    };
 
     //-----------------------------------------------------------------------
     /**
      * A query for {@code ZoneOffset} returning null if not found.
      */
-    static final TemporalQuery<ZoneOffset> OFFSET = (temporal) -> {
-        if (temporal.isSupported(OFFSET_SECONDS)) {
-            return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS));
+    static final TemporalQuery<ZoneOffset> OFFSET = new TemporalQuery<>() {
+        @Override
+        public ZoneOffset queryFrom(TemporalAccessor temporal) {
+            if (temporal.isSupported(OFFSET_SECONDS)) {
+                return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS));
+            }
+            return null;
         }
-        return null;
+
+        @Override
+        public String toString() {
+            return "ZoneOffset";
+        }
     };
 
     /**
      * A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}.
      */
-    static final TemporalQuery<ZoneId> ZONE = (temporal) -> {
-        ZoneId zone = temporal.query(ZONE_ID);
-        return (zone != null ? zone : temporal.query(OFFSET));
+    static final TemporalQuery<ZoneId> ZONE = new TemporalQuery<>() {
+        @Override
+        public ZoneId queryFrom(TemporalAccessor temporal) {
+            ZoneId zone = temporal.query(ZONE_ID);
+            return (zone != null ? zone : temporal.query(OFFSET));
+        }
+
+        @Override
+        public String toString() {
+            return "Zone";
+        }
     };
 
     /**
      * A query for {@code LocalDate} returning null if not found.
      */
-    static final TemporalQuery<LocalDate> LOCAL_DATE = (temporal) -> {
-        if (temporal.isSupported(EPOCH_DAY)) {
-            return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY));
+    static final TemporalQuery<LocalDate> LOCAL_DATE = new TemporalQuery<>() {
+        @Override
+        public LocalDate queryFrom(TemporalAccessor temporal) {
+            if (temporal.isSupported(EPOCH_DAY)) {
+                return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY));
+            }
+            return null;
         }
-        return null;
+
+        @Override
+        public String toString() {
+            return "LocalDate";
+        }
     };
 
     /**
      * A query for {@code LocalTime} returning null if not found.
      */
-    static final TemporalQuery<LocalTime> LOCAL_TIME = (temporal) -> {
-        if (temporal.isSupported(NANO_OF_DAY)) {
-            return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY));
+    static final TemporalQuery<LocalTime> LOCAL_TIME = new TemporalQuery<>() {
+        @Override
+        public LocalTime queryFrom(TemporalAccessor temporal) {
+            if (temporal.isSupported(NANO_OF_DAY)) {
+                return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY));
+            }
+            return null;
         }
-        return null;
+
+        @Override
+        public String toString() {
+            return "LocalTime";
+        }
     };
 
 }
diff --git a/ojluni/src/main/java/java/time/temporal/TemporalUnit.java b/ojluni/src/main/java/java/time/temporal/TemporalUnit.java
index 949104d..1904bd2 100644
--- a/ojluni/src/main/java/java/time/temporal/TemporalUnit.java
+++ b/ojluni/src/main/java/java/time/temporal/TemporalUnit.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/time/temporal/ValueRange.java b/ojluni/src/main/java/java/time/temporal/ValueRange.java
index 4e5c2fd..d31cdca 100644
--- a/ojluni/src/main/java/java/time/temporal/ValueRange.java
+++ b/ojluni/src/main/java/java/time/temporal/ValueRange.java
@@ -385,7 +385,7 @@
         }
         if (obj instanceof ValueRange) {
             ValueRange other = (ValueRange) obj;
-           return minSmallest == other.minSmallest && minLargest == other.minLargest &&
+            return minSmallest == other.minSmallest && minLargest == other.minLargest &&
                    maxSmallest == other.maxSmallest && maxLargest == other.maxLargest;
         }
         return false;
@@ -398,8 +398,9 @@
      */
     @Override
     public int hashCode() {
-        long hash = minSmallest + minLargest << 16 + minLargest >> 48 + maxSmallest << 32 +
-            maxSmallest >> 32 + maxLargest << 48 + maxLargest >> 16;
+        long hash = minSmallest + (minLargest << 16) + (minLargest >> 48) +
+                (maxSmallest << 32) + (maxSmallest >> 32) + (maxLargest << 48) +
+                (maxLargest >> 16);
         return (int) (hash ^ (hash >>> 32));
     }
 
diff --git a/ojluni/src/main/java/java/time/temporal/WeekFields.java b/ojluni/src/main/java/java/time/temporal/WeekFields.java
index b2f85ae..fc92343 100644
--- a/ojluni/src/main/java/java/time/temporal/WeekFields.java
+++ b/ojluni/src/main/java/java/time/temporal/WeekFields.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -127,18 +127,22 @@
  * The earliest period is referred to as week 0 if it has less than the minimal number of days
  * and week 1 if it has at least the minimal number of days.
  *
- * <table cellpadding="0" cellspacing="3" border="0" style="text-align: left; width: 50%;">
+ * <table class=striped style="text-align: left">
  * <caption>Examples of WeekFields</caption>
- * <tr><th>Date</th><td>Day-of-week</td>
- *  <td>First day: Monday<br>Minimal days: 4</td><td>First day: Monday<br>Minimal days: 5</td></tr>
- * <tr><th>2008-12-31</th><td>Wednesday</td>
+ * <thead>
+ * <tr><th scope="col">Date</th><th scope="col">Day-of-week</th>
+ *  <th scope="col">First day: Monday<br>Minimal days: 4</th><th scope="col">First day: Monday<br>Minimal days: 5</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><th scope="row">2008-12-31</th><td>Wednesday</td>
  *  <td>Week 5 of December 2008</td><td>Week 5 of December 2008</td></tr>
- * <tr><th>2009-01-01</th><td>Thursday</td>
+ * <tr><th scope="row">2009-01-01</th><td>Thursday</td>
  *  <td>Week 1 of January 2009</td><td>Week 0 of January 2009</td></tr>
- * <tr><th>2009-01-04</th><td>Sunday</td>
+ * <tr><th scope="row">2009-01-04</th><td>Sunday</td>
  *  <td>Week 1 of January 2009</td><td>Week 0 of January 2009</td></tr>
- * <tr><th>2009-01-05</th><td>Monday</td>
+ * <tr><th scope="row">2009-01-05</th><td>Monday</td>
  *  <td>Week 2 of January 2009</td><td>Week 1 of January 2009</td></tr>
+ * </tbody>
  * </table>
  *
  * <h3>Week of Year</h3>
@@ -157,18 +161,22 @@
  * The first and last weeks of a year may contain days from the
  * previous calendar year or next calendar year respectively.
  *
- * <table cellpadding="0" cellspacing="3" border="0" style="text-align: left; width: 50%;">
+ * <table class=striped style="text-align: left;">
  * <caption>Examples of WeekFields for week-based-year</caption>
- * <tr><th>Date</th><td>Day-of-week</td>
- *  <td>First day: Monday<br>Minimal days: 4</td><td>First day: Monday<br>Minimal days: 5</td></tr>
- * <tr><th>2008-12-31</th><td>Wednesday</td>
+ * <thead>
+ * <tr><th scope="col">Date</th><th scope="col">Day-of-week</th>
+ *  <th scope="col">First day: Monday<br>Minimal days: 4</th><th scope="col">First day: Monday<br>Minimal days: 5</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><th scope="row">2008-12-31</th><td>Wednesday</td>
  *  <td>Week 1 of 2009</td><td>Week 53 of 2008</td></tr>
- * <tr><th>2009-01-01</th><td>Thursday</td>
+ * <tr><th scope="row">2009-01-01</th><td>Thursday</td>
  *  <td>Week 1 of 2009</td><td>Week 53 of 2008</td></tr>
- * <tr><th>2009-01-04</th><td>Sunday</td>
+ * <tr><th scope="row">2009-01-04</th><td>Sunday</td>
  *  <td>Week 1 of 2009</td><td>Week 53 of 2008</td></tr>
- * <tr><th>2009-01-05</th><td>Monday</td>
+ * <tr><th scope="row">2009-01-05</th><td>Monday</td>
  *  <td>Week 2 of 2009</td><td>Week 1 of 2009</td></tr>
+ * </tbody>
  * </table>
  *
  * @implSpec
@@ -274,23 +282,66 @@
     private final transient TemporalField weekBasedYear = ComputedDayOfField.ofWeekBasedYearField(this);
 
     //-----------------------------------------------------------------------
+    // Android-changed: Remove "rg" support in the javadoc. See http://b/228322300.
+    // Android-changed: Support the "fw" extension since Android 13. See http://b/228322300.
     /**
      * Obtains an instance of {@code WeekFields} appropriate for a locale.
      * <p>
      * This will look up appropriate values from the provider of localization data.
+     * Since Android 13, if the locale contains "fw" (First day of week)
+     * <a href="../../util/Locale.html#def_locale_extension">
+     * Unicode extensions</a>, returned instance will reflect the values specified with
+     * those extensions.
      *
      * @param locale  the locale to use, not null
      * @return the week-definition, not null
      */
     public static WeekFields of(Locale locale) {
         Objects.requireNonNull(locale, "locale");
-        // Android-changed: get Week data from ICU4J
+
+        // Android-changed: Obtain week data from ICU4J.
+        // int calDow = CalendarDataUtility.retrieveFirstDayOfWeek(locale);
         Calendar calendar = Calendar.getInstance(locale);
         Calendar.WeekData weekData = calendar.getWeekData();
-        DayOfWeek dow = DayOfWeek.SUNDAY.plus(weekData.firstDayOfWeek - 1);
-        return WeekFields.of(dow, weekData.minimalDaysInFirstWeek);
+        int calDow = retrieveFirstDayOfWeek(locale, weekData);
+        DayOfWeek dow = DayOfWeek.SUNDAY.plus(calDow - 1);
+        // Android-changed: Obtain minimal days from ICU4J.
+        // int minDays = CalendarDataUtility.retrieveMinimalDaysInFirstWeek(locale);
+        int minDays = weekData.minimalDaysInFirstWeek;
+        return WeekFields.of(dow, minDays);
     }
 
+    // BEGIN Android-added: Extra method needed to support "fw" the Unicode extension.
+    // A modified version of the upstream CalendarDataUtility.retrieveFirstDayOfWeek() but with
+    // ICU provider.
+    private static int retrieveFirstDayOfWeek(Locale locale, Calendar.WeekData icuWeekData) {
+        // Look for the Unicode Extension in the locale parameter
+        if (locale.hasExtensions()) {
+            String fw = locale.getUnicodeLocaleType("fw");
+            if (fw != null) {
+                switch (fw.toLowerCase(Locale.ROOT)) {
+                    case "mon":
+                        return Calendar.MONDAY;
+                    case "tue":
+                        return Calendar.TUESDAY;
+                    case "wed":
+                        return Calendar.WEDNESDAY;
+                    case "thu":
+                        return Calendar.THURSDAY;
+                    case "fri":
+                        return Calendar.FRIDAY;
+                    case "sat":
+                        return Calendar.SATURDAY;
+                    case "sun":
+                        return Calendar.SUNDAY;
+                }
+            }
+        }
+
+        return icuWeekData.firstDayOfWeek;
+    }
+    // END Android-added: Extra method needed to support "fw" the Unicode extension.
+
     /**
      * Obtains an instance of {@code WeekFields} from the first day-of-week and minimal days.
      * <p>
@@ -302,7 +353,7 @@
      * the new month or year.
      * <p>
      * WeekFields instances are singletons; for each unique combination
-     * of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek} the
+     * of {@code firstDayOfWeek} and {@code minimalDaysInFirstWeek}
      * the same instance will be returned.
      *
      * @param firstDayOfWeek  the first day of the week, not null
@@ -1032,6 +1083,13 @@
             Objects.requireNonNull(locale, "locale");
             if (rangeUnit == YEARS) {  // only have values for week-of-year
                 // Android-changed: Use ICU name values.
+                /*
+                LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
+                        .getLocaleResources(
+                            CalendarDataUtility.findRegionOverride(locale));
+                ResourceBundle rb = lr.getJavaTimeFormatData();
+                return rb.containsKey("field.week") ? rb.getString("field.week") : name;
+                 */
                 DateTimePatternGenerator dateTimePatternGenerator = DateTimePatternGenerator
                         .getInstance(ULocale.forLocale(locale));
                 String icuName = dateTimePatternGenerator
diff --git a/ojluni/src/main/java/java/time/temporal/package-info.java b/ojluni/src/main/java/java/time/temporal/package-info.java
index d3e9c05..25b228f 100644
--- a/ojluni/src/main/java/java/time/temporal/package-info.java
+++ b/ojluni/src/main/java/java/time/temporal/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
  * <li>Different definitions of weeks</li>
  * </ul>
  *
- * <h3>Fields and Units</h3>
+ * <h2>Fields and Units</h2>
  * <p>
  * Dates and times are expressed in terms of fields and units.
  * A unit is used to measure an amount of time, such as years, days or minutes.
@@ -106,7 +106,7 @@
  * The fields also provide access to the range of valid values.
  * </p>
  *
- * <h3>Adjustment and Query</h3>
+ * <h2>Adjustment and Query</h2>
  * <p>
  * A key part of the date-time problem space is adjusting a date to a new, related value,
  * such as the "last day of the month", or "next Wednesday".
@@ -131,7 +131,7 @@
  * Applications can also define queries by implementing {@link java.time.temporal.TemporalQuery}.
  * </p>
  *
- * <h3>Weeks</h3>
+ * <h2>Weeks</h2>
  * <p>
  * Different locales have different definitions of the week.
  * For example, in Europe the week typically starts on a Monday, while in the US it starts on a Sunday.
@@ -143,7 +143,7 @@
  * This is modeled in {@link java.time.temporal.IsoFields}.
  * </p>
  *
- * <h3>Package specification</h3>
+ * <h2>Package specification</h2>
  * <p>
  * Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
  * in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
@@ -154,6 +154,6 @@
  * All calculations should check for numeric overflow and throw either an {@link java.lang.ArithmeticException}
  * or a {@link java.time.DateTimeException}.
  * </p>
- * @since JDK1.8
+ * @since 1.8
  */
 package java.time.temporal;
diff --git a/ojluni/src/main/java/java/time/zone/Ser.java b/ojluni/src/main/java/java/time/zone/Ser.java
index 31c2f2d..0017fb8 100644
--- a/ojluni/src/main/java/java/time/zone/Ser.java
+++ b/ojluni/src/main/java/java/time/zone/Ser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
     static final byte ZRULES = 1;
     /** Type for ZoneOffsetTransition. */
     static final byte ZOT = 2;
-    /** Type for ZoneOffsetTransition. */
+    /** Type for ZoneOffsetTransitionRule. */
     static final byte ZOTRULE = 3;
 
     /** The type being serialized. */
diff --git a/ojluni/src/main/java/java/time/zone/ZoneOffsetTransition.java b/ojluni/src/main/java/java/time/zone/ZoneOffsetTransition.java
index bc9cafe..94264f3 100644
--- a/ojluni/src/main/java/java/time/zone/ZoneOffsetTransition.java
+++ b/ojluni/src/main/java/java/time/zone/ZoneOffsetTransition.java
@@ -104,6 +104,10 @@
      */
     private static final long serialVersionUID = -6946044323557704546L;
     /**
+     * The transition epoch-second.
+     */
+    private final long epochSecond;
+    /**
      * The local transition date-time at the transition.
      */
     private final LocalDateTime transition;
@@ -152,6 +156,8 @@
      * @param offsetAfter  the offset at and after the transition, not null
      */
     ZoneOffsetTransition(LocalDateTime transition, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {
+        assert transition.getNano() == 0;
+        this.epochSecond = transition.toEpochSecond(offsetBefore);
         this.transition = transition;
         this.offsetBefore = offsetBefore;
         this.offsetAfter = offsetAfter;
@@ -165,6 +171,7 @@
      * @param offsetAfter  the offset at and after the transition, not null
      */
     ZoneOffsetTransition(long epochSecond, ZoneOffset offsetBefore, ZoneOffset offsetAfter) {
+        this.epochSecond = epochSecond;
         this.transition = LocalDateTime.ofEpochSecond(epochSecond, 0, offsetBefore);
         this.offsetBefore = offsetBefore;
         this.offsetAfter = offsetAfter;
@@ -209,7 +216,7 @@
      * @throws IOException if an error occurs
      */
     void writeExternal(DataOutput out) throws IOException {
-        Ser.writeEpochSec(toEpochSecond(), out);
+        Ser.writeEpochSec(epochSecond, out);
         Ser.writeOffset(offsetBefore, out);
         Ser.writeOffset(offsetAfter, out);
     }
@@ -244,7 +251,7 @@
      * @return the transition instant, not null
      */
     public Instant getInstant() {
-        return transition.toInstant(offsetBefore);
+        return Instant.ofEpochSecond(epochSecond);
     }
 
     /**
@@ -253,7 +260,7 @@
      * @return the transition epoch second
      */
     public long toEpochSecond() {
-        return transition.toEpochSecond(offsetBefore);
+        return epochSecond;
     }
 
     //-------------------------------------------------------------------------
@@ -380,9 +387,9 @@
      */
     List<ZoneOffset> getValidOffsets() {
         if (isGap()) {
-            return Collections.emptyList();
+            return List.of();
         }
-        return Arrays.asList(getOffsetBefore(), getOffsetAfter());
+        return List.of(getOffsetBefore(), getOffsetAfter());
     }
 
     //-----------------------------------------------------------------------
@@ -397,7 +404,7 @@
      */
     @Override
     public int compareTo(ZoneOffsetTransition transition) {
-        return this.getInstant().compareTo(transition.getInstant());
+        return Long.compare(epochSecond, transition.epochSecond);
     }
 
     //-----------------------------------------------------------------------
@@ -416,7 +423,7 @@
         }
         if (other instanceof ZoneOffsetTransition) {
             ZoneOffsetTransition d = (ZoneOffsetTransition) other;
-            return transition.equals(d.transition) &&
+            return epochSecond == d.epochSecond &&
                 offsetBefore.equals(d.offsetBefore) && offsetAfter.equals(d.offsetAfter);
         }
         return false;
diff --git a/ojluni/src/main/java/java/time/zone/ZoneOffsetTransitionRule.java b/ojluni/src/main/java/java/time/zone/ZoneOffsetTransitionRule.java
index db1a055..68d3469 100644
--- a/ojluni/src/main/java/java/time/zone/ZoneOffsetTransitionRule.java
+++ b/ojluni/src/main/java/java/time/zone/ZoneOffsetTransitionRule.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -167,6 +167,7 @@
      * @return the rule, not null
      * @throws IllegalArgumentException if the day of month indicator is invalid
      * @throws IllegalArgumentException if the end of day flag is true when the time is not midnight
+     * @throws IllegalArgumentException if {@code time.getNano()} returns non-zero value
      */
     public static ZoneOffsetTransitionRule of(
             Month month,
@@ -190,6 +191,9 @@
         if (timeEndOfDay && time.equals(LocalTime.MIDNIGHT) == false) {
             throw new IllegalArgumentException("Time must be midnight when end of day flag is true");
         }
+        if (time.getNano() != 0) {
+            throw new IllegalArgumentException("Time's nano-of-second must be zero");
+        }
         return new ZoneOffsetTransitionRule(month, dayOfMonthIndicator, dayOfWeek, time, timeEndOfDay, timeDefnition, standardOffset, offsetBefore, offsetAfter);
     }
 
@@ -220,6 +224,7 @@
             ZoneOffset standardOffset,
             ZoneOffset offsetBefore,
             ZoneOffset offsetAfter) {
+        assert time.getNano() == 0;
         this.month = month;
         this.dom = (byte) dayOfMonthIndicator;
         this.dow = dayOfWeek;
@@ -251,7 +256,7 @@
      * for the encoding of epoch seconds and offsets.
      * <pre style="font-size:1.0em">{@code
      *
-     *      out.writeByte(3);                // identifies a ZoneOffsetTransition
+     *      out.writeByte(3);                // identifies a ZoneOffsetTransitionRule
      *      final int timeSecs = (timeEndOfDay ? 86400 : time.toSecondOfDay());
      *      final int stdOffset = standardOffset.getTotalSeconds();
      *      final int beforeDiff = offsetBefore.getTotalSeconds() - stdOffset;
diff --git a/ojluni/src/main/java/java/time/zone/ZoneRules.java b/ojluni/src/main/java/java/time/zone/ZoneRules.java
index c3b5bba..6eaba2e 100644
--- a/ojluni/src/main/java/java/time/zone/ZoneRules.java
+++ b/ojluni/src/main/java/java/time/zone/ZoneRules.java
@@ -303,7 +303,6 @@
      * Creates an instance of ZoneRules that has fixed zone rules.
      *
      * @param offset  the offset this fixed zone rules is based on, not null
-     * @return the zone rules, not null
      * @see #isFixedOffset()
      */
     private ZoneRules(ZoneOffset offset) {
@@ -420,7 +419,10 @@
     }
 
     /**
-     * Reads the state from the stream.
+     * Reads the state from the stream. The 1,024 limit to the lengths
+     * of stdTrans and savSize is intended to be the size well enough
+     * to accommodate the max number of transitions in current tzdb data
+     * (203 for Asia/Tehran).
      *
      * @param in  the input stream, not null
      * @return the created object, not null
@@ -428,6 +430,9 @@
      */
     static ZoneRules readExternal(DataInput in) throws IOException, ClassNotFoundException {
         int stdSize = in.readInt();
+        if (stdSize > 1024) {
+            throw new InvalidObjectException("Too many transitions");
+        }
         long[] stdTrans = (stdSize == 0) ? EMPTY_LONG_ARRAY
                                          : new long[stdSize];
         for (int i = 0; i < stdSize; i++) {
@@ -438,6 +443,9 @@
             stdOffsets[i] = Ser.readOffset(in);
         }
         int savSize = in.readInt();
+        if (savSize > 1024) {
+            throw new InvalidObjectException("Too many saving offsets");
+        }
         long[] savTrans = (savSize == 0) ? EMPTY_LONG_ARRAY
                                          : new long[savSize];
         for (int i = 0; i < savSize; i++) {
@@ -448,6 +456,9 @@
             savOffsets[i] = Ser.readOffset(in);
         }
         int ruleSize = in.readByte();
+        if (ruleSize > 16) {
+            throw new InvalidObjectException("Too many transition rules");
+        }
         ZoneOffsetTransitionRule[] rules = (ruleSize == 0) ?
             EMPTY_LASTRULES : new ZoneOffsetTransitionRule[ruleSize];
         for (int i = 0; i < ruleSize; i++) {
@@ -614,7 +625,7 @@
      * One technique, using this method, would be:
      * <pre>
      *  ZoneOffsetTransition trans = rules.getTransition(localDT);
-     *  if (trans == null) {
+     *  if (trans != null) {
      *    // Gap or Overlap: determine what to do from transition
      *  } else {
      *    // Normal case: only one valid offset
@@ -872,13 +883,13 @@
     /**
      * Gets the previous transition before the specified instant.
      * <p>
-     * This returns details of the previous transition after the specified instant.
+     * This returns details of the previous transition before the specified instant.
      * For example, if the instant represents a point where "summer" daylight saving time
      * applies, then the method will return the transition from the previous "winter" time.
      *
      * @param instant  the instant to get the previous transition after, not null, but null
      *  may be ignored if the rules have a single offset for all instants
-     * @return the previous transition after the specified instant, null if this is before the first transition
+     * @return the previous transition before the specified instant, null if this is before the first transition
      */
     public ZoneOffsetTransition previousTransition(Instant instant) {
         if (savingsInstantTransitions.length == 0) {
@@ -970,7 +981,7 @@
      * @return an immutable list of transition rules, not null
      */
     public List<ZoneOffsetTransitionRule> getTransitionRules() {
-        return Collections.unmodifiableList(Arrays.asList(lastRules));
+        return List.of(lastRules);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/time/zone/ZoneRulesProvider.java b/ojluni/src/main/java/java/time/zone/ZoneRulesProvider.java
index a90727a..acc04fc 100644
--- a/ojluni/src/main/java/java/time/zone/ZoneRulesProvider.java
+++ b/ojluni/src/main/java/java/time/zone/ZoneRulesProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,6 +77,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.Collections;
 
 /**
  * Provider of time-zone rules to the system.
@@ -118,7 +119,7 @@
  * Providers must ensure that once a rule has been seen by the application, the
  * rule must continue to be available.
  * <p>
-*  Providers are encouraged to implement a meaningful {@code toString} method.
+ * Providers are encouraged to implement a meaningful {@code toString} method.
  * <p>
  * Many systems would like to update time-zone rules dynamically without stopping the JVM.
  * When examined in detail, this is a complex problem.
@@ -137,10 +138,66 @@
      */
     private static final ConcurrentMap<String, ZoneRulesProvider> ZONES = new ConcurrentHashMap<>(512, 0.75f, 2);
 
+    /**
+     * The zone ID data
+     */
+    private static volatile Set<String> ZONE_IDS;
+
     static {
-        // Android-changed: use a single hard-coded provider.
+        // BEGIN Android-changed: use a single hard-coded provider.
+        /*
+        // if the property java.time.zone.DefaultZoneRulesProvider is
+        // set then its value is the class name of the default provider
+        final List<ZoneRulesProvider> loaded = new ArrayList<>();
+        AccessController.doPrivileged(new PrivilegedAction<>() {
+            public Object run() {
+                String prop = System.getProperty("java.time.zone.DefaultZoneRulesProvider");
+                if (prop != null) {
+                    try {
+                        Class<?> c = Class.forName(prop, true, ClassLoader.getSystemClassLoader());
+                        @SuppressWarnings("deprecation")
+                        ZoneRulesProvider provider = ZoneRulesProvider.class.cast(c.newInstance());
+                        registerProvider(provider);
+                        loaded.add(provider);
+                    } catch (Exception x) {
+                        throw new Error(x);
+                    }
+                } else {
+                    registerProvider(new TzdbZoneRulesProvider());
+                }
+                return null;
+            }
+        });
+
+        ServiceLoader<ZoneRulesProvider> sl = ServiceLoader.load(ZoneRulesProvider.class, ClassLoader.getSystemClassLoader());
+        Iterator<ZoneRulesProvider> it = sl.iterator();
+        while (it.hasNext()) {
+            ZoneRulesProvider provider;
+            try {
+                provider = it.next();
+            } catch (ServiceConfigurationError ex) {
+                if (ex.getCause() instanceof SecurityException) {
+                    continue;  // ignore the security exception, try the next provider
+                }
+                throw ex;
+            }
+            boolean found = false;
+            for (ZoneRulesProvider p : loaded) {
+                if (p.getClass() == provider.getClass()) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                registerProvider0(provider);
+                loaded.add(provider);
+            }
+        }
+        // CopyOnWriteList could be slow if lots of providers and each added individually
+        PROVIDERS.addAll(loaded);
+         */
         ZoneRulesProvider provider = new IcuZoneRulesProvider();
         registerProvider(provider);
+        // END Android-changed: use a single hard-coded provider.
     }
 
     //-------------------------------------------------------------------------
@@ -149,10 +206,10 @@
      * <p>
      * These IDs are the string form of a {@link ZoneId}.
      *
-     * @return a modifiable copy of the set of zone IDs, not null
+     * @return the unmodifiable set of zone IDs, not null
      */
     public static Set<String> getAvailableZoneIds() {
-        return new HashSet<>(ZONES.keySet());
+        return ZONE_IDS;
     }
 
     /**
@@ -258,7 +315,7 @@
      * @param provider  the provider to register, not null
      * @throws ZoneRulesException if unable to complete the registration
      */
-    private static void registerProvider0(ZoneRulesProvider provider) {
+    private static synchronized void registerProvider0(ZoneRulesProvider provider) {
         for (String zoneId : provider.provideZoneIds()) {
             Objects.requireNonNull(zoneId, "zoneId");
             ZoneRulesProvider old = ZONES.putIfAbsent(zoneId, provider);
@@ -268,6 +325,8 @@
                     ", currently loading from provider: " + provider);
             }
         }
+        Set<String> combinedSet = new HashSet<String>(ZONES.keySet());
+        ZONE_IDS = Collections.unmodifiableSet(combinedSet);
     }
 
     /**
diff --git a/ojluni/src/main/java/java/time/zone/package-info.java b/ojluni/src/main/java/java/time/zone/package-info.java
index f50b3de..e5c6a75 100644
--- a/ojluni/src/main/java/java/time/zone/package-info.java
+++ b/ojluni/src/main/java/java/time/zone/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,7 +70,7 @@
  * gaps and overlaps in the local time-line typically caused by Daylight Saving Time.
  * </p>
  *
- * <h3>Package specification</h3>
+ * <h2>Package specification</h2>
  * <p>
  * Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
  * in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
@@ -81,6 +81,6 @@
  * All calculations should check for numeric overflow and throw either an {@link java.lang.ArithmeticException}
  * or a {@link java.time.DateTimeException}.
  * </p>
- * @since JDK1.8
+ * @since 1.8
  */
 package java.time.zone;
diff --git a/ojluni/src/main/java/java/util/AbstractCollection.java b/ojluni/src/main/java/java/util/AbstractCollection.java
index 19c15f8..0fa05a2 100644
--- a/ojluni/src/main/java/java/util/AbstractCollection.java
+++ b/ojluni/src/main/java/java/util/AbstractCollection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,30 +26,30 @@
 package java.util;
 
 /**
- * This class provides a skeletal implementation of the <tt>Collection</tt>
+ * This class provides a skeletal implementation of the {@code Collection}
  * interface, to minimize the effort required to implement this interface. <p>
  *
  * To implement an unmodifiable collection, the programmer needs only to
- * extend this class and provide implementations for the <tt>iterator</tt> and
- * <tt>size</tt> methods.  (The iterator returned by the <tt>iterator</tt>
- * method must implement <tt>hasNext</tt> and <tt>next</tt>.)<p>
+ * extend this class and provide implementations for the {@code iterator} and
+ * {@code size} methods.  (The iterator returned by the {@code iterator}
+ * method must implement {@code hasNext} and {@code next}.)<p>
  *
  * To implement a modifiable collection, the programmer must additionally
- * override this class's <tt>add</tt> method (which otherwise throws an
- * <tt>UnsupportedOperationException</tt>), and the iterator returned by the
- * <tt>iterator</tt> method must additionally implement its <tt>remove</tt>
+ * override this class's {@code add} method (which otherwise throws an
+ * {@code UnsupportedOperationException}), and the iterator returned by the
+ * {@code iterator} method must additionally implement its {@code remove}
  * method.<p>
  *
  * The programmer should generally provide a void (no argument) and
- * <tt>Collection</tt> constructor, as per the recommendation in the
- * <tt>Collection</tt> interface specification.<p>
+ * {@code Collection} constructor, as per the recommendation in the
+ * {@code Collection} interface specification.<p>
  *
  * The documentation for each non-abstract method in this class describes its
  * implementation in detail.  Each of these methods may be overridden if
  * the collection being implemented admits a more efficient implementation.<p>
  *
  * This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
@@ -80,7 +80,8 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation returns <tt>size() == 0</tt>.
+     * @implSpec
+     * This implementation returns {@code size() == 0}.
      */
     public boolean isEmpty() {
         return size() == 0;
@@ -89,7 +90,8 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation iterates over the elements in the collection,
+     * @implSpec
+     * This implementation iterates over the elements in the collection,
      * checking each element in turn for equality with the specified element.
      *
      * @throws ClassCastException   {@inheritDoc}
@@ -112,7 +114,8 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation returns an array containing all the elements
+     * @implSpec
+     * This implementation returns an array containing all the elements
      * returned by this collection's iterator, in the same order, stored in
      * consecutive elements of the array, starting with index {@code 0}.
      * The length of the returned array is equal to the number of elements
@@ -146,7 +149,8 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation returns an array containing all the elements
+     * @implSpec
+     * This implementation returns an array containing all the elements
      * returned by this collection's iterator in the same order, stored in
      * consecutive elements of the array, starting with index {@code 0}.
      * If the number of elements returned by the iterator is too large to
@@ -249,8 +253,9 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation always throws an
-     * <tt>UnsupportedOperationException</tt>.
+     * @implSpec
+     * This implementation always throws an
+     * {@code UnsupportedOperationException}.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
@@ -265,13 +270,14 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation iterates over the collection looking for the
+     * @implSpec
+     * This implementation iterates over the collection looking for the
      * specified element.  If it finds the element, it removes the element
      * from the collection using the iterator's remove method.
      *
      * <p>Note that this implementation throws an
-     * <tt>UnsupportedOperationException</tt> if the iterator returned by this
-     * collection's iterator method does not implement the <tt>remove</tt>
+     * {@code UnsupportedOperationException} if the iterator returned by this
+     * collection's iterator method does not implement the {@code remove}
      * method and this collection contains the specified object.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
@@ -304,10 +310,11 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation iterates over the specified collection,
+     * @implSpec
+     * This implementation iterates over the specified collection,
      * checking each element returned by the iterator in turn to see
      * if it's contained in this collection.  If all elements are so
-     * contained <tt>true</tt> is returned, otherwise <tt>false</tt>.
+     * contained {@code true} is returned, otherwise {@code false}.
      *
      * @throws ClassCastException            {@inheritDoc}
      * @throws NullPointerException          {@inheritDoc}
@@ -323,11 +330,12 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation iterates over the specified collection, and adds
+     * @implSpec
+     * This implementation iterates over the specified collection, and adds
      * each object returned by the iterator to this collection, in turn.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> unless <tt>add</tt> is
+     * {@code UnsupportedOperationException} unless {@code add} is
      * overridden (assuming the specified collection is non-empty).
      *
      * @throws UnsupportedOperationException {@inheritDoc}
@@ -349,14 +357,15 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation iterates over this collection, checking each
+     * @implSpec
+     * This implementation iterates over this collection, checking each
      * element returned by the iterator in turn to see if it's contained
      * in the specified collection.  If it's so contained, it's removed from
-     * this collection with the iterator's <tt>remove</tt> method.
+     * this collection with the iterator's {@code remove} method.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the iterator returned by the
-     * <tt>iterator</tt> method does not implement the <tt>remove</tt> method
+     * {@code UnsupportedOperationException} if the iterator returned by the
+     * {@code iterator} method does not implement the {@code remove} method
      * and this collection contains one or more elements in common with the
      * specified collection.
      *
@@ -383,14 +392,15 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation iterates over this collection, checking each
+     * @implSpec
+     * This implementation iterates over this collection, checking each
      * element returned by the iterator in turn to see if it's contained
      * in the specified collection.  If it's not so contained, it's removed
-     * from this collection with the iterator's <tt>remove</tt> method.
+     * from this collection with the iterator's {@code remove} method.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the iterator returned by the
-     * <tt>iterator</tt> method does not implement the <tt>remove</tt> method
+     * {@code UnsupportedOperationException} if the iterator returned by the
+     * {@code iterator} method does not implement the {@code remove} method
      * and this collection contains one or more elements not present in the
      * specified collection.
      *
@@ -417,15 +427,16 @@
     /**
      * {@inheritDoc}
      *
-     * <p>This implementation iterates over this collection, removing each
-     * element using the <tt>Iterator.remove</tt> operation.  Most
+     * @implSpec
+     * This implementation iterates over this collection, removing each
+     * element using the {@code Iterator.remove} operation.  Most
      * implementations will probably choose to override this method for
      * efficiency.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the iterator returned by this
-     * collection's <tt>iterator</tt> method does not implement the
-     * <tt>remove</tt> method and this collection is non-empty.
+     * {@code UnsupportedOperationException} if the iterator returned by this
+     * collection's {@code iterator} method does not implement the
+     * {@code remove} method and this collection is non-empty.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      */
@@ -444,8 +455,8 @@
      * Returns a string representation of this collection.  The string
      * representation consists of a list of the collection's elements in the
      * order they are returned by its iterator, enclosed in square brackets
-     * (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
-     * <tt>", "</tt> (comma and space).  Elements are converted to strings as
+     * ({@code "[]"}).  Adjacent elements are separated by the characters
+     * {@code ", "} (comma and space).  Elements are converted to strings as
      * by {@link String#valueOf(Object)}.
      *
      * @return a string representation of this collection
diff --git a/ojluni/src/main/java/java/util/AbstractList.java b/ojluni/src/main/java/java/util/AbstractList.java
index 30778ad..848e80c 100644
--- a/ojluni/src/main/java/java/util/AbstractList.java
+++ b/ojluni/src/main/java/java/util/AbstractList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,7 +62,7 @@
  * collection being implemented admits a more efficient implementation.
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
diff --git a/ojluni/src/main/java/java/util/AbstractMap.java b/ojluni/src/main/java/java/util/AbstractMap.java
index 09c2f94..7109d318 100644
--- a/ojluni/src/main/java/java/util/AbstractMap.java
+++ b/ojluni/src/main/java/java/util/AbstractMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,24 +27,24 @@
 import java.util.Map.Entry;
 
 /**
- * This class provides a skeletal implementation of the <tt>Map</tt>
+ * This class provides a skeletal implementation of the {@code Map}
  * interface, to minimize the effort required to implement this interface.
  *
  * <p>To implement an unmodifiable map, the programmer needs only to extend this
- * class and provide an implementation for the <tt>entrySet</tt> method, which
+ * class and provide an implementation for the {@code entrySet} method, which
  * returns a set-view of the map's mappings.  Typically, the returned set
- * will, in turn, be implemented atop <tt>AbstractSet</tt>.  This set should
- * not support the <tt>add</tt> or <tt>remove</tt> methods, and its iterator
- * should not support the <tt>remove</tt> method.
+ * will, in turn, be implemented atop {@code AbstractSet}.  This set should
+ * not support the {@code add} or {@code remove} methods, and its iterator
+ * should not support the {@code remove} method.
  *
  * <p>To implement a modifiable map, the programmer must additionally override
- * this class's <tt>put</tt> method (which otherwise throws an
- * <tt>UnsupportedOperationException</tt>), and the iterator returned by
- * <tt>entrySet().iterator()</tt> must additionally implement its
- * <tt>remove</tt> method.
+ * this class's {@code put} method (which otherwise throws an
+ * {@code UnsupportedOperationException}), and the iterator returned by
+ * {@code entrySet().iterator()} must additionally implement its
+ * {@code remove} method.
  *
  * <p>The programmer should generally provide a void (no argument) and map
- * constructor, as per the recommendation in the <tt>Map</tt> interface
+ * constructor, as per the recommendation in the {@code Map} interface
  * specification.
  *
  * <p>The documentation for each non-abstract method in this class describes its
@@ -52,7 +52,7 @@
  * map being implemented admits a more efficient implementation.
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <K> the type of keys maintained by this map
@@ -79,7 +79,7 @@
      * {@inheritDoc}
      *
      * @implSpec
-     * This implementation returns <tt>entrySet().size()</tt>.
+     * This implementation returns {@code entrySet().size()}.
      */
     public int size() {
         return entrySet().size();
@@ -89,7 +89,7 @@
      * {@inheritDoc}
      *
      * @implSpec
-     * This implementation returns <tt>size() == 0</tt>.
+     * This implementation returns {@code size() == 0}.
      */
     public boolean isEmpty() {
         return size() == 0;
@@ -99,10 +99,10 @@
      * {@inheritDoc}
      *
      * @implSpec
-     * This implementation iterates over <tt>entrySet()</tt> searching
+     * This implementation iterates over {@code entrySet()} searching
      * for an entry with the specified value.  If such an entry is found,
-     * <tt>true</tt> is returned.  If the iteration terminates without
-     * finding such an entry, <tt>false</tt> is returned.  Note that this
+     * {@code true} is returned.  If the iteration terminates without
+     * finding such an entry, {@code false} is returned.  Note that this
      * implementation requires linear time in the size of the map.
      *
      * @throws ClassCastException   {@inheritDoc}
@@ -130,10 +130,10 @@
      * {@inheritDoc}
      *
      * @implSpec
-     * This implementation iterates over <tt>entrySet()</tt> searching
+     * This implementation iterates over {@code entrySet()} searching
      * for an entry with the specified key.  If such an entry is found,
-     * <tt>true</tt> is returned.  If the iteration terminates without
-     * finding such an entry, <tt>false</tt> is returned.  Note that this
+     * {@code true} is returned.  If the iteration terminates without
+     * finding such an entry, {@code false} is returned.  Note that this
      * implementation requires linear time in the size of the map; many
      * implementations will override this method.
      *
@@ -162,10 +162,10 @@
      * {@inheritDoc}
      *
      * @implSpec
-     * This implementation iterates over <tt>entrySet()</tt> searching
+     * This implementation iterates over {@code entrySet()} searching
      * for an entry with the specified key.  If such an entry is found,
      * the entry's value is returned.  If the iteration terminates without
-     * finding such an entry, <tt>null</tt> is returned.  Note that this
+     * finding such an entry, {@code null} is returned.  Note that this
      * implementation requires linear time in the size of the map; many
      * implementations will override this method.
      *
@@ -198,7 +198,7 @@
      *
      * @implSpec
      * This implementation always throws an
-     * <tt>UnsupportedOperationException</tt>.
+     * {@code UnsupportedOperationException}.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
@@ -213,18 +213,18 @@
      * {@inheritDoc}
      *
      * @implSpec
-     * This implementation iterates over <tt>entrySet()</tt> searching for an
+     * This implementation iterates over {@code entrySet()} searching for an
      * entry with the specified key.  If such an entry is found, its value is
-     * obtained with its <tt>getValue</tt> operation, the entry is removed
+     * obtained with its {@code getValue} operation, the entry is removed
      * from the collection (and the backing map) with the iterator's
-     * <tt>remove</tt> operation, and the saved value is returned.  If the
-     * iteration terminates without finding such an entry, <tt>null</tt> is
+     * {@code remove} operation, and the saved value is returned.  If the
+     * iteration terminates without finding such an entry, {@code null} is
      * returned.  Note that this implementation requires linear time in the
      * size of the map; many implementations will override this method.
      *
      * <p>Note that this implementation throws an
-     * <tt>UnsupportedOperationException</tt> if the <tt>entrySet</tt>
-     * iterator does not support the <tt>remove</tt> method and this map
+     * {@code UnsupportedOperationException} if the {@code entrySet}
+     * iterator does not support the {@code remove} method and this map
      * contains a mapping for the specified key.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
@@ -264,12 +264,12 @@
      *
      * @implSpec
      * This implementation iterates over the specified map's
-     * <tt>entrySet()</tt> collection, and calls this map's <tt>put</tt>
+     * {@code entrySet()} collection, and calls this map's {@code put}
      * operation once for each entry returned by the iteration.
      *
      * <p>Note that this implementation throws an
-     * <tt>UnsupportedOperationException</tt> if this map does not support
-     * the <tt>put</tt> operation and the specified map is nonempty.
+     * {@code UnsupportedOperationException} if this map does not support
+     * the {@code put} operation and the specified map is nonempty.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
@@ -285,11 +285,11 @@
      * {@inheritDoc}
      *
      * @implSpec
-     * This implementation calls <tt>entrySet().clear()</tt>.
+     * This implementation calls {@code entrySet().clear()}.
      *
      * <p>Note that this implementation throws an
-     * <tt>UnsupportedOperationException</tt> if the <tt>entrySet</tt>
-     * does not support the <tt>clear</tt> operation.
+     * {@code UnsupportedOperationException} if the {@code entrySet}
+     * does not support the {@code clear} operation.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      */
@@ -333,10 +333,10 @@
      * @implSpec
      * This implementation returns a set that subclasses {@link AbstractSet}.
      * The subclass's iterator method returns a "wrapper object" over this
-     * map's <tt>entrySet()</tt> iterator.  The <tt>size</tt> method
-     * delegates to this map's <tt>size</tt> method and the
-     * <tt>contains</tt> method delegates to this map's
-     * <tt>containsKey</tt> method.
+     * map's {@code entrySet()} iterator.  The {@code size} method
+     * delegates to this map's {@code size} method and the
+     * {@code contains} method delegates to this map's
+     * {@code containsKey} method.
      *
      * <p>The set is created the first time this method is called,
      * and returned in response to all subsequent calls.  No synchronization
@@ -392,10 +392,10 @@
      * @implSpec
      * This implementation returns a collection that subclasses {@link
      * AbstractCollection}.  The subclass's iterator method returns a
-     * "wrapper object" over this map's <tt>entrySet()</tt> iterator.
-     * The <tt>size</tt> method delegates to this map's <tt>size</tt>
-     * method and the <tt>contains</tt> method delegates to this map's
-     * <tt>containsValue</tt> method.
+     * "wrapper object" over this map's {@code entrySet()} iterator.
+     * The {@code size} method delegates to this map's {@code size}
+     * method and the {@code contains} method delegates to this map's
+     * {@code containsValue} method.
      *
      * <p>The collection is created the first time this method is called, and
      * returned in response to all subsequent calls.  No synchronization is
@@ -452,25 +452,25 @@
 
     /**
      * Compares the specified object with this map for equality.  Returns
-     * <tt>true</tt> 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 ensures that the
-     * <tt>equals</tt> method works properly across different implementations
-     * of the <tt>Map</tt> interface.
+     * {@code true} if the given object is also a map and the two maps
+     * represent the same mappings.  More formally, two maps {@code m1} and
+     * {@code m2} represent the same mappings if
+     * {@code m1.entrySet().equals(m2.entrySet())}.  This ensures that the
+     * {@code equals} method works properly across different implementations
+     * of the {@code Map} interface.
      *
      * @implSpec
      * This implementation first checks if the specified object is this map;
-     * if so it returns <tt>true</tt>.  Then, it checks if the specified
+     * if so it returns {@code true}.  Then, it checks if the specified
      * object is a map whose size is identical to the size of this map; if
-     * not, it returns <tt>false</tt>.  If so, it iterates over this map's
-     * <tt>entrySet</tt> collection, and checks that the specified map
+     * not, it returns {@code false}.  If so, it iterates over this map's
+     * {@code entrySet} collection, and checks that the specified map
      * contains each mapping that this map contains.  If the specified map
-     * fails to contain such a mapping, <tt>false</tt> is returned.  If the
-     * iteration completes, <tt>true</tt> is returned.
+     * fails to contain such a mapping, {@code false} is returned.  If the
+     * iteration completes, {@code true} is returned.
      *
      * @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)
@@ -483,13 +483,11 @@
             return false;
 
         try {
-            Iterator<Entry<K,V>> i = entrySet().iterator();
-            while (i.hasNext()) {
-                Entry<K,V> e = i.next();
+            for (Entry<K, V> e : entrySet()) {
                 K key = e.getKey();
                 V value = e.getValue();
                 if (value == null) {
-                    if (!(m.get(key)==null && m.containsKey(key)))
+                    if (!(m.get(key) == null && m.containsKey(key)))
                         return false;
                 } else {
                     if (!value.equals(m.get(key)))
@@ -508,13 +506,13 @@
     /**
      * Returns the hash code value for this map.  The hash code of a map is
      * defined to be the sum of the hash codes of each entry in the map's
-     * <tt>entrySet()</tt> view.  This ensures that <tt>m1.equals(m2)</tt>
-     * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two maps
-     * <tt>m1</tt> and <tt>m2</tt>, as required by the general contract of
+     * {@code entrySet()} view.  This ensures that {@code m1.equals(m2)}
+     * implies that {@code m1.hashCode()==m2.hashCode()} for any two maps
+     * {@code m1} and {@code m2}, as required by the general contract of
      * {@link Object#hashCode}.
      *
      * @implSpec
-     * This implementation iterates over <tt>entrySet()</tt>, calling
+     * This implementation iterates over {@code entrySet()}, calling
      * {@link Map.Entry#hashCode hashCode()} on each element (entry) in the
      * set, and adding up the results.
      *
@@ -525,19 +523,18 @@
      */
     public int hashCode() {
         int h = 0;
-        Iterator<Entry<K,V>> i = entrySet().iterator();
-        while (i.hasNext())
-            h += i.next().hashCode();
+        for (Entry<K, V> entry : entrySet())
+            h += entry.hashCode();
         return h;
     }
 
     /**
      * Returns a string representation of this map.  The string representation
      * consists of a list of key-value mappings in the order returned by the
-     * map's <tt>entrySet</tt> view's iterator, enclosed in braces
-     * (<tt>"{}"</tt>).  Adjacent mappings are separated by the characters
-     * <tt>", "</tt> (comma and space).  Each key-value mapping is rendered as
-     * the key followed by an equals sign (<tt>"="</tt>) followed by the
+     * map's {@code entrySet} view's iterator, enclosed in braces
+     * ({@code "{}"}).  Adjacent mappings are separated by the characters
+     * {@code ", "} (comma and space).  Each key-value mapping is rendered as
+     * the key followed by an equals sign ({@code "="}) followed by the
      * associated value.  Keys and values are converted to strings as by
      * {@link String#valueOf(Object)}.
      *
@@ -564,7 +561,7 @@
     }
 
     /**
-     * Returns a shallow copy of this <tt>AbstractMap</tt> instance: the keys
+     * Returns a shallow copy of this {@code AbstractMap} instance: the keys
      * and values themselves are not cloned.
      *
      * @return a shallow copy of this map
@@ -596,11 +593,11 @@
 
     /**
      * An Entry maintaining a key and a value.  The value may be
-     * changed using the <tt>setValue</tt> method.  This class
+     * changed using the {@code setValue} method.  This class
      * facilitates the process of building custom map
      * implementations. For example, it may be convenient to return
-     * arrays of <tt>SimpleEntry</tt> instances in method
-     * <tt>Map.entrySet().toArray</tt>.
+     * arrays of {@code SimpleEntry} instances in method
+     * {@code Map.entrySet().toArray}.
      *
      * @since 1.6
      */
@@ -715,7 +712,7 @@
         /**
          * Returns a String representation of this map entry.  This
          * implementation returns the string representation of this
-         * entry's key followed by the equals character ("<tt>=</tt>")
+         * entry's key followed by the equals character ("{@code =}")
          * followed by the string representation of this entry's value.
          *
          * @return a String representation of this map entry
@@ -728,7 +725,7 @@
 
     /**
      * An Entry maintaining an immutable key and value.  This class
-     * does not support method <tt>setValue</tt>.  This class may be
+     * does not support method {@code setValue}.  This class may be
      * convenient in methods that return thread-safe snapshots of
      * key-value mappings.
      *
@@ -786,7 +783,7 @@
         /**
          * Replaces the value corresponding to this entry with the specified
          * value (optional operation).  This implementation simply throws
-         * <tt>UnsupportedOperationException</tt>, as this class implements
+         * {@code UnsupportedOperationException}, as this class implements
          * an <i>immutable</i> map entry.
          *
          * @param value new value to be stored in this entry
@@ -846,7 +843,7 @@
         /**
          * Returns a String representation of this map entry.  This
          * implementation returns the string representation of this
-         * entry's key followed by the equals character ("<tt>=</tt>")
+         * entry's key followed by the equals character ("{@code =}")
          * followed by the string representation of this entry's value.
          *
          * @return a String representation of this map entry
diff --git a/ojluni/src/main/java/java/util/AbstractSequentialList.java b/ojluni/src/main/java/java/util/AbstractSequentialList.java
index 37292df..91ce740 100644
--- a/ojluni/src/main/java/java/util/AbstractSequentialList.java
+++ b/ojluni/src/main/java/java/util/AbstractSequentialList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,35 +26,35 @@
 package java.util;
 
 /**
- * This class provides a skeletal implementation of the <tt>List</tt>
+ * This class provides a skeletal implementation of the {@code List}
  * interface to minimize the effort required to implement this interface
  * backed by a "sequential access" data store (such as a linked list).  For
- * random access data (such as an array), <tt>AbstractList</tt> should be used
+ * random access data (such as an array), {@code AbstractList} should be used
  * in preference to this class.<p>
  *
- * This class is the opposite of the <tt>AbstractList</tt> class in the sense
- * that it implements the "random access" methods (<tt>get(int index)</tt>,
- * <tt>set(int index, E element)</tt>, <tt>add(int index, E element)</tt> and
- * <tt>remove(int index)</tt>) on top of the list's list iterator, instead of
+ * This class is the opposite of the {@code AbstractList} class in the sense
+ * that it implements the "random access" methods ({@code get(int index)},
+ * {@code set(int index, E element)}, {@code add(int index, E element)} and
+ * {@code remove(int index)}) on top of the list's list iterator, instead of
  * the other way around.<p>
  *
  * To implement a list the programmer needs only to extend this class and
- * provide implementations for the <tt>listIterator</tt> and <tt>size</tt>
+ * provide implementations for the {@code listIterator} and {@code size}
  * methods.  For an unmodifiable list, the programmer need only implement the
- * list iterator's <tt>hasNext</tt>, <tt>next</tt>, <tt>hasPrevious</tt>,
- * <tt>previous</tt> and <tt>index</tt> methods.<p>
+ * list iterator's {@code hasNext}, {@code next}, {@code hasPrevious},
+ * {@code previous} and {@code index} methods.<p>
  *
  * For a modifiable list the programmer should additionally implement the list
- * iterator's <tt>set</tt> method.  For a variable-size list the programmer
- * should additionally implement the list iterator's <tt>remove</tt> and
- * <tt>add</tt> methods.<p>
+ * iterator's {@code set} method.  For a variable-size list the programmer
+ * should additionally implement the list iterator's {@code remove} and
+ * {@code add} methods.<p>
  *
  * The programmer should generally provide a void (no argument) and collection
- * constructor, as per the recommendation in the <tt>Collection</tt> interface
+ * constructor, as per the recommendation in the {@code Collection} interface
  * specification.<p>
  *
  * This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
@@ -78,8 +78,8 @@
      * Returns the element at the specified position in this list.
      *
      * <p>This implementation first gets a list iterator pointing to the
-     * indexed element (with <tt>listIterator(index)</tt>).  Then, it gets
-     * the element using <tt>ListIterator.next</tt> and returns it.
+     * indexed element (with {@code listIterator(index)}).  Then, it gets
+     * the element using {@code ListIterator.next} and returns it.
      *
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
@@ -96,13 +96,13 @@
      * specified element (optional operation).
      *
      * <p>This implementation first gets a list iterator pointing to the
-     * indexed element (with <tt>listIterator(index)</tt>).  Then, it gets
-     * the current element using <tt>ListIterator.next</tt> and replaces it
-     * with <tt>ListIterator.set</tt>.
+     * indexed element (with {@code listIterator(index)}).  Then, it gets
+     * the current element using {@code ListIterator.next} and replaces it
+     * with {@code ListIterator.set}.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the list iterator does not
-     * implement the <tt>set</tt> operation.
+     * {@code UnsupportedOperationException} if the list iterator does not
+     * implement the {@code set} operation.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
@@ -128,12 +128,12 @@
      * indices).
      *
      * <p>This implementation first gets a list iterator pointing to the
-     * indexed element (with <tt>listIterator(index)</tt>).  Then, it
-     * inserts the specified element with <tt>ListIterator.add</tt>.
+     * indexed element (with {@code listIterator(index)}).  Then, it
+     * inserts the specified element with {@code ListIterator.add}.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the list iterator does not
-     * implement the <tt>add</tt> operation.
+     * {@code UnsupportedOperationException} if the list iterator does not
+     * implement the {@code add} operation.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
@@ -156,12 +156,12 @@
      * list.
      *
      * <p>This implementation first gets a list iterator pointing to the
-     * indexed element (with <tt>listIterator(index)</tt>).  Then, it removes
-     * the element with <tt>ListIterator.remove</tt>.
+     * indexed element (with {@code listIterator(index)}).  Then, it removes
+     * the element with {@code ListIterator.remove}.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the list iterator does not
-     * implement the <tt>remove</tt> operation.
+     * {@code UnsupportedOperationException} if the list iterator does not
+     * implement the {@code remove} operation.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws IndexOutOfBoundsException     {@inheritDoc}
@@ -193,14 +193,14 @@
      *
      * <p>This implementation gets an iterator over the specified collection and
      * a list iterator over this list pointing to the indexed element (with
-     * <tt>listIterator(index)</tt>).  Then, it iterates over the specified
+     * {@code listIterator(index)}).  Then, it iterates over the specified
      * collection, inserting the elements obtained from the iterator into this
-     * list, one at a time, using <tt>ListIterator.add</tt> followed by
-     * <tt>ListIterator.next</tt> (to skip over the added element).
+     * list, one at a time, using {@code ListIterator.add} followed by
+     * {@code ListIterator.next} (to skip over the added element).
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the list iterator returned by
-     * the <tt>listIterator</tt> method does not implement the <tt>add</tt>
+     * {@code UnsupportedOperationException} if the list iterator returned by
+     * the {@code listIterator} method does not implement the {@code add}
      * operation.
      *
      * @throws UnsupportedOperationException {@inheritDoc}
@@ -213,9 +213,8 @@
         try {
             boolean modified = false;
             ListIterator<E> e1 = listIterator(index);
-            Iterator<? extends E> e2 = c.iterator();
-            while (e2.hasNext()) {
-                e1.add(e2.next());
+            for (E e : c) {
+                e1.add(e);
                 modified = true;
             }
             return modified;
@@ -244,7 +243,7 @@
      * sequence).
      *
      * @param  index index of first element to be returned from the list
-     *         iterator (by a call to the <code>next</code> method)
+     *         iterator (by a call to the {@code next} method)
      * @return a list iterator over the elements in this list (in proper
      *         sequence)
      * @throws IndexOutOfBoundsException {@inheritDoc}
diff --git a/ojluni/src/main/java/java/util/AbstractSet.java b/ojluni/src/main/java/java/util/AbstractSet.java
index 620f672..80d4c5e 100644
--- a/ojluni/src/main/java/java/util/AbstractSet.java
+++ b/ojluni/src/main/java/java/util/AbstractSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,23 +26,23 @@
 package java.util;
 
 /**
- * This class provides a skeletal implementation of the <tt>Set</tt>
+ * This class provides a skeletal implementation of the {@code Set}
  * interface to minimize the effort required to implement this
  * interface. <p>
  *
  * The process of implementing a set by extending this class is identical
  * to that of implementing a Collection by extending AbstractCollection,
  * except that all of the methods and constructors in subclasses of this
- * class must obey the additional constraints imposed by the <tt>Set</tt>
+ * class must obey the additional constraints imposed by the {@code Set}
  * interface (for instance, the add method must not permit addition of
  * multiple instances of an object to a set).<p>
  *
  * Note that this class does not override any of the implementations from
- * the <tt>AbstractCollection</tt> class.  It merely adds implementations
- * for <tt>equals</tt> and <tt>hashCode</tt>.<p>
+ * the {@code AbstractCollection} class.  It merely adds implementations
+ * for {@code equals} and {@code hashCode}.<p>
  *
  * This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <E> the type of elements maintained by this set
@@ -67,20 +67,20 @@
 
     /**
      * Compares the specified object with this set for equality.  Returns
-     * <tt>true</tt> if the given object is also a set, the two sets have
+     * {@code true} if the given object is also a set, the two sets have
      * the same size, and every member of the given set is contained in
-     * this set.  This ensures that the <tt>equals</tt> method works
-     * properly across different implementations of the <tt>Set</tt>
+     * this set.  This ensures that the {@code equals} method works
+     * properly across different implementations of the {@code Set}
      * interface.<p>
      *
      * This implementation first checks if the specified object is this
-     * set; if so it returns <tt>true</tt>.  Then, it checks if the
+     * set; if so it returns {@code true}.  Then, it checks if the
      * specified object is a set whose size is identical to the size of
      * this set; if not, it returns false.  If so, it returns
-     * <tt>containsAll((Collection) o)</tt>.
+     * {@code containsAll((Collection) o)}.
      *
      * @param o 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) {
         if (o == this)
@@ -93,9 +93,7 @@
             return false;
         try {
             return containsAll(c);
-        } catch (ClassCastException unused)   {
-            return false;
-        } catch (NullPointerException unused) {
+        } catch (ClassCastException | NullPointerException unused) {
             return false;
         }
     }
@@ -103,14 +101,14 @@
     /**
      * Returns the hash code value for this set.  The hash code of a set is
      * defined to be the sum of the hash codes of the elements in the set,
-     * where the hash code of a <tt>null</tt> element is defined to be zero.
-     * This ensures that <tt>s1.equals(s2)</tt> implies that
-     * <tt>s1.hashCode()==s2.hashCode()</tt> for any two sets <tt>s1</tt>
-     * and <tt>s2</tt>, as required by the general contract of
+     * where the hash code of a {@code null} element is defined to be zero.
+     * This ensures that {@code s1.equals(s2)} implies that
+     * {@code s1.hashCode()==s2.hashCode()} for any two sets {@code s1}
+     * and {@code s2}, as required by the general contract of
      * {@link Object#hashCode}.
      *
      * <p>This implementation iterates over the set, calling the
-     * <tt>hashCode</tt> method on each element in the set, and adding up
+     * {@code hashCode} method on each element in the set, and adding up
      * the results.
      *
      * @return the hash code value for this set
@@ -136,24 +134,24 @@
      * the two sets.
      *
      * <p>This implementation determines which is the smaller of this set
-     * and the specified collection, by invoking the <tt>size</tt>
+     * and the specified collection, by invoking the {@code size}
      * method on each.  If this set has fewer elements, then the
      * implementation iterates over this set, checking each element
      * returned by the iterator in turn to see if it is contained in
      * the specified collection.  If it is so contained, it is removed
-     * from this set with the iterator's <tt>remove</tt> method.  If
+     * from this set with the iterator's {@code remove} method.  If
      * the specified collection has fewer elements, then the
      * implementation iterates over the specified collection, removing
      * from this set each element returned by the iterator, using this
-     * set's <tt>remove</tt> method.
+     * set's {@code remove} method.
      *
      * <p>Note that this implementation will throw an
-     * <tt>UnsupportedOperationException</tt> if the iterator returned by the
-     * <tt>iterator</tt> method does not implement the <tt>remove</tt> method.
+     * {@code UnsupportedOperationException} if the iterator returned by the
+     * {@code iterator} method does not implement the {@code remove} method.
      *
      * @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
-     * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation
+     * @return {@code true} if this set changed as a result of the call
+     * @throws UnsupportedOperationException if the {@code removeAll} operation
      *         is not supported by this set
      * @throws ClassCastException if the class of an element of this set
      *         is incompatible with the specified collection
@@ -170,8 +168,8 @@
         boolean modified = false;
 
         if (size() > c.size()) {
-            for (Iterator<?> i = c.iterator(); i.hasNext(); )
-                modified |= remove(i.next());
+            for (Object e : c)
+                modified |= remove(e);
         } else {
             for (Iterator<?> i = iterator(); i.hasNext(); ) {
                 if (c.contains(i.next())) {
diff --git a/ojluni/src/main/java/java/util/ArrayList.java b/ojluni/src/main/java/java/util/ArrayList.java
index 02f9479..20c623a 100644
--- a/ojluni/src/main/java/java/util/ArrayList.java
+++ b/ojluni/src/main/java/java/util/ArrayList.java
@@ -92,7 +92,7 @@
  * should be used only to detect bugs.</i>
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java
index d0a218a..51b84ec 100644
--- a/ojluni/src/main/java/java/util/Arrays.java
+++ b/ojluni/src/main/java/java/util/Arrays.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,9 @@
 
 package java.util;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.util.ArraysSupport;
+
 import java.lang.reflect.Array;
 import java.util.concurrent.ForkJoinPool;
 import java.util.function.BinaryOperator;
@@ -53,7 +56,7 @@
  * if the specified array reference is null, except where noted.
  *
  * <p>The documentation for the methods contained in this class includes
- * briefs description of the <i>implementations</i>. Such descriptions should
+ * brief descriptions of the <i>implementations</i>. Such descriptions should
  * be regarded as <i>implementation notes</i>, rather than parts of the
  * <i>specification</i>. Implementors should feel free to substitute other
  * algorithms, so long as the specification itself is adhered to. (For
@@ -61,7 +64,7 @@
  * a MergeSort, but it does have to be <i>stable</i>.)
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author Josh Bloch
@@ -111,7 +114,7 @@
      * Checks that {@code fromIndex} and {@code toIndex} are in
      * the range and throws an exception if they aren't.
      */
-    private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
+    static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
         if (fromIndex > toIndex) {
             throw new IllegalArgumentException(
                     "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
@@ -1007,7 +1010,7 @@
             (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
             TimSort.sort(a, 0, n, NaturalOrder.INSTANCE, null, 0, 0);
         else
-            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+            new ArraysParallelSortHelpers.FJObject.Sorter<>
                 (null, a,
                  (T[])Array.newInstance(a.getClass().getComponentType(), n),
                  0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
@@ -1066,7 +1069,7 @@
             (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
             TimSort.sort(a, fromIndex, toIndex, NaturalOrder.INSTANCE, null, 0, 0);
         else
-            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+            new ArraysParallelSortHelpers.FJObject.Sorter<>
                 (null, a,
                  (T[])Array.newInstance(a.getClass().getComponentType(), n),
                  fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
@@ -1115,7 +1118,7 @@
             (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
             TimSort.sort(a, 0, n, cmp, null, 0, 0);
         else
-            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+            new ArraysParallelSortHelpers.FJObject.Sorter<>
                 (null, a,
                  (T[])Array.newInstance(a.getClass().getComponentType(), n),
                  0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
@@ -1176,7 +1179,7 @@
             (p = ForkJoinPool.getCommonPoolParallelism()) == 1)
             TimSort.sort(a, fromIndex, toIndex, cmp, null, 0, 0);
         else
-            new ArraysParallelSortHelpers.FJObject.Sorter<T>
+            new ArraysParallelSortHelpers.FJObject.Sorter<>
                 (null, a,
                  (T[])Array.newInstance(a.getClass().getComponentType(), n),
                  fromIndex, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
@@ -1213,7 +1216,7 @@
      *
      * <p>The implementation takes equal advantage of ascending and
      * descending order in its input array, and can take advantage of
-     * ascending and descending order in different parts of the the same
+     * ascending and descending order in different parts of the same
      * input array.  It is well-suited to merging two or more sorted arrays:
      * simply concatenate the arrays and sort the resulting array.
      *
@@ -1269,7 +1272,7 @@
      *
      * <p>The implementation takes equal advantage of ascending and
      * descending order in its input array, and can take advantage of
-     * ascending and descending order in different parts of the the same
+     * ascending and descending order in different parts of the same
      * input array.  It is well-suited to merging two or more sorted arrays:
      * simply concatenate the arrays and sort the resulting array.
      *
@@ -1392,7 +1395,7 @@
      *
      * <p>The implementation takes equal advantage of ascending and
      * descending order in its input array, and can take advantage of
-     * ascending and descending order in different parts of the the same
+     * ascending and descending order in different parts of the same
      * input array.  It is well-suited to merging two or more sorted arrays:
      * simply concatenate the arrays and sort the resulting array.
      *
@@ -1452,7 +1455,7 @@
      *
      * <p>The implementation takes equal advantage of ascending and
      * descending order in its input array, and can take advantage of
-     * ascending and descending order in different parts of the the same
+     * ascending and descending order in different parts of the same
      * input array.  It is well-suited to merging two or more sorted arrays:
      * simply concatenate the arrays and sort the resulting array.
      *
@@ -1696,10 +1699,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -1726,11 +1729,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -1777,10 +1780,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -1807,11 +1810,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -1858,10 +1861,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -1888,11 +1891,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -1939,10 +1942,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -1969,11 +1972,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2020,10 +2023,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2050,11 +2053,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2102,10 +2105,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2133,11 +2136,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2193,10 +2196,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key. Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2224,11 +2227,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key. Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2290,10 +2293,10 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2328,11 +2331,11 @@
      * @param key the value to be searched for
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2388,13 +2391,13 @@
      * @param a the array to be searched
      * @param key the value to be searched for
      * @param c the comparator by which the array is ordered.  A
-     *        <tt>null</tt> value indicates that the elements'
+     *        {@code null} value indicates that the elements'
      *        {@linkplain Comparable natural ordering} should be used.
      * @return index of the search key, if it is contained in the array;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
-     *         element greater than the key, or <tt>a.length</tt> if all
+     *         element greater than the key, or {@code a.length} if all
      *         elements in the array are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2427,15 +2430,15 @@
      * @param toIndex the index of the last element (exclusive) to be searched
      * @param key the value to be searched for
      * @param c the comparator by which the array is ordered.  A
-     *        <tt>null</tt> value indicates that the elements'
+     *        {@code null} value indicates that the elements'
      *        {@linkplain Comparable natural ordering} should be used.
      * @return index of the search key, if it is contained in the array
      *         within the specified range;
-     *         otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>.  The
+     *         otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The
      *         <i>insertion point</i> is defined as the point at which the
      *         key would be inserted into the array: the index of the first
      *         element in the range greater than the key,
-     *         or <tt>toIndex</tt> if all
+     *         or {@code toIndex} if all
      *         elements in the range are less than the specified key.  Note
      *         that this guarantees that the return value will be &gt;= 0 if
      *         and only if the key is found.
@@ -2481,16 +2484,16 @@
     // Equality Testing
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of longs are
+     * Returns {@code true} if the two specified arrays of longs are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      */
     public static boolean equals(long[] a, long[] a2) {
         if (a==a2)
@@ -2502,24 +2505,67 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (a[i] != a2[i])
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of ints are
+     * Returns true if the two specified arrays of longs, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static boolean equals(long[] a, int aFromIndex, int aToIndex,
+                                 long[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex,
+                                      aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of ints are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      */
     public static boolean equals(int[] a, int[] a2) {
         if (a==a2)
@@ -2531,24 +2577,67 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (a[i] != a2[i])
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of shorts are
+     * Returns true if the two specified arrays of ints, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static boolean equals(int[] a, int aFromIndex, int aToIndex,
+                                 int[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex,
+                                      aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of shorts are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      */
     public static boolean equals(short[] a, short a2[]) {
         if (a==a2)
@@ -2560,25 +2649,69 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (a[i] != a2[i])
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of chars are
+     * Returns true if the two specified arrays of shorts, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static boolean equals(short[] a, int aFromIndex, int aToIndex,
+                                 short[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex,
+                                      aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of chars are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      */
+    @HotSpotIntrinsicCandidate
     public static boolean equals(char[] a, char[] a2) {
         if (a==a2)
             return true;
@@ -2589,25 +2722,69 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (a[i] != a2[i])
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of bytes are
+     * Returns true if the two specified arrays of chars, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static boolean equals(char[] a, int aFromIndex, int aToIndex,
+                                 char[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex,
+                                      aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of bytes are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      */
+    @HotSpotIntrinsicCandidate
     public static boolean equals(byte[] a, byte[] a2) {
         if (a==a2)
             return true;
@@ -2618,24 +2795,67 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (a[i] != a2[i])
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of booleans are
+     * Returns true if the two specified arrays of bytes, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static boolean equals(byte[] a, int aFromIndex, int aToIndex,
+                                 byte[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex,
+                                      aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of booleans are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      */
     public static boolean equals(boolean[] a, boolean[] a2) {
         if (a==a2)
@@ -2647,29 +2867,72 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (a[i] != a2[i])
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of doubles are
+     * Returns true if the two specified arrays of booleans, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static boolean equals(boolean[] a, int aFromIndex, int aToIndex,
+                                 boolean[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex,
+                                      aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of doubles are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
-     * Two doubles <tt>d1</tt> and <tt>d2</tt> are considered equal if:
-     * <pre>    <tt>new Double(d1).equals(new Double(d2))</tt></pre>
-     * (Unlike the <tt>==</tt> operator, this method considers
-     * <tt>NaN</tt> equals to itself, and 0.0d unequal to -0.0d.)
+     * Two doubles {@code d1} and {@code d2} are considered equal if:
+     * <pre>    {@code new Double(d1).equals(new Double(d2))}</pre>
+     * (Unlike the {@code ==} operator, this method considers
+     * {@code NaN} equals to itself, and 0.0d unequal to -0.0d.)
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      * @see Double#equals(Object)
      */
     public static boolean equals(double[] a, double[] a2) {
@@ -2682,29 +2945,77 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (Double.doubleToLongBits(a[i])!=Double.doubleToLongBits(a2[i]))
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of floats are
+     * Returns true if the two specified arrays of doubles, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * <p>Two doubles {@code d1} and {@code d2} are considered equal if:
+     * <pre>    {@code new Double(d1).equals(new Double(d2))}</pre>
+     * (Unlike the {@code ==} operator, this method considers
+     * {@code NaN} equals to itself, and 0.0d unequal to -0.0d.)
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @see Double#equals(Object)
+     * @since 9
+     */
+    public static boolean equals(double[] a, int aFromIndex, int aToIndex,
+                                 double[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex, aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of floats are
      * <i>equal</i> to one another.  Two arrays are considered equal if both
      * arrays contain the same number of elements, and all corresponding pairs
      * of elements in the two arrays are equal.  In other words, two arrays
      * are equal if they contain the same elements in the same order.  Also,
-     * two array references are considered equal if both are <tt>null</tt>.<p>
+     * two array references are considered equal if both are {@code null}.
      *
-     * Two floats <tt>f1</tt> and <tt>f2</tt> are considered equal if:
-     * <pre>    <tt>new Float(f1).equals(new Float(f2))</tt></pre>
-     * (Unlike the <tt>==</tt> operator, this method considers
-     * <tt>NaN</tt> equals to itself, and 0.0f unequal to -0.0f.)
+     * Two floats {@code f1} and {@code f2} are considered equal if:
+     * <pre>    {@code new Float(f1).equals(new Float(f2))}</pre>
+     * (Unlike the {@code ==} operator, this method considers
+     * {@code NaN} equals to itself, and 0.0f unequal to -0.0f.)
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      * @see Float#equals(Object)
      */
     public static boolean equals(float[] a, float[] a2) {
@@ -2717,26 +3028,75 @@
         if (a2.length != length)
             return false;
 
-        for (int i=0; i<length; i++)
-            if (Float.floatToIntBits(a[i])!=Float.floatToIntBits(a2[i]))
-                return false;
-
-        return true;
+        return ArraysSupport.mismatch(a, a2, length) < 0;
     }
 
     /**
-     * Returns <tt>true</tt> if the two specified arrays of Objects are
+     * Returns true if the two specified arrays of floats, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * <p>Two floats {@code f1} and {@code f2} are considered equal if:
+     * <pre>    {@code new Float(f1).equals(new Float(f2))}</pre>
+     * (Unlike the {@code ==} operator, this method considers
+     * {@code NaN} equals to itself, and 0.0f unequal to -0.0f.)
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @see Float#equals(Object)
+     * @since 9
+     */
+    public static boolean equals(float[] a, int aFromIndex, int aToIndex,
+                                 float[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        return ArraysSupport.mismatch(a, aFromIndex,
+                                      b, bFromIndex, aLength) < 0;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of Objects are
      * <i>equal</i> to one another.  The two arrays are considered equal if
      * both arrays contain the same number of elements, and all corresponding
-     * pairs of elements in the two arrays are equal.  Two objects <tt>e1</tt>
-     * and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null
-     * : e1.equals(e2))</tt>.  In other words, the two arrays are equal if
+     * pairs of elements in the two arrays are equal.  Two objects {@code e1}
+     * and {@code e2} are considered <i>equal</i> if
+     * {@code Objects.equals(e1, e2)}.
+     * In other words, the two arrays are equal if
      * they contain the same elements in the same order.  Also, two array
-     * references are considered equal if both are <tt>null</tt>.<p>
+     * references are considered equal if both are {@code null}.
      *
      * @param a one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      */
     public static boolean equals(Object[] a, Object[] a2) {
         if (a==a2)
@@ -2749,9 +3109,157 @@
             return false;
 
         for (int i=0; i<length; i++) {
-            Object o1 = a[i];
-            Object o2 = a2[i];
-            if (!(o1==null ? o2==null : o1.equals(o2)))
+            if (!Objects.equals(a[i], a2[i]))
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns true if the two specified arrays of Objects, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * <p>Two objects {@code e1} and {@code e2} are considered <i>equal</i> if
+     * {@code Objects.equals(e1, e2)}.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static boolean equals(Object[] a, int aFromIndex, int aToIndex,
+                                 Object[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        for (int i = 0; i < aLength; i++) {
+            if (!Objects.equals(a[aFromIndex++], b[bFromIndex++]))
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns {@code true} if the two specified arrays of Objects are
+     * <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if both arrays contain the same number
+     * of elements, and all corresponding pairs of elements in the two arrays
+     * are equal.  In other words, the two arrays are equal if they contain the
+     * same elements in the same order.  Also, two array references are
+     * considered equal if both are {@code null}.
+     *
+     * <p>Two objects {@code e1} and {@code e2} are considered <i>equal</i> if,
+     * given the specified comparator, {@code cmp.compare(e1, e2) == 0}.
+     *
+     * @param a one array to be tested for equality
+     * @param a2 the other array to be tested for equality
+     * @param cmp the comparator to compare array elements
+     * @param <T> the type of array elements
+     * @return {@code true} if the two arrays are equal
+     * @throws NullPointerException if the comparator is {@code null}
+     * @since 9
+     */
+    public static <T> boolean equals(T[] a, T[] a2, Comparator<? super T> cmp) {
+        Objects.requireNonNull(cmp);
+        if (a==a2)
+            return true;
+        if (a==null || a2==null)
+            return false;
+
+        int length = a.length;
+        if (a2.length != length)
+            return false;
+
+        for (int i=0; i<length; i++) {
+            if (cmp.compare(a[i], a2[i]) != 0)
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns true if the two specified arrays of Objects, over the specified
+     * ranges, are <i>equal</i> to one another.
+     *
+     * <p>Two arrays are considered equal if the number of elements covered by
+     * each range is the same, and all corresponding pairs of elements over the
+     * specified ranges in the two arrays are equal.  In other words, two arrays
+     * are equal if they contain, over the specified ranges, the same elements
+     * in the same order.
+     *
+     * <p>Two objects {@code e1} and {@code e2} are considered <i>equal</i> if,
+     * given the specified comparator, {@code cmp.compare(e1, e2) == 0}.
+     *
+     * @param a the first array to be tested for equality
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested fro equality
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @param cmp the comparator to compare array elements
+     * @param <T> the type of array elements
+     * @return {@code true} if the two arrays, over the specified ranges, are
+     *         equal
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array or the comparator is {@code null}
+     * @since 9
+     */
+    public static <T> boolean equals(T[] a, int aFromIndex, int aToIndex,
+                                     T[] b, int bFromIndex, int bToIndex,
+                                     Comparator<? super T> cmp) {
+        Objects.requireNonNull(cmp);
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        for (int i = 0; i < aLength; i++) {
+            if (cmp.compare(a[aFromIndex++], b[bFromIndex++]) != 0)
                 return false;
         }
 
@@ -2775,8 +3283,8 @@
     /**
      * Assigns the specified long value to each element of the specified
      * range of the specified array of longs.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -2785,9 +3293,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(long[] a, int fromIndex, int toIndex, long val) {
         rangeCheck(a.length, fromIndex, toIndex);
@@ -2810,8 +3318,8 @@
     /**
      * Assigns the specified int value to each element of the specified
      * range of the specified array of ints.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -2820,9 +3328,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(int[] a, int fromIndex, int toIndex, int val) {
         rangeCheck(a.length, fromIndex, toIndex);
@@ -2845,8 +3353,8 @@
     /**
      * Assigns the specified short value to each element of the specified
      * range of the specified array of shorts.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -2855,9 +3363,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(short[] a, int fromIndex, int toIndex, short val) {
         rangeCheck(a.length, fromIndex, toIndex);
@@ -2880,8 +3388,8 @@
     /**
      * Assigns the specified char value to each element of the specified
      * range of the specified array of chars.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -2890,9 +3398,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(char[] a, int fromIndex, int toIndex, char val) {
         rangeCheck(a.length, fromIndex, toIndex);
@@ -2915,8 +3423,8 @@
     /**
      * Assigns the specified byte value to each element of the specified
      * range of the specified array of bytes.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -2925,9 +3433,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(byte[] a, int fromIndex, int toIndex, byte val) {
         rangeCheck(a.length, fromIndex, toIndex);
@@ -2950,8 +3458,8 @@
     /**
      * Assigns the specified boolean value to each element of the specified
      * range of the specified array of booleans.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -2960,9 +3468,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(boolean[] a, int fromIndex, int toIndex,
                             boolean val) {
@@ -2986,8 +3494,8 @@
     /**
      * Assigns the specified double value to each element of the specified
      * range of the specified array of doubles.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -2996,9 +3504,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(double[] a, int fromIndex, int toIndex,double val){
         rangeCheck(a.length, fromIndex, toIndex);
@@ -3021,8 +3529,8 @@
     /**
      * Assigns the specified float value to each element of the specified
      * range of the specified array of floats.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -3031,9 +3539,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static void fill(float[] a, int fromIndex, int toIndex, float val) {
         rangeCheck(a.length, fromIndex, toIndex);
@@ -3058,8 +3566,8 @@
     /**
      * Assigns the specified Object reference to each element of the specified
      * range of the specified array of Objects.  The range to be filled
-     * extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be filled is empty.)
      *
      * @param a the array to be filled
@@ -3068,9 +3576,9 @@
      * @param toIndex the index of the last element (exclusive) to be
      *        filled with the specified value
      * @param val the value to be stored in all elements of the array
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex}
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      * @throws ArrayStoreException if the specified value is not of a
      *         runtime type that can be stored in the specified array
      */
@@ -3087,7 +3595,7 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>null</tt>.
+     * copy but not the original, the copy will contain {@code null}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      * The resulting array is of exactly the same class as the original array.
@@ -3097,8 +3605,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with nulls
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     @SuppressWarnings("unchecked")
@@ -3111,10 +3619,10 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>null</tt>.
+     * copy but not the original, the copy will contain {@code null}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
-     * The resulting array is of the class <tt>newType</tt>.
+     * The resulting array is of the class {@code newType}.
      *
      * @param <U> the class of the objects in the original array
      * @param <T> the class of the objects in the returned array
@@ -3123,13 +3631,14 @@
      * @param newType the class of the copy to be returned
      * @return a copy of the original array, truncated or padded with nulls
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @throws ArrayStoreException if an element copied from
-     *     <tt>original</tt> is not of a runtime type that can be stored in
-     *     an array of class <tt>newType</tt>
+     *     {@code original} is not of a runtime type that can be stored in
+     *     an array of class {@code newType}
      * @since 1.6
      */
+    @HotSpotIntrinsicCandidate
     public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
         @SuppressWarnings("unchecked")
         T[] copy = ((Object)newType == (Object)Object[].class)
@@ -3145,7 +3654,7 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>(byte)0</tt>.
+     * copy but not the original, the copy will contain {@code (byte)0}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      *
@@ -3153,8 +3662,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with zeros
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static byte[] copyOf(byte[] original, int newLength) {
@@ -3169,7 +3678,7 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>(short)0</tt>.
+     * copy but not the original, the copy will contain {@code (short)0}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      *
@@ -3177,8 +3686,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with zeros
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static short[] copyOf(short[] original, int newLength) {
@@ -3193,7 +3702,7 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>0</tt>.
+     * copy but not the original, the copy will contain {@code 0}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      *
@@ -3201,8 +3710,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with zeros
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static int[] copyOf(int[] original, int newLength) {
@@ -3217,7 +3726,7 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>0L</tt>.
+     * copy but not the original, the copy will contain {@code 0L}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      *
@@ -3225,8 +3734,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with zeros
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static long[] copyOf(long[] original, int newLength) {
@@ -3241,7 +3750,7 @@
      * so the copy has the specified length.  For all indices that are valid
      * in both the original array and the copy, the two arrays will contain
      * identical values.  For any indices that are valid in the copy but not
-     * the original, the copy will contain <tt>'\\u000'</tt>.  Such indices
+     * the original, the copy will contain {@code '\\u000'}.  Such indices
      * will exist if and only if the specified length is greater than that of
      * the original array.
      *
@@ -3249,8 +3758,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with null characters
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static char[] copyOf(char[] original, int newLength) {
@@ -3265,7 +3774,7 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>0f</tt>.
+     * copy but not the original, the copy will contain {@code 0f}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      *
@@ -3273,8 +3782,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with zeros
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static float[] copyOf(float[] original, int newLength) {
@@ -3289,7 +3798,7 @@
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>0d</tt>.
+     * copy but not the original, the copy will contain {@code 0d}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      *
@@ -3297,8 +3806,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with zeros
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static double[] copyOf(double[] original, int newLength) {
@@ -3309,11 +3818,11 @@
     }
 
     /**
-     * Copies the specified array, truncating or padding with <tt>false</tt> (if necessary)
+     * Copies the specified array, truncating or padding with {@code false} (if necessary)
      * so the copy has the specified length.  For all indices that are
      * valid in both the original array and the copy, the two arrays will
      * contain identical values.  For any indices that are valid in the
-     * copy but not the original, the copy will contain <tt>false</tt>.
+     * copy but not the original, the copy will contain {@code false}.
      * Such indices will exist if and only if the specified length
      * is greater than that of the original array.
      *
@@ -3321,8 +3830,8 @@
      * @param newLength the length of the copy to be returned
      * @return a copy of the original array, truncated or padded with false elements
      *     to obtain the specified length
-     * @throws NegativeArraySizeException if <tt>newLength</tt> is negative
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws NegativeArraySizeException if {@code newLength} is negative
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static boolean[] copyOf(boolean[] original, int newLength) {
@@ -3334,17 +3843,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>null</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code null} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      * <p>
      * The resulting array is of exactly the same class as the original array.
      *
@@ -3357,8 +3866,8 @@
      *     truncated or padded with nulls to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     @SuppressWarnings("unchecked")
@@ -3368,18 +3877,18 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>null</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
-     * The resulting array is of the class <tt>newType</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code null} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
+     * The resulting array is of the class {@code newType}.
      *
      * @param <U> the class of the objects in the original array
      * @param <T> the class of the objects in the returned array
@@ -3392,13 +3901,14 @@
      *     truncated or padded with nulls to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @throws ArrayStoreException if an element copied from
-     *     <tt>original</tt> is not of a runtime type that can be stored in
-     *     an array of class <tt>newType</tt>.
+     *     {@code original} is not of a runtime type that can be stored in
+     *     an array of class {@code newType}.
      * @since 1.6
      */
+    @HotSpotIntrinsicCandidate
     public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
         int newLength = to - from;
         if (newLength < 0)
@@ -3414,17 +3924,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>(byte)0</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code (byte)0} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3434,8 +3944,8 @@
      *     truncated or padded with zeros to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static byte[] copyOfRange(byte[] original, int from, int to) {
@@ -3450,17 +3960,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>(short)0</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code (short)0} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3470,8 +3980,8 @@
      *     truncated or padded with zeros to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static short[] copyOfRange(short[] original, int from, int to) {
@@ -3486,17 +3996,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>0</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code 0} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3506,8 +4016,8 @@
      *     truncated or padded with zeros to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static int[] copyOfRange(int[] original, int from, int to) {
@@ -3522,17 +4032,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>0L</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code 0L} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3542,8 +4052,8 @@
      *     truncated or padded with zeros to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static long[] copyOfRange(long[] original, int from, int to) {
@@ -3558,17 +4068,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>'\\u000'</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code '\\u000'} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3578,8 +4088,8 @@
      *     truncated or padded with null characters to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static char[] copyOfRange(char[] original, int from, int to) {
@@ -3594,17 +4104,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>0f</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code 0f} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3614,8 +4124,8 @@
      *     truncated or padded with zeros to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static float[] copyOfRange(float[] original, int from, int to) {
@@ -3630,17 +4140,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>0d</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code 0d} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3650,8 +4160,8 @@
      *     truncated or padded with zeros to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static double[] copyOfRange(double[] original, int from, int to) {
@@ -3666,17 +4176,17 @@
 
     /**
      * Copies the specified range of the specified array into a new array.
-     * The initial index of the range (<tt>from</tt>) must lie between zero
-     * and <tt>original.length</tt>, inclusive.  The value at
-     * <tt>original[from]</tt> is placed into the initial element of the copy
-     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
+     * The initial index of the range ({@code from}) must lie between zero
+     * and {@code original.length}, inclusive.  The value at
+     * {@code original[from]} is placed into the initial element of the copy
+     * (unless {@code from == original.length} or {@code from == to}).
      * Values from subsequent elements in the original array are placed into
      * subsequent elements in the copy.  The final index of the range
-     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
-     * may be greater than <tt>original.length</tt>, in which case
-     * <tt>false</tt> is placed in all elements of the copy whose index is
-     * greater than or equal to <tt>original.length - from</tt>.  The length
-     * of the returned array will be <tt>to - from</tt>.
+     * ({@code to}), which must be greater than or equal to {@code from},
+     * may be greater than {@code original.length}, in which case
+     * {@code false} is placed in all elements of the copy whose index is
+     * greater than or equal to {@code original.length - from}.  The length
+     * of the returned array will be {@code to - from}.
      *
      * @param original the array from which a range is to be copied
      * @param from the initial index of the range to be copied, inclusive
@@ -3686,8 +4196,8 @@
      *     truncated or padded with false elements to obtain the required length
      * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
      *     or {@code from > original.length}
-     * @throws IllegalArgumentException if <tt>from &gt; to</tt>
-     * @throws NullPointerException if <tt>original</tt> is null
+     * @throws IllegalArgumentException if {@code from > to}
+     * @throws NullPointerException if {@code original} is null
      * @since 1.6
      */
     public static boolean[] copyOfRange(boolean[] original, int from, int to) {
@@ -3745,6 +4255,11 @@
 
         @Override
         public Object[] toArray() {
+            // Android-changed: there are applications which expect this method
+            // to return array with component type E, not just Object.
+            // Keeping pre-Java 9 behaviour for compatibility sake.
+            // See b/204397945.
+            // return Arrays.copyOf(a, a.length, Object[].class);
             return a.clone();
         }
 
@@ -3790,7 +4305,7 @@
 
         @Override
         public boolean contains(Object o) {
-            return indexOf(o) != -1;
+            return indexOf(o) >= 0;
         }
 
         @Override
@@ -3819,22 +4334,51 @@
         public void sort(Comparator<? super E> c) {
             Arrays.sort(a, c);
         }
+
+        @Override
+        public Iterator<E> iterator() {
+            return new ArrayItr<>(a);
+        }
+    }
+
+    private static class ArrayItr<E> implements Iterator<E> {
+        private int cursor;
+        private final E[] a;
+
+        ArrayItr(E[] a) {
+            this.a = a;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return cursor < a.length;
+        }
+
+        @Override
+        public E next() {
+            int i = cursor;
+            if (i >= a.length) {
+                throw new NoSuchElementException();
+            }
+            cursor = i + 1;
+            return a[i];
+        }
     }
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two <tt>long</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two {@code long} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Long}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(long a[]) {
@@ -3852,18 +4396,18 @@
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two non-null <tt>int</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two non-null {@code int} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Integer}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(int a[]) {
@@ -3879,18 +4423,18 @@
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two <tt>short</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two {@code short} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Short}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(short a[]) {
@@ -3906,18 +4450,18 @@
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two <tt>char</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two {@code char} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Character}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(char a[]) {
@@ -3933,18 +4477,18 @@
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two <tt>byte</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two {@code byte} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Byte}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(byte a[]) {
@@ -3960,18 +4504,18 @@
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two <tt>boolean</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two {@code boolean} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Boolean}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(boolean a[]) {
@@ -3987,18 +4531,18 @@
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two <tt>float</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two {@code float} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Float}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(float a[]) {
@@ -4014,18 +4558,18 @@
 
     /**
      * Returns a hash code based on the contents of the specified array.
-     * For any two <tt>double</tt> arrays <tt>a</tt> and <tt>b</tt>
-     * such that <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * For any two {@code double} arrays {@code a} and {@code b}
+     * such that {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is the same value that would be
-     * obtained by invoking the {@link List#hashCode() <tt>hashCode</tt>}
+     * obtained by invoking the {@link List#hashCode() hashCode}
      * method on a {@link List} containing a sequence of {@link Double}
-     * instances representing the elements of <tt>a</tt> in the same order.
-     * If <tt>a</tt> is <tt>null</tt>, this method returns 0.
+     * instances representing the elements of {@code a} in the same order.
+     * If {@code a} is {@code null}, this method returns 0.
      *
      * @param a the array whose hash value to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @since 1.5
      */
     public static int hashCode(double a[]) {
@@ -4048,16 +4592,16 @@
      * element,  either directly or indirectly through one or more levels of
      * arrays.
      *
-     * <p>For any two arrays <tt>a</tt> and <tt>b</tt> such that
-     * <tt>Arrays.equals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.hashCode(a) == Arrays.hashCode(b)</tt>.
+     * <p>For any two arrays {@code a} and {@code b} such that
+     * {@code Arrays.equals(a, b)}, it is also the case that
+     * {@code Arrays.hashCode(a) == Arrays.hashCode(b)}.
      *
      * <p>The value returned by this method is equal to the value that would
-     * be returned by <tt>Arrays.asList(a).hashCode()</tt>, unless <tt>a</tt>
-     * is <tt>null</tt>, in which case <tt>0</tt> is returned.
+     * be returned by {@code Arrays.asList(a).hashCode()}, unless {@code a}
+     * is {@code null}, in which case {@code 0} is returned.
      *
      * @param a the array whose content-based hash code to compute
-     * @return a content-based hash code for <tt>a</tt>
+     * @return a content-based hash code for {@code a}
      * @see #deepHashCode(Object[])
      * @since 1.5
      */
@@ -4082,23 +4626,23 @@
      * one or more levels of arrays.  The behavior of such an invocation is
      * undefined.
      *
-     * <p>For any two arrays <tt>a</tt> and <tt>b</tt> such that
-     * <tt>Arrays.deepEquals(a, b)</tt>, it is also the case that
-     * <tt>Arrays.deepHashCode(a) == Arrays.deepHashCode(b)</tt>.
+     * <p>For any two arrays {@code a} and {@code b} such that
+     * {@code Arrays.deepEquals(a, b)}, it is also the case that
+     * {@code Arrays.deepHashCode(a) == Arrays.deepHashCode(b)}.
      *
      * <p>The computation of the value returned by this method is similar to
      * that of the value returned by {@link List#hashCode()} on a list
-     * containing the same elements as <tt>a</tt> in the same order, with one
-     * difference: If an element <tt>e</tt> of <tt>a</tt> is itself an array,
-     * its hash code is computed not by calling <tt>e.hashCode()</tt>, but as
-     * by calling the appropriate overloading of <tt>Arrays.hashCode(e)</tt>
-     * if <tt>e</tt> is an array of a primitive type, or as by calling
-     * <tt>Arrays.deepHashCode(e)</tt> recursively if <tt>e</tt> is an array
-     * of a reference type.  If <tt>a</tt> is <tt>null</tt>, this method
+     * containing the same elements as {@code a} in the same order, with one
+     * difference: If an element {@code e} of {@code a} is itself an array,
+     * its hash code is computed not by calling {@code e.hashCode()}, but as
+     * by calling the appropriate overloading of {@code Arrays.hashCode(e)}
+     * if {@code e} is an array of a primitive type, or as by calling
+     * {@code Arrays.deepHashCode(e)} recursively if {@code e} is an array
+     * of a reference type.  If {@code a} is {@code null}, this method
      * returns 0.
      *
      * @param a the array whose deep-content-based hash code to compute
-     * @return a deep-content-based hash code for <tt>a</tt>
+     * @return a deep-content-based hash code for {@code a}
      * @see #hashCode(Object[])
      * @since 1.5
      */
@@ -4109,63 +4653,60 @@
         int result = 1;
 
         for (Object element : a) {
-            int elementHash = 0;
-            // BEGIN Android-changed: getComponentType() is faster than instanceof().
-            if (element != null) {
-                Class<?> cl = element.getClass().getComponentType();
-                if (cl == null)
-                    elementHash = element.hashCode();
-                else if (element instanceof Object[])
-                    elementHash = deepHashCode((Object[]) element);
-                else if (cl == byte.class)
-                    elementHash = hashCode((byte[]) element);
-                else if (cl == short.class)
-                    elementHash = hashCode((short[]) element);
-                else if (cl == int.class)
-                    elementHash = hashCode((int[]) element);
-                else if (cl == long.class)
-                    elementHash = hashCode((long[]) element);
-                else if (cl == char.class)
-                    elementHash = hashCode((char[]) element);
-                else if (cl == float.class)
-                    elementHash = hashCode((float[]) element);
-                else if (cl == double.class)
-                    elementHash = hashCode((double[]) element);
-                else if (cl == boolean.class)
-                    elementHash = hashCode((boolean[]) element);
-                else
-                    elementHash = element.hashCode();
-            }
-            // END Android-changed: getComponentType() is faster than instanceof().
+            final int elementHash;
+            final Class<?> cl;
+            if (element == null)
+                elementHash = 0;
+            else if ((cl = element.getClass().getComponentType()) == null)
+                elementHash = element.hashCode();
+            else if (element instanceof Object[])
+                elementHash = deepHashCode((Object[]) element);
+            else
+                elementHash = primitiveArrayHashCode(element, cl);
+
             result = 31 * result + elementHash;
         }
 
         return result;
     }
 
+    private static int primitiveArrayHashCode(Object a, Class<?> cl) {
+        return
+            (cl == byte.class)    ? hashCode((byte[]) a)    :
+            (cl == int.class)     ? hashCode((int[]) a)     :
+            (cl == long.class)    ? hashCode((long[]) a)    :
+            (cl == char.class)    ? hashCode((char[]) a)    :
+            (cl == short.class)   ? hashCode((short[]) a)   :
+            (cl == boolean.class) ? hashCode((boolean[]) a) :
+            (cl == double.class)  ? hashCode((double[]) a)  :
+            // If new primitive types are ever added, this method must be
+            // expanded or we will fail here with ClassCastException.
+            hashCode((float[]) a);
+    }
+
     /**
-     * Returns <tt>true</tt> if the two specified arrays are <i>deeply
+     * Returns {@code true} if the two specified arrays are <i>deeply
      * equal</i> to one another.  Unlike the {@link #equals(Object[],Object[])}
      * method, this method is appropriate for use with nested arrays of
      * arbitrary depth.
      *
      * <p>Two array references are considered deeply equal if both
-     * are <tt>null</tt>, or if they refer to arrays that contain the same
+     * are {@code null}, or if they refer to arrays that contain the same
      * number of elements and all corresponding pairs of elements in the two
      * arrays are deeply equal.
      *
-     * <p>Two possibly <tt>null</tt> elements <tt>e1</tt> and <tt>e2</tt> are
+     * <p>Two possibly {@code null} elements {@code e1} and {@code e2} are
      * deeply equal if any of the following conditions hold:
      * <ul>
-     *    <li> <tt>e1</tt> and <tt>e2</tt> are both arrays of object reference
-     *         types, and <tt>Arrays.deepEquals(e1, e2) would return true</tt>
-     *    <li> <tt>e1</tt> and <tt>e2</tt> are arrays of the same primitive
+     *    <li> {@code e1} and {@code e2} are both arrays of object reference
+     *         types, and {@code Arrays.deepEquals(e1, e2) would return true}
+     *    <li> {@code e1} and {@code e2} are arrays of the same primitive
      *         type, and the appropriate overloading of
-     *         <tt>Arrays.equals(e1, e2)</tt> would return true.
-     *    <li> <tt>e1 == e2</tt>
-     *    <li> <tt>e1.equals(e2)</tt> would return true.
+     *         {@code Arrays.equals(e1, e2)} would return true.
+     *    <li> {@code e1 == e2}
+     *    <li> {@code e1.equals(e2)} would return true.
      * </ul>
-     * Note that this definition permits <tt>null</tt> elements at any depth.
+     * Note that this definition permits {@code null} elements at any depth.
      *
      * <p>If either of the specified arrays contain themselves as elements
      * either directly or indirectly through one or more levels of arrays,
@@ -4173,7 +4714,7 @@
      *
      * @param a1 one array to be tested for equality
      * @param a2 the other array to be tested for equality
-     * @return <tt>true</tt> if the two arrays are equal
+     * @return {@code true} if the two arrays are equal
      * @see #equals(Object[],Object[])
      * @see Objects#deepEquals(Object, Object)
      * @since 1.5
@@ -4234,14 +4775,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements are
-     * separated by the characters <tt>", "</tt> (a comma followed by a
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements are
+     * separated by the characters {@code ", "} (a comma followed by a
      * space).  Elements are converted to strings as by
-     * <tt>String.valueOf(long)</tt>.  Returns <tt>"null"</tt> if <tt>a</tt>
-     * is <tt>null</tt>.
+     * {@code String.valueOf(long)}.  Returns {@code "null"} if {@code a}
+     * is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(long[] a) {
@@ -4264,14 +4805,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements are
-     * separated by the characters <tt>", "</tt> (a comma followed by a
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements are
+     * separated by the characters {@code ", "} (a comma followed by a
      * space).  Elements are converted to strings as by
-     * <tt>String.valueOf(int)</tt>.  Returns <tt>"null"</tt> if <tt>a</tt> is
-     * <tt>null</tt>.
+     * {@code String.valueOf(int)}.  Returns {@code "null"} if {@code a} is
+     * {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(int[] a) {
@@ -4294,14 +4835,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements are
-     * separated by the characters <tt>", "</tt> (a comma followed by a
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements are
+     * separated by the characters {@code ", "} (a comma followed by a
      * space).  Elements are converted to strings as by
-     * <tt>String.valueOf(short)</tt>.  Returns <tt>"null"</tt> if <tt>a</tt>
-     * is <tt>null</tt>.
+     * {@code String.valueOf(short)}.  Returns {@code "null"} if {@code a}
+     * is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(short[] a) {
@@ -4324,14 +4865,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements are
-     * separated by the characters <tt>", "</tt> (a comma followed by a
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements are
+     * separated by the characters {@code ", "} (a comma followed by a
      * space).  Elements are converted to strings as by
-     * <tt>String.valueOf(char)</tt>.  Returns <tt>"null"</tt> if <tt>a</tt>
-     * is <tt>null</tt>.
+     * {@code String.valueOf(char)}.  Returns {@code "null"} if {@code a}
+     * is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(char[] a) {
@@ -4354,14 +4895,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements
-     * are separated by the characters <tt>", "</tt> (a comma followed
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements
+     * are separated by the characters {@code ", "} (a comma followed
      * by a space).  Elements are converted to strings as by
-     * <tt>String.valueOf(byte)</tt>.  Returns <tt>"null"</tt> if
-     * <tt>a</tt> is <tt>null</tt>.
+     * {@code String.valueOf(byte)}.  Returns {@code "null"} if
+     * {@code a} is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(byte[] a) {
@@ -4384,14 +4925,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements are
-     * separated by the characters <tt>", "</tt> (a comma followed by a
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements are
+     * separated by the characters {@code ", "} (a comma followed by a
      * space).  Elements are converted to strings as by
-     * <tt>String.valueOf(boolean)</tt>.  Returns <tt>"null"</tt> if
-     * <tt>a</tt> is <tt>null</tt>.
+     * {@code String.valueOf(boolean)}.  Returns {@code "null"} if
+     * {@code a} is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(boolean[] a) {
@@ -4414,14 +4955,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements are
-     * separated by the characters <tt>", "</tt> (a comma followed by a
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements are
+     * separated by the characters {@code ", "} (a comma followed by a
      * space).  Elements are converted to strings as by
-     * <tt>String.valueOf(float)</tt>.  Returns <tt>"null"</tt> if <tt>a</tt>
-     * is <tt>null</tt>.
+     * {@code String.valueOf(float)}.  Returns {@code "null"} if {@code a}
+     * is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(float[] a) {
@@ -4445,14 +4986,14 @@
     /**
      * Returns a string representation of the contents of the specified array.
      * The string representation consists of a list of the array's elements,
-     * enclosed in square brackets (<tt>"[]"</tt>).  Adjacent elements are
-     * separated by the characters <tt>", "</tt> (a comma followed by a
+     * enclosed in square brackets ({@code "[]"}).  Adjacent elements are
+     * separated by the characters {@code ", "} (a comma followed by a
      * space).  Elements are converted to strings as by
-     * <tt>String.valueOf(double)</tt>.  Returns <tt>"null"</tt> if <tt>a</tt>
-     * is <tt>null</tt>.
+     * {@code String.valueOf(double)}.  Returns {@code "null"} if {@code a}
+     * is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @since 1.5
      */
     public static String toString(double[] a) {
@@ -4476,15 +5017,15 @@
      * Returns a string representation of the contents of the specified array.
      * If the array contains other arrays as elements, they are converted to
      * strings by the {@link Object#toString} method inherited from
-     * <tt>Object</tt>, which describes their <i>identities</i> rather than
+     * {@code Object}, which describes their <i>identities</i> rather than
      * their contents.
      *
      * <p>The value returned by this method is equal to the value that would
-     * be returned by <tt>Arrays.asList(a).toString()</tt>, unless <tt>a</tt>
-     * is <tt>null</tt>, in which case <tt>"null"</tt> is returned.
+     * be returned by {@code Arrays.asList(a).toString()}, unless {@code a}
+     * is {@code null}, in which case {@code "null"} is returned.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @see #deepToString(Object[])
      * @since 1.5
      */
@@ -4513,29 +5054,29 @@
      * designed for converting multidimensional arrays to strings.
      *
      * <p>The string representation consists of a list of the array's
-     * elements, enclosed in square brackets (<tt>"[]"</tt>).  Adjacent
-     * elements are separated by the characters <tt>", "</tt> (a comma
+     * elements, enclosed in square brackets ({@code "[]"}).  Adjacent
+     * elements are separated by the characters {@code ", "} (a comma
      * followed by a space).  Elements are converted to strings as by
-     * <tt>String.valueOf(Object)</tt>, unless they are themselves
+     * {@code String.valueOf(Object)}, unless they are themselves
      * arrays.
      *
-     * <p>If an element <tt>e</tt> is an array of a primitive type, it is
+     * <p>If an element {@code e} is an array of a primitive type, it is
      * converted to a string as by invoking the appropriate overloading of
-     * <tt>Arrays.toString(e)</tt>.  If an element <tt>e</tt> is an array of a
+     * {@code Arrays.toString(e)}.  If an element {@code e} is an array of a
      * reference type, it is converted to a string as by invoking
      * this method recursively.
      *
      * <p>To avoid infinite recursion, if the specified array contains itself
      * as an element, or contains an indirect reference to itself through one
      * or more levels of arrays, the self-reference is converted to the string
-     * <tt>"[...]"</tt>.  For example, an array containing only a reference
-     * to itself would be rendered as <tt>"[[...]]"</tt>.
+     * {@code "[...]"}.  For example, an array containing only a reference
+     * to itself would be rendered as {@code "[[...]]"}.
      *
-     * <p>This method returns <tt>"null"</tt> if the specified array
-     * is <tt>null</tt>.
+     * <p>This method returns {@code "null"} if the specified array
+     * is {@code null}.
      *
      * @param a the array whose string representation to return
-     * @return a string representation of <tt>a</tt>
+     * @return a string representation of {@code a}
      * @see #toString(Object[])
      * @since 1.5
      */
@@ -4547,7 +5088,7 @@
         if (a.length != 0 && bufLen <= 0)
             bufLen = Integer.MAX_VALUE;
         StringBuilder buf = new StringBuilder(bufLen);
-        deepToString(a, buf, new HashSet<Object[]>());
+        deepToString(a, buf, new HashSet<>());
         return buf.toString();
     }
 
@@ -4616,6 +5157,14 @@
      * <p>If the generator function throws an exception, it is relayed to
      * the caller and the array is left in an indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, using a generator function to compute
+     * each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .forEach(i -> array[i] = generator.apply(i));
+     * }</pre>
+     *
      * @param <T> type of elements of the array
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
@@ -4637,6 +5186,15 @@
      * is thrown from {@code parallelSetAll} and the array is left in an
      * indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, in parallel, using a generator function
+     * to compute each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .parallel()
+     *          .forEach(i -> array[i] = generator.apply(i));
+     * }</pre>
+     *
      * @param <T> type of elements of the array
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
@@ -4656,6 +5214,14 @@
      * <p>If the generator function throws an exception, it is relayed to
      * the caller and the array is left in an indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, using a generator function to compute
+     * each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .forEach(i -> array[i] = generator.applyAsInt(i));
+     * }</pre>
+     *
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
      *        value for that position
@@ -4676,6 +5242,15 @@
      * is thrown from {@code parallelSetAll} and the array is left in an
      * indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, in parallel, using a generator function
+     * to compute each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .parallel()
+     *          .forEach(i -> array[i] = generator.applyAsInt(i));
+     * }</pre>
+     *
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
      * value for that position
@@ -4694,6 +5269,14 @@
      * <p>If the generator function throws an exception, it is relayed to
      * the caller and the array is left in an indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, using a generator function to compute
+     * each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .forEach(i -> array[i] = generator.applyAsLong(i));
+     * }</pre>
+     *
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
      *        value for that position
@@ -4714,6 +5297,15 @@
      * is thrown from {@code parallelSetAll} and the array is left in an
      * indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, in parallel, using a generator function
+     * to compute each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .parallel()
+     *          .forEach(i -> array[i] = generator.applyAsLong(i));
+     * }</pre>
+     *
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
      *        value for that position
@@ -4732,6 +5324,14 @@
      * <p>If the generator function throws an exception, it is relayed to
      * the caller and the array is left in an indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, using a generator function to compute
+     * each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .forEach(i -> array[i] = generator.applyAsDouble(i));
+     * }</pre>
+     *
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
      *        value for that position
@@ -4752,6 +5352,15 @@
      * is thrown from {@code parallelSetAll} and the array is left in an
      * indeterminate state.
      *
+     * @apiNote
+     * Setting a subrange of an array, in parallel, using a generator function
+     * to compute each element, can be written as follows:
+     * <pre>{@code
+     * IntStream.range(startInclusive, endExclusive)
+     *          .parallel()
+     *          .forEach(i -> array[i] = generator.applyAsDouble(i));
+     * }</pre>
+     *
      * @param array array to be initialized
      * @param generator a function accepting an index and producing the desired
      *        value for that position
@@ -5043,4 +5652,3185 @@
     public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
         return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
     }
+
+
+    // Comparison methods
+
+    // Compare boolean
+
+    /**
+     * Compares two {@code boolean} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Boolean#compare(boolean, boolean)}, at an index within the
+     * respective arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(boolean[], boolean[])} for the definition of a
+     * common and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(boolean[], boolean[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Boolean.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(boolean[] a, boolean[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Boolean.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code boolean} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Boolean#compare(boolean, boolean)}, at a
+     * relative index within the respective arrays that is the length of the
+     * prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(boolean[], int, int, boolean[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(boolean[], int, int, boolean[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Boolean.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(boolean[] a, int aFromIndex, int aToIndex,
+                              boolean[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Boolean.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare byte
+
+    /**
+     * Compares two {@code byte} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Byte#compare(byte, byte)}, at an index within the respective
+     * arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(byte[], byte[])} for the definition of a common and
+     * proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(byte[], byte[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Byte.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(byte[] a, byte[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Byte.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code byte} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Byte#compare(byte, byte)}, at a relative index
+     * within the respective arrays that is the length of the prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(byte[], int, int, byte[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Byte.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(byte[] a, int aFromIndex, int aToIndex,
+                              byte[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Byte.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    /**
+     * Compares two {@code byte} arrays lexicographically, numerically treating
+     * elements as unsigned.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Byte#compareUnsigned(byte, byte)}, at an index within the
+     * respective arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(byte[], byte[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Byte.compareUnsigned(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are
+     *         equal and contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compareUnsigned(byte[] a, byte[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Byte.compareUnsigned(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+
+    /**
+     * Compares two {@code byte} arrays lexicographically over the specified
+     * ranges, numerically treating elements as unsigned.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Byte#compareUnsigned(byte, byte)}, at a
+     * relative index within the respective arrays that is the length of the
+     * prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(byte[], int, int, byte[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Byte.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is null
+     * @since 9
+     */
+    public static int compareUnsigned(byte[] a, int aFromIndex, int aToIndex,
+                                      byte[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Byte.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare short
+
+    /**
+     * Compares two {@code short} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Short#compare(short, short)}, at an index within the respective
+     * arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(short[], short[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(short[], short[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Short.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(short[] a, short[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Short.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code short} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Short#compare(short, short)}, at a relative
+     * index within the respective arrays that is the length of the prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(short[], int, int, short[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(short[], int, int, short[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Short.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(short[] a, int aFromIndex, int aToIndex,
+                              short[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Short.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    /**
+     * Compares two {@code short} arrays lexicographically, numerically treating
+     * elements as unsigned.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Short#compareUnsigned(short, short)}, at an index within the
+     * respective arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(short[], short[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Short.compareUnsigned(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are
+     *         equal and contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compareUnsigned(short[] a, short[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Short.compareUnsigned(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code short} arrays lexicographically over the specified
+     * ranges, numerically treating elements as unsigned.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Short#compareUnsigned(short, short)}, at a
+     * relative index within the respective arrays that is the length of the
+     * prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(short[], int, int, short[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Short.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is null
+     * @since 9
+     */
+    public static int compareUnsigned(short[] a, int aFromIndex, int aToIndex,
+                                      short[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Short.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare char
+
+    /**
+     * Compares two {@code char} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Character#compare(char, char)}, at an index within the respective
+     * arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(char[], char[])} for the definition of a common and
+     * proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(char[], char[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Character.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(char[] a, char[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Character.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code char} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Character#compare(char, char)}, at a relative
+     * index within the respective arrays that is the length of the prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(char[], int, int, char[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(char[], int, int, char[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Character.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(char[] a, int aFromIndex, int aToIndex,
+                              char[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Character.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare int
+
+    /**
+     * Compares two {@code int} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Integer#compare(int, int)}, at an index within the respective
+     * arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(int[], int[])} for the definition of a common and
+     * proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(int[], int[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Integer.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(int[] a, int[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Integer.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code int} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Integer#compare(int, int)}, at a relative index
+     * within the respective arrays that is the length of the prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(int[], int, int, int[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(int[], int, int, int[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Integer.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(int[] a, int aFromIndex, int aToIndex,
+                              int[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Integer.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    /**
+     * Compares two {@code int} arrays lexicographically, numerically treating
+     * elements as unsigned.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Integer#compareUnsigned(int, int)}, at an index within the
+     * respective arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(int[], int[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Integer.compareUnsigned(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are
+     *         equal and contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compareUnsigned(int[] a, int[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Integer.compareUnsigned(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code int} arrays lexicographically over the specified
+     * ranges, numerically treating elements as unsigned.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Integer#compareUnsigned(int, int)}, at a
+     * relative index within the respective arrays that is the length of the
+     * prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(int[], int, int, int[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Integer.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is null
+     * @since 9
+     */
+    public static int compareUnsigned(int[] a, int aFromIndex, int aToIndex,
+                                      int[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Integer.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare long
+
+    /**
+     * Compares two {@code long} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Long#compare(long, long)}, at an index within the respective
+     * arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(long[], long[])} for the definition of a common and
+     * proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(long[], long[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Long.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(long[] a, long[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Long.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code long} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Long#compare(long, long)}, at a relative index
+     * within the respective arrays that is the length of the prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(long[], int, int, long[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(long[], int, int, long[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Long.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(long[] a, int aFromIndex, int aToIndex,
+                              long[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Long.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    /**
+     * Compares two {@code long} arrays lexicographically, numerically treating
+     * elements as unsigned.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Long#compareUnsigned(long, long)}, at an index within the
+     * respective arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(long[], long[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Long.compareUnsigned(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are
+     *         equal and contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compareUnsigned(long[] a, long[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Long.compareUnsigned(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code long} arrays lexicographically over the specified
+     * ranges, numerically treating elements as unsigned.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Long#compareUnsigned(long, long)}, at a
+     * relative index within the respective arrays that is the length of the
+     * prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(long[], int, int, long[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Long.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is null
+     * @since 9
+     */
+    public static int compareUnsigned(long[] a, int aFromIndex, int aToIndex,
+                                      long[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Long.compareUnsigned(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare float
+
+    /**
+     * Compares two {@code float} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Float#compare(float, float)}, at an index within the respective
+     * arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(float[], float[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(float[], float[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Float.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(float[] a, float[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Float.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code float} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Float#compare(float, float)}, at a relative
+     * index within the respective arrays that is the length of the prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(float[], int, int, float[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(float[], int, int, float[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Float.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(float[] a, int aFromIndex, int aToIndex,
+                              float[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Float.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare double
+
+    /**
+     * Compares two {@code double} arrays lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements, as if by
+     * {@link Double#compare(double, double)}, at an index within the respective
+     * arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(double[], double[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(double[], double[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return Double.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static int compare(double[] a, double[] b) {
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int i = ArraysSupport.mismatch(a, b,
+                                       Math.min(a.length, b.length));
+        if (i >= 0) {
+            return Double.compare(a[i], b[i]);
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code double} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements, as if by {@link Double#compare(double, double)}, at a relative
+     * index within the respective arrays that is the length of the prefix.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(double[], int, int, double[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(double[], int, int, double[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if:
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return Double.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int compare(double[] a, int aFromIndex, int aToIndex,
+                              double[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       Math.min(aLength, bLength));
+        if (i >= 0) {
+            return Double.compare(a[aFromIndex + i], b[bFromIndex + i]);
+        }
+
+        return aLength - bLength;
+    }
+
+    // Compare objects
+
+    /**
+     * Compares two {@code Object} arrays, within comparable elements,
+     * lexicographically.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing two elements of type {@code T} at
+     * an index {@code i} within the respective arrays that is the prefix
+     * length, as if by:
+     * <pre>{@code
+     *     Comparator.nullsFirst(Comparator.<T>naturalOrder()).
+     *         compare(a[i], b[i])
+     * }</pre>
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(Object[], Object[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     * A {@code null} array element is considered lexicographically than a
+     * non-{@code null} array element.  Two {@code null} array elements are
+     * considered equal.
+     *
+     * <p>The comparison is consistent with {@link #equals(Object[], Object[]) equals},
+     * more specifically the following holds for arrays {@code a} and {@code b}:
+     * <pre>{@code
+     *     Arrays.equals(a, b) == (Arrays.compare(a, b) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references
+     * and elements):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return a[i].compareTo(b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @param <T> the type of comparable array elements
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @since 9
+     */
+    public static <T extends Comparable<? super T>> int compare(T[] a, T[] b) {
+        if (a == b)
+            return 0;
+        // A null array is less than a non-null array
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int length = Math.min(a.length, b.length);
+        for (int i = 0; i < length; i++) {
+            T oa = a[i];
+            T ob = b[i];
+            if (oa != ob) {
+                // A null element is less than a non-null element
+                if (oa == null || ob == null)
+                    return oa == null ? -1 : 1;
+                int v = oa.compareTo(ob);
+                if (v != 0) {
+                    return v;
+                }
+            }
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code Object} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing two
+     * elements of type {@code T} at a relative index {@code i} within the
+     * respective arrays that is the prefix length, as if by:
+     * <pre>{@code
+     *     Comparator.nullsFirst(Comparator.<T>naturalOrder()).
+     *         compare(a[aFromIndex + i, b[bFromIndex + i])
+     * }</pre>
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * <p>The comparison is consistent with
+     * {@link #equals(Object[], int, int, Object[], int, int) equals}, more
+     * specifically the following holds for arrays {@code a} and {@code b} with
+     * specified ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively:
+     * <pre>{@code
+     *     Arrays.equals(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) ==
+     *         (Arrays.compare(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex) == 0)
+     * }</pre>
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array elements):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return a[aFromIndex + i].compareTo(b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @param <T> the type of comparable array elements
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static <T extends Comparable<? super T>> int compare(
+            T[] a, int aFromIndex, int aToIndex,
+            T[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        for (int i = 0; i < length; i++) {
+            T oa = a[aFromIndex++];
+            T ob = b[bFromIndex++];
+            if (oa != ob) {
+                if (oa == null || ob == null)
+                    return oa == null ? -1 : 1;
+                int v = oa.compareTo(ob);
+                if (v != 0) {
+                    return v;
+                }
+            }
+        }
+
+        return aLength - bLength;
+    }
+
+    /**
+     * Compares two {@code Object} arrays lexicographically using a specified
+     * comparator.
+     *
+     * <p>If the two arrays share a common prefix then the lexicographic
+     * comparison is the result of comparing with the specified comparator two
+     * elements at an index within the respective arrays that is the prefix
+     * length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two array lengths.
+     * (See {@link #mismatch(Object[], Object[])} for the definition of a common
+     * and proper prefix.)
+     *
+     * <p>A {@code null} array reference is considered lexicographically less
+     * than a non-{@code null} array reference.  Two {@code null} array
+     * references are considered equal.
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array references):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, b, cmp);
+     *     if (i >= 0 && i < Math.min(a.length, b.length))
+     *         return cmp.compare(a[i], b[i]);
+     *     return a.length - b.length;
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param b the second array to compare
+     * @param cmp the comparator to compare array elements
+     * @param <T> the type of array elements
+     * @return the value {@code 0} if the first and second array are equal and
+     *         contain the same elements in the same order;
+     *         a value less than {@code 0} if the first array is
+     *         lexicographically less than the second array; and
+     *         a value greater than {@code 0} if the first array is
+     *         lexicographically greater than the second array
+     * @throws NullPointerException if the comparator is {@code null}
+     * @since 9
+     */
+    public static <T> int compare(T[] a, T[] b,
+                                  Comparator<? super T> cmp) {
+        Objects.requireNonNull(cmp);
+        if (a == b)
+            return 0;
+        if (a == null || b == null)
+            return a == null ? -1 : 1;
+
+        int length = Math.min(a.length, b.length);
+        for (int i = 0; i < length; i++) {
+            T oa = a[i];
+            T ob = b[i];
+            if (oa != ob) {
+                // Null-value comparison is deferred to the comparator
+                int v = cmp.compare(oa, ob);
+                if (v != 0) {
+                    return v;
+                }
+            }
+        }
+
+        return a.length - b.length;
+    }
+
+    /**
+     * Compares two {@code Object} arrays lexicographically over the specified
+     * ranges.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the lexicographic comparison is the result of comparing with the
+     * specified comparator two elements at a relative index within the
+     * respective arrays that is the prefix length.
+     * Otherwise, one array is a proper prefix of the other and, lexicographic
+     * comparison is the result of comparing the two range lengths.
+     * (See {@link #mismatch(Object[], int, int, Object[], int, int)} for the
+     * definition of a common and proper prefix.)
+     *
+     * @apiNote
+     * <p>This method behaves as if (for non-{@code null} array elements):
+     * <pre>{@code
+     *     int i = Arrays.mismatch(a, aFromIndex, aToIndex,
+     *                             b, bFromIndex, bToIndex, cmp);
+     *     if (i >= 0 && i < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     *         return cmp.compare(a[aFromIndex + i], b[bFromIndex + i]);
+     *     return (aToIndex - aFromIndex) - (bToIndex - bFromIndex);
+     * }</pre>
+     *
+     * @param a the first array to compare
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be compared
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be compared
+     * @param b the second array to compare
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be compared
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be compared
+     * @param cmp the comparator to compare array elements
+     * @param <T> the type of array elements
+     * @return the value {@code 0} if, over the specified ranges, the first and
+     *         second array are equal and contain the same elements in the same
+     *         order;
+     *         a value less than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically less than the second array; and
+     *         a value greater than {@code 0} if, over the specified ranges, the
+     *         first array is lexicographically greater than the second array
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array or the comparator is {@code null}
+     * @since 9
+     */
+    public static <T> int compare(
+            T[] a, int aFromIndex, int aToIndex,
+            T[] b, int bFromIndex, int bToIndex,
+            Comparator<? super T> cmp) {
+        Objects.requireNonNull(cmp);
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        for (int i = 0; i < length; i++) {
+            T oa = a[aFromIndex++];
+            T ob = b[bFromIndex++];
+            if (oa != ob) {
+                // Null-value comparison is deferred to the comparator
+                int v = cmp.compare(oa, ob);
+                if (v != 0) {
+                    return v;
+                }
+            }
+        }
+
+        return aLength - bLength;
+    }
+
+
+    // Mismatch methods
+
+    // Mismatch boolean
+
+    /**
+     * Finds and returns the index of the first mismatch between two
+     * {@code boolean} arrays, otherwise return -1 if no mismatch is found.  The
+     * index will be in the range of 0 (inclusive) up to the length (inclusive)
+     * of the smaller array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     a[pl] != b[pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(boolean[] a, boolean[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code boolean} arrays over the specified ranges, otherwise return -1 if
+     * no mismatch is found.  The index will be in the range of 0 (inclusive) up
+     * to the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     a[aFromIndex + pl] != b[bFromIndex + pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(boolean[] a, int aFromIndex, int aToIndex,
+                               boolean[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch byte
+
+    /**
+     * Finds and returns the index of the first mismatch between two {@code byte}
+     * arrays, otherwise return -1 if no mismatch is found.  The index will be
+     * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+     * array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     a[pl] != b[pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(byte[] a, byte[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code byte} arrays over the specified ranges, otherwise return -1 if no
+     * mismatch is found.  The index will be in the range of 0 (inclusive) up to
+     * the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     a[aFromIndex + pl] != b[bFromIndex + pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(byte[] a, int aFromIndex, int aToIndex,
+                               byte[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch char
+
+    /**
+     * Finds and returns the index of the first mismatch between two {@code char}
+     * arrays, otherwise return -1 if no mismatch is found.  The index will be
+     * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+     * array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     a[pl] != b[pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(char[] a, char[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code char} arrays over the specified ranges, otherwise return -1 if no
+     * mismatch is found.  The index will be in the range of 0 (inclusive) up to
+     * the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     a[aFromIndex + pl] != b[bFromIndex + pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(char[] a, int aFromIndex, int aToIndex,
+                               char[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch short
+
+    /**
+     * Finds and returns the index of the first mismatch between two {@code short}
+     * arrays, otherwise return -1 if no mismatch is found.  The index will be
+     * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+     * array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     a[pl] != b[pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(short[] a, short[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code short} arrays over the specified ranges, otherwise return -1 if no
+     * mismatch is found.  The index will be in the range of 0 (inclusive) up to
+     * the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     a[aFromIndex + pl] != b[bFromIndex + pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(short[] a, int aFromIndex, int aToIndex,
+                               short[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch int
+
+    /**
+     * Finds and returns the index of the first mismatch between two {@code int}
+     * arrays, otherwise return -1 if no mismatch is found.  The index will be
+     * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+     * array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     a[pl] != b[pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(int[] a, int[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code int} arrays over the specified ranges, otherwise return -1 if no
+     * mismatch is found.  The index will be in the range of 0 (inclusive) up to
+     * the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     a[aFromIndex + pl] != b[bFromIndex + pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(int[] a, int aFromIndex, int aToIndex,
+                               int[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch long
+
+    /**
+     * Finds and returns the index of the first mismatch between two {@code long}
+     * arrays, otherwise return -1 if no mismatch is found.  The index will be
+     * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+     * array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     a[pl] != b[pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(long[] a, long[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code long} arrays over the specified ranges, otherwise return -1 if no
+     * mismatch is found.  The index will be in the range of 0 (inclusive) up to
+     * the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     a[aFromIndex + pl] != b[bFromIndex + pl]
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(long[] a, int aFromIndex, int aToIndex,
+                               long[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch float
+
+    /**
+     * Finds and returns the index of the first mismatch between two {@code float}
+     * arrays, otherwise return -1 if no mismatch is found.  The index will be
+     * in the range of 0 (inclusive) up to the length (inclusive) of the smaller
+     * array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     Float.compare(a[pl], b[pl]) != 0
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(float[] a, float[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code float} arrays over the specified ranges, otherwise return -1 if no
+     * mismatch is found.  The index will be in the range of 0 (inclusive) up to
+     * the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     Float.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(float[] a, int aFromIndex, int aToIndex,
+                               float[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch double
+
+    /**
+     * Finds and returns the index of the first mismatch between two
+     * {@code double} arrays, otherwise return -1 if no mismatch is found.  The
+     * index will be in the range of 0 (inclusive) up to the length (inclusive)
+     * of the smaller array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     Double.compare(a[pl], b[pl]) != 0
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(double[] a, double[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        int i = ArraysSupport.mismatch(a, b, length);
+        return (i < 0 && a.length != b.length) ? length : i;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code double} arrays over the specified ranges, otherwise return -1 if
+     * no mismatch is found.  The index will be in the range of 0 (inclusive) up
+     * to the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     Double.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(double[] a, int aFromIndex, int aToIndex,
+                               double[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        int i = ArraysSupport.mismatch(a, aFromIndex,
+                                       b, bFromIndex,
+                                       length);
+        return (i < 0 && aLength != bLength) ? length : i;
+    }
+
+    // Mismatch objects
+
+    /**
+     * Finds and returns the index of the first mismatch between two
+     * {@code Object} arrays, otherwise return -1 if no mismatch is found.  The
+     * index will be in the range of 0 (inclusive) up to the length (inclusive)
+     * of the smaller array.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl) &&
+     *     !Objects.equals(a[pl], b[pl])
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(Object[] a, Object[] b) {
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        for (int i = 0; i < length; i++) {
+            if (!Objects.equals(a[i], b[i]))
+                return i;
+        }
+
+        return a.length != b.length ? length : -1;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code Object} arrays over the specified ranges, otherwise return -1 if
+     * no mismatch is found.  The index will be in the range of 0 (inclusive) up
+     * to the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl) &&
+     *     !Objects.equals(a[aFromIndex + pl], b[bFromIndex + pl])
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex))
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array is {@code null}
+     * @since 9
+     */
+    public static int mismatch(
+            Object[] a, int aFromIndex, int aToIndex,
+            Object[] b, int bFromIndex, int bToIndex) {
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        for (int i = 0; i < length; i++) {
+            if (!Objects.equals(a[aFromIndex++], b[bFromIndex++]))
+                return i;
+        }
+
+        return aLength != bLength ? length : -1;
+    }
+
+    /**
+     * Finds and returns the index of the first mismatch between two
+     * {@code Object} arrays, otherwise return -1 if no mismatch is found.
+     * The index will be in the range of 0 (inclusive) up to the length
+     * (inclusive) of the smaller array.
+     *
+     * <p>The specified comparator is used to determine if two array elements
+     * from the each array are not equal.
+     *
+     * <p>If the two arrays share a common prefix then the returned index is the
+     * length of the common prefix and it follows that there is a mismatch
+     * between the two elements at that index within the respective arrays.
+     * If one array is a proper prefix of the other then the returned index is
+     * the length of the smaller array and it follows that the index is only
+     * valid for the larger array.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(a.length, b.length) &&
+     *     Arrays.equals(a, 0, pl, b, 0, pl, cmp)
+     *     cmp.compare(a[pl], b[pl]) != 0
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b}, share a proper
+     * prefix if the following expression is true:
+     * <pre>{@code
+     *     a.length != b.length &&
+     *     Arrays.equals(a, 0, Math.min(a.length, b.length),
+     *                   b, 0, Math.min(a.length, b.length),
+     *                   cmp)
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @param cmp the comparator to compare array elements
+     * @param <T> the type of array elements
+     * @return the index of the first mismatch between the two arrays,
+     *         otherwise {@code -1}.
+     * @throws NullPointerException
+     *         if either array or the comparator is {@code null}
+     * @since 9
+     */
+    public static <T> int mismatch(T[] a, T[] b, Comparator<? super T> cmp) {
+        Objects.requireNonNull(cmp);
+        int length = Math.min(a.length, b.length); // Check null array refs
+        if (a == b)
+            return -1;
+
+        for (int i = 0; i < length; i++) {
+            T oa = a[i];
+            T ob = b[i];
+            if (oa != ob) {
+                // Null-value comparison is deferred to the comparator
+                int v = cmp.compare(oa, ob);
+                if (v != 0) {
+                    return i;
+                }
+            }
+        }
+
+        return a.length != b.length ? length : -1;
+    }
+
+    /**
+     * Finds and returns the relative index of the first mismatch between two
+     * {@code Object} arrays over the specified ranges, otherwise return -1 if
+     * no mismatch is found.  The index will be in the range of 0 (inclusive) up
+     * to the length (inclusive) of the smaller range.
+     *
+     * <p>If the two arrays, over the specified ranges, share a common prefix
+     * then the returned relative index is the length of the common prefix and
+     * it follows that there is a mismatch between the two elements at that
+     * relative index within the respective arrays.
+     * If one array is a proper prefix of the other, over the specified ranges,
+     * then the returned relative index is the length of the smaller range and
+     * it follows that the relative index is only valid for the array with the
+     * larger range.
+     * Otherwise, there is no mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a common
+     * prefix of length {@code pl} if the following expression is true:
+     * <pre>{@code
+     *     pl >= 0 &&
+     *     pl < Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, aFromIndex, aFromIndex + pl, b, bFromIndex, bFromIndex + pl, cmp) &&
+     *     cmp.compare(a[aFromIndex + pl], b[bFromIndex + pl]) != 0
+     * }</pre>
+     * Note that a common prefix length of {@code 0} indicates that the first
+     * elements from each array mismatch.
+     *
+     * <p>Two non-{@code null} arrays, {@code a} and {@code b} with specified
+     * ranges [{@code aFromIndex}, {@code atoIndex}) and
+     * [{@code bFromIndex}, {@code btoIndex}) respectively, share a proper
+     * if the following expression is true:
+     * <pre>{@code
+     *     (aToIndex - aFromIndex) != (bToIndex - bFromIndex) &&
+     *     Arrays.equals(a, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   b, 0, Math.min(aToIndex - aFromIndex, bToIndex - bFromIndex),
+     *                   cmp)
+     * }</pre>
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index (inclusive) of the first element in the
+     *                   first array to be tested
+     * @param aToIndex the index (exclusive) of the last element in the
+     *                 first array to be tested
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index (inclusive) of the first element in the
+     *                   second array to be tested
+     * @param bToIndex the index (exclusive) of the last element in the
+     *                 second array to be tested
+     * @param cmp the comparator to compare array elements
+     * @param <T> the type of array elements
+     * @return the relative index of the first mismatch between the two arrays
+     *         over the specified ranges, otherwise {@code -1}.
+     * @throws IllegalArgumentException
+     *         if {@code aFromIndex > aToIndex} or
+     *         if {@code bFromIndex > bToIndex}
+     * @throws ArrayIndexOutOfBoundsException
+     *         if {@code aFromIndex < 0 or aToIndex > a.length} or
+     *         if {@code bFromIndex < 0 or bToIndex > b.length}
+     * @throws NullPointerException
+     *         if either array or the comparator is {@code null}
+     * @since 9
+     */
+    public static <T> int mismatch(
+            T[] a, int aFromIndex, int aToIndex,
+            T[] b, int bFromIndex, int bToIndex,
+            Comparator<? super T> cmp) {
+        Objects.requireNonNull(cmp);
+        rangeCheck(a.length, aFromIndex, aToIndex);
+        rangeCheck(b.length, bFromIndex, bToIndex);
+
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        int length = Math.min(aLength, bLength);
+        for (int i = 0; i < length; i++) {
+            T oa = a[aFromIndex++];
+            T ob = b[bFromIndex++];
+            if (oa != ob) {
+                // Null-value comparison is deferred to the comparator
+                int v = cmp.compare(oa, ob);
+                if (v != 0) {
+                    return i;
+                }
+            }
+        }
+
+        return aLength != bLength ? length : -1;
+    }
 }
diff --git a/ojluni/src/main/java/java/util/ArraysParallelSortHelpers.java b/ojluni/src/main/java/java/util/ArraysParallelSortHelpers.java
index 8fa2262..3e0ef5a 100644
--- a/ojluni/src/main/java/java/util/ArraysParallelSortHelpers.java
+++ b/ojluni/src/main/java/java/util/ArraysParallelSortHelpers.java
@@ -130,15 +130,15 @@
                 int b = this.base, n = this.size, wb = this.wbase, g = this.gran;
                 while (n > g) {
                     int h = n >>> 1, q = h >>> 1, u = h + q; // quartiles
-                    Relay fc = new Relay(new Merger<T>(s, w, a, wb, h,
-                                                       wb+h, n-h, b, g, c));
-                    Relay rc = new Relay(new Merger<T>(fc, a, w, b+h, q,
-                                                       b+u, n-u, wb+h, g, c));
-                    new Sorter<T>(rc, a, w, b+u, n-u, wb+u, g, c).fork();
-                    new Sorter<T>(rc, a, w, b+h, q, wb+h, g, c).fork();;
-                    Relay bc = new Relay(new Merger<T>(fc, a, w, b, q,
-                                                       b+q, h-q, wb, g, c));
-                    new Sorter<T>(bc, a, w, b+q, h-q, wb+q, g, c).fork();
+                    Relay fc = new Relay(new Merger<>(s, w, a, wb, h,
+                                                      wb+h, n-h, b, g, c));
+                    Relay rc = new Relay(new Merger<>(fc, a, w, b+h, q,
+                                                      b+u, n-u, wb+h, g, c));
+                    new Sorter<>(rc, a, w, b+u, n-u, wb+u, g, c).fork();
+                    new Sorter<>(rc, a, w, b+h, q, wb+h, g, c).fork();;
+                    Relay bc = new Relay(new Merger<>(fc, a, w, b, q,
+                                                      b+q, h-q, wb, g, c));
+                    new Sorter<>(bc, a, w, b+q, h-q, wb+q, g, c).fork();
                     s = new EmptyCompleter(bc);
                     n = q;
                 }
@@ -199,9 +199,9 @@
                                 lo = lm + 1;
                         }
                     }
-                    Merger<T> m = new Merger<T>(this, a, w, lb + lh, ln - lh,
-                                                rb + rh, rn - rh,
-                                                k + lh + rh, g, c);
+                    Merger<T> m = new Merger<>(this, a, w, lb + lh, ln - lh,
+                                               rb + rh, rn - rh,
+                                               k + lh + rh, g, c);
                     rn = rh;
                     ln = lh;
                     addToPendingCount(1);
diff --git a/ojluni/src/main/java/java/util/BitSet.java b/ojluni/src/main/java/java/util/BitSet.java
index 261a77c..c72970d 100644
--- a/ojluni/src/main/java/java/util/BitSet.java
+++ b/ojluni/src/main/java/java/util/BitSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.LongBuffer;
+import java.util.function.IntConsumer;
 import java.util.stream.IntStream;
 import java.util.stream.StreamSupport;
 
@@ -60,7 +61,7 @@
  * @author  Arthur van Hoff
  * @author  Michael McCloskey
  * @author  Martin Buchholz
- * @since   JDK1.0
+ * @since   1.0
  */
 public class BitSet implements Cloneable, java.io.Serializable {
     /*
@@ -68,9 +69,9 @@
      * a long, which consists of 64 bits, requiring 6 address bits.
      * The choice of word size is determined purely by performance concerns.
      */
-    private final static int ADDRESS_BITS_PER_WORD = 6;
-    private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
-    private final static int BIT_INDEX_MASK = BITS_PER_WORD - 1;
+    private static final int ADDRESS_BITS_PER_WORD = 6;
+    private static final int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
+    private static final int BIT_INDEX_MASK = BITS_PER_WORD - 1;
 
     /* Used to shift left or right for a partial word mask */
     private static final long WORD_MASK = 0xffffffffffffffffL;
@@ -437,7 +438,7 @@
      *
      * @param  bitIndex a bit index
      * @throws IndexOutOfBoundsException if the specified index is negative
-     * @since  JDK1.0
+     * @since  1.0
      */
     public void set(int bitIndex) {
         if (bitIndex < 0)
@@ -533,7 +534,7 @@
      *
      * @param  bitIndex the index of the bit to be cleared
      * @throws IndexOutOfBoundsException if the specified index is negative
-     * @since  JDK1.0
+     * @since  1.0
      */
     public void clear(int bitIndex) {
         if (bitIndex < 0)
@@ -1209,40 +1210,186 @@
      * is the number of bits in the set state, equal to the value
      * returned by the {@link #cardinality()} method.
      *
-     * <p>The bit set must remain constant during the execution of the
-     * terminal stream operation.  Otherwise, the result of the terminal
-     * stream operation is undefined.
+     * <p>The stream binds to this bit set when the terminal stream operation
+     * commences (specifically, the spliterator for the stream is
+     * <a href="Spliterator.html#binding"><em>late-binding</em></a>).  If the
+     * bit set is modified during that operation then the result is undefined.
      *
      * @return a stream of integers representing set indices
      * @since 1.8
      */
     public IntStream stream() {
-        class BitSetIterator implements PrimitiveIterator.OfInt {
-            int next = nextSetBit(0);
+        class BitSetSpliterator implements Spliterator.OfInt {
+            private int index; // current bit index for a set bit
+            private int fence; // -1 until used; then one past last bit index
+            private int est;   // size estimate
+            private boolean root; // true if root and not split
+            // root == true then size estimate is accurate
+            // index == -1 or index >= fence if fully traversed
+            // Special case when the max bit set is Integer.MAX_VALUE
 
-            @Override
-            public boolean hasNext() {
-                return next != -1;
+            BitSetSpliterator(int origin, int fence, int est, boolean root) {
+                this.index = origin;
+                this.fence = fence;
+                this.est = est;
+                this.root = root;
+            }
+
+            private int getFence() {
+                int hi;
+                if ((hi = fence) < 0) {
+                    // Round up fence to maximum cardinality for allocated words
+                    // This is sufficient and cheap for sequential access
+                    // When splitting this value is lowered
+                    hi = fence = (wordsInUse >= wordIndex(Integer.MAX_VALUE))
+                                 ? Integer.MAX_VALUE
+                                 : wordsInUse << ADDRESS_BITS_PER_WORD;
+                    est = cardinality();
+                    index = nextSetBit(0);
+                }
+                return hi;
             }
 
             @Override
-            public int nextInt() {
-                if (next != -1) {
-                    int ret = next;
-                    next = nextSetBit(next+1);
-                    return ret;
-                } else {
-                    throw new NoSuchElementException();
+            public boolean tryAdvance(IntConsumer action) {
+                Objects.requireNonNull(action);
+
+                int hi = getFence();
+                int i = index;
+                if (i < 0 || i >= hi) {
+                    // Check if there is a final bit set for Integer.MAX_VALUE
+                    if (i == Integer.MAX_VALUE && hi == Integer.MAX_VALUE) {
+                        index = -1;
+                        action.accept(Integer.MAX_VALUE);
+                        return true;
+                    }
+                    return false;
+                }
+
+                index = nextSetBit(i + 1, wordIndex(hi - 1));
+                action.accept(i);
+                return true;
+            }
+
+            @Override
+            public void forEachRemaining(IntConsumer action) {
+                Objects.requireNonNull(action);
+
+                int hi = getFence();
+                int i = index;
+                index = -1;
+
+                if (i >= 0 && i < hi) {
+                    action.accept(i++);
+
+                    int u = wordIndex(i);      // next lower word bound
+                    int v = wordIndex(hi - 1); // upper word bound
+
+                    words_loop:
+                    for (; u <= v && i <= hi; u++, i = u << ADDRESS_BITS_PER_WORD) {
+                        long word = words[u] & (WORD_MASK << i);
+                        while (word != 0) {
+                            i = (u << ADDRESS_BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
+                            if (i >= hi) {
+                                // Break out of outer loop to ensure check of
+                                // Integer.MAX_VALUE bit set
+                                break words_loop;
+                            }
+
+                            // Flip the set bit
+                            word &= ~(1L << i);
+
+                            action.accept(i);
+                        }
+                    }
+                }
+
+                // Check if there is a final bit set for Integer.MAX_VALUE
+                if (i == Integer.MAX_VALUE && hi == Integer.MAX_VALUE) {
+                    action.accept(Integer.MAX_VALUE);
                 }
             }
-        }
 
-        return StreamSupport.intStream(
-                () -> Spliterators.spliterator(
-                        new BitSetIterator(), cardinality(),
-                        Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED),
-                Spliterator.SIZED | Spliterator.SUBSIZED |
-                        Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED,
-                false);
+            @Override
+            public OfInt trySplit() {
+                int hi = getFence();
+                int lo = index;
+                if (lo < 0) {
+                    return null;
+                }
+
+                // Lower the fence to be the upper bound of last bit set
+                // The index is the first bit set, thus this spliterator
+                // covers one bit and cannot be split, or two or more
+                // bits
+                hi = fence = (hi < Integer.MAX_VALUE || !get(Integer.MAX_VALUE))
+                        ? previousSetBit(hi - 1) + 1
+                        : Integer.MAX_VALUE;
+
+                // Find the mid point
+                int mid = (lo + hi) >>> 1;
+                if (lo >= mid) {
+                    return null;
+                }
+
+                // Raise the index of this spliterator to be the next set bit
+                // from the mid point
+                index = nextSetBit(mid, wordIndex(hi - 1));
+                root = false;
+
+                // Don't lower the fence (mid point) of the returned spliterator,
+                // traversal or further splitting will do that work
+                return new BitSetSpliterator(lo, mid, est >>>= 1, false);
+            }
+
+            @Override
+            public long estimateSize() {
+                getFence(); // force init
+                return est;
+            }
+
+            @Override
+            public int characteristics() {
+                // Only sized when root and not split
+                return (root ? Spliterator.SIZED : 0) |
+                    Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED;
+            }
+
+            @Override
+            public Comparator<? super Integer> getComparator() {
+                return null;
+            }
+        }
+        return StreamSupport.intStream(new BitSetSpliterator(0, -1, 0, true), false);
     }
+
+    /**
+     * Returns the index of the first bit that is set to {@code true}
+     * that occurs on or after the specified starting index and up to and
+     * including the specified word index
+     * If no such bit exists then {@code -1} is returned.
+     *
+     * @param  fromIndex the index to start checking from (inclusive)
+     * @param  toWordIndex the last word index to check (inclusive)
+     * @return the index of the next set bit, or {@code -1} if there
+     *         is no such bit
+     */
+    private int nextSetBit(int fromIndex, int toWordIndex) {
+        int u = wordIndex(fromIndex);
+        // Check if out of bounds
+        if (u > toWordIndex)
+            return -1;
+
+        long word = words[u] & (WORD_MASK << fromIndex);
+
+        while (true) {
+            if (word != 0)
+                return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
+            // Check if out of bounds
+            if (++u > toWordIndex)
+                return -1;
+            word = words[u];
+        }
+    }
+
 }
diff --git a/ojluni/src/main/java/java/util/Collection.java b/ojluni/src/main/java/java/util/Collection.java
index 279ec9e..dd773bc 100644
--- a/ojluni/src/main/java/java/util/Collection.java
+++ b/ojluni/src/main/java/java/util/Collection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 package java.util;
 
+import java.util.function.IntFunction;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
@@ -35,41 +36,37 @@
  * collections allow duplicate elements and others do not.  Some are ordered
  * and others unordered.  The JDK does not provide any <i>direct</i>
  * implementations of this interface: it provides implementations of more
- * specific subinterfaces like <tt>Set</tt> and <tt>List</tt>.  This interface
+ * specific subinterfaces like {@code Set} and {@code List}.  This interface
  * is typically used to pass collections around and manipulate them where
  * maximum generality is desired.
  *
  * <p><i>Bags</i> or <i>multisets</i> (unordered collections that may contain
  * duplicate elements) should implement this interface directly.
  *
- * <p>All general-purpose <tt>Collection</tt> implementation classes (which
- * typically implement <tt>Collection</tt> indirectly through one of its
+ * <p>All general-purpose {@code Collection} implementation classes (which
+ * typically implement {@code Collection} indirectly through one of its
  * subinterfaces) should provide two "standard" constructors: a void (no
  * arguments) constructor, which creates an empty collection, and a
- * constructor with a single argument of type <tt>Collection</tt>, which
+ * constructor with a single argument of type {@code Collection}, which
  * creates a new collection with the same elements as its argument.  In
  * effect, the latter constructor allows the user to copy any collection,
  * producing an equivalent collection of the desired implementation type.
  * There is no way to enforce this convention (as interfaces cannot contain
- * constructors) but all of the general-purpose <tt>Collection</tt>
+ * constructors) but all of the general-purpose {@code Collection}
  * implementations in the Java platform libraries comply.
  *
- * <p>The "destructive" methods contained in this interface, that is, the
- * methods that modify the collection on which they operate, are specified to
- * throw <tt>UnsupportedOperationException</tt> if this collection does not
- * support the operation.  If this is the case, these methods may, but are not
- * required to, throw an <tt>UnsupportedOperationException</tt> if the
- * invocation would have no effect on the collection.  For example, invoking
- * the {@link #addAll(Collection)} method on an unmodifiable collection may,
- * but is not required to, throw the exception if the collection to be added
- * is empty.
+ * <p>Certain methods are specified to be
+ * <i>optional</i>. If a collection implementation doesn't implement a
+ * particular operation, it should define the corresponding method to throw
+ * {@code UnsupportedOperationException}. Such methods are marked "optional
+ * operation" in method specifications of the collections interfaces.
  *
- * <p><a name="optional-restrictions">
- * Some collection implementations have restrictions on the elements that
- * they may contain.</a>  For example, some implementations prohibit null elements,
+ * <p><a id="optional-restrictions"></a>Some collection implementations
+ * have restrictions on the elements that they may contain.
+ * For example, some implementations prohibit null elements,
  * and some have restrictions on the types of their elements.  Attempting to
  * add an ineligible element throws an unchecked exception, typically
- * <tt>NullPointerException</tt> or <tt>ClassCastException</tt>.  Attempting
+ * {@code NullPointerException} or {@code ClassCastException}.  Attempting
  * to query the presence of an ineligible element may throw an exception,
  * or it may simply return false; some implementations will exhibit the former
  * behavior and some will exhibit the latter.  More generally, attempting an
@@ -90,13 +87,13 @@
  * <p>Many methods in Collections Framework interfaces are defined in
  * terms of the {@link Object#equals(Object) equals} method.  For example,
  * the specification for the {@link #contains(Object) contains(Object o)}
- * method says: "returns <tt>true</tt> if and only if this collection
- * contains at least one element <tt>e</tt> such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>."  This specification should
- * <i>not</i> be construed to imply that invoking <tt>Collection.contains</tt>
- * with a non-null argument <tt>o</tt> will cause <tt>o.equals(e)</tt> to be
- * invoked for any element <tt>e</tt>.  Implementations are free to implement
- * optimizations whereby the <tt>equals</tt> invocation is avoided, for
+ * method says: "returns {@code true} if and only if this collection
+ * contains at least one element {@code e} such that
+ * {@code (o==null ? e==null : o.equals(e))}."  This specification should
+ * <i>not</i> be construed to imply that invoking {@code Collection.contains}
+ * with a non-null argument {@code o} will cause {@code o.equals(e)} to be
+ * invoked for any element {@code e}.  Implementations are free to implement
+ * optimizations whereby the {@code equals} invocation is avoided, for
  * example, by first comparing the hash codes of the two elements.  (The
  * {@link Object#hashCode()} specification guarantees that two objects with
  * unequal hash codes cannot be equal.)  More generally, implementations of
@@ -111,8 +108,88 @@
  * methods. Implementations may optionally handle the self-referential scenario,
  * however most current implementations do not do so.
  *
+ * <h2><a id="view">View Collections</a></h2>
+ *
+ * <p>Most collections manage storage for elements they contain. By contrast, <i>view
+ * collections</i> themselves do not store elements, but instead they rely on a
+ * backing collection to store the actual elements. Operations that are not handled
+ * by the view collection itself are delegated to the backing collection. Examples of
+ * view collections include the wrapper collections returned by methods such as
+ * {@link Collections#checkedCollection Collections.checkedCollection},
+ * {@link Collections#synchronizedCollection Collections.synchronizedCollection}, and
+ * {@link Collections#unmodifiableCollection Collections.unmodifiableCollection}.
+ * Other examples of view collections include collections that provide a
+ * different representation of the same elements, for example, as
+ * provided by {@link List#subList List.subList},
+ * {@link NavigableSet#subSet NavigableSet.subSet}, or
+ * {@link Map#entrySet Map.entrySet}.
+ * Any changes made to the backing collection are visible in the view collection.
+ * Correspondingly, any changes made to the view collection &mdash; if changes
+ * are permitted &mdash; are written through to the backing collection.
+ * Although they technically aren't collections, instances of
+ * {@link Iterator} and {@link ListIterator} can also allow modifications
+ * to be written through to the backing collection, and in some cases,
+ * modifications to the backing collection will be visible to the Iterator
+ * during iteration.
+ *
+ * <h2><a id="unmodifiable">Unmodifiable Collections</a></h2>
+ *
+ * <p>Certain methods of this interface are considered "destructive" and are called
+ * "mutator" methods in that they modify the group of objects contained within
+ * the collection on which they operate. They can be specified to throw
+ * {@code UnsupportedOperationException} if this collection implementation
+ * does not support the operation. Such methods should (but are not required
+ * to) throw an {@code UnsupportedOperationException} if the invocation would
+ * have no effect on the collection. For example, consider a collection that
+ * does not support the {@link #add add} operation. What will happen if the
+ * {@link #addAll addAll} method is invoked on this collection, with an empty
+ * collection as the argument? The addition of zero elements has no effect,
+ * so it is permissible for this collection simply to do nothing and not to throw
+ * an exception. However, it is recommended that such cases throw an exception
+ * unconditionally, as throwing only in certain cases can lead to
+ * programming errors.
+ *
+ * <p>An <i>unmodifiable collection</i> is a collection, all of whose
+ * mutator methods (as defined above) are specified to throw
+ * {@code UnsupportedOperationException}. Such a collection thus cannot be
+ * modified by calling any methods on it. For a collection to be properly
+ * unmodifiable, any view collections derived from it must also be unmodifiable.
+ * For example, if a List is unmodifiable, the List returned by
+ * {@link List#subList List.subList} is also unmodifiable.
+ *
+ * <p>An unmodifiable collection is not necessarily immutable. If the
+ * contained elements are mutable, the entire collection is clearly
+ * mutable, even though it might be unmodifiable. For example, consider
+ * two unmodifiable lists containing mutable elements. The result of calling
+ * {@code list1.equals(list2)} might differ from one call to the next if
+ * the elements had been mutated, even though both lists are unmodifiable.
+ * However, if an unmodifiable collection contains all immutable elements,
+ * it can be considered effectively immutable.
+ *
+ * <h2><a id="unmodview">Unmodifiable View Collections</a></h2>
+ *
+ * <p>An <i>unmodifiable view collection</i> is a collection that is unmodifiable
+ * and that is also a view onto a backing collection. Its mutator methods throw
+ * {@code UnsupportedOperationException}, as described above, while
+ * reading and querying methods are delegated to the backing collection.
+ * The effect is to provide read-only access to the backing collection.
+ * This is useful for a component to provide users with read access to
+ * an internal collection, while preventing them from modifying such
+ * collections unexpectedly. Examples of unmodifiable view collections
+ * are those returned by the
+ * {@link Collections#unmodifiableCollection Collections.unmodifiableCollection},
+ * {@link Collections#unmodifiableList Collections.unmodifiableList}, and
+ * related methods.
+ *
+ * <p>Note that changes to the backing collection might still be possible,
+ * and if they occur, they are visible through the unmodifiable view. Thus,
+ * an unmodifiable view collection is not necessarily immutable. However,
+ * if the backing collection of an unmodifiable view is effectively immutable,
+ * or if the only reference to the backing collection is through an
+ * unmodifiable view, the view can be considered effectively immutable.
+ *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @implSpec
@@ -146,35 +223,35 @@
 
     /**
      * Returns the number of elements in this collection.  If this collection
-     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
-     * <tt>Integer.MAX_VALUE</tt>.
+     * contains more than {@code Integer.MAX_VALUE} elements, returns
+     * {@code Integer.MAX_VALUE}.
      *
      * @return the number of elements in this collection
      */
     int size();
 
     /**
-     * Returns <tt>true</tt> if this collection contains no elements.
+     * Returns {@code true} if this collection contains no elements.
      *
-     * @return <tt>true</tt> if this collection contains no elements
+     * @return {@code true} if this collection contains no elements
      */
     boolean isEmpty();
 
     /**
-     * Returns <tt>true</tt> if this collection contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this collection
-     * contains at least one element <tt>e</tt> such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     * Returns {@code true} if this collection contains the specified element.
+     * More formally, returns {@code true} if and only if this collection
+     * contains at least one element {@code e} such that
+     * {@code Objects.equals(o, e)}.
      *
      * @param o element whose presence in this collection is to be tested
-     * @return <tt>true</tt> if this collection contains the specified
+     * @return {@code true} if this collection contains the specified
      *         element
      * @throws ClassCastException if the type of the specified element
      *         is incompatible with this collection
-     *         (<a href="#optional-restrictions">optional</a>)
+     *         (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null and this
      *         collection does not permit null elements
-     *         (<a href="#optional-restrictions">optional</a>)
+     *         (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean contains(Object o);
 
@@ -184,7 +261,7 @@
      * (unless this collection is an instance of some class that provides a
      * guarantee).
      *
-     * @return an <tt>Iterator</tt> over the elements in this collection
+     * @return an {@code Iterator} over the elements in this collection
      */
     Iterator<E> iterator();
 
@@ -192,17 +269,23 @@
      * Returns an array containing all of the elements in this collection.
      * If this collection makes any guarantees as to what order its elements
      * are returned by its iterator, this method must return the elements in
-     * the same order.
+     * the same order. The returned array's {@linkplain Class#getComponentType
+     * runtime component type} is {@code Object}.
      *
      * <p>The returned array will be "safe" in that no references to it are
      * maintained by this collection.  (In other words, this method must
      * allocate a new array even if this collection is backed by an array).
      * The caller is thus free to modify the returned array.
      *
-     * <p>This method acts as bridge between array-based and collection-based
-     * APIs.
+     * @apiNote
+     * This method acts as a bridge between array-based and collection-based APIs.
+     * It returns an array whose runtime type is {@code Object[]}.
+     * Use {@link #toArray(Object[]) toArray(T[])} to reuse an existing
+     * array, or use {@link #toArray(IntFunction)} to control the runtime type
+     * of the array.
      *
-     * @return an array containing all of the elements in this collection
+     * @return an array, whose {@linkplain Class#getComponentType runtime component
+     * type} is {@code Object}, containing all of the elements in this collection
      */
     Object[] toArray();
 
@@ -216,66 +299,113 @@
      * <p>If this collection fits in the specified array with room to spare
      * (i.e., the array has more elements than this collection), the element
      * in the array immediately following the end of the collection 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
      * collection <i>only</i> if the caller knows that this collection does
-     * not contain any <tt>null</tt> elements.)
+     * not contain any {@code null} elements.)
      *
      * <p>If this collection makes any guarantees as to what order its elements
      * are returned by its iterator, this method must return the elements in
      * the same order.
      *
-     * <p>Like the {@link #toArray()} method, this method acts as bridge between
-     * array-based and collection-based APIs.  Further, this method allows
-     * precise control over the runtime type of the output array, and may,
-     * under certain circumstances, be used to save allocation costs.
+     * @apiNote
+     * This method acts as a bridge between array-based and collection-based APIs.
+     * It allows an existing array to be reused under certain circumstances.
+     * Use {@link #toArray()} to create an array whose runtime type is {@code Object[]},
+     * or use {@link #toArray(IntFunction)} to control the runtime type of
+     * the array.
      *
-     * <p>Suppose <tt>x</tt> is a collection known to contain only strings.
-     * The following code can be used to dump the collection into a newly
-     * allocated array of <tt>String</tt>:
+     * <p>Suppose {@code x} is a collection known to contain only strings.
+     * The following code can be used to dump the collection into a previously
+     * allocated {@code String} array:
      *
      * <pre>
-     *     String[] y = x.toArray(new String[0]);</pre>
+     *     String[] y = new String[SIZE];
+     *     ...
+     *     y = x.toArray(y);</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * <p>The return value is reassigned to the variable {@code y}, because a
+     * new array will be allocated and returned if the collection {@code x} has
+     * too many elements to fit into the existing array {@code y}.
      *
-     * @param <T> the runtime type of the array to contain the collection
+     * <p>Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
+     *
+     * @param <T> the component type of the array to contain the collection
      * @param a the array into which the elements of this collection are to be
      *        stored, if it is big enough; otherwise, a new array of the same
      *        runtime type is allocated for this purpose.
      * @return an array containing all of the elements in this collection
-     * @throws ArrayStoreException if the runtime type of the specified array
-     *         is not a supertype of the runtime type of every element in
-     *         this collection
+     * @throws ArrayStoreException if the runtime type of any element in this
+     *         collection is not assignable to the {@linkplain Class#getComponentType
+     *         runtime component type} of the specified array
      * @throws NullPointerException if the specified array is null
      */
     <T> T[] toArray(T[] a);
 
+    /**
+     * Returns an array containing all of the elements in this collection,
+     * using the provided {@code generator} function to allocate the returned array.
+     *
+     * <p>If this collection makes any guarantees as to what order its elements
+     * are returned by its iterator, this method must return the elements in
+     * the same order.
+     *
+     * @apiNote
+     * This method acts as a bridge between array-based and collection-based APIs.
+     * It allows creation of an array of a particular runtime type. Use
+     * {@link #toArray()} to create an array whose runtime type is {@code Object[]},
+     * or use {@link #toArray(Object[]) toArray(T[])} to reuse an existing array.
+     *
+     * <p>Suppose {@code x} is a collection known to contain only strings.
+     * The following code can be used to dump the collection into a newly
+     * allocated array of {@code String}:
+     *
+     * <pre>
+     *     String[] y = x.toArray(String[]::new);</pre>
+     *
+     * @implSpec
+     * The default implementation calls the generator function with zero
+     * and then passes the resulting array to {@link #toArray(Object[]) toArray(T[])}.
+     *
+     * @param <T> the component type of the array to contain the collection
+     * @param generator a function which produces a new array of the desired
+     *                  type and the provided length
+     * @return an array containing all of the elements in this collection
+     * @throws ArrayStoreException if the runtime type of any element in this
+     *         collection is not assignable to the {@linkplain Class#getComponentType
+     *         runtime component type} of the generated array
+     * @throws NullPointerException if the generator function is null
+     * @since 11
+     */
+    default <T> T[] toArray(IntFunction<T[]> generator) {
+        return toArray(generator.apply(0));
+    }
+
     // Modification Operations
 
     /**
      * Ensures that this collection contains the specified element (optional
-     * operation).  Returns <tt>true</tt> if this collection changed as a
-     * result of the call.  (Returns <tt>false</tt> if this collection does
+     * operation).  Returns {@code true} if this collection changed as a
+     * result of the call.  (Returns {@code false} if this collection does
      * not permit duplicates and already contains the specified element.)<p>
      *
      * Collections that support this operation may place limitations on what
      * elements may be added to this collection.  In particular, some
-     * collections will refuse to add <tt>null</tt> elements, and others will
+     * collections will refuse to add {@code null} elements, and others will
      * impose restrictions on the type of elements that may be added.
      * Collection classes should clearly specify in their documentation any
      * restrictions on what elements may be added.<p>
      *
      * If a collection refuses to add a particular element for any reason
      * other than that it already contains the element, it <i>must</i> throw
-     * an exception (rather than returning <tt>false</tt>).  This preserves
+     * an exception (rather than returning {@code false}).  This preserves
      * the invariant that a collection always contains the specified element
      * after this call returns.
      *
      * @param e element whose presence in this collection is to be ensured
-     * @return <tt>true</tt> if this collection changed as a result of the
+     * @return {@code true} if this collection changed as a result of the
      *         call
-     * @throws UnsupportedOperationException if the <tt>add</tt> operation
+     * @throws UnsupportedOperationException if the {@code add} operation
      *         is not supported by this collection
      * @throws ClassCastException if the class of the specified element
      *         prevents it from being added to this collection
@@ -291,14 +421,14 @@
     /**
      * Removes a single instance of the specified element from this
      * collection, if it is present (optional operation).  More formally,
-     * removes an element <tt>e</tt> such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>, if
+     * removes an element {@code e} such that
+     * {@code Objects.equals(o, e)}, if
      * this collection contains one or more such elements.  Returns
-     * <tt>true</tt> if this collection contained the specified element (or
+     * {@code true} if this collection contained the specified element (or
      * equivalently, if this collection changed as a result of the call).
      *
      * @param o element to be removed from this collection, 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 type of the specified element
      *         is incompatible with this collection
      *         (<a href="#optional-restrictions">optional</a>)
@@ -314,11 +444,11 @@
     // Bulk Operations
 
     /**
-     * Returns <tt>true</tt> if this collection contains all of the elements
+     * Returns {@code true} if this collection contains all of the elements
      * in the specified collection.
      *
      * @param  c collection to be checked for containment in this collection
-     * @return <tt>true</tt> if this collection contains all of the elements
+     * @return {@code true} if this collection contains all of the elements
      *         in the specified collection
      * @throws ClassCastException if the types of one or more elements
      *         in the specified collection are incompatible with this
@@ -342,8 +472,8 @@
      * nonempty.)
      *
      * @param c collection containing elements to be added to this collection
-     * @return <tt>true</tt> if this collection changed as a result of the call
-     * @throws UnsupportedOperationException if the <tt>addAll</tt> operation
+     * @return {@code true} if this collection changed as a result of the call
+     * @throws UnsupportedOperationException if the {@code addAll} operation
      *         is not supported by this collection
      * @throws ClassCastException if the class of an element of the specified
      *         collection prevents it from being added to this collection
@@ -366,9 +496,9 @@
      * collection.
      *
      * @param c collection containing elements to be removed from this collection
-     * @return <tt>true</tt> if this collection changed as a result of the
+     * @return {@code true} if this collection changed as a result of the
      *         call
-     * @throws UnsupportedOperationException if the <tt>removeAll</tt> method
+     * @throws UnsupportedOperationException if the {@code removeAll} method
      *         is not supported by this collection
      * @throws ClassCastException if the types of one or more elements
      *         in this collection are incompatible with the specified
@@ -426,8 +556,8 @@
      * specified collection.
      *
      * @param c collection containing elements to be retained in this collection
-     * @return <tt>true</tt> if this collection changed as a result of the call
-     * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation
+     * @return {@code true} if this collection changed as a result of the call
+     * @throws UnsupportedOperationException if the {@code retainAll} operation
      *         is not supported by this collection
      * @throws ClassCastException if the types of one or more elements
      *         in this collection are incompatible with the specified
@@ -447,7 +577,7 @@
      * Removes all of the elements from this collection (optional operation).
      * The collection will be empty after this method returns.
      *
-     * @throws UnsupportedOperationException if the <tt>clear</tt> operation
+     * @throws UnsupportedOperationException if the {@code clear} operation
      *         is not supported by this collection
      */
     void clear();
@@ -458,30 +588,30 @@
     /**
      * Compares the specified object with this collection for equality. <p>
      *
-     * While the <tt>Collection</tt> interface adds no stipulations to the
-     * general contract for the <tt>Object.equals</tt>, programmers who
-     * implement the <tt>Collection</tt> interface "directly" (in other words,
-     * create a class that is a <tt>Collection</tt> but is not a <tt>Set</tt>
-     * or a <tt>List</tt>) must exercise care if they choose to override the
-     * <tt>Object.equals</tt>.  It is not necessary to do so, and the simplest
-     * course of action is to rely on <tt>Object</tt>'s implementation, but
+     * While the {@code Collection} interface adds no stipulations to the
+     * general contract for the {@code Object.equals}, programmers who
+     * implement the {@code Collection} interface "directly" (in other words,
+     * create a class that is a {@code Collection} but is not a {@code Set}
+     * or a {@code List}) must exercise care if they choose to override the
+     * {@code Object.equals}.  It is not necessary to do so, and the simplest
+     * course of action is to rely on {@code Object}'s implementation, but
      * the implementor may wish to implement a "value comparison" in place of
-     * the default "reference comparison."  (The <tt>List</tt> and
-     * <tt>Set</tt> interfaces mandate such value comparisons.)<p>
+     * the default "reference comparison."  (The {@code List} and
+     * {@code Set} interfaces mandate such value comparisons.)<p>
      *
-     * The general contract for the <tt>Object.equals</tt> method states that
-     * equals must be symmetric (in other words, <tt>a.equals(b)</tt> if and
-     * only if <tt>b.equals(a)</tt>).  The contracts for <tt>List.equals</tt>
-     * and <tt>Set.equals</tt> state that lists are only equal to other lists,
-     * and sets to other sets.  Thus, a custom <tt>equals</tt> method for a
-     * collection class that implements neither the <tt>List</tt> nor
-     * <tt>Set</tt> interface must return <tt>false</tt> when this collection
+     * The general contract for the {@code Object.equals} method states that
+     * equals must be symmetric (in other words, {@code a.equals(b)} if and
+     * only if {@code b.equals(a)}).  The contracts for {@code List.equals}
+     * and {@code Set.equals} state that lists are only equal to other lists,
+     * and sets to other sets.  Thus, a custom {@code equals} method for a
+     * collection class that implements neither the {@code List} nor
+     * {@code Set} interface must return {@code false} when this collection
      * is compared to any list or set.  (By the same logic, it is not possible
-     * to write a class that correctly implements both the <tt>Set</tt> and
-     * <tt>List</tt> interfaces.)
+     * to write a class that correctly implements both the {@code Set} and
+     * {@code List} interfaces.)
      *
      * @param o object to be compared for equality with this collection
-     * @return <tt>true</tt> if the specified object is equal to this
+     * @return {@code true} if the specified object is equal to this
      * collection
      *
      * @see Object#equals(Object)
@@ -492,13 +622,13 @@
 
     /**
      * Returns the hash code value for this collection.  While the
-     * <tt>Collection</tt> interface adds no stipulations to the general
-     * contract for the <tt>Object.hashCode</tt> method, programmers should
-     * take note that any class that overrides the <tt>Object.equals</tt>
-     * method must also override the <tt>Object.hashCode</tt> method in order
-     * to satisfy the general contract for the <tt>Object.hashCode</tt> method.
-     * In particular, <tt>c1.equals(c2)</tt> implies that
-     * <tt>c1.hashCode()==c2.hashCode()</tt>.
+     * {@code Collection} interface adds no stipulations to the general
+     * contract for the {@code Object.hashCode} method, programmers should
+     * take note that any class that overrides the {@code Object.equals}
+     * method must also override the {@code Object.hashCode} method in order
+     * to satisfy the general contract for the {@code Object.hashCode} method.
+     * In particular, {@code c1.equals(c2)} implies that
+     * {@code c1.hashCode()==c2.hashCode()}.
      *
      * @return the hash code value for this collection
      *
@@ -518,7 +648,7 @@
      * <p>The default implementation should be overridden by subclasses that
      * can return a more efficient spliterator.  In order to
      * preserve expected laziness behavior for the {@link #stream()} and
-     * {@link #parallelStream()}} methods, spliterators should either have the
+     * {@link #parallelStream()} methods, spliterators should either have the
      * characteristic of {@code IMMUTABLE} or {@code CONCURRENT}, or be
      * <em><a href="Spliterator.html#binding">late-binding</a></em>.
      * If none of these is practical, the overriding class should describe the
@@ -537,7 +667,7 @@
      * @implSpec
      * The default implementation creates a
      * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator
-     * from the collections's {@code Iterator}.  The spliterator inherits the
+     * from the collection's {@code Iterator}.  The spliterator inherits the
      * <em>fail-fast</em> properties of the collection's iterator.
      * <p>
      * The created {@code Spliterator} reports {@link Spliterator#SIZED}.
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index e7e8e72..58ad86f 100644
--- a/ojluni/src/main/java/java/util/Collections.java
+++ b/ojluni/src/main/java/java/util/Collections.java
@@ -70,7 +70,7 @@
  * already sorted may or may not throw <tt>UnsupportedOperationException</tt>.
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
diff --git a/ojluni/src/main/java/java/util/ComparableTimSort.java b/ojluni/src/main/java/java/util/ComparableTimSort.java
index 36c8d90..7b90807 100644
--- a/ojluni/src/main/java/java/util/ComparableTimSort.java
+++ b/ojluni/src/main/java/java/util/ComparableTimSort.java
@@ -305,7 +305,7 @@
      * @param a the array in which a run is to be counted and possibly reversed
      * @param lo index of the first element in the run
      * @param hi index after the last element that may be contained in the run.
-              It is required that {@code lo < hi}.
+     *        It is required that {@code lo < hi}.
      * @return  the length of the run beginning at the specified position in
      *          the specified array
      */
@@ -394,19 +394,23 @@
      * This method is called each time a new run is pushed onto the stack,
      * so the invariants are guaranteed to hold for i < stackSize upon
      * entry to the method.
+     *
+     * Thanks to Stijn de Gouw, Jurriaan Rot, Frank S. de Boer,
+     * Richard Bubel and Reiner Hahnle, this is fixed with respect to
+     * the analysis in "On the Worst-Case Complexity of TimSort" by
+     * Nicolas Auger, Vincent Jug, Cyril Nicaud, and Carine Pivoteau.
      */
     private void mergeCollapse() {
         while (stackSize > 1) {
             int n = stackSize - 2;
-            if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
+            if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1] ||
+                n > 1 && runLen[n-2] <= runLen[n] + runLen[n-1]) {
                 if (runLen[n - 1] < runLen[n + 1])
                     n--;
-                mergeAt(n);
-            } else if (runLen[n] <= runLen[n + 1]) {
-                mergeAt(n);
-            } else {
+            } else if (n < 0 || runLen[n] > runLen[n + 1]) {
                 break; // Invariant is established
             }
+            mergeAt(n);
         }
     }
 
@@ -883,12 +887,7 @@
     private Object[]  ensureCapacity(int minCapacity) {
         if (tmpLen < minCapacity) {
             // Compute smallest power of 2 > minCapacity
-            int newSize = minCapacity;
-            newSize |= newSize >> 1;
-            newSize |= newSize >> 2;
-            newSize |= newSize >> 4;
-            newSize |= newSize >> 8;
-            newSize |= newSize >> 16;
+            int newSize = -1 >>> Integer.numberOfLeadingZeros(minCapacity);
             newSize++;
 
             if (newSize < 0) // Not bloody likely!
diff --git a/ojluni/src/main/java/java/util/Comparator.java b/ojluni/src/main/java/java/util/Comparator.java
index 27cfdd5..0516559 100644
--- a/ojluni/src/main/java/java/util/Comparator.java
+++ b/ojluni/src/main/java/java/util/Comparator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,20 +42,20 @@
  * SortedMap sorted maps}), or to provide an ordering for collections of
  * objects that don't have a {@link Comparable natural ordering}.<p>
  *
- * The ordering imposed by a comparator <tt>c</tt> on a set of elements
- * <tt>S</tt> is said to be <i>consistent with equals</i> if and only if
- * <tt>c.compare(e1, e2)==0</tt> has the same boolean value as
- * <tt>e1.equals(e2)</tt> for every <tt>e1</tt> and <tt>e2</tt> in
- * <tt>S</tt>.<p>
+ * The ordering imposed by a comparator {@code c} on a set of elements
+ * {@code S} is said to be <i>consistent with equals</i> if and only if
+ * {@code c.compare(e1, e2)==0} has the same boolean value as
+ * {@code e1.equals(e2)} for every {@code e1} and {@code e2} in
+ * {@code S}.<p>
  *
  * Caution should be exercised when using a comparator capable of imposing an
  * ordering inconsistent with equals to order a sorted set (or sorted map).
- * Suppose a sorted set (or sorted map) with an explicit comparator <tt>c</tt>
- * is used with elements (or keys) drawn from a set <tt>S</tt>.  If the
- * ordering imposed by <tt>c</tt> on <tt>S</tt> is inconsistent with equals,
+ * Suppose a sorted set (or sorted map) with an explicit comparator {@code c}
+ * is used with elements (or keys) drawn from a set {@code S}.  If the
+ * ordering imposed by {@code c} on {@code S} is inconsistent with equals,
  * the sorted set (or sorted map) will behave "strangely."  In particular the
  * sorted set (or sorted map) will violate the general contract for set (or
- * map), which is defined in terms of <tt>equals</tt>.<p>
+ * map), which is defined in terms of {@code equals}.<p>
  *
  * For example, suppose one adds two elements {@code a} and {@code b} such that
  * {@code (a.equals(b) && c.compare(a, b) != 0)}
@@ -67,23 +67,23 @@
  * {@link Set#add Set.add} method.<p>
  *
  * Note: It is generally a good idea for comparators to also implement
- * <tt>java.io.Serializable</tt>, as they may be used as ordering methods in
+ * {@code java.io.Serializable}, as they may be used as ordering methods in
  * serializable data structures (like {@link TreeSet}, {@link TreeMap}).  In
  * order for the data structure to serialize successfully, the comparator (if
- * provided) must implement <tt>Serializable</tt>.<p>
+ * provided) must implement {@code Serializable}.<p>
  *
  * For the mathematically inclined, the <i>relation</i> that defines the
- * <i>imposed ordering</i> that a given comparator <tt>c</tt> imposes on a
- * given set of objects <tt>S</tt> is:<pre>
+ * <i>imposed ordering</i> that a given comparator {@code c} imposes on a
+ * given set of objects {@code S} is:<pre>
  *       {(x, y) such that c.compare(x, y) &lt;= 0}.
  * </pre> The <i>quotient</i> for this total order is:<pre>
  *       {(x, y) such that c.compare(x, y) == 0}.
  * </pre>
  *
- * It follows immediately from the contract for <tt>compare</tt> that the
- * quotient is an <i>equivalence relation</i> on <tt>S</tt>, and that the
- * imposed ordering is a <i>total order</i> on <tt>S</tt>.  When we say that
- * the ordering imposed by <tt>c</tt> on <tt>S</tt> is <i>consistent with
+ * It follows immediately from the contract for {@code compare} that the
+ * quotient is an <i>equivalence relation</i> on {@code S}, and that the
+ * imposed ordering is a <i>total order</i> on {@code S}.  When we say that
+ * the ordering imposed by {@code c} on {@code S} is <i>consistent with
  * equals</i>, we mean that the quotient for the ordering is the equivalence
  * relation defined by the objects' {@link Object#equals(Object)
  * equals(Object)} method(s):<pre>
@@ -94,7 +94,7 @@
  * an equivalence relation.
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <T> the type of objects that may be compared by this comparator
@@ -112,30 +112,30 @@
      * zero, or a positive integer as the first argument is less than, equal
      * to, or greater than the second.<p>
      *
-     * In the foregoing description, the notation
-     * <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
-     * <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
-     * <tt>0</tt>, or <tt>1</tt> according to whether the value of
-     * <i>expression</i> is negative, zero or positive.<p>
-     *
-     * The implementor must ensure that <tt>sgn(compare(x, y)) ==
-     * -sgn(compare(y, x))</tt> for all <tt>x</tt> and <tt>y</tt>.  (This
-     * implies that <tt>compare(x, y)</tt> must throw an exception if and only
-     * if <tt>compare(y, x)</tt> throws an exception.)<p>
+     * The implementor must ensure that {@code sgn(compare(x, y)) ==
+     * -sgn(compare(y, x))} for all {@code x} and {@code y}.  (This
+     * implies that {@code compare(x, y)} must throw an exception if and only
+     * if {@code compare(y, x)} throws an exception.)<p>
      *
      * The implementor must also ensure that the relation is transitive:
-     * <tt>((compare(x, y)&gt;0) &amp;&amp; (compare(y, z)&gt;0))</tt> implies
-     * <tt>compare(x, z)&gt;0</tt>.<p>
+     * {@code ((compare(x, y)>0) && (compare(y, z)>0))} implies
+     * {@code compare(x, z)>0}.<p>
      *
-     * Finally, the implementor must ensure that <tt>compare(x, y)==0</tt>
-     * implies that <tt>sgn(compare(x, z))==sgn(compare(y, z))</tt> for all
-     * <tt>z</tt>.<p>
+     * Finally, the implementor must ensure that {@code compare(x, y)==0}
+     * implies that {@code sgn(compare(x, z))==sgn(compare(y, z))} for all
+     * {@code z}.<p>
      *
      * It is generally the case, but <i>not</i> strictly required that
-     * <tt>(compare(x, y)==0) == (x.equals(y))</tt>.  Generally speaking,
+     * {@code (compare(x, y)==0) == (x.equals(y))}.  Generally speaking,
      * any comparator that violates this condition should clearly indicate
      * this fact.  The recommended language is "Note: this comparator
-     * imposes orderings that are inconsistent with equals."
+     * imposes orderings that are inconsistent with equals."<p>
+     *
+     * In the foregoing description, the notation
+     * {@code sgn(}<i>expression</i>{@code )} designates the mathematical
+     * <i>signum</i> function, which is defined to return one of {@code -1},
+     * {@code 0}, or {@code 1} according to whether the value of
+     * <i>expression</i> is negative, zero, or positive, respectively.
      *
      * @param o1 the first object to be compared.
      * @param o2 the second object to be compared.
@@ -153,19 +153,19 @@
      * Indicates whether some other object is &quot;equal to&quot; this
      * comparator.  This method must obey the general contract of
      * {@link Object#equals(Object)}.  Additionally, this method can return
-     * <tt>true</tt> <i>only</i> if the specified object is also a comparator
+     * {@code true} <i>only</i> if the specified object is also a comparator
      * and it imposes the same ordering as this comparator.  Thus,
-     * <code>comp1.equals(comp2)</code> implies that <tt>sgn(comp1.compare(o1,
-     * o2))==sgn(comp2.compare(o1, o2))</tt> for every object reference
-     * <tt>o1</tt> and <tt>o2</tt>.<p>
+     * {@code comp1.equals(comp2)} implies that {@code sgn(comp1.compare(o1,
+     * o2))==sgn(comp2.compare(o1, o2))} for every object reference
+     * {@code o1} and {@code o2}.<p>
      *
      * Note that it is <i>always</i> safe <i>not</i> to override
-     * <tt>Object.equals(Object)</tt>.  However, overriding this method may,
+     * {@code Object.equals(Object)}.  However, overriding this method may,
      * in some cases, improve performance by allowing programs to determine
      * that two distinct comparators impose the same order.
      *
      * @param   obj   the reference object with which to compare.
-     * @return  <code>true</code> only if the specified object is also
+     * @return  {@code true} only if the specified object is also
      *          a comparator and it imposes the same ordering as this
      *          comparator.
      * @see Object#equals(Object)
@@ -267,7 +267,7 @@
 
     /**
      * Returns a lexicographic-order comparator with a function that
-     * extracts a {@code int} sort key.
+     * extracts an {@code int} sort key.
      *
      * @implSpec This default implementation behaves as if {@code
      *           thenComparing(comparingInt(keyExtractor))}.
diff --git a/ojluni/src/main/java/java/util/Comparators.java b/ojluni/src/main/java/java/util/Comparators.java
index ee80679..8104f99 100644
--- a/ojluni/src/main/java/java/util/Comparators.java
+++ b/ojluni/src/main/java/java/util/Comparators.java
@@ -61,7 +61,7 @@
     /**
      * Null-friendly comparators
      */
-    final static class NullComparator<T> implements Comparator<T>, Serializable {
+    static final class NullComparator<T> implements Comparator<T>, Serializable {
         private static final long serialVersionUID = -7569533591570686392L;
         private final boolean nullFirst;
         // if null, non-null Ts are considered equal
diff --git a/ojluni/src/main/java/java/util/Date.java b/ojluni/src/main/java/java/util/Date.java
index f7a576d..d60ce3d 100644
--- a/ojluni/src/main/java/java/util/Date.java
+++ b/ojluni/src/main/java/java/util/Date.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,20 +41,20 @@
 import sun.util.calendar.Gregorian;
 
 /**
- * The class <code>Date</code> represents a specific instant
+ * The class {@code Date} represents a specific instant
  * in time, with millisecond precision.
  * <p>
- * Prior to JDK&nbsp;1.1, the class <code>Date</code> had two additional
+ * Prior to JDK&nbsp;1.1, the class {@code Date} had two additional
  * functions.  It allowed the interpretation of dates as year, month, day, hour,
  * minute, and second values.  It also allowed the formatting and parsing
  * of date strings.  Unfortunately, the API for these functions was not
  * amenable to internationalization.  As of JDK&nbsp;1.1, the
- * <code>Calendar</code> class should be used to convert between dates and time
- * fields and the <code>DateFormat</code> class should be used to format and
+ * {@code Calendar} class should be used to convert between dates and time
+ * fields and the {@code DateFormat} class should be used to format and
  * parse date strings.
- * The corresponding methods in <code>Date</code> are deprecated.
+ * The corresponding methods in {@code Date} are deprecated.
  * <p>
- * Although the <code>Date</code> class is intended to reflect
+ * Although the {@code Date} class is intended to reflect
  * coordinated universal time (UTC), it may not do so exactly,
  * depending on the host environment of the Java Virtual Machine.
  * Nearly all modern operating systems assume that 1&nbsp;day&nbsp;=
@@ -82,23 +82,25 @@
  * well; for example, the time scale used by the satellite-based
  * global positioning system (GPS) is synchronized to UTC but is
  * <i>not</i> adjusted for leap seconds. An interesting source of
- * further information is the U.S. Naval Observatory, particularly
- * the Directorate of Time at:
+ * further information is the United States Naval Observatory (USNO):
  * <blockquote><pre>
- *     <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a>
+ *     <a href="http://www.usno.navy.mil/USNO">http://www.usno.navy.mil/USNO</a>
  * </pre></blockquote>
  * <p>
- * and their definitions of "Systems of Time" at:
+ * and the material regarding "Systems of Time" at:
  * <blockquote><pre>
- *     <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a>
+ *     <a href="http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time">http://www.usno.navy.mil/USNO/time/master-clock/systems-of-time</a>
  * </pre></blockquote>
  * <p>
- * In all methods of class <code>Date</code> that accept or return
+ * which has descriptions of various different time systems including
+ * UT, UT1, and UTC.
+ * <p>
+ * In all methods of class {@code Date} that accept or return
  * year, month, date, hours, minutes, and seconds values, the
  * following representations are used:
  * <ul>
  * <li>A year <i>y</i> is represented by the integer
- *     <i>y</i>&nbsp;<code>-&nbsp;1900</code>.
+ *     <i>y</i>&nbsp;{@code - 1900}.
  * <li>A month is represented by an integer from 0 to 11; 0 is January,
  *     1 is February, and so forth; thus 11 is December.
  * <li>A date (day of month) is represented by an integer from 1 to 31
@@ -126,7 +128,7 @@
  * @see     java.text.DateFormat
  * @see     java.util.Calendar
  * @see     java.util.TimeZone
- * @since   JDK1.0
+ * @since   1.0
  */
 public class Date
     implements java.io.Serializable, Cloneable, Comparable<Date>
@@ -155,7 +157,7 @@
     private static final long serialVersionUID = 7523967970034938905L;
 
     /**
-     * Allocates a <code>Date</code> object and initializes it so that
+     * Allocates a {@code Date} object and initializes it so that
      * it represents the time at which it was allocated, measured to the
      * nearest millisecond.
      *
@@ -166,7 +168,7 @@
     }
 
     /**
-     * Allocates a <code>Date</code> object and initializes it to
+     * Allocates a {@code Date} object and initializes it to
      * represent the specified number of milliseconds since the
      * standard base time known as "the epoch", namely January 1,
      * 1970, 00:00:00 GMT.
@@ -179,18 +181,18 @@
     }
 
     /**
-     * Allocates a <code>Date</code> object and initializes it so that
+     * Allocates a {@code Date} object and initializes it so that
      * it represents midnight, local time, at the beginning of the day
-     * specified by the <code>year</code>, <code>month</code>, and
-     * <code>date</code> arguments.
+     * specified by the {@code year}, {@code month}, and
+     * {@code date} arguments.
      *
      * @param   year    the year minus 1900.
      * @param   month   the month between 0-11.
      * @param   date    the day of the month between 1-31.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(year + 1900, month, date)</code>
-     * or <code>GregorianCalendar(year + 1900, month, date)</code>.
+     * replaced by {@code Calendar.set(year + 1900, month, date)}
+     * or {@code GregorianCalendar(year + 1900, month, date)}.
      */
     @Deprecated
     public Date(int year, int month, int date) {
@@ -198,10 +200,10 @@
     }
 
     /**
-     * Allocates a <code>Date</code> object and initializes it so that
+     * Allocates a {@code Date} object and initializes it so that
      * it represents the instant at the start of the minute specified by
-     * the <code>year</code>, <code>month</code>, <code>date</code>,
-     * <code>hrs</code>, and <code>min</code> arguments, in the local
+     * the {@code year}, {@code month}, {@code date},
+     * {@code hrs}, and {@code min} arguments, in the local
      * time zone.
      *
      * @param   year    the year minus 1900.
@@ -211,9 +213,8 @@
      * @param   min     the minutes between 0-59.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(year + 1900, month, date,
-     * hrs, min)</code> or <code>GregorianCalendar(year + 1900,
-     * month, date, hrs, min)</code>.
+     * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min)}
+     * or {@code GregorianCalendar(year + 1900, month, date, hrs, min)}.
      */
     @Deprecated
     public Date(int year, int month, int date, int hrs, int min) {
@@ -221,10 +222,10 @@
     }
 
     /**
-     * Allocates a <code>Date</code> object and initializes it so that
+     * Allocates a {@code Date} object and initializes it so that
      * it represents the instant at the start of the second specified
-     * by the <code>year</code>, <code>month</code>, <code>date</code>,
-     * <code>hrs</code>, <code>min</code>, and <code>sec</code> arguments,
+     * by the {@code year}, {@code month}, {@code date},
+     * {@code hrs}, {@code min}, and {@code sec} arguments,
      * in the local time zone.
      *
      * @param   year    the year minus 1900.
@@ -235,9 +236,8 @@
      * @param   sec     the seconds between 0-59.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(year + 1900, month, date,
-     * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
-     * month, date, hrs, min, sec)</code>.
+     * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min, sec)}
+     * or {@code GregorianCalendar(year + 1900, month, date, hrs, min, sec)}.
      */
     @Deprecated
     public Date(int year, int month, int date, int hrs, int min, int sec) {
@@ -258,16 +258,16 @@
     }
 
     /**
-     * Allocates a <code>Date</code> object and initializes it so that
+     * Allocates a {@code Date} object and initializes it so that
      * it represents the date and time indicated by the string
-     * <code>s</code>, which is interpreted as if by the
+     * {@code s}, which is interpreted as if by the
      * {@link Date#parse} method.
      *
      * @param   s   a string representation of the date.
      * @see     java.text.DateFormat
      * @see     java.util.Date#parse(java.lang.String)
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>DateFormat.parse(String s)</code>.
+     * replaced by {@code DateFormat.parse(String s)}.
      */
     @Deprecated
     public Date(String s) {
@@ -292,7 +292,7 @@
      * Determines the date and time based on the arguments. The
      * arguments are interpreted as a year, month, day of the month,
      * hour of the day, minute within the hour, and second within the
-     * minute, exactly as for the <tt>Date</tt> constructor with six
+     * minute, exactly as for the {@code Date} constructor with six
      * arguments, except that the arguments are interpreted relative
      * to UTC rather than to the local time zone. The time indicated is
      * returned represented as the distance, measured in milliseconds,
@@ -308,10 +308,9 @@
      *          the date and time specified by the arguments.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(year + 1900, month, date,
-     * hrs, min, sec)</code> or <code>GregorianCalendar(year + 1900,
-     * month, date, hrs, min, sec)</code>, using a UTC
-     * <code>TimeZone</code>, followed by <code>Calendar.getTime().getTime()</code>.
+     * replaced by {@code Calendar.set(year + 1900, month, date, hrs, min, sec)}
+     * or {@code GregorianCalendar(year + 1900, month, date, hrs, min, sec)}, using a UTC
+     * {@code TimeZone}, followed by {@code Calendar.getTime().getTime()}.
      */
     @Deprecated
     public static long UTC(int year, int month, int date,
@@ -338,12 +337,12 @@
     }
 
     /**
-     * Attempts to interpret the string <tt>s</tt> as a representation
+     * Attempts to interpret the string {@code s} as a representation
      * of a date and time. If the attempt is successful, the time
      * indicated is returned represented as the distance, measured in
      * milliseconds, of that time from the epoch (00:00:00 GMT on
      * January 1, 1970). If the attempt fails, an
-     * <tt>IllegalArgumentException</tt> is thrown.
+     * {@code IllegalArgumentException} is thrown.
      * <p>
      * It accepts many syntaxes; in particular, it recognizes the IETF
      * standard date syntax: "Sat, 12 Aug 1995 13:30:00 GMT". It also
@@ -353,11 +352,11 @@
      * meridian). If no time zone is specified, the local time zone is
      * assumed. GMT and UTC are considered equivalent.
      * <p>
-     * The string <tt>s</tt> is processed from left to right, looking for
-     * data of interest. Any material in <tt>s</tt> that is within the
-     * ASCII parenthesis characters <tt>(</tt> and <tt>)</tt> is ignored.
+     * The string {@code s} is processed from left to right, looking for
+     * data of interest. Any material in {@code s} that is within the
+     * ASCII parenthesis characters {@code (} and {@code )} is ignored.
      * Parentheses may be nested. Otherwise, the only characters permitted
-     * within <tt>s</tt> are these ASCII characters:
+     * within {@code s} are these ASCII characters:
      * <blockquote><pre>
      * abcdefghijklmnopqrstuvwxyz
      * ABCDEFGHIJKLMNOPQRSTUVWXYZ
@@ -365,18 +364,18 @@
      * and whitespace characters.<p>
      * A consecutive sequence of decimal digits is treated as a decimal
      * number:<ul>
-     * <li>If a number is preceded by <tt>+</tt> or <tt>-</tt> and a year
+     * <li>If a number is preceded by {@code +} or {@code -} and a year
      *     has already been recognized, then the number is a time-zone
      *     offset. If the number is less than 24, it is an offset measured
      *     in hours. Otherwise, it is regarded as an offset in minutes,
      *     expressed in 24-hour time format without punctuation. A
-     *     preceding <tt>-</tt> means a westward offset. Time zone offsets
+     *     preceding {@code -} means a westward offset. Time zone offsets
      *     are always relative to UTC (Greenwich). Thus, for example,
-     *     <tt>-5</tt> occurring in the string would mean "five hours west
-     *     of Greenwich" and <tt>+0430</tt> would mean "four hours and
+     *     {@code -5} occurring in the string would mean "five hours west
+     *     of Greenwich" and {@code +0430} would mean "four hours and
      *     thirty minutes east of Greenwich." It is permitted for the
-     *     string to specify <tt>GMT</tt>, <tt>UT</tt>, or <tt>UTC</tt>
-     *     redundantly-for example, <tt>GMT-5</tt> or <tt>utc+0430</tt>.
+     *     string to specify {@code GMT}, {@code UT}, or {@code UTC}
+     *     redundantly-for example, {@code GMT-5} or {@code utc+0430}.
      * <li>The number is regarded as a year number if one of the
      *     following conditions is true:
      * <ul>
@@ -399,8 +398,8 @@
      *     unless an hour has already been recognized, in which case it is
      *     regarded as a minute.
      * <li>If the number is followed by a slash, it is regarded as a month
-     *     (it is decreased by 1 to produce a number in the range <tt>0</tt>
-     *     to <tt>11</tt>), unless a month has already been recognized, in
+     *     (it is decreased by 1 to produce a number in the range {@code 0}
+     *     to {@code 11}), unless a month has already been recognized, in
      *     which case it is regarded as a day of the month.
      * <li>If the number is followed by whitespace, a comma, a hyphen, or
      *     end of string, then if an hour has been recognized but not a
@@ -409,31 +408,31 @@
      *     otherwise, it is regarded as a day of the month. </ul><p>
      * A consecutive sequence of letters is regarded as a word and treated
      * as follows:<ul>
-     * <li>A word that matches <tt>AM</tt>, ignoring case, is ignored (but
+     * <li>A word that matches {@code AM}, ignoring case, is ignored (but
      *     the parse fails if an hour has not been recognized or is less
-     *     than <tt>1</tt> or greater than <tt>12</tt>).
-     * <li>A word that matches <tt>PM</tt>, ignoring case, adds <tt>12</tt>
+     *     than {@code 1} or greater than {@code 12}).
+     * <li>A word that matches {@code PM}, ignoring case, adds {@code 12}
      *     to the hour (but the parse fails if an hour has not been
-     *     recognized or is less than <tt>1</tt> or greater than <tt>12</tt>).
-     * <li>Any word that matches any prefix of <tt>SUNDAY, MONDAY, TUESDAY,
-     *     WEDNESDAY, THURSDAY, FRIDAY</tt>, or <tt>SATURDAY</tt>, ignoring
-     *     case, is ignored. For example, <tt>sat, Friday, TUE</tt>, and
-     *     <tt>Thurs</tt> are ignored.
-     * <li>Otherwise, any word that matches any prefix of <tt>JANUARY,
+     *     recognized or is less than {@code 1} or greater than {@code 12}).
+     * <li>Any word that matches any prefix of {@code SUNDAY, MONDAY, TUESDAY,
+     *     WEDNESDAY, THURSDAY, FRIDAY}, or {@code SATURDAY}, ignoring
+     *     case, is ignored. For example, {@code sat, Friday, TUE}, and
+     *     {@code Thurs} are ignored.
+     * <li>Otherwise, any word that matches any prefix of {@code JANUARY,
      *     FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER,
-     *     OCTOBER, NOVEMBER</tt>, or <tt>DECEMBER</tt>, ignoring case, and
+     *     OCTOBER, NOVEMBER}, or {@code DECEMBER}, ignoring case, and
      *     considering them in the order given here, is recognized as
-     *     specifying a month and is converted to a number (<tt>0</tt> to
-     *     <tt>11</tt>). For example, <tt>aug, Sept, april</tt>, and
-     *     <tt>NOV</tt> are recognized as months. So is <tt>Ma</tt>, which
-     *     is recognized as <tt>MARCH</tt>, not <tt>MAY</tt>.
-     * <li>Any word that matches <tt>GMT, UT</tt>, or <tt>UTC</tt>, ignoring
+     *     specifying a month and is converted to a number ({@code 0} to
+     *     {@code 11}). For example, {@code aug, Sept, april}, and
+     *     {@code NOV} are recognized as months. So is {@code Ma}, which
+     *     is recognized as {@code MARCH}, not {@code MAY}.
+     * <li>Any word that matches {@code GMT, UT}, or {@code UTC}, ignoring
      *     case, is treated as referring to UTC.
-     * <li>Any word that matches <tt>EST, CST, MST</tt>, or <tt>PST</tt>,
+     * <li>Any word that matches {@code EST, CST, MST}, or {@code PST},
      *     ignoring case, is recognized as referring to the time zone in
      *     North America that is five, six, seven, or eight hours west of
-     *     Greenwich, respectively. Any word that matches <tt>EDT, CDT,
-     *     MDT</tt>, or <tt>PDT</tt>, ignoring case, is recognized as
+     *     Greenwich, respectively. Any word that matches {@code EDT, CDT,
+     *     MDT}, or {@code PDT}, ignoring case, is recognized as
      *     referring to the same time zone, respectively, during daylight
      *     saving time.</ul><p>
      * Once the entire string s has been scanned, it is converted to a time
@@ -448,7 +447,7 @@
      *          represented by the string argument.
      * @see     java.text.DateFormat
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>DateFormat.parse(String s)</code>.
+     * replaced by {@code DateFormat.parse(String s)}.
      */
     @Deprecated
     public static long parse(String s) {
@@ -637,7 +636,7 @@
         // syntax error
         throw new IllegalArgumentException();
     }
-    private final static String wtb[] = {
+    private static final String wtb[] = {
         "am", "pm",
         "monday", "tuesday", "wednesday", "thursday", "friday",
         "saturday", "sunday",
@@ -646,7 +645,7 @@
         "gmt", "ut", "utc", "est", "edt", "cst", "cdt",
         "mst", "mdt", "pst", "pdt"
     };
-    private final static int ttb[] = {
+    private static final int ttb[] = {
         14, 1, 0, 0, 0, 0, 0, 0, 0,
         2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
         10000 + 0, 10000 + 0, 10000 + 0,    // GMT/UT/UTC
@@ -659,13 +658,13 @@
     /**
      * Returns a value that is the result of subtracting 1900 from the
      * year that contains or begins with the instant in time represented
-     * by this <code>Date</code> object, as interpreted in the local
+     * by this {@code Date} object, as interpreted in the local
      * time zone.
      *
      * @return  the year represented by this date, minus 1900.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.get(Calendar.YEAR) - 1900</code>.
+     * replaced by {@code Calendar.get(Calendar.YEAR) - 1900}.
      */
     @Deprecated
     public int getYear() {
@@ -673,8 +672,8 @@
     }
 
     /**
-     * Sets the year of this <tt>Date</tt> object to be the specified
-     * value plus 1900. This <code>Date</code> object is modified so
+     * Sets the year of this {@code Date} object to be the specified
+     * value plus 1900. This {@code Date} object is modified so
      * that it represents a point in time within the specified year,
      * with the month, date, hour, minute, and second the same as
      * before, as interpreted in the local time zone. (Of course, if
@@ -685,7 +684,7 @@
      * @param   year    the year value.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>.
+     * replaced by {@code Calendar.set(Calendar.YEAR, year + 1900)}.
      */
     @Deprecated
     public void setYear(int year) {
@@ -694,14 +693,14 @@
 
     /**
      * Returns a number representing the month that contains or begins
-     * with the instant in time represented by this <tt>Date</tt> object.
-     * The value returned is between <code>0</code> and <code>11</code>,
-     * with the value <code>0</code> representing January.
+     * with the instant in time represented by this {@code Date} object.
+     * The value returned is between {@code 0} and {@code 11},
+     * with the value {@code 0} representing January.
      *
      * @return  the month represented by this date.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.get(Calendar.MONTH)</code>.
+     * replaced by {@code Calendar.get(Calendar.MONTH)}.
      */
     @Deprecated
     public int getMonth() {
@@ -710,7 +709,7 @@
 
     /**
      * Sets the month of this date to the specified value. This
-     * <tt>Date</tt> object is modified so that it represents a point
+     * {@code Date} object is modified so that it represents a point
      * in time within the specified month, with the year, date, hour,
      * minute, and second the same as before, as interpreted in the
      * local time zone. If the date was October 31, for example, and
@@ -720,7 +719,7 @@
      * @param   month   the month value between 0-11.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>.
+     * replaced by {@code Calendar.set(Calendar.MONTH, int month)}.
      */
     @Deprecated
     public void setMonth(int month) {
@@ -740,26 +739,25 @@
     }
 
     /**
-     * Returns the day of the month represented by this <tt>Date</tt> object.
-     * The value returned is between <code>1</code> and <code>31</code>
+     * Returns the day of the month represented by this {@code Date} object.
+     * The value returned is between {@code 1} and {@code 31}
      * representing the day of the month that contains or begins with the
-     * instant in time represented by this <tt>Date</tt> object, as
+     * instant in time represented by this {@code Date} object, as
      * interpreted in the local time zone.
      *
      * @return  the day of the month represented by this date.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.get(Calendar.DAY_OF_MONTH)</code>.
+     * replaced by {@code Calendar.get(Calendar.DAY_OF_MONTH)}.
      */
     @Deprecated
-    // Android-removed stray @deprecated tag.
     public int getDate() {
         return normalize().getDayOfMonth();
     }
 
     /**
-     * Sets the day of the month of this <tt>Date</tt> object to the
-     * specified value. This <tt>Date</tt> object is modified so that
+     * Sets the day of the month of this {@code Date} object to the
+     * specified value. This {@code Date} object is modified so that
      * it represents a point in time within the specified day of the
      * month, with the year, month, hour, minute, and second the same
      * as before, as interpreted in the local time zone. If the date
@@ -770,7 +768,7 @@
      * @param   date   the day of the month value between 1-31.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>.
+     * replaced by {@code Calendar.set(Calendar.DAY_OF_MONTH, int date)}.
      */
     @Deprecated
     public void setDate(int date) {
@@ -779,17 +777,17 @@
 
     /**
      * Returns the day of the week represented by this date. The
-     * returned value (<tt>0</tt> = Sunday, <tt>1</tt> = Monday,
-     * <tt>2</tt> = Tuesday, <tt>3</tt> = Wednesday, <tt>4</tt> =
-     * Thursday, <tt>5</tt> = Friday, <tt>6</tt> = Saturday)
+     * returned value ({@code 0} = Sunday, {@code 1} = Monday,
+     * {@code 2} = Tuesday, {@code 3} = Wednesday, {@code 4} =
+     * Thursday, {@code 5} = Friday, {@code 6} = Saturday)
      * represents the day of the week that contains or begins with
-     * the instant in time represented by this <tt>Date</tt> object,
+     * the instant in time represented by this {@code Date} object,
      * as interpreted in the local time zone.
      *
      * @return  the day of the week represented by this date.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.get(Calendar.DAY_OF_WEEK)</code>.
+     * replaced by {@code Calendar.get(Calendar.DAY_OF_WEEK)}.
      */
     @Deprecated
     public int getDay() {
@@ -797,16 +795,16 @@
     }
 
     /**
-     * Returns the hour represented by this <tt>Date</tt> object. The
-     * returned value is a number (<tt>0</tt> through <tt>23</tt>)
+     * Returns the hour represented by this {@code Date} object. The
+     * returned value is a number ({@code 0} through {@code 23})
      * representing the hour within the day that contains or begins
-     * with the instant in time represented by this <tt>Date</tt>
+     * with the instant in time represented by this {@code Date}
      * object, as interpreted in the local time zone.
      *
      * @return  the hour represented by this date.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.get(Calendar.HOUR_OF_DAY)</code>.
+     * replaced by {@code Calendar.get(Calendar.HOUR_OF_DAY)}.
      */
     @Deprecated
     public int getHours() {
@@ -814,8 +812,8 @@
     }
 
     /**
-     * Sets the hour of this <tt>Date</tt> object to the specified value.
-     * This <tt>Date</tt> object is modified so that it represents a point
+     * Sets the hour of this {@code Date} object to the specified value.
+     * This {@code Date} object is modified so that it represents a point
      * in time within the specified hour of the day, with the year, month,
      * date, minute, and second the same as before, as interpreted in the
      * local time zone.
@@ -823,7 +821,7 @@
      * @param   hours   the hour value.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>.
+     * replaced by {@code Calendar.set(Calendar.HOUR_OF_DAY, int hours)}.
      */
     @Deprecated
     public void setHours(int hours) {
@@ -833,12 +831,12 @@
     /**
      * Returns the number of minutes past the hour represented by this date,
      * as interpreted in the local time zone.
-     * The value returned is between <code>0</code> and <code>59</code>.
+     * The value returned is between {@code 0} and {@code 59}.
      *
      * @return  the number of minutes past the hour represented by this date.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.get(Calendar.MINUTE)</code>.
+     * replaced by {@code Calendar.get(Calendar.MINUTE)}.
      */
     @Deprecated
     public int getMinutes() {
@@ -846,8 +844,8 @@
     }
 
     /**
-     * Sets the minutes of this <tt>Date</tt> object to the specified value.
-     * This <tt>Date</tt> object is modified so that it represents a point
+     * Sets the minutes of this {@code Date} object to the specified value.
+     * This {@code Date} object is modified so that it represents a point
      * in time within the specified minute of the hour, with the year, month,
      * date, hour, and second the same as before, as interpreted in the
      * local time zone.
@@ -855,7 +853,7 @@
      * @param   minutes   the value of the minutes.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>.
+     * replaced by {@code Calendar.set(Calendar.MINUTE, int minutes)}.
      */
     @Deprecated
     public void setMinutes(int minutes) {
@@ -864,14 +862,14 @@
 
     /**
      * Returns the number of seconds past the minute represented by this date.
-     * The value returned is between <code>0</code> and <code>61</code>. The
-     * values <code>60</code> and <code>61</code> can only occur on those
+     * The value returned is between {@code 0} and {@code 61}. The
+     * values {@code 60} and {@code 61} can only occur on those
      * Java Virtual Machines that take leap seconds into account.
      *
      * @return  the number of seconds past the minute represented by this date.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.get(Calendar.SECOND)</code>.
+     * replaced by {@code Calendar.get(Calendar.SECOND)}.
      */
     @Deprecated
     public int getSeconds() {
@@ -879,8 +877,8 @@
     }
 
     /**
-     * Sets the seconds of this <tt>Date</tt> to the specified value.
-     * This <tt>Date</tt> object is modified so that it represents a
+     * Sets the seconds of this {@code Date} to the specified value.
+     * This {@code Date} object is modified so that it represents a
      * point in time within the specified second of the minute, with
      * the year, month, date, hour, and minute the same as before, as
      * interpreted in the local time zone.
@@ -888,7 +886,7 @@
      * @param   seconds   the seconds value.
      * @see     java.util.Calendar
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>.
+     * replaced by {@code Calendar.set(Calendar.SECOND, int seconds)}.
      */
     @Deprecated
     public void setSeconds(int seconds) {
@@ -897,7 +895,7 @@
 
     /**
      * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
-     * represented by this <tt>Date</tt> object.
+     * represented by this {@code Date} object.
      *
      * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
      *          represented by this date.
@@ -914,8 +912,8 @@
     }
 
     /**
-     * Sets this <code>Date</code> object to represent a point in time that is
-     * <code>time</code> milliseconds after January 1, 1970 00:00:00 GMT.
+     * Sets this {@code Date} object to represent a point in time that is
+     * {@code time} milliseconds after January 1, 1970 00:00:00 GMT.
      *
      * @param   time   the number of milliseconds.
      */
@@ -928,11 +926,11 @@
      * Tests if this date is before the specified date.
      *
      * @param   when   a date.
-     * @return  <code>true</code> if and only if the instant of time
-     *            represented by this <tt>Date</tt> object is strictly
-     *            earlier than the instant represented by <tt>when</tt>;
-     *          <code>false</code> otherwise.
-     * @exception NullPointerException if <code>when</code> is null.
+     * @return  {@code true} if and only if the instant of time
+     *            represented by this {@code Date} object is strictly
+     *            earlier than the instant represented by {@code when};
+     *          {@code false} otherwise.
+     * @exception NullPointerException if {@code when} is null.
      */
     public boolean before(Date when) {
         return getMillisOf(this) < getMillisOf(when);
@@ -942,11 +940,11 @@
      * Tests if this date is after the specified date.
      *
      * @param   when   a date.
-     * @return  <code>true</code> if and only if the instant represented
-     *          by this <tt>Date</tt> object is strictly later than the
-     *          instant represented by <tt>when</tt>;
-     *          <code>false</code> otherwise.
-     * @exception NullPointerException if <code>when</code> is null.
+     * @return  {@code true} if and only if the instant represented
+     *          by this {@code Date} object is strictly later than the
+     *          instant represented by {@code when};
+     *          {@code false} otherwise.
+     * @exception NullPointerException if {@code when} is null.
      */
     public boolean after(Date when) {
         return getMillisOf(this) > getMillisOf(when);
@@ -954,17 +952,17 @@
 
     /**
      * Compares two dates for equality.
-     * The result is <code>true</code> if and only if the argument is
-     * not <code>null</code> and is a <code>Date</code> object that
+     * The result is {@code true} if and only if the argument is
+     * not {@code null} and is a {@code Date} object that
      * represents the same point in time, to the millisecond, as this object.
      * <p>
-     * Thus, two <code>Date</code> objects are equal if and only if the
-     * <code>getTime</code> method returns the same <code>long</code>
+     * Thus, two {@code Date} objects are equal if and only if the
+     * {@code getTime} method returns the same {@code long}
      * value for both.
      *
      * @param   obj   the object to compare with.
-     * @return  <code>true</code> if the objects are the same;
-     *          <code>false</code> otherwise.
+     * @return  {@code true} if the objects are the same;
+     *          {@code false} otherwise.
      * @see     java.util.Date#getTime()
      */
     public boolean equals(Object obj) {
@@ -972,10 +970,13 @@
     }
 
     /**
-     * Returns the millisecond value of this <code>Date</code> object
+     * Returns the millisecond value of this {@code Date} object
      * without affecting its internal state.
      */
     static final long getMillisOf(Date date) {
+        if (date.getClass() != Date.class) {
+            return date.getTime();
+        }
         if (date.cdate == null || date.cdate.isNormalized()) {
             return date.fastTime;
         }
@@ -986,13 +987,13 @@
     /**
      * Compares two Dates for ordering.
      *
-     * @param   anotherDate   the <code>Date</code> to be compared.
-     * @return  the value <code>0</code> if the argument Date is equal to
-     *          this Date; a value less than <code>0</code> if this Date
+     * @param   anotherDate   the {@code Date} to be compared.
+     * @return  the value {@code 0} if the argument Date is equal to
+     *          this Date; a value less than {@code 0} if this Date
      *          is before the Date argument; and a value greater than
-     *      <code>0</code> if this Date is after the Date argument.
+     *      {@code 0} if this Date is after the Date argument.
      * @since   1.2
-     * @exception NullPointerException if <code>anotherDate</code> is null.
+     * @exception NullPointerException if {@code anotherDate} is null.
      */
     public int compareTo(Date anotherDate) {
         long thisTime = getMillisOf(this);
@@ -1002,7 +1003,7 @@
 
     /**
      * Returns a hash code value for this object. The result is the
-     * exclusive OR of the two halves of the primitive <tt>long</tt>
+     * exclusive OR of the two halves of the primitive {@code long}
      * value returned by the {@link Date#getTime}
      * method. That is, the hash code is the value of the expression:
      * <blockquote><pre>{@code
@@ -1017,29 +1018,29 @@
     }
 
     /**
-     * Converts this <code>Date</code> object to a <code>String</code>
+     * Converts this {@code Date} object to a {@code String}
      * of the form:
      * <blockquote><pre>
      * dow mon dd hh:mm:ss zzz yyyy</pre></blockquote>
      * where:<ul>
-     * <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed,
-     *     Thu, Fri, Sat</tt>).
-     * <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun,
-     *     Jul, Aug, Sep, Oct, Nov, Dec</tt>).
-     * <li><tt>dd</tt> is the day of the month (<tt>01</tt> through
-     *     <tt>31</tt>), as two decimal digits.
-     * <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through
-     *     <tt>23</tt>), as two decimal digits.
-     * <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through
-     *     <tt>59</tt>), as two decimal digits.
-     * <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through
-     *     <tt>61</tt>, as two decimal digits.
-     * <li><tt>zzz</tt> is the time zone (and may reflect daylight saving
+     * <li>{@code dow} is the day of the week ({@code Sun, Mon, Tue, Wed,
+     *     Thu, Fri, Sat}).
+     * <li>{@code mon} is the month ({@code Jan, Feb, Mar, Apr, May, Jun,
+     *     Jul, Aug, Sep, Oct, Nov, Dec}).
+     * <li>{@code dd} is the day of the month ({@code 01} through
+     *     {@code 31}), as two decimal digits.
+     * <li>{@code hh} is the hour of the day ({@code 00} through
+     *     {@code 23}), as two decimal digits.
+     * <li>{@code mm} is the minute within the hour ({@code 00} through
+     *     {@code 59}), as two decimal digits.
+     * <li>{@code ss} is the second within the minute ({@code 00} through
+     *     {@code 61}, as two decimal digits.
+     * <li>{@code zzz} is the time zone (and may reflect daylight saving
      *     time). Standard time zone abbreviations include those
-     *     recognized by the method <tt>parse</tt>. If time zone
-     *     information is not available, then <tt>zzz</tt> is empty -
+     *     recognized by the method {@code parse}. If time zone
+     *     information is not available, then {@code zzz} is empty -
      *     that is, it consists of no characters at all.
-     * <li><tt>yyyy</tt> is the year, as four decimal digits.
+     * <li>{@code yyyy} is the year, as four decimal digits.
      * </ul>
      *
      * @return  a string representation of this date.
@@ -1074,7 +1075,7 @@
     /**
      * Converts the given name to its 3-letter abbreviation (e.g.,
      * "monday" -> "Mon") and stored the abbreviation in the given
-     * <code>StringBuilder</code>.
+     * {@code StringBuilder}.
      */
     private static final StringBuilder convertToAbbr(StringBuilder sb, String name) {
         sb.append(Character.toUpperCase(name.charAt(0)));
@@ -1083,11 +1084,11 @@
     }
 
     /**
-     * Creates a string representation of this <tt>Date</tt> object in an
+     * Creates a string representation of this {@code Date} object in an
      * implementation-dependent form. The intent is that the form should
      * be familiar to the user of the Java application, wherever it may
      * happen to be running. The intent is comparable to that of the
-     * "<code>%c</code>" format supported by the <code>strftime()</code>
+     * "{@code %c}" format supported by the {@code strftime()}
      * function of ISO&nbsp;C.
      *
      * @return  a string representation of this date, using the locale
@@ -1096,7 +1097,7 @@
      * @see     java.util.Date#toString()
      * @see     java.util.Date#toGMTString()
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>DateFormat.format(Date date)</code>.
+     * replaced by {@code DateFormat.format(Date date)}.
      */
     @Deprecated
     public String toLocaleString() {
@@ -1105,23 +1106,23 @@
     }
 
     /**
-     * Creates a string representation of this <tt>Date</tt> object of
+     * Creates a string representation of this {@code Date} object of
      * the form:
      * <blockquote><pre>
      * d mon yyyy hh:mm:ss GMT</pre></blockquote>
      * where:<ul>
-     * <li><i>d</i> is the day of the month (<tt>1</tt> through <tt>31</tt>),
+     * <li><i>d</i> is the day of the month ({@code 1} through {@code 31}),
      *     as one or two decimal digits.
-     * <li><i>mon</i> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, Jul,
-     *     Aug, Sep, Oct, Nov, Dec</tt>).
+     * <li><i>mon</i> is the month ({@code Jan, Feb, Mar, Apr, May, Jun, Jul,
+     *     Aug, Sep, Oct, Nov, Dec}).
      * <li><i>yyyy</i> is the year, as four decimal digits.
-     * <li><i>hh</i> is the hour of the day (<tt>00</tt> through <tt>23</tt>),
+     * <li><i>hh</i> is the hour of the day ({@code 00} through {@code 23}),
      *     as two decimal digits.
-     * <li><i>mm</i> is the minute within the hour (<tt>00</tt> through
-     *     <tt>59</tt>), as two decimal digits.
-     * <li><i>ss</i> is the second within the minute (<tt>00</tt> through
-     *     <tt>61</tt>), as two decimal digits.
-     * <li><i>GMT</i> is exactly the ASCII letters "<tt>GMT</tt>" to indicate
+     * <li><i>mm</i> is the minute within the hour ({@code 00} through
+     *     {@code 59}), as two decimal digits.
+     * <li><i>ss</i> is the second within the minute ({@code 00} through
+     *     {@code 61}), as two decimal digits.
+     * <li><i>GMT</i> is exactly the ASCII letters "{@code GMT}" to indicate
      *     Greenwich Mean Time.
      * </ul><p>
      * The result does not depend on the local time zone.
@@ -1132,8 +1133,8 @@
      * @see     java.util.Date#toString()
      * @see     java.util.Date#toLocaleString()
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>DateFormat.format(Date date)</code>, using a
-     * GMT <code>TimeZone</code>.
+     * replaced by {@code DateFormat.format(Date date)}, using a
+     * GMT {@code TimeZone}.
      */
     @Deprecated
     public String toGMTString() {
@@ -1156,7 +1157,7 @@
     /**
      * Returns the offset, measured in minutes, for the local time zone
      * relative to UTC that is appropriate for the time represented by
-     * this <code>Date</code> object.
+     * this {@code Date} object.
      * <p>
      * For example, in Massachusetts, five time zones west of Greenwich:
      * <blockquote><pre>
@@ -1182,8 +1183,8 @@
      * @see     java.util.Calendar#DST_OFFSET
      * @see     java.util.TimeZone#getDefault
      * @deprecated As of JDK version 1.1,
-     * replaced by <code>-(Calendar.get(Calendar.ZONE_OFFSET) +
-     * Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)</code>.
+     * replaced by {@code -(Calendar.get(Calendar.ZONE_OFFSET) +
+     * Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)}.
      */
     @Deprecated
     public int getTimezoneOffset() {
@@ -1321,7 +1322,7 @@
         return gcal;
     }
 
-    synchronized private static final BaseCalendar getJulianCalendar() {
+    private static final synchronized BaseCalendar getJulianCalendar() {
         if (jcal == null) {
             jcal = (BaseCalendar) CalendarSystem.forName("julian");
         }
@@ -1331,13 +1332,14 @@
     /**
      * Save the state of this object to a stream (i.e., serialize it).
      *
-     * @serialData The value returned by <code>getTime()</code>
+     * @serialData The value returned by {@code getTime()}
      *             is emitted (long).  This represents the offset from
      *             January 1, 1970, 00:00:00 GMT in milliseconds.
      */
     private void writeObject(ObjectOutputStream s)
          throws IOException
     {
+        s.defaultWriteObject();
         s.writeLong(getTimeImpl());
     }
 
@@ -1347,6 +1349,7 @@
     private void readObject(ObjectInputStream s)
          throws IOException, ClassNotFoundException
     {
+        s.defaultReadObject();
         fastTime = s.readLong();
     }
 
@@ -1354,7 +1357,7 @@
      * Obtains an instance of {@code Date} from an {@code Instant} object.
      * <p>
      * {@code Instant} uses a precision of nanoseconds, whereas {@code Date}
-     * uses a precision of milliseconds.  The conversion will trancate any
+     * uses a precision of milliseconds.  The conversion will truncate any
      * excess precision information as though the amount in nanoseconds was
      * subject to integer division by one million.
      * <p>
diff --git a/ojluni/src/main/java/java/util/Deque.java b/ojluni/src/main/java/java/util/Deque.java
index 3d79952..5396673 100644
--- a/ojluni/src/main/java/java/util/Deque.java
+++ b/ojluni/src/main/java/java/util/Deque.java
@@ -57,41 +57,44 @@
  * <p>The twelve methods described above are summarized in the
  * following table:
  *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <table class="striped">
  * <caption>Summary of Deque methods</caption>
+ *  <thead>
  *  <tr>
- *    <td></td>
- *    <td ALIGN=CENTER COLSPAN = 2> <b>First Element (Head)</b></td>
- *    <td ALIGN=CENTER COLSPAN = 2> <b>Last Element (Tail)</b></td>
+ *    <td rowspan="2"></td>
+ *    <th scope="col" colspan="2"> First Element (Head)</th>
+ *    <th scope="col" colspan="2"> Last Element (Tail)</th>
  *  </tr>
  *  <tr>
- *    <td></td>
- *    <td ALIGN=CENTER><em>Throws exception</em></td>
- *    <td ALIGN=CENTER><em>Special value</em></td>
- *    <td ALIGN=CENTER><em>Throws exception</em></td>
- *    <td ALIGN=CENTER><em>Special value</em></td>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Special value</th>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Special value</th>
+ *  </tr>
+ *  </thead>
+ *  <tbody>
+ *  <tr>
+ *    <th scope="row">Insert</th>
+ *    <td>{@link #addFirst(Object) addFirst(e)}</td>
+ *    <td>{@link #offerFirst(Object) offerFirst(e)}</td>
+ *    <td>{@link #addLast(Object) addLast(e)}</td>
+ *    <td>{@link #offerLast(Object) offerLast(e)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Insert</b></td>
- *    <td>{@link Deque#addFirst addFirst(e)}</td>
- *    <td>{@link Deque#offerFirst offerFirst(e)}</td>
- *    <td>{@link Deque#addLast addLast(e)}</td>
- *    <td>{@link Deque#offerLast offerLast(e)}</td>
+ *    <th scope="row">Remove</th>
+ *    <td>{@link #removeFirst() removeFirst()}</td>
+ *    <td>{@link #pollFirst() pollFirst()}</td>
+ *    <td>{@link #removeLast() removeLast()}</td>
+ *    <td>{@link #pollLast() pollLast()}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Remove</b></td>
- *    <td>{@link Deque#removeFirst removeFirst()}</td>
- *    <td>{@link Deque#pollFirst pollFirst()}</td>
- *    <td>{@link Deque#removeLast removeLast()}</td>
- *    <td>{@link Deque#pollLast pollLast()}</td>
+ *    <th scope="row">Examine</th>
+ *    <td>{@link #getFirst() getFirst()}</td>
+ *    <td>{@link #peekFirst() peekFirst()}</td>
+ *    <td>{@link #getLast() getLast()}</td>
+ *    <td>{@link #peekLast() peekLast()}</td>
  *  </tr>
- *  <tr>
- *    <td><b>Examine</b></td>
- *    <td>{@link Deque#getFirst getFirst()}</td>
- *    <td>{@link Deque#peekFirst peekFirst()}</td>
- *    <td>{@link Deque#getLast getLast()}</td>
- *    <td>{@link Deque#peekLast peekLast()}</td>
- *  </tr>
+ *  </tbody>
  * </table>
  *
  * <p>This interface extends the {@link Queue} interface.  When a deque is
@@ -100,62 +103,70 @@
  * inherited from the {@code Queue} interface are precisely equivalent to
  * {@code Deque} methods as indicated in the following table:
  *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <table class="striped">
  * <caption>Comparison of Queue and Deque methods</caption>
+ *  <thead>
  *  <tr>
- *    <td ALIGN=CENTER> <b>{@code Queue} Method</b></td>
- *    <td ALIGN=CENTER> <b>Equivalent {@code Deque} Method</b></td>
+ *    <th scope="col"> {@code Queue} Method</th>
+ *    <th scope="col"> Equivalent {@code Deque} Method</th>
+ *  </tr>
+ *  </thead>
+ *  <tbody>
+ *  <tr>
+ *    <th scope="row">{@link #add(Object) add(e)}</th>
+ *    <td>{@link #addLast(Object) addLast(e)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link java.util.Queue#add add(e)}</td>
- *    <td>{@link #addLast addLast(e)}</td>
+ *    <th scope="row">{@link #offer(Object) offer(e)}</th>
+ *    <td>{@link #offerLast(Object) offerLast(e)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link java.util.Queue#offer offer(e)}</td>
- *    <td>{@link #offerLast offerLast(e)}</td>
+ *    <th scope="row">{@link #remove() remove()}</th>
+ *    <td>{@link #removeFirst() removeFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link java.util.Queue#remove remove()}</td>
- *    <td>{@link #removeFirst removeFirst()}</td>
+ *    <th scope="row">{@link #poll() poll()}</th>
+ *    <td>{@link #pollFirst() pollFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link java.util.Queue#poll poll()}</td>
- *    <td>{@link #pollFirst pollFirst()}</td>
+ *    <th scope="row">{@link #element() element()}</th>
+ *    <td>{@link #getFirst() getFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link java.util.Queue#element element()}</td>
- *    <td>{@link #getFirst getFirst()}</td>
+ *    <th scope="row">{@link #peek() peek()}</th>
+ *    <td>{@link #peekFirst() peekFirst()}</td>
  *  </tr>
- *  <tr>
- *    <td>{@link java.util.Queue#peek peek()}</td>
- *    <td>{@link #peek peekFirst()}</td>
- *  </tr>
+ *  </tbody>
  * </table>
  *
  * <p>Deques can also be used as LIFO (Last-In-First-Out) stacks.  This
  * interface should be used in preference to the legacy {@link Stack} class.
  * When a deque is used as a stack, elements are pushed and popped from the
- * beginning of the deque.  Stack methods are precisely equivalent to
- * {@code Deque} methods as indicated in the table below:
+ * beginning of the deque.  Stack methods are equivalent to {@code Deque}
+ * methods as indicated in the table below:
  *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <table class="striped">
  * <caption>Comparison of Stack and Deque methods</caption>
+ *  <thead>
  *  <tr>
- *    <td ALIGN=CENTER> <b>Stack Method</b></td>
- *    <td ALIGN=CENTER> <b>Equivalent {@code Deque} Method</b></td>
+ *    <th scope="col"> Stack Method</th>
+ *    <th scope="col"> Equivalent {@code Deque} Method</th>
+ *  </tr>
+ *  </thead>
+ *  <tbody>
+ *  <tr>
+ *    <th scope="row">{@link #push(Object) push(e)}</th>
+ *    <td>{@link #addFirst(Object) addFirst(e)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #push push(e)}</td>
- *    <td>{@link #addFirst addFirst(e)}</td>
+ *    <th scope="row">{@link #pop() pop()}</th>
+ *    <td>{@link #removeFirst() removeFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #pop pop()}</td>
- *    <td>{@link #removeFirst removeFirst()}</td>
+ *    <th scope="row">{@link #peek() peek()}</th>
+ *    <td>{@link #getFirst() getFirst()}</td>
  *  </tr>
- *  <tr>
- *    <td>{@link #peek peek()}</td>
- *    <td>{@link #peekFirst peekFirst()}</td>
- *  </tr>
+ *  </tbody>
  * </table>
  *
  * <p>Note that the {@link #peek peek} method works equally well when
@@ -175,7 +186,7 @@
  * that do allow null elements are strongly encouraged <i>not</i> to
  * take advantage of the ability to insert nulls.  This is so because
  * {@code null} is used as a special return value by various methods
- * to indicated that the deque is empty.
+ * to indicate that the deque is empty.
  *
  * <p>{@code Deque} implementations generally do not define
  * element-based versions of the {@code equals} and {@code hashCode}
@@ -430,8 +441,8 @@
     /**
      * Retrieves and removes the head of the queue represented by this deque
      * (in other words, the first element of this deque).
-     * This method differs from {@link #poll poll} only in that it throws an
-     * exception if this deque is empty.
+     * This method differs from {@link #poll() poll()} only in that it
+     * throws an exception if this deque is empty.
      *
      * <p>This method is equivalent to {@link #removeFirst()}.
      *
@@ -477,6 +488,31 @@
      */
     E peek();
 
+    /**
+     * Adds all of the elements in the specified collection at the end
+     * of this deque, as if by calling {@link #addLast} on each one,
+     * in the order that they are returned by the collection's iterator.
+     *
+     * <p>When using a capacity-restricted deque, it is generally preferable
+     * to call {@link #offer(Object) offer} separately on each element.
+     *
+     * <p>An exception encountered while trying to add an element may result
+     * in only some of the elements having been successfully added when
+     * the associated exception is thrown.
+     *
+     * @param c the elements to be inserted into this deque
+     * @return {@code true} if this deque changed as a result of the call
+     * @throws IllegalStateException if not all the elements can be added at
+     *         this time due to insertion restrictions
+     * @throws ClassCastException if the class of an element of the specified
+     *         collection prevents it from being added to this deque
+     * @throws NullPointerException if the specified collection contains a
+     *         null element and this deque does not permit null elements,
+     *         or if the specified collection is null
+     * @throws IllegalArgumentException if some property of an element of the
+     *         specified collection prevents it from being added to this deque
+     */
+    boolean addAll(Collection<? extends E> c);
 
     // *** Stack methods ***
 
diff --git a/ojluni/src/main/java/java/util/Dictionary.java b/ojluni/src/main/java/java/util/Dictionary.java
index 4c4574b..c9825b4 100644
--- a/ojluni/src/main/java/java/util/Dictionary.java
+++ b/ojluni/src/main/java/java/util/Dictionary.java
@@ -26,14 +26,14 @@
 package java.util;
 
 /**
- * The <code>Dictionary</code> class is the abstract parent of any
- * class, such as <code>Hashtable</code>, which maps keys to values.
- * Every key and every value is an object. In any one <tt>Dictionary</tt>
+ * The {@code Dictionary} class is the abstract parent of any
+ * class, such as {@code Hashtable}, which maps keys to values.
+ * Every key and every value is an object. In any one {@code Dictionary}
  * object, every key is associated with at most one value. Given a
- * <tt>Dictionary</tt> and a key, the associated element can be looked up.
- * Any non-<code>null</code> object can be used as a key and as a value.
+ * {@code Dictionary} and a key, the associated element can be looked up.
+ * Any non-{@code null} object can be used as a key and as a value.
  * <p>
- * As a rule, the <code>equals</code> method should be used by
+ * As a rule, the {@code equals} method should be used by
  * implementations of this class to decide if two keys are the same.
  * <p>
  * <strong>NOTE: This class is obsolete.  New implementations should
@@ -44,7 +44,7 @@
  * @see     java.lang.Object#equals(java.lang.Object)
  * @see     java.lang.Object#hashCode()
  * @see     java.util.Hashtable
- * @since   JDK1.0
+ * @since   1.0
  */
 public abstract
 class Dictionary<K,V> {
@@ -60,21 +60,21 @@
      *
      * @return  the number of keys in this dictionary.
      */
-    abstract public int size();
+    public abstract int size();
 
     /**
      * Tests if this dictionary maps no keys to value. The general contract
-     * for the <tt>isEmpty</tt> method is that the result is true if and only
+     * for the {@code isEmpty} method is that the result is true if and only
      * if this dictionary contains no entries.
      *
-     * @return  <code>true</code> if this dictionary maps no keys to values;
-     *          <code>false</code> otherwise.
+     * @return  {@code true} if this dictionary maps no keys to values;
+     *          {@code false} otherwise.
      */
-    abstract public boolean isEmpty();
+    public abstract boolean isEmpty();
 
     /**
      * Returns an enumeration of the keys in this dictionary. The general
-     * contract for the keys method is that an <tt>Enumeration</tt> object
+     * contract for the keys method is that an {@code Enumeration} object
      * is returned that will generate all the keys for which this dictionary
      * contains entries.
      *
@@ -82,74 +82,74 @@
      * @see     java.util.Dictionary#elements()
      * @see     java.util.Enumeration
      */
-    abstract public Enumeration<K> keys();
+    public abstract Enumeration<K> keys();
 
     /**
      * Returns an enumeration of the values in this dictionary. The general
-     * contract for the <tt>elements</tt> method is that an
-     * <tt>Enumeration</tt> is returned that will generate all the elements
+     * contract for the {@code elements} method is that an
+     * {@code Enumeration} is returned that will generate all the elements
      * contained in entries in this dictionary.
      *
      * @return  an enumeration of the values in this dictionary.
      * @see     java.util.Dictionary#keys()
      * @see     java.util.Enumeration
      */
-    abstract public Enumeration<V> elements();
+    public abstract Enumeration<V> elements();
 
     /**
      * Returns the value to which the key is mapped in this dictionary.
-     * The general contract for the <tt>isEmpty</tt> method is that if this
+     * The general contract for the {@code isEmpty} method is that if this
      * dictionary contains an entry for the specified key, the associated
-     * value is returned; otherwise, <tt>null</tt> is returned.
+     * value is returned; otherwise, {@code null} is returned.
      *
      * @return  the value to which the key is mapped in this dictionary;
      * @param   key   a key in this dictionary.
-     *          <code>null</code> if the key is not mapped to any value in
+     *          {@code null} if the key is not mapped to any value in
      *          this dictionary.
-     * @exception NullPointerException if the <tt>key</tt> is <tt>null</tt>.
+     * @exception NullPointerException if the {@code key} is {@code null}.
      * @see     java.util.Dictionary#put(java.lang.Object, java.lang.Object)
      */
-    abstract public V get(Object key);
+    public abstract V get(Object key);
 
     /**
-     * Maps the specified <code>key</code> to the specified
-     * <code>value</code> in this dictionary. Neither the key nor the
-     * value can be <code>null</code>.
+     * Maps the specified {@code key} to the specified
+     * {@code value} in this dictionary. Neither the key nor the
+     * value can be {@code null}.
      * <p>
      * If this dictionary already contains an entry for the specified
-     * <tt>key</tt>, the value already in this dictionary for that
-     * <tt>key</tt> is returned, after modifying the entry to contain the
+     * {@code key}, the value already in this dictionary for that
+     * {@code key} is returned, after modifying the entry to contain the
      *  new element. <p>If this dictionary does not already have an entry
-     *  for the specified <tt>key</tt>, an entry is created for the
-     *  specified <tt>key</tt> and <tt>value</tt>, and <tt>null</tt> is
+     *  for the specified {@code key}, an entry is created for the
+     *  specified {@code key} and {@code value}, and {@code null} is
      *  returned.
      * <p>
-     * The <code>value</code> can be retrieved by calling the
-     * <code>get</code> method with a <code>key</code> that is equal to
-     * the original <code>key</code>.
+     * The {@code value} can be retrieved by calling the
+     * {@code get} method with a {@code key} that is equal to
+     * the original {@code key}.
      *
      * @param      key     the hashtable key.
      * @param      value   the value.
-     * @return     the previous value to which the <code>key</code> was mapped
-     *             in this dictionary, or <code>null</code> if the key did not
+     * @return     the previous value to which the {@code key} was mapped
+     *             in this dictionary, or {@code null} if the key did not
      *             have a previous mapping.
-     * @exception  NullPointerException  if the <code>key</code> or
-     *               <code>value</code> is <code>null</code>.
+     * @exception  NullPointerException  if the {@code key} or
+     *               {@code value} is {@code null}.
      * @see        java.lang.Object#equals(java.lang.Object)
      * @see        java.util.Dictionary#get(java.lang.Object)
      */
-    abstract public V put(K key, V value);
+    public abstract V put(K key, V value);
 
     /**
-     * Removes the <code>key</code> (and its corresponding
-     * <code>value</code>) from this dictionary. This method does nothing
-     * if the <code>key</code> is not in this dictionary.
+     * Removes the {@code key} (and its corresponding
+     * {@code value}) from this dictionary. This method does nothing
+     * if the {@code key} is not in this dictionary.
      *
      * @param   key   the key that needs to be removed.
-     * @return  the value to which the <code>key</code> had been mapped in this
-     *          dictionary, or <code>null</code> if the key did not have a
+     * @return  the value to which the {@code key} had been mapped in this
+     *          dictionary, or {@code null} if the key did not have a
      *          mapping.
-     * @exception NullPointerException if <tt>key</tt> is <tt>null</tt>.
+     * @exception NullPointerException if {@code key} is {@code null}.
      */
-    abstract public V remove(Object key);
+    public abstract V remove(Object key);
 }
diff --git a/ojluni/src/main/java/java/util/DualPivotQuicksort.java b/ojluni/src/main/java/java/util/DualPivotQuicksort.java
index 4682dde..97a48ae 100644
--- a/ojluni/src/main/java/java/util/DualPivotQuicksort.java
+++ b/ojluni/src/main/java/java/util/DualPivotQuicksort.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,11 +61,6 @@
     private static final int MAX_RUN_COUNT = 67;
 
     /**
-     * The maximum length of run in merge sort.
-     */
-    private static final int MAX_RUN_LENGTH = 33;
-
-    /**
      * If the length of an array to be sorted is less than this
      * constant, Quicksort is used in preference to merge sort.
      */
@@ -121,20 +116,24 @@
 
         // Check if the array is nearly sorted
         for (int k = left; k < right; run[count] = k) {
+            // Equal items in the beginning of the sequence
+            while (k < right && a[k] == a[k + 1])
+                k++;
+            if (k == right) break;  // Sequence finishes with equal items
             if (a[k] < a[k + 1]) { // ascending
                 while (++k <= right && a[k - 1] <= a[k]);
             } else if (a[k] > a[k + 1]) { // descending
                 while (++k <= right && a[k - 1] >= a[k]);
+                // Transform into an ascending sequence
                 for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                     int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                 }
-            } else { // equal
-                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
-                    if (--m == 0) {
-                        sort(a, left, right, true);
-                        return;
-                    }
-                }
+            }
+
+            // Merge a transformed descending sequence followed by an
+            // ascending sequence
+            if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+                count--;
             }
 
             /*
@@ -147,12 +146,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count == 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -569,20 +582,24 @@
 
         // Check if the array is nearly sorted
         for (int k = left; k < right; run[count] = k) {
+            // Equal items in the beginning of the sequence
+            while (k < right && a[k] == a[k + 1])
+                k++;
+            if (k == right) break;  // Sequence finishes with equal items
             if (a[k] < a[k + 1]) { // ascending
                 while (++k <= right && a[k - 1] <= a[k]);
             } else if (a[k] > a[k + 1]) { // descending
                 while (++k <= right && a[k - 1] >= a[k]);
+                // Transform into an ascending sequence
                 for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                     long t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                 }
-            } else { // equal
-                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
-                    if (--m == 0) {
-                        sort(a, left, right, true);
-                        return;
-                    }
-                }
+            }
+
+            // Merge a transformed descending sequence followed by an
+            // ascending sequence
+            if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+                count--;
             }
 
             /*
@@ -595,12 +612,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count == 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -1053,20 +1084,24 @@
 
         // Check if the array is nearly sorted
         for (int k = left; k < right; run[count] = k) {
+            // Equal items in the beginning of the sequence
+            while (k < right && a[k] == a[k + 1])
+                k++;
+            if (k == right) break;  // Sequence finishes with equal items
             if (a[k] < a[k + 1]) { // ascending
                 while (++k <= right && a[k - 1] <= a[k]);
             } else if (a[k] > a[k + 1]) { // descending
                 while (++k <= right && a[k - 1] >= a[k]);
+                // Transform into an ascending sequence
                 for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                     short t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                 }
-            } else { // equal
-                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
-                    if (--m == 0) {
-                        sort(a, left, right, true);
-                        return;
-                    }
-                }
+            }
+
+            // Merge a transformed descending sequence followed by an
+            // ascending sequence
+            if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+                count--;
             }
 
             /*
@@ -1079,12 +1114,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count == 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -1537,20 +1586,24 @@
 
         // Check if the array is nearly sorted
         for (int k = left; k < right; run[count] = k) {
+            // Equal items in the beginning of the sequence
+            while (k < right && a[k] == a[k + 1])
+                k++;
+            if (k == right) break;  // Sequence finishes with equal items
             if (a[k] < a[k + 1]) { // ascending
                 while (++k <= right && a[k - 1] <= a[k]);
             } else if (a[k] > a[k + 1]) { // descending
                 while (++k <= right && a[k - 1] >= a[k]);
+                // Transform into an ascending sequence
                 for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                     char t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                 }
-            } else { // equal
-                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
-                    if (--m == 0) {
-                        sort(a, left, right, true);
-                        return;
-                    }
-                }
+            }
+
+            // Merge a transformed descending sequence followed by an
+            // ascending sequence
+            if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+                count--;
             }
 
             /*
@@ -1563,12 +1616,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count == 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -2117,20 +2184,24 @@
 
         // Check if the array is nearly sorted
         for (int k = left; k < right; run[count] = k) {
+            // Equal items in the beginning of the sequence
+            while (k < right && a[k] == a[k + 1])
+                k++;
+            if (k == right) break;  // Sequence finishes with equal items
             if (a[k] < a[k + 1]) { // ascending
                 while (++k <= right && a[k - 1] <= a[k]);
             } else if (a[k] > a[k + 1]) { // descending
                 while (++k <= right && a[k - 1] >= a[k]);
+                // Transform into an ascending sequence
                 for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                     float t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                 }
-            } else { // equal
-                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
-                    if (--m == 0) {
-                        sort(a, left, right, true);
-                        return;
-                    }
-                }
+            }
+
+            // Merge a transformed descending sequence followed by an
+            // ascending sequence
+            if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+                count--;
             }
 
             /*
@@ -2143,12 +2214,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count == 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
@@ -2656,20 +2741,24 @@
 
         // Check if the array is nearly sorted
         for (int k = left; k < right; run[count] = k) {
+            // Equal items in the beginning of the sequence
+            while (k < right && a[k] == a[k + 1])
+                k++;
+            if (k == right) break;  // Sequence finishes with equal items
             if (a[k] < a[k + 1]) { // ascending
                 while (++k <= right && a[k - 1] <= a[k]);
             } else if (a[k] > a[k + 1]) { // descending
                 while (++k <= right && a[k - 1] >= a[k]);
+                // Transform into an ascending sequence
                 for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                     double t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                 }
-            } else { // equal
-                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
-                    if (--m == 0) {
-                        sort(a, left, right, true);
-                        return;
-                    }
-                }
+            }
+
+            // Merge a transformed descending sequence followed by an
+            // ascending sequence
+            if (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
+                count--;
             }
 
             /*
@@ -2682,12 +2771,26 @@
             }
         }
 
-        // Check special cases
-        // Implementation note: variable "right" is increased by 1.
-        if (run[count] == right++) { // The last run contains one element
-            run[++count] = right;
-        } else if (count == 1) { // The array is already sorted
+        // These invariants should hold true:
+        //    run[0] = 0
+        //    run[<last>] = right + 1; (terminator)
+
+        if (count == 0) {
+            // A single equal run
             return;
+        } else if (count == 1 && run[count] > right) {
+            // Either a single ascending or a transformed descending run.
+            // Always check that a final run is a proper terminator, otherwise
+            // we have an unterminated trailing run, to handle downstream.
+            return;
+        }
+        right++;
+        if (run[count] < right) {
+            // Corner case: the final run is not a terminator. This may happen
+            // if a final run is an equals run, or there is a single-element run
+            // at the end. Fix up by adding a proper terminator at the end.
+            // Note that we terminate with (right + 1), incremented earlier.
+            run[++count] = right;
         }
 
         // Determine alternation base for merge
diff --git a/ojluni/src/main/java/java/util/DuplicateFormatFlagsException.java b/ojluni/src/main/java/java/util/DuplicateFormatFlagsException.java
index 0dcdf37..ec016a5 100644
--- a/ojluni/src/main/java/java/util/DuplicateFormatFlagsException.java
+++ b/ojluni/src/main/java/java/util/DuplicateFormatFlagsException.java
@@ -29,7 +29,7 @@
  * Unchecked exception thrown when duplicate flags are provided in the format
  * specifier.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/EmptyStackException.java b/ojluni/src/main/java/java/util/EmptyStackException.java
index 1f1e878..53dcacd 100644
--- a/ojluni/src/main/java/java/util/EmptyStackException.java
+++ b/ojluni/src/main/java/java/util/EmptyStackException.java
@@ -26,19 +26,19 @@
 package java.util;
 
 /**
- * Thrown by methods in the <code>Stack</code> class to indicate
+ * Thrown by methods in the {@code Stack} class to indicate
  * that the stack is empty.
  *
  * @author  Jonathan Payne
  * @see     java.util.Stack
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class EmptyStackException extends RuntimeException {
     private static final long serialVersionUID = 5084686378493302095L;
 
     /**
-     * Constructs a new <code>EmptyStackException</code> with <tt>null</tt>
+     * Constructs a new {@code EmptyStackException} with {@code null}
      * as its error message string.
      */
     public EmptyStackException() {
diff --git a/ojluni/src/main/java/java/util/EnumMap.java b/ojluni/src/main/java/java/util/EnumMap.java
index 30a8dce..66a767d 100644
--- a/ojluni/src/main/java/java/util/EnumMap.java
+++ b/ojluni/src/main/java/java/util/EnumMap.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,6 @@
 
 package java.util;
 
-import java.util.Map.Entry;
-
 /**
  * A specialized {@link Map} implementation for use with enum type keys.  All
  * of the keys in an enum map must come from a single enum type that is
@@ -50,7 +48,7 @@
  * presence of a null key or to remove one will, however, function properly.
  * Null values are permitted.
 
- * <P>Like most collection implementations <tt>EnumMap</tt> is not
+ * <P>Like most collection implementations {@code EnumMap} is not
  * synchronized. If multiple threads access an enum map concurrently, and at
  * least one of the threads modifies the map, it should be synchronized
  * externally.  This is typically accomplished by synchronizing on some
@@ -69,7 +67,7 @@
  * {@link HashMap} counterparts.
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author Josh Bloch
@@ -80,7 +78,7 @@
     implements java.io.Serializable, Cloneable
 {
     /**
-     * The <tt>Class</tt> object for the enum type of all the keys of this map.
+     * The {@code Class} object for the enum type of all the keys of this map.
      *
      * @serial
      */
@@ -125,13 +123,11 @@
         return (V)(value == NULL ? null : value);
     }
 
-    private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
-
     /**
      * Creates an empty enum map with the specified key type.
      *
      * @param keyType the class object of the key type for this enum map
-     * @throws NullPointerException if <tt>keyType</tt> is null
+     * @throws NullPointerException if {@code keyType} is null
      */
     public EnumMap(Class<K> keyType) {
         this.keyType = keyType;
@@ -144,7 +140,7 @@
      * map, initially containing the same mappings (if any).
      *
      * @param m the enum map from which to initialize this enum map
-     * @throws NullPointerException if <tt>m</tt> is null
+     * @throws NullPointerException if {@code m} is null
      */
     public EnumMap(EnumMap<K, ? extends V> m) {
         keyType = m.keyType;
@@ -155,15 +151,15 @@
 
     /**
      * Creates an enum map initialized from the specified map.  If the
-     * specified map is an <tt>EnumMap</tt> instance, this constructor behaves
+     * specified map is an {@code EnumMap} instance, this constructor behaves
      * identically to {@link #EnumMap(EnumMap)}.  Otherwise, the specified map
      * must contain at least one mapping (in order to determine the new
      * enum map's key type).
      *
      * @param m the map from which to initialize this enum map
-     * @throws IllegalArgumentException if <tt>m</tt> is not an
-     *     <tt>EnumMap</tt> instance and contains no mappings
-     * @throws NullPointerException if <tt>m</tt> is null
+     * @throws IllegalArgumentException if {@code m} is not an
+     *     {@code EnumMap} instance and contains no mappings
+     * @throws NullPointerException if {@code m} is null
      */
     public EnumMap(Map<K, ? extends V> m) {
         if (m instanceof EnumMap) {
@@ -194,11 +190,11 @@
     }
 
     /**
-     * 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.
      *
      * @param value the value whose presence in this map is to be tested
-     * @return <tt>true</tt> if this map maps one or more keys to this value
+     * @return {@code true} if this map maps one or more keys to this value
      */
     public boolean containsValue(Object value) {
         value = maskNull(value);
@@ -211,11 +207,11 @@
     }
 
     /**
-     * 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 the key whose presence in this map is to be tested
-     * @return <tt>true</tt> if this map contains a mapping for the specified
+     * @return {@code true} if this map contains a mapping for the specified
      *            key
      */
     public boolean containsKey(Object key) {
@@ -258,9 +254,9 @@
      * @param value the value to be associated with the specified key
      *
      * @return the previous value associated with specified key, or
-     *     <tt>null</tt> if there was no mapping for key.  (A <tt>null</tt>
+     *     {@code null} if there was no mapping for key.  (A {@code null}
      *     return can also indicate that the map previously associated
-     *     <tt>null</tt> with the specified key.)
+     *     {@code null} with the specified key.)
      * @throws NullPointerException if the specified key is null
      */
     public V put(K key, V value) {
@@ -279,9 +275,9 @@
      *
      * @param key the key whose mapping is to be removed from the map
      * @return the previous value associated with specified key, or
-     *     <tt>null</tt> if there was no entry for key.  (A <tt>null</tt>
+     *     {@code null} if there was no entry for key.  (A {@code null}
      *     return can also indicate that the map previously associated
-     *     <tt>null</tt> with the specified key.)
+     *     {@code null} with the specified key.)
      */
     public V remove(Object key) {
         if (!isValidKey(key))
@@ -646,12 +642,12 @@
 
     /**
      * Compares the specified object with this map for equality.  Returns
-     * <tt>true</tt> if the given object is also a map and the two maps
+     * {@code true} if the given object is also a map and the two maps
      * represent the same mappings, as specified in the {@link
      * Map#equals(Object)} contract.
      *
      * @param o the 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 (this == o)
@@ -683,8 +679,11 @@
     }
 
     private boolean equals(EnumMap<?,?> em) {
+        if (em.size != size)
+            return false;
+
         if (em.keyType != keyType)
-            return size == 0 && em.size == 0;
+            return size == 0;
 
         // Key types match, compare each value
         for (int i = 0; i < keyUniverse.length; i++) {
@@ -718,7 +717,7 @@
     }
 
     /**
-     * Returns a shallow copy of this enum map.  (The values themselves
+     * Returns a shallow copy of this enum map. The values themselves
      * are not cloned.
      *
      * @return a shallow copy of this enum map
@@ -758,7 +757,7 @@
     private static final long serialVersionUID = 458661240069192865L;
 
     /**
-     * Save the state of the <tt>EnumMap</tt> instance to a stream (i.e.,
+     * Save the state of the {@code EnumMap} instance to a stream (i.e.,
      * serialize it).
      *
      * @serialData The <i>size</i> of the enum map (the number of key-value
@@ -787,7 +786,7 @@
     }
 
     /**
-     * Reconstitute the <tt>EnumMap</tt> instance from a stream (i.e.,
+     * Reconstitute the {@code EnumMap} instance from a stream (i.e.,
      * deserialize it).
      */
     @SuppressWarnings("unchecked")
diff --git a/ojluni/src/main/java/java/util/EnumSet.java b/ojluni/src/main/java/java/util/EnumSet.java
index f1b0329..cef74b7 100644
--- a/ojluni/src/main/java/java/util/EnumSet.java
+++ b/ojluni/src/main/java/java/util/EnumSet.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,11 +33,11 @@
  * are represented internally as bit vectors.  This representation is
  * extremely compact and efficient. The space and time performance of this
  * class should be good enough to allow its use as a high-quality, typesafe
- * alternative to traditional <tt>int</tt>-based "bit flags."  Even bulk
- * operations (such as <tt>containsAll</tt> and <tt>retainAll</tt>) should
+ * alternative to traditional {@code int}-based "bit flags."  Even bulk
+ * operations (such as {@code containsAll} and {@code retainAll}) should
  * run very quickly if their argument is also an enum set.
  *
- * <p>The iterator returned by the <tt>iterator</tt> method traverses the
+ * <p>The iterator returned by the {@code iterator} method traverses the
  * elements in their <i>natural order</i> (the order in which the enum
  * constants are declared).  The returned iterator is <i>weakly
  * consistent</i>: it will never throw {@link ConcurrentModificationException}
@@ -49,7 +49,7 @@
  * presence of a null element or to remove one will, however, function
  * properly.
  *
- * <P>Like most collection implementations, <tt>EnumSet</tt> is not
+ * <P>Like most collection implementations, {@code EnumSet} is not
  * synchronized.  If multiple threads access an enum set concurrently, and at
  * least one of the threads modifies the set, it should be synchronized
  * externally.  This is typically accomplished by synchronizing on some
@@ -68,29 +68,34 @@
  * constant time if their argument is also an enum set.
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author Josh Bloch
  * @since 1.5
  * @see EnumMap
- * @serial exclude
  */
+@SuppressWarnings("serial") // No serialVersionUID declared
 public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
     implements Cloneable, java.io.Serializable
 {
+    // The following must be present in order to preserve the same computed
+    // serialVersionUID value as JDK 8, and to prevent the appearance of
+    // the fields in the Serialized Form documentation. See JDK-8227368.
+    static Enum<?>[] access$000() { return null; }
+    private static final java.io.ObjectStreamField[] serialPersistentFields
+        = new java.io.ObjectStreamField[0];
+
     /**
      * The class of all the elements of this set.
      */
     final Class<E> elementType;
 
     /**
-     * All of the values comprising T.  (Cached for performance.)
+     * All of the values comprising E.  (Cached for performance.)
      */
     final Enum<?>[] universe;
 
-    private static Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
-
     EnumSet(Class<E>elementType, Enum<?>[] universe) {
         this.elementType = elementType;
         this.universe    = universe;
@@ -103,7 +108,7 @@
      * @param elementType the class object of the element type for this enum
      *     set
      * @return An empty enum set of the specified type.
-     * @throws NullPointerException if <tt>elementType</tt> is null
+     * @throws NullPointerException if {@code elementType} is null
      */
     public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
         Enum<?>[] universe = getUniverse(elementType);
@@ -124,7 +129,7 @@
      * @param elementType the class object of the element type for this enum
      *     set
      * @return An enum set containing all the elements in the specified type.
-     * @throws NullPointerException if <tt>elementType</tt> is null
+     * @throws NullPointerException if {@code elementType} is null
      */
     public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
         EnumSet<E> result = noneOf(elementType);
@@ -145,7 +150,7 @@
      * @param <E> The class of the elements in the set
      * @param s the enum set from which to initialize this enum set
      * @return A copy of the specified enum set.
-     * @throws NullPointerException if <tt>s</tt> is null
+     * @throws NullPointerException if {@code s} is null
      */
     public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
         return s.clone();
@@ -153,7 +158,7 @@
 
     /**
      * Creates an enum set initialized from the specified collection.  If
-     * the specified collection is an <tt>EnumSet</tt> instance, this static
+     * the specified collection is an {@code EnumSet} instance, this static
      * factory method behaves identically to {@link #copyOf(EnumSet)}.
      * Otherwise, the specified collection must contain at least one element
      * (in order to determine the new enum set's element type).
@@ -161,9 +166,9 @@
      * @param <E> The class of the elements in the collection
      * @param c the collection from which to initialize this enum set
      * @return An enum set initialized from the given collection.
-     * @throws IllegalArgumentException if <tt>c</tt> is not an
-     *     <tt>EnumSet</tt> instance and contains no elements
-     * @throws NullPointerException if <tt>c</tt> is null
+     * @throws IllegalArgumentException if {@code c} is not an
+     *     {@code EnumSet} instance and contains no elements
+     * @throws NullPointerException if {@code c} is null
      */
     public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
         if (c instanceof EnumSet) {
@@ -188,7 +193,7 @@
      * @param <E> The class of the elements in the enum set
      * @param s the enum set from whose complement to initialize this enum set
      * @return The complement of the specified set in this set
-     * @throws NullPointerException if <tt>s</tt> is null
+     * @throws NullPointerException if {@code s} is null
      */
     public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
         EnumSet<E> result = copyOf(s);
@@ -207,7 +212,7 @@
      *
      * @param <E> The class of the specified element and of the set
      * @param e the element that this set is to contain initially
-     * @throws NullPointerException if <tt>e</tt> is null
+     * @throws NullPointerException if {@code e} is null
      * @return an enum set initially containing the specified element
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e) {
@@ -329,7 +334,7 @@
      * @param first an element that the set is to contain initially
      * @param rest the remaining elements the set is to contain initially
      * @throws NullPointerException if any of the specified elements are null,
-     *     or if <tt>rest</tt> is null
+     *     or if {@code rest} is null
      * @return an enum set initially containing the specified elements
      */
     @SafeVarargs
@@ -416,9 +421,12 @@
      *
      * @serial include
      */
-    private static class SerializationProxy <E extends Enum<E>>
+    private static class SerializationProxy<E extends Enum<E>>
         implements java.io.Serializable
     {
+
+        private static final Enum<?>[] ZERO_LENGTH_ENUM_ARRAY = new Enum<?>[0];
+
         /**
          * The element type of this enum set.
          *
@@ -438,10 +446,18 @@
             elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
         }
 
-        // instead of cast to E, we should perhaps use elementType.cast()
-        // to avoid injection of forged stream, but it will slow the implementation
+        /**
+         * Returns an {@code EnumSet} object with initial state
+         * held by this proxy.
+         *
+         * @return a {@code EnumSet} object with initial state
+         * held by this proxy
+         */
         @SuppressWarnings("unchecked")
         private Object readResolve() {
+            // instead of cast to E, we should perhaps use elementType.cast()
+            // to avoid injection of forged stream, but it will slow the
+            // implementation
             EnumSet<E> result = EnumSet.noneOf(elementType);
             for (Enum<?> e : elements)
                 result.add((E)e);
@@ -451,13 +467,24 @@
         private static final long serialVersionUID = 362491234563181265L;
     }
 
+    /**
+     * Returns a
+     * <a href="../../serialized-form.html#java.util.EnumSet.SerializationProxy">
+     * SerializationProxy</a>
+     * representing the state of this instance.
+     *
+     * @return a {@link SerializationProxy}
+     * representing the state of this instance
+     */
     Object writeReplace() {
         return new SerializationProxy<>(this);
     }
 
-    // readObject method for the serialization proxy pattern
-    // See Effective Java, Second Ed., Item 78.
-    private void readObject(java.io.ObjectInputStream stream)
+    /**
+     * @param s the stream
+     * @throws java.io.InvalidObjectException always
+     */
+    private void readObject(java.io.ObjectInputStream s)
         throws java.io.InvalidObjectException {
         throw new java.io.InvalidObjectException("Proxy required");
     }
diff --git a/ojluni/src/main/java/java/util/Enumeration.java b/ojluni/src/main/java/java/util/Enumeration.java
index 8aebb5c..96aa3a9 100644
--- a/ojluni/src/main/java/java/util/Enumeration.java
+++ b/ojluni/src/main/java/java/util/Enumeration.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,10 +28,10 @@
 /**
  * An object that implements the Enumeration interface generates a
  * series of elements, one at a time. Successive calls to the
- * <code>nextElement</code> method return successive elements of the
+ * {@code nextElement} method return successive elements of the
  * series.
  * <p>
- * For example, to print all elements of a <tt>Vector&lt;E&gt;</tt> <i>v</i>:
+ * For example, to print all elements of a {@code Vector<E>} <i>v</i>:
  * <pre>
  *   for (Enumeration&lt;E&gt; e = v.elements(); e.hasMoreElements();)
  *       System.out.println(e.nextElement());</pre>
@@ -39,12 +39,15 @@
  * Methods are provided to enumerate through the elements of a
  * vector, the keys of a hashtable, and the values in a hashtable.
  * Enumerations are also used to specify the input streams to a
- * <code>SequenceInputStream</code>.
- * <p>
- * NOTE: The functionality of this interface is duplicated by the Iterator
- * interface.  In addition, Iterator adds an optional remove operation, and
- * has shorter method names.  New implementations should consider using
- * Iterator in preference to Enumeration.
+ * {@code SequenceInputStream}.
+ *
+ * @apiNote
+ * The functionality of this interface is duplicated by the {@link Iterator}
+ * interface.  In addition, {@code Iterator} adds an optional remove operation,
+ * and has shorter method names.  New implementations should consider using
+ * {@code Iterator} in preference to {@code Enumeration}. It is possible to
+ * adapt an {@code Enumeration} to an {@code Iterator} by using the
+ * {@link #asIterator} method.
  *
  * @see     java.util.Iterator
  * @see     java.io.SequenceInputStream
@@ -56,15 +59,15 @@
  * @see     java.util.Vector#elements()
  *
  * @author  Lee Boynton
- * @since   JDK1.0
+ * @since   1.0
  */
 public interface Enumeration<E> {
     /**
      * Tests if this enumeration contains more elements.
      *
-     * @return  <code>true</code> if and only if this enumeration object
+     * @return  {@code true} if and only if this enumeration object
      *           contains at least one more element to provide;
-     *          <code>false</code> otherwise.
+     *          {@code false} otherwise.
      */
     boolean hasMoreElements();
 
@@ -76,4 +79,49 @@
      * @exception  NoSuchElementException  if no more elements exist.
      */
     E nextElement();
+
+    /**
+     * Returns an {@link Iterator} that traverses the remaining elements
+     * covered by this enumeration. Traversal is undefined if any methods
+     * are called on this enumeration after the call to {@code asIterator}.
+     *
+     * @apiNote
+     * This method is intended to help adapt code that produces
+     * {@code Enumeration} instances to code that consumes {@code Iterator}
+     * instances. For example, the {@link java.util.jar.JarFile#entries
+     * JarFile.entries()} method returns an {@code Enumeration<JarEntry>}.
+     * This can be turned into an {@code Iterator}, and then the
+     * {@code forEachRemaining()} method can be used:
+     *
+     * <pre>{@code
+     *     JarFile jarFile = ... ;
+     *     jarFile.entries().asIterator().forEachRemaining(entry -> { ... });
+     * }</pre>
+     *
+     * (Note that there is also a {@link java.util.jar.JarFile#stream
+     * JarFile.stream()} method that returns a {@code Stream} of entries,
+     * which may be more convenient in some cases.)
+     *
+     * @implSpec
+     * The default implementation returns an {@code Iterator} whose
+     * {@link Iterator#hasNext hasNext} method calls this Enumeration's
+     * {@code hasMoreElements} method, whose {@link Iterator#next next}
+     * method calls this Enumeration's {@code nextElement} method, and
+     * whose {@link Iterator#remove remove} method throws
+     * {@code UnsupportedOperationException}.
+     *
+     * @return an Iterator representing the remaining elements of this Enumeration
+     *
+     * @since 9
+     */
+    default Iterator<E> asIterator() {
+        return new Iterator<>() {
+            @Override public boolean hasNext() {
+                return hasMoreElements();
+            }
+            @Override public E next() {
+                return nextElement();
+            }
+        };
+    }
 }
diff --git a/ojluni/src/main/java/java/util/EventListener.java b/ojluni/src/main/java/java/util/EventListener.java
index 1daf446..9e51158 100644
--- a/ojluni/src/main/java/java/util/EventListener.java
+++ b/ojluni/src/main/java/java/util/EventListener.java
@@ -27,7 +27,7 @@
 
 /**
  * A tagging interface that all event listener interfaces must extend.
- * @since JDK1.1
+ * @since 1.1
  */
 public interface EventListener {
 }
diff --git a/ojluni/src/main/java/java/util/EventObject.java b/ojluni/src/main/java/java/util/EventObject.java
index 3bccae1..ff89754 100644
--- a/ojluni/src/main/java/java/util/EventObject.java
+++ b/ojluni/src/main/java/java/util/EventObject.java
@@ -33,7 +33,7 @@
  * that is logically deemed to be the object upon which the Event in question
  * initially occurred upon.
  *
- * @since JDK1.1
+ * @since 1.1
  */
 
 public class EventObject implements java.io.Serializable {
@@ -43,13 +43,13 @@
     /**
      * The object on which the Event initially occurred.
      */
-    protected transient Object  source;
+    protected transient Object source;
 
     /**
      * Constructs a prototypical Event.
      *
-     * @param    source    The object on which the Event initially occurred.
-     * @exception  IllegalArgumentException  if source is null.
+     * @param source the object on which the Event initially occurred
+     * @throws IllegalArgumentException if source is null
      */
     public EventObject(Object source) {
         if (source == null)
@@ -61,7 +61,7 @@
     /**
      * The object on which the Event initially occurred.
      *
-     * @return   The object on which the Event initially occurred.
+     * @return the object on which the Event initially occurred
      */
     public Object getSource() {
         return source;
@@ -70,7 +70,7 @@
     /**
      * Returns a String representation of this EventObject.
      *
-     * @return  A a String representation of this EventObject.
+     * @return a String representation of this EventObject
      */
     public String toString() {
         return getClass().getName() + "[source=" + source + "]";
diff --git a/ojluni/src/main/java/java/util/FormatFlagsConversionMismatchException.java b/ojluni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
index 58f593e..664cd39 100644
--- a/ojluni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
+++ b/ojluni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
@@ -28,7 +28,7 @@
 /**
  * Unchecked exception thrown when a conversion and flag are incompatible.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/Formattable.java b/ojluni/src/main/java/java/util/Formattable.java
index f7e1e50..2caabae 100644
--- a/ojluni/src/main/java/java/util/Formattable.java
+++ b/ojluni/src/main/java/java/util/Formattable.java
@@ -28,22 +28,22 @@
 import java.io.IOException;
 
 /**
- * The <tt>Formattable</tt> interface must be implemented by any class that
- * needs to perform custom formatting using the <tt>'s'</tt> conversion
+ * The {@code Formattable} interface must be implemented by any class that
+ * needs to perform custom formatting using the {@code 's'} conversion
  * specifier of {@link java.util.Formatter}.  This interface allows basic
  * control for formatting arbitrary objects.
  *
  * For example, the following class prints out different representations of a
  * stock's name depending on the flags and length constraints:
  *
- * {@code
+ * <pre> {@code
  *   import java.nio.CharBuffer;
  *   import java.util.Formatter;
  *   import java.util.Formattable;
  *   import java.util.Locale;
  *   import static java.util.FormattableFlags.*;
  *
- *  ...
+ *   ...
  *
  *   public class StockName implements Formattable {
  *       private String symbol, companyName, frenchCompanyName;
@@ -89,12 +89,12 @@
  *           return String.format("%s - %s", symbol, companyName);
  *       }
  *   }
- * }
+ * }</pre>
  *
  * <p> When used in conjunction with the {@link java.util.Formatter}, the above
  * class produces the following output for various format strings.
  *
- * {@code
+ * <pre> {@code
  *   Formatter fmt = new Formatter();
  *   StockName sn = new StockName("HUGE", "Huge Fruit, Inc.",
  *                                "Fruit Titanesque, Inc.");
@@ -104,13 +104,13 @@
  *   fmt.format("%-10.8s", sn);              //   -> "HUGE      "
  *   fmt.format("%.12s", sn);                //   -> "Huge Fruit,*"
  *   fmt.format(Locale.FRANCE, "%25s", sn);  //   -> "   Fruit Titanesque, Inc."
- * }
+ * }</pre>
  *
  * <p> Formattables are not necessarily safe for multithreaded access.  Thread
  * safety is optional and may be enforced by classes that extend and implement
  * this interface.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to
+ * <p> Unless otherwise specified, passing a {@code null} argument to
  * any method in this interface will cause a {@link
  * NullPointerException} to be thrown.
  *
@@ -126,7 +126,7 @@
      *         {@link Formatter#out() formatter.out()} or {@link
      *         Formatter#locale() formatter.locale()} to obtain the {@link
      *         Appendable} or {@link Locale} used by this
-     *         <tt>formatter</tt> respectively.
+     *         {@code formatter} respectively.
      *
      * @param  flags
      *         The flags modify the output format.  The value is interpreted as
@@ -139,19 +139,19 @@
      * @param  width
      *         The minimum number of characters to be written to the output.
      *         If the length of the converted value is less than the
-     *         <tt>width</tt> then the output will be padded by
-     *         <tt>'&nbsp;&nbsp;'</tt> until the total number of characters
+     *         {@code width} then the output will be padded by
+     *         <code>'&nbsp;&nbsp;'</code> until the total number of characters
      *         equals width.  The padding is at the beginning by default.  If
      *         the {@link FormattableFlags#LEFT_JUSTIFY} flag is set then the
-     *         padding will be at the end.  If <tt>width</tt> is <tt>-1</tt>
+     *         padding will be at the end.  If {@code width} is {@code -1}
      *         then there is no minimum.
      *
      * @param  precision
      *         The maximum number of characters to be written to the output.
      *         The precision is applied before the width, thus the output will
-     *         be truncated to <tt>precision</tt> characters even if the
-     *         <tt>width</tt> is greater than the <tt>precision</tt>.  If
-     *         <tt>precision</tt> is <tt>-1</tt> then there is no explicit
+     *         be truncated to {@code precision} characters even if the
+     *         {@code width} is greater than the {@code precision}.  If
+     *         {@code precision} is {@code -1} then there is no explicit
      *         limit on the number of characters.
      *
      * @throws  IllegalFormatException
diff --git a/ojluni/src/main/java/java/util/FormattableFlags.java b/ojluni/src/main/java/java/util/FormattableFlags.java
index 11a10dd..92c020f 100644
--- a/ojluni/src/main/java/java/util/FormattableFlags.java
+++ b/ojluni/src/main/java/java/util/FormattableFlags.java
@@ -26,7 +26,7 @@
 package java.util;
 
 /**
- * FomattableFlags are passed to the {@link Formattable#formatTo
+ * FormattableFlags are passed to the {@link Formattable#formatTo
  * Formattable.formatTo()} method and modify the output format for {@linkplain
  * Formattable Formattables}.  Implementations of {@link Formattable} are
  * responsible for interpreting and validating any flags.
@@ -39,12 +39,12 @@
     private FormattableFlags() {}
 
     /**
-     * Left-justifies the output.  Spaces (<tt>'&#92;u0020'</tt>) will be added
+     * Left-justifies the output.  Spaces (<code>'&#92;u0020'</code>) will be added
      * at the end of the converted value as required to fill the minimum width
      * of the field.  If this flag is not set then the output will be
      * right-justified.
      *
-     * <p> This flag corresponds to <tt>'-'</tt> (<tt>'&#92;u002d'</tt>) in
+     * <p> This flag corresponds to {@code '-'} (<code>'&#92;u002d'</code>) in
      * the format specifier.
      */
     public static final int LEFT_JUSTIFY = 1<<0; // '-'
@@ -52,23 +52,23 @@
     /**
      * Converts the output to upper case according to the rules of the
      * {@linkplain java.util.Locale locale} given during creation of the
-     * <tt>formatter</tt> argument of the {@link Formattable#formatTo
+     * {@code formatter} argument of the {@link Formattable#formatTo
      * formatTo()} method.  The output should be equivalent the following
      * invocation of {@link String#toUpperCase(java.util.Locale)}
      *
      * <pre>
      *     out.toUpperCase() </pre>
      *
-     * <p> This flag corresponds to <tt>'S'</tt> (<tt>'&#92;u0053'</tt>) in
+     * <p> This flag corresponds to {@code 'S'} (<code>'&#92;u0053'</code>) in
      * the format specifier.
      */
     public static final int UPPERCASE = 1<<1;    // 'S'
 
     /**
      * Requires the output to use an alternate form.  The definition of the
-     * form is specified by the <tt>Formattable</tt>.
+     * form is specified by the {@code Formattable}.
      *
-     * <p> This flag corresponds to <tt>'#'</tt> (<tt>'&#92;u0023'</tt>) in
+     * <p> This flag corresponds to {@code '#'} (<code>'&#92;u0023'</code>) in
      * the format specifier.
      */
     public static final int ALTERNATE = 1<<2;    // '#'
diff --git a/ojluni/src/main/java/java/util/Formatter.java b/ojluni/src/main/java/java/util/Formatter.java
index 0b0c095..b5c3c3a 100644
--- a/ojluni/src/main/java/java/util/Formatter.java
+++ b/ojluni/src/main/java/java/util/Formatter.java
@@ -56,10 +56,10 @@
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalQueries;
 
+import libcore.icu.DecimalFormatData;
 import libcore.icu.LocaleData;
-import sun.misc.FpUtils;
-import sun.misc.DoubleConsts;
-import sun.misc.FormattedFloatingDecimal;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FormattedFloatingDecimal;
 
 // Android-changed: Use localized exponent separator for %e.
 /**
@@ -2284,8 +2284,13 @@
 
     private static char getZero(Locale l) {
         if ((l != null) && !l.equals(Locale.US)) {
-            DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
-            return dfs.getZeroDigit();
+            // Android-changed: Improve the performance by 10x http://b/197788756
+            // Unclear if this mapping is needed but inherited from DecimalFormatSymbols
+            l = LocaleData.mapInvalidAndNullLocales(l);
+            DecimalFormatData decimalFormatData = DecimalFormatData.getInstance(l);
+            return decimalFormatData.getZeroDigit();
+            // DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
+            //  return dfs.getZeroDigit();
         } else {
             return '0';
         }
@@ -3376,10 +3381,10 @@
 
                 // BEGIN Android-changed: Use localized exponent separator for %e.
                 Locale separatorLocale = (l != null) ? l : Locale.getDefault();
-                LocaleData localeData = LocaleData.get(separatorLocale);
+                DecimalFormatData formatData = DecimalFormatData.getInstance(separatorLocale);
                 sb.append(f.contains(Flags.UPPERCASE) ?
-                        localeData.exponentSeparator.toUpperCase(separatorLocale) :
-                        localeData.exponentSeparator.toLowerCase(separatorLocale));
+                        formatData.getExponentSeparator().toUpperCase(separatorLocale) :
+                        formatData.getExponentSeparator().toLowerCase(separatorLocale));
                 // END Android-changed: Use localized exponent separator for %e.
 
                 Flags flags = f.dup().remove(Flags.GROUP);
@@ -4405,8 +4410,13 @@
 
         private char getZero(Locale l) {
             if ((l != null) &&  !l.equals(locale())) {
-                DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
-                return dfs.getZeroDigit();
+                // Android-changed: Improve the performance by 10x http://b/197788756
+                // Unclear if this mapping is needed but inherited from DecimalFormatSymbols
+                l = LocaleData.mapInvalidAndNullLocales(l);
+                DecimalFormatData decimalFormatData = DecimalFormatData.getInstance(l);
+                return decimalFormatData.getZeroDigit();
+                //  DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
+                //  return dfs.getZeroDigit();
             }
             return zero;
         }
diff --git a/ojluni/src/main/java/java/util/FormatterClosedException.java b/ojluni/src/main/java/java/util/FormatterClosedException.java
index b0aa872..856dc97 100644
--- a/ojluni/src/main/java/java/util/FormatterClosedException.java
+++ b/ojluni/src/main/java/java/util/FormatterClosedException.java
@@ -28,7 +28,7 @@
 /**
  * Unchecked exception thrown when the formatter has been closed.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/GregorianCalendar.java b/ojluni/src/main/java/java/util/GregorianCalendar.java
index 46733e9..85fa642 100644
--- a/ojluni/src/main/java/java/util/GregorianCalendar.java
+++ b/ojluni/src/main/java/java/util/GregorianCalendar.java
@@ -92,7 +92,7 @@
  * adjustment may be made if desired for dates that are prior to the Gregorian
  * changeover and which fall between January 1 and March 24.
  *
- * <h3><a name="week_and_year">Week Of Year and Week Year</a></h3>
+ * <h3><a id="week_and_year">Week Of Year and Week Year</a></h3>
  *
  * <p>Values calculated for the {@link Calendar#WEEK_OF_YEAR
  * WEEK_OF_YEAR} field range from 1 to 53. The first week of a
@@ -109,7 +109,7 @@
  * <p>The {@code getFirstDayOfWeek()} and {@code
  * getMinimalDaysInFirstWeek()} values are initialized using
  * locale-dependent resources when constructing a {@code
- * GregorianCalendar}. <a name="iso8601_compatible_setting">The week
+ * GregorianCalendar}. <a id="iso8601_compatible_setting">The week
  * determination is compatible</a> with the ISO 8601 standard when {@code
  * getFirstDayOfWeek()} is {@code MONDAY} and {@code
  * getMinimalDaysInFirstWeek()} is 4, which values are used in locales
@@ -118,7 +118,7 @@
  * {@link Calendar#setMinimalDaysInFirstWeek(int)
  * setMinimalDaysInFirstWeek()}.
  *
- * <p>A <a name="week_year"><em>week year</em></a> is in sync with a
+ * <p>A <a id="week_year"><em>week year</em></a> is in sync with a
  * {@code WEEK_OF_YEAR} cycle. All weeks between the first and last
  * weeks (inclusive) have the same <em>week year</em> value.
  * Therefore, the first and last days of a week year may have
@@ -160,88 +160,89 @@
  * undefined. <code>GregorianCalendar</code> uses the following
  * default value for each calendar field if its value is undefined.
  *
- * <table cellpadding="0" cellspacing="3" border="0"
- *        summary="GregorianCalendar default field values"
- *        style="text-align: left; width: 66%;">
+ * <table class="striped" style="text-align: left; width: 66%;">
+ * <caption style="display:none">GregorianCalendar default field values</caption>
+ *   <thead>
+ *     <tr>
+ *       <th scope="col">
+ *          Field
+ *       </th>
+ *       <th scope="col">
+            Default Value
+ *       </th>
+ *     </tr>
+ *   </thead>
  *   <tbody>
  *     <tr>
- *       <th style="vertical-align: top; background-color: rgb(204, 204, 255);
- *           text-align: center;">Field<br>
+ *       <th scope="row">
+ *              <code>ERA</code>
  *       </th>
- *       <th style="vertical-align: top; background-color: rgb(204, 204, 255);
- *           text-align: center;">Default Value<br>
+ *       <td>
+ *              <code>AD</code>
+ *       </td>
+ *     </tr>
+ *     <tr>
+ *       <th scope="row">
+ *              <code>YEAR</code>
  *       </th>
- *     </tr>
- *     <tr>
- *       <td style="vertical-align: middle;">
- *              <code>ERA<br></code>
- *       </td>
- *       <td style="vertical-align: middle;">
- *              <code>AD<br></code>
+ *       <td>
+ *              <code>1970</code>
  *       </td>
  *     </tr>
  *     <tr>
- *       <td style="vertical-align: middle; background-color: rgb(238, 238, 255);">
- *              <code>YEAR<br></code>
- *       </td>
- *       <td style="vertical-align: middle; background-color: rgb(238, 238, 255);">
- *              <code>1970<br></code>
+ *       <th scope="row">
+ *              <code>MONTH</code>
+ *       </th>
+ *       <td>
+ *              <code>JANUARY</code>
  *       </td>
  *     </tr>
  *     <tr>
- *       <td style="vertical-align: middle;">
- *              <code>MONTH<br></code>
- *       </td>
- *       <td style="vertical-align: middle;">
- *              <code>JANUARY<br></code>
+ *       <th scope="row">
+ *              <code>DAY_OF_MONTH</code>
+ *       </th>
+ *       <td>
+ *              <code>1</code>
  *       </td>
  *     </tr>
  *     <tr>
- *       <td style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *              <code>DAY_OF_MONTH<br></code>
- *       </td>
- *       <td style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *              <code>1<br></code>
+ *       <th scope="row">
+ *              <code>DAY_OF_WEEK</code>
+ *       </th>
+ *       <td>
+ *              <code>the first day of week</code>
  *       </td>
  *     </tr>
  *     <tr>
- *       <td style="vertical-align: middle;">
- *              <code>DAY_OF_WEEK<br></code>
- *       </td>
- *       <td style="vertical-align: middle;">
- *              <code>the first day of week<br></code>
+ *       <th scope="row">
+ *              <code>WEEK_OF_MONTH</code>
+ *       </th>
+ *       <td>
+ *              <code>0</code>
  *       </td>
  *     </tr>
  *     <tr>
- *       <td style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *              <code>WEEK_OF_MONTH<br></code>
- *       </td>
- *       <td style="vertical-align: top; background-color: rgb(238, 238, 255);">
- *              <code>0<br></code>
+ *       <th scope="row">
+ *              <code>DAY_OF_WEEK_IN_MONTH</code>
+ *       </th>
+ *       <td>
+ *              <code>1</code>
  *       </td>
  *     </tr>
  *     <tr>
- *       <td style="vertical-align: top;">
- *              <code>DAY_OF_WEEK_IN_MONTH<br></code>
- *       </td>
- *       <td style="vertical-align: top;">
- *              <code>1<br></code>
+ *       <th scope="row">
+ *              <code>AM_PM</code>
+ *       </th>
+ *       <td>
+ *              <code>AM</code>
  *       </td>
  *     </tr>
  *     <tr>
- *       <td style="vertical-align: middle; background-color: rgb(238, 238, 255);">
- *              <code>AM_PM<br></code>
- *       </td>
- *       <td style="vertical-align: middle; background-color: rgb(238, 238, 255);">
- *              <code>AM<br></code>
- *       </td>
- *     </tr>
- *     <tr>
- *       <td style="vertical-align: middle;">
- *              <code>HOUR, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND<br></code>
- *       </td>
- *       <td style="vertical-align: middle;">
- *              <code>0<br></code>
+ *       <th scope="row">
+ *              <code>HOUR, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code>
+ *       </th>
+ *       <td>
+ *              <code>0</code>
  *       </td>
  *     </tr>
  *   </tbody>
@@ -326,7 +327,7 @@
  *
  * @see          TimeZone
  * @author David Goldsmith, Mark Davis, Chen-Lieh Huang, Alan Liu
- * @since JDK1.1
+ * @since 1.1
  */
 public class GregorianCalendar extends Calendar {
     /*
@@ -425,7 +426,7 @@
      * DAY_OF_MONTH            1         1          28*         31
      * DAY_OF_YEAR             1         1         365*        366
      * DAY_OF_WEEK             1         1           7           7
-     * DAY_OF_WEEK_IN_MONTH   -1        -1           4*          6
+     * DAY_OF_WEEK_IN_MONTH    1         1           4*          6
      * AM_PM                   0         0           1           1
      * HOUR                    0         0          11          11
      * HOUR_OF_DAY             0         0          23          23
@@ -731,7 +732,7 @@
      * Constructs an empty GregorianCalendar.
      *
      * @param zone    the given time zone
-     * @param locale the given locale
+     * @param aLocale the given locale
      * @param flag    the flag requesting an empty instance
      */
     GregorianCalendar(TimeZone zone, Locale locale, boolean flag) {
@@ -1198,37 +1199,33 @@
         case HOUR:
         case HOUR_OF_DAY:
             {
-                int unit = max + 1; // 12 or 24 hours
-                int h = internalGet(field);
-                int nh = (h + amount) % unit;
-                if (nh < 0) {
-                    nh += unit;
+                int rolledValue = getRolledValue(internalGet(field), amount, min, max);
+                int hourOfDay = rolledValue;
+                if (field == HOUR && internalGet(AM_PM) == PM) {
+                    hourOfDay += 12;
                 }
-                time += ONE_HOUR * (nh - h);
 
-                // The day might have changed, which could happen if
-                // the daylight saving time transition brings it to
-                // the next day, although it's very unlikely. But we
-                // have to make sure not to change the larger fields.
+                // Create the current date/time value to perform wall-clock-based
+                // roll.
                 CalendarDate d = calsys.getCalendarDate(time, getZone());
-                if (internalGet(DAY_OF_MONTH) != d.getDayOfMonth()) {
-                    d.setDate(internalGet(YEAR),
-                              internalGet(MONTH) + 1,
-                              internalGet(DAY_OF_MONTH));
-                    if (field == HOUR) {
-                        assert (internalGet(AM_PM) == PM);
-                        d.addHours(+12); // restore PM
+                d.setHours(hourOfDay);
+                time = calsys.getTime(d);
+
+                // If we stay on the same wall-clock time, try the next or previous hour.
+                if (internalGet(HOUR_OF_DAY) == d.getHours()) {
+                    hourOfDay = getRolledValue(rolledValue, amount > 0 ? +1 : -1, min, max);
+                    if (field == HOUR && internalGet(AM_PM) == PM) {
+                        hourOfDay += 12;
                     }
+                    d.setHours(hourOfDay);
                     time = calsys.getTime(d);
                 }
-                int hourOfDay = d.getHours();
-                internalSet(field, hourOfDay % unit);
-                if (field == HOUR) {
-                    internalSet(HOUR_OF_DAY, hourOfDay);
-                } else {
-                    internalSet(AM_PM, hourOfDay / 12);
-                    internalSet(HOUR, hourOfDay % 12);
-                }
+                // Get the new hourOfDay value which might have changed due to a DST transition.
+                hourOfDay = d.getHours();
+                // Update the hour related fields
+                internalSet(HOUR_OF_DAY, hourOfDay);
+                internalSet(AM_PM, hourOfDay / 12);
+                internalSet(HOUR, hourOfDay % 12);
 
                 // Time zone offset and/or daylight saving might have changed.
                 int zoneOffset = d.getZoneOffset();
@@ -2291,7 +2288,7 @@
      * Long.MIN_VALUE, the fixed date value is unknown. Currently,
      * Julian calendar dates are not cached.
      */
-    transient private long cachedFixedDate = Long.MIN_VALUE;
+    private transient long cachedFixedDate = Long.MIN_VALUE;
 
     /**
      * Converts the time value (millisecond offset from the <a
diff --git a/ojluni/src/main/java/java/util/HashMap.java b/ojluni/src/main/java/java/util/HashMap.java
index 360f736..2c01f6f 100644
--- a/ojluni/src/main/java/java/util/HashMap.java
+++ b/ojluni/src/main/java/java/util/HashMap.java
@@ -117,7 +117,7 @@
  * should be used only to detect bugs.</i>
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @param <K> the type of keys maintained by this map
diff --git a/ojluni/src/main/java/java/util/HashSet.java b/ojluni/src/main/java/java/util/HashSet.java
index 5805331..f9b09ee 100644
--- a/ojluni/src/main/java/java/util/HashSet.java
+++ b/ojluni/src/main/java/java/util/HashSet.java
@@ -72,7 +72,7 @@
  * should be used only to detect bugs.</i>
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @param <E> the type of elements maintained by this set
diff --git a/ojluni/src/main/java/java/util/Hashtable.java b/ojluni/src/main/java/java/util/Hashtable.java
index fc163a7..4c76a74 100644
--- a/ojluni/src/main/java/java/util/Hashtable.java
+++ b/ojluni/src/main/java/java/util/Hashtable.java
@@ -105,7 +105,7 @@
  *
  * <p>As of the Java 2 platform v1.2, this class was retrofitted to
  * implement the {@link Map} interface, making it a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  *
  * Java Collections Framework</a>.  Unlike the new collection
  * implementations, {@code Hashtable} is synchronized.  If a
diff --git a/ojluni/src/main/java/java/util/IdentityHashMap.java b/ojluni/src/main/java/java/util/IdentityHashMap.java
index 1ed9d76..9dc0c26 100644
--- a/ojluni/src/main/java/java/util/IdentityHashMap.java
+++ b/ojluni/src/main/java/java/util/IdentityHashMap.java
@@ -122,7 +122,7 @@
  * {@link HashMap} (which uses <i>chaining</i> rather than linear-probing).
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @see     System#identityHashCode(Object)
diff --git a/ojluni/src/main/java/java/util/IllegalFormatCodePointException.java b/ojluni/src/main/java/java/util/IllegalFormatCodePointException.java
index 02add44..d79d4997 100644
--- a/ojluni/src/main/java/java/util/IllegalFormatCodePointException.java
+++ b/ojluni/src/main/java/java/util/IllegalFormatCodePointException.java
@@ -30,7 +30,7 @@
  * point as defined by {@link Character#isValidCodePoint} is passed to the
  * {@link Formatter}.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/IllegalFormatConversionException.java b/ojluni/src/main/java/java/util/IllegalFormatConversionException.java
index a9b006f..09ee5c4 100644
--- a/ojluni/src/main/java/java/util/IllegalFormatConversionException.java
+++ b/ojluni/src/main/java/java/util/IllegalFormatConversionException.java
@@ -29,7 +29,7 @@
  * Unchecked exception thrown when the argument corresponding to the format
  * specifier is of an incompatible type.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/IllegalFormatFlagsException.java b/ojluni/src/main/java/java/util/IllegalFormatFlagsException.java
index 6b8223a..5374f59 100644
--- a/ojluni/src/main/java/java/util/IllegalFormatFlagsException.java
+++ b/ojluni/src/main/java/java/util/IllegalFormatFlagsException.java
@@ -28,7 +28,7 @@
 /**
  * Unchecked exception thrown when an illegal combination flags is given.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/IllegalFormatPrecisionException.java b/ojluni/src/main/java/java/util/IllegalFormatPrecisionException.java
index 41cbbb7..bc9c621 100644
--- a/ojluni/src/main/java/java/util/IllegalFormatPrecisionException.java
+++ b/ojluni/src/main/java/java/util/IllegalFormatPrecisionException.java
@@ -27,7 +27,7 @@
 
 /**
  * Unchecked exception thrown when the precision is a negative value other than
- * <tt>-1</tt>, the conversion does not support a precision, or the value is
+ * {@code -1}, the conversion does not support a precision, or the value is
  * otherwise unsupported.
  *
  * @since 1.5
diff --git a/ojluni/src/main/java/java/util/IllegalFormatWidthException.java b/ojluni/src/main/java/java/util/IllegalFormatWidthException.java
index 08ae47d..c7b7823 100644
--- a/ojluni/src/main/java/java/util/IllegalFormatWidthException.java
+++ b/ojluni/src/main/java/java/util/IllegalFormatWidthException.java
@@ -27,7 +27,7 @@
 
 /**
  * Unchecked exception thrown when the format width is a negative value other
- * than <tt>-1</tt> or is otherwise unsupported.
+ * than {@code -1} or is otherwise unsupported.
  *
  * @since 1.5
  */
diff --git a/ojluni/src/main/java/java/util/ImmutableCollections.java b/ojluni/src/main/java/java/util/ImmutableCollections.java
index e42538c..a756669 100644
--- a/ojluni/src/main/java/java/util/ImmutableCollections.java
+++ b/ojluni/src/main/java/java/util/ImmutableCollections.java
@@ -35,6 +35,8 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.VM;
 import jdk.internal.vm.annotation.Stable;
 
 /**
@@ -409,7 +411,16 @@
     static final class ListN<E> extends AbstractImmutableList<E>
             implements Serializable {
 
-        static final List<?> EMPTY_LIST = new ListN<>();
+        // EMPTY_LIST may be initialized from the CDS archive.
+        static @Stable List<?> EMPTY_LIST;
+
+        static {
+            // Android-removed: VM.initializeFromArchive() isn't supported on Android.
+            // VM.initializeFromArchive(ListN.class);
+            if (EMPTY_LIST == null) {
+                EMPTY_LIST = new ListN<>();
+            }
+        }
 
         @Stable
         private final E[] elements;
@@ -618,7 +629,20 @@
      * least one null is always present.
      * @param <E> the element type
      */
-    static final class SetN<E> extends AbstractImmutableSet<E> {
+    static final class SetN<E> extends AbstractImmutableSet<E>
+            implements Serializable {
+
+        // EMPTY_SET may be initialized from the CDS archive.
+        static @Stable Set<?> EMPTY_SET;
+
+        static {
+            // Android-removed: VM.initializeFromArchive isn't supported on Android.
+            // VM.initializeFromArchive(SetN.class);
+            if (EMPTY_SET == null) {
+                EMPTY_SET = new SetN<>();
+            }
+        }
+
         @Stable
         final E[] elements;
         @Stable
@@ -797,6 +821,11 @@
         }
 
         @Override
+        public V get(Object o) {
+            return o.equals(k0) ? v0 : null; // implicit nullcheck of o
+        }
+
+        @Override
         public boolean containsKey(Object o) {
             return o.equals(k0); // implicit nullcheck of o
         }
@@ -830,6 +859,18 @@
      * @param <V> the value type
      */
     static final class MapN<K,V> extends AbstractImmutableMap<K,V> {
+
+        // EMPTY_MAP may be initialized from the CDS archive.
+        static @Stable Map<?,?> EMPTY_MAP;
+
+        static {
+            // Android-removed: VM.initializeFromArchive() isn't supported on Android.
+            // VM.initializeFromArchive(MapN.class);
+            if (EMPTY_MAP == null) {
+                EMPTY_MAP = new MapN<>();
+            }
+        }
+
         @Stable
         final Object[] table; // pairs of key, value
         @Stable
diff --git a/ojluni/src/main/java/java/util/InputMismatchException.java b/ojluni/src/main/java/java/util/InputMismatchException.java
index e4d1ce3..c101c65 100644
--- a/ojluni/src/main/java/java/util/InputMismatchException.java
+++ b/ojluni/src/main/java/java/util/InputMismatchException.java
@@ -26,7 +26,7 @@
 package java.util;
 
 /**
- * Thrown by a <code>Scanner</code> to indicate that the token
+ * Thrown by a {@code Scanner} to indicate that the token
  * retrieved does not match the pattern for the expected type, or
  * that the token is out of range for the expected type.
  *
@@ -39,7 +39,7 @@
     private static final long serialVersionUID = 8811230760997066428L;
 
     /**
-     * Constructs an <code>InputMismatchException</code> with <tt>null</tt>
+     * Constructs an {@code InputMismatchException} with {@code null}
      * as its error message string.
      */
     public InputMismatchException() {
@@ -47,9 +47,9 @@
     }
 
     /**
-     * Constructs an <code>InputMismatchException</code>, saving a reference
-     * to the error message string <tt>s</tt> for later retrieval by the
-     * <tt>getMessage</tt> method.
+     * Constructs an {@code InputMismatchException}, saving a reference
+     * to the error message string {@code s} for later retrieval by the
+     * {@code getMessage} method.
      *
      * @param   s   the detail message.
      */
diff --git a/ojluni/src/main/java/java/util/IntSummaryStatistics.java b/ojluni/src/main/java/java/util/IntSummaryStatistics.java
index f93436e..9043c8a 100644
--- a/ojluni/src/main/java/java/util/IntSummaryStatistics.java
+++ b/ojluni/src/main/java/java/util/IntSummaryStatistics.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
  *
  * @implNote This implementation is not thread safe. However, it is safe to use
  * {@link java.util.stream.Collectors#summarizingInt(java.util.function.ToIntFunction)
- * Collectors.toIntStatistics()} on a parallel stream, because the parallel
+ * Collectors.summarizingInt()} on a parallel stream, because the parallel
  * implementation of {@link java.util.stream.Stream#collect Stream.collect()}
  * provides the necessary partitioning, isolation, and merging of results for
  * safe and efficient parallel execution.
@@ -69,13 +69,58 @@
     private int max = Integer.MIN_VALUE;
 
     /**
-     * Construct an empty instance with zero count, zero sum,
+     * Constructs an empty instance with zero count, zero sum,
      * {@code Integer.MAX_VALUE} min, {@code Integer.MIN_VALUE} max and zero
      * average.
      */
     public IntSummaryStatistics() { }
 
     /**
+     * Constructs a non-empty instance with the specified {@code count},
+     * {@code min}, {@code max}, and {@code sum}.
+     *
+     * <p>If {@code count} is zero then the remaining arguments are ignored and
+     * an empty instance is constructed.
+     *
+     * <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
+     * is thrown.  The necessary consistent argument conditions are:
+     * <ul>
+     *   <li>{@code count >= 0}</li>
+     *   <li>{@code min <= max}</li>
+     * </ul>
+     * @apiNote
+     * The enforcement of argument correctness means that the retrieved set of
+     * recorded values obtained from a {@code IntSummaryStatistics} source
+     * instance may not be a legal set of arguments for this constructor due to
+     * arithmetic overflow of the source's recorded count of values.
+     * The consistent argument conditions are not sufficient to prevent the
+     * creation of an internally inconsistent instance.  An example of such a
+     * state would be an instance with: {@code count} = 2, {@code min} = 1,
+     * {@code max} = 2, and {@code sum} = 0.
+     *
+     * @param count the count of values
+     * @param min the minimum value
+     * @param max the maximum value
+     * @param sum the sum of all values
+     * @throws IllegalArgumentException if the arguments are inconsistent
+     * @since 10
+     */
+    public IntSummaryStatistics(long count, int min, int max, long sum)
+            throws IllegalArgumentException {
+        if (count < 0L) {
+            throw new IllegalArgumentException("Negative count value");
+        } else if (count > 0L) {
+            if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
+
+            this.count = count;
+            this.sum = sum;
+            this.min = min;
+            this.max = max;
+        }
+        // Use default field values if count == 0
+    }
+
+    /**
      * Records a new value into the summary information
      *
      * @param value the input value
@@ -150,14 +195,12 @@
         return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
     }
 
-    @Override
     /**
-     * {@inheritDoc}
-     *
      * Returns a non-empty string representation of this object suitable for
      * debugging. The exact presentation format is unspecified and may vary
      * between implementations and versions.
      */
+    @Override
     public String toString() {
         return String.format(
             "%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
diff --git a/ojluni/src/main/java/java/util/Iterator.java b/ojluni/src/main/java/java/util/Iterator.java
index 02777b6..aaf6a04 100644
--- a/ojluni/src/main/java/java/util/Iterator.java
+++ b/ojluni/src/main/java/java/util/Iterator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,9 +40,13 @@
  * </ul>
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
+ * @apiNote
+ * An {@link Enumeration} can be converted into an {@code Iterator} by
+ * using the {@link Enumeration#asIterator} method.
+ *
  * @param <E> the type of elements returned by this iterator
  *
  * @author  Josh Bloch
@@ -72,10 +76,15 @@
     /**
      * Removes from the underlying collection the last element returned
      * by this iterator (optional operation).  This method can be called
-     * only once per call to {@link #next}.  The behavior of an iterator
-     * is unspecified if the underlying collection is modified while the
-     * iteration is in progress in any way other than by calling this
-     * method.
+     * only once per call to {@link #next}.
+     * <p>
+     * The behavior of an iterator is unspecified if the underlying collection
+     * is modified while the iteration is in progress in any way other than by
+     * calling this method, unless an overriding class has specified a
+     * concurrent modification policy.
+     * <p>
+     * The behavior of an iterator is unspecified if this method is called
+     * after a call to the {@link #forEachRemaining forEachRemaining} method.
      *
      * @implSpec
      * The default implementation throws an instance of
@@ -98,6 +107,14 @@
      * have been processed or the action throws an exception.  Actions are
      * performed in the order of iteration, if that order is specified.
      * Exceptions thrown by the action are relayed to the caller.
+     * <p>
+     * The behavior of an iterator is unspecified if the action modifies the
+     * collection in any way (even by calling the {@link #remove remove} method
+     * or other mutator methods of {@code Iterator} subtypes),
+     * unless an overriding class has specified a concurrent modification policy.
+     * <p>
+     * Subsequent behavior of an iterator is unspecified if the action throws an
+     * exception.
      *
      * @implSpec
      * <p>The default implementation behaves as if:
diff --git a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
index f0512c5..a652b1f 100644
--- a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
+++ b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
@@ -37,25 +37,25 @@
 import sun.util.calendar.LocalGregorianCalendar;
 
 /**
- * <code>JapaneseImperialCalendar</code> implements a Japanese
+ * {@code JapaneseImperialCalendar} implements a Japanese
  * calendar system in which the imperial era-based year numbering is
  * supported from the Meiji era. The following are the eras supported
  * by this calendar system.
- * <pre><tt>
+ * <pre>{@code
  * ERA value   Era name    Since (in Gregorian)
  * ------------------------------------------------------
  *     0       N/A         N/A
- *     1       Meiji       1868-01-01 midnight local time
- *     2       Taisho      1912-07-30 midnight local time
- *     3       Showa       1926-12-25 midnight local time
- *     4       Heisei      1989-01-08 midnight local time
- *     5       Reiwa       2019-05-01 midnight local time
+ *     1       Meiji       1868-01-01T00:00:00 local time
+ *     2       Taisho      1912-07-30T00:00:00 local time
+ *     3       Showa       1926-12-25T00:00:00 local time
+ *     4       Heisei      1989-01-08T00:00:00 local time
+ *     5       Reiwa       2019-05-01T00:00:00 local time
  * ------------------------------------------------------
- * </tt></pre>
+ * }</pre>
  *
- * <p><code>ERA</code> value 0 specifies the years before Meiji and
- * the Gregorian year values are used. Unlike {@link
- * GregorianCalendar}, the Julian to Gregorian transition is not
+ * <p>{@code ERA} value 0 specifies the years before Meiji and
+ * the Gregorian year values are used. Unlike
+ * {@link GregorianCalendar}, the Julian to Gregorian transition is not
  * supported because it doesn't make any sense to the Japanese
  * calendar systems used before Meiji. To represent the years before
  * Gregorian year 1, 0 and negative values are used. The Japanese
@@ -72,8 +72,7 @@
      *
      * This implementation uses
      * sun.util.calendar.LocalGregorianCalendar to perform most of the
-     * calendar calculations. LocalGregorianCalendar is configurable
-     * and reads <JRE_HOME>/lib/calendars.properties at the start-up.
+     * calendar calculations.
      */
 
     /**
@@ -101,14 +100,13 @@
      */
     public static final int HEISEI = 4;
 
-    // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa.
+    // Android-changed: Call the New Era it's proper name Reiwa.
     /**
      * The ERA constant designating the Reiwa era.
      */
     public static final int REIWA = 5;
 
     private static final int EPOCH_OFFSET   = 719163; // Fixed date of January 1, 1970 (Gregorian)
-    private static final int EPOCH_YEAR     = 1970;
 
     // Useful millisecond constants.  Although ONE_DAY and ONE_WEEK can fit
     // into ints, they must be longs in order to prevent arithmetic overflow
@@ -117,7 +115,6 @@
     private static final int  ONE_MINUTE = 60*ONE_SECOND;
     private static final int  ONE_HOUR   = 60*ONE_MINUTE;
     private static final long ONE_DAY    = 24*ONE_HOUR;
-    private static final long ONE_WEEK   = 7*ONE_DAY;
 
     // Reference to the sun.util.calendar.LocalGregorianCalendar instance (singleton).
     private static final LocalGregorianCalendar jcal
@@ -226,6 +223,7 @@
     };
 
     // Proclaim serialization compatibility with JDK 1.6
+    @SuppressWarnings("FieldNameHidesFieldInSuperclass")
     private static final long serialVersionUID = -3364572813905467929L;
 
     static {
@@ -313,7 +311,7 @@
     private transient int[] originalFields;
 
     /**
-     * Constructs a <code>JapaneseImperialCalendar</code> based on the current time
+     * Constructs a {@code JapaneseImperialCalendar} based on the current time
      * in the given time zone with the given locale.
      *
      * @param zone the given time zone.
@@ -349,18 +347,19 @@
     }
 
     /**
-     * Compares this <code>JapaneseImperialCalendar</code> to the specified
-     * <code>Object</code>. The result is <code>true</code> if and
-     * only if the argument is a <code>JapaneseImperialCalendar</code> object
+     * Compares this {@code JapaneseImperialCalendar} to the specified
+     * {@code Object}. The result is {@code true} if and
+     * only if the argument is a {@code JapaneseImperialCalendar} object
      * that represents the same time value (millisecond offset from
      * the <a href="Calendar.html#Epoch">Epoch</a>) under the same
-     * <code>Calendar</code> parameters.
+     * {@code Calendar} parameters.
      *
      * @param obj the object to compare with.
-     * @return <code>true</code> if this object is equal to <code>obj</code>;
-     * <code>false</code> otherwise.
+     * @return {@code true} if this object is equal to {@code obj};
+     * {@code false} otherwise.
      * @see Calendar#compareTo(Calendar)
      */
+    @Override
     public boolean equals(Object obj) {
         return obj instanceof JapaneseImperialCalendar &&
             super.equals(obj);
@@ -368,8 +367,9 @@
 
     /**
      * Generates the hash code for this
-     * <code>JapaneseImperialCalendar</code> object.
+     * {@code JapaneseImperialCalendar} object.
      */
+    @Override
     public int hashCode() {
         return super.hashCode() ^ jdate.hashCode();
     }
@@ -378,30 +378,31 @@
      * Adds the specified (signed) amount of time to the given calendar field,
      * based on the calendar's rules.
      *
-     * <p><em>Add rule 1</em>. The value of <code>field</code>
-     * after the call minus the value of <code>field</code> before the
-     * call is <code>amount</code>, modulo any overflow that has occurred in
-     * <code>field</code>. Overflow occurs when a field value exceeds its
+     * <p><em>Add rule 1</em>. The value of {@code field}
+     * after the call minus the value of {@code field} before the
+     * call is {@code amount}, modulo any overflow that has occurred in
+     * {@code field}. Overflow occurs when a field value exceeds its
      * range and, as a result, the next larger field is incremented or
      * decremented and the field value is adjusted back into its range.</p>
      *
      * <p><em>Add rule 2</em>. If a smaller field is expected to be
      * invariant, but it is impossible for it to be equal to its
      * prior value because of changes in its minimum or maximum after
-     * <code>field</code> is changed, then its value is adjusted to be as close
+     * {@code field} is changed, then its value is adjusted to be as close
      * as possible to its expected value. A smaller field represents a
-     * smaller unit of time. <code>HOUR</code> is a smaller field than
-     * <code>DAY_OF_MONTH</code>. No adjustment is made to smaller fields
+     * smaller unit of time. {@code HOUR} is a smaller field than
+     * {@code DAY_OF_MONTH}. No adjustment is made to smaller fields
      * that are not expected to be invariant. The calendar system
      * determines what fields are expected to be invariant.</p>
      *
      * @param field the calendar field.
      * @param amount the amount of date or time to be added to the field.
-     * @exception IllegalArgumentException if <code>field</code> is
-     * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
+     * @exception IllegalArgumentException if {@code field} is
+     * {@code ZONE_OFFSET}, {@code DST_OFFSET}, or unknown,
      * or if any calendar fields have out-of-range values in
      * non-lenient mode.
      */
+    @Override
     public void add(int field, int amount) {
         // If amount == 0, do nothing even the given field is out of
         // range. This is tested by JCK.
@@ -530,6 +531,7 @@
         }
     }
 
+    @Override
     public void roll(int field, boolean up) {
         roll(field, up ? +1 : -1);
     }
@@ -542,18 +544,19 @@
      * <p>This method calls {@link #complete()} before adding the
      * amount so that all the calendar fields are normalized. If there
      * is any calendar field having an out-of-range value in non-lenient mode, then an
-     * <code>IllegalArgumentException</code> is thrown.
+     * {@code IllegalArgumentException} is thrown.
      *
      * @param field the calendar field.
-     * @param amount the signed amount to add to <code>field</code>.
-     * @exception IllegalArgumentException if <code>field</code> is
-     * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or unknown,
+     * @param amount the signed amount to add to {@code field}.
+     * @exception IllegalArgumentException if {@code field} is
+     * {@code ZONE_OFFSET}, {@code DST_OFFSET}, or unknown,
      * or if any calendar fields have out-of-range values in
      * non-lenient mode.
      * @see #roll(int,boolean)
      * @see #add(int,int)
      * @see #set(int,int)
      */
+    @Override
     public void roll(int field, int amount) {
         // If amount == 0, do nothing even the given field is out of
         // range. This is tested by JCK.
@@ -999,9 +1002,11 @@
 
         String name = CalendarDataUtility.retrieveFieldValueName(getCalendarType(), field,
                                                                  fieldValue, style, locale);
-        // If the ERA value is null, then
+        // If the ERA value is null or empty, then
         // try to get its name or abbreviation from the Era instance.
-        if (name == null && field == ERA && fieldValue < eras.length) {
+        if ((name == null || name.isEmpty()) &&
+                field == ERA &&
+                fieldValue < eras.length) {
             Era era = eras[fieldValue];
             name = (style == SHORT) ? era.getAbbreviation() : era.getName();
         }
@@ -1030,14 +1035,16 @@
                 }
                 if (size < eras.length) {
                     int baseStyle = getBaseStyle(style);
-                    for (int i = size; i < eras.length; i++) {
-                        Era era = eras[i];
-                        if (baseStyle == ALL_STYLES || baseStyle == SHORT
-                                || baseStyle == NARROW_FORMAT) {
-                            names.put(era.getAbbreviation(), i);
-                        }
-                        if (baseStyle == ALL_STYLES || baseStyle == LONG) {
-                            names.put(era.getName(), i);
+                    for (int i = 0; i < eras.length; i++) {
+                        if (!names.values().contains(i)) {
+                            Era era = eras[i];
+                            if (baseStyle == ALL_STYLES || baseStyle == SHORT
+                                    || baseStyle == NARROW_FORMAT) {
+                                names.put(era.getAbbreviation(), i);
+                            }
+                            if (baseStyle == ALL_STYLES || baseStyle == LONG) {
+                                names.put(era.getName(), i);
+                            }
                         }
                     }
                 }
@@ -1048,9 +1055,9 @@
 
     /**
      * Returns the minimum value for the given calendar field of this
-     * <code>Calendar</code> instance. The minimum value is
-     * defined as the smallest value returned by the {@link
-     * Calendar#get(int) get} method for any possible time value,
+     * {@code Calendar} instance. The minimum value is
+     * defined as the smallest value returned by the
+     * {@link Calendar#get(int) get} method for any possible time value,
      * taking into consideration the current values of the
      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
@@ -1070,9 +1077,9 @@
 
     /**
      * Returns the maximum value for the given calendar field of this
-     * <code>GregorianCalendar</code> instance. The maximum value is
-     * defined as the largest value returned by the {@link
-     * Calendar#get(int) get} method for any possible time value,
+     * {@code GregorianCalendar} instance. The maximum value is
+     * defined as the largest value returned by the
+     * {@link Calendar#get(int) get} method for any possible time value,
      * taking into consideration the current values of the
      * {@link Calendar#getFirstDayOfWeek() getFirstDayOfWeek},
      * {@link Calendar#getMinimalDaysInFirstWeek() getMinimalDaysInFirstWeek},
@@ -1101,7 +1108,7 @@
 
     /**
      * Returns the highest minimum value for the given calendar field
-     * of this <code>GregorianCalendar</code> instance. The highest
+     * of this {@code GregorianCalendar} instance. The highest
      * minimum value is defined as the largest value returned by
      * {@link #getActualMinimum(int)} for any possible time value,
      * taking into consideration the current values of the
@@ -1123,7 +1130,7 @@
 
     /**
      * Returns the lowest maximum value for the given calendar field
-     * of this <code>GregorianCalendar</code> instance. The lowest
+     * of this {@code GregorianCalendar} instance. The lowest
      * maximum value is defined as the smallest value returned by
      * {@link #getActualMaximum(int)} for any possible time value,
      * taking into consideration the current values of the
@@ -1159,7 +1166,7 @@
      *
      * @param field the calendar field
      * @return the minimum of the given field for the time value of
-     * this <code>JapaneseImperialCalendar</code>
+     * this {@code JapaneseImperialCalendar}
      * @see #getMinimum(int)
      * @see #getMaximum(int)
      * @see #getGreatestMinimum(int)
@@ -1262,13 +1269,13 @@
      * and
      * {@link Calendar#getTimeZone() getTimeZone} methods.
      * For example, if the date of this instance is Heisei 16February 1,
-     * the actual maximum value of the <code>DAY_OF_MONTH</code> field
+     * the actual maximum value of the {@code DAY_OF_MONTH} field
      * is 29 because Heisei 16 is a leap year, and if the date of this
      * instance is Heisei 17 February 1, it's 28.
      *
      * @param field the calendar field
      * @return the maximum of the given field for the time value of
-     * this <code>JapaneseImperialCalendar</code>
+     * this {@code JapaneseImperialCalendar}
      * @see #getMinimum(int)
      * @see #getMaximum(int)
      * @see #getGreatestMinimum(int)
@@ -1544,14 +1551,14 @@
      * The fixed date corresponding to jdate. If the value is
      * Long.MIN_VALUE, the fixed date value is unknown.
      */
-    transient private long cachedFixedDate = Long.MIN_VALUE;
+    private transient long cachedFixedDate = Long.MIN_VALUE;
 
     /**
      * Converts the time value (millisecond offset from the <a
      * href="Calendar.html#Epoch">Epoch</a>) to calendar field values.
      * The time is <em>not</em>
      * recomputed first; to recompute the time, then the fields, call the
-     * <code>complete</code> method.
+     * {@code complete} method.
      *
      * @see Calendar#complete
      */
diff --git a/ojluni/src/main/java/java/util/JumboEnumSet.java b/ojluni/src/main/java/java/util/JumboEnumSet.java
index 6798511..20e8222 100644
--- a/ojluni/src/main/java/java/util/JumboEnumSet.java
+++ b/ojluni/src/main/java/java/util/JumboEnumSet.java
@@ -163,19 +163,19 @@
     }
 
     /**
-     * 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 size == 0;
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains the specified element.
+     * Returns {@code true} if this set contains the specified element.
      *
      * @param e element to be checked for containment in this collection
-     * @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 e) {
         if (e == null)
@@ -194,9 +194,9 @@
      * Adds the specified element to this set if it is not already present.
      *
      * @param e element to be added to this set
-     * @return <tt>true</tt> if the set changed as a result of the call
+     * @return {@code true} if the set changed as a result of the call
      *
-     * @throws NullPointerException if <tt>e</tt> is null
+     * @throws NullPointerException if {@code e} is null
      */
     public boolean add(E e) {
         typeCheck(e);
@@ -216,7 +216,7 @@
      * Removes the specified element from this set if it is present.
      *
      * @param e element to be removed from this set, if present
-     * @return <tt>true</tt> if the set contained the specified element
+     * @return {@code true} if the set contained the specified element
      */
     public boolean remove(Object e) {
         if (e == null)
@@ -238,11 +238,11 @@
     // Bulk Operations
 
     /**
-     * Returns <tt>true</tt> if this set contains all of the elements
+     * Returns {@code true} if this set contains all of the elements
      * in the specified collection.
      *
      * @param c collection to be checked for containment in this set
-     * @return <tt>true</tt> if this set contains all of the elements
+     * @return {@code true} if this set contains all of the elements
      *        in the specified collection
      * @throws NullPointerException if the specified collection is null
      */
@@ -264,7 +264,7 @@
      * Adds all of the elements in the specified collection to this set.
      *
      * @param c collection whose elements are 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 or any of
      *     its elements are null
      */
@@ -291,7 +291,7 @@
      * the specified collection.
      *
      * @param c 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 NullPointerException if the specified collection is null
      */
     public boolean removeAll(Collection<?> c) {
@@ -312,7 +312,7 @@
      * specified collection.
      *
      * @param c 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 NullPointerException if the specified collection is null
      */
     public boolean retainAll(Collection<?> c) {
@@ -341,12 +341,12 @@
 
     /**
      * Compares the specified object with this set for equality.  Returns
-     * <tt>true</tt> if the given object is also a set, the two sets have
+     * {@code true} if the given object is also a set, the two sets have
      * the same size, and every member of the given set is contained in
      * this set.
      *
      * @param o 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) {
         if (!(o instanceof JumboEnumSet))
diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java
index cd501a5..376f40f 100644
--- a/ojluni/src/main/java/java/util/LinkedHashMap.java
+++ b/ojluni/src/main/java/java/util/LinkedHashMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,15 +32,15 @@
 
 // Android-added: Note about spliterator order b/33945212 in Android N
 /**
- * <p>Hash table and linked list implementation of the <tt>Map</tt> interface,
+ * <p>Hash table and linked list implementation of the {@code Map} interface,
  * with predictable iteration order.  This implementation differs from
- * <tt>HashMap</tt> in that it maintains a doubly-linked list running through
+ * {@code HashMap} in that it maintains a doubly-linked list running through
  * all of its entries.  This linked list defines the iteration ordering,
  * which is normally the order in which keys were inserted into the map
  * (<i>insertion-order</i>).  Note that insertion order is not affected
- * if a key is <i>re-inserted</i> into the map.  (A key <tt>k</tt> is
- * reinserted into a map <tt>m</tt> if <tt>m.put(k, v)</tt> is invoked when
- * <tt>m.containsKey(k)</tt> would return <tt>true</tt> immediately prior to
+ * if a key is <i>re-inserted</i> into the map.  (A key {@code k} is
+ * reinserted into a map {@code m} if {@code m.put(k, v)} is invoked when
+ * {@code m.containsKey(k)} would return {@code true} immediately prior to
  * the invocation.)
  *
  * <p>This implementation spares its clients from the unspecified, generally
@@ -79,23 +79,23 @@
  * impose a policy for removing stale mappings automatically when new mappings
  * are added to the map.
  *
- * <p>This class provides all of the optional <tt>Map</tt> operations, and
- * permits null elements.  Like <tt>HashMap</tt>, it provides constant-time
- * performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
- * <tt>remove</tt>), assuming the hash function disperses elements
+ * <p>This class provides all of the optional {@code Map} operations, and
+ * permits null elements.  Like {@code HashMap}, it provides constant-time
+ * performance for the basic operations ({@code add}, {@code contains} and
+ * {@code remove}), assuming the hash function disperses elements
  * properly among the buckets.  Performance is likely to be just slightly
- * below that of <tt>HashMap</tt>, due to the added expense of maintaining the
+ * below that of {@code HashMap}, due to the added expense of maintaining the
  * linked list, with one exception: Iteration over the collection-views
- * of a <tt>LinkedHashMap</tt> requires time proportional to the <i>size</i>
- * of the map, regardless of its capacity.  Iteration over a <tt>HashMap</tt>
+ * of a {@code LinkedHashMap} requires time proportional to the <i>size</i>
+ * of the map, regardless of its capacity.  Iteration over a {@code HashMap}
  * is likely to be more expensive, requiring time proportional to its
  * <i>capacity</i>.
  *
  * <p>A linked hash map has two parameters that affect its performance:
  * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
- * as for <tt>HashMap</tt>.  Note, however, that the penalty for choosing an
+ * as for {@code HashMap}.  Note, however, that the penalty for choosing an
  * excessively high value for initial capacity is less severe for this class
- * than for <tt>HashMap</tt>, as iteration times for this class are unaffected
+ * than for {@code HashMap}, as iteration times for this class are unaffected
  * by capacity.
  *
  * <p><strong>Note that this implementation is not synchronized.</strong>
@@ -115,14 +115,14 @@
  * iteration order.  In insertion-ordered linked hash maps, merely changing
  * the value associated with a key that is already contained in the map is not
  * a structural modification.  <strong>In access-ordered linked hash maps,
- * merely querying the map with <tt>get</tt> is a structural modification.
+ * merely querying the map with {@code get} is a structural modification.
  * </strong>)
  *
- * <p>The iterators returned by the <tt>iterator</tt> method of the collections
+ * <p>The iterators returned by the {@code iterator} method of the collections
  * returned by all of this class's collection view methods are
  * <em>fail-fast</em>: if the map is structurally modified at any time after
  * the iterator is created, in any way except through the iterator's own
- * <tt>remove</tt> method, the iterator will throw a {@link
+ * {@code remove} method, the iterator will throw a {@link
  * ConcurrentModificationException}.  Thus, in the face of concurrent
  * modification, the iterator fails quickly and cleanly, rather than risking
  * arbitrary, non-deterministic behavior at an undetermined time in the future.
@@ -130,7 +130,7 @@
  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  * as it is, generally speaking, impossible to make any hard guarantees in the
  * presence of unsynchronized concurrent modification.  Fail-fast iterators
- * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * throw {@code ConcurrentModificationException} on a best-effort basis.
  * Therefore, it would be wrong to write a program that depended on this
  * exception for its correctness:   <i>the fail-fast behavior of iterators
  * should be used only to detect bugs.</i>
@@ -158,7 +158,7 @@
  * {@code LinkedHashMap}.
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @implNote
@@ -233,8 +233,8 @@
     transient LinkedHashMapEntry<K,V> tail;
 
     /**
-     * The iteration ordering method for this linked hash map: <tt>true</tt>
-     * for access-order, <tt>false</tt> for insertion-order.
+     * The iteration ordering method for this linked hash map: {@code true}
+     * for access-order, {@code false} for insertion-order.
      *
      * @serial
      */
@@ -278,7 +278,7 @@
 
     Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
         LinkedHashMapEntry<K,V> p =
-            new LinkedHashMapEntry<K,V>(hash, key, value, e);
+            new LinkedHashMapEntry<>(hash, key, value, e);
         linkNodeLast(p);
         return p;
     }
@@ -286,20 +286,20 @@
     Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
         LinkedHashMapEntry<K,V> q = (LinkedHashMapEntry<K,V>)p;
         LinkedHashMapEntry<K,V> t =
-            new LinkedHashMapEntry<K,V>(q.hash, q.key, q.value, next);
+            new LinkedHashMapEntry<>(q.hash, q.key, q.value, next);
         transferLinks(q, t);
         return t;
     }
 
     TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
-        TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next);
+        TreeNode<K,V> p = new TreeNode<>(hash, key, value, next);
         linkNodeLast(p);
         return p;
     }
 
     TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
         LinkedHashMapEntry<K,V> q = (LinkedHashMapEntry<K,V>)p;
-        TreeNode<K,V> t = new TreeNode<K,V>(q.hash, q.key, q.value, next);
+        TreeNode<K,V> t = new TreeNode<>(q.hash, q.key, q.value, next);
         transferLinks(q, t);
         return t;
     }
@@ -359,7 +359,7 @@
     }
 
     /**
-     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
+     * Constructs an empty insertion-ordered {@code LinkedHashMap} instance
      * with the specified initial capacity and load factor.
      *
      * @param  initialCapacity the initial capacity
@@ -373,7 +373,7 @@
     }
 
     /**
-     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
+     * Constructs an empty insertion-ordered {@code LinkedHashMap} instance
      * with the specified initial capacity and a default load factor (0.75).
      *
      * @param  initialCapacity the initial capacity
@@ -385,7 +385,7 @@
     }
 
     /**
-     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
+     * Constructs an empty insertion-ordered {@code LinkedHashMap} instance
      * with the default initial capacity (16) and load factor (0.75).
      */
     public LinkedHashMap() {
@@ -394,8 +394,8 @@
     }
 
     /**
-     * Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
-     * the same mappings as the specified map.  The <tt>LinkedHashMap</tt>
+     * Constructs an insertion-ordered {@code LinkedHashMap} instance with
+     * the same mappings as the specified map.  The {@code LinkedHashMap}
      * instance is created with a default load factor (0.75) and an initial
      * capacity sufficient to hold the mappings in the specified map.
      *
@@ -409,13 +409,13 @@
     }
 
     /**
-     * Constructs an empty <tt>LinkedHashMap</tt> instance with the
+     * Constructs an empty {@code LinkedHashMap} instance with the
      * specified initial capacity, load factor and ordering mode.
      *
      * @param  initialCapacity the initial capacity
      * @param  loadFactor      the load factor
-     * @param  accessOrder     the ordering mode - <tt>true</tt> for
-     *         access-order, <tt>false</tt> for insertion-order
+     * @param  accessOrder     the ordering mode - {@code true} for
+     *         access-order, {@code false} for insertion-order
      * @throws IllegalArgumentException if the initial capacity is negative
      *         or the load factor is nonpositive
      */
@@ -428,11 +428,11 @@
 
 
     /**
-     * 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.
      *
      * @param value value whose presence in this map is to be tested
-     * @return <tt>true</tt> if this map maps one or more keys to the
+     * @return {@code true} if this map maps one or more keys to the
      *         specified value
      */
     public boolean containsValue(Object value) {
@@ -501,8 +501,8 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map should remove its eldest entry.
-     * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
+     * Returns {@code true} if this map should remove its eldest entry.
+     * This method is invoked by {@code put} and {@code putAll} after
      * inserting a new entry into the map.  It provides the implementor
      * with the opportunity to remove the eldest entry each time a new one
      * is added.  This is useful if the map represents a cache: it allows
@@ -523,23 +523,23 @@
      * instead allowing the map to modify itself as directed by its
      * return value.  It <i>is</i> permitted for this method to modify
      * the map directly, but if it does so, it <i>must</i> return
-     * <tt>false</tt> (indicating that the map should not attempt any
-     * further modification).  The effects of returning <tt>true</tt>
+     * {@code false} (indicating that the map should not attempt any
+     * further modification).  The effects of returning {@code true}
      * after modifying the map from within this method are unspecified.
      *
-     * <p>This implementation merely returns <tt>false</tt> (so that this
+     * <p>This implementation merely returns {@code false} (so that this
      * map acts like a normal map - the eldest element is never removed).
      *
      * @param    eldest The least recently inserted entry in the map, or if
      *           this is an access-ordered map, the least recently accessed
      *           entry.  This is the entry that will be removed it this
-     *           method returns <tt>true</tt>.  If the map was empty prior
-     *           to the <tt>put</tt> or <tt>putAll</tt> invocation resulting
+     *           method returns {@code true}.  If the map was empty prior
+     *           to the {@code put} or {@code putAll} invocation resulting
      *           in this invocation, this will be the entry that was just
      *           inserted; in other words, if the map contains a single
      *           entry, the eldest entry is also the newest.
-     * @return   <tt>true</tt> if the eldest entry should be removed
-     *           from the map; <tt>false</tt> if it should be retained.
+     * @return   {@code true} if the eldest entry should be removed
+     *           from the map; {@code false} if it should be retained.
      */
     protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
         return false;
@@ -550,12 +550,12 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  If the map is modified
      * while an iteration over the set is in progress (except through
-     * the iterator's own <tt>remove</tt> operation), the results of
+     * the iterator's own {@code remove} operation), the results of
      * the iteration are undefined.  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>
+     * {@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.
      * Its {@link Spliterator} typically provides faster sequential
      * performance but much poorer parallel performance than that of
@@ -604,13 +604,13 @@
      * The collection is backed by the map, so changes to the map are
      * reflected in the collection, and vice-versa.  If the map is
      * modified while an iteration over the collection is in progress
-     * (except through the iterator's own <tt>remove</tt> operation),
+     * (except through the iterator's own {@code remove} operation),
      * the results of the iteration are undefined.  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.
      * Its {@link Spliterator} typically provides faster sequential
      * performance but much poorer parallel performance than that of
      * {@code HashMap}.
@@ -654,14 +654,14 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  If the map is modified
      * while an iteration over the set is in progress (except through
-     * the iterator's own <tt>remove</tt> operation, or through the
-     * <tt>setValue</tt> operation on a map entry returned by the
+     * the iterator's own {@code remove} operation, or through the
+     * {@code setValue} operation on a map entry returned by the
      * iterator) the results of the iteration are undefined.  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.
+     * mapping from the map, 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.
      * Its {@link Spliterator} typically provides faster sequential
      * performance but much poorer parallel performance than that of
      * {@code HashMap}.
@@ -772,8 +772,7 @@
             if (modCount != expectedModCount)
                 throw new ConcurrentModificationException();
             current = null;
-            K key = p.key;
-            removeNode(hash(key), key, null, false, false);
+            removeNode(p.hash, p.key, null, false, false);
             expectedModCount = modCount;
         }
     }
diff --git a/ojluni/src/main/java/java/util/LinkedHashSet.java b/ojluni/src/main/java/java/util/LinkedHashSet.java
index c573d7c..48b1e4f 100644
--- a/ojluni/src/main/java/java/util/LinkedHashSet.java
+++ b/ojluni/src/main/java/java/util/LinkedHashSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,15 +26,15 @@
 package java.util;
 
 /**
- * <p>Hash table and linked list implementation of the <tt>Set</tt> interface,
+ * <p>Hash table and linked list implementation of the {@code Set} interface,
  * with predictable iteration order.  This implementation differs from
- * <tt>HashSet</tt> in that it maintains a doubly-linked list running through
+ * {@code HashSet} in that it maintains a doubly-linked list running through
  * all of its entries.  This linked list defines the iteration ordering,
  * which is the order in which elements were inserted into the set
  * (<i>insertion-order</i>).  Note that insertion order is <i>not</i> affected
- * if an element is <i>re-inserted</i> into the set.  (An element <tt>e</tt>
- * is reinserted into a set <tt>s</tt> if <tt>s.add(e)</tt> is invoked when
- * <tt>s.contains(e)</tt> would return <tt>true</tt> immediately prior to
+ * if an element is <i>re-inserted</i> into the set.  (An element {@code e}
+ * is reinserted into a set {@code s} if {@code s.add(e)} is invoked when
+ * {@code s.contains(e)} would return {@code true} immediately prior to
  * the invocation.)
  *
  * <p>This implementation spares its clients from the unspecified, generally
@@ -53,22 +53,22 @@
  * the copy.  (Clients generally appreciate having things returned in the same
  * order they were presented.)
  *
- * <p>This class provides all of the optional <tt>Set</tt> operations, and
- * permits null elements.  Like <tt>HashSet</tt>, it provides constant-time
- * performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
- * <tt>remove</tt>), assuming the hash function disperses elements
+ * <p>This class provides all of the optional {@code Set} operations, and
+ * permits null elements.  Like {@code HashSet}, it provides constant-time
+ * performance for the basic operations ({@code add}, {@code contains} and
+ * {@code remove}), assuming the hash function disperses elements
  * properly among the buckets.  Performance is likely to be just slightly
- * below that of <tt>HashSet</tt>, due to the added expense of maintaining the
- * linked list, with one exception: Iteration over a <tt>LinkedHashSet</tt>
+ * below that of {@code HashSet}, due to the added expense of maintaining the
+ * linked list, with one exception: Iteration over a {@code LinkedHashSet}
  * requires time proportional to the <i>size</i> of the set, regardless of
- * its capacity.  Iteration over a <tt>HashSet</tt> is likely to be more
+ * its capacity.  Iteration over a {@code HashSet} is likely to be more
  * expensive, requiring time proportional to its <i>capacity</i>.
  *
  * <p>A linked hash set has two parameters that affect its performance:
  * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
- * as for <tt>HashSet</tt>.  Note, however, that the penalty for choosing an
+ * as for {@code HashSet}.  Note, however, that the penalty for choosing an
  * excessively high value for initial capacity is less severe for this class
- * than for <tt>HashSet</tt>, as iteration times for this class are unaffected
+ * than for {@code HashSet}, as iteration times for this class are unaffected
  * by capacity.
  *
  * <p><strong>Note that this implementation is not synchronized.</strong>
@@ -83,9 +83,9 @@
  * unsynchronized access to the set: <pre>
  *   Set s = Collections.synchronizedSet(new LinkedHashSet(...));</pre>
  *
- * <p>The iterators returned by this class's <tt>iterator</tt> method are
+ * <p>The iterators returned by this class's {@code iterator} method are
  * <em>fail-fast</em>: if the set is modified at any time after the iterator
- * is created, in any way except through the iterator's own <tt>remove</tt>
+ * is created, in any way except through the iterator's own {@code remove}
  * method, the iterator will throw a {@link ConcurrentModificationException}.
  * Thus, in the face of concurrent modification, the iterator fails quickly
  * and cleanly, rather than risking arbitrary, non-deterministic behavior at
@@ -94,13 +94,13 @@
  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  * as it is, generally speaking, impossible to make any hard guarantees in the
  * presence of unsynchronized concurrent modification.  Fail-fast iterators
- * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * throw {@code ConcurrentModificationException} on a best-effort basis.
  * Therefore, it would be wrong to write a program that depended on this
  * exception for its correctness:   <i>the fail-fast behavior of iterators
  * should be used only to detect bugs.</i>
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <E> the type of elements maintained by this set
diff --git a/ojluni/src/main/java/java/util/LinkedList.java b/ojluni/src/main/java/java/util/LinkedList.java
index 2683a90..8dd1d12 100644
--- a/ojluni/src/main/java/java/util/LinkedList.java
+++ b/ojluni/src/main/java/java/util/LinkedList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,7 +70,7 @@
  * should be used only to detect bugs.</i>
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
@@ -88,18 +88,22 @@
 
     /**
      * Pointer to first node.
-     * Invariant: (first == null && last == null) ||
-     *            (first.prev == null && first.item != null)
      */
     transient Node<E> first;
 
     /**
      * Pointer to last node.
-     * Invariant: (first == null && last == null) ||
-     *            (last.next == null && last.item != null)
      */
     transient Node<E> last;
 
+    /*
+    void dataStructureInvariants() {
+        assert (size == 0)
+            ? (first == null && last == null)
+            : (first.prev == null && last.next == null);
+    }
+    */
+
     /**
      * Constructs an empty list.
      */
@@ -308,13 +312,13 @@
      * Returns {@code true} if this list contains the specified element.
      * More formally, returns {@code true} if and only if this list contains
      * at least one element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     * {@code Objects.equals(o, e)}.
      *
      * @param o element whose presence in this list is to be tested
      * @return {@code true} if this list contains the specified element
      */
     public boolean contains(Object o) {
-        return indexOf(o) != -1;
+        return indexOf(o) >= 0;
     }
 
     /**
@@ -344,7 +348,7 @@
      * if it is present.  If this list does not contain the element, it is
      * unchanged.  More formally, removes the element with the lowest index
      * {@code i} such that
-     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
+     * {@code Objects.equals(o, get(i))}
      * (if such an element exists).  Returns {@code true} if this list
      * contained the specified element (or equivalently, if this list
      * changed as a result of the call).
@@ -585,7 +589,7 @@
      * Returns the index of the first occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
      * More formally, returns the lowest index {@code i} such that
-     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
+     * {@code Objects.equals(o, get(i))},
      * or -1 if there is no such index.
      *
      * @param o element to search for
@@ -614,7 +618,7 @@
      * Returns the index of the last occurrence of the specified element
      * in this list, or -1 if this list does not contain the element.
      * More formally, returns the highest index {@code i} such that
-     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
+     * {@code Objects.equals(o, get(i))},
      * or -1 if there is no such index.
      *
      * @param o element to search for
@@ -1167,7 +1171,7 @@
      */
     @Override
     public Spliterator<E> spliterator() {
-        return new LLSpliterator<E>(this, -1, 0);
+        return new LLSpliterator<>(this, -1, 0);
     }
 
     /** A customized variant of Spliterators.IteratorSpliterator */
diff --git a/ojluni/src/main/java/java/util/ListIterator.java b/ojluni/src/main/java/java/util/ListIterator.java
index 85a2f25..365daf0 100644
--- a/ojluni/src/main/java/java/util/ListIterator.java
+++ b/ojluni/src/main/java/java/util/ListIterator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
  * {@link #previous()}.
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @author  Josh Bloch
diff --git a/ojluni/src/main/java/java/util/ListResourceBundle.java b/ojluni/src/main/java/java/util/ListResourceBundle.java
index 99090ca..f2722e1 100644
--- a/ojluni/src/main/java/java/util/ListResourceBundle.java
+++ b/ojluni/src/main/java/java/util/ListResourceBundle.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
  * that key.
  *
  * <p>
- * The following <a name="sample">example</a> shows two members of a resource
+ * The following <a id="sample">example</a> shows two members of a resource
  * bundle family with the base name "MyResources".
  * "MyResources" is the default member of the bundle family, and
  * "MyResources_fr" is the French member.
@@ -113,7 +113,7 @@
  *
  * @see ResourceBundle
  * @see PropertyResourceBundle
- * @since JDK1.1
+ * @since 1.1
  */
 public abstract class ListResourceBundle extends ResourceBundle {
     /**
@@ -180,7 +180,7 @@
      * @return an array of an <code>Object</code> array representing a
      * key-value pair.
      */
-    abstract protected Object[][] getContents();
+    protected abstract Object[][] getContents();
 
     // ==================privates====================
 
@@ -194,10 +194,10 @@
 
         Object[][] contents = getContents();
         HashMap<String,Object> temp = new HashMap<>(contents.length);
-        for (int i = 0; i < contents.length; ++i) {
+        for (Object[] content : contents) {
             // key must be non-null String, value must be non-null
-            String key = (String) contents[i][0];
-            Object value = contents[i][1];
+            String key = (String) content[0];
+            Object value = content[1];
             if (key == null || value == null) {
                 throw new NullPointerException();
             }
diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java
index 80f9ed7..ffa8b71 100644
--- a/ojluni/src/main/java/java/util/Locale.java
+++ b/ojluni/src/main/java/java/util/Locale.java
@@ -837,6 +837,19 @@
         return LOCALECACHE.get(key);
     }
 
+    // BEGIN Android-added: Add a static method to clear the stale entries in Zygote
+    /**
+     * This method cleans the stale entries in LOCALECACHE.  This would
+     * be called in Zygote after GC but before fork, and so to avoid the
+     * cleaning of the cache to happen in child processes.
+     *
+     * @hide
+     */
+    public static void cleanCache() {
+        LOCALECACHE.cleanStaleEntries();
+    }
+    // END Android-added: Add a static method to clear the stale entries in Zygote
+
     private static class Cache extends LocaleObjectCache<LocaleKey, Locale> {
         private Cache() {
         }
diff --git a/ojluni/src/main/java/java/util/LongSummaryStatistics.java b/ojluni/src/main/java/java/util/LongSummaryStatistics.java
index 085aa29..06ad647 100644
--- a/ojluni/src/main/java/java/util/LongSummaryStatistics.java
+++ b/ojluni/src/main/java/java/util/LongSummaryStatistics.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
  * }</pre>
  *
  * <p>{@code LongSummaryStatistics} can be used as a
- * {@linkplain java.util.stream.Stream#collect(Collector)} reduction}
+ * {@linkplain java.util.stream.Stream#collect(Collector) reduction}
  * target for a {@linkplain java.util.stream.Stream stream}. For example:
  *
  * <pre> {@code
@@ -55,7 +55,7 @@
  *
  * @implNote This implementation is not thread safe. However, it is safe to use
  * {@link java.util.stream.Collectors#summarizingLong(java.util.function.ToLongFunction)
- * Collectors.toLongStatistics()} on a parallel stream, because the parallel
+ * Collectors.summarizingLong()} on a parallel stream, because the parallel
  * implementation of {@link java.util.stream.Stream#collect Stream.collect()}
  * provides the necessary partitioning, isolation, and merging of results for
  * safe and efficient parallel execution.
@@ -70,13 +70,58 @@
     private long max = Long.MIN_VALUE;
 
     /**
-     * Construct an empty instance with zero count, zero sum,
+     * Constructs an empty instance with zero count, zero sum,
      * {@code Long.MAX_VALUE} min, {@code Long.MIN_VALUE} max and zero
      * average.
      */
     public LongSummaryStatistics() { }
 
     /**
+     * Constructs a non-empty instance with the specified {@code count},
+     * {@code min}, {@code max}, and {@code sum}.
+     *
+     * <p>If {@code count} is zero then the remaining arguments are ignored and
+     * an empty instance is constructed.
+     *
+     * <p>If the arguments are inconsistent then an {@code IllegalArgumentException}
+     * is thrown.  The necessary consistent argument conditions are:
+     * <ul>
+     *   <li>{@code count >= 0}</li>
+     *   <li>{@code min <= max}</li>
+     * </ul>
+     * @apiNote
+     * The enforcement of argument correctness means that the retrieved set of
+     * recorded values obtained from a {@code LongSummaryStatistics} source
+     * instance may not be a legal set of arguments for this constructor due to
+     * arithmetic overflow of the source's recorded count of values.
+     * The consistent argument conditions are not sufficient to prevent the
+     * creation of an internally inconsistent instance.  An example of such a
+     * state would be an instance with: {@code count} = 2, {@code min} = 1,
+     * {@code max} = 2, and {@code sum} = 0.
+     *
+     * @param count the count of values
+     * @param min the minimum value
+     * @param max the maximum value
+     * @param sum the sum of all values
+     * @throws IllegalArgumentException if the arguments are inconsistent
+     * @since 10
+     */
+    public LongSummaryStatistics(long count, long min, long max, long sum)
+            throws IllegalArgumentException {
+        if (count < 0L) {
+            throw new IllegalArgumentException("Negative count value");
+        } else if (count > 0L) {
+            if (min > max) throw new IllegalArgumentException("Minimum greater than maximum");
+
+            this.count = count;
+            this.sum = sum;
+            this.min = min;
+            this.max = max;
+        }
+        // Use default field values if count == 0
+    }
+
+    /**
      * Records a new {@code int} value into the summary information.
      *
      * @param value the input value
@@ -162,14 +207,12 @@
         return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
     }
 
-    @Override
     /**
-     * {@inheritDoc}
-     *
      * Returns a non-empty string representation of this object suitable for
      * debugging. The exact presentation format is unspecified and may vary
      * between implementations and versions.
      */
+    @Override
     public String toString() {
         return String.format(
             "%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
diff --git a/ojluni/src/main/java/java/util/Map.java b/ojluni/src/main/java/java/util/Map.java
index cf07a11..9e303ad 100644
--- a/ojluni/src/main/java/java/util/Map.java
+++ b/ojluni/src/main/java/java/util/Map.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,10 +111,11 @@
  * Implementations may optionally handle the self-referential scenario, however
  * most current implementations do not do so.
  *
- * <h2><a id="immutable">Immutable Map Static Factory Methods</a></h2>
- * <p>The {@link Map#of() Map.of()} and
- * {@link Map#ofEntries(Map.Entry...) Map.ofEntries()}
- * static factory methods provide a convenient way to create immutable maps.
+ * <h2><a id="unmodifiable">Unmodifiable Maps</a></h2>
+ * <p>The {@link Map#of() Map.of},
+ * {@link Map#ofEntries(Map.Entry...) Map.ofEntries}, and
+ * {@link Map#copyOf Map.copyOf}
+ * static factory methods provide a convenient way to create unmodifiable maps.
  * The {@code Map}
  * instances created by these methods have the following characteristics:
  *
@@ -1274,8 +1275,8 @@
     }
 
     /**
-     * Returns an immutable map containing zero mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing zero mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1288,8 +1289,8 @@
     }
 
     /**
-     * Returns an immutable map containing a single mapping.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing a single mapping.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1305,8 +1306,8 @@
     }
 
     /**
-     * Returns an immutable map containing two mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing two mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1325,8 +1326,8 @@
     }
 
     /**
-     * Returns an immutable map containing three mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing three mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1347,8 +1348,8 @@
     }
 
     /**
-     * Returns an immutable map containing four mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing four mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1371,8 +1372,8 @@
     }
 
     /**
-     * Returns an immutable map containing five mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing five mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1397,8 +1398,8 @@
     }
 
     /**
-     * Returns an immutable map containing six mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing six mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1427,8 +1428,8 @@
     }
 
     /**
-     * Returns an immutable map containing seven mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing seven mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1459,8 +1460,8 @@
     }
 
     /**
-     * Returns an immutable map containing eight mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing eight mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1493,8 +1494,8 @@
     }
 
     /**
-     * Returns an immutable map containing nine mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing nine mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1529,8 +1530,8 @@
     }
 
     /**
-     * Returns an immutable map containing ten mappings.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * Returns an unmodifiable map containing ten mappings.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @param <K> the {@code Map}'s key type
      * @param <V> the {@code Map}'s value type
@@ -1567,9 +1568,9 @@
     }
 
     /**
-     * Returns an immutable map containing keys and values extracted from the given entries.
+     * Returns an unmodifiable map containing keys and values extracted from the given entries.
      * The entries themselves are not stored in the map.
-     * See <a href="#immutable">Immutable Map Static Factory Methods</a> for details.
+     * See <a href="#unmodifiable">Unmodifiable Maps</a> for details.
      *
      * @apiNote
      * It is convenient to create the map entries using the {@link Map#entry Map.entry()} method.
@@ -1617,7 +1618,7 @@
     }
 
     /**
-     * Returns an immutable {@link Entry} containing the given key and value.
+     * Returns an unmodifiable {@link Entry} containing the given key and value.
      * These entries are suitable for populating {@code Map} instances using the
      * {@link Map#ofEntries Map.ofEntries()} method.
      * The {@code Entry} instances created by this method have the following characteristics:
@@ -1625,7 +1626,7 @@
      * <ul>
      * <li>They disallow {@code null} keys and values. Attempts to create them using a {@code null}
      * key or value result in {@code NullPointerException}.
-     * <li>They are immutable. Calls to {@link Entry#setValue Entry.setValue()}
+     * <li>They are unmodifiable. Calls to {@link Entry#setValue Entry.setValue()}
      * on a returned {@code Entry} result in {@code UnsupportedOperationException}.
      * <li>They are not serializable.
      * <li>They are <a href="../lang/doc-files/ValueBased.html">value-based</a>.
diff --git a/ojluni/src/main/java/java/util/MissingFormatArgumentException.java b/ojluni/src/main/java/java/util/MissingFormatArgumentException.java
index 79b04a3..926a697 100644
--- a/ojluni/src/main/java/java/util/MissingFormatArgumentException.java
+++ b/ojluni/src/main/java/java/util/MissingFormatArgumentException.java
@@ -30,7 +30,7 @@
  * have a corresponding argument or if an argument index refers to an argument
  * that does not exist.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/MissingFormatWidthException.java b/ojluni/src/main/java/java/util/MissingFormatWidthException.java
index 9650fe2..e748695 100644
--- a/ojluni/src/main/java/java/util/MissingFormatWidthException.java
+++ b/ojluni/src/main/java/java/util/MissingFormatWidthException.java
@@ -28,7 +28,7 @@
 /**
  * Unchecked exception thrown when the format width is required.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/MissingResourceException.java b/ojluni/src/main/java/java/util/MissingResourceException.java
index 4586480..3e09dfa 100644
--- a/ojluni/src/main/java/java/util/MissingResourceException.java
+++ b/ojluni/src/main/java/java/util/MissingResourceException.java
@@ -45,7 +45,7 @@
  * @see java.lang.Exception
  * @see ResourceBundle
  * @author      Mark Davis
- * @since       JDK1.1
+ * @since       1.1
  */
 public
 class MissingResourceException extends RuntimeException {
@@ -64,10 +64,10 @@
     }
 
     /**
-     * Constructs a <code>MissingResourceException</code> with
-     * <code>message</code>, <code>className</code>, <code>key</code>,
-     * and <code>cause</code>. This constructor is package private for
-     * use by <code>ResourceBundle.getBundle</code>.
+     * Constructs a {@code MissingResourceException} with
+     * {@code message}, {@code className}, {@code key},
+     * and {@code cause}. This constructor is package private for
+     * use by {@code ResourceBundle.getBundle}.
      *
      * @param message
      *        the detail message
diff --git a/ojluni/src/main/java/java/util/NoSuchElementException.java b/ojluni/src/main/java/java/util/NoSuchElementException.java
index 15e1aad..6ce6c28 100644
--- a/ojluni/src/main/java/java/util/NoSuchElementException.java
+++ b/ojluni/src/main/java/java/util/NoSuchElementException.java
@@ -32,14 +32,14 @@
  * @author  unascribed
  * @see     java.util.Enumeration#nextElement()
  * @see     java.util.Iterator#next()
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class NoSuchElementException extends RuntimeException {
     private static final long serialVersionUID = 6769829250639411880L;
 
     /**
-     * Constructs a <code>NoSuchElementException</code> with <tt>null</tt>
+     * Constructs a {@code NoSuchElementException} with {@code null}
      * as its error message string.
      */
     public NoSuchElementException() {
@@ -47,9 +47,9 @@
     }
 
     /**
-     * Constructs a <code>NoSuchElementException</code>, saving a reference
-     * to the error message string <tt>s</tt> for later retrieval by the
-     * <tt>getMessage</tt> method.
+     * Constructs a {@code NoSuchElementException}, saving a reference
+     * to the error message string {@code s} for later retrieval by the
+     * {@code getMessage} method.
      *
      * @param   s   the detail message.
      */
diff --git a/ojluni/src/main/java/java/util/Objects.java b/ojluni/src/main/java/java/util/Objects.java
index 1f76487..815fbd8 100644
--- a/ojluni/src/main/java/java/util/Objects.java
+++ b/ojluni/src/main/java/java/util/Objects.java
@@ -34,16 +34,16 @@
  * on objects, or checking certain conditions before operation.  These utilities
  * include {@code null}-safe or {@code null}-tolerant methods for computing the
  * hash code of an object, returning a string for an object, comparing two
- * objects, and checking if indexes or sub-range values are out-of-bounds.
+ * objects, and checking if indexes or sub-range values are out of bounds.
  *
  * @apiNote
  * Static methods such as {@link Objects#checkIndex},
  * {@link Objects#checkFromToIndex}, and {@link Objects#checkFromIndexSize} are
  * provided for the convenience of checking if values corresponding to indexes
- * and sub-ranges are out-of-bounds.
+ * and sub-ranges are out of bounds.
  * Variations of these static methods support customization of the runtime
  * exception, and corresponding exception detail message, that is thrown when
- * values are out-of-bounds.  Such methods accept a functional interface
+ * values are out of bounds.  Such methods accept a functional interface
  * argument, instances of {@code BiFunction}, that maps out-of-bound values to a
  * runtime exception.  Care should be taken when using such methods in
  * combination with an argument that is a lambda expression, method reference or
@@ -351,7 +351,7 @@
      * Checks if the {@code index} is within the bounds of the range from
      * {@code 0} (inclusive) to {@code length} (exclusive).
      *
-     * <p>The {@code index} is defined to be out-of-bounds if any of the
+     * <p>The {@code index} is defined to be out of bounds if any of the
      * following inequalities is true:
      * <ul>
      *  <li>{@code index < 0}</li>
@@ -362,7 +362,7 @@
      * @param index the index
      * @param length the upper-bound (exclusive) of the range
      * @return {@code index} if it is within bounds of the range
-     * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
+     * @throws IndexOutOfBoundsException if the {@code index} is out of bounds
      * @since 9
      */
     // Android-removed: @ForceInline is an unsupported attribute.
@@ -377,7 +377,7 @@
      * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
      * (inclusive) to {@code length} (exclusive).
      *
-     * <p>The sub-range is defined to be out-of-bounds if any of the following
+     * <p>The sub-range is defined to be out of bounds if any of the following
      * inequalities is true:
      * <ul>
      *  <li>{@code fromIndex < 0}</li>
@@ -403,7 +403,7 @@
      * {@code fromIndex + size} (exclusive) is within the bounds of range from
      * {@code 0} (inclusive) to {@code length} (exclusive).
      *
-     * <p>The sub-range is defined to be out-of-bounds if any of the following
+     * <p>The sub-range is defined to be out of bounds if any of the following
      * inequalities is true:
      * <ul>
      *  <li>{@code fromIndex < 0}</li>
@@ -416,7 +416,7 @@
      * @param size the size of the sub-range
      * @param length the upper-bound (exclusive) of the range
      * @return {@code fromIndex} if the sub-range within bounds of the range
-     * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds
+     * @throws IndexOutOfBoundsException if the sub-range is out of bounds
      * @since 9
      */
     public static
diff --git a/ojluni/src/main/java/java/util/Observable.java b/ojluni/src/main/java/java/util/Observable.java
index be01640..65e3995 100644
--- a/ojluni/src/main/java/java/util/Observable.java
+++ b/ojluni/src/main/java/java/util/Observable.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,11 +31,11 @@
  * object that the application wants to have observed.
  * <p>
  * An observable object can have one or more observers. An observer
- * may be any object that implements interface <tt>Observer</tt>. After an
+ * may be any object that implements interface {@code Observer}. After an
  * observable instance changes, an application calling the
- * <code>Observable</code>'s <code>notifyObservers</code> method
+ * {@code Observable}'s {@code notifyObservers} method
  * causes all of its observers to be notified of the change by a call
- * to their <code>update</code> method.
+ * to their {@code update} method.
  * <p>
  * The order in which notifications will be delivered is unspecified.
  * The default implementation provided in the Observable class will
@@ -45,20 +45,34 @@
  * subclass follows this order, as they choose.
  * <p>
  * Note that this notification mechanism has nothing to do with threads
- * and is completely separate from the <tt>wait</tt> and <tt>notify</tt>
- * mechanism of class <tt>Object</tt>.
+ * and is completely separate from the {@code wait} and {@code notify}
+ * mechanism of class {@code Object}.
  * <p>
  * When an observable object is newly created, its set of observers is
  * empty. Two observers are considered the same if and only if the
- * <tt>equals</tt> method returns true for them.
+ * {@code equals} method returns true for them.
  *
  * @author  Chris Warth
  * @see     java.util.Observable#notifyObservers()
  * @see     java.util.Observable#notifyObservers(java.lang.Object)
  * @see     java.util.Observer
  * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
- * @since   JDK1.0
+ * @since   1.0
+ *
+ * @deprecated
+ * This class and the {@link Observer} interface have been deprecated.
+ * The event model supported by {@code Observer} and {@code Observable}
+ * is quite limited, the order of notifications delivered by
+ * {@code Observable} is unspecified, and state changes are not in
+ * one-for-one correspondence with notifications.
+ * For a richer event model, consider using the
+ * {@link java.beans} package.  For reliable and ordered
+ * messaging among threads, consider using one of the concurrent data
+ * structures in the {@link java.util.concurrent} package.
+ * For reactive streams style programming, see the
+ * {@link java.util.concurrent.Flow} API.
  */
+@Deprecated(since="9")
 public class Observable {
     private boolean changed = false;
     private Vector<Observer> obs;
@@ -88,7 +102,7 @@
 
     /**
      * Deletes an observer from the set of observers of this object.
-     * Passing <CODE>null</CODE> to this method will have no effect.
+     * Passing {@code null} to this method will have no effect.
      * @param   o   the observer to be deleted.
      */
     public synchronized void deleteObserver(Observer o) {
@@ -97,15 +111,15 @@
 
     /**
      * If this object has changed, as indicated by the
-     * <code>hasChanged</code> method, then notify all of its observers
-     * and then call the <code>clearChanged</code> method to
+     * {@code hasChanged} method, then notify all of its observers
+     * and then call the {@code clearChanged} method to
      * indicate that this object has no longer changed.
      * <p>
-     * Each observer has its <code>update</code> method called with two
-     * arguments: this observable object and <code>null</code>. In other
+     * Each observer has its {@code update} method called with two
+     * arguments: this observable object and {@code null}. In other
      * words, this method is equivalent to:
-     * <blockquote><tt>
-     * notifyObservers(null)</tt></blockquote>
+     * <blockquote>{@code
+     * notifyObservers(null)}</blockquote>
      *
      * @see     java.util.Observable#clearChanged()
      * @see     java.util.Observable#hasChanged()
@@ -117,12 +131,12 @@
 
     /**
      * If this object has changed, as indicated by the
-     * <code>hasChanged</code> method, then notify all of its observers
-     * and then call the <code>clearChanged</code> method to indicate
+     * {@code hasChanged} method, then notify all of its observers
+     * and then call the {@code clearChanged} method to indicate
      * that this object has no longer changed.
      * <p>
-     * Each observer has its <code>update</code> method called with two
-     * arguments: this observable object and the <code>arg</code> argument.
+     * Each observer has its {@code update} method called with two
+     * arguments: this observable object and the {@code arg} argument.
      *
      * @param   arg   any object.
      * @see     java.util.Observable#clearChanged()
@@ -171,8 +185,8 @@
     }
 
     /**
-     * Marks this <tt>Observable</tt> object as having been changed; the
-     * <tt>hasChanged</tt> method will now return <tt>true</tt>.
+     * Marks this {@code Observable} object as having been changed; the
+     * {@code hasChanged} method will now return {@code true}.
      */
     protected synchronized void setChanged() {
         changed = true;
@@ -181,9 +195,9 @@
     /**
      * Indicates that this object has no longer changed, or that it has
      * already notified all of its observers of its most recent change,
-     * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.
+     * so that the {@code hasChanged} method will now return {@code false}.
      * This method is called automatically by the
-     * <code>notifyObservers</code> methods.
+     * {@code notifyObservers} methods.
      *
      * @see     java.util.Observable#notifyObservers()
      * @see     java.util.Observable#notifyObservers(java.lang.Object)
@@ -195,10 +209,10 @@
     /**
      * Tests if this object has changed.
      *
-     * @return  <code>true</code> if and only if the <code>setChanged</code>
+     * @return  {@code true} if and only if the {@code setChanged}
      *          method has been called more recently than the
-     *          <code>clearChanged</code> method on this object;
-     *          <code>false</code> otherwise.
+     *          {@code clearChanged} method on this object;
+     *          {@code false} otherwise.
      * @see     java.util.Observable#clearChanged()
      * @see     java.util.Observable#setChanged()
      */
@@ -207,7 +221,7 @@
     }
 
     /**
-     * Returns the number of observers of this <tt>Observable</tt> object.
+     * Returns the number of observers of this {@code Observable} object.
      *
      * @return  the number of observers of this object.
      */
diff --git a/ojluni/src/main/java/java/util/Observer.java b/ojluni/src/main/java/java/util/Observer.java
index ef64e14..47f7933 100644
--- a/ojluni/src/main/java/java/util/Observer.java
+++ b/ojluni/src/main/java/java/util/Observer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,22 +25,27 @@
 package java.util;
 
 /**
- * A class can implement the <code>Observer</code> interface when it
+ * A class can implement the {@code Observer} interface when it
  * wants to be informed of changes in observable objects.
  *
  * @author  Chris Warth
  * @see     java.util.Observable
- * @since   JDK1.0
+ * @since   1.0
+ *
+ * @deprecated
+ * This interface has been deprecated. See the {@link Observable}
+ * class for further information.
  */
+@Deprecated(since="9")
 public interface Observer {
     /**
      * This method is called whenever the observed object is changed. An
-     * application calls an <tt>Observable</tt> object's
-     * <code>notifyObservers</code> method to have all the object's
+     * application calls an {@code Observable} object's
+     * {@code notifyObservers} method to have all the object's
      * observers notified of the change.
      *
      * @param   o     the observable object.
-     * @param   arg   an argument passed to the <code>notifyObservers</code>
+     * @param   arg   an argument passed to the {@code notifyObservers}
      *                 method.
      */
     void update(Observable o, Object arg);
diff --git a/ojluni/src/main/java/java/util/Optional.java b/ojluni/src/main/java/java/util/Optional.java
index bce8ff9..64ebd10 100644
--- a/ojluni/src/main/java/java/util/Optional.java
+++ b/ojluni/src/main/java/java/util/Optional.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,19 +28,29 @@
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
+import java.util.stream.Stream;
 
 // Android-changed: removed ValueBased paragraph.
 /**
- * A container object which may or may not contain a non-null value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code get()} will return the value.
+ * A container object which may or may not contain a non-{@code null} value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered <i>empty</i> and
+ * {@code isPresent()} returns {@code false}.
  *
  * <p>Additional methods that depend on the presence or absence of a contained
- * value are provided, such as {@link #orElse(java.lang.Object) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * value are provided, such as {@link #orElse(Object) orElse()}
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(Consumer) ifPresent()} (performs an
+ * action if a value is present).
  *
+ * @apiNote
+ * {@code Optional} is primarily intended for use as a method return type where
+ * there is a clear need to represent "no result," and where using {@code null}
+ * is likely to cause errors. A variable whose type is {@code Optional} should
+ * never itself be {@code null}; it should always point to an {@code Optional}
+ * instance.
+ *
+ * @param <T> the type of value
  * @since 1.8
  */
 public final class Optional<T> {
@@ -66,14 +76,15 @@
 
     /**
      * Returns an empty {@code Optional} instance.  No value is present for this
-     * Optional.
+     * {@code Optional}.
      *
-     * @apiNote Though it may be tempting to do so, avoid testing if an object
-     * is empty by comparing with {@code ==} against instances returned by
-     * {@code Option.empty()}. There is no guarantee that it is a singleton.
+     * @apiNote
+     * Though it may be tempting to do so, avoid testing if an object is empty
+     * by comparing with {@code ==} against instances returned by
+     * {@code Optional.empty()}.  There is no guarantee that it is a singleton.
      * Instead, use {@link #isPresent()}.
      *
-     * @param <T> Type of the non-existent value
+     * @param <T> The type of the non-existent value
      * @return an empty {@code Optional}
      */
     public static<T> Optional<T> empty() {
@@ -83,48 +94,50 @@
     }
 
     /**
-     * Constructs an instance with the value present.
+     * Constructs an instance with the described value.
      *
-     * @param value the non-null value to be present
-     * @throws NullPointerException if value is null
+     * @param value the non-{@code null} value to describe
+     * @throws NullPointerException if value is {@code null}
      */
     private Optional(T value) {
         this.value = Objects.requireNonNull(value);
     }
 
     /**
-     * Returns an {@code Optional} with the specified present non-null value.
+     * Returns an {@code Optional} describing the given non-{@code null}
+     * value.
      *
-     * @param <T> the class of the value
-     * @param value the value to be present, which must be non-null
+     * @param value the value to describe, which must be non-{@code null}
+     * @param <T> the type of the value
      * @return an {@code Optional} with the value present
-     * @throws NullPointerException if value is null
+     * @throws NullPointerException if value is {@code null}
      */
     public static <T> Optional<T> of(T value) {
         return new Optional<>(value);
     }
 
     /**
-     * Returns an {@code Optional} describing the specified value, if non-null,
-     * otherwise returns an empty {@code Optional}.
+     * Returns an {@code Optional} describing the given value, if
+     * non-{@code null}, otherwise returns an empty {@code Optional}.
      *
-     * @param <T> the class of the value
-     * @param value the possibly-null value to describe
+     * @param value the possibly-{@code null} value to describe
+     * @param <T> the type of the value
      * @return an {@code Optional} with a present value if the specified value
-     * is non-null, otherwise an empty {@code Optional}
+     *         is non-{@code null}, otherwise an empty {@code Optional}
      */
     public static <T> Optional<T> ofNullable(T value) {
         return value == null ? empty() : of(value);
     }
 
     /**
-     * If a value is present in this {@code Optional}, returns the value,
-     * otherwise throws {@code NoSuchElementException}.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @return the non-null value held by this {@code Optional}
-     * @throws NoSuchElementException if there is no value present
+     * @apiNote
+     * The preferred alternative to this method is {@link #orElseThrow()}.
      *
-     * @see Optional#isPresent()
+     * @return the non-{@code null} value described by this {@code Optional}
+     * @throws NoSuchElementException if no value is present
      */
     public T get() {
         if (value == null) {
@@ -134,115 +147,204 @@
     }
 
     /**
-     * Return {@code true} if there is a value present, otherwise {@code false}.
+     * If a value is present, returns {@code true}, otherwise {@code false}.
      *
-     * @return {@code true} if there is a value present, otherwise {@code false}
+     * @return {@code true} if a value is present, otherwise {@code false}
      */
     public boolean isPresent() {
         return value != null;
     }
 
     /**
-     * If a value is present, invoke the specified consumer with the value,
-     * otherwise do nothing.
+     * If a value is  not present, returns {@code true}, otherwise
+     * {@code false}.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
-     * null
+     * @return  {@code true} if a value is not present, otherwise {@code false}
+     * @since   11
      */
-    public void ifPresent(Consumer<? super T> consumer) {
-        if (value != null)
-            consumer.accept(value);
+    public boolean isEmpty() {
+        return value == null;
+    }
+
+    /**
+     * If a value is present, performs the given action with the value,
+     * otherwise does nothing.
+     *
+     * @param action the action to be performed, if a value is present
+     * @throws NullPointerException if value is present and the given action is
+     *         {@code null}
+     */
+    public void ifPresent(Consumer<? super T> action) {
+        if (value != null) {
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, performs the given action with the value,
+     * otherwise performs the given empty-based action.
+     *
+     * @param action the action to be performed, if a value is present
+     * @param emptyAction the empty-based action to be performed, if no value is
+     *        present
+     * @throws NullPointerException if a value is present and the given action
+     *         is {@code null}, or no value is present and the given empty-based
+     *         action is {@code null}.
+     * @since 9
+     */
+    public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
+        if (value != null) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
+        }
     }
 
     /**
      * If a value is present, and the value matches the given predicate,
-     * return an {@code Optional} describing the value, otherwise return an
+     * returns an {@code Optional} describing the value, otherwise returns an
      * empty {@code Optional}.
      *
-     * @param predicate a predicate to apply to the value, if present
-     * @return an {@code Optional} describing the value of this {@code Optional}
-     * if a value is present and the value matches the given predicate,
-     * otherwise an empty {@code Optional}
-     * @throws NullPointerException if the predicate is null
+     * @param predicate the predicate to apply to a value, if present
+     * @return an {@code Optional} describing the value of this
+     *         {@code Optional}, if a value is present and the value matches the
+     *         given predicate, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the predicate is {@code null}
      */
     public Optional<T> filter(Predicate<? super T> predicate) {
         Objects.requireNonNull(predicate);
-        if (!isPresent())
+        if (!isPresent()) {
             return this;
-        else
+        } else {
             return predicate.test(value) ? this : empty();
+        }
     }
 
     /**
-     * If a value is present, apply the provided mapping function to it,
-     * and if the result is non-null, return an {@code Optional} describing the
-     * result.  Otherwise return an empty {@code Optional}.
+     * If a value is present, returns an {@code Optional} describing (as if by
+     * {@link #ofNullable}) the result of applying the given mapping function to
+     * the value, otherwise returns an empty {@code Optional}.
      *
-     * @apiNote This method supports post-processing on optional values, without
+     * <p>If the mapping function returns a {@code null} result then this method
+     * returns an empty {@code Optional}.
+     *
+     * @apiNote
+     * This method supports post-processing on {@code Optional} values, without
      * the need to explicitly check for a return status.  For example, the
-     * following code traverses a stream of file names, selects one that has
-     * not yet been processed, and then opens that file, returning an
-     * {@code Optional<FileInputStream>}:
+     * following code traverses a stream of URIs, selects one that has not
+     * yet been processed, and creates a path from that URI, returning
+     * an {@code Optional<Path>}:
      *
      * <pre>{@code
-     *     Optional<FileInputStream> fis =
-     *         names.stream().filter(name -> !isProcessedYet(name))
+     *     Optional<Path> p =
+     *         uris.stream().filter(uri -> !isProcessedYet(uri))
      *                       .findFirst()
-     *                       .map(name -> new FileInputStream(name));
+     *                       .map(Paths::get);
      * }</pre>
      *
-     * Here, {@code findFirst} returns an {@code Optional<String>}, and then
-     * {@code map} returns an {@code Optional<FileInputStream>} for the desired
-     * file if one exists.
+     * Here, {@code findFirst} returns an {@code Optional<URI>}, and then
+     * {@code map} returns an {@code Optional<Path>} for the desired
+     * URI if one exists.
      *
-     * @param <U> The type of the result of the mapping function
-     * @param mapper a mapping function to apply to the value, if present
+     * @param mapper the mapping function to apply to a value, if present
+     * @param <U> The type of the value returned from the mapping function
      * @return an {@code Optional} describing the result of applying a mapping
-     * function to the value of this {@code Optional}, if a value is present,
-     * otherwise an empty {@code Optional}
-     * @throws NullPointerException if the mapping function is null
+     *         function to the value of this {@code Optional}, if a value is
+     *         present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null}
      */
-    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
+    public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
         Objects.requireNonNull(mapper);
-        if (!isPresent())
+        if (!isPresent()) {
             return empty();
-        else {
+        } else {
             return Optional.ofNullable(mapper.apply(value));
         }
     }
 
     /**
-     * If a value is present, apply the provided {@code Optional}-bearing
-     * mapping function to it, return that result, otherwise return an empty
-     * {@code Optional}.  This method is similar to {@link #map(Function)},
-     * but the provided mapper is one whose result is already an {@code Optional},
-     * and if invoked, {@code flatMap} does not wrap it with an additional
+     * If a value is present, returns the result of applying the given
+     * {@code Optional}-bearing mapping function to the value, otherwise returns
+     * an empty {@code Optional}.
+     *
+     * <p>This method is similar to {@link #map(Function)}, but the mapping
+     * function is one whose result is already an {@code Optional}, and if
+     * invoked, {@code flatMap} does not wrap it within an additional
      * {@code Optional}.
      *
-     * @param <U> The type parameter to the {@code Optional} returned by
-     * @param mapper a mapping function to apply to the value, if present
-     *           the mapping function
+     * @param <U> The type of value of the {@code Optional} returned by the
+     *            mapping function
+     * @param mapper the mapping function to apply to a value, if present
      * @return the result of applying an {@code Optional}-bearing mapping
-     * function to the value of this {@code Optional}, if a value is present,
-     * otherwise an empty {@code Optional}
-     * @throws NullPointerException if the mapping function is null or returns
-     * a null result
+     *         function to the value of this {@code Optional}, if a value is
+     *         present, otherwise an empty {@code Optional}
+     * @throws NullPointerException if the mapping function is {@code null} or
+     *         returns a {@code null} result
      */
-    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
+    public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) {
         Objects.requireNonNull(mapper);
-        if (!isPresent())
+        if (!isPresent()) {
             return empty();
-        else {
-            return Objects.requireNonNull(mapper.apply(value));
+        } else {
+            @SuppressWarnings("unchecked")
+            Optional<U> r = (Optional<U>) mapper.apply(value);
+            return Objects.requireNonNull(r);
         }
     }
 
     /**
-     * Return the value if present, otherwise return {@code other}.
+     * If a value is present, returns an {@code Optional} describing the value,
+     * otherwise returns an {@code Optional} produced by the supplying function.
      *
-     * @param other the value to be returned if there is no value present, may
-     * be null
+     * @param supplier the supplying function that produces an {@code Optional}
+     *        to be returned
+     * @return returns an {@code Optional} describing the value of this
+     *         {@code Optional}, if a value is present, otherwise an
+     *         {@code Optional} produced by the supplying function.
+     * @throws NullPointerException if the supplying function is {@code null} or
+     *         produces a {@code null} result
+     * @since 9
+     */
+    public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) {
+        Objects.requireNonNull(supplier);
+        if (isPresent()) {
+            return this;
+        } else {
+            @SuppressWarnings("unchecked")
+            Optional<T> r = (Optional<T>) supplier.get();
+            return Objects.requireNonNull(r);
+        }
+    }
+
+    /**
+     * If a value is present, returns a sequential {@link Stream} containing
+     * only that value, otherwise returns an empty {@code Stream}.
+     *
+     * @apiNote
+     * This method can be used to transform a {@code Stream} of optional
+     * elements to a {@code Stream} of present value elements:
+     * <pre>{@code
+     *     Stream<Optional<T>> os = ..
+     *     Stream<T> s = os.flatMap(Optional::stream)
+     * }</pre>
+     *
+     * @return the optional value as a {@code Stream}
+     * @since 9
+     */
+    public Stream<T> stream() {
+        if (!isPresent()) {
+            return Stream.empty();
+        } else {
+            return Stream.of(value);
+        }
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise returns
+     * {@code other}.
+     *
+     * @param other the value to be returned, if no value is present.
+     *        May be {@code null}.
      * @return the value, if present, otherwise {@code other}
      */
     public T orElse(T other) {
@@ -250,34 +352,50 @@
     }
 
     /**
-     * Return the value if present, otherwise invoke {@code other} and return
-     * the result of that invocation.
+     * If a value is present, returns the value, otherwise returns the result
+     * produced by the supplying function.
      *
-     * @param other a {@code Supplier} whose result is returned if no value
-     * is present
-     * @return the value if present otherwise the result of {@code other.get()}
-     * @throws NullPointerException if value is not present and {@code other} is
-     * null
+     * @param supplier the supplying function that produces a value to be returned
+     * @return the value, if present, otherwise the result produced by the
+     *         supplying function
+     * @throws NullPointerException if no value is present and the supplying
+     *         function is {@code null}
      */
-    public T orElseGet(Supplier<? extends T> other) {
-        return value != null ? value : other.get();
+    public T orElseGet(Supplier<? extends T> supplier) {
+        return value != null ? value : supplier.get();
     }
 
     /**
-     * Return the contained value, if present, otherwise throw an exception
-     * to be created by the provided supplier.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @apiNote A method reference to the exception constructor with an empty
-     * argument list can be used as the supplier. For example,
+     * @return the non-{@code null} value described by this {@code Optional}
+     * @throws NoSuchElementException if no value is present
+     * @since 10
+     */
+    public T orElseThrow() {
+        if (value == null) {
+            throw new NoSuchElementException("No value present");
+        }
+        return value;
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise throws an exception
+     * produced by the exception supplying function.
+     *
+     * @apiNote
+     * A method reference to the exception constructor with an empty argument
+     * list can be used as the supplier. For example,
      * {@code IllegalStateException::new}
      *
      * @param <X> Type of the exception to be thrown
-     * @param exceptionSupplier The supplier which will return the exception to
-     * be thrown
-     * @return the present value
-     * @throws X if there is no value present
-     * @throws NullPointerException if no value is present and
-     * {@code exceptionSupplier} is null
+     * @param exceptionSupplier the supplying function that produces an
+     *        exception to be thrown
+     * @return the value, if present
+     * @throws X if no value is present
+     * @throws NullPointerException if no value is present and the exception
+     *          supplying function is {@code null}
      */
     public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
         if (value != null) {
@@ -288,8 +406,8 @@
     }
 
     /**
-     * Indicates whether some other object is "equal to" this Optional. The
-     * other object is considered equal if:
+     * Indicates whether some other object is "equal to" this {@code Optional}.
+     * The other object is considered equal if:
      * <ul>
      * <li>it is also an {@code Optional} and;
      * <li>both instances have no value present or;
@@ -297,8 +415,8 @@
      * </ul>
      *
      * @param obj an object to be tested for equality
-     * @return {code true} if the other object is "equal to" this object
-     * otherwise {@code false}
+     * @return {@code true} if the other object is "equal to" this object
+     *         otherwise {@code false}
      */
     @Override
     public boolean equals(Object obj) {
@@ -315,10 +433,11 @@
     }
 
     /**
-     * Returns the hash code value of the present value, if any, or 0 (zero) if
-     * no value is present.
+     * Returns the hash code of the value, if present, otherwise {@code 0}
+     * (zero) if no value is present.
      *
-     * @return hash code value of the present value or 0 if no value is present
+     * @return hash code value of the present value or {@code 0} if no value is
+     *         present
      */
     @Override
     public int hashCode() {
@@ -326,13 +445,14 @@
     }
 
     /**
-     * Returns a non-empty string representation of this Optional suitable for
-     * debugging. The exact presentation format is unspecified and may vary
-     * between implementations and versions.
+     * Returns a non-empty string representation of this {@code Optional}
+     * suitable for debugging.  The exact presentation format is unspecified and
+     * may vary between implementations and versions.
      *
-     * @implSpec If a value is present the result must include its string
-     * representation in the result. Empty and present Optionals must be
-     * unambiguously differentiable.
+     * @implSpec
+     * If a value is present the result must include its string representation
+     * in the result.  Empty and present {@code Optional}s must be unambiguously
+     * differentiable.
      *
      * @return the string representation of this instance
      */
diff --git a/ojluni/src/main/java/java/util/OptionalDouble.java b/ojluni/src/main/java/java/util/OptionalDouble.java
index 7112df1..4539fa9 100644
--- a/ojluni/src/main/java/java/util/OptionalDouble.java
+++ b/ojluni/src/main/java/java/util/OptionalDouble.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,18 +27,26 @@
 import java.util.function.DoubleConsumer;
 import java.util.function.DoubleSupplier;
 import java.util.function.Supplier;
+import java.util.stream.DoubleStream;
 
 // Android-changed: removed ValueBased paragraph.
 /**
  * A container object which may or may not contain a {@code double} value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code getAsDouble()} will return the value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered <i>empty</i> and
+ * {@code isPresent()} returns {@code false}.
  *
  * <p>Additional methods that depend on the presence or absence of a contained
  * value are provided, such as {@link #orElse(double) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.DoubleConsumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(DoubleConsumer) ifPresent()} (performs
+ * an action if a value is present).
+ *
+ * @apiNote
+ * {@code OptionalDouble} is primarily intended for use as a method return type where
+ * there is a clear need to represent "no result." A variable whose type is
+ * {@code OptionalDouble} should never itself be {@code null}; it should always point
+ * to an {@code OptionalDouble} instance.
  *
  * @since 1.8
  */
@@ -66,12 +74,13 @@
     }
 
     /**
-     * Returns an empty {@code OptionalDouble} instance.  No value is present for this
-     * OptionalDouble.
+     * Returns an empty {@code OptionalDouble} instance.  No value is present
+     * for this {@code OptionalDouble}.
      *
-     * @apiNote Though it may be tempting to do so, avoid testing if an object
-     * is empty by comparing with {@code ==} against instances returned by
-     * {@code Option.empty()}. There is no guarantee that it is a singleton.
+     * @apiNote
+     * Though it may be tempting to do so, avoid testing if an object is empty
+     * by comparing with {@code ==} against instances returned by
+     * {@code OptionalDouble.empty()}.  There is no guarantee that it is a singleton.
      * Instead, use {@link #isPresent()}.
      *
      *  @return an empty {@code OptionalDouble}.
@@ -81,9 +90,9 @@
     }
 
     /**
-     * Construct an instance with the value present.
+     * Construct an instance with the described value.
      *
-     * @param value the double value to be present.
+     * @param value the double value to describe.
      */
     private OptionalDouble(double value) {
         this.isPresent = true;
@@ -91,9 +100,9 @@
     }
 
     /**
-     * Return an {@code OptionalDouble} with the specified value present.
+     * Returns an {@code OptionalDouble} describing the given value.
      *
-     * @param value the value to be present
+     * @param value the value to describe
      * @return an {@code OptionalDouble} with the value present
      */
     public static OptionalDouble of(double value) {
@@ -101,13 +110,14 @@
     }
 
     /**
-     * If a value is present in this {@code OptionalDouble}, returns the value,
-     * otherwise throws {@code NoSuchElementException}.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @return the value held by this {@code OptionalDouble}
-     * @throws NoSuchElementException if there is no value present
+     * @apiNote
+     * The preferred alternative to this method is {@link #orElseThrow()}.
      *
-     * @see OptionalDouble#isPresent()
+     * @return the value described by this {@code OptionalDouble}
+     * @throws NoSuchElementException if no value is present
      */
     public double getAsDouble() {
         if (!isPresent) {
@@ -117,31 +127,88 @@
     }
 
     /**
-     * Return {@code true} if there is a value present, otherwise {@code false}.
+     * If a value is present, returns {@code true}, otherwise {@code false}.
      *
-     * @return {@code true} if there is a value present, otherwise {@code false}
+     * @return {@code true} if a value is present, otherwise {@code false}
      */
     public boolean isPresent() {
         return isPresent;
     }
 
     /**
-     * Have the specified consumer accept the value if a value is present,
-     * otherwise do nothing.
+     * If a value is not present, returns {@code true}, otherwise
+     * {@code false}.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
-     * null
+     * @return  {@code true} if a value is not present, otherwise {@code false}
+     * @since   11
      */
-    public void ifPresent(DoubleConsumer consumer) {
-        if (isPresent)
-            consumer.accept(value);
+    public boolean isEmpty() {
+        return !isPresent;
     }
 
     /**
-     * Return the value if present, otherwise return {@code other}.
+     * If a value is present, performs the given action with the value,
+     * otherwise does nothing.
      *
-     * @param other the value to be returned if there is no value present
+     * @param action the action to be performed, if a value is present
+     * @throws NullPointerException if value is present and the given action is
+     *         {@code null}
+     */
+    public void ifPresent(DoubleConsumer action) {
+        if (isPresent) {
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, performs the given action with the value,
+     * otherwise performs the given empty-based action.
+     *
+     * @param action the action to be performed, if a value is present
+     * @param emptyAction the empty-based action to be performed, if no value is
+     * present
+     * @throws NullPointerException if a value is present and the given action
+     *         is {@code null}, or no value is present and the given empty-based
+     *         action is {@code null}.
+     * @since 9
+     */
+    public void ifPresentOrElse(DoubleConsumer action, Runnable emptyAction) {
+        if (isPresent) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
+        }
+    }
+
+    /**
+     * If a value is present, returns a sequential {@link DoubleStream}
+     * containing only that value, otherwise returns an empty
+     * {@code DoubleStream}.
+     *
+     * @apiNote
+     * This method can be used to transform a {@code Stream} of optional doubles
+     * to a {@code DoubleStream} of present doubles:
+     * <pre>{@code
+     *     Stream<OptionalDouble> os = ..
+     *     DoubleStream s = os.flatMapToDouble(OptionalDouble::stream)
+     * }</pre>
+     *
+     * @return the optional value as a {@code DoubleStream}
+     * @since 9
+     */
+    public DoubleStream stream() {
+        if (isPresent) {
+            return DoubleStream.of(value);
+        } else {
+            return DoubleStream.empty();
+        }
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise returns
+     * {@code other}.
+     *
+     * @param other the value to be returned, if no value is present
      * @return the value, if present, otherwise {@code other}
      */
     public double orElse(double other) {
@@ -149,36 +216,52 @@
     }
 
     /**
-     * Return the value if present, otherwise invoke {@code other} and return
-     * the result of that invocation.
+     * If a value is present, returns the value, otherwise returns the result
+     * produced by the supplying function.
      *
-     * @param other a {@code DoubleSupplier} whose result is returned if no value
-     * is present
-     * @return the value if present otherwise the result of {@code other.getAsDouble()}
-     * @throws NullPointerException if value is not present and {@code other} is
-     * null
+     * @param supplier the supplying function that produces a value to be returned
+     * @return the value, if present, otherwise the result produced by the
+     *         supplying function
+     * @throws NullPointerException if no value is present and the supplying
+     *         function is {@code null}
      */
-    public double orElseGet(DoubleSupplier other) {
-        return isPresent ? value : other.getAsDouble();
+    public double orElseGet(DoubleSupplier supplier) {
+        return isPresent ? value : supplier.getAsDouble();
     }
 
     /**
-     * Return the contained value, if present, otherwise throw an exception
-     * to be created by the provided supplier.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @apiNote A method reference to the exception constructor with an empty
-     * argument list can be used as the supplier. For example,
+     * @return the value described by this {@code OptionalDouble}
+     * @throws NoSuchElementException if no value is present
+     * @since 10
+     */
+    public double orElseThrow() {
+        if (!isPresent) {
+            throw new NoSuchElementException("No value present");
+        }
+        return value;
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise throws an exception
+     * produced by the exception supplying function.
+     *
+     * @apiNote
+     * A method reference to the exception constructor with an empty argument
+     * list can be used as the supplier. For example,
      * {@code IllegalStateException::new}
      *
      * @param <X> Type of the exception to be thrown
-     * @param exceptionSupplier The supplier which will return the exception to
-     * be thrown
-     * @return the present value
-     * @throws X if there is no value present
-     * @throws NullPointerException if no value is present and
-     * {@code exceptionSupplier} is null
+     * @param exceptionSupplier the supplying function that produces an
+     *        exception to be thrown
+     * @return the value, if present
+     * @throws X if no value is present
+     * @throws NullPointerException if no value is present and the exception
+     *         supplying function is {@code null}
      */
-    public<X extends Throwable> double orElseThrow(Supplier<X> exceptionSupplier) throws X {
+    public<X extends Throwable> double orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
         if (isPresent) {
             return value;
         } else {
@@ -187,17 +270,18 @@
     }
 
     /**
-     * Indicates whether some other object is "equal to" this OptionalDouble. The
-     * other object is considered equal if:
+     * Indicates whether some other object is "equal to" this
+     * {@code OptionalDouble}. The other object is considered equal if:
      * <ul>
      * <li>it is also an {@code OptionalDouble} and;
      * <li>both instances have no value present or;
-     * <li>the present values are "equal to" each other via {@code Double.compare() == 0}.
+     * <li>the present values are "equal to" each other via
+     * {@code Double.compare() == 0}.
      * </ul>
      *
      * @param obj an object to be tested for equality
-     * @return {code true} if the other object is "equal to" this object
-     * otherwise {@code false}
+     * @return {@code true} if the other object is "equal to" this object
+     *         otherwise {@code false}
      */
     @Override
     public boolean equals(Object obj) {
@@ -216,10 +300,11 @@
     }
 
     /**
-     * Returns the hash code value of the present value, if any, or 0 (zero) if
-     * no value is present.
+     * Returns the hash code of the value, if present, otherwise {@code 0}
+     * (zero) if no value is present.
      *
-     * @return hash code value of the present value or 0 if no value is present
+     * @return hash code value of the present value or {@code 0} if no value is
+     *         present
      */
     @Override
     public int hashCode() {
@@ -227,14 +312,13 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Returns a non-empty string representation of this {@code OptionalDouble}
+     * suitable for debugging.  The exact presentation format is unspecified and
+     * may vary between implementations and versions.
      *
-     * Returns a non-empty string representation of this object suitable for
-     * debugging. The exact presentation format is unspecified and may vary
-     * between implementations and versions.
-     *
-     * @implSpec If a value is present the result must include its string
-     * representation in the result. Empty and present instances must be
+     * @implSpec
+     * If a value is present the result must include its string representation
+     * in the result.  Empty and present {@code OptionalDouble}s must be
      * unambiguously differentiable.
      *
      * @return the string representation of this instance
diff --git a/ojluni/src/main/java/java/util/OptionalInt.java b/ojluni/src/main/java/java/util/OptionalInt.java
index 61cac03..d28bd02 100644
--- a/ojluni/src/main/java/java/util/OptionalInt.java
+++ b/ojluni/src/main/java/java/util/OptionalInt.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,18 +27,27 @@
 import java.util.function.IntConsumer;
 import java.util.function.IntSupplier;
 import java.util.function.Supplier;
+import java.util.stream.IntStream;
 
 // Android-changed: removed ValueBased paragraph.
 /**
- * A container object which may or may not contain a {@code int} value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code getAsInt()} will return the value.
+ * A container object which may or may not contain an {@code int} value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered <i>empty</i> and
+ * {@code isPresent()} returns {@code false}.
  *
  * <p>Additional methods that depend on the presence or absence of a contained
  * value are provided, such as {@link #orElse(int) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.IntConsumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(IntConsumer) ifPresent()} (performs an
+ * action if a value is present).
+ *
+ *
+ * @apiNote
+ * {@code OptionalInt} is primarily intended for use as a method return type where
+ * there is a clear need to represent "no result." A variable whose type is
+ * {@code OptionalInt} should never itself be {@code null}; it should always point
+ * to an {@code OptionalInt} instance.
  *
  * @since 1.8
  */
@@ -66,24 +75,25 @@
     }
 
     /**
-     * Returns an empty {@code OptionalInt} instance.  No value is present for this
-     * OptionalInt.
+     * Returns an empty {@code OptionalInt} instance.  No value is present for
+     * this {@code OptionalInt}.
      *
-     * @apiNote Though it may be tempting to do so, avoid testing if an object
-     * is empty by comparing with {@code ==} against instances returned by
-     * {@code Option.empty()}. There is no guarantee that it is a singleton.
+     * @apiNote
+     * Though it may be tempting to do so, avoid testing if an object is empty
+     * by comparing with {@code ==} against instances returned by
+     * {@code OptionalInt.empty()}.  There is no guarantee that it is a singleton.
      * Instead, use {@link #isPresent()}.
      *
-     *  @return an empty {@code OptionalInt}
+     * @return an empty {@code OptionalInt}
      */
     public static OptionalInt empty() {
         return EMPTY;
     }
 
     /**
-     * Construct an instance with the value present.
+     * Construct an instance with the described value.
      *
-     * @param value the int value to be present
+     * @param value the int value to describe
      */
     private OptionalInt(int value) {
         this.isPresent = true;
@@ -91,9 +101,9 @@
     }
 
     /**
-     * Return an {@code OptionalInt} with the specified value present.
+     * Returns an {@code OptionalInt} describing the given value.
      *
-     * @param value the value to be present
+     * @param value the value to describe
      * @return an {@code OptionalInt} with the value present
      */
     public static OptionalInt of(int value) {
@@ -101,13 +111,14 @@
     }
 
     /**
-     * If a value is present in this {@code OptionalInt}, returns the value,
-     * otherwise throws {@code NoSuchElementException}.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @return the value held by this {@code OptionalInt}
-     * @throws NoSuchElementException if there is no value present
+     * @apiNote
+     * The preferred alternative to this method is {@link #orElseThrow()}.
      *
-     * @see OptionalInt#isPresent()
+     * @return the value described by this {@code OptionalInt}
+     * @throws NoSuchElementException if no value is present
      */
     public int getAsInt() {
         if (!isPresent) {
@@ -117,31 +128,87 @@
     }
 
     /**
-     * Return {@code true} if there is a value present, otherwise {@code false}.
+     * If a value is present, returns {@code true}, otherwise {@code false}.
      *
-     * @return {@code true} if there is a value present, otherwise {@code false}
+     * @return {@code true} if a value is present, otherwise {@code false}
      */
     public boolean isPresent() {
         return isPresent;
     }
 
     /**
-     * Have the specified consumer accept the value if a value is present,
-     * otherwise do nothing.
+     * If a value is not present, returns {@code true}, otherwise
+     * {@code false}.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
-     * null
+     * @return  {@code true} if a value is not present, otherwise {@code false}
+     * @since   11
      */
-    public void ifPresent(IntConsumer consumer) {
-        if (isPresent)
-            consumer.accept(value);
+    public boolean isEmpty() {
+        return !isPresent;
     }
 
     /**
-     * Return the value if present, otherwise return {@code other}.
+     * If a value is present, performs the given action with the value,
+     * otherwise does nothing.
      *
-     * @param other the value to be returned if there is no value present
+     * @param action the action to be performed, if a value is present
+     * @throws NullPointerException if value is present and the given action is
+     *         {@code null}
+     */
+    public void ifPresent(IntConsumer action) {
+        if (isPresent) {
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, performs the given action with the value,
+     * otherwise performs the given empty-based action.
+     *
+     * @param action the action to be performed, if a value is present
+     * @param emptyAction the empty-based action to be performed, if no value is
+     *        present
+     * @throws NullPointerException if a value is present and the given action
+     *         is {@code null}, or no value is present and the given empty-based
+     *         action is {@code null}.
+     * @since 9
+     */
+    public void ifPresentOrElse(IntConsumer action, Runnable emptyAction) {
+        if (isPresent) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
+        }
+    }
+
+    /**
+     * If a value is present, returns a sequential {@link IntStream} containing
+     * only that value, otherwise returns an empty {@code IntStream}.
+     *
+     * @apiNote
+     * This method can be used to transform a {@code Stream} of optional
+     * integers to an {@code IntStream} of present integers:
+     * <pre>{@code
+     *     Stream<OptionalInt> os = ..
+     *     IntStream s = os.flatMapToInt(OptionalInt::stream)
+     * }</pre>
+     *
+     * @return the optional value as an {@code IntStream}
+     * @since 9
+     */
+    public IntStream stream() {
+        if (isPresent) {
+            return IntStream.of(value);
+        } else {
+            return IntStream.empty();
+        }
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise returns
+     * {@code other}.
+     *
+     * @param other the value to be returned, if no value is present
      * @return the value, if present, otherwise {@code other}
      */
     public int orElse(int other) {
@@ -149,36 +216,52 @@
     }
 
     /**
-     * Return the value if present, otherwise invoke {@code other} and return
-     * the result of that invocation.
+     * If a value is present, returns the value, otherwise returns the result
+     * produced by the supplying function.
      *
-     * @param other a {@code IntSupplier} whose result is returned if no value
-     * is present
-     * @return the value if present otherwise the result of {@code other.getAsInt()}
-     * @throws NullPointerException if value is not present and {@code other} is
-     * null
+     * @param supplier the supplying function that produces a value to be returned
+     * @return the value, if present, otherwise the result produced by the
+     *         supplying function
+     * @throws NullPointerException if no value is present and the supplying
+     *         function is {@code null}
      */
-    public int orElseGet(IntSupplier other) {
-        return isPresent ? value : other.getAsInt();
+    public int orElseGet(IntSupplier supplier) {
+        return isPresent ? value : supplier.getAsInt();
     }
 
     /**
-     * Return the contained value, if present, otherwise throw an exception
-     * to be created by the provided supplier.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @apiNote A method reference to the exception constructor with an empty
-     * argument list can be used as the supplier. For example,
+     * @return the value described by this {@code OptionalInt}
+     * @throws NoSuchElementException if no value is present
+     * @since 10
+     */
+    public int orElseThrow() {
+        if (!isPresent) {
+            throw new NoSuchElementException("No value present");
+        }
+        return value;
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise throws an exception
+     * produced by the exception supplying function.
+     *
+     * @apiNote
+     * A method reference to the exception constructor with an empty argument
+     * list can be used as the supplier. For example,
      * {@code IllegalStateException::new}
      *
      * @param <X> Type of the exception to be thrown
-     * @param exceptionSupplier The supplier which will return the exception to
-     * be thrown
-     * @return the present value
-     * @throws X if there is no value present
-     * @throws NullPointerException if no value is present and
-     * {@code exceptionSupplier} is null
+     * @param exceptionSupplier the supplying function that produces an
+     *        exception to be thrown
+     * @return the value, if present
+     * @throws X if no value is present
+     * @throws NullPointerException if no value is present and the exception
+     *         supplying function is {@code null}
      */
-    public<X extends Throwable> int orElseThrow(Supplier<X> exceptionSupplier) throws X {
+    public<X extends Throwable> int orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
         if (isPresent) {
             return value;
         } else {
@@ -187,8 +270,8 @@
     }
 
     /**
-     * Indicates whether some other object is "equal to" this OptionalInt. The
-     * other object is considered equal if:
+     * Indicates whether some other object is "equal to" this
+     * {@code OptionalInt}.  The other object is considered equal if:
      * <ul>
      * <li>it is also an {@code OptionalInt} and;
      * <li>both instances have no value present or;
@@ -196,8 +279,8 @@
      * </ul>
      *
      * @param obj an object to be tested for equality
-     * @return {code true} if the other object is "equal to" this object
-     * otherwise {@code false}
+     * @return {@code true} if the other object is "equal to" this object
+     *         otherwise {@code false}
      */
     @Override
     public boolean equals(Object obj) {
@@ -216,10 +299,11 @@
     }
 
     /**
-     * Returns the hash code value of the present value, if any, or 0 (zero) if
-     * no value is present.
+     * Returns the hash code of the value, if present, otherwise {@code 0}
+     * (zero) if no value is present.
      *
-     * @return hash code value of the present value or 0 if no value is present
+     * @return hash code value of the present value or {@code 0} if no value is
+     *         present
      */
     @Override
     public int hashCode() {
@@ -227,14 +311,13 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Returns a non-empty string representation of this {@code OptionalInt}
+     * suitable for debugging.  The exact presentation format is unspecified and
+     * may vary between implementations and versions.
      *
-     * Returns a non-empty string representation of this object suitable for
-     * debugging. The exact presentation format is unspecified and may vary
-     * between implementations and versions.
-     *
-     * @implSpec If a value is present the result must include its string
-     * representation in the result. Empty and present instances must be
+     * @implSpec
+     * If a value is present the result must include its string representation
+     * in the result.  Empty and present {@code OptionalInt}s must be
      * unambiguously differentiable.
      *
      * @return the string representation of this instance
diff --git a/ojluni/src/main/java/java/util/OptionalLong.java b/ojluni/src/main/java/java/util/OptionalLong.java
index b337d83..5558afa 100644
--- a/ojluni/src/main/java/java/util/OptionalLong.java
+++ b/ojluni/src/main/java/java/util/OptionalLong.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,18 +27,27 @@
 import java.util.function.LongConsumer;
 import java.util.function.LongSupplier;
 import java.util.function.Supplier;
+import java.util.stream.LongStream;
 
 // Android-changed: removed ValueBased paragraph.
 /**
  * A container object which may or may not contain a {@code long} value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code getAsLong()} will return the value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered <i>empty</i> and
+ * {@code isPresent()} returns {@code false}.
  *
  * <p>Additional methods that depend on the presence or absence of a contained
  * value are provided, such as {@link #orElse(long) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.LongConsumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(LongConsumer) ifPresent()} (performs an
+ * action if a value is present).
+ *
+ *
+ * @apiNote
+ * {@code OptionalLong} is primarily intended for use as a method return type where
+ * there is a clear need to represent "no result." A variable whose type is
+ * {@code OptionalLong} should never itself be {@code null}; it should always point
+ * to an {@code OptionalLong} instance.
  *
  * @since 1.8
  */
@@ -66,24 +75,25 @@
     }
 
     /**
-     * Returns an empty {@code OptionalLong} instance.  No value is present for this
-     * OptionalLong.
+     * Returns an empty {@code OptionalLong} instance.  No value is present for
+     * this {@code OptionalLong}.
      *
-     * @apiNote Though it may be tempting to do so, avoid testing if an object
-     * is empty by comparing with {@code ==} against instances returned by
-     * {@code Option.empty()}. There is no guarantee that it is a singleton.
+     * @apiNote
+     * Though it may be tempting to do so, avoid testing if an object is empty
+     * by comparing with {@code ==} against instances returned by
+     * {@code OptionalLong.empty()}.  There is no guarantee that it is a singleton.
      * Instead, use {@link #isPresent()}.
      *
-     *  @return an empty {@code OptionalLong}.
+     * @return an empty {@code OptionalLong}.
      */
     public static OptionalLong empty() {
         return EMPTY;
     }
 
     /**
-     * Construct an instance with the value present.
+     * Construct an instance with the described value.
      *
-     * @param value the long value to be present
+     * @param value the long value to describe
      */
     private OptionalLong(long value) {
         this.isPresent = true;
@@ -91,9 +101,9 @@
     }
 
     /**
-     * Return an {@code OptionalLong} with the specified value present.
+     * Returns an {@code OptionalLong} describing the given value.
      *
-     * @param value the value to be present
+     * @param value the value to describe
      * @return an {@code OptionalLong} with the value present
      */
     public static OptionalLong of(long value) {
@@ -101,13 +111,14 @@
     }
 
     /**
-     * If a value is present in this {@code OptionalLong}, returns the value,
-     * otherwise throws {@code NoSuchElementException}.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @return the value held by this {@code OptionalLong}
-     * @throws NoSuchElementException if there is no value present
+     * @apiNote
+     * The preferred alternative to this method is {@link #orElseThrow()}.
      *
-     * @see OptionalLong#isPresent()
+     * @return the value described by this {@code OptionalLong}
+     * @throws NoSuchElementException if no value is present
      */
     public long getAsLong() {
         if (!isPresent) {
@@ -117,31 +128,87 @@
     }
 
     /**
-     * Return {@code true} if there is a value present, otherwise {@code false}.
+     * If a value is present, returns {@code true}, otherwise {@code false}.
      *
-     * @return {@code true} if there is a value present, otherwise {@code false}
+     * @return {@code true} if a value is present, otherwise {@code false}
      */
     public boolean isPresent() {
         return isPresent;
     }
 
     /**
-     * Have the specified consumer accept the value if a value is present,
-     * otherwise do nothing.
+     * If a value is not present, returns {@code true}, otherwise
+     * {@code false}.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
-     * null
+     * @return  {@code true} if a value is not present, otherwise {@code false}
+     * @since   11
      */
-    public void ifPresent(LongConsumer consumer) {
-        if (isPresent)
-            consumer.accept(value);
+    public boolean isEmpty() {
+        return !isPresent;
     }
 
     /**
-     * Return the value if present, otherwise return {@code other}.
+     * If a value is present, performs the given action with the value,
+     * otherwise does nothing.
      *
-     * @param other the value to be returned if there is no value present
+     * @param action the action to be performed, if a value is present
+     * @throws NullPointerException if value is present and the given action is
+     *         {@code null}
+     */
+    public void ifPresent(LongConsumer action) {
+        if (isPresent) {
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, performs the given action with the value,
+     * otherwise performs the given empty-based action.
+     *
+     * @param action the action to be performed, if a value is present
+     * @param emptyAction the empty-based action to be performed, if no value is
+     *        present
+     * @throws NullPointerException if a value is present and the given action
+     *         is {@code null}, or no value is present and the given empty-based
+     *         action is {@code null}.
+     * @since 9
+     */
+    public void ifPresentOrElse(LongConsumer action, Runnable emptyAction) {
+        if (isPresent) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
+        }
+    }
+
+    /**
+     * If a value is present, returns a sequential {@link LongStream} containing
+     * only that value, otherwise returns an empty {@code LongStream}.
+     *
+     * @apiNote
+     * This method can be used to transform a {@code Stream} of optional longs
+     * to an {@code LongStream} of present longs:
+     * <pre>{@code
+     *     Stream<OptionalLong> os = ..
+     *     LongStream s = os.flatMapToLong(OptionalLong::stream)
+     * }</pre>
+     *
+     * @return the optional value as an {@code LongStream}
+     * @since 9
+     */
+    public LongStream stream() {
+        if (isPresent) {
+            return LongStream.of(value);
+        } else {
+            return LongStream.empty();
+        }
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise returns
+     * {@code other}.
+     *
+     * @param other the value to be returned, if no value is present
      * @return the value, if present, otherwise {@code other}
      */
     public long orElse(long other) {
@@ -149,36 +216,52 @@
     }
 
     /**
-     * Return the value if present, otherwise invoke {@code other} and return
-     * the result of that invocation.
+     * If a value is present, returns the value, otherwise returns the result
+     * produced by the supplying function.
      *
-     * @param other a {@code LongSupplier} whose result is returned if no value
-     * is present
-     * @return the value if present otherwise the result of {@code other.getAsLong()}
-     * @throws NullPointerException if value is not present and {@code other} is
-     * null
+     * @param supplier the supplying function that produces a value to be returned
+     * @return the value, if present, otherwise the result produced by the
+     *         supplying function
+     * @throws NullPointerException if no value is present and the supplying
+     *         function is {@code null}
      */
-    public long orElseGet(LongSupplier other) {
-        return isPresent ? value : other.getAsLong();
+    public long orElseGet(LongSupplier supplier) {
+        return isPresent ? value : supplier.getAsLong();
     }
 
     /**
-     * Return the contained value, if present, otherwise throw an exception
-     * to be created by the provided supplier.
+     * If a value is present, returns the value, otherwise throws
+     * {@code NoSuchElementException}.
      *
-     * @apiNote A method reference to the exception constructor with an empty
-     * argument list can be used as the supplier. For example,
+     * @return the value described by this {@code OptionalLong}
+     * @throws NoSuchElementException if no value is present
+     * @since 10
+     */
+    public long orElseThrow() {
+        if (!isPresent) {
+            throw new NoSuchElementException("No value present");
+        }
+        return value;
+    }
+
+    /**
+     * If a value is present, returns the value, otherwise throws an exception
+     * produced by the exception supplying function.
+     *
+     * @apiNote
+     * A method reference to the exception constructor with an empty argument
+     * list can be used as the supplier. For example,
      * {@code IllegalStateException::new}
      *
      * @param <X> Type of the exception to be thrown
-     * @param exceptionSupplier The supplier which will return the exception to
-     * be thrown
-     * @return the present value
-     * @throws X if there is no value present
-     * @throws NullPointerException if no value is present and
-     * {@code exceptionSupplier} is null
+     * @param exceptionSupplier the supplying function that produces an
+     *        exception to be thrown
+     * @return the value, if present
+     * @throws X if no value is present
+     * @throws NullPointerException if no value is present and the exception
+     *         supplying function is {@code null}
      */
-    public<X extends Throwable> long orElseThrow(Supplier<X> exceptionSupplier) throws X {
+    public<X extends Throwable> long orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
         if (isPresent) {
             return value;
         } else {
@@ -187,8 +270,8 @@
     }
 
     /**
-     * Indicates whether some other object is "equal to" this OptionalLong. The
-     * other object is considered equal if:
+     * Indicates whether some other object is "equal to" this
+     * {@code OptionalLong}.  The other object is considered equal if:
      * <ul>
      * <li>it is also an {@code OptionalLong} and;
      * <li>both instances have no value present or;
@@ -196,8 +279,8 @@
      * </ul>
      *
      * @param obj an object to be tested for equality
-     * @return {code true} if the other object is "equal to" this object
-     * otherwise {@code false}
+     * @return {@code true} if the other object is "equal to" this object
+     *         otherwise {@code false}
      */
     @Override
     public boolean equals(Object obj) {
@@ -216,10 +299,11 @@
     }
 
     /**
-     * Returns the hash code value of the present value, if any, or 0 (zero) if
-     * no value is present.
+     * Returns the hash code of the value, if present, otherwise {@code 0}
+     * (zero) if no value is present.
      *
-     * @return hash code value of the present value or 0 if no value is present
+     * @return hash code value of the present value or {@code 0} if no value is
+     *         present
      */
     @Override
     public int hashCode() {
@@ -227,14 +311,13 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Returns a non-empty string representation of this {@code OptionalLong}
+     * suitable for debugging.  The exact presentation format is unspecified and
+     * may vary between implementations and versions.
      *
-     * Returns a non-empty string representation of this object suitable for
-     * debugging. The exact presentation format is unspecified and may vary
-     * between implementations and versions.
-     *
-     * @implSpec If a value is present the result must include its string
-     * representation in the result. Empty and present instances must be
+     * @implSpec
+     * If a value is present the result must include its string representation
+     * in the result.  Empty and present {@code OptionalLong}s must be
      * unambiguously differentiable.
      *
      * @return the string representation of this instance
diff --git a/ojluni/src/main/java/java/util/PriorityQueue.java b/ojluni/src/main/java/java/util/PriorityQueue.java
index 90e59d1..7c929bd 100644
--- a/ojluni/src/main/java/java/util/PriorityQueue.java
+++ b/ojluni/src/main/java/java/util/PriorityQueue.java
@@ -72,7 +72,7 @@
  * ({@code peek}, {@code element}, and {@code size}).
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @since 1.5
diff --git a/ojluni/src/main/java/java/util/Queue.java b/ojluni/src/main/java/java/util/Queue.java
index cbdc205..a3ff4be 100644
--- a/ojluni/src/main/java/java/util/Queue.java
+++ b/ojluni/src/main/java/java/util/Queue.java
@@ -41,38 +41,41 @@
 
 /**
  * A collection designed for holding elements prior to processing.
- * Besides basic {@link java.util.Collection Collection} operations,
- * queues provide additional insertion, extraction, and inspection
- * operations.  Each of these methods exists in two forms: one throws
- * an exception if the operation fails, the other returns a special
- * value (either {@code null} or {@code false}, depending on the
- * operation).  The latter form of the insert operation is designed
- * specifically for use with capacity-restricted {@code Queue}
- * implementations; in most implementations, insert operations cannot
- * fail.
+ * Besides basic {@link Collection} operations, queues provide
+ * additional insertion, extraction, and inspection operations.
+ * Each of these methods exists in two forms: one throws an exception
+ * if the operation fails, the other returns a special value (either
+ * {@code null} or {@code false}, depending on the operation).  The
+ * latter form of the insert operation is designed specifically for
+ * use with capacity-restricted {@code Queue} implementations; in most
+ * implementations, insert operations cannot fail.
  *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <table class="striped">
  * <caption>Summary of Queue methods</caption>
+ *  <thead>
  *  <tr>
  *    <td></td>
- *    <td ALIGN=CENTER><em>Throws exception</em></td>
- *    <td ALIGN=CENTER><em>Returns special value</em></td>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Returns special value</th>
+ *  </tr>
+ *  </thead>
+ *  <tbody>
+ *  <tr>
+ *    <th scope="row">Insert</th>
+ *    <td>{@link #add(Object) add(e)}</td>
+ *    <td>{@link #offer(Object) offer(e)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Insert</b></td>
- *    <td>{@link Queue#add add(e)}</td>
- *    <td>{@link Queue#offer offer(e)}</td>
+ *    <th scope="row">Remove</th>
+ *    <td>{@link #remove() remove()}</td>
+ *    <td>{@link #poll() poll()}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Remove</b></td>
- *    <td>{@link Queue#remove remove()}</td>
- *    <td>{@link Queue#poll poll()}</td>
+ *    <th scope="row">Examine</th>
+ *    <td>{@link #element() element()}</td>
+ *    <td>{@link #peek() peek()}</td>
  *  </tr>
- *  <tr>
- *    <td><b>Examine</b></td>
- *    <td>{@link Queue#element element()}</td>
- *    <td>{@link Queue#peek peek()}</td>
- *  </tr>
+ *  </tbody>
  * </table>
  *
  * <p>Queues typically, but do not necessarily, order elements in a
@@ -81,7 +84,7 @@
  * comparator, or the elements' natural ordering, and LIFO queues (or
  * stacks) which order the elements LIFO (last-in-first-out).
  * Whatever the ordering used, the <em>head</em> of the queue is that
- * element which would be removed by a call to {@link #remove() } or
+ * element which would be removed by a call to {@link #remove()} or
  * {@link #poll()}.  In a FIFO queue, all new elements are inserted at
  * the <em>tail</em> of the queue. Other kinds of queues may use
  * different placement rules.  Every {@code Queue} implementation
@@ -173,8 +176,8 @@
 
     /**
      * Retrieves and removes the head of this queue.  This method differs
-     * from {@link #poll poll} only in that it throws an exception if this
-     * queue is empty.
+     * from {@link #poll() poll()} only in that it throws an exception if
+     * this queue is empty.
      *
      * @return the head of this queue
      * @throws NoSuchElementException if this queue is empty
diff --git a/ojluni/src/main/java/java/util/Random.java b/ojluni/src/main/java/java/util/Random.java
index 1061b59..f9c3c75 100644
--- a/ojluni/src/main/java/java/util/Random.java
+++ b/ojluni/src/main/java/java/util/Random.java
@@ -34,7 +34,7 @@
 import java.util.stream.LongStream;
 import java.util.stream.StreamSupport;
 
-import sun.misc.Unsafe;
+import jdk.internal.misc.Unsafe;
 
 /**
  * An instance of this class is used to generate a stream of
@@ -110,7 +110,7 @@
         // Different Sizes and Good Lattice Structure", 1999
         for (;;) {
             long current = seedUniquifier.get();
-            long next = current * 181783497276652981L;
+            long next = current * 1181783497276652981L;
             if (seedUniquifier.compareAndSet(current, next))
                 return next;
         }
@@ -165,7 +165,7 @@
      *
      * @param seed the initial seed
      */
-    synchronized public void setSeed(long seed) {
+    public synchronized void setSeed(long seed) {
         this.seed.set(initialScramble(seed));
         haveNextNextGaussian = false;
     }
@@ -187,7 +187,7 @@
      *
      * This is a linear congruential pseudorandom number generator, as
      * defined by D. H. Lehmer and described by Donald E. Knuth in
-     * <i>The Art of Computer Programming,</i> Volume 3:
+     * <i>The Art of Computer Programming,</i> Volume 2:
      * <i>Seminumerical Algorithms</i>, section 3.2.1.
      *
      * @param  bits random bits
@@ -570,7 +570,7 @@
      * }}</pre>
      * This uses the <i>polar method</i> of G. E. P. Box, M. E. Muller, and
      * G. Marsaglia, as described by Donald E. Knuth in <i>The Art of
-     * Computer Programming</i>, Volume 3: <i>Seminumerical Algorithms</i>,
+     * Computer Programming</i>, Volume 2: <i>Seminumerical Algorithms</i>,
      * section 3.4.1, subsection C, algorithm P. Note that it generates two
      * independent values at the cost of only one call to {@code StrictMath.log}
      * and one call to {@code StrictMath.sqrt}.
@@ -580,7 +580,7 @@
      *         standard deviation {@code 1.0} from this random number
      *         generator's sequence
      */
-    synchronized public double nextGaussian() {
+    public synchronized double nextGaussian() {
         // See Knuth, ACP, Section 3.4.1 Algorithm C.
         if (haveNextNextGaussian) {
             haveNextNextGaussian = false;
@@ -1197,7 +1197,7 @@
     /**
      * Save the {@code Random} instance to a stream.
      */
-    synchronized private void writeObject(ObjectOutputStream s)
+    private synchronized void writeObject(ObjectOutputStream s)
         throws IOException {
 
         // set the values of the Serializable fields
diff --git a/ojluni/src/main/java/java/util/RandomAccess.java b/ojluni/src/main/java/java/util/RandomAccess.java
index 6b7e453..52de56d 100644
--- a/ojluni/src/main/java/java/util/RandomAccess.java
+++ b/ojluni/src/main/java/java/util/RandomAccess.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,27 +26,27 @@
 package java.util;
 
 /**
- * Marker interface used by <tt>List</tt> implementations to indicate that
+ * Marker interface used by {@code List} implementations to indicate that
  * they support fast (generally constant time) random access.  The primary
  * purpose of this interface is to allow generic algorithms to alter their
  * behavior to provide good performance when applied to either random or
  * sequential access lists.
  *
  * <p>The best algorithms for manipulating random access lists (such as
- * <tt>ArrayList</tt>) can produce quadratic behavior when applied to
- * sequential access lists (such as <tt>LinkedList</tt>).  Generic list
+ * {@code ArrayList}) can produce quadratic behavior when applied to
+ * sequential access lists (such as {@code LinkedList}).  Generic list
  * algorithms are encouraged to check whether the given list is an
- * <tt>instanceof</tt> this interface before applying an algorithm that would
+ * {@code instanceof} this interface before applying an algorithm that would
  * provide poor performance if it were applied to a sequential access list,
  * and to alter their behavior if necessary to guarantee acceptable
  * performance.
  *
  * <p>It is recognized that the distinction between random and sequential
- * access is often fuzzy.  For example, some <tt>List</tt> implementations
+ * access is often fuzzy.  For example, some {@code List} implementations
  * provide asymptotically linear access times if they get huge, but constant
- * access times in practice.  Such a <tt>List</tt> implementation
+ * access times in practice.  Such a {@code List} implementation
  * should generally implement this interface.  As a rule of thumb, a
- * <tt>List</tt> implementation should implement this interface if,
+ * {@code List} implementation should implement this interface if,
  * for typical instances of the class, this loop:
  * <pre>
  *     for (int i=0, n=list.size(); i &lt; n; i++)
@@ -59,7 +59,7 @@
  * </pre>
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @since 1.4
diff --git a/ojluni/src/main/java/java/util/RegularEnumSet.java b/ojluni/src/main/java/java/util/RegularEnumSet.java
index 31a63f1..eef447e 100644
--- a/ojluni/src/main/java/java/util/RegularEnumSet.java
+++ b/ojluni/src/main/java/java/util/RegularEnumSet.java
@@ -123,19 +123,19 @@
     }
 
     /**
-     * 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 elements == 0;
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains the specified element.
+     * Returns {@code true} if this set contains the specified element.
      *
      * @param e element to be checked for containment in this collection
-     * @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 e) {
         if (e == null)
@@ -153,9 +153,9 @@
      * Adds the specified element to this set if it is not already present.
      *
      * @param e element to be added to this set
-     * @return <tt>true</tt> if the set changed as a result of the call
+     * @return {@code true} if the set changed as a result of the call
      *
-     * @throws NullPointerException if <tt>e</tt> is null
+     * @throws NullPointerException if {@code e} is null
      */
     public boolean add(E e) {
         typeCheck(e);
@@ -169,7 +169,7 @@
      * Removes the specified element from this set if it is present.
      *
      * @param e element to be removed from this set, if present
-     * @return <tt>true</tt> if the set contained the specified element
+     * @return {@code true} if the set contained the specified element
      */
     public boolean remove(Object e) {
         if (e == null)
@@ -186,11 +186,11 @@
     // Bulk Operations
 
     /**
-     * Returns <tt>true</tt> if this set contains all of the elements
+     * Returns {@code true} if this set contains all of the elements
      * in the specified collection.
      *
      * @param c collection to be checked for containment in this set
-     * @return <tt>true</tt> if this set contains all of the elements
+     * @return {@code true} if this set contains all of the elements
      *        in the specified collection
      * @throws NullPointerException if the specified collection is null
      */
@@ -209,7 +209,7 @@
      * Adds all of the elements in the specified collection to this set.
      *
      * @param c collection whose elements are 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 or any
      *     of its elements are null
      */
@@ -236,7 +236,7 @@
      * the specified collection.
      *
      * @param c 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 NullPointerException if the specified collection is null
      */
     public boolean removeAll(Collection<?> c) {
@@ -257,7 +257,7 @@
      * specified collection.
      *
      * @param c 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 NullPointerException if the specified collection is null
      */
     public boolean retainAll(Collection<?> c) {
@@ -285,12 +285,12 @@
 
     /**
      * Compares the specified object with this set for equality.  Returns
-     * <tt>true</tt> if the given object is also a set, the two sets have
+     * {@code true} if the given object is also a set, the two sets have
      * the same size, and every member of the given set is contained in
      * this set.
      *
      * @param o 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) {
         if (!(o instanceof RegularEnumSet))
diff --git a/ojluni/src/main/java/java/util/ResourceBundle.java b/ojluni/src/main/java/java/util/ResourceBundle.java
index dd07452..48f289f 100644
--- a/ojluni/src/main/java/java/util/ResourceBundle.java
+++ b/ojluni/src/main/java/java/util/ResourceBundle.java
@@ -1449,7 +1449,8 @@
                 // Otherwise, remove the cached one since we can't keep
                 // the same bundles having different parents.
                 BundleReference bundleRef = cacheList.get(cacheKey);
-                if (bundleRef != null && bundleRef.get() == bundle) {
+                // Android-changed: Use refersTo().
+                if (bundleRef != null && bundleRef.refersTo(bundle)) {
                     cacheList.remove(cacheKey, bundleRef);
                 }
             }
diff --git a/ojluni/src/main/java/java/util/ServiceConfigurationError.java b/ojluni/src/main/java/java/util/ServiceConfigurationError.java
index e0335f6..2852384 100644
--- a/ojluni/src/main/java/java/util/ServiceConfigurationError.java
+++ b/ojluni/src/main/java/java/util/ServiceConfigurationError.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,33 +27,12 @@
 
 
 /**
- * Error thrown when something goes wrong while loading a service provider.
- *
- * <p> This error will be thrown in the following situations:
- *
- * <ul>
- *
- *   <li> The format of a provider-configuration file violates the <a
- *   href="ServiceLoader.html#format">specification</a>; </li>
- *
- *   <li> An {@link java.io.IOException IOException} occurs while reading a
- *   provider-configuration file; </li>
- *
- *   <li> A concrete provider class named in a provider-configuration file
- *   cannot be found; </li>
- *
- *   <li> A concrete provider class is not a subclass of the service class;
- *   </li>
- *
- *   <li> A concrete provider class cannot be instantiated; or
- *
- *   <li> Some other kind of error occurs. </li>
- *
- * </ul>
- *
+ * Error thrown when something goes wrong while locating, loading, or
+ * instantiating a service provider.
  *
  * @author Mark Reinhold
  * @since 1.6
+ * @see ServiceLoader
  */
 
 public class ServiceConfigurationError
@@ -65,7 +44,7 @@
     /**
      * Constructs a new instance with the specified message.
      *
-     * @param  msg  The message, or <tt>null</tt> if there is no message
+     * @param  msg  The message, or {@code null} if there is no message
      *
      */
     public ServiceConfigurationError(String msg) {
@@ -75,9 +54,9 @@
     /**
      * Constructs a new instance with the specified message and cause.
      *
-     * @param  msg  The message, or <tt>null</tt> if there is no message
+     * @param  msg  The message, or {@code null} if there is no message
      *
-     * @param  cause  The cause, or <tt>null</tt> if the cause is nonexistent
+     * @param  cause  The cause, or {@code null} if the cause is nonexistent
      *                or unknown
      */
     public ServiceConfigurationError(String msg, Throwable cause) {
diff --git a/ojluni/src/main/java/java/util/Set.java b/ojluni/src/main/java/java/util/Set.java
index 91497ca..c2f6560 100644
--- a/ojluni/src/main/java/java/util/Set.java
+++ b/ojluni/src/main/java/java/util/Set.java
@@ -91,7 +91,7 @@
  * </ul>
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
  *
  * @param <E> the type of elements maintained by this set
diff --git a/ojluni/src/main/java/java/util/SimpleTimeZone.java b/ojluni/src/main/java/java/util/SimpleTimeZone.java
index ef70b96..7bc00bf 100644
--- a/ojluni/src/main/java/java/util/SimpleTimeZone.java
+++ b/ojluni/src/main/java/java/util/SimpleTimeZone.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,7 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.IOException;
+import java.io.InvalidObjectException;
 import sun.util.calendar.CalendarSystem;
 import sun.util.calendar.CalendarUtils;
 import sun.util.calendar.BaseCalendar;
@@ -547,12 +548,11 @@
 
       computeOffset:
         if (useDaylight) {
-            synchronized (this) {
-                if (cacheStart != 0) {
-                    if (date >= cacheStart && date < cacheEnd) {
-                        offset += dstSavings;
-                        break computeOffset;
-                    }
+            Cache cache = this.cache;
+            if (cache != null) {
+                if (date >= cache.start && date < cache.end) {
+                    offset += dstSavings;
+                    break computeOffset;
                 }
             }
             BaseCalendar cal = date >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER ?
@@ -670,14 +670,13 @@
     }
 
     private int getOffset(BaseCalendar cal, BaseCalendar.Date cdate, int year, long time) {
-        synchronized (this) {
-            if (cacheStart != 0) {
-                if (time >= cacheStart && time < cacheEnd) {
-                    return rawOffset + dstSavings;
-                }
-                if (year == cacheYear) {
-                    return rawOffset;
-                }
+        Cache cache = this.cache;
+        if (cache != null) {
+            if (time >= cache.start && time < cache.end) {
+                return rawOffset + dstSavings;
+            }
+            if (year == cache.year) {
+                return rawOffset;
             }
         }
 
@@ -688,11 +687,7 @@
             if (time >= start && time < end) {
                 offset += dstSavings;
             }
-            synchronized (this) {
-                cacheYear = year;
-                cacheStart = start;
-                cacheEnd = end;
-            }
+            this.cache = new Cache(year, start, end);
         } else {
             if (time < end) {
                 // TODO: support Gregorian cutover. The previous year
@@ -710,12 +705,7 @@
                 }
             }
             if (start <= end) {
-                synchronized (this) {
-                    // The start and end transitions are in multiple years.
-                    cacheYear = (long) startYear - 1;
-                    cacheStart = start;
-                    cacheEnd = end;
-                }
+                this.cache = new Cache((long) startYear - 1, start, end);
             }
         }
         return offset;
@@ -875,7 +865,7 @@
      * Generates the hash code for the SimpleDateFormat object.
      * @return the hash code for this object
      */
-    public synchronized int hashCode()
+    public int hashCode()
     {
         return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
             endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
@@ -1125,8 +1115,8 @@
      * be streamed out for compatibility with JDK 1.1.
      */
     private final byte monthLength[] = staticMonthLength;
-    private final static byte staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31};
-    private final static byte staticLeapMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31};
+    private static final byte staticMonthLength[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+    private static final byte staticLeapMonthLength[] = {31,29,31,30,31,30,31,31,30,31,30,31};
 
     /**
      * Variables specifying the mode of the start rule.  Takes the following
@@ -1200,19 +1190,27 @@
 
     /**
      * Cache values representing a single period of daylight saving
-     * time. When the cache values are valid, cacheStart is the start
-     * time (inclusive) of daylight saving time and cacheEnd is the
-     * end time (exclusive).
+     * time. Cache.start is the start time (inclusive) of daylight
+     * saving time and Cache.end is the end time (exclusive).
      *
-     * cacheYear has a year value if both cacheStart and cacheEnd are
-     * in the same year. cacheYear is set to startYear - 1 if
-     * cacheStart and cacheEnd are in different years. cacheStart is 0
-     * if the cache values are void. cacheYear is a long to support
-     * Integer.MIN_VALUE - 1 (JCK requirement).
+     * Cache.year has a year value if both Cache.start and Cache.end are
+     * in the same year. Cache.year is set to startYear - 1 if
+     * Cache.start and Cache.end are in different years.
+     * Cache.year is a long to support Integer.MIN_VALUE - 1 (JCK requirement).
      */
-    private transient long cacheYear;
-    private transient long cacheStart;
-    private transient long cacheEnd;
+    private static final class Cache {
+        final long year;
+        final long start;
+        final long end;
+
+        Cache(long year, long start, long end) {
+            this.year = year;
+            this.start = start;
+            this.end = end;
+        }
+    }
+
+    private transient volatile Cache cache;
 
     /**
      * Constants specifying values of startMode and endMode.
@@ -1278,9 +1276,11 @@
      */
     private int serialVersionOnStream = currentSerialVersion;
 
-    synchronized private void invalidateCache() {
-        cacheYear = startYear - 1;
-        cacheStart = cacheEnd = 0;
+    // Maximum number of rules.
+    private static final int MAX_RULE_NUM = 6;
+
+    private void invalidateCache() {
+        cache = null;
     }
 
     //----------------------------------------------------------------------
@@ -1569,7 +1569,7 @@
      */
     private byte[] packRules()
     {
-        byte[] rules = new byte[6];
+        byte[] rules = new byte[MAX_RULE_NUM];
         rules[0] = (byte)startDay;
         rules[1] = (byte)startDayOfWeek;
         rules[2] = (byte)endDay;
@@ -1594,7 +1594,7 @@
         endDayOfWeek   = rules[3];
 
         // As of serial version 2, include time modes
-        if (rules.length >= 6) {
+        if (rules.length >= MAX_RULE_NUM) {
             startTimeMode = rules[4];
             endTimeMode   = rules[5];
         }
@@ -1691,9 +1691,13 @@
             // store the actual rules (which have not be made compatible with 1.1)
             // in the optional area.  Read them in here and parse them.
             int length = stream.readInt();
-            byte[] rules = new byte[length];
-            stream.readFully(rules);
-            unpackRules(rules);
+            if (length <= MAX_RULE_NUM) {
+                byte[] rules = new byte[length];
+                stream.readFully(rules);
+                unpackRules(rules);
+            } else {
+                throw new InvalidObjectException("Too many rules: " + length);
+            }
         }
 
         if (serialVersionOnStream >= 2) {
diff --git a/ojluni/src/main/java/java/util/SortedMap.java b/ojluni/src/main/java/java/util/SortedMap.java
index 15ddba5..77553bc 100644
--- a/ojluni/src/main/java/java/util/SortedMap.java
+++ b/ojluni/src/main/java/java/util/SortedMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,7 +93,7 @@
  *   SortedMap&lt;String, V&gt; sub = m.subMap(low+"\0", high);</pre>
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <K> the type of keys maintained by this map
diff --git a/ojluni/src/main/java/java/util/SortedSet.java b/ojluni/src/main/java/java/util/SortedSet.java
index 1ba72dd..c3ef264 100644
--- a/ojluni/src/main/java/java/util/SortedSet.java
+++ b/ojluni/src/main/java/java/util/SortedSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,38 +34,38 @@
  * to take advantage of the ordering.  (This interface is the set
  * analogue of {@link SortedMap}.)
  *
- * <p>All elements inserted into a sorted set must implement the <tt>Comparable</tt>
+ * <p>All elements inserted into a sorted set must implement the {@code Comparable}
  * interface (or be accepted by the specified comparator).  Furthermore, all
- * such elements must be <i>mutually comparable</i>: <tt>e1.compareTo(e2)</tt>
- * (or <tt>comparator.compare(e1, e2)</tt>) must not throw a
- * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and <tt>e2</tt> in
+ * such elements must be <i>mutually comparable</i>: {@code e1.compareTo(e2)}
+ * (or {@code comparator.compare(e1, e2)}) must not throw a
+ * {@code ClassCastException} for any elements {@code e1} and {@code e2} in
  * the sorted set.  Attempts to violate this restriction will cause the
  * offending method or constructor invocation to throw a
- * <tt>ClassCastException</tt>.
+ * {@code ClassCastException}.
  *
  * <p>Note that the ordering maintained by a sorted set (whether or not an
  * explicit comparator is provided) must be <i>consistent with equals</i> if
- * the sorted set is to correctly implement the <tt>Set</tt> interface.  (See
- * the <tt>Comparable</tt> interface or <tt>Comparator</tt> interface for a
+ * the sorted set is to correctly implement the {@code Set} interface.  (See
+ * the {@code Comparable} interface or {@code Comparator} interface for a
  * precise definition of <i>consistent with equals</i>.)  This is so because
- * the <tt>Set</tt> interface is defined in terms of the <tt>equals</tt>
+ * the {@code Set} interface is defined in terms of the {@code equals}
  * operation, but a sorted set performs all element comparisons using its
- * <tt>compareTo</tt> (or <tt>compare</tt>) method, so two elements that are
+ * {@code compareTo} (or {@code compare}) method, so two elements that are
  * deemed equal by this method are, from the standpoint of the sorted set,
  * equal.  The behavior of a sorted set <i>is</i> well-defined even if its
  * ordering is inconsistent with equals; it just fails to obey the general
- * contract of the <tt>Set</tt> interface.
+ * contract of the {@code Set} interface.
  *
  * <p>All general-purpose sorted set implementation classes should
  * provide four "standard" constructors: 1) A void (no arguments)
  * constructor, which creates an empty sorted set sorted according to
  * the natural ordering of its elements.  2) A constructor with a
- * single argument of type <tt>Comparator</tt>, which creates an empty
+ * single argument of type {@code Comparator}, which creates an empty
  * sorted set sorted according to the specified comparator.  3) A
- * constructor with a single argument of type <tt>Collection</tt>,
+ * constructor with a single argument of type {@code Collection},
  * which creates a new sorted set with the same elements as its
  * argument, sorted according to the natural ordering of the elements.
- * 4) A constructor with a single argument of type <tt>SortedSet</tt>,
+ * 4) A constructor with a single argument of type {@code SortedSet},
  * which creates a new sorted set with the same elements and the same
  * ordering as the input sorted set.  There is no way to enforce this
  * recommendation, as interfaces cannot contain constructors.
@@ -75,21 +75,21 @@
  * endpoint but not their high endpoint (where applicable).
  * If you need a <i>closed range</i> (which includes both endpoints), and
  * the element type allows for calculation of the successor of a given
- * value, merely request the subrange from <tt>lowEndpoint</tt> to
- * <tt>successor(highEndpoint)</tt>.  For example, suppose that <tt>s</tt>
+ * value, merely request the subrange from {@code lowEndpoint} to
+ * {@code successor(highEndpoint)}.  For example, suppose that {@code s}
  * is a sorted set of strings.  The following idiom obtains a view
- * containing all of the strings in <tt>s</tt> from <tt>low</tt> to
- * <tt>high</tt>, inclusive:<pre>
+ * containing all of the strings in {@code s} from {@code low} to
+ * {@code high}, inclusive:<pre>
  *   SortedSet&lt;String&gt; sub = s.subSet(low, high+"\0");</pre>
  *
  * A similar technique can be used to generate an <i>open range</i> (which
  * contains neither endpoint).  The following idiom obtains a view
- * containing all of the Strings in <tt>s</tt> from <tt>low</tt> to
- * <tt>high</tt>, exclusive:<pre>
+ * containing all of the Strings in {@code s} from {@code low} to
+ * {@code high}, exclusive:<pre>
  *   SortedSet&lt;String&gt; sub = s.subSet(low+"\0", high);</pre>
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <E> the type of elements maintained by this set
@@ -108,98 +108,98 @@
 public interface SortedSet<E> extends Set<E> {
     /**
      * Returns the comparator used to order the elements in this set,
-     * or <tt>null</tt> if this set uses the {@linkplain Comparable
+     * or {@code null} if this set uses the {@linkplain Comparable
      * natural ordering} of its elements.
      *
      * @return the comparator used to order the elements in this set,
-     *         or <tt>null</tt> if this set uses the natural ordering
+     *         or {@code null} if this set uses the natural ordering
      *         of its elements
      */
     Comparator<? super E> comparator();
 
     /**
      * Returns a view of the portion of this set whose elements range
-     * from <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
-     * exclusive.  (If <tt>fromElement</tt> and <tt>toElement</tt> are
+     * from {@code fromElement}, inclusive, to {@code toElement},
+     * exclusive.  (If {@code fromElement} and {@code toElement} are
      * equal, the returned set is empty.)  The returned set is backed
      * by this set, so changes in the returned set are reflected in
      * this set, and vice-versa.  The returned set supports all
      * optional set operations that this set supports.
      *
-     * <p>The returned set will throw an <tt>IllegalArgumentException</tt>
+     * <p>The returned set will throw an {@code IllegalArgumentException}
      * on an attempt to insert an element outside its range.
      *
      * @param fromElement low endpoint (inclusive) of the returned set
      * @param toElement high endpoint (exclusive) of the returned set
      * @return a view of the portion of this set whose elements range from
-     *         <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive
-     * @throws ClassCastException if <tt>fromElement</tt> and
-     *         <tt>toElement</tt> cannot be compared to one another using this
+     *         {@code fromElement}, inclusive, to {@code toElement}, exclusive
+     * @throws ClassCastException if {@code fromElement} and
+     *         {@code toElement} cannot be compared to one another using this
      *         set's comparator (or, if the set has no comparator, using
      *         natural ordering).  Implementations may, but are not required
-     *         to, throw this exception if <tt>fromElement</tt> or
-     *         <tt>toElement</tt> cannot be compared to elements currently in
+     *         to, throw this exception if {@code fromElement} or
+     *         {@code toElement} cannot be compared to elements currently in
      *         the set.
-     * @throws NullPointerException if <tt>fromElement</tt> or
-     *         <tt>toElement</tt> is null and this set does not permit null
+     * @throws NullPointerException if {@code fromElement} or
+     *         {@code toElement} is null and this set does not permit null
      *         elements
-     * @throws IllegalArgumentException if <tt>fromElement</tt> is
-     *         greater than <tt>toElement</tt>; or if this set itself
-     *         has a restricted range, and <tt>fromElement</tt> or
-     *         <tt>toElement</tt> lies outside the bounds of the range
+     * @throws IllegalArgumentException if {@code fromElement} is
+     *         greater than {@code toElement}; or if this set itself
+     *         has a restricted range, and {@code fromElement} or
+     *         {@code toElement} lies outside the bounds of the range
      */
     SortedSet<E> subSet(E fromElement, E toElement);
 
     /**
      * Returns a view of the portion of this set whose elements are
-     * strictly less than <tt>toElement</tt>.  The returned set is
+     * strictly less than {@code toElement}.  The returned set is
      * backed by this set, so changes in the returned set are
      * reflected in this set, and vice-versa.  The returned set
      * supports all optional set operations that this set supports.
      *
-     * <p>The returned set will throw an <tt>IllegalArgumentException</tt>
+     * <p>The returned set will throw an {@code IllegalArgumentException}
      * on an attempt to insert an element outside its range.
      *
      * @param toElement high endpoint (exclusive) of the returned set
      * @return a view of the portion of this set whose elements are strictly
-     *         less than <tt>toElement</tt>
-     * @throws ClassCastException if <tt>toElement</tt> is not compatible
+     *         less than {@code toElement}
+     * @throws ClassCastException if {@code toElement} is not compatible
      *         with this set's comparator (or, if the set has no comparator,
-     *         if <tt>toElement</tt> does not implement {@link Comparable}).
+     *         if {@code toElement} does not implement {@link Comparable}).
      *         Implementations may, but are not required to, throw this
-     *         exception if <tt>toElement</tt> cannot be compared to elements
+     *         exception if {@code toElement} cannot be compared to elements
      *         currently in the set.
-     * @throws NullPointerException if <tt>toElement</tt> is null and
+     * @throws NullPointerException if {@code toElement} is null and
      *         this set does not permit null elements
      * @throws IllegalArgumentException if this set itself has a
-     *         restricted range, and <tt>toElement</tt> lies outside the
+     *         restricted range, and {@code toElement} lies outside the
      *         bounds of the range
      */
     SortedSet<E> headSet(E toElement);
 
     /**
      * Returns a view of the portion of this set whose elements are
-     * greater than or equal to <tt>fromElement</tt>.  The returned
+     * greater than or equal to {@code fromElement}.  The returned
      * set is backed by this set, so changes in the returned set are
      * reflected in this set, and vice-versa.  The returned set
      * supports all optional set operations that this set supports.
      *
-     * <p>The returned set will throw an <tt>IllegalArgumentException</tt>
+     * <p>The returned set will throw an {@code IllegalArgumentException}
      * on an attempt to insert an element outside its range.
      *
      * @param fromElement low endpoint (inclusive) of the returned set
      * @return a view of the portion of this set whose elements are greater
-     *         than or equal to <tt>fromElement</tt>
-     * @throws ClassCastException if <tt>fromElement</tt> is not compatible
+     *         than or equal to {@code fromElement}
+     * @throws ClassCastException if {@code fromElement} is not compatible
      *         with this set's comparator (or, if the set has no comparator,
-     *         if <tt>fromElement</tt> does not implement {@link Comparable}).
+     *         if {@code fromElement} does not implement {@link Comparable}).
      *         Implementations may, but are not required to, throw this
-     *         exception if <tt>fromElement</tt> cannot be compared to elements
+     *         exception if {@code fromElement} cannot be compared to elements
      *         currently in the set.
-     * @throws NullPointerException if <tt>fromElement</tt> is null
+     * @throws NullPointerException if {@code fromElement} is null
      *         and this set does not permit null elements
      * @throws IllegalArgumentException if this set itself has a
-     *         restricted range, and <tt>fromElement</tt> lies outside the
+     *         restricted range, and {@code fromElement} lies outside the
      *         bounds of the range
      */
     SortedSet<E> tailSet(E fromElement);
diff --git a/ojluni/src/main/java/java/util/Spliterator.java b/ojluni/src/main/java/java/util/Spliterator.java
index 35322b3..4851879 100644
--- a/ojluni/src/main/java/java/util/Spliterator.java
+++ b/ojluni/src/main/java/java/util/Spliterator.java
@@ -62,7 +62,7 @@
  * New characteristics may be defined in the future, so implementors should not
  * assign meanings to unlisted values.
  *
- * <p><a name="binding">A Spliterator that does not report {@code IMMUTABLE} or
+ * <p><a id="binding">A Spliterator that does not report {@code IMMUTABLE} or
  * {@code CONCURRENT} is expected to have a documented policy concerning:
  * when the spliterator <em>binds</em> to the element source; and detection of
  * structural interference of the element source detected after binding.</a>  A
@@ -84,7 +84,7 @@
  * via the {@link #estimateSize} method.  Ideally, as reflected in characteristic
  * {@link #SIZED}, this value corresponds exactly to the number of elements
  * that would be encountered in a successful traversal.  However, even when not
- * exactly known, an estimated value value may still be useful to operations
+ * exactly known, an estimated value may still be useful to operations
  * being performed on the source, such as helping to determine whether it is
  * preferable to split further or traverse the remaining elements sequentially.
  *
@@ -553,6 +553,12 @@
      * sub-split size is known and additions or removals to the source are not
      * reflected when traversing.
      *
+     * <p>A top-level Spliterator should not report both {@code CONCURRENT} and
+     * {@code IMMUTABLE}, since they are mutually exclusive. Such a Spliterator
+     * is inconsistent and no guarantees can be made about any computation using
+     * that Spliterator. Sub-spliterators may report {@code IMMUTABLE} if
+     * additions or removals to the source are not reflected when traversing.
+     *
      * @apiNote Most concurrent collections maintain a consistency policy
      * guaranteeing accuracy with respect to elements present at the point of
      * Spliterator construction, but possibly not reflecting subsequent
diff --git a/ojluni/src/main/java/java/util/Spliterators.java b/ojluni/src/main/java/java/util/Spliterators.java
index 79c0ef3..3b5fe86 100644
--- a/ojluni/src/main/java/java/util/Spliterators.java
+++ b/ojluni/src/main/java/java/util/Spliterators.java
@@ -132,7 +132,7 @@
      * @param array The array, assumed to be unmodified during use
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @see Arrays#spliterator(Object[])
@@ -164,7 +164,7 @@
      * @param toIndex One past the greatest index to cover
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
@@ -196,7 +196,7 @@
      * @param array The array, assumed to be unmodified during use
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @see Arrays#spliterator(int[])
@@ -226,7 +226,7 @@
      * @param toIndex One past the greatest index to cover
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
@@ -258,7 +258,7 @@
      * @param array The array, assumed to be unmodified during use
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @see Arrays#spliterator(long[])
@@ -282,7 +282,7 @@
      * {@code SIZED} and {@code SUBSIZED}.  The caller may provide additional
      * characteristics for the spliterator to report.  (For example, if it is
      * known the array will not be further modified, specify {@code IMMUTABLE};
-     * if the array data is considered to have an an encounter order, specify
+     * if the array data is considered to have an encounter order, specify
      * {@code ORDERED}).  The method {@link Arrays#spliterator(long[], int, int)} can
      * often be used instead, which returns a spliterator that reports
      * {@code SIZED}, {@code SUBSIZED}, {@code IMMUTABLE}, and {@code ORDERED}.
@@ -292,7 +292,7 @@
      * @param toIndex One past the greatest index to cover
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
@@ -324,7 +324,7 @@
      * @param array The array, assumed to be unmodified during use
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @see Arrays#spliterator(double[])
@@ -348,7 +348,7 @@
      * {@code SIZED} and {@code SUBSIZED}.  The caller may provide additional
      * characteristics for the spliterator to report.  (For example, if it is
      * known the array will not be further modified, specify {@code IMMUTABLE};
-     * if the array data is considered to have an an encounter order, specify
+     * if the array data is considered to have an encounter order, specify
      * {@code ORDERED}).  The method {@link Arrays#spliterator(long[], int, int)} can
      * often be used instead, which returns a spliterator that reports
      * {@code SIZED}, {@code SUBSIZED}, {@code IMMUTABLE}, and {@code ORDERED}.
@@ -358,7 +358,7 @@
      * @param toIndex One past the greatest index to cover
      * @param additionalCharacteristics Additional spliterator characteristics
      *        of this spliterator's source or elements beyond {@code SIZED} and
-     *        {@code SUBSIZED} which are are always reported
+     *        {@code SUBSIZED} which are always reported
      * @return A spliterator for an array
      * @throws NullPointerException if the given array is {@code null}
      * @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
@@ -833,7 +833,7 @@
 
     // Implementations
 
-    private static abstract class EmptySpliterator<T, S extends Spliterator<T>, C> {
+    private abstract static class EmptySpliterator<T, S extends Spliterator<T>, C> {
 
         EmptySpliterator() { }
 
@@ -907,7 +907,7 @@
          * @param array the array, assumed to be unmodified during use
          * @param additionalCharacteristics Additional spliterator characteristics
          * of this spliterator's source or elements beyond {@code SIZED} and
-         * {@code SUBSIZED} which are are always reported
+         * {@code SUBSIZED} which are always reported
          */
         public ArraySpliterator(Object[] array, int additionalCharacteristics) {
             this(array, 0, array.length, additionalCharacteristics);
@@ -920,7 +920,7 @@
          * @param fence one past the greatest index to cover
          * @param additionalCharacteristics Additional spliterator characteristics
          * of this spliterator's source or elements beyond {@code SIZED} and
-         * {@code SUBSIZED} which are are always reported
+         * {@code SUBSIZED} which are always reported
          */
         public ArraySpliterator(Object[] array, int origin, int fence, int additionalCharacteristics) {
             this.array = array;
@@ -992,7 +992,7 @@
          * @param array the array, assumed to be unmodified during use
          * @param additionalCharacteristics Additional spliterator characteristics
          *        of this spliterator's source or elements beyond {@code SIZED} and
-         *        {@code SUBSIZED} which are are always reported
+         *        {@code SUBSIZED} which are always reported
          */
         public IntArraySpliterator(int[] array, int additionalCharacteristics) {
             this(array, 0, array.length, additionalCharacteristics);
@@ -1005,7 +1005,7 @@
          * @param fence one past the greatest index to cover
          * @param additionalCharacteristics Additional spliterator characteristics
          *        of this spliterator's source or elements beyond {@code SIZED} and
-         *        {@code SUBSIZED} which are are always reported
+         *        {@code SUBSIZED} which are always reported
          */
         public IntArraySpliterator(int[] array, int origin, int fence, int additionalCharacteristics) {
             this.array = array;
@@ -1075,7 +1075,7 @@
          * @param array the array, assumed to be unmodified during use
          * @param additionalCharacteristics Additional spliterator characteristics
          *        of this spliterator's source or elements beyond {@code SIZED} and
-         *        {@code SUBSIZED} which are are always reported
+         *        {@code SUBSIZED} which are always reported
          */
         public LongArraySpliterator(long[] array, int additionalCharacteristics) {
             this(array, 0, array.length, additionalCharacteristics);
@@ -1088,7 +1088,7 @@
          * @param fence one past the greatest index to cover
          * @param additionalCharacteristics Additional spliterator characteristics
          *        of this spliterator's source or elements beyond {@code SIZED} and
-         *        {@code SUBSIZED} which are are always reported
+         *        {@code SUBSIZED} which are always reported
          */
         public LongArraySpliterator(long[] array, int origin, int fence, int additionalCharacteristics) {
             this.array = array;
@@ -1158,7 +1158,7 @@
          * @param array the array, assumed to be unmodified during use
          * @param additionalCharacteristics Additional spliterator characteristics
          *        of this spliterator's source or elements beyond {@code SIZED} and
-         *        {@code SUBSIZED} which are are always reported
+         *        {@code SUBSIZED} which are always reported
          */
         public DoubleArraySpliterator(double[] array, int additionalCharacteristics) {
             this(array, 0, array.length, additionalCharacteristics);
@@ -1171,7 +1171,7 @@
          * @param fence one past the greatest index to cover
          * @param additionalCharacteristics Additional spliterator characteristics
          *        of this spliterator's source or elements beyond {@code SIZED} and
-         *        {@code SUBSIZED} which are are always reported
+         *        {@code SUBSIZED} which are always reported
          */
         public DoubleArraySpliterator(double[] array, int origin, int fence, int additionalCharacteristics) {
             this.array = array;
@@ -1235,8 +1235,8 @@
      * <p>An extending class need only
      * implement {@link #tryAdvance(java.util.function.Consumer) tryAdvance}.
      * The extending class should override
-     * {@link #forEachRemaining(java.util.function.Consumer) forEach} if it can
-     * provide a more performant implementation.
+     * {@link #forEachRemaining(java.util.function.Consumer) forEachRemaining}
+     * if it can provide a more performant implementation.
      *
      * @apiNote
      * This class is a useful aid for creating a spliterator when it is not
@@ -1253,7 +1253,7 @@
      * @see #spliterator(Iterator, long, int)
      * @since 1.8
      */
-    public static abstract class AbstractSpliterator<T> implements Spliterator<T> {
+    public abstract static class AbstractSpliterator<T> implements Spliterator<T> {
         static final int BATCH_UNIT = 1 << 10;  // batch array size increment
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
         private final int characteristics;
@@ -1356,10 +1356,10 @@
      * permit limited parallelism.
      *
      * <p>To implement a spliterator an extending class need only
-     * implement {@link #tryAdvance(java.util.function.IntConsumer)}
+     * implement {@link #tryAdvance(java.util.function.IntConsumer)
      * tryAdvance}.  The extending class should override
-     * {@link #forEachRemaining(java.util.function.IntConsumer)} forEach} if it
-     * can provide a more performant implementation.
+     * {@link #forEachRemaining(java.util.function.IntConsumer) forEachRemaining}
+     * if it can provide a more performant implementation.
      *
      * @apiNote
      * This class is a useful aid for creating a spliterator when it is not
@@ -1376,7 +1376,7 @@
      * @see #spliterator(java.util.PrimitiveIterator.OfInt, long, int)
      * @since 1.8
      */
-    public static abstract class AbstractIntSpliterator implements Spliterator.OfInt {
+    public abstract static class AbstractIntSpliterator implements Spliterator.OfInt {
         static final int MAX_BATCH = AbstractSpliterator.MAX_BATCH;
         static final int BATCH_UNIT = AbstractSpliterator.BATCH_UNIT;
         private final int characteristics;
@@ -1466,10 +1466,10 @@
      * to permit limited parallelism.
      *
      * <p>To implement a spliterator an extending class need only
-     * implement {@link #tryAdvance(java.util.function.LongConsumer)}
+     * implement {@link #tryAdvance(java.util.function.LongConsumer)
      * tryAdvance}.  The extending class should override
-     * {@link #forEachRemaining(java.util.function.LongConsumer)} forEach} if it
-     * can provide a more performant implementation.
+     * {@link #forEachRemaining(java.util.function.LongConsumer) forEachRemaining}
+     * if it can provide a more performant implementation.
      *
      * @apiNote
      * This class is a useful aid for creating a spliterator when it is not
@@ -1486,7 +1486,7 @@
      * @see #spliterator(java.util.PrimitiveIterator.OfLong, long, int)
      * @since 1.8
      */
-    public static abstract class AbstractLongSpliterator implements Spliterator.OfLong {
+    public abstract static class AbstractLongSpliterator implements Spliterator.OfLong {
         static final int MAX_BATCH = AbstractSpliterator.MAX_BATCH;
         static final int BATCH_UNIT = AbstractSpliterator.BATCH_UNIT;
         private final int characteristics;
@@ -1576,10 +1576,10 @@
      * {@code trySplit} to permit limited parallelism.
      *
      * <p>To implement a spliterator an extending class need only
-     * implement {@link #tryAdvance(java.util.function.DoubleConsumer)}
+     * implement {@link #tryAdvance(java.util.function.DoubleConsumer)
      * tryAdvance}.  The extending class should override
-     * {@link #forEachRemaining(java.util.function.DoubleConsumer)} forEach} if
-     * it can provide a more performant implementation.
+     * {@link #forEachRemaining(java.util.function.DoubleConsumer) forEachRemaining}
+     * if it can provide a more performant implementation.
      *
      * @apiNote
      * This class is a useful aid for creating a spliterator when it is not
@@ -1596,7 +1596,7 @@
      * @see #spliterator(java.util.PrimitiveIterator.OfDouble, long, int)
      * @since 1.8
      */
-    public static abstract class AbstractDoubleSpliterator implements Spliterator.OfDouble {
+    public abstract static class AbstractDoubleSpliterator implements Spliterator.OfDouble {
         static final int MAX_BATCH = AbstractSpliterator.MAX_BATCH;
         static final int BATCH_UNIT = AbstractSpliterator.BATCH_UNIT;
         private final int characteristics;
@@ -1698,7 +1698,7 @@
         private int batch;            // batch size for splits
 
         /**
-         * Creates a spliterator using the given given
+         * Creates a spliterator using the given
          * collection's {@link java.util.Collection#iterator()) for traversal,
          * and reporting its {@link java.util.Collection#size()) as its initial
          * size.
diff --git a/ojluni/src/main/java/java/util/SplittableRandom.java b/ojluni/src/main/java/java/util/SplittableRandom.java
index 579102a..b85572f 100644
--- a/ojluni/src/main/java/java/util/SplittableRandom.java
+++ b/ojluni/src/main/java/java/util/SplittableRandom.java
@@ -375,7 +375,7 @@
      * may, and typically does, vary across program invocations.
      */
     public SplittableRandom() { // emulate defaultGen.split()
-        long s = defaultGen.getAndAdd(2 * GOLDEN_GAMMA);
+        long s = defaultGen.getAndAdd(GOLDEN_GAMMA << 1);
         this.seed = mix64(s);
         this.gamma = mixGamma(s + GOLDEN_GAMMA);
     }
@@ -399,6 +399,26 @@
     }
 
     /**
+     * Fills a user-supplied byte array with generated pseudorandom bytes.
+     *
+     * @param  bytes the byte array to fill with pseudorandom bytes
+     * @throws NullPointerException if bytes is null
+     * @since  10
+     */
+    public void nextBytes(byte[] bytes) {
+        int i = 0;
+        int len = bytes.length;
+        for (int words = len >> 3; words--> 0; ) {
+            long rnd = nextLong();
+            for (int n = 8; n--> 0; rnd >>>= Byte.SIZE)
+                bytes[i++] = (byte)rnd;
+        }
+        if (i < len)
+            for (long rnd = nextLong(); i < len; rnd >>>= Byte.SIZE)
+                bytes[i++] = (byte)rnd;
+    }
+
+    /**
      * Returns a pseudorandom {@code int} value.
      *
      * @return a pseudorandom {@code int} value
@@ -779,8 +799,7 @@
      * @return a stream of pseudorandom {@code double} values,
      *         each with the given origin (inclusive) and bound (exclusive)
      * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         less than zero, or {@code randomNumberOrigin}
      *         is greater than or equal to {@code randomNumberBound}
      */
     public DoubleStream doubles(long streamSize, double randomNumberOrigin,
diff --git a/ojluni/src/main/java/java/util/Stack.java b/ojluni/src/main/java/java/util/Stack.java
index ebea11e..2573276 100644
--- a/ojluni/src/main/java/java/util/Stack.java
+++ b/ojluni/src/main/java/java/util/Stack.java
@@ -26,12 +26,12 @@
 package java.util;
 
 /**
- * The <code>Stack</code> class represents a last-in-first-out
- * (LIFO) stack of objects. It extends class <tt>Vector</tt> with five
+ * The {@code Stack} class represents a last-in-first-out
+ * (LIFO) stack of objects. It extends class {@code Vector} with five
  * operations that allow a vector to be treated as a stack. The usual
- * <tt>push</tt> and <tt>pop</tt> operations are provided, as well as a
- * method to <tt>peek</tt> at the top item on the stack, a method to test
- * for whether the stack is <tt>empty</tt>, and a method to <tt>search</tt>
+ * {@code push} and {@code pop} operations are provided, as well as a
+ * method to {@code peek} at the top item on the stack, a method to test
+ * for whether the stack is {@code empty}, and a method to {@code search}
  * the stack for an item and discover how far it is from the top.
  * <p>
  * When a stack is first created, it contains no items.
@@ -43,7 +43,7 @@
  *   Deque<Integer> stack = new ArrayDeque<Integer>();}</pre>
  *
  * @author  Jonathan Payne
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class Stack<E> extends Vector<E> {
@@ -60,7 +60,7 @@
      * addElement(item)</pre></blockquote>
      *
      * @param   item   the item to be pushed onto this stack.
-     * @return  the <code>item</code> argument.
+     * @return  the {@code item} argument.
      * @see     java.util.Vector#addElement
      */
     public E push(E item) {
@@ -74,7 +74,7 @@
      * object as the value of this function.
      *
      * @return  The object at the top of this stack (the last item
-     *          of the <tt>Vector</tt> object).
+     *          of the {@code Vector} object).
      * @throws  EmptyStackException  if this stack is empty.
      */
     public synchronized E pop() {
@@ -92,7 +92,7 @@
      * from the stack.
      *
      * @return  the object at the top of this stack (the last item
-     *          of the <tt>Vector</tt> object).
+     *          of the {@code Vector} object).
      * @throws  EmptyStackException  if this stack is empty.
      */
     public synchronized E peek() {
@@ -106,8 +106,8 @@
     /**
      * Tests if this stack is empty.
      *
-     * @return  <code>true</code> if and only if this stack contains
-     *          no items; <code>false</code> otherwise.
+     * @return  {@code true} if and only if this stack contains
+     *          no items; {@code false} otherwise.
      */
     public boolean empty() {
         return size() == 0;
@@ -115,16 +115,16 @@
 
     /**
      * Returns the 1-based position where an object is on this stack.
-     * If the object <tt>o</tt> occurs as an item in this stack, this
+     * If the object {@code o} occurs as an item in this stack, this
      * method returns the distance from the top of the stack of the
      * occurrence nearest the top of the stack; the topmost item on the
-     * stack is considered to be at distance <tt>1</tt>. The <tt>equals</tt>
-     * method is used to compare <tt>o</tt> to the
+     * stack is considered to be at distance {@code 1}. The {@code equals}
+     * method is used to compare {@code o} to the
      * items in this stack.
      *
      * @param   o   the desired object.
      * @return  the 1-based position from the top of the stack where
-     *          the object is located; the return value <code>-1</code>
+     *          the object is located; the return value {@code -1}
      *          indicates that the object is not on the stack.
      */
     public synchronized int search(Object o) {
diff --git a/ojluni/src/main/java/java/util/StringJoiner.java b/ojluni/src/main/java/java/util/StringJoiner.java
index b6ba84c..27e2fb2 100644
--- a/ojluni/src/main/java/java/util/StringJoiner.java
+++ b/ojluni/src/main/java/java/util/StringJoiner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,10 +76,9 @@
     private StringBuilder value;
 
     /*
-     * By default, the string consisting of prefix+suffix, returned by
-     * toString(), or properties of value, when no elements have yet been added,
-     * i.e. when it is empty.  This may be overridden by the user to be some
-     * other value including the empty String.
+     * When overridden by the user to be non-null via {@link setEmptyValue}, the
+     * string returned by toString() when no elements have yet been added.
+     * When null, prefix + suffix is used as the empty value.
      */
     private String emptyValue;
 
@@ -152,7 +151,7 @@
      * Returns the current value, consisting of the {@code prefix}, the values
      * added so far separated by the {@code delimiter}, and the {@code suffix},
      * unless no elements have been added in which case, the
-     * {@code prefix + suffix} or the {@code emptyValue} characters are returned
+     * {@code prefix + suffix} or the {@code emptyValue} characters are returned.
      *
      * @return the string representation of this {@code StringJoiner}
      */
diff --git a/ojluni/src/main/java/java/util/StringTokenizer.java b/ojluni/src/main/java/java/util/StringTokenizer.java
index 1540c1a..5d55ae0 100644
--- a/ojluni/src/main/java/java/util/StringTokenizer.java
+++ b/ojluni/src/main/java/java/util/StringTokenizer.java
@@ -30,32 +30,32 @@
 /**
  * The string tokenizer class allows an application to break a
  * string into tokens. The tokenization method is much simpler than
- * the one used by the <code>StreamTokenizer</code> class. The
- * <code>StringTokenizer</code> methods do not distinguish among
+ * the one used by the {@code StreamTokenizer} class. The
+ * {@code StringTokenizer} methods do not distinguish among
  * identifiers, numbers, and quoted strings, nor do they recognize
  * and skip comments.
  * <p>
  * The set of delimiters (the characters that separate tokens) may
  * be specified either at creation time or on a per-token basis.
  * <p>
- * An instance of <code>StringTokenizer</code> behaves in one of two
+ * An instance of {@code StringTokenizer} behaves in one of two
  * ways, depending on whether it was created with the
- * <code>returnDelims</code> flag having the value <code>true</code>
- * or <code>false</code>:
+ * {@code returnDelims} flag having the value {@code true}
+ * or {@code false}:
  * <ul>
- * <li>If the flag is <code>false</code>, delimiter characters serve to
+ * <li>If the flag is {@code false}, delimiter characters serve to
  *     separate tokens. A token is a maximal sequence of consecutive
  *     characters that are not delimiters.
- * <li>If the flag is <code>true</code>, delimiter characters are themselves
+ * <li>If the flag is {@code true}, delimiter characters are themselves
  *     considered to be tokens. A token is thus either one delimiter
  *     character, or a maximal sequence of consecutive characters that are
  *     not delimiters.
  * </ul><p>
- * A <tt>StringTokenizer</tt> object internally maintains a current
+ * A {@code StringTokenizer} object internally maintains a current
  * position within the string to be tokenized. Some operations advance this
  * current position past the characters processed.<p>
  * A token is returned by taking a substring of the string that was used to
- * create the <tt>StringTokenizer</tt> object.
+ * create the {@code StringTokenizer} object.
  * <p>
  * The following is one example of the use of the tokenizer. The code:
  * <blockquote><pre>
@@ -74,12 +74,12 @@
  * </pre></blockquote>
  *
  * <p>
- * <tt>StringTokenizer</tt> is a legacy class that is retained for
+ * {@code StringTokenizer} is a legacy class that is retained for
  * compatibility reasons although its use is discouraged in new code. It is
- * recommended that anyone seeking this functionality use the <tt>split</tt>
- * method of <tt>String</tt> or the java.util.regex package instead.
+ * recommended that anyone seeking this functionality use the {@code split}
+ * method of {@code String} or the java.util.regex package instead.
  * <p>
- * The following example illustrates how the <tt>String.split</tt>
+ * The following example illustrates how the {@code String.split}
  * method can be used to break up a string into its basic tokens:
  * <blockquote><pre>
  *     String[] result = "this is a test".split("\\s");
@@ -97,7 +97,7 @@
  *
  * @author  unascribed
  * @see     java.io.StreamTokenizer
- * @since   JDK1.0
+ * @since   1.0
  */
 public
 class StringTokenizer implements Enumeration<Object> {
@@ -171,25 +171,25 @@
 
     /**
      * Constructs a string tokenizer for the specified string. All
-     * characters in the <code>delim</code> argument are the delimiters
+     * characters in the {@code delim} argument are the delimiters
      * for separating tokens.
      * <p>
-     * If the <code>returnDelims</code> flag is <code>true</code>, then
+     * If the {@code returnDelims} flag is {@code true}, then
      * the delimiter characters are also returned as tokens. Each
      * delimiter is returned as a string of length one. If the flag is
-     * <code>false</code>, the delimiter characters are skipped and only
+     * {@code false}, the delimiter characters are skipped and only
      * serve as separators between tokens.
      * <p>
-     * Note that if <tt>delim</tt> is <tt>null</tt>, this constructor does
+     * Note that if {@code delim} is {@code null}, this constructor does
      * not throw an exception. However, trying to invoke other methods on the
-     * resulting <tt>StringTokenizer</tt> may result in a
-     * <tt>NullPointerException</tt>.
+     * resulting {@code StringTokenizer} may result in a
+     * {@code NullPointerException}.
      *
      * @param   str            a string to be parsed.
      * @param   delim          the delimiters.
      * @param   returnDelims   flag indicating whether to return the delimiters
      *                         as tokens.
-     * @exception NullPointerException if str is <CODE>null</CODE>
+     * @exception NullPointerException if str is {@code null}
      */
     public StringTokenizer(String str, String delim, boolean returnDelims) {
         currentPosition = 0;
@@ -204,18 +204,18 @@
 
     /**
      * Constructs a string tokenizer for the specified string. The
-     * characters in the <code>delim</code> argument are the delimiters
+     * characters in the {@code delim} argument are the delimiters
      * for separating tokens. Delimiter characters themselves will not
      * be treated as tokens.
      * <p>
-     * Note that if <tt>delim</tt> is <tt>null</tt>, this constructor does
+     * Note that if {@code delim} is {@code null}, this constructor does
      * not throw an exception. However, trying to invoke other methods on the
-     * resulting <tt>StringTokenizer</tt> may result in a
-     * <tt>NullPointerException</tt>.
+     * resulting {@code StringTokenizer} may result in a
+     * {@code NullPointerException}.
      *
      * @param   str     a string to be parsed.
      * @param   delim   the delimiters.
-     * @exception NullPointerException if str is <CODE>null</CODE>
+     * @exception NullPointerException if str is {@code null}
      */
     public StringTokenizer(String str, String delim) {
         this(str, delim, false);
@@ -230,7 +230,7 @@
      * not be treated as tokens.
      *
      * @param   str   a string to be parsed.
-     * @exception NullPointerException if str is <CODE>null</CODE>
+     * @exception NullPointerException if str is {@code null}
      */
     public StringTokenizer(String str) {
         this(str, " \t\n\r\f", false);
@@ -297,8 +297,8 @@
     }
 
     private boolean isDelimiter(int codePoint) {
-        for (int i = 0; i < delimiterCodePoints.length; i++) {
-            if (delimiterCodePoints[i] == codePoint) {
+        for (int delimiterCodePoint : delimiterCodePoints) {
+            if (delimiterCodePoint == codePoint) {
                 return true;
             }
         }
@@ -307,11 +307,11 @@
 
     /**
      * Tests if there are more tokens available from this tokenizer's string.
-     * If this method returns <tt>true</tt>, then a subsequent call to
-     * <tt>nextToken</tt> with no argument will successfully return a token.
+     * If this method returns {@code true}, then a subsequent call to
+     * {@code nextToken} with no argument will successfully return a token.
      *
-     * @return  <code>true</code> if and only if there is at least one token
-     *          in the string after the current position; <code>false</code>
+     * @return  {@code true} if and only if there is at least one token
+     *          in the string after the current position; {@code false}
      *          otherwise.
      */
     public boolean hasMoreTokens() {
@@ -355,8 +355,8 @@
     /**
      * Returns the next token in this string tokenizer's string. First,
      * the set of characters considered to be delimiters by this
-     * <tt>StringTokenizer</tt> object is changed to be the characters in
-     * the string <tt>delim</tt>. Then the next token in the string
+     * {@code StringTokenizer} object is changed to be the characters in
+     * the string {@code delim}. Then the next token in the string
      * after the current position is returned. The current position is
      * advanced beyond the recognized token.  The new delimiter set
      * remains the default after this call.
@@ -365,7 +365,7 @@
      * @return     the next token, after switching to the new delimiter set.
      * @exception  NoSuchElementException  if there are no more tokens in this
      *               tokenizer's string.
-     * @exception NullPointerException if delim is <CODE>null</CODE>
+     * @exception NullPointerException if delim is {@code null}
      */
     public String nextToken(String delim) {
         delimiters = delim;
@@ -378,12 +378,12 @@
     }
 
     /**
-     * Returns the same value as the <code>hasMoreTokens</code>
+     * Returns the same value as the {@code hasMoreTokens}
      * method. It exists so that this class can implement the
-     * <code>Enumeration</code> interface.
+     * {@code Enumeration} interface.
      *
-     * @return  <code>true</code> if there are more tokens;
-     *          <code>false</code> otherwise.
+     * @return  {@code true} if there are more tokens;
+     *          {@code false} otherwise.
      * @see     java.util.Enumeration
      * @see     java.util.StringTokenizer#hasMoreTokens()
      */
@@ -392,10 +392,10 @@
     }
 
     /**
-     * Returns the same value as the <code>nextToken</code> method,
-     * except that its declared return value is <code>Object</code> rather than
-     * <code>String</code>. It exists so that this class can implement the
-     * <code>Enumeration</code> interface.
+     * Returns the same value as the {@code nextToken} method,
+     * except that its declared return value is {@code Object} rather than
+     * {@code String}. It exists so that this class can implement the
+     * {@code Enumeration} interface.
      *
      * @return     the next token in the string.
      * @exception  NoSuchElementException  if there are no more tokens in this
@@ -409,7 +409,7 @@
 
     /**
      * Calculates the number of times that this tokenizer's
-     * <code>nextToken</code> method can be called before it generates an
+     * {@code nextToken} method can be called before it generates an
      * exception. The current position is not advanced.
      *
      * @return  the number of tokens remaining in the string using the current
diff --git a/ojluni/src/main/java/java/util/TimSort.java b/ojluni/src/main/java/java/util/TimSort.java
index ea0d58f..7cce1cc 100644
--- a/ojluni/src/main/java/java/util/TimSort.java
+++ b/ojluni/src/main/java/java/util/TimSort.java
@@ -339,7 +339,7 @@
      * @param a the array in which a run is to be counted and possibly reversed
      * @param lo index of the first element in the run
      * @param hi index after the last element that may be contained in the run.
-              It is required that {@code lo < hi}.
+     *        It is required that {@code lo < hi}.
      * @param c the comparator to used for the sort
      * @return  the length of the run beginning at the specified position in
      *          the specified array
@@ -429,19 +429,23 @@
      * This method is called each time a new run is pushed onto the stack,
      * so the invariants are guaranteed to hold for i < stackSize upon
      * entry to the method.
+     *
+     * Thanks to Stijn de Gouw, Jurriaan Rot, Frank S. de Boer,
+     * Richard Bubel and Reiner Hahnle, this is fixed with respect to
+     * the analysis in "On the Worst-Case Complexity of TimSort" by
+     * Nicolas Auger, Vincent Jug, Cyril Nicaud, and Carine Pivoteau.
      */
     private void mergeCollapse() {
         while (stackSize > 1) {
             int n = stackSize - 2;
-            if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
+            if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1] ||
+                n > 1 && runLen[n-2] <= runLen[n] + runLen[n-1]) {
                 if (runLen[n - 1] < runLen[n + 1])
                     n--;
-                mergeAt(n);
-            } else if (runLen[n] <= runLen[n + 1]) {
-                mergeAt(n);
-            } else {
+            } else if (n < 0 || runLen[n] > runLen[n + 1]) {
                 break; // Invariant is established
             }
+            mergeAt(n);
         }
     }
 
@@ -916,12 +920,7 @@
     private T[] ensureCapacity(int minCapacity) {
         if (tmpLen < minCapacity) {
             // Compute smallest power of 2 > minCapacity
-            int newSize = minCapacity;
-            newSize |= newSize >> 1;
-            newSize |= newSize >> 2;
-            newSize |= newSize >> 4;
-            newSize |= newSize >> 8;
-            newSize |= newSize >> 16;
+            int newSize = -1 >>> Integer.numberOfLeadingZeros(minCapacity);
             newSize++;
 
             if (newSize < 0) // Not bloody likely!
diff --git a/ojluni/src/main/java/java/util/TimeZone.java b/ojluni/src/main/java/java/util/TimeZone.java
index 265a59d..bcac85c 100644
--- a/ojluni/src/main/java/java/util/TimeZone.java
+++ b/ojluni/src/main/java/java/util/TimeZone.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,7 @@
  * produce a TimeZone. The syntax of a custom time zone ID is:
  *
  * <blockquote><pre>
- * <a name="CustomID"><i>CustomID:</i></a>
+ * <a id="CustomID"><i>CustomID:</i></a>
  *         <code>GMT</code> <i>Sign</i> <i>Hours</i> <code>:</code> <i>Minutes</i>
  *         <code>GMT</code> <i>Sign</i> <i>Hours</i> <i>Minutes</i>
  *         <code>GMT</code> <i>Sign</i> <i>Hours</i>
@@ -109,7 +109,7 @@
  * When creating a <code>TimeZone</code>, the specified custom time
  * zone ID is normalized in the following syntax:
  * <blockquote><pre>
- * <a name="NormalizedCustomID"><i>NormalizedCustomID:</i></a>
+ * <a id="NormalizedCustomID"><i>NormalizedCustomID:</i></a>
  *         <code>GMT</code> <i>Sign</i> <i>TwoDigitHours</i> <code>:</code> <i>Minutes</i>
  * <i>Sign:</i> one of
  *         <code>+ -</code>
@@ -136,9 +136,9 @@
  * @see          GregorianCalendar
  * @see          SimpleTimeZone
  * @author       Mark Davis, David Goldsmith, Chen-Lieh Huang, Alan Liu
- * @since        JDK1.1
+ * @since        1.1
  */
-abstract public class TimeZone implements Serializable, Cloneable {
+public abstract class TimeZone implements Serializable, Cloneable {
     /**
      * Sole constructor.  (For invocation by subclass constructors, typically
      * implicit.)
@@ -266,7 +266,7 @@
      *
      * @param offsetMillis the given base time zone offset to GMT.
      */
-    abstract public void setRawOffset(int offsetMillis);
+    public abstract void setRawOffset(int offsetMillis);
 
     /**
      * Returns the amount of time in milliseconds to add to UTC to get
@@ -548,7 +548,7 @@
      * @return {@code true} if the given date is in Daylight Saving Time,
      *         {@code false}, otherwise.
      */
-    abstract public boolean inDaylightTime(Date date);
+    public abstract boolean inDaylightTime(Date date);
 
     /**
      * Gets the <code>TimeZone</code> for the given ID.
@@ -772,9 +772,7 @@
     public Object clone()
     {
         try {
-            TimeZone other = (TimeZone) super.clone();
-            other.ID = ID;
-            return other;
+            return super.clone();
         } catch (CloneNotSupportedException e) {
             throw new InternalError(e);
         }
diff --git a/ojluni/src/main/java/java/util/Timer.java b/ojluni/src/main/java/java/util/Timer.java
index 487db0d..de45fba 100644
--- a/ojluni/src/main/java/java/util/Timer.java
+++ b/ojluni/src/main/java/java/util/Timer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
  * background thread.  Tasks may be scheduled for one-time execution, or for
  * repeated execution at regular intervals.
  *
- * <p>Corresponding to each <tt>Timer</tt> object is a single background
+ * <p>Corresponding to each {@code Timer} object is a single background
  * thread that is used to execute all of the timer's tasks, sequentially.
  * Timer tasks should complete quickly.  If a timer task takes excessive time
  * to complete, it "hogs" the timer's task execution thread.  This can, in
@@ -41,26 +41,26 @@
  * execute in rapid succession when (and if) the offending task finally
  * completes.
  *
- * <p>After the last live reference to a <tt>Timer</tt> object goes away
+ * <p>After the last live reference to a {@code Timer} object goes away
  * <i>and</i> all outstanding tasks have completed execution, the timer's task
  * execution thread terminates gracefully (and becomes subject to garbage
  * collection).  However, this can take arbitrarily long to occur.  By
  * default, the task execution thread does not run as a <i>daemon thread</i>,
  * so it is capable of keeping an application from terminating.  If a caller
  * wants to terminate a timer's task execution thread rapidly, the caller
- * should invoke the timer's <tt>cancel</tt> method.
+ * should invoke the timer's {@code cancel} method.
  *
  * <p>If the timer's task execution thread terminates unexpectedly, for
- * example, because its <tt>stop</tt> method is invoked, any further
+ * example, because its {@code stop} method is invoked, any further
  * attempt to schedule a task on the timer will result in an
- * <tt>IllegalStateException</tt>, as if the timer's <tt>cancel</tt>
+ * {@code IllegalStateException}, as if the timer's {@code cancel}
  * method had been invoked.
  *
  * <p>This class is thread-safe: multiple threads can share a single
- * <tt>Timer</tt> object without the need for external synchronization.
+ * {@code Timer} object without the need for external synchronization.
  *
  * <p>This class does <i>not</i> offer real-time guarantees: it schedules
- * tasks using the <tt>Object.wait(long)</tt> method.
+ * tasks using the {@code Object.wait(long)} method.
  *
  * <p>Java 5.0 introduced the {@code java.util.concurrent} package and
  * one of the concurrency utilities therein is the {@link
@@ -115,6 +115,7 @@
      * finalizer forgetting to call it.
      */
     private final Object threadReaper = new Object() {
+        @SuppressWarnings("deprecation")
         protected void finalize() throws Throwable {
             synchronized(queue) {
                 thread.newTasksMayBeScheduled = false;
@@ -126,7 +127,7 @@
     /**
      * This ID is used to generate thread names.
      */
-    private final static AtomicInteger nextSerialNumber = new AtomicInteger(0);
+    private static final AtomicInteger nextSerialNumber = new AtomicInteger(0);
     private static int serialNumber() {
         return nextSerialNumber.getAndIncrement();
     }
@@ -188,8 +189,8 @@
      *
      * @param task  task to be scheduled.
      * @param delay delay in milliseconds before task is to be executed.
-     * @throws IllegalArgumentException if <tt>delay</tt> is negative, or
-     *         <tt>delay + System.currentTimeMillis()</tt> is negative.
+     * @throws IllegalArgumentException if {@code delay} is negative, or
+     *         {@code delay + System.currentTimeMillis()} is negative.
      * @throws IllegalStateException if task was already scheduled or
      *         cancelled, timer was cancelled, or timer thread terminated.
      * @throws NullPointerException if {@code task} is null
@@ -206,7 +207,7 @@
      *
      * @param task task to be scheduled.
      * @param time time at which task is to be executed.
-     * @throws IllegalArgumentException if <tt>time.getTime()</tt> is negative.
+     * @throws IllegalArgumentException if {@code time.getTime()} is negative.
      * @throws IllegalStateException if task was already scheduled or
      *         cancelled, timer was cancelled, or timer thread terminated.
      * @throws NullPointerException if {@code task} or {@code time} is null
@@ -226,7 +227,7 @@
      * background activity), subsequent executions will be delayed as well.
      * In the long run, the frequency of execution will generally be slightly
      * lower than the reciprocal of the specified period (assuming the system
-     * clock underlying <tt>Object.wait(long)</tt> is accurate).
+     * clock underlying {@code Object.wait(long)} is accurate).
      *
      * <p>Fixed-delay execution is appropriate for recurring activities
      * that require "smoothness."  In other words, it is appropriate for
@@ -266,7 +267,7 @@
      * background activity), subsequent executions will be delayed as well.
      * In the long run, the frequency of execution will generally be slightly
      * lower than the reciprocal of the specified period (assuming the system
-     * clock underlying <tt>Object.wait(long)</tt> is accurate).  As a
+     * clock underlying {@code Object.wait(long)} is accurate).  As a
      * consequence of the above, if the scheduled first time is in the past,
      * it is scheduled for immediate execution.
      *
@@ -305,7 +306,7 @@
      * activity), two or more executions will occur in rapid succession to
      * "catch up."  In the long run, the frequency of execution will be
      * exactly the reciprocal of the specified period (assuming the system
-     * clock underlying <tt>Object.wait(long)</tt> is accurate).
+     * clock underlying {@code Object.wait(long)} is accurate).
      *
      * <p>Fixed-rate execution is appropriate for recurring activities that
      * are sensitive to <i>absolute</i> time, such as ringing a chime every
@@ -346,7 +347,7 @@
      * activity), two or more executions will occur in rapid succession to
      * "catch up."  In the long run, the frequency of execution will be
      * exactly the reciprocal of the specified period (assuming the system
-     * clock underlying <tt>Object.wait(long)</tt> is accurate).  As a
+     * clock underlying {@code Object.wait(long)} is accurate).  As a
      * consequence of the above, if the scheduled first time is in the past,
      * then any "missed" executions will be scheduled for immediate "catch up"
      * execution.
@@ -385,7 +386,7 @@
      * in Date.getTime() format.  This method checks timer state, task state,
      * and initial execution time, but not period.
      *
-     * @throws IllegalArgumentException if <tt>time</tt> is negative.
+     * @throws IllegalArgumentException if {@code time} is negative.
      * @throws IllegalStateException if task was already scheduled or
      *         cancelled, timer was cancelled, or timer thread terminated.
      * @throws NullPointerException if {@code task} is null
@@ -454,7 +455,7 @@
      * is the number of tasks in the queue and c is the number of cancelled
      * tasks.
      *
-     * <p>Note that it is permissible to call this method from within a
+     * <p>Note that it is permissible to call this method from within
      * a task scheduled on this timer.
      *
      * @return the number of tasks removed from the queue.
diff --git a/ojluni/src/main/java/java/util/TimerTask.java b/ojluni/src/main/java/java/util/TimerTask.java
index 5750486..6703cc0 100644
--- a/ojluni/src/main/java/java/util/TimerTask.java
+++ b/ojluni/src/main/java/java/util/TimerTask.java
@@ -26,10 +26,14 @@
 package java.util;
 
 /**
- * A task that can be scheduled for one-time or repeated execution by a Timer.
+ * A task that can be scheduled for one-time or repeated execution by a
+ * {@link Timer}.
+ *
+ * <p>A timer task is <em>not</em> reusable.  Once a task has been scheduled
+ * for execution on a {@code Timer} or cancelled, subsequent attempts to
+ * schedule it for execution will throw {@code IllegalStateException}.
  *
  * @author  Josh Bloch
- * @see     Timer
  * @since   1.3
  */
 
@@ -98,7 +102,7 @@
      * will never run again.  (If the task is running when this call occurs,
      * the task will run to completion, but will never run again.)
      *
-     * <p>Note that calling this method from within the <tt>run</tt> method of
+     * <p>Note that calling this method from within the {@code run} method of
      * a repeating timer task absolutely guarantees that the timer task will
      * not run again.
      *
@@ -110,7 +114,7 @@
      *         Returns false if the task was scheduled for one-time execution
      *         and has already run, or if the task was never scheduled, or if
      *         the task was already cancelled.  (Loosely speaking, this method
-     *         returns <tt>true</tt> if it prevents one or more scheduled
+     *         returns {@code true} if it prevents one or more scheduled
      *         executions from taking place.)
      */
     public boolean cancel() {
diff --git a/ojluni/src/main/java/java/util/TooManyListenersException.java b/ojluni/src/main/java/java/util/TooManyListenersException.java
index 134dea8..9635a5c 100644
--- a/ojluni/src/main/java/java/util/TooManyListenersException.java
+++ b/ojluni/src/main/java/java/util/TooManyListenersException.java
@@ -44,7 +44,7 @@
  * @see java.util.EventListener
  *
  * @author Laurence P. G. Cable
- * @since  JDK1.1
+ * @since  1.1
  */
 
 public class TooManyListenersException extends Exception {
diff --git a/ojluni/src/main/java/java/util/TreeMap.java b/ojluni/src/main/java/java/util/TreeMap.java
index 63d7c35..8768aab 100644
--- a/ojluni/src/main/java/java/util/TreeMap.java
+++ b/ojluni/src/main/java/java/util/TreeMap.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,7 +93,7 @@
  * associated map using {@code put}.)
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <K> the type of keys maintained by this map
@@ -199,8 +199,7 @@
         comparator = m.comparator();
         try {
             buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
-        } catch (java.io.IOException cannotHappen) {
-        } catch (ClassNotFoundException cannotHappen) {
+        } catch (java.io.IOException | ClassNotFoundException cannotHappen) {
         }
     }
 
@@ -319,8 +318,7 @@
                 try {
                     buildFromSorted(mapSize, map.entrySet().iterator(),
                                     null, null);
-                } catch (java.io.IOException cannotHappen) {
-                } catch (ClassNotFoundException cannotHappen) {
+                } catch (java.io.IOException | ClassNotFoundException cannotHappen) {
                 }
                 return;
             }
@@ -645,8 +643,7 @@
         // Initialize clone with our mappings
         try {
             clone.buildFromSorted(size, entrySet().iterator(), null, null);
-        } catch (java.io.IOException cannotHappen) {
-        } catch (ClassNotFoundException cannotHappen) {
+        } catch (java.io.IOException | ClassNotFoundException cannotHappen) {
         }
 
         return clone;
@@ -867,7 +864,7 @@
      * Returns a {@link Set} view of the mappings contained in this map.
      *
      * <p>The set's iterator returns the entries in ascending key order. The
-     * sets's spliterator is
+     * set's spliterator is
      * <em><a href="Spliterator.html#binding">late-binding</a></em>,
      * <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED} and
      * {@link Spliterator#ORDERED} with an encounter order that is ascending key
@@ -1055,7 +1052,7 @@
         }
 
         public Spliterator<V> spliterator() {
-            return new ValueSpliterator<K,V>(TreeMap.this, null, null, 0, -1, 0);
+            return new ValueSpliterator<>(TreeMap.this, null, null, 0, -1, 0);
         }
     }
 
@@ -1095,7 +1092,7 @@
         }
 
         public Spliterator<Map.Entry<K,V>> spliterator() {
-            return new EntrySpliterator<K,V>(TreeMap.this, null, null, 0, -1, 0);
+            return new EntrySpliterator<>(TreeMap.this, null, null, 0, -1, 0);
         }
     }
 
@@ -2462,8 +2459,7 @@
         s.writeInt(size);
 
         // Write out keys and values (alternating)
-        for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) {
-            Map.Entry<K,V> e = i.next();
+        for (Map.Entry<K, V> e : entrySet()) {
             s.writeObject(e.getKey());
             s.writeObject(e.getValue());
         }
@@ -2494,8 +2490,7 @@
     void addAllForTreeSet(SortedSet<? extends K> set, V defaultVal) {
         try {
             buildFromSorted(set.size(), set.iterator(), null, defaultVal);
-        } catch (java.io.IOException cannotHappen) {
-        } catch (ClassNotFoundException cannotHappen) {
+        } catch (java.io.IOException | ClassNotFoundException cannotHappen) {
         }
     }
 
@@ -2620,19 +2615,17 @@
     }
 
     /**
-     * Find the level down to which to assign all nodes BLACK.  This is the
-     * last `full' level of the complete binary tree produced by
-     * buildTree. The remaining nodes are colored RED. (This makes a `nice'
-     * set of color assignments wrt future insertions.) This level number is
+     * Finds the level down to which to assign all nodes BLACK.  This is the
+     * last `full' level of the complete binary tree produced by buildTree.
+     * The remaining nodes are colored RED. (This makes a `nice' set of
+     * color assignments wrt future insertions.) This level number is
      * computed by finding the number of splits needed to reach the zeroeth
-     * node.  (The answer is ~lg(N), but in any case must be computed by same
-     * quick O(lg(N)) loop.)
+     * node.
+     *
+     * @param size the (non-negative) number of keys in the tree to be built
      */
-    private static int computeRedLevel(int sz) {
-        int level = 0;
-        for (int m = sz - 1; m >= 0; m = m / 2 - 1)
-            level++;
-        return level;
+    private static int computeRedLevel(int size) {
+        return 31 - Integer.numberOfLeadingZeros(size + 1);
     }
 
     /**
@@ -2666,11 +2659,11 @@
     }
 
     final Spliterator<K> keySpliterator() {
-        return new KeySpliterator<K,V>(this, null, null, 0, -1, 0);
+        return new KeySpliterator<>(this, null, null, 0, -1, 0);
     }
 
     final Spliterator<K> descendingKeySpliterator() {
-        return new DescendingKeySpliterator<K,V>(this, null, null, 0, -2, 0);
+        return new DescendingKeySpliterator<>(this, null, null, 0, -2, 0);
     }
 
     /**
@@ -2682,7 +2675,7 @@
      * child, also serving as origin for the split-off spliterator.
      * Left-hands are symmetric. Descending versions place the origin
      * at the end and invert ascending split rules.  This base class
-     * is non-commital about directionality, or whether the top-level
+     * is non-committal about directionality, or whether the top-level
      * spliterator covers the whole tree. This means that the actual
      * split mechanics are located in subclasses. Some of the subclass
      * trySplit methods are identical (except for return types), but
diff --git a/ojluni/src/main/java/java/util/TreeSet.java b/ojluni/src/main/java/java/util/TreeSet.java
index be215ba..faf394c 100644
--- a/ojluni/src/main/java/java/util/TreeSet.java
+++ b/ojluni/src/main/java/java/util/TreeSet.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,7 +74,7 @@
  * should be used only to detect bugs.</i>
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <E> the type of elements maintained by this set
@@ -121,7 +121,7 @@
      * {@code ClassCastException}.
      */
     public TreeSet() {
-        this(new TreeMap<E,Object>());
+        this(new TreeMap<>());
     }
 
     /**
@@ -220,7 +220,7 @@
      * 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>.
+     * {@code Objects.equals(o, e)}.
      *
      * @param o object to be checked for containment in this set
      * @return {@code true} if this set contains the specified element
@@ -238,7 +238,7 @@
      * Adds the specified element to this set if it is not already present.
      * 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>.
+     * {@code Objects.equals(e, e2)}.
      * If this set already contains the element, the call leaves the set
      * unchanged and returns {@code false}.
      *
@@ -258,7 +258,7 @@
     /**
      * Removes the specified element from this set if it is present.
      * More formally, removes an element {@code e} such that
-     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
+     * {@code Objects.equals(o, 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
diff --git a/ojluni/src/main/java/java/util/UnknownFormatConversionException.java b/ojluni/src/main/java/java/util/UnknownFormatConversionException.java
index 9ef964d..1278c6e 100644
--- a/ojluni/src/main/java/java/util/UnknownFormatConversionException.java
+++ b/ojluni/src/main/java/java/util/UnknownFormatConversionException.java
@@ -28,7 +28,7 @@
 /**
  * Unchecked exception thrown when an unknown conversion is given.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to
+ * <p> Unless otherwise specified, passing a {@code null} argument to
  * any method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/UnknownFormatFlagsException.java b/ojluni/src/main/java/java/util/UnknownFormatFlagsException.java
index 764fe6d..8549566 100644
--- a/ojluni/src/main/java/java/util/UnknownFormatFlagsException.java
+++ b/ojluni/src/main/java/java/util/UnknownFormatFlagsException.java
@@ -28,7 +28,7 @@
 /**
  * Unchecked exception thrown when an unknown flag is given.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method or constructor in this class will cause a {@link
  * NullPointerException} to be thrown.
  *
diff --git a/ojluni/src/main/java/java/util/Vector.java b/ojluni/src/main/java/java/util/Vector.java
index 6c5247c..f184437 100644
--- a/ojluni/src/main/java/java/util/Vector.java
+++ b/ojluni/src/main/java/java/util/Vector.java
@@ -68,7 +68,7 @@
  *
  * <p>As of the Java 2 platform v1.2, this class was retrofitted to
  * implement the {@link List} interface, making it a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.  Unlike the new collection
  * implementations, {@code Vector} is synchronized.  If a thread-safe
  * implementation is not needed, it is recommended to use {@link
diff --git a/ojluni/src/main/java/java/util/WeakHashMap.java b/ojluni/src/main/java/java/util/WeakHashMap.java
index 68738df..81d870b 100644
--- a/ojluni/src/main/java/java/util/WeakHashMap.java
+++ b/ojluni/src/main/java/java/util/WeakHashMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,79 +34,79 @@
 
 
 /**
- * Hash table based implementation of the <tt>Map</tt> interface, with
+ * Hash table based implementation of the {@code Map} interface, with
  * <em>weak keys</em>.
- * An entry in a <tt>WeakHashMap</tt> will automatically be removed when
+ * An entry in a {@code WeakHashMap} will automatically be removed when
  * its key is no longer in ordinary use.  More precisely, the presence of a
  * mapping for a given key will not prevent the key from being discarded by the
  * garbage collector, that is, made finalizable, finalized, and then reclaimed.
  * When a key has been discarded its entry is effectively removed from the map,
- * so this class behaves somewhat differently from other <tt>Map</tt>
+ * so this class behaves somewhat differently from other {@code Map}
  * implementations.
  *
  * <p> Both null values and the null key are supported. This class has
- * performance characteristics similar to those of the <tt>HashMap</tt>
+ * performance characteristics similar to those of the {@code HashMap}
  * class, and has the same efficiency parameters of <em>initial capacity</em>
  * and <em>load factor</em>.
  *
  * <p> Like most collection classes, this class is not synchronized.
- * A synchronized <tt>WeakHashMap</tt> may be constructed using the
+ * A synchronized {@code WeakHashMap} may be constructed using the
  * {@link Collections#synchronizedMap Collections.synchronizedMap}
  * method.
  *
  * <p> This class is intended primarily for use with key objects whose
- * <tt>equals</tt> methods test for object identity using the
- * <tt>==</tt> operator.  Once such a key is discarded it can never be
+ * {@code equals} methods test for object identity using the
+ * {@code ==} operator.  Once such a key is discarded it can never be
  * recreated, so it is impossible to do a lookup of that key in a
- * <tt>WeakHashMap</tt> at some later time and be surprised that its entry
+ * {@code WeakHashMap} at some later time and be surprised that its entry
  * has been removed.  This class will work perfectly well with key objects
- * whose <tt>equals</tt> methods are not based upon object identity, such
- * as <tt>String</tt> instances.  With such recreatable key objects,
- * however, the automatic removal of <tt>WeakHashMap</tt> entries whose
+ * whose {@code equals} methods are not based upon object identity, such
+ * as {@code String} instances.  With such recreatable key objects,
+ * however, the automatic removal of {@code WeakHashMap} entries whose
  * keys have been discarded may prove to be confusing.
  *
- * <p> The behavior of the <tt>WeakHashMap</tt> class depends in part upon
+ * <p> The behavior of the {@code WeakHashMap} class depends in part upon
  * the actions of the garbage collector, so several familiar (though not
- * required) <tt>Map</tt> invariants do not hold for this class.  Because
+ * required) {@code Map} invariants do not hold for this class.  Because
  * the garbage collector may discard keys at any time, a
- * <tt>WeakHashMap</tt> may behave as though an unknown thread is silently
+ * {@code WeakHashMap} may behave as though an unknown thread is silently
  * removing entries.  In particular, even if you synchronize on a
- * <tt>WeakHashMap</tt> instance and invoke none of its mutator methods, it
- * is possible for the <tt>size</tt> method to return smaller values over
- * time, for the <tt>isEmpty</tt> method to return <tt>false</tt> and
- * then <tt>true</tt>, for the <tt>containsKey</tt> method to return
- * <tt>true</tt> and later <tt>false</tt> for a given key, for the
- * <tt>get</tt> method to return a value for a given key but later return
- * <tt>null</tt>, for the <tt>put</tt> method to return
- * <tt>null</tt> and the <tt>remove</tt> method to return
- * <tt>false</tt> for a key that previously appeared to be in the map, and
+ * {@code WeakHashMap} instance and invoke none of its mutator methods, it
+ * is possible for the {@code size} method to return smaller values over
+ * time, for the {@code isEmpty} method to return {@code false} and
+ * then {@code true}, for the {@code containsKey} method to return
+ * {@code true} and later {@code false} for a given key, for the
+ * {@code get} method to return a value for a given key but later return
+ * {@code null}, for the {@code put} method to return
+ * {@code null} and the {@code remove} method to return
+ * {@code false} for a key that previously appeared to be in the map, and
  * for successive examinations of the key set, the value collection, and
  * the entry set to yield successively smaller numbers of elements.
  *
- * <p> Each key object in a <tt>WeakHashMap</tt> is stored indirectly as
+ * <p> Each key object in a {@code WeakHashMap} is stored indirectly as
  * the referent of a weak reference.  Therefore a key will automatically be
  * removed only after the weak references to it, both inside and outside of the
  * map, have been cleared by the garbage collector.
  *
  * <p> <strong>Implementation note:</strong> The value objects in a
- * <tt>WeakHashMap</tt> are held by ordinary strong references.  Thus care
+ * {@code WeakHashMap} are held by ordinary strong references.  Thus care
  * should be taken to ensure that value objects do not strongly refer to their
  * own keys, either directly or indirectly, since that will prevent the keys
  * from being discarded.  Note that a value object may refer indirectly to its
- * key via the <tt>WeakHashMap</tt> itself; that is, a value object may
+ * key via the {@code WeakHashMap} itself; that is, a value object may
  * strongly refer to some other key object whose associated value object, in
  * turn, strongly refers to the key of the first value object.  If the values
  * in the map do not rely on the map holding strong references to them, one way
  * to deal with this is to wrap values themselves within
- * <tt>WeakReferences</tt> before
- * inserting, as in: <tt>m.put(key, new WeakReference(value))</tt>,
- * and then unwrapping upon each <tt>get</tt>.
+ * {@code WeakReferences} before
+ * inserting, as in: {@code m.put(key, new WeakReference(value))},
+ * and then unwrapping upon each {@code get}.
  *
- * <p>The iterators returned by the <tt>iterator</tt> method of the collections
+ * <p>The iterators returned by the {@code iterator} method of the collections
  * returned by all of this class's "collection view methods" are
  * <i>fail-fast</i>: if the map is structurally modified at any time after the
  * iterator is created, in any way except through the iterator's own
- * <tt>remove</tt> method, the iterator will throw a {@link
+ * {@code remove} method, the iterator will throw a {@link
  * ConcurrentModificationException}.  Thus, in the face of concurrent
  * modification, the iterator fails quickly and cleanly, rather than risking
  * arbitrary, non-deterministic behavior at an undetermined time in the future.
@@ -114,13 +114,13 @@
  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  * as it is, generally speaking, impossible to make any hard guarantees in the
  * presence of unsynchronized concurrent modification.  Fail-fast iterators
- * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
+ * throw {@code ConcurrentModificationException} on a best-effort basis.
  * Therefore, it would be wrong to write a program that depended on this
  * exception for its correctness:  <i>the fail-fast behavior of iterators
  * should be used only to detect bugs.</i>
  *
  * <p>This class is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @param <K> the type of keys maintained by this map
@@ -196,11 +196,11 @@
     }
 
     /**
-     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
+     * Constructs a new, empty {@code WeakHashMap} with the given initial
      * capacity and the given load factor.
      *
-     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
-     * @param  loadFactor      The load factor of the <tt>WeakHashMap</tt>
+     * @param  initialCapacity The initial capacity of the {@code WeakHashMap}
+     * @param  loadFactor      The load factor of the {@code WeakHashMap}
      * @throws IllegalArgumentException if the initial capacity is negative,
      *         or if the load factor is nonpositive.
      */
@@ -223,10 +223,10 @@
     }
 
     /**
-     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
+     * Constructs a new, empty {@code WeakHashMap} with the given initial
      * capacity and the default load factor (0.75).
      *
-     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
+     * @param  initialCapacity The initial capacity of the {@code WeakHashMap}
      * @throws IllegalArgumentException if the initial capacity is negative
      */
     public WeakHashMap(int initialCapacity) {
@@ -234,7 +234,7 @@
     }
 
     /**
-     * Constructs a new, empty <tt>WeakHashMap</tt> with the default initial
+     * Constructs a new, empty {@code WeakHashMap} with the default initial
      * capacity (16) and load factor (0.75).
      */
     public WeakHashMap() {
@@ -242,8 +242,8 @@
     }
 
     /**
-     * Constructs a new <tt>WeakHashMap</tt> with the same mappings as the
-     * specified map.  The <tt>WeakHashMap</tt> is created with the default
+     * Constructs a new {@code WeakHashMap} with the same mappings as the
+     * specified map.  The {@code WeakHashMap} is created with the default
      * load factor (0.75) and an initial capacity sufficient to hold the
      * mappings in the specified map.
      *
@@ -365,7 +365,7 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map contains no key-value mappings.
+     * Returns {@code true} if this map contains no key-value mappings.
      * This result is a snapshot, and may not reflect unprocessed
      * entries that will be removed before next attempted access
      * because they are no longer referenced.
@@ -379,8 +379,9 @@
      * or {@code null} if this map contains no mapping for the key.
      *
      * <p>More formally, if this map contains a mapping from a key
-     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
-     * key.equals(k))}, then this method returns {@code v}; otherwise
+     * {@code k} to a value {@code v} such that
+     * {@code Objects.equals(key, k)},
+     * then this method returns {@code v}; otherwise
      * it returns {@code null}.  (There can be at most one such mapping.)
      *
      * <p>A return value of {@code null} does not <i>necessarily</i>
@@ -406,12 +407,12 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map contains a mapping for the
+     * Returns {@code true} if this map contains a mapping for the
      * specified key.
      *
      * @param  key   The key whose presence in this map is to be tested
-     * @return <tt>true</tt> if there is a mapping for <tt>key</tt>;
-     *         <tt>false</tt> otherwise
+     * @return {@code true} if there is a mapping for {@code key};
+     *         {@code false} otherwise
      */
     public boolean containsKey(Object key) {
         return getEntry(key) != null;
@@ -439,10 +440,10 @@
      *
      * @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 <tt>key</tt>, or
-     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
-     *         (A <tt>null</tt> return can also indicate that the map
-     *         previously associated <tt>null</tt> with <tt>key</tt>.)
+     * @return the previous value associated with {@code key}, or
+     *         {@code null} if there was no mapping for {@code key}.
+     *         (A {@code null} return can also indicate that the map
+     *         previously associated {@code null} with {@code key}.)
      */
     public V put(K key, V value) {
         Object k = maskNull(key);
@@ -568,23 +569,23 @@
 
     /**
      * Removes the mapping for a key from this weak hash map if it is present.
-     * More formally, if this map contains a mapping from key <tt>k</tt> to
-     * value <tt>v</tt> such that <code>(key==null ?  k==null :
+     * More formally, if this map contains a mapping from key {@code k} to
+     * value {@code v} such that <code>(key==null ?  k==null :
      * key.equals(k))</code>, that mapping is removed.  (The map can contain
      * at most one such mapping.)
      *
      * <p>Returns the value to which this map previously associated the key,
-     * or <tt>null</tt> if the map contained no mapping for the key.  A
-     * return value of <tt>null</tt> does not <i>necessarily</i> indicate
+     * or {@code null} if the map contained no mapping for the key.  A
+     * return value of {@code null} does not <i>necessarily</i> indicate
      * that the map contained no mapping for the key; it's also possible
-     * that the map explicitly mapped the key to <tt>null</tt>.
+     * that the map explicitly mapped the key to {@code null}.
      *
      * <p>The map will not contain a mapping for the specified key once the
      * call returns.
      *
      * @param key key whose mapping is to be removed from the map
-     * @return the previous value associated with <tt>key</tt>, or
-     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
+     * @return the previous value associated with {@code key}, or
+     *         {@code null} if there was no mapping for {@code key}
      */
     public V remove(Object key) {
         Object k = maskNull(key);
@@ -664,11 +665,11 @@
     }
 
     /**
-     * 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.
      *
      * @param value value whose presence in this map is to be tested
-     * @return <tt>true</tt> if this map maps one or more keys to the
+     * @return {@code true} if this map maps one or more keys to the
      *         specified value
      */
     public boolean containsValue(Object value) {
@@ -855,12 +856,12 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  If the map is modified
      * while an iteration over the set is in progress (except through
-     * the iterator's own <tt>remove</tt> operation), the results of
+     * the iterator's own {@code remove} operation), the results of
      * the iteration are undefined.  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>
+     * {@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.
      */
     public Set<K> keySet() {
@@ -908,13 +909,13 @@
      * The collection is backed by the map, so changes to the map are
      * reflected in the collection, and vice-versa.  If the map is
      * modified while an iteration over the collection is in progress
-     * (except through the iterator's own <tt>remove</tt> operation),
+     * (except through the iterator's own {@code remove} operation),
      * the results of the iteration are undefined.  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.
      */
     public Collection<V> values() {
         Collection<V> vs = values;
@@ -952,14 +953,14 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  If the map is modified
      * while an iteration over the set is in progress (except through
-     * the iterator's own <tt>remove</tt> operation, or through the
-     * <tt>setValue</tt> operation on a map entry returned by the
+     * the iterator's own {@code remove} operation, or through the
+     * {@code setValue} operation on a map entry returned by the
      * iterator) the results of the iteration are undefined.  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.
+     * mapping from the map, 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.
      */
     public Set<Map.Entry<K,V>> entrySet() {
         Set<Map.Entry<K,V>> es = entrySet;
@@ -1105,8 +1106,8 @@
         public KeySpliterator<K,V> trySplit() {
             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
             return (lo >= mid) ? null :
-                new KeySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
-                                        expectedModCount);
+                new KeySpliterator<>(map, lo, index = mid, est >>>= 1,
+                                     expectedModCount);
         }
 
         public void forEachRemaining(Consumer<? super K> action) {
@@ -1185,8 +1186,8 @@
         public ValueSpliterator<K,V> trySplit() {
             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
             return (lo >= mid) ? null :
-                new ValueSpliterator<K,V>(map, lo, index = mid, est >>>= 1,
-                                          expectedModCount);
+                new ValueSpliterator<>(map, lo, index = mid, est >>>= 1,
+                                       expectedModCount);
         }
 
         public void forEachRemaining(Consumer<? super V> action) {
@@ -1262,8 +1263,8 @@
         public EntrySpliterator<K,V> trySplit() {
             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
             return (lo >= mid) ? null :
-                new EntrySpliterator<K,V>(map, lo, index = mid, est >>>= 1,
-                                          expectedModCount);
+                new EntrySpliterator<>(map, lo, index = mid, est >>>= 1,
+                                       expectedModCount);
         }
 
 
@@ -1294,7 +1295,7 @@
                             @SuppressWarnings("unchecked") K k =
                                 (K) WeakHashMap.unmaskNull(x);
                             action.accept
-                                (new AbstractMap.SimpleImmutableEntry<K,V>(k, v));
+                                (new AbstractMap.SimpleImmutableEntry<>(k, v));
                         }
                     }
                 } while (p != null || i < hi);
@@ -1320,7 +1321,7 @@
                             @SuppressWarnings("unchecked") K k =
                                 (K) WeakHashMap.unmaskNull(x);
                             action.accept
-                                (new AbstractMap.SimpleImmutableEntry<K,V>(k, v));
+                                (new AbstractMap.SimpleImmutableEntry<>(k, v));
                             if (map.modCount != expectedModCount)
                                 throw new ConcurrentModificationException();
                             return true;
diff --git a/ojluni/src/main/java/java/util/concurrent/AbstractExecutorService.java b/ojluni/src/main/java/java/util/concurrent/AbstractExecutorService.java
index e4d2235..a206867 100644
--- a/ojluni/src/main/java/java/util/concurrent/AbstractExecutorService.java
+++ b/ojluni/src/main/java/java/util/concurrent/AbstractExecutorService.java
@@ -245,8 +245,7 @@
                 Future<T> f = futures.get(i);
                 if (!f.isDone()) {
                     try { f.get(); }
-                    catch (CancellationException ignore) {}
-                    catch (ExecutionException ignore) {}
+                    catch (CancellationException | ExecutionException ignore) {}
                 }
             }
             return futures;
@@ -283,8 +282,7 @@
                 Future<T> f = futures.get(j);
                 if (!f.isDone()) {
                     try { f.get(deadline - System.nanoTime(), NANOSECONDS); }
-                    catch (CancellationException ignore) {}
-                    catch (ExecutionException ignore) {}
+                    catch (CancellationException | ExecutionException ignore) {}
                     catch (TimeoutException timedOut) {
                         break timedOut;
                     }
diff --git a/ojluni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/ojluni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index 96a60b3..13fc3ce 100644
--- a/ojluni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -46,10 +46,8 @@
 import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 /**
  * A bounded {@linkplain BlockingQueue blocking queue} backed by an
@@ -74,9 +72,12 @@
  * generally decreases throughput but reduces variability and avoids
  * starvation.
  *
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
  *
  * @since 1.5
  * @author Doug Lea
@@ -85,6 +86,11 @@
 public class ArrayBlockingQueue<E> extends AbstractQueue<E>
         implements BlockingQueue<E>, java.io.Serializable {
 
+    /*
+     * Much of the implementation mechanics, especially the unusual
+     * nested loops, are shared and co-maintained with ArrayDeque.
+     */
+
     /**
      * Serialization ID. This class relies on default serialization
      * even for the items array, which is default-serialized, even if
@@ -129,10 +135,21 @@
     // Internal helper methods
 
     /**
-     * Circularly decrements array index i.
+     * Increments i, mod modulus.
+     * Precondition and postcondition: 0 <= i < modulus.
      */
-    final int dec(int i) {
-        return ((i == 0) ? items.length : i) - 1;
+    static final int inc(int i, int modulus) {
+        if (++i >= modulus) i = 0;
+        return i;
+    }
+
+    /**
+     * Decrements i, mod modulus.
+     * Precondition and postcondition: 0 <= i < modulus.
+     */
+    static final int dec(int i, int modulus) {
+        if (--i < 0) i = modulus - 1;
+        return i;
     }
 
     /**
@@ -144,14 +161,24 @@
     }
 
     /**
+     * Returns element at array index i.
+     * This is a slight abuse of generics, accepted by javac.
+     */
+    @SuppressWarnings("unchecked")
+    static <E> E itemAt(Object[] items, int i) {
+        return (E) items[i];
+    }
+
+    /**
      * Inserts element at current put position, advances, and signals.
      * Call only when holding lock.
      */
-    private void enqueue(E x) {
+    private void enqueue(E e) {
+        // assert lock.isHeldByCurrentThread();
         // assert lock.getHoldCount() == 1;
         // assert items[putIndex] == null;
         final Object[] items = this.items;
-        items[putIndex] = x;
+        items[putIndex] = e;
         if (++putIndex == items.length) putIndex = 0;
         count++;
         notEmpty.signal();
@@ -162,18 +189,19 @@
      * Call only when holding lock.
      */
     private E dequeue() {
+        // assert lock.isHeldByCurrentThread();
         // assert lock.getHoldCount() == 1;
         // assert items[takeIndex] != null;
         final Object[] items = this.items;
         @SuppressWarnings("unchecked")
-        E x = (E) items[takeIndex];
+        E e = (E) items[takeIndex];
         items[takeIndex] = null;
         if (++takeIndex == items.length) takeIndex = 0;
         count--;
         if (itrs != null)
             itrs.elementDequeued();
         notFull.signal();
-        return x;
+        return e;
     }
 
     /**
@@ -182,6 +210,7 @@
      * Call only when holding lock.
      */
     void removeAt(final int removeIndex) {
+        // assert lock.isHeldByCurrentThread();
         // assert lock.getHoldCount() == 1;
         // assert items[removeIndex] != null;
         // assert removeIndex >= 0 && removeIndex < items.length;
@@ -267,6 +296,7 @@
         final ReentrantLock lock = this.lock;
         lock.lock(); // Lock only for visibility, not mutual exclusion
         try {
+            final Object[] items = this.items;
             int i = 0;
             try {
                 for (E e : c)
@@ -481,15 +511,16 @@
         try {
             if (count > 0) {
                 final Object[] items = this.items;
-                final int putIndex = this.putIndex;
-                int i = takeIndex;
-                do {
-                    if (o.equals(items[i])) {
-                        removeAt(i);
-                        return true;
-                    }
-                    if (++i == items.length) i = 0;
-                } while (i != putIndex);
+                for (int i = takeIndex, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        if (o.equals(items[i])) {
+                            removeAt(i);
+                            return true;
+                        }
+                    if (to == end) break;
+                }
             }
             return false;
         } finally {
@@ -512,13 +543,14 @@
         try {
             if (count > 0) {
                 final Object[] items = this.items;
-                final int putIndex = this.putIndex;
-                int i = takeIndex;
-                do {
-                    if (o.equals(items[i]))
-                        return true;
-                    if (++i == items.length) i = 0;
-                } while (i != putIndex);
+                for (int i = takeIndex, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        if (o.equals(items[i]))
+                            return true;
+                    if (to == end) break;
+                }
             }
             return false;
         } finally {
@@ -625,15 +657,9 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int k = count;
-            if (k > 0) {
-                final Object[] items = this.items;
-                final int putIndex = this.putIndex;
-                int i = takeIndex;
-                do {
-                    items[i] = null;
-                    if (++i == items.length) i = 0;
-                } while (i != putIndex);
+            int k;
+            if ((k = count) > 0) {
+                circularClear(items, takeIndex, putIndex);
                 takeIndex = putIndex;
                 count = 0;
                 if (itrs != null)
@@ -647,6 +673,20 @@
     }
 
     /**
+     * Nulls out slots starting at array index i, upto index end.
+     * Condition i == end means "full" - the entire array is cleared.
+     */
+    private static void circularClear(Object[] items, int i, int end) {
+        // assert 0 <= i && i < items.length;
+        // assert 0 <= end && end < items.length;
+        for (int to = (i < end) ? end : items.length;
+             ; i = 0, to = end) {
+            for (; i < to; i++) items[i] = null;
+            if (to == end) break;
+        }
+    }
+
+    /**
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
      * @throws NullPointerException          {@inheritDoc}
@@ -678,8 +718,8 @@
             try {
                 while (i < n) {
                     @SuppressWarnings("unchecked")
-                    E x = (E) items[take];
-                    c.add(x);
+                    E e = (E) items[take];
+                    c.add(e);
                     items[take] = null;
                     if (++take == items.length) take = 0;
                     i++;
@@ -808,7 +848,7 @@
          * there is known to be at least one iterator to collect
          */
         void doSomeSweeping(boolean tryHarder) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             // assert head != null;
             int probes = tryHarder ? LONG_SWEEP_PROBES : SHORT_SWEEP_PROBES;
             Node o, p;
@@ -864,7 +904,7 @@
          * Adds a new iterator to the linked list of tracked iterators.
          */
         void register(Itr itr) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             head = new Node(itr, head);
         }
 
@@ -874,7 +914,7 @@
          * Notifies all iterators, and expunges any that are now stale.
          */
         void takeIndexWrapped() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             cycles++;
             for (Node o = null, p = head; p != null;) {
                 final Itr it = p.get();
@@ -931,7 +971,7 @@
          * clears all weak refs, and unlinks the itrs datastructure.
          */
         void queueIsEmpty() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             for (Node p = head; p != null; p = p.next) {
                 Itr it = p.get();
                 if (it != null) {
@@ -947,7 +987,7 @@
          * Called whenever an element has been dequeued (at takeIndex).
          */
         void elementDequeued() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (count == 0)
                 queueIsEmpty();
             else if (takeIndex == 0)
@@ -972,6 +1012,11 @@
      * expected element to remove, in lastItem.  Yes, we may fail to
      * remove lastItem from the queue if it moved due to an interleaved
      * interior remove while in detached mode.
+     *
+     * Method forEachRemaining, added in Java 8, is treated similarly
+     * to hasNext returning false, in that we switch to detached mode,
+     * but we regard it as an even stronger request to "close" this
+     * iteration, and don't bother supporting subsequent remove().
      */
     private class Itr implements Iterator<E> {
         /** Index to look for new nextItem; NONE at end */
@@ -1008,7 +1053,6 @@
         private static final int DETACHED = -3;
 
         Itr() {
-            // assert lock.getHoldCount() == 0;
             lastRet = NONE;
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
@@ -1041,12 +1085,12 @@
         }
 
         boolean isDetached() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             return prevTakeIndex < 0;
         }
 
         private int incCursor(int index) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (++index == items.length) index = 0;
             if (index == putIndex) index = NONE;
             return index;
@@ -1071,7 +1115,7 @@
          * operation on this iterator.  Call only from iterating thread.
          */
         private void incorporateDequeues() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             // assert itrs != null;
             // assert !isDetached();
             // assert count > 0;
@@ -1085,7 +1129,7 @@
                 final int len = items.length;
                 // how far takeIndex has advanced since the previous
                 // operation of this iterator
-                long dequeues = (cycles - prevCycles) * len
+                long dequeues = (long) (cycles - prevCycles) * len
                     + (takeIndex - prevTakeIndex);
 
                 // Check indices for invalidation
@@ -1114,7 +1158,7 @@
          */
         private void detach() {
             // Switch to detached mode
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             // assert cursor == NONE;
             // assert nextIndex < 0;
             // assert lastRet < 0 || nextItem == null;
@@ -1134,7 +1178,6 @@
          * triggered by queue modifications.
          */
         public boolean hasNext() {
-            // assert lock.getHoldCount() == 0;
             if (nextItem != null)
                 return true;
             noNext();
@@ -1164,9 +1207,8 @@
         }
 
         public E next() {
-            // assert lock.getHoldCount() == 0;
-            final E x = nextItem;
-            if (x == null)
+            final E e = nextItem;
+            if (e == null)
                 throw new NoSuchElementException();
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
@@ -1184,17 +1226,48 @@
                 } else {
                     nextIndex = NONE;
                     nextItem = null;
+                    if (lastRet == REMOVED) detach();
                 }
             } finally {
                 lock.unlock();
             }
-            return x;
+            return e;
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+            lock.lock();
+            try {
+                final E e = nextItem;
+                if (e == null) return;
+                if (!isDetached())
+                    incorporateDequeues();
+                action.accept(e);
+                if (isDetached() || cursor < 0) return;
+                final Object[] items = ArrayBlockingQueue.this.items;
+                for (int i = cursor, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        action.accept(itemAt(items, i));
+                    if (to == end) break;
+                }
+            } finally {
+                // Calling forEachRemaining is a strong hint that this
+                // iteration is surely over; supporting remove() after
+                // forEachRemaining() is more trouble than it's worth
+                cursor = nextIndex = lastRet = NONE;
+                nextItem = lastItem = null;
+                detach();
+                lock.unlock();
+            }
         }
 
         public void remove() {
-            // assert lock.getHoldCount() == 0;
             final ReentrantLock lock = ArrayBlockingQueue.this.lock;
             lock.lock();
+            // assert lock.getHoldCount() == 1;
             try {
                 if (!isDetached())
                     incorporateDequeues(); // might update lastRet or detach
@@ -1232,7 +1305,7 @@
          * from next(), as promised by returning true from hasNext().
          */
         void shutdown() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             cursor = NONE;
             if (nextIndex >= 0)
                 nextIndex = REMOVED;
@@ -1260,7 +1333,7 @@
          * @return true if this iterator should be unlinked from itrs
          */
         boolean removedAt(int removedIndex) {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (isDetached())
                 return true;
 
@@ -1285,7 +1358,7 @@
                 }
                 else if (x > removedDistance) {
                     // assert cursor != prevTakeIndex;
-                    this.cursor = cursor = dec(cursor);
+                    this.cursor = cursor = dec(cursor, len);
                 }
             }
             int lastRet = this.lastRet;
@@ -1294,7 +1367,7 @@
                 if (x == removedDistance)
                     this.lastRet = lastRet = REMOVED;
                 else if (x > removedDistance)
-                    this.lastRet = lastRet = dec(lastRet);
+                    this.lastRet = lastRet = dec(lastRet, len);
             }
             int nextIndex = this.nextIndex;
             if (nextIndex >= 0) {
@@ -1302,7 +1375,7 @@
                 if (x == removedDistance)
                     this.nextIndex = nextIndex = REMOVED;
                 else if (x > removedDistance)
-                    this.nextIndex = nextIndex = dec(nextIndex);
+                    this.nextIndex = nextIndex = dec(nextIndex, len);
             }
             if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
                 this.prevTakeIndex = DETACHED;
@@ -1317,7 +1390,7 @@
          * @return true if this iterator should be unlinked from itrs
          */
         boolean takeIndexWrapped() {
-            // assert lock.getHoldCount() == 1;
+            // assert lock.isHeldByCurrentThread();
             if (isDetached())
                 return true;
             if (itrs.cycles - prevCycles > 1) {
@@ -1366,4 +1439,197 @@
                     Spliterator.CONCURRENT));
     }
 
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            if (count > 0) {
+                final Object[] items = this.items;
+                for (int i = takeIndex, end = putIndex,
+                         to = (i < end) ? end : items.length;
+                     ; i = 0, to = end) {
+                    for (; i < to; i++)
+                        action.accept(itemAt(items, i));
+                    if (to == end) break;
+                }
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    /** Implementation of bulk remove methods. */
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            if (itrs == null) { // check for active iterators
+                if (count > 0) {
+                    final Object[] items = this.items;
+                    // Optimize for initial run of survivors
+                    for (int i = takeIndex, end = putIndex,
+                             to = (i < end) ? end : items.length;
+                         ; i = 0, to = end) {
+                        for (; i < to; i++)
+                            if (filter.test(itemAt(items, i)))
+                                return bulkRemoveModified(filter, i);
+                        if (to == end) break;
+                    }
+                }
+                return false;
+            }
+        } finally {
+            lock.unlock();
+        }
+        // Active iterators are too hairy!
+        // Punting (for now) to the slow n^2 algorithm ...
+        return super.removeIf(filter);
+    }
+
+    // A tiny bit set implementation
+
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
+    }
+
+    /**
+     * Returns circular distance from i to j, disambiguating i == j to
+     * items.length; never returns 0.
+     */
+    private int distanceNonEmpty(int i, int j) {
+        if ((j -= i) <= 0) j += items.length;
+        return j;
+    }
+
+    /**
+     * Helper for bulkRemove, in case of at least one deletion.
+     * Tolerate predicates that reentrantly access the collection for
+     * read (but not write), so traverse once to find elements to
+     * delete, a second pass to physically expunge.
+     *
+     * @param beg valid index of first element to be deleted
+     */
+    private boolean bulkRemoveModified(
+        Predicate<? super E> filter, final int beg) {
+        final Object[] es = items;
+        final int capacity = items.length;
+        final int end = putIndex;
+        final long[] deathRow = nBits(distanceNonEmpty(beg, putIndex));
+        deathRow[0] = 1L;   // set bit 0
+        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
+             ; i = 0, to = end, k -= capacity) {
+            for (; i < to; i++)
+                if (filter.test(itemAt(es, i)))
+                    setBit(deathRow, i - k);
+            if (to == end) break;
+        }
+        // a two-finger traversal, with hare i reading, tortoise w writing
+        int w = beg;
+        for (int i = beg + 1, to = (i <= end) ? end : es.length, k = beg;
+             ; w = 0) { // w rejoins i on second leg
+            // In this loop, i and w are on the same leg, with i > w
+            for (; i < to; i++)
+                if (isClear(deathRow, i - k))
+                    es[w++] = es[i];
+            if (to == end) break;
+            // In this loop, w is on the first leg, i on the second
+            for (i = 0, to = end, k -= capacity; i < to && w < capacity; i++)
+                if (isClear(deathRow, i - k))
+                    es[w++] = es[i];
+            if (i >= to) {
+                if (w == capacity) w = 0; // "corner" case
+                break;
+            }
+        }
+        count -= distanceNonEmpty(w, end);
+        circularClear(es, putIndex = w, end);
+        return true;
+    }
+
+    /** debugging */
+    void checkInvariants() {
+        // meta-assertions
+        // assert lock.isHeldByCurrentThread();
+        if (!invariantsSatisfied()) {
+            String detail = String.format(
+                "takeIndex=%d putIndex=%d count=%d capacity=%d items=%s",
+                takeIndex, putIndex, count, items.length,
+                Arrays.toString(items));
+            System.err.println(detail);
+            throw new AssertionError(detail);
+        }
+    }
+
+    private boolean invariantsSatisfied() {
+        // Unlike ArrayDeque, we have a count field but no spare slot.
+        // We prefer ArrayDeque's strategy (and the names of its fields!),
+        // but our field layout is baked into the serial form, and so is
+        // too annoying to change.
+        //
+        // putIndex == takeIndex must be disambiguated by checking count.
+        int capacity = items.length;
+        return capacity > 0
+            && items.getClass() == Object[].class
+            && (takeIndex | putIndex | count) >= 0
+            && takeIndex <  capacity
+            && putIndex  <  capacity
+            && count     <= capacity
+            && (putIndex - takeIndex - count) % capacity == 0
+            && (count == 0 || items[takeIndex] != null)
+            && (count == capacity || items[putIndex] == null)
+            && (count == 0 || items[dec(putIndex, capacity)] != null);
+    }
+
+    /**
+     * Reconstitutes this queue from a stream (that is, deserializes it).
+     *
+     * @param s the stream
+     * @throws ClassNotFoundException if the class of a serialized object
+     *         could not be found
+     * @throws java.io.InvalidObjectException if invariants are violated
+     * @throws java.io.IOException if an I/O error occurs
+     */
+    private void readObject(java.io.ObjectInputStream s)
+        throws java.io.IOException, ClassNotFoundException {
+
+        // Read in items array and various fields
+        s.defaultReadObject();
+
+        if (!invariantsSatisfied())
+            throw new java.io.InvalidObjectException("invariants violated");
+    }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java b/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java
index da1a4fd..8043510 100644
--- a/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java
+++ b/ojluni/src/main/java/java/util/concurrent/BlockingDeque.java
@@ -39,10 +39,6 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
-// BEGIN android-note
-// fixed framework docs link to "Collection#optional"
-// END android-note
-
 /**
  * A {@link Deque} that additionally supports blocking operations that wait
  * for the deque to become non-empty when retrieving an element, and wait for
@@ -57,69 +53,69 @@
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
  *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <table class="plain">
  * <caption>Summary of BlockingDeque methods</caption>
  *  <tr>
- *    <td ALIGN=CENTER COLSPAN = 5> <b>First Element (Head)</b></td>
+ *    <th id="First" colspan="5"> First Element (Head)</th>
  *  </tr>
  *  <tr>
  *    <td></td>
- *    <td ALIGN=CENTER><em>Throws exception</em></td>
- *    <td ALIGN=CENTER><em>Special value</em></td>
- *    <td ALIGN=CENTER><em>Blocks</em></td>
- *    <td ALIGN=CENTER><em>Times out</em></td>
+ *    <th id="FThrow" style="font-weight:normal; font-style: italic">Throws exception</th>
+ *    <th id="FValue" style="font-weight:normal; font-style: italic">Special value</th>
+ *    <th id="FBlock" style="font-weight:normal; font-style: italic">Blocks</th>
+ *    <th id="FTimes" style="font-weight:normal; font-style: italic">Times out</th>
  *  </tr>
  *  <tr>
- *    <td><b>Insert</b></td>
- *    <td>{@link #addFirst addFirst(e)}</td>
- *    <td>{@link #offerFirst(Object) offerFirst(e)}</td>
- *    <td>{@link #putFirst putFirst(e)}</td>
- *    <td>{@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)}</td>
+ *    <th id="FInsert" style="text-align:left">Insert</th>
+ *    <td headers="First FInsert FThrow">{@link #addFirst(Object) addFirst(e)}</td>
+ *    <td headers="First FInsert FValue">{@link #offerFirst(Object) offerFirst(e)}</td>
+ *    <td headers="First FInsert FBlock">{@link #putFirst(Object) putFirst(e)}</td>
+ *    <td headers="First FInsert FTimes">{@link #offerFirst(Object, long, TimeUnit) offerFirst(e, time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Remove</b></td>
- *    <td>{@link #removeFirst removeFirst()}</td>
- *    <td>{@link #pollFirst pollFirst()}</td>
- *    <td>{@link #takeFirst takeFirst()}</td>
- *    <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
+ *    <th id="FRemove" style="text-align:left">Remove</th>
+ *    <td headers="First FRemove FThrow">{@link #removeFirst() removeFirst()}</td>
+ *    <td headers="First FRemove FValue">{@link #pollFirst() pollFirst()}</td>
+ *    <td headers="First FRemove FBlock">{@link #takeFirst() takeFirst()}</td>
+ *    <td headers="First FRemove FTimes">{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Examine</b></td>
- *    <td>{@link #getFirst getFirst()}</td>
- *    <td>{@link #peekFirst peekFirst()}</td>
- *    <td><em>not applicable</em></td>
- *    <td><em>not applicable</em></td>
+ *    <th id="FExamine" style="text-align:left">Examine</th>
+ *    <td headers="First FExamine FThrow">{@link #getFirst() getFirst()}</td>
+ *    <td headers="First FExamine FValue">{@link #peekFirst() peekFirst()}</td>
+ *    <td headers="First FExamine FBlock" style="font-style:italic">not applicable</td>
+ *    <td headers="First FExamine FTimes" style="font-style:italic">not applicable</td>
  *  </tr>
  *  <tr>
- *    <td ALIGN=CENTER COLSPAN = 5> <b>Last Element (Tail)</b></td>
+ *    <th id="Last" colspan="5"> Last Element (Tail)</th>
  *  </tr>
  *  <tr>
  *    <td></td>
- *    <td ALIGN=CENTER><em>Throws exception</em></td>
- *    <td ALIGN=CENTER><em>Special value</em></td>
- *    <td ALIGN=CENTER><em>Blocks</em></td>
- *    <td ALIGN=CENTER><em>Times out</em></td>
+ *    <th id="LThrow" style="font-weight:normal; font-style: italic">Throws exception</th>
+ *    <th id="LValue" style="font-weight:normal; font-style: italic">Special value</th>
+ *    <th id="LBlock" style="font-weight:normal; font-style: italic">Blocks</th>
+ *    <th id="LTimes" style="font-weight:normal; font-style: italic">Times out</th>
  *  </tr>
  *  <tr>
- *    <td><b>Insert</b></td>
- *    <td>{@link #addLast addLast(e)}</td>
- *    <td>{@link #offerLast(Object) offerLast(e)}</td>
- *    <td>{@link #putLast putLast(e)}</td>
- *    <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
+ *    <th id="LInsert" style="text-align:left">Insert</th>
+ *    <td headers="Last LInsert LThrow">{@link #addLast(Object) addLast(e)}</td>
+ *    <td headers="Last LInsert LValue">{@link #offerLast(Object) offerLast(e)}</td>
+ *    <td headers="Last LInsert LBlock">{@link #putLast(Object) putLast(e)}</td>
+ *    <td headers="Last LInsert LTimes">{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Remove</b></td>
- *    <td>{@link #removeLast() removeLast()}</td>
- *    <td>{@link #pollLast() pollLast()}</td>
- *    <td>{@link #takeLast takeLast()}</td>
- *    <td>{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td>
+ *    <th id="LRemove" style="text-align:left">Remove</th>
+ *    <td headers="Last LRemove LThrow">{@link #removeLast() removeLast()}</td>
+ *    <td headers="Last LRemove LValue">{@link #pollLast() pollLast()}</td>
+ *    <td headers="Last LRemove LBlock">{@link #takeLast() takeLast()}</td>
+ *    <td headers="Last LRemove LTimes">{@link #pollLast(long, TimeUnit) pollLast(time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Examine</b></td>
- *    <td>{@link #getLast getLast()}</td>
- *    <td>{@link #peekLast peekLast()}</td>
- *    <td><em>not applicable</em></td>
- *    <td><em>not applicable</em></td>
+ *    <th id="LExamine" style="text-align:left">Examine</th>
+ *    <td headers="Last LExamine LThrow">{@link #getLast() getLast()}</td>
+ *    <td headers="Last LExamine LValue">{@link #peekLast() peekLast()}</td>
+ *    <td headers="Last LExamine LBlock" style="font-style:italic">not applicable</td>
+ *    <td headers="Last LExamine LTimes" style="font-style:italic">not applicable</td>
  *  </tr>
  * </table>
  *
@@ -132,60 +128,55 @@
  * {@code BlockingQueue} interface are precisely equivalent to
  * {@code BlockingDeque} methods as indicated in the following table:
  *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <table class="plain">
  * <caption>Comparison of BlockingQueue and BlockingDeque methods</caption>
  *  <tr>
- *    <td ALIGN=CENTER> <b>{@code BlockingQueue} Method</b></td>
- *    <td ALIGN=CENTER> <b>Equivalent {@code BlockingDeque} Method</b></td>
+ *    <td></td>
+ *    <th id="BQueue"> {@code BlockingQueue} Method</th>
+ *    <th id="BDeque"> Equivalent {@code BlockingDeque} Method</th>
  *  </tr>
  *  <tr>
- *    <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
+ *    <th id="Insert" rowspan="4" style="text-align:left; vertical-align:top">Insert</th>
+ *    <th id="add" style="font-weight:normal; text-align:left">{@link #add(Object) add(e)}</th>
+ *    <td headers="Insert BDeque add">{@link #addLast(Object) addLast(e)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #add(Object) add(e)}</td>
- *    <td>{@link #addLast(Object) addLast(e)}</td>
+ *    <th id="offer1" style="font-weight:normal; text-align:left">{@link #offer(Object) offer(e)}</th>
+ *    <td headers="Insert BDeque offer1">{@link #offerLast(Object) offerLast(e)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #offer(Object) offer(e)}</td>
- *    <td>{@link #offerLast(Object) offerLast(e)}</td>
+ *    <th id="put" style="font-weight:normal; text-align:left">{@link #put(Object) put(e)}</th>
+ *    <td headers="Insert BDeque put">{@link #putLast(Object) putLast(e)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #put(Object) put(e)}</td>
- *    <td>{@link #putLast(Object) putLast(e)}</td>
+ *    <th id="offer2" style="font-weight:normal; text-align:left">{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</th>
+ *    <td headers="Insert BDeque offer2">{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
- *    <td>{@link #offerLast(Object, long, TimeUnit) offerLast(e, time, unit)}</td>
+ *    <th id="Remove" rowspan="4" style="text-align:left; vertical-align:top">Remove</th>
+ *    <th id="remove" style="font-weight:normal; text-align:left">{@link #remove() remove()}</th>
+ *    <td headers="Remove BDeque remove">{@link #removeFirst() removeFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td ALIGN=CENTER COLSPAN = 2> <b>Remove</b></td>
+ *    <th id="poll1" style="font-weight:normal; text-align:left">{@link #poll() poll()}</th>
+ *    <td headers="Remove BDeque poll1">{@link #pollFirst() pollFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #remove() remove()}</td>
- *    <td>{@link #removeFirst() removeFirst()}</td>
+ *    <th id="take" style="font-weight:normal; text-align:left">{@link #take() take()}</th>
+ *    <td headers="Remove BDeque take">{@link #takeFirst() takeFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #poll() poll()}</td>
- *    <td>{@link #pollFirst() pollFirst()}</td>
+ *    <th id="poll2" style="font-weight:normal; text-align:left">{@link #poll(long, TimeUnit) poll(time, unit)}</th>
+ *    <td headers="Remove BDeque poll2">{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #take() take()}</td>
- *    <td>{@link #takeFirst() takeFirst()}</td>
+ *    <th id="Examine" rowspan="2" style="text-align:left; vertical-align:top">Examine</th>
+ *    <th id="element" style="font-weight:normal; text-align:left">{@link #element() element()}</th>
+ *    <td headers="Examine BDeque element">{@link #getFirst() getFirst()}</td>
  *  </tr>
  *  <tr>
- *    <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
- *    <td>{@link #pollFirst(long, TimeUnit) pollFirst(time, unit)}</td>
- *  </tr>
- *  <tr>
- *    <td ALIGN=CENTER COLSPAN = 2> <b>Examine</b></td>
- *  </tr>
- *  <tr>
- *    <td>{@link #element() element()}</td>
- *    <td>{@link #getFirst() getFirst()}</td>
- *  </tr>
- *  <tr>
- *    <td>{@link #peek() peek()}</td>
- *    <td>{@link #peekFirst() peekFirst()}</td>
+ *    <th id="peek" style="font-weight:normal; text-align:left">{@link #peek() peek()}</th>
+ *    <td headers="Examine BDeque peek">{@link #peekFirst() peekFirst()}</td>
  *  </tr>
  * </table>
  *
@@ -197,7 +188,7 @@
  * the {@code BlockingDeque} in another thread.
  *
  * <p>This interface is a member of the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/index.html">
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
  * Java Collections Framework</a>.
  *
  * @since 1.6
@@ -408,9 +399,9 @@
      * @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>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeFirstOccurrence(Object o);
 
@@ -426,9 +417,9 @@
      * @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>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean removeLastOccurrence(Object o);
 
@@ -516,7 +507,7 @@
     /**
      * Retrieves and removes the head of the queue represented by this deque
      * (in other words, the first element of this deque).
-     * This method differs from {@link #poll poll} only in that it
+     * This method differs from {@link #poll() poll()} only in that it
      * throws an exception if this deque is empty.
      *
      * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
@@ -567,7 +558,7 @@
     /**
      * Retrieves, but does not remove, the head of the queue represented by
      * this deque (in other words, the first element of this deque).
-     * This method differs from {@link #peek peek} only in that it throws an
+     * This method differs from {@link #peek() peek} only in that it throws an
      * exception if this deque is empty.
      *
      * <p>This method is equivalent to {@link #getFirst() getFirst}.
@@ -603,9 +594,9 @@
      * @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>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object o);
 
@@ -618,9 +609,9 @@
      * @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>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean contains(Object o);
 
diff --git a/ojluni/src/main/java/java/util/concurrent/BlockingQueue.java b/ojluni/src/main/java/java/util/concurrent/BlockingQueue.java
index 6f01b77..ec7593d 100644
--- a/ojluni/src/main/java/java/util/concurrent/BlockingQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/BlockingQueue.java
@@ -38,16 +38,10 @@
 import java.util.Collection;
 import java.util.Queue;
 
-// BEGIN android-note
-// removed link to collections framework docs from header
-// fixed framework docs link to "Collection#optional"
-// END android-note
-
 /**
- * A {@link java.util.Queue} that additionally supports operations
- * that wait for the queue to become non-empty when retrieving an
- * element, and wait for space to become available in the queue when
- * storing an element.
+ * A {@link Queue} that additionally supports operations that wait for
+ * the queue to become non-empty when retrieving an element, and wait
+ * for space to become available in the queue when storing an element.
  *
  * <p>{@code BlockingQueue} methods come in four forms, with different ways
  * of handling operations that cannot be satisfied immediately, but may be
@@ -58,35 +52,35 @@
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
  *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ * <table class="plain">
  * <caption>Summary of BlockingQueue methods</caption>
  *  <tr>
  *    <td></td>
- *    <td ALIGN=CENTER><em>Throws exception</em></td>
- *    <td ALIGN=CENTER><em>Special value</em></td>
- *    <td ALIGN=CENTER><em>Blocks</em></td>
- *    <td ALIGN=CENTER><em>Times out</em></td>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Throws exception</th>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Special value</th>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Blocks</th>
+ *    <th scope="col" style="font-weight:normal; font-style:italic">Times out</th>
  *  </tr>
  *  <tr>
- *    <td><b>Insert</b></td>
- *    <td>{@link #add add(e)}</td>
- *    <td>{@link #offer offer(e)}</td>
- *    <td>{@link #put put(e)}</td>
+ *    <th scope="row" style="text-align:left">Insert</th>
+ *    <td>{@link #add(Object) add(e)}</td>
+ *    <td>{@link #offer(Object) offer(e)}</td>
+ *    <td>{@link #put(Object) put(e)}</td>
  *    <td>{@link #offer(Object, long, TimeUnit) offer(e, time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Remove</b></td>
- *    <td>{@link #remove remove()}</td>
- *    <td>{@link #poll poll()}</td>
- *    <td>{@link #take take()}</td>
+ *    <th scope="row" style="text-align:left">Remove</th>
+ *    <td>{@link #remove() remove()}</td>
+ *    <td>{@link #poll() poll()}</td>
+ *    <td>{@link #take() take()}</td>
  *    <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
  *  </tr>
  *  <tr>
- *    <td><b>Examine</b></td>
- *    <td>{@link #element element()}</td>
- *    <td>{@link #peek peek()}</td>
- *    <td><em>not applicable</em></td>
- *    <td><em>not applicable</em></td>
+ *    <th scope="row" style="text-align:left">Examine</th>
+ *    <td>{@link #element() element()}</td>
+ *    <td>{@link #peek() peek()}</td>
+ *    <td style="font-style: italic">not applicable</td>
+ *    <td style="font-style: italic">not applicable</td>
  *  </tr>
  * </table>
  *
@@ -104,7 +98,7 @@
  *
  * <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
+ * the {@link Collection} interface.  So, for example, it is
  * possible to remove an arbitrary element from a queue using
  * {@code remove(x)}. However, such operations are in general
  * <em>not</em> performed very efficiently, and are intended for only
@@ -174,6 +168,10 @@
  * actions subsequent to the access or removal of that element from
  * the {@code BlockingQueue} in another thread.
  *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this queue
@@ -304,9 +302,9 @@
      * @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>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object o);
 
@@ -319,9 +317,9 @@
      * @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>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified element is null
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean contains(Object o);
 
diff --git a/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java b/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java
index e98e1be..936ffc3 100644
--- a/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java
+++ b/ojluni/src/main/java/java/util/concurrent/CompletableFuture.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.locks.LockSupport;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
@@ -110,9 +112,9 @@
  * in a {@link NullPointerException} being thrown.
  *
  * @author Doug Lea
- * @since 1.8
  * @param <T> The result type returned by this future's {@code join}
  * and {@code get} methods
+ * @since 1.8
  */
 public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
 
@@ -125,26 +127,29 @@
      * applies across normal vs exceptional outcomes, sync vs async
      * actions, binary triggers, and various forms of completions.
      *
-     * Non-nullness of field result (set via CAS) indicates done.  An
-     * AltResult is used to box null as a result, as well as to hold
-     * exceptions.  Using a single field makes completion simple to
-     * detect and trigger.  Encoding and decoding is straightforward
-     * but adds to the sprawl of trapping and associating exceptions
-     * with targets.  Minor simplifications rely on (static) NIL (to
-     * box null results) being the only AltResult with a null
-     * exception field, so we don't usually need explicit comparisons.
-     * Even though some of the generics casts are unchecked (see
-     * SuppressWarnings annotations), they are placed to be
-     * appropriate even if checked.
+     * Non-nullness of volatile field "result" indicates done.  It may
+     * be set directly if known to be thread-confined, else via CAS.
+     * An AltResult is used to box null as a result, as well as to
+     * hold exceptions.  Using a single field makes completion simple
+     * to detect and trigger.  Result encoding and decoding is
+     * straightforward but tedious and adds to the sprawl of trapping
+     * and associating exceptions with targets.  Minor simplifications
+     * rely on (static) NIL (to box null results) being the only
+     * AltResult with a null exception field, so we don't usually need
+     * explicit comparisons.  Even though some of the generics casts
+     * are unchecked (see SuppressWarnings annotations), they are
+     * placed to be appropriate even if checked.
      *
      * Dependent actions are represented by Completion objects linked
      * as Treiber stacks headed by field "stack". There are Completion
-     * classes for each kind of action, grouped into single-input
-     * (UniCompletion), two-input (BiCompletion), projected
-     * (BiCompletions using either (not both) of two inputs), shared
-     * (CoCompletion, used by the second of two sources), zero-input
-     * source actions, and Signallers that unblock waiters. Class
-     * Completion extends ForkJoinTask to enable async execution
+     * classes for each kind of action, grouped into:
+     * - single-input (UniCompletion),
+     * - two-input (BiCompletion),
+     * - projected (BiCompletions using exactly one of two inputs),
+     * - shared (CoCompletion, used by the second of two sources),
+     * - zero-input source actions,
+     * - Signallers that unblock waiters.
+     * Class Completion extends ForkJoinTask to enable async execution
      * (adding no space overhead because we exploit its "tag" methods
      * to maintain claims). It is also declared as Runnable to allow
      * usage with arbitrary executors.
@@ -160,7 +165,7 @@
      *   encounter layers of adapters in common usages.
      *
      * * Boolean CompletableFuture method x(...) (for example
-     *   uniApply) takes all of the arguments needed to check that an
+     *   biApply) takes all of the arguments needed to check that an
      *   action is triggerable, and then either runs the action or
      *   arranges its async execution by executing its Completion
      *   argument, if present. The method returns true if known to be
@@ -170,24 +175,32 @@
      *   method with its held arguments, and on success cleans up.
      *   The mode argument allows tryFire to be called twice (SYNC,
      *   then ASYNC); the first to screen and trap exceptions while
-     *   arranging to execute, and the second when called from a
-     *   task. (A few classes are not used async so take slightly
-     *   different forms.)  The claim() callback suppresses function
-     *   invocation if already claimed by another thread.
+     *   arranging to execute, and the second when called from a task.
+     *   (A few classes are not used async so take slightly different
+     *   forms.)  The claim() callback suppresses function invocation
+     *   if already claimed by another thread.
+     *
+     * * Some classes (for example UniApply) have separate handling
+     *   code for when known to be thread-confined ("now" methods) and
+     *   for when shared (in tryFire), for efficiency.
      *
      * * CompletableFuture method xStage(...) is called from a public
-     *   stage method of CompletableFuture x. It screens user
+     *   stage method of CompletableFuture f. It screens user
      *   arguments and invokes and/or creates the stage object.  If
-     *   not async and x is already complete, the action is run
-     *   immediately.  Otherwise a Completion c is created, pushed to
-     *   x's stack (unless done), and started or triggered via
-     *   c.tryFire.  This also covers races possible if x completes
-     *   while pushing.  Classes with two inputs (for example BiApply)
-     *   deal with races across both while pushing actions.  The
-     *   second completion is a CoCompletion pointing to the first,
-     *   shared so that at most one performs the action.  The
-     *   multiple-arity methods allOf and anyOf do this pairwise to
-     *   form trees of completions.
+     *   not async and already triggerable, the action is run
+     *   immediately.  Otherwise a Completion c is created, and
+     *   submitted to the executor if triggerable, or pushed onto f's
+     *   stack if not.  Completion actions are started via c.tryFire.
+     *   We recheck after pushing to a source future's stack to cover
+     *   possible races if the source completes while pushing.
+     *   Classes with two inputs (for example BiApply) deal with races
+     *   across both while pushing actions.  The second completion is
+     *   a CoCompletion pointing to the first, shared so that at most
+     *   one performs the action.  The multiple-arity methods allOf
+     *   does this pairwise to form trees of completions.  Method
+     *   anyOf is handled differently from allOf because completion of
+     *   any source should trigger a cleanStack of other sources.
+     *   Each AnyOf completion can reach others via a shared array.
      *
      * Note that the generic type parameters of methods vary according
      * to whether "this" is a source, dependent, or completion.
@@ -212,29 +225,30 @@
      * pointing back to its sources. So we null out fields as soon as
      * possible.  The screening checks needed anyway harmlessly ignore
      * null arguments that may have been obtained during races with
-     * threads nulling out fields.  We also try to unlink fired
-     * Completions from stacks that might never be popped (see method
-     * postFire).  Completion fields need not be declared as final or
-     * volatile because they are only visible to other threads upon
-     * safe publication.
+     * threads nulling out fields.  We also try to unlink non-isLive
+     * (fired or cancelled) Completions from stacks that might
+     * otherwise never be popped: Method cleanStack always unlinks non
+     * isLive completions from the head of stack; others may
+     * occasionally remain if racing with other cancellations or
+     * removals.
+     *
+     * Completion fields need not be declared as final or volatile
+     * because they are only visible to other threads upon safe
+     * publication.
      */
 
     volatile Object result;       // Either the result or boxed AltResult
     volatile Completion stack;    // Top of Treiber stack of dependent actions
 
     final boolean internalComplete(Object r) { // CAS from null to r
-        return U.compareAndSwapObject(this, RESULT, null, r);
-    }
-
-    final boolean casStack(Completion cmp, Completion val) {
-        return U.compareAndSwapObject(this, STACK, cmp, val);
+        return RESULT.compareAndSet(this, null, r);
     }
 
     /** Returns true if successfully pushed c onto stack. */
     final boolean tryPushStack(Completion c) {
         Completion h = stack;
-        lazySetNext(c, h);
-        return U.compareAndSwapObject(this, STACK, h, c);
+        NEXT.set(c, h);         // CAS piggyback
+        return STACK.compareAndSet(this, h, c);
     }
 
     /** Unconditionally pushes c onto stack, retrying if necessary. */
@@ -254,8 +268,7 @@
 
     /** Completes with the null value, unless already completed. */
     final boolean completeNull() {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      NIL);
+        return RESULT.compareAndSet(this, null, NIL);
     }
 
     /** Returns the encoding of the given non-exceptional value. */
@@ -265,8 +278,7 @@
 
     /** Completes with a non-exceptional result, unless already completed. */
     final boolean completeValue(T t) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      (t == null) ? NIL : t);
+        return RESULT.compareAndSet(this, null, (t == null) ? NIL : t);
     }
 
     /**
@@ -280,8 +292,7 @@
 
     /** Completes with an exceptional result, unless already completed. */
     final boolean completeThrowable(Throwable x) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeThrowable(x));
+        return RESULT.compareAndSet(this, null, encodeThrowable(x));
     }
 
     /**
@@ -308,8 +319,7 @@
      * existing CompletionException.
      */
     final boolean completeThrowable(Throwable x, Object r) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeThrowable(x, r));
+        return RESULT.compareAndSet(this, null, encodeThrowable(x, r));
     }
 
     /**
@@ -327,10 +337,11 @@
      */
     static Object encodeRelay(Object r) {
         Throwable x;
-        return (((r instanceof AltResult) &&
-                 (x = ((AltResult)r).ex) != null &&
-                 !(x instanceof CompletionException)) ?
-                new AltResult(new CompletionException(x)) : r);
+        if (r instanceof AltResult
+            && (x = ((AltResult)r).ex) != null
+            && !(x instanceof CompletionException))
+            r = new AltResult(new CompletionException(x));
+        return r;
     }
 
     /**
@@ -338,14 +349,13 @@
      * If exceptional, r is first coerced to a CompletionException.
      */
     final boolean completeRelay(Object r) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeRelay(r));
+        return RESULT.compareAndSet(this, null, encodeRelay(r));
     }
 
     /**
      * Reports result using Future.get conventions.
      */
-    private static <T> T reportGet(Object r)
+    private static Object reportGet(Object r)
         throws InterruptedException, ExecutionException {
         if (r == null) // by convention below, null means interrupted
             throw new InterruptedException();
@@ -360,14 +370,13 @@
                 x = cause;
             throw new ExecutionException(x);
         }
-        @SuppressWarnings("unchecked") T t = (T) r;
-        return t;
+        return r;
     }
 
     /**
      * Decodes outcome to return result or throw unchecked exception.
      */
-    private static <T> T reportJoin(Object r) {
+    private static Object reportJoin(Object r) {
         if (r instanceof AltResult) {
             Throwable x;
             if ((x = ((AltResult)r).ex) == null)
@@ -378,8 +387,7 @@
                 throw (CompletionException)x;
             throw new CompletionException(x);
         }
-        @SuppressWarnings("unchecked") T t = (T) r;
-        return t;
+        return r;
     }
 
     /* ------------- Async task preliminaries -------------- */
@@ -425,12 +433,6 @@
     static final int ASYNC  =  1;
     static final int NESTED = -1;
 
-    /**
-     * Spins before blocking in waitingGet
-     */
-    static final int SPINS = (Runtime.getRuntime().availableProcessors() > 1 ?
-                              1 << 8 : 0);
-
     /* ------------- Base Completion classes and operations -------------- */
 
     @SuppressWarnings("serial")
@@ -455,10 +457,6 @@
         public final void setRawResult(Void v) {}
     }
 
-    static void lazySetNext(Completion c, Completion next) {
-        U.putOrderedObject(c, NEXT, next);
-    }
-
     /**
      * Pops and tries to trigger all reachable dependents.  Call only
      * when known to be done.
@@ -473,40 +471,47 @@
         while ((h = f.stack) != null ||
                (f != this && (h = (f = this).stack) != null)) {
             CompletableFuture<?> d; Completion t;
-            if (f.casStack(h, t = h.next)) {
+            if (STACK.compareAndSet(f, h, t = h.next)) {
                 if (t != null) {
                     if (f != this) {
                         pushStack(h);
                         continue;
                     }
-                    h.next = null;    // detach
+                    NEXT.compareAndSet(h, t, null); // try to detach
                 }
                 f = (d = h.tryFire(NESTED)) == null ? this : d;
             }
         }
     }
 
-    /** Traverses stack and unlinks dead Completions. */
+    /** Traverses stack and unlinks one or more dead Completions, if found. */
     final void cleanStack() {
-        for (Completion p = null, q = stack; q != null;) {
+        Completion p = stack;
+        // ensure head of stack live
+        for (boolean unlinked = false;;) {
+            if (p == null)
+                return;
+            else if (p.isLive()) {
+                if (unlinked)
+                    return;
+                else
+                    break;
+            }
+            else if (STACK.weakCompareAndSet(this, p, (p = p.next)))
+                unlinked = true;
+            else
+                p = stack;
+        }
+        // try to unlink first non-live
+        for (Completion q = p.next; q != null;) {
             Completion s = q.next;
             if (q.isLive()) {
                 p = q;
                 q = s;
-            }
-            else if (p == null) {
-                casStack(q, s);
-                q = stack;
-            }
-            else {
-                p.next = s;
-                if (p.isLive())
-                    q = s;
-                else {
-                    p = null;  // restart
-                    q = stack;
-                }
-            }
+            } else if (NEXT.weakCompareAndSet(p, q, s))
+                break;
+            else
+                q = p.next;
         }
     }
 
@@ -544,24 +549,34 @@
         final boolean isLive() { return dep != null; }
     }
 
-    /** Pushes the given completion (if it exists) unless done. */
-    final void push(UniCompletion<?,?> c) {
+    /**
+     * Pushes the given completion unless it completes while trying.
+     * Caller should first check that result is null.
+     */
+    final void unipush(Completion c) {
         if (c != null) {
-            while (result == null && !tryPushStack(c))
-                lazySetNext(c, null); // clear on failure
+            while (!tryPushStack(c)) {
+                if (result != null) {
+                    NEXT.set(c, null);
+                    break;
+                }
+            }
+            if (result != null)
+                c.tryFire(SYNC);
         }
     }
 
     /**
-     * Post-processing by dependent after successful UniCompletion
-     * tryFire.  Tries to clean stack of source a, and then either runs
-     * postComplete or returns this to caller, depending on mode.
+     * Post-processing by dependent after successful UniCompletion tryFire.
+     * Tries to clean stack of source a, and then either runs postComplete
+     * or returns this to caller, depending on mode.
      */
     final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
         if (a != null && a.stack != null) {
-            if (mode < 0 || a.result == null)
+            Object r;
+            if ((r = a.result) == null)
                 a.cleanStack();
-            else
+            if (mode >= 0 && (r != null || a.result != null))
                 a.postComplete();
         }
         if (result != null && stack != null) {
@@ -583,48 +598,65 @@
         }
         final CompletableFuture<V> tryFire(int mode) {
             CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniApply(a = src, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Function<? super T,? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            tryComplete: if (d.result == null) {
+                if (r instanceof AltResult) {
+                    if ((x = ((AltResult)r).ex) != null) {
+                        d.completeThrowable(x, r);
+                        break tryComplete;
+                    }
+                    r = null;
+                }
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    else {
+                        @SuppressWarnings("unchecked") T t = (T) r;
+                        d.completeValue(f.apply(t));
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniApply(CompletableFuture<S> a,
-                               Function<? super S,? extends T> f,
-                               UniApply<S,T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                completeValue(f.apply(s));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <V> CompletableFuture<V> uniApplyStage(
         Executor e, Function<? super T,? extends V> f) {
         if (f == null) throw new NullPointerException();
+        Object r;
+        if ((r = result) != null)
+            return uniApplyNow(r, e, f);
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.uniApply(this, f, null)) {
-            UniApply<T,V> c = new UniApply<T,V>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        unipush(new UniApply<T,V>(e, d, this, f));
+        return d;
+    }
+
+    private <V> CompletableFuture<V> uniApplyNow(
+        Object r, Executor e, Function<? super T,? extends V> f) {
+        Throwable x;
+        CompletableFuture<V> d = newIncompleteFuture();
+        if (r instanceof AltResult) {
+            if ((x = ((AltResult)r).ex) != null) {
+                d.result = encodeThrowable(x, r);
+                return d;
+            }
+            r = null;
+        }
+        try {
+            if (e != null) {
+                e.execute(new UniApply<T,V>(null, d, this, f));
+            } else {
+                @SuppressWarnings("unchecked") T t = (T) r;
+                d.result = d.encodeValue(f.apply(t));
+            }
+        } catch (Throwable ex) {
+            d.result = encodeThrowable(ex);
         }
         return d;
     }
@@ -638,48 +670,67 @@
         }
         final CompletableFuture<Void> tryFire(int mode) {
             CompletableFuture<Void> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniAccept(a = src, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Consumer<? super T> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            tryComplete: if (d.result == null) {
+                if (r instanceof AltResult) {
+                    if ((x = ((AltResult)r).ex) != null) {
+                        d.completeThrowable(x, r);
+                        break tryComplete;
+                    }
+                    r = null;
+                }
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    else {
+                        @SuppressWarnings("unchecked") T t = (T) r;
+                        f.accept(t);
+                        d.completeNull();
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniAccept(CompletableFuture<S> a,
-                                Consumer<? super S> f, UniAccept<S> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                f.accept(s);
-                completeNull();
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private CompletableFuture<Void> uniAcceptStage(Executor e,
                                                    Consumer<? super T> f) {
         if (f == null) throw new NullPointerException();
+        Object r;
+        if ((r = result) != null)
+            return uniAcceptNow(r, e, f);
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.uniAccept(this, f, null)) {
-            UniAccept<T> c = new UniAccept<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        unipush(new UniAccept<T>(e, d, this, f));
+        return d;
+    }
+
+    private CompletableFuture<Void> uniAcceptNow(
+        Object r, Executor e, Consumer<? super T> f) {
+        Throwable x;
+        CompletableFuture<Void> d = newIncompleteFuture();
+        if (r instanceof AltResult) {
+            if ((x = ((AltResult)r).ex) != null) {
+                d.result = encodeThrowable(x, r);
+                return d;
+            }
+            r = null;
+        }
+        try {
+            if (e != null) {
+                e.execute(new UniAccept<T>(null, d, this, f));
+            } else {
+                @SuppressWarnings("unchecked") T t = (T) r;
+                f.accept(t);
+                d.result = NIL;
+            }
+        } catch (Throwable ex) {
+            d.result = encodeThrowable(ex);
         }
         return d;
     }
@@ -693,42 +744,56 @@
         }
         final CompletableFuture<Void> tryFire(int mode) {
             CompletableFuture<Void> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniRun(a = src, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Runnable f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            if (d.result == null) {
+                if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
+                    d.completeThrowable(x, r);
+                else
+                    try {
+                        if (mode <= 0 && !claim())
+                            return null;
+                        else {
+                            f.run();
+                            d.completeNull();
+                        }
+                    } catch (Throwable ex) {
+                        d.completeThrowable(ex);
+                    }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniRun(CompletableFuture<?> a, Runnable f, UniRun<?> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else
-                try {
-                    if (c != null && !c.claim())
-                        return false;
-                    f.run();
-                    completeNull();
-                } catch (Throwable ex) {
-                    completeThrowable(ex);
-                }
-        }
-        return true;
-    }
-
     private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
         if (f == null) throw new NullPointerException();
+        Object r;
+        if ((r = result) != null)
+            return uniRunNow(r, e, f);
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.uniRun(this, f, null)) {
-            UniRun<T> c = new UniRun<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
+        unipush(new UniRun<T>(e, d, this, f));
+        return d;
+    }
+
+    private CompletableFuture<Void> uniRunNow(Object r, Executor e, Runnable f) {
+        Throwable x;
+        CompletableFuture<Void> d = newIncompleteFuture();
+        if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
+            d.result = encodeThrowable(x, r);
+        else
+            try {
+                if (e != null) {
+                    e.execute(new UniRun<T>(null, d, this, f));
+                } else {
+                    f.run();
+                    d.result = NIL;
+                }
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -742,20 +807,20 @@
         }
         final CompletableFuture<T> tryFire(int mode) {
             CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniWhenComplete(a = src, fn, mode > 0 ? null : this))
+            Object r; BiConsumer<? super T, ? super Throwable> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || !d.uniWhenComplete(r, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniWhenComplete(CompletableFuture<T> a,
+    final boolean uniWhenComplete(Object r,
                                   BiConsumer<? super T,? super Throwable> f,
                                   UniWhenComplete<T> c) {
-        Object r; T t; Throwable x = null;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
+        T t; Throwable x = null;
         if (result == null) {
             try {
                 if (c != null && !c.claim())
@@ -787,10 +852,17 @@
         Executor e, BiConsumer<? super T, ? super Throwable> f) {
         if (f == null) throw new NullPointerException();
         CompletableFuture<T> d = newIncompleteFuture();
-        if (e != null || !d.uniWhenComplete(this, f, null)) {
-            UniWhenComplete<T> c = new UniWhenComplete<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        Object r;
+        if ((r = result) == null)
+            unipush(new UniWhenComplete<T>(e, d, this, f));
+        else if (e == null)
+            d.uniWhenComplete(r, f, null);
+        else {
+            try {
+                e.execute(new UniWhenComplete<T>(null, d, this, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         }
         return d;
     }
@@ -805,20 +877,20 @@
         }
         final CompletableFuture<V> tryFire(int mode) {
             CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniHandle(a = src, fn, mode > 0 ? null : this))
+            Object r; BiFunction<? super T, Throwable, ? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || !d.uniHandle(r, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniHandle(CompletableFuture<S> a,
+    final <S> boolean uniHandle(Object r,
                                 BiFunction<? super S, Throwable, ? extends T> f,
                                 UniHandle<S,T> c) {
-        Object r; S s; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
+        S s; Throwable x;
         if (result == null) {
             try {
                 if (c != null && !c.claim())
@@ -843,10 +915,17 @@
         Executor e, BiFunction<? super T, Throwable, ? extends V> f) {
         if (f == null) throw new NullPointerException();
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.uniHandle(this, f, null)) {
-            UniHandle<T,V> c = new UniHandle<T,V>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        Object r;
+        if ((r = result) == null)
+            unipush(new UniHandle<T,V>(e, d, this, f));
+        else if (e == null)
+            d.uniHandle(r, f, null);
+        else {
+            try {
+                e.execute(new UniHandle<T,V>(null, d, this, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         }
         return d;
     }
@@ -861,19 +940,20 @@
         final CompletableFuture<T> tryFire(int mode) { // never ASYNC
             // assert mode != ASYNC;
             CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null || !d.uniExceptionally(a = src, fn, this))
+            Object r; Function<? super Throwable, ? extends T> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || !d.uniExceptionally(r, f, this))
                 return null;
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniExceptionally(CompletableFuture<T> a,
+    final boolean uniExceptionally(Object r,
                                    Function<? super Throwable, ? extends T> f,
                                    UniExceptionally<T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
+        Throwable x;
         if (result == null) {
             try {
                 if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) {
@@ -893,47 +973,39 @@
         Function<Throwable, ? extends T> f) {
         if (f == null) throw new NullPointerException();
         CompletableFuture<T> d = newIncompleteFuture();
-        if (!d.uniExceptionally(this, f, null)) {
-            UniExceptionally<T> c = new UniExceptionally<T>(d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
+        Object r;
+        if ((r = result) == null)
+            unipush(new UniExceptionally<T>(d, this, f));
+        else
+            d.uniExceptionally(r, f, null);
         return d;
     }
 
     @SuppressWarnings("serial")
-    static final class UniRelay<T> extends UniCompletion<T,T> { // for Compose
-        UniRelay(CompletableFuture<T> dep, CompletableFuture<T> src) {
+    static final class UniRelay<U, T extends U> extends UniCompletion<T,U> {
+        UniRelay(CompletableFuture<U> dep, CompletableFuture<T> src) {
             super(null, dep, src);
         }
-        final CompletableFuture<T> tryFire(int mode) {
-            CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null || !d.uniRelay(a = src))
+        final CompletableFuture<U> tryFire(int mode) {
+            CompletableFuture<U> d; CompletableFuture<T> a; Object r;
+            if ((d = dep) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            if (d.result == null)
+                d.completeRelay(r);
             src = null; dep = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniRelay(CompletableFuture<T> a) {
+    private static <U, T extends U> CompletableFuture<U> uniCopyStage(
+        CompletableFuture<T> src) {
         Object r;
-        if (a == null || (r = a.result) == null)
-            return false;
-        if (result == null) // no need to claim
-            completeRelay(r);
-        return true;
-    }
-
-    private CompletableFuture<T> uniCopyStage() {
-        Object r;
-        CompletableFuture<T> d = newIncompleteFuture();
-        if ((r = result) != null)
-            d.completeRelay(r);
-        else {
-            UniRelay<T> c = new UniRelay<T>(d, this);
-            push(c);
-            c.tryFire(SYNC);
-        }
+        CompletableFuture<U> d = src.newIncompleteFuture();
+        if ((r = src.result) != null)
+            d.result = encodeRelay(r);
+        else
+            src.unipush(new UniRelay<U,T>(d, src));
         return d;
     }
 
@@ -942,9 +1014,7 @@
         if ((r = result) != null)
             return new MinimalStage<T>(encodeRelay(r));
         MinimalStage<T> d = new MinimalStage<T>();
-        UniRelay<T> c = new UniRelay<T>(d, this);
-        push(c);
-        c.tryFire(SYNC);
+        unipush(new UniRelay<T,T>(d, this));
         return d;
     }
 
@@ -958,54 +1028,48 @@
         }
         final CompletableFuture<V> tryFire(int mode) {
             CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniCompose(a = src, fn, mode > 0 ? null : this))
+            Function<? super T, ? extends CompletionStage<V>> f;
+            Object r; Throwable x;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            tryComplete: if (d.result == null) {
+                if (r instanceof AltResult) {
+                    if ((x = ((AltResult)r).ex) != null) {
+                        d.completeThrowable(x, r);
+                        break tryComplete;
+                    }
+                    r = null;
+                }
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    @SuppressWarnings("unchecked") T t = (T) r;
+                    CompletableFuture<V> g = f.apply(t).toCompletableFuture();
+                    if ((r = g.result) != null)
+                        d.completeRelay(r);
+                    else {
+                        g.unipush(new UniRelay<V,V>(d, g));
+                        if (d.result == null)
+                            return null;
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniCompose(
-        CompletableFuture<S> a,
-        Function<? super S, ? extends CompletionStage<T>> f,
-        UniCompose<S,T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                CompletableFuture<T> g = f.apply(s).toCompletableFuture();
-                if (g.result == null || !uniRelay(g)) {
-                    UniRelay<T> copy = new UniRelay<T>(this, g);
-                    g.push(copy);
-                    copy.tryFire(SYNC);
-                    if (result == null)
-                        return false;
-                }
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <V> CompletableFuture<V> uniComposeStage(
         Executor e, Function<? super T, ? extends CompletionStage<V>> f) {
         if (f == null) throw new NullPointerException();
-        Object r, s; Throwable x;
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e == null && (r = result) != null) {
+        Object r, s; Throwable x;
+        if ((r = result) == null)
+            unipush(new UniCompose<T,V>(e, d, this, f));
+        else if (e == null) {
             if (r instanceof AltResult) {
                 if ((x = ((AltResult)r).ex) != null) {
                     d.result = encodeThrowable(x, r);
@@ -1017,21 +1081,20 @@
                 @SuppressWarnings("unchecked") T t = (T) r;
                 CompletableFuture<V> g = f.apply(t).toCompletableFuture();
                 if ((s = g.result) != null)
-                    d.completeRelay(s);
+                    d.result = encodeRelay(s);
                 else {
-                    UniRelay<V> c = new UniRelay<V>(d, g);
-                    g.push(c);
-                    c.tryFire(SYNC);
+                    g.unipush(new UniRelay<V,V>(d, g));
                 }
-                return d;
             } catch (Throwable ex) {
                 d.result = encodeThrowable(ex);
-                return d;
             }
         }
-        UniCompose<T,V> c = new UniCompose<T,V>(e, d, this, f);
-        push(c);
-        c.tryFire(SYNC);
+        else
+            try {
+                e.execute(new UniCompose<T,V>(null, d, this, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -1061,21 +1124,28 @@
         }
         final boolean isLive() {
             BiCompletion<?,?,?> c;
-            return (c = base) != null && c.dep != null;
+            return (c = base) != null
+                // && c.isLive()
+                && c.dep != null;
         }
     }
 
-    /** Pushes completion to this and b unless both done. */
+    /**
+     * Pushes completion to this and b unless both done.
+     * Caller should first check that either result or b.result is null.
+     */
     final void bipush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
         if (c != null) {
-            Object r;
-            while ((r = result) == null && !tryPushStack(c))
-                lazySetNext(c, null); // clear on failure
-            if (b != null && b != this && b.result == null) {
-                Completion q = (r != null) ? c : new CoCompletion(c);
-                while (b.result == null && !b.tryPushStack(q))
-                    lazySetNext(q, null); // clear on failure
+            while (result == null) {
+                if (tryPushStack(c)) {
+                    if (b.result == null)
+                        b.unipush(new CoCompletion(c));
+                    else if (result != null)
+                        c.tryFire(SYNC);
+                    return;
+                }
             }
+            b.unipush(c);
         }
     }
 
@@ -1083,9 +1153,10 @@
     final CompletableFuture<T> postFire(CompletableFuture<?> a,
                                         CompletableFuture<?> b, int mode) {
         if (b != null && b.stack != null) { // clean second source
-            if (mode < 0 || b.result == null)
+            Object r;
+            if ((r = b.result) == null)
                 b.cleanStack();
-            else
+            if (mode >= 0 && (r != null || b.result != null))
                 b.postComplete();
         }
         return postFire(a, mode);
@@ -1103,22 +1174,21 @@
             CompletableFuture<V> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biApply(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r, s; BiFunction<? super T,? super U,? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null
+                || !d.biApply(r, s, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S> boolean biApply(CompletableFuture<R> a,
-                                CompletableFuture<S> b,
+    final <R,S> boolean biApply(Object r, Object s,
                                 BiFunction<? super R,? super S,? extends T> f,
                                 BiApply<R,S,T> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
+        Throwable x;
         tryComplete: if (result == null) {
             if (r instanceof AltResult) {
                 if ((x = ((AltResult)r).ex) != null) {
@@ -1150,15 +1220,20 @@
     private <U,V> CompletableFuture<V> biApplyStage(
         Executor e, CompletionStage<U> o,
         BiFunction<? super T,? super U,? extends V> f) {
-        CompletableFuture<U> b;
+        CompletableFuture<U> b; Object r, s;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.biApply(this, b, f, null)) {
-            BiApply<T,U,V> c = new BiApply<T,U,V>(e, d, this, b, f);
-            bipush(b, c);
-            c.tryFire(SYNC);
-        }
+        if ((r = result) == null || (s = b.result) == null)
+            bipush(b, new BiApply<T,U,V>(e, d, this, b, f));
+        else if (e == null)
+            d.biApply(r, s, f, null);
+        else
+            try {
+                e.execute(new BiApply<T,U,V>(null, d, this, b, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -1174,22 +1249,21 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biAccept(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r, s; BiConsumer<? super T,? super U> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null
+                || !d.biAccept(r, s, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S> boolean biAccept(CompletableFuture<R> a,
-                                 CompletableFuture<S> b,
+    final <R,S> boolean biAccept(Object r, Object s,
                                  BiConsumer<? super R,? super S> f,
                                  BiAccept<R,S> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
+        Throwable x;
         tryComplete: if (result == null) {
             if (r instanceof AltResult) {
                 if ((x = ((AltResult)r).ex) != null) {
@@ -1222,15 +1296,20 @@
     private <U> CompletableFuture<Void> biAcceptStage(
         Executor e, CompletionStage<U> o,
         BiConsumer<? super T,? super U> f) {
-        CompletableFuture<U> b;
+        CompletableFuture<U> b; Object r, s;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.biAccept(this, b, f, null)) {
-            BiAccept<T,U> c = new BiAccept<T,U>(e, d, this, b, f);
-            bipush(b, c);
-            c.tryFire(SYNC);
-        }
+        if ((r = result) == null || (s = b.result) == null)
+            bipush(b, new BiAccept<T,U>(e, d, this, b, f));
+        else if (e == null)
+            d.biAccept(r, s, f, null);
+        else
+            try {
+                e.execute(new BiAccept<T,U>(null, d, this, b, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -1238,8 +1317,7 @@
     static final class BiRun<T,U> extends BiCompletion<T,U,Void> {
         Runnable fn;
         BiRun(Executor executor, CompletableFuture<Void> dep,
-              CompletableFuture<T> src,
-              CompletableFuture<U> snd,
+              CompletableFuture<T> src, CompletableFuture<U> snd,
               Runnable fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1247,25 +1325,25 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biRun(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r, s; Runnable f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null
+                || !d.biRun(r, s, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final boolean biRun(CompletableFuture<?> a, CompletableFuture<?> b,
-                        Runnable f, BiRun<?,?> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
+    final boolean biRun(Object r, Object s, Runnable f, BiRun<?,?> c) {
+        Throwable x; Object z;
         if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
-                completeThrowable(x, s);
+            if ((r instanceof AltResult
+                 && (x = ((AltResult)(z = r)).ex) != null) ||
+                (s instanceof AltResult
+                 && (x = ((AltResult)(z = s)).ex) != null))
+                completeThrowable(x, z);
             else
                 try {
                     if (c != null && !c.claim())
@@ -1281,52 +1359,52 @@
 
     private CompletableFuture<Void> biRunStage(Executor e, CompletionStage<?> o,
                                                Runnable f) {
-        CompletableFuture<?> b;
+        CompletableFuture<?> b; Object r, s;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.biRun(this, b, f, null)) {
-            BiRun<T,?> c = new BiRun<>(e, d, this, b, f);
-            bipush(b, c);
-            c.tryFire(SYNC);
-        }
+        if ((r = result) == null || (s = b.result) == null)
+            bipush(b, new BiRun<>(e, d, this, b, f));
+        else if (e == null)
+            d.biRun(r, s, f, null);
+        else
+            try {
+                e.execute(new BiRun<>(null, d, this, b, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
     @SuppressWarnings("serial")
     static final class BiRelay<T,U> extends BiCompletion<T,U,Void> { // for And
         BiRelay(CompletableFuture<Void> dep,
-                CompletableFuture<T> src,
-                CompletableFuture<U> snd) {
+                CompletableFuture<T> src, CompletableFuture<U> snd) {
             super(null, dep, src, snd);
         }
         final CompletableFuture<Void> tryFire(int mode) {
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null || !d.biRelay(a = src, b = snd))
+            Object r, s, z; Throwable x;
+            if ((d = dep) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null)
                 return null;
+            if (d.result == null) {
+                if ((r instanceof AltResult
+                     && (x = ((AltResult)(z = r)).ex) != null) ||
+                    (s instanceof AltResult
+                     && (x = ((AltResult)(z = s)).ex) != null))
+                    d.completeThrowable(x, z);
+                else
+                    d.completeNull();
+            }
             src = null; snd = null; dep = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    boolean biRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null)
-            return false;
-        if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
-                completeThrowable(x, s);
-            else
-                completeNull();
-        }
-        return true;
-    }
-
     /** Recursively constructs a tree of completions. */
     static CompletableFuture<Void> andTree(CompletableFuture<?>[] cfs,
                                            int lo, int hi) {
@@ -1334,39 +1412,44 @@
         if (lo > hi) // empty
             d.result = NIL;
         else {
-            CompletableFuture<?> a, b;
+            CompletableFuture<?> a, b; Object r, s, z; Throwable x;
             int mid = (lo + hi) >>> 1;
             if ((a = (lo == mid ? cfs[lo] :
                       andTree(cfs, lo, mid))) == null ||
                 (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
                       andTree(cfs, mid+1, hi))) == null)
                 throw new NullPointerException();
-            if (!d.biRelay(a, b)) {
-                BiRelay<?,?> c = new BiRelay<>(d, a, b);
-                a.bipush(b, c);
-                c.tryFire(SYNC);
-            }
+            if ((r = a.result) == null || (s = b.result) == null)
+                a.bipush(b, new BiRelay<>(d, a, b));
+            else if ((r instanceof AltResult
+                      && (x = ((AltResult)(z = r)).ex) != null) ||
+                     (s instanceof AltResult
+                      && (x = ((AltResult)(z = s)).ex) != null))
+                d.result = encodeThrowable(x, z);
+            else
+                d.result = NIL;
         }
         return d;
     }
 
     /* ------------- Projected (Ored) BiCompletions -------------- */
 
-    /** Pushes completion to this and b unless either done. */
+    /**
+     * Pushes completion to this and b unless either done.
+     * Caller should first check that result and b.result are both null.
+     */
     final void orpush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
         if (c != null) {
-            while ((b == null || b.result == null) && result == null) {
-                if (tryPushStack(c)) {
-                    if (b != null && b != this && b.result == null) {
-                        Completion q = new CoCompletion(c);
-                        while (result == null && b.result == null &&
-                               !b.tryPushStack(q))
-                            lazySetNext(q, null); // clear on failure
-                    }
+            while (!tryPushStack(c)) {
+                if (result != null) {
+                    NEXT.set(c, null);
                     break;
                 }
-                lazySetNext(c, null); // clear on failure
             }
+            if (result != null)
+                c.tryFire(SYNC);
+            else
+                b.unipush(new CoCompletion(c));
         }
     }
 
@@ -1374,8 +1457,7 @@
     static final class OrApply<T,U extends T,V> extends BiCompletion<T,U,V> {
         Function<? super T,? extends V> fn;
         OrApply(Executor executor, CompletableFuture<V> dep,
-                CompletableFuture<T> src,
-                CompletableFuture<U> snd,
+                CompletableFuture<T> src, CompletableFuture<U> snd,
                 Function<? super T,? extends V> fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1383,54 +1465,46 @@
             CompletableFuture<V> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orApply(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Function<? super T,? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (b = snd) == null
+                || ((r = a.result) == null && (r = b.result) == null))
                 return null;
+            tryComplete: if (d.result == null) {
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    if (r instanceof AltResult) {
+                        if ((x = ((AltResult)r).ex) != null) {
+                            d.completeThrowable(x, r);
+                            break tryComplete;
+                        }
+                        r = null;
+                    }
+                    @SuppressWarnings("unchecked") T t = (T) r;
+                    d.completeValue(f.apply(t));
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S extends R> boolean orApply(CompletableFuture<R> a,
-                                          CompletableFuture<S> b,
-                                          Function<? super R, ? extends T> f,
-                                          OrApply<R,S,T> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    if ((x = ((AltResult)r).ex) != null) {
-                        completeThrowable(x, r);
-                        break tryComplete;
-                    }
-                    r = null;
-                }
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                completeValue(f.apply(rr));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <U extends T,V> CompletableFuture<V> orApplyStage(
-        Executor e, CompletionStage<U> o,
-        Function<? super T, ? extends V> f) {
+        Executor e, CompletionStage<U> o, Function<? super T, ? extends V> f) {
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
+
+        Object r; CompletableFuture<? extends T> z;
+        if ((r = (z = this).result) != null ||
+            (r = (z = b).result) != null)
+            return z.uniApplyNow(r, e, f);
+
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.orApply(this, b, f, null)) {
-            OrApply<T,U,V> c = new OrApply<T,U,V>(e, d, this, b, f);
-            orpush(b, c);
-            c.tryFire(SYNC);
-        }
+        orpush(b, new OrApply<T,U,V>(e, d, this, b, f));
         return d;
     }
 
@@ -1438,8 +1512,7 @@
     static final class OrAccept<T,U extends T> extends BiCompletion<T,U,Void> {
         Consumer<? super T> fn;
         OrAccept(Executor executor, CompletableFuture<Void> dep,
-                 CompletableFuture<T> src,
-                 CompletableFuture<U> snd,
+                 CompletableFuture<T> src, CompletableFuture<U> snd,
                  Consumer<? super T> fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1447,54 +1520,47 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orAccept(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Consumer<? super T> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (b = snd) == null
+                || ((r = a.result) == null && (r = b.result) == null))
                 return null;
+            tryComplete: if (d.result == null) {
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    if (r instanceof AltResult) {
+                        if ((x = ((AltResult)r).ex) != null) {
+                            d.completeThrowable(x, r);
+                            break tryComplete;
+                        }
+                        r = null;
+                    }
+                    @SuppressWarnings("unchecked") T t = (T) r;
+                    f.accept(t);
+                    d.completeNull();
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S extends R> boolean orAccept(CompletableFuture<R> a,
-                                           CompletableFuture<S> b,
-                                           Consumer<? super R> f,
-                                           OrAccept<R,S> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    if ((x = ((AltResult)r).ex) != null) {
-                        completeThrowable(x, r);
-                        break tryComplete;
-                    }
-                    r = null;
-                }
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                f.accept(rr);
-                completeNull();
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <U extends T> CompletableFuture<Void> orAcceptStage(
         Executor e, CompletionStage<U> o, Consumer<? super T> f) {
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
+
+        Object r; CompletableFuture<? extends T> z;
+        if ((r = (z = this).result) != null ||
+            (r = (z = b).result) != null)
+            return z.uniAcceptNow(r, e, f);
+
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.orAccept(this, b, f, null)) {
-            OrAccept<T,U> c = new OrAccept<T,U>(e, d, this, b, f);
-            orpush(b, c);
-            c.tryFire(SYNC);
-        }
+        orpush(b, new OrAccept<T,U>(e, d, this, b, f));
         return d;
     }
 
@@ -1502,8 +1568,7 @@
     static final class OrRun<T,U> extends BiCompletion<T,U,Void> {
         Runnable fn;
         OrRun(Executor executor, CompletableFuture<Void> dep,
-              CompletableFuture<T> src,
-              CompletableFuture<U> snd,
+              CompletableFuture<T> src, CompletableFuture<U> snd,
               Runnable fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1511,97 +1576,81 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orRun(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Runnable f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (b = snd) == null
+                || ((r = a.result) == null && (r = b.result) == null))
                 return null;
+            if (d.result == null) {
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    else if (r instanceof AltResult
+                        && (x = ((AltResult)r).ex) != null)
+                        d.completeThrowable(x, r);
+                    else {
+                        f.run();
+                        d.completeNull();
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final boolean orRun(CompletableFuture<?> a, CompletableFuture<?> b,
-                        Runnable f, OrRun<?,?> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                    completeThrowable(x, r);
-                else {
-                    f.run();
-                    completeNull();
-                }
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private CompletableFuture<Void> orRunStage(Executor e, CompletionStage<?> o,
                                                Runnable f) {
         CompletableFuture<?> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
+
+        Object r; CompletableFuture<?> z;
+        if ((r = (z = this).result) != null ||
+            (r = (z = b).result) != null)
+            return z.uniRunNow(r, e, f);
+
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.orRun(this, b, f, null)) {
-            OrRun<T,?> c = new OrRun<>(e, d, this, b, f);
-            orpush(b, c);
-            c.tryFire(SYNC);
-        }
+        orpush(b, new OrRun<>(e, d, this, b, f));
         return d;
     }
 
+    /** Completion for an anyOf input future. */
     @SuppressWarnings("serial")
-    static final class OrRelay<T,U> extends BiCompletion<T,U,Object> { // for Or
-        OrRelay(CompletableFuture<Object> dep, CompletableFuture<T> src,
-                CompletableFuture<U> snd) {
-            super(null, dep, src, snd);
+    static class AnyOf extends Completion {
+        CompletableFuture<Object> dep; CompletableFuture<?> src;
+        CompletableFuture<?>[] srcs;
+        AnyOf(CompletableFuture<Object> dep, CompletableFuture<?> src,
+              CompletableFuture<?>[] srcs) {
+            this.dep = dep; this.src = src; this.srcs = srcs;
         }
         final CompletableFuture<Object> tryFire(int mode) {
-            CompletableFuture<Object> d;
-            CompletableFuture<T> a;
-            CompletableFuture<U> b;
-            if ((d = dep) == null || !d.orRelay(a = src, b = snd))
+            // assert mode != ASYNC;
+            CompletableFuture<Object> d; CompletableFuture<?> a;
+            CompletableFuture<?>[] as;
+            Object r;
+            if ((d = dep) == null
+                || (a = src) == null || (r = a.result) == null
+                || (as = srcs) == null)
                 return null;
-            src = null; snd = null; dep = null;
-            return d.postFire(a, b, mode);
-        }
-    }
-
-    final boolean orRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
-        Object r;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null))
-            return false;
-        if (result == null)
-            completeRelay(r);
-        return true;
-    }
-
-    /** Recursively constructs a tree of completions. */
-    static CompletableFuture<Object> orTree(CompletableFuture<?>[] cfs,
-                                            int lo, int hi) {
-        CompletableFuture<Object> d = new CompletableFuture<Object>();
-        if (lo <= hi) {
-            CompletableFuture<?> a, b;
-            int mid = (lo + hi) >>> 1;
-            if ((a = (lo == mid ? cfs[lo] :
-                      orTree(cfs, lo, mid))) == null ||
-                (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
-                      orTree(cfs, mid+1, hi))) == null)
-                throw new NullPointerException();
-            if (!d.orRelay(a, b)) {
-                OrRelay<?,?> c = new OrRelay<>(d, a, b);
-                a.orpush(b, c);
-                c.tryFire(SYNC);
+            dep = null; src = null; srcs = null;
+            if (d.completeRelay(r)) {
+                for (CompletableFuture<?> b : as)
+                    if (b != a)
+                        b.cleanStack();
+                if (mode < 0)
+                    return d;
+                else
+                    d.postComplete();
             }
+            return null;
         }
-        return d;
+        final boolean isLive() {
+            CompletableFuture<Object> d;
+            return (d = dep) != null && d.result == null;
+        }
     }
 
     /* ------------- Zero-input Async forms -------------- */
@@ -1616,7 +1665,7 @@
 
         public final Void getRawResult() { return null; }
         public final void setRawResult(Void v) {}
-        public final boolean exec() { run(); return true; }
+        public final boolean exec() { run(); return false; }
 
         public void run() {
             CompletableFuture<T> d; Supplier<? extends T> f;
@@ -1652,7 +1701,7 @@
 
         public final Void getRawResult() { return null; }
         public final void setRawResult(Void v) {}
-        public final boolean exec() { run(); return true; }
+        public final boolean exec() { run(); return false; }
 
         public void run() {
             CompletableFuture<Void> d; Runnable f;
@@ -1736,15 +1785,13 @@
     private Object waitingGet(boolean interruptible) {
         Signaller q = null;
         boolean queued = false;
-        int spins = SPINS;
         Object r;
         while ((r = result) == null) {
-            if (spins > 0) {
-                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
-                    --spins;
-            }
-            else if (q == null)
+            if (q == null) {
                 q = new Signaller(interruptible, 0L, 0L);
+                if (Thread.currentThread() instanceof ForkJoinWorkerThread)
+                    ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q);
+            }
             else if (!queued)
                 queued = tryPushStack(q);
             else {
@@ -1757,16 +1804,14 @@
                     break;
             }
         }
-        if (q != null) {
+        if (q != null && queued) {
             q.thread = null;
-            if (q.interrupted) {
-                if (interruptible)
-                    cleanStack();
-                else
-                    Thread.currentThread().interrupt();
-            }
+            if (!interruptible && q.interrupted)
+                Thread.currentThread().interrupt();
+            if (r == null)
+                cleanStack();
         }
-        if (r != null)
+        if (r != null || (r = result) != null)
             postComplete();
         return r;
     }
@@ -1784,9 +1829,12 @@
             Signaller q = null;
             boolean queued = false;
             Object r;
-            while ((r = result) == null) { // similar to untimed, without spins
-                if (q == null)
+            while ((r = result) == null) { // similar to untimed
+                if (q == null) {
                     q = new Signaller(true, nanos, deadline);
+                    if (Thread.currentThread() instanceof ForkJoinWorkerThread)
+                        ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q);
+                }
                 else if (!queued)
                     queued = tryPushStack(q);
                 else if (q.nanos <= 0L)
@@ -1801,12 +1849,13 @@
                         break;
                 }
             }
-            if (q != null)
+            if (q != null && queued) {
                 q.thread = null;
-            if (r != null)
+                if (r == null)
+                    cleanStack();
+            }
+            if (r != null || (r = result) != null)
                 postComplete();
-            else
-                cleanStack();
             if (r != null || (q != null && q.interrupted))
                 return r;
         }
@@ -1918,9 +1967,12 @@
      * @throws InterruptedException if the current thread was interrupted
      * while waiting
      */
+    @SuppressWarnings("unchecked")
     public T get() throws InterruptedException, ExecutionException {
         Object r;
-        return reportGet((r = result) == null ? waitingGet(true) : r);
+        if ((r = result) == null)
+            r = waitingGet(true);
+        return (T) reportGet(r);
     }
 
     /**
@@ -1936,11 +1988,14 @@
      * while waiting
      * @throws TimeoutException if the wait timed out
      */
+    @SuppressWarnings("unchecked")
     public T get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
-        Object r;
         long nanos = unit.toNanos(timeout);
-        return reportGet((r = result) == null ? timedGet(nanos) : r);
+        Object r;
+        if ((r = result) == null)
+            r = timedGet(nanos);
+        return (T) reportGet(r);
     }
 
     /**
@@ -1957,9 +2012,12 @@
      * @throws CompletionException if this future completed
      * exceptionally or a completion computation threw an exception
      */
+    @SuppressWarnings("unchecked")
     public T join() {
         Object r;
-        return reportJoin((r = result) == null ? waitingGet(false) : r);
+        if ((r = result) == null)
+            r = waitingGet(false);
+        return (T) reportJoin(r);
     }
 
     /**
@@ -1972,9 +2030,10 @@
      * @throws CompletionException if this future completed
      * exceptionally or a completion computation threw an exception
      */
+    @SuppressWarnings("unchecked")
     public T getNow(T valueIfAbsent) {
         Object r;
-        return ((r = result) == null) ? valueIfAbsent : reportJoin(r);
+        return ((r = result) == null) ? valueIfAbsent : (T) reportJoin(r);
     }
 
     /**
@@ -2270,7 +2329,28 @@
      * {@code null}
      */
     public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
-        return orTree(cfs, 0, cfs.length - 1);
+        int n; Object r;
+        if ((n = cfs.length) <= 1)
+            return (n == 0)
+                ? new CompletableFuture<Object>()
+                : uniCopyStage(cfs[0]);
+        for (CompletableFuture<?> cf : cfs)
+            if ((r = cf.result) != null)
+                return new CompletableFuture<Object>(encodeRelay(r));
+        cfs = cfs.clone();
+        CompletableFuture<Object> d = new CompletableFuture<>();
+        for (CompletableFuture<?> cf : cfs)
+            cf.unipush(new AnyOf(d, cf, cfs));
+        // If d was completed while we were adding completions, we should
+        // clean the stack of any sources that may have had completions
+        // pushed on their stack after d was completed.
+        if (d.result != null)
+            for (int i = 0, len = cfs.length; i < len; i++)
+                if (cfs[i].result != null)
+                    for (i++; i < len; i++)
+                        if (cfs[i].result == null)
+                            cfs[i].cleanStack();
+        return d;
     }
 
     /* ------------- Control and status methods -------------- */
@@ -2386,13 +2466,13 @@
         for (Completion p = stack; p != null; p = p.next)
             ++count;
         return super.toString() +
-            ((r == null) ?
-             ((count == 0) ?
-              "[Not completed]" :
-              "[Not completed, " + count + " dependents]") :
-             (((r instanceof AltResult) && ((AltResult)r).ex != null) ?
-              "[Completed exceptionally]" :
-              "[Completed normally]"));
+            ((r == null)
+             ? ((count == 0)
+                ? "[Not completed]"
+                : "[Not completed, " + count + " dependents]")
+             : (((r instanceof AltResult) && ((AltResult)r).ex != null)
+                ? "[Completed exceptionally: " + ((AltResult)r).ex + "]"
+                : "[Completed normally]"));
     }
 
     // jdk9 additions
@@ -2442,7 +2522,7 @@
      * @since 9
      */
     public CompletableFuture<T> copy() {
-        return uniCopyStage();
+        return uniCopyStage(this);
     }
 
     /**
@@ -2455,6 +2535,13 @@
      * exceptionally with a CompletionException with this exception as
      * cause.
      *
+     * <p>Unless overridden by a subclass, a new non-minimal
+     * CompletableFuture with all methods available can be obtained from
+     * a minimal CompletionStage via {@link #toCompletableFuture()}.
+     * For example, completion of a minimal stage can be awaited by
+     *
+     * <pre> {@code minimalStage.toCompletableFuture().join(); }</pre>
+     *
      * @return the new CompletionStage
      * @since 9
      */
@@ -2749,23 +2836,30 @@
         @Override public CompletableFuture<T> completeOnTimeout
             (T value, long timeout, TimeUnit unit) {
             throw new UnsupportedOperationException(); }
+        @Override public CompletableFuture<T> toCompletableFuture() {
+            Object r;
+            if ((r = result) != null)
+                return new CompletableFuture<T>(encodeRelay(r));
+            else {
+                CompletableFuture<T> d = new CompletableFuture<>();
+                unipush(new UniRelay<T,T>(d, this));
+                return d;
+            }
+        }
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long RESULT;
-    private static final long STACK;
-    private static final long NEXT;
+    // VarHandle mechanics
+    private static final VarHandle RESULT;
+    private static final VarHandle STACK;
+    private static final VarHandle NEXT;
     static {
         try {
-            RESULT = U.objectFieldOffset
-                (CompletableFuture.class.getDeclaredField("result"));
-            STACK = U.objectFieldOffset
-                (CompletableFuture.class.getDeclaredField("stack"));
-            NEXT = U.objectFieldOffset
-                (Completion.class.getDeclaredField("next"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            RESULT = l.findVarHandle(CompletableFuture.class, "result", Object.class);
+            STACK = l.findVarHandle(CompletableFuture.class, "stack", Completion.class);
+            NEXT = l.findVarHandle(Completion.class, "next", Completion.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
 
         // Reduce the risk of rare disastrous classloading in first call to
diff --git a/ojluni/src/main/java/java/util/concurrent/CompletionService.java b/ojluni/src/main/java/java/util/concurrent/CompletionService.java
index f647e21..5e5232e 100644
--- a/ojluni/src/main/java/java/util/concurrent/CompletionService.java
+++ b/ojluni/src/main/java/java/util/concurrent/CompletionService.java
@@ -57,6 +57,8 @@
  * <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()}.
+ *
+ * @since 1.5
  */
 public interface CompletionService<V> {
     /**
diff --git a/ojluni/src/main/java/java/util/concurrent/CompletionStage.java b/ojluni/src/main/java/java/util/concurrent/CompletionStage.java
index d855945..70b601a 100644
--- a/ojluni/src/main/java/java/util/concurrent/CompletionStage.java
+++ b/ojluni/src/main/java/java/util/concurrent/CompletionStage.java
@@ -856,13 +856,9 @@
      * CompletableFuture, this method may return this stage itself.
      * Otherwise, invocation of this method may be equivalent in
      * effect to {@code thenApply(x -> x)}, but returning an instance
-     * of type {@code CompletableFuture}. A CompletionStage
-     * implementation that does not choose to interoperate with others
-     * may throw {@code UnsupportedOperationException}.
+     * of type {@code CompletableFuture}.
      *
      * @return the CompletableFuture
-     * @throws UnsupportedOperationException if this implementation
-     * does not interoperate with CompletableFuture
      */
     public CompletableFuture<T> toCompletableFuture();
 
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
index 5407963..e43eb7d 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentHashMap.java
@@ -68,10 +68,7 @@
 import java.util.function.ToLongBiFunction;
 import java.util.function.ToLongFunction;
 import java.util.stream.Stream;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import jdk.internal.misc.Unsafe;
 
 /**
  * A hash table supporting full concurrency of retrievals and
@@ -162,8 +159,7 @@
  * ordering, or on any other objects or values that may transiently
  * change while computation is in progress; and except for forEach
  * actions, should ideally be side-effect-free. Bulk operations on
- * {@link java.util.Map.Entry} objects do not support method {@code
- * setValue}.
+ * {@link Map.Entry} objects do not support method {@code setValue}.
  *
  * <ul>
  * <li>forEach: Performs a given action on each element.
@@ -256,6 +252,10 @@
  *
  * <p>All arguments to all task methods must be non-null.
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <K> the type of keys maintained by this map
@@ -297,7 +297,7 @@
      * Table accesses require volatile/atomic reads, writes, and
      * CASes.  Because there is no other way to arrange this without
      * adding further indirections, we use intrinsics
-     * (sun.misc.Unsafe) operations.
+     * (jdk.internal.misc.Unsafe) operations.
      *
      * We use the top (sign) bit of Node hash fields for control
      * purposes -- it is available anyway because of addressing
@@ -628,10 +628,14 @@
         volatile V val;
         volatile Node<K,V> next;
 
-        Node(int hash, K key, V val, Node<K,V> next) {
+        Node(int hash, K key, V val) {
             this.hash = hash;
             this.key = key;
             this.val = val;
+        }
+
+        Node(int hash, K key, V val, Node<K,V> next) {
+            this(hash, key, val);
             this.next = next;
         }
 
@@ -698,12 +702,7 @@
      * See Hackers Delight, sec 3.2
      */
     private static final int tableSizeFor(int c) {
-        int n = c - 1;
-        n |= n >>> 1;
-        n |= n >>> 2;
-        n |= n >>> 4;
-        n |= n >>> 8;
-        n |= n >>> 16;
+        int n = -1 >>> Integer.numberOfLeadingZeros(c - 1);
         return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
     }
 
@@ -713,12 +712,12 @@
      */
     static Class<?> comparableClassFor(Object x) {
         if (x instanceof Comparable) {
-            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
+            Class<?> c; Type[] ts, as; ParameterizedType p;
             if ((c = x.getClass()) == String.class) // bypass checks
                 return c;
             if ((ts = c.getGenericInterfaces()) != null) {
-                for (int i = 0; i < ts.length; ++i) {
-                    if (((t = ts[i]) instanceof ParameterizedType) &&
+                for (Type t : ts) {
+                    if ((t instanceof ParameterizedType) &&
                         ((p = (ParameterizedType)t).getRawType() ==
                          Comparable.class) &&
                         (as = p.getActualTypeArguments()) != null &&
@@ -743,7 +742,7 @@
     /* ---------------- Table element access -------------- */
 
     /*
-     * Volatile access methods are used for table elements as well as
+     * Atomic access methods are used for table elements as well as
      * elements of in-progress next table while resizing.  All uses of
      * the tab arguments must be null checked by callers.  All callers
      * also paranoically precheck that tab's length is not zero (or an
@@ -753,23 +752,21 @@
      * errors by users, these checks must operate on local variables,
      * which accounts for some odd-looking inline assignments below.
      * Note that calls to setTabAt always occur within locked regions,
-     * and so in principle require only release ordering, not
-     * full volatile semantics, but are currently coded as volatile
-     * writes to be conservative.
+     * and so require only release ordering.
      */
 
     @SuppressWarnings("unchecked")
     static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
-        return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
+        return (Node<K,V>)U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE);
     }
 
     static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
                                         Node<K,V> c, Node<K,V> v) {
-        return U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
+        return U.compareAndSetObject(tab, ((long)i << ASHIFT) + ABASE, c, v);
     }
 
     static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
-        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
+        U.putObjectRelease(tab, ((long)i << ASHIFT) + ABASE, v);
     }
 
     /* ---------------- Fields -------------- */
@@ -842,12 +839,7 @@
      * elements is negative
      */
     public ConcurrentHashMap(int initialCapacity) {
-        if (initialCapacity < 0)
-            throw new IllegalArgumentException();
-        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
-                   MAXIMUM_CAPACITY :
-                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
-        this.sizeCtl = cap;
+        this(initialCapacity, LOAD_FACTOR, 1);
     }
 
     /**
@@ -881,8 +873,8 @@
 
     /**
      * Creates a new, empty map with an initial table size based on
-     * the given number of elements ({@code initialCapacity}), table
-     * density ({@code loadFactor}), and number of concurrently
+     * the given number of elements ({@code initialCapacity}), initial
+     * table density ({@code loadFactor}), and number of concurrently
      * updating threads ({@code concurrencyLevel}).
      *
      * @param initialCapacity the initial capacity. The implementation
@@ -1020,16 +1012,20 @@
         int hash = spread(key.hashCode());
         int binCount = 0;
         for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
+            Node<K,V> f; int n, i, fh; K fk; V fv;
             if (tab == null || (n = tab.length) == 0)
                 tab = initTable();
             else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
-                if (casTabAt(tab, i, null,
-                             new Node<K,V>(hash, key, value, null)))
+                if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))
                     break;                   // no lock when adding to empty bin
             }
             else if ((fh = f.hash) == MOVED)
                 tab = helpTransfer(tab, f);
+            else if (onlyIfAbsent // check first node without acquiring lock
+                     && fh == hash
+                     && ((fk = f.key) == key || (fk != null && key.equals(fk)))
+                     && (fv = f.val) != null)
+                return fv;
             else {
                 V oldVal = null;
                 synchronized (f) {
@@ -1048,8 +1044,7 @@
                                 }
                                 Node<K,V> pred = e;
                                 if ((e = e.next) == null) {
-                                    pred.next = new Node<K,V>(hash, key,
-                                                              value, null);
+                                    pred.next = new Node<K,V>(hash, key, value);
                                     break;
                                 }
                             }
@@ -1245,7 +1240,8 @@
     @dalvik.annotation.codegen.CovariantReturnType(returnType = KeySetView.class, presentAfter = 28)
     public Set<K> keySet() {
         KeySetView<K,V> ks;
-        return (ks = keySet) != null ? ks : (keySet = new KeySetView<K,V>(this, null));
+        if ((ks = keySet) != null) return ks;
+        return keySet = new KeySetView<K,V>(this, null);
     }
 
     /**
@@ -1268,7 +1264,8 @@
      */
     public Collection<V> values() {
         ValuesView<K,V> vs;
-        return (vs = values) != null ? vs : (values = new ValuesView<K,V>(this));
+        if ((vs = values) != null) return vs;
+        return values = new ValuesView<K,V>(this);
     }
 
     /**
@@ -1290,7 +1287,8 @@
      */
     public Set<Map.Entry<K,V>> entrySet() {
         EntrySetView<K,V> es;
-        return (es = entrySet) != null ? es : (entrySet = new EntrySetView<K,V>(this));
+        if ((es = entrySet) != null) return es;
+        return entrySet = new EntrySetView<K,V>(this);
     }
 
     /**
@@ -1391,8 +1389,8 @@
     }
 
     /**
-     * Saves the state of the {@code ConcurrentHashMap} instance to a
-     * stream (i.e., serializes it).
+     * Saves this map to a stream (that is, serializes it).
+     *
      * @param s the stream
      * @throws java.io.IOException if an I/O error occurs
      * @serialData
@@ -1436,7 +1434,7 @@
     }
 
     /**
-     * Reconstitutes the instance from a stream (that is, deserializes it).
+     * Reconstitutes this map from a stream (that is, deserializes it).
      * @param s the stream
      * @throws ClassNotFoundException if the class of a serialized object
      *         could not be found
@@ -1470,13 +1468,9 @@
         if (size == 0L)
             sizeCtl = 0;
         else {
-            int n;
-            if (size >= (long)(MAXIMUM_CAPACITY >>> 1))
-                n = MAXIMUM_CAPACITY;
-            else {
-                int sz = (int)size;
-                n = tableSizeFor(sz + (sz >>> 1) + 1);
-            }
+            long ts = (long)(1.0 + size / LOAD_FACTOR);
+            int n = (ts >= (long)MAXIMUM_CAPACITY) ?
+                MAXIMUM_CAPACITY : tableSizeFor((int)ts);
             @SuppressWarnings("unchecked")
             Node<K,V>[] tab = (Node<K,V>[])new Node<?,?>[n];
             int mask = n - 1;
@@ -1703,7 +1697,7 @@
         V val = null;
         int binCount = 0;
         for (Node<K,V>[] tab = table;;) {
-            Node<K,V> f; int n, i, fh;
+            Node<K,V> f; int n, i, fh; K fk; V fv;
             if (tab == null || (n = tab.length) == 0)
                 tab = initTable();
             else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
@@ -1714,7 +1708,7 @@
                         Node<K,V> node = null;
                         try {
                             if ((val = mappingFunction.apply(key)) != null)
-                                node = new Node<K,V>(h, key, val, null);
+                                node = new Node<K,V>(h, key, val);
                         } finally {
                             setTabAt(tab, i, node);
                         }
@@ -1725,6 +1719,10 @@
             }
             else if ((fh = f.hash) == MOVED)
                 tab = helpTransfer(tab, f);
+            else if (fh == h    // check first node without acquiring lock
+                     && ((fk = f.key) == key || (fk != null && key.equals(fk)))
+                     && (fv = f.val) != null)
+                return fv;
             else {
                 boolean added = false;
                 synchronized (f) {
@@ -1745,7 +1743,7 @@
                                         if (pred.next != null)
                                             throw new IllegalStateException("Recursive update");
                                         added = true;
-                                        pred.next = new Node<K,V>(h, key, val, null);
+                                        pred.next = new Node<K,V>(h, key, val);
                                     }
                                     break;
                                 }
@@ -1914,7 +1912,7 @@
                         try {
                             if ((val = remappingFunction.apply(key, null)) != null) {
                                 delta = 1;
-                                node = new Node<K,V>(h, key, val, null);
+                                node = new Node<K,V>(h, key, val);
                             }
                         } finally {
                             setTabAt(tab, i, node);
@@ -1956,8 +1954,7 @@
                                         if (pred.next != null)
                                             throw new IllegalStateException("Recursive update");
                                         delta = 1;
-                                        pred.next =
-                                            new Node<K,V>(h, key, val, null);
+                                        pred.next = new Node<K,V>(h, key, val);
                                     }
                                     break;
                                 }
@@ -2035,7 +2032,7 @@
             if (tab == null || (n = tab.length) == 0)
                 tab = initTable();
             else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
-                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value, null))) {
+                if (casTabAt(tab, i, null, new Node<K,V>(h, key, value))) {
                     delta = 1;
                     val = value;
                     break;
@@ -2070,8 +2067,7 @@
                                 if ((e = e.next) == null) {
                                     delta = 1;
                                     val = value;
-                                    pred.next =
-                                        new Node<K,V>(h, key, val, null);
+                                    pred.next = new Node<K,V>(h, key, val);
                                     break;
                                 }
                             }
@@ -2232,7 +2228,7 @@
     static final class ForwardingNode<K,V> extends Node<K,V> {
         final Node<K,V>[] nextTable;
         ForwardingNode(Node<K,V>[] tab) {
-            super(MOVED, null, null, null);
+            super(MOVED, null, null);
             this.nextTable = tab;
         }
 
@@ -2268,7 +2264,7 @@
      */
     static final class ReservationNode<K,V> extends Node<K,V> {
         ReservationNode() {
-            super(RESERVED, null, null, null);
+            super(RESERVED, null, null);
         }
 
         Node<K,V> find(int h, Object k) {
@@ -2294,7 +2290,7 @@
         while ((tab = table) == null || tab.length == 0) {
             if ((sc = sizeCtl) < 0)
                 Thread.yield(); // lost initialization race; just spin
-            else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
+            else if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
                 try {
                     if ((tab = table) == null || tab.length == 0) {
                         int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
@@ -2323,15 +2319,15 @@
      * @param check if <0, don't check resize, if <= 1 only check if uncontended
      */
     private final void addCount(long x, int check) {
-        CounterCell[] as; long b, s;
-        if ((as = counterCells) != null ||
-            !U.compareAndSwapLong(this, BASECOUNT, b = baseCount, s = b + x)) {
-            CounterCell a; long v; int m;
+        CounterCell[] cs; long b, s;
+        if ((cs = counterCells) != null ||
+            !U.compareAndSetLong(this, BASECOUNT, b = baseCount, s = b + x)) {
+            CounterCell c; long v; int m;
             boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[ThreadLocalRandom.getProbe() & m]) == null ||
+            if (cs == null || (m = cs.length - 1) < 0 ||
+                (c = cs[ThreadLocalRandom.getProbe() & m]) == null ||
                 !(uncontended =
-                  U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))) {
+                  U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))) {
                 fullAddCount(x, uncontended);
                 return;
             }
@@ -2349,10 +2345,10 @@
                         sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
                         transferIndex <= 0)
                         break;
-                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
+                    if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1))
                         transfer(tab, nt);
                 }
-                else if (U.compareAndSwapInt(this, SIZECTL, sc,
+                else if (U.compareAndSetInt(this, SIZECTL, sc,
                                              (rs << RESIZE_STAMP_SHIFT) + 2))
                     transfer(tab, null);
                 s = sumCount();
@@ -2373,7 +2369,7 @@
                 if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
                     sc == rs + MAX_RESIZERS || transferIndex <= 0)
                     break;
-                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
+                if (U.compareAndSetInt(this, SIZECTL, sc, sc + 1)) {
                     transfer(tab, nextTab);
                     break;
                 }
@@ -2396,7 +2392,7 @@
             Node<K,V>[] tab = table; int n;
             if (tab == null || (n = tab.length) == 0) {
                 n = (sc > c) ? sc : c;
-                if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
+                if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {
                     try {
                         if (table == tab) {
                             @SuppressWarnings("unchecked")
@@ -2413,7 +2409,7 @@
                 break;
             else if (tab == table) {
                 int rs = resizeStamp(n);
-                if (U.compareAndSwapInt(this, SIZECTL, sc,
+                if (U.compareAndSetInt(this, SIZECTL, sc,
                                         (rs << RESIZE_STAMP_SHIFT) + 2))
                     transfer(tab, null);
             }
@@ -2454,7 +2450,7 @@
                     i = -1;
                     advance = false;
                 }
-                else if (U.compareAndSwapInt
+                else if (U.compareAndSetInt
                          (this, TRANSFERINDEX, nextIndex,
                           nextBound = (nextIndex > stride ?
                                        nextIndex - stride : 0))) {
@@ -2471,7 +2467,7 @@
                     sizeCtl = (n << 1) - (n >>> 1);
                     return;
                 }
-                if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
+                if (U.compareAndSetInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
                     if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
                         return;
                     finishing = advance = true;
@@ -2563,21 +2559,19 @@
      * A padded cell for distributing counts.  Adapted from LongAdder
      * and Striped64.  See their internal docs for explanation.
      */
-    // Android-removed: @Contended, this hint is not used by the Android runtime.
-    //@jdk.internal.vm.annotation.Contended
+    @jdk.internal.vm.annotation.Contended
     static final class CounterCell {
         volatile long value;
         CounterCell(long x) { value = x; }
     }
 
     final long sumCount() {
-        CounterCell[] as = counterCells; CounterCell a;
+        CounterCell[] cs = counterCells;
         long sum = baseCount;
-        if (as != null) {
-            for (int i = 0; i < as.length; ++i) {
-                if ((a = as[i]) != null)
-                    sum += a.value;
-            }
+        if (cs != null) {
+            for (CounterCell c : cs)
+                if (c != null)
+                    sum += c.value;
         }
         return sum;
     }
@@ -2592,13 +2586,13 @@
         }
         boolean collide = false;                // True if last slot nonempty
         for (;;) {
-            CounterCell[] as; CounterCell a; int n; long v;
-            if ((as = counterCells) != null && (n = as.length) > 0) {
-                if ((a = as[(n - 1) & h]) == null) {
+            CounterCell[] cs; CounterCell c; int n; long v;
+            if ((cs = counterCells) != null && (n = cs.length) > 0) {
+                if ((c = cs[(n - 1) & h]) == null) {
                     if (cellsBusy == 0) {            // Try to attach new Cell
                         CounterCell r = new CounterCell(x); // Optimistic create
                         if (cellsBusy == 0 &&
-                            U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
+                            U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
                             boolean created = false;
                             try {               // Recheck under lock
                                 CounterCell[] rs; int m, j;
@@ -2620,21 +2614,17 @@
                 }
                 else if (!wasUncontended)       // CAS already known to fail
                     wasUncontended = true;      // Continue after rehash
-                else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))
+                else if (U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))
                     break;
-                else if (counterCells != as || n >= NCPU)
+                else if (counterCells != cs || n >= NCPU)
                     collide = false;            // At max size or stale
                 else if (!collide)
                     collide = true;
                 else if (cellsBusy == 0 &&
-                         U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
+                         U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
                     try {
-                        if (counterCells == as) {// Expand table unless stale
-                            CounterCell[] rs = new CounterCell[n << 1];
-                            for (int i = 0; i < n; ++i)
-                                rs[i] = as[i];
-                            counterCells = rs;
-                        }
+                        if (counterCells == cs) // Expand table unless stale
+                            counterCells = Arrays.copyOf(cs, n << 1);
                     } finally {
                         cellsBusy = 0;
                     }
@@ -2643,11 +2633,11 @@
                 }
                 h = ThreadLocalRandom.advanceProbe(h);
             }
-            else if (cellsBusy == 0 && counterCells == as &&
-                     U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) {
+            else if (cellsBusy == 0 && counterCells == cs &&
+                     U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
                 boolean init = false;
                 try {                           // Initialize table
-                    if (counterCells == as) {
+                    if (counterCells == cs) {
                         CounterCell[] rs = new CounterCell[2];
                         rs[h & 1] = new CounterCell(x);
                         counterCells = rs;
@@ -2659,7 +2649,7 @@
                 if (init)
                     break;
             }
-            else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x))
+            else if (U.compareAndSetLong(this, BASECOUNT, v = baseCount, v + x))
                 break;                          // Fall back on using base
         }
     }
@@ -2697,12 +2687,12 @@
     }
 
     /**
-     * Returns a list on non-TreeNodes replacing those in given list.
+     * Returns a list of non-TreeNodes replacing those in given list.
      */
     static <K,V> Node<K,V> untreeify(Node<K,V> b) {
         Node<K,V> hd = null, tl = null;
         for (Node<K,V> q = b; q != null; q = q.next) {
-            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val, null);
+            Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val);
             if (tl == null)
                 hd = p;
             else
@@ -2808,7 +2798,7 @@
          * Creates bin with initial set of nodes headed by b.
          */
         TreeBin(TreeNode<K,V> b) {
-            super(TREEBIN, null, null, null);
+            super(TREEBIN, null, null);
             this.first = b;
             TreeNode<K,V> r = null;
             for (TreeNode<K,V> x = b, next; x != null; x = next) {
@@ -2855,7 +2845,7 @@
          * Acquires write lock for tree restructuring.
          */
         private final void lockRoot() {
-            if (!U.compareAndSwapInt(this, LOCKSTATE, 0, WRITER))
+            if (!U.compareAndSetInt(this, LOCKSTATE, 0, WRITER))
                 contendedLock(); // offload to separate method
         }
 
@@ -2873,14 +2863,14 @@
             boolean waiting = false;
             for (int s;;) {
                 if (((s = lockState) & ~WAITER) == 0) {
-                    if (U.compareAndSwapInt(this, LOCKSTATE, s, WRITER)) {
+                    if (U.compareAndSetInt(this, LOCKSTATE, s, WRITER)) {
                         if (waiting)
                             waiter = null;
                         return;
                     }
                 }
                 else if ((s & WAITER) == 0) {
-                    if (U.compareAndSwapInt(this, LOCKSTATE, s, s | WAITER)) {
+                    if (U.compareAndSetInt(this, LOCKSTATE, s, s | WAITER)) {
                         waiting = true;
                         waiter = Thread.currentThread();
                     }
@@ -2905,7 +2895,7 @@
                             return e;
                         e = e.next;
                     }
-                    else if (U.compareAndSwapInt(this, LOCKSTATE, s,
+                    else if (U.compareAndSetInt(this, LOCKSTATE, s,
                                                  s + READER)) {
                         TreeNode<K,V> r, p;
                         try {
@@ -3302,16 +3292,9 @@
             return true;
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long LOCKSTATE;
-        static {
-            try {
-                LOCKSTATE = U.objectFieldOffset
-                    (TreeBin.class.getDeclaredField("lockState"));
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-        }
+        private static final Unsafe U = Unsafe.getUnsafe();
+        private static final long LOCKSTATE
+                = U.objectFieldOffset(TreeBin.class, "lockState");
     }
 
     /* ----------------Table Traversal -------------- */
@@ -3465,9 +3448,9 @@
 
     static final class KeyIterator<K,V> extends BaseIterator<K,V>
         implements Iterator<K>, Enumeration<K> {
-        KeyIterator(Node<K,V>[] tab, int index, int size, int limit,
+        KeyIterator(Node<K,V>[] tab, int size, int index, int limit,
                     ConcurrentHashMap<K,V> map) {
-            super(tab, index, size, limit, map);
+            super(tab, size, index, limit, map);
         }
 
         public final K next() {
@@ -3485,9 +3468,9 @@
 
     static final class ValueIterator<K,V> extends BaseIterator<K,V>
         implements Iterator<V>, Enumeration<V> {
-        ValueIterator(Node<K,V>[] tab, int index, int size, int limit,
+        ValueIterator(Node<K,V>[] tab, int size, int index, int limit,
                       ConcurrentHashMap<K,V> map) {
-            super(tab, index, size, limit, map);
+            super(tab, size, index, limit, map);
         }
 
         public final V next() {
@@ -3505,9 +3488,9 @@
 
     static final class EntryIterator<K,V> extends BaseIterator<K,V>
         implements Iterator<Map.Entry<K,V>> {
-        EntryIterator(Node<K,V>[] tab, int index, int size, int limit,
+        EntryIterator(Node<K,V>[] tab, int size, int index, int limit,
                       ConcurrentHashMap<K,V> map) {
-            super(tab, index, size, limit, map);
+            super(tab, size, index, limit, map);
         }
 
         public final Map.Entry<K,V> next() {
@@ -4558,14 +4541,24 @@
             return true;
         }
 
-        public final boolean removeAll(Collection<?> c) {
+        public boolean removeAll(Collection<?> c) {
             if (c == null) throw new NullPointerException();
             boolean modified = false;
-            for (Iterator<E> it = iterator(); it.hasNext();) {
-                if (c.contains(it.next())) {
-                    it.remove();
-                    modified = true;
+            // Use (c instanceof Set) as a hint that lookup in c is as
+            // efficient as this view
+            Node<K,V>[] t;
+            if ((t = map.table) == null) {
+                return false;
+            } else if (c instanceof Set<?> && c.size() > t.length) {
+                for (Iterator<?> it = iterator(); it.hasNext(); ) {
+                    if (c.contains(it.next())) {
+                        it.remove();
+                        modified = true;
+                    }
                 }
+            } else {
+                for (Object e : c)
+                    modified |= remove(e);
             }
             return modified;
         }
@@ -4751,6 +4744,18 @@
             throw new UnsupportedOperationException();
         }
 
+        @Override public boolean removeAll(Collection<?> c) {
+            if (c == null) throw new NullPointerException();
+            boolean modified = false;
+            for (Iterator<V> it = iterator(); it.hasNext();) {
+                if (c.contains(it.next())) {
+                    it.remove();
+                    modified = true;
+                }
+            }
+            return modified;
+        }
+
         public boolean removeIf(Predicate<? super V> filter) {
             return map.removeValueIf(filter);
         }
@@ -6344,7 +6349,7 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+    private static final Unsafe U = Unsafe.getUnsafe();
     private static final long SIZECTL;
     private static final long TRANSFERINDEX;
     private static final long BASECOUNT;
@@ -6354,30 +6359,29 @@
     private static final int ASHIFT;
 
     static {
-        try {
-            SIZECTL = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
-            TRANSFERINDEX = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
-            BASECOUNT = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("baseCount"));
-            CELLSBUSY = U.objectFieldOffset
-                (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
+        SIZECTL = U.objectFieldOffset
+            (ConcurrentHashMap.class, "sizeCtl");
+        TRANSFERINDEX = U.objectFieldOffset
+            (ConcurrentHashMap.class, "transferIndex");
+        BASECOUNT = U.objectFieldOffset
+            (ConcurrentHashMap.class, "baseCount");
+        CELLSBUSY = U.objectFieldOffset
+            (ConcurrentHashMap.class, "cellsBusy");
 
-            CELLVALUE = U.objectFieldOffset
-                (CounterCell.class.getDeclaredField("value"));
+        CELLVALUE = U.objectFieldOffset
+            (CounterCell.class, "value");
 
-            ABASE = U.arrayBaseOffset(Node[].class);
-            int scale = U.arrayIndexScale(Node[].class);
-            if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
-            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+        ABASE = U.arrayBaseOffset(Node[].class);
+        int scale = U.arrayIndexScale(Node[].class);
+        if ((scale & (scale - 1)) != 0)
+            throw new ExceptionInInitializerError("array index scale not a power of two");
+        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
 
         // Reduce the risk of rare disastrous classloading in first call to
         // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
         Class<?> ensureLoaded = LockSupport.class;
+
+        // Eager class load observed to help JIT during startup
+        ensureLoaded = ReservationNode.class;
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
index 3edde54..91ddabd 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractCollection;
 import java.util.Arrays;
 import java.util.Collection;
@@ -46,10 +48,7 @@
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.function.Consumer;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.function.Predicate;
 
 /**
  * An unbounded concurrent {@linkplain Deque deque} based on linked nodes.
@@ -68,12 +67,12 @@
  * asynchronous nature of these deques, 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 {@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 {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
  *
  * <p>This class and its iterator implement all of the <em>optional</em>
  * methods of the {@link Deque} and {@link Iterator} interfaces.
@@ -85,6 +84,10 @@
  * actions subsequent to the access or removal of that element from
  * the {@code ConcurrentLinkedDeque} in another thread.
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.7
  * @author Doug Lea
  * @author Martin Buchholz
@@ -228,15 +231,16 @@
      *
      * The implementation is completely directionally symmetrical,
      * except that most public methods that iterate through the list
-     * follow next pointers ("forward" direction).
+     * follow next pointers, in the "forward" direction.
      *
-     * We believe (without full proof) that all single-element deque
-     * operations (e.g., addFirst, peekLast, pollLast) are linearizable
-     * (see Herlihy and Shavit's book).  However, some combinations of
+     * We believe (without full proof) that all single-element Deque
+     * operations that operate directly at the two ends of the Deque
+     * (e.g., addFirst, peekLast, pollLast) are linearizable (see
+     * Herlihy and Shavit's book).  However, some combinations of
      * operations are known not to be linearizable.  In particular,
-     * when an addFirst(A) is racing with pollFirst() removing B, it is
-     * possible for an observer iterating over the elements to observe
-     * A B C and subsequently observe A C, even though no interior
+     * when an addFirst(A) is racing with pollFirst() removing B, it
+     * is possible for an observer iterating over the elements to
+     * observe first [A B C] and then [A C], even though no interior
      * removes are ever performed.  Nevertheless, iterators behave
      * reasonably, providing the "weakly consistent" guarantees.
      *
@@ -292,64 +296,23 @@
         volatile Node<E> prev;
         volatile E item;
         volatile Node<E> next;
+    }
 
-        Node() {  // default constructor for NEXT_TERMINATOR, PREV_TERMINATOR
-        }
-
-        /**
-         * Constructs a new node.  Uses relaxed write because item can
-         * only be seen after publication via casNext or casPrev.
-         */
-        Node(E item) {
-            U.putObject(this, ITEM, item);
-        }
-
-        boolean casItem(E cmp, E val) {
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
-        }
-
-        void lazySetNext(Node<E> val) {
-            U.putOrderedObject(this, NEXT, val);
-        }
-
-        boolean casNext(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
-        }
-
-        void lazySetPrev(Node<E> val) {
-            U.putOrderedObject(this, PREV, val);
-        }
-
-        boolean casPrev(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, PREV, cmp, val);
-        }
-
-        // Unsafe mechanics
-
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long PREV;
-        private static final long ITEM;
-        private static final long NEXT;
-
-        static {
-            try {
-                PREV = U.objectFieldOffset
-                    (Node.class.getDeclaredField("prev"));
-                ITEM = U.objectFieldOffset
-                    (Node.class.getDeclaredField("item"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-        }
+    /**
+     * Returns a new node holding item.  Uses relaxed write because item
+     * can only be seen after piggy-backing publication via CAS.
+     */
+    static <E> Node<E> newNode(E item) {
+        Node<E> node = new Node<E>();
+        ITEM.set(node, item);
+        return node;
     }
 
     /**
      * Links e as first element.
      */
     private void linkFirst(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        final Node<E> newNode = newNode(Objects.requireNonNull(e));
 
         restartFromHead:
         for (;;)
@@ -363,13 +326,13 @@
                     continue restartFromHead;
                 else {
                     // p is first node
-                    newNode.lazySetNext(p); // CAS piggyback
-                    if (p.casPrev(null, newNode)) {
+                    NEXT.set(newNode, p); // CAS piggyback
+                    if (PREV.compareAndSet(p, null, newNode)) {
                         // Successful CAS is the linearization point
                         // for e to become an element of this deque,
                         // and for newNode to become "live".
-                        if (p != h) // hop two nodes at a time
-                            casHead(h, newNode);  // Failure is OK.
+                        if (p != h) // hop two nodes at a time; failure is OK
+                            HEAD.weakCompareAndSet(this, h, newNode);
                         return;
                     }
                     // Lost CAS race to another thread; re-read prev
@@ -381,7 +344,7 @@
      * Links e as last element.
      */
     private void linkLast(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        final Node<E> newNode = newNode(Objects.requireNonNull(e));
 
         restartFromTail:
         for (;;)
@@ -395,13 +358,13 @@
                     continue restartFromTail;
                 else {
                     // p is last node
-                    newNode.lazySetPrev(p); // CAS piggyback
-                    if (p.casNext(null, newNode)) {
+                    PREV.set(newNode, p); // CAS piggyback
+                    if (NEXT.compareAndSet(p, null, newNode)) {
                         // Successful CAS is the linearization point
                         // for e to become an element of this deque,
                         // and for newNode to become "live".
-                        if (p != t) // hop two nodes at a time
-                            casTail(t, newNode);  // Failure is OK.
+                        if (p != t) // hop two nodes at a time; failure is OK
+                            TAIL.weakCompareAndSet(this, t, newNode);
                         return;
                     }
                     // Lost CAS race to another thread; re-read next
@@ -516,8 +479,8 @@
                 updateTail(); // Ensure x is not reachable from tail
 
                 // Finally, actually gc-unlink
-                x.lazySetPrev(isFirst ? prevTerminator() : x);
-                x.lazySetNext(isLast  ? nextTerminator() : x);
+                PREV.setRelease(x, isFirst ? prevTerminator() : x);
+                NEXT.setRelease(x, isLast  ? nextTerminator() : x);
             }
         }
     }
@@ -531,7 +494,8 @@
         // assert first.item == null;
         for (Node<E> o = null, p = next, q;;) {
             if (p.item != null || (q = p.next) == null) {
-                if (o != null && p.prev != p && first.casNext(next, p)) {
+                if (o != null && p.prev != p &&
+                    NEXT.compareAndSet(first, next, p)) {
                     skipDeletedPredecessors(p);
                     if (first.prev == null &&
                         (p.next == null || p.item != null) &&
@@ -541,8 +505,8 @@
                         updateTail(); // Ensure o is not reachable from tail
 
                         // Finally, actually gc-unlink
-                        o.lazySetNext(o);
-                        o.lazySetPrev(prevTerminator());
+                        NEXT.setRelease(o, o);
+                        PREV.setRelease(o, prevTerminator());
                     }
                 }
                 return;
@@ -565,7 +529,8 @@
         // assert last.item == null;
         for (Node<E> o = null, p = prev, q;;) {
             if (p.item != null || (q = p.prev) == null) {
-                if (o != null && p.next != p && last.casPrev(prev, p)) {
+                if (o != null && p.next != p &&
+                    PREV.compareAndSet(last, prev, p)) {
                     skipDeletedSuccessors(p);
                     if (last.next == null &&
                         (p.prev == null || p.item != null) &&
@@ -575,8 +540,8 @@
                         updateTail(); // Ensure o is not reachable from tail
 
                         // Finally, actually gc-unlink
-                        o.lazySetPrev(o);
-                        o.lazySetNext(nextTerminator());
+                        PREV.setRelease(o, o);
+                        NEXT.setRelease(o, nextTerminator());
                     }
                 }
                 return;
@@ -607,7 +572,7 @@
                     (q = (p = q).prev) == null) {
                     // It is possible that p is PREV_TERMINATOR,
                     // but if so, the CAS is guaranteed to fail.
-                    if (casHead(h, p))
+                    if (HEAD.compareAndSet(this, h, p))
                         return;
                     else
                         continue restartFromHead;
@@ -637,7 +602,7 @@
                     (q = (p = q).next) == null) {
                     // It is possible that p is NEXT_TERMINATOR,
                     // but if so, the CAS is guaranteed to fail.
-                    if (casTail(t, p))
+                    if (TAIL.compareAndSet(this, t, p))
                         return;
                     else
                         continue restartFromTail;
@@ -675,7 +640,7 @@
             }
 
             // found active CAS target
-            if (prev == p || x.casPrev(prev, p))
+            if (prev == p || PREV.compareAndSet(x, prev, p))
                 return;
 
         } while (x.item != null || x.next == null);
@@ -706,7 +671,7 @@
             }
 
             // found active CAS target
-            if (next == p || x.casNext(next, p))
+            if (next == p || NEXT.compareAndSet(x, next, p))
                 return;
 
         } while (x.item != null || x.prev == null);
@@ -719,8 +684,9 @@
      */
     final Node<E> succ(Node<E> p) {
         // TODO: should we skip deleted nodes here?
-        Node<E> q = p.next;
-        return (p == q) ? first() : q;
+        if (p == (p = p.next))
+            p = first();
+        return p;
     }
 
     /**
@@ -729,8 +695,9 @@
      * stale pointer that is now off the list.
      */
     final Node<E> pred(Node<E> p) {
-        Node<E> q = p.prev;
-        return (p == q) ? last() : q;
+        if (p == (p = p.prev))
+            p = last();
+        return p;
     }
 
     /**
@@ -751,7 +718,7 @@
                 else if (p == h
                          // It is possible that p is PREV_TERMINATOR,
                          // but if so, the CAS is guaranteed to fail.
-                         || casHead(h, p))
+                         || HEAD.compareAndSet(this, h, p))
                     return p;
                 else
                     continue restartFromHead;
@@ -776,7 +743,7 @@
                 else if (p == t
                          // It is possible that p is NEXT_TERMINATOR,
                          // but if so, the CAS is guaranteed to fail.
-                         || casTail(t, p))
+                         || TAIL.compareAndSet(this, t, p))
                     return p;
                 else
                     continue restartFromTail;
@@ -802,7 +769,7 @@
      * Constructs an empty deque.
      */
     public ConcurrentLinkedDeque() {
-        head = tail = new Node<E>(null);
+        head = tail = new Node<E>();
     }
 
     /**
@@ -818,12 +785,12 @@
         // Copy c into a private chain of Nodes
         Node<E> h = null, t = null;
         for (E e : c) {
-            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
@@ -836,12 +803,12 @@
     private void initHeadTail(Node<E> h, Node<E> t) {
         if (h == t) {
             if (h == null)
-                h = t = new Node<E>(null);
+                h = t = new Node<E>();
             else {
                 // Avoid edge case of a single Node with non-null item.
-                Node<E> newNode = new Node<E>(null);
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                Node<E> newNode = new Node<E>();
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
@@ -900,21 +867,33 @@
     }
 
     public E peekFirst() {
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null)
-                return item;
+        restart: for (;;) {
+            E item;
+            Node<E> first = first(), p = first;
+            while ((item = p.item) == null) {
+                if (p == (p = p.next)) continue restart;
+                if (p == null)
+                    break;
+            }
+            // recheck for linearizability
+            if (first.prev != null) continue restart;
+            return item;
         }
-        return null;
     }
 
     public E peekLast() {
-        for (Node<E> p = last(); p != null; p = pred(p)) {
-            E item = p.item;
-            if (item != null)
-                return item;
+        restart: for (;;) {
+            E item;
+            Node<E> last = last(), p = last;
+            while ((item = p.item) == null) {
+                if (p == (p = p.prev)) continue restart;
+                if (p == null)
+                    break;
+            }
+            // recheck for linearizability
+            if (last.next != null) continue restart;
+            return item;
         }
-        return null;
     }
 
     /**
@@ -932,25 +911,45 @@
     }
 
     public E pollFirst() {
-        for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null && p.casItem(item, null)) {
-                unlink(p);
-                return item;
+        restart: for (;;) {
+            for (Node<E> first = first(), p = first;;) {
+                final E item;
+                if ((item = p.item) != null) {
+                    // recheck for linearizability
+                    if (first.prev != null) continue restart;
+                    if (ITEM.compareAndSet(p, item, null)) {
+                        unlink(p);
+                        return item;
+                    }
+                }
+                if (p == (p = p.next)) continue restart;
+                if (p == null) {
+                    if (first.prev != null) continue restart;
+                    return null;
+                }
             }
         }
-        return null;
     }
 
     public E pollLast() {
-        for (Node<E> p = last(); p != null; p = pred(p)) {
-            E item = p.item;
-            if (item != null && p.casItem(item, null)) {
-                unlink(p);
-                return item;
+        restart: for (;;) {
+            for (Node<E> last = last(), p = last;;) {
+                final E item;
+                if ((item = p.item) != null) {
+                    // recheck for linearizability
+                    if (last.next != null) continue restart;
+                    if (ITEM.compareAndSet(p, item, null)) {
+                        unlink(p);
+                        return item;
+                    }
+                }
+                if (p == (p = p.prev)) continue restart;
+                if (p == null) {
+                    if (last.next != null) continue restart;
+                    return null;
+                }
             }
         }
-        return null;
     }
 
     /**
@@ -1030,8 +1029,10 @@
     public boolean removeFirstOccurrence(Object o) {
         Objects.requireNonNull(o);
         for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null && o.equals(item) && p.casItem(item, null)) {
+            final E item;
+            if ((item = p.item) != null
+                && o.equals(item)
+                && ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return true;
             }
@@ -1054,8 +1055,10 @@
     public boolean removeLastOccurrence(Object o) {
         Objects.requireNonNull(o);
         for (Node<E> p = last(); p != null; p = pred(p)) {
-            E item = p.item;
-            if (item != null && o.equals(item) && p.casItem(item, null)) {
+            final E item;
+            if ((item = p.item) != null
+                && o.equals(item)
+                && ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return true;
             }
@@ -1074,8 +1077,8 @@
     public boolean contains(Object o) {
         if (o != null) {
             for (Node<E> p = first(); p != null; p = succ(p)) {
-                E item = p.item;
-                if (item != null && o.equals(item))
+                final E item;
+                if ((item = p.item) != null && o.equals(item))
                     return true;
             }
         }
@@ -1108,14 +1111,14 @@
      * @return the number of elements in this deque
      */
     public int size() {
-        restartFromHead: for (;;) {
+        restart: for (;;) {
             int count = 0;
             for (Node<E> p = first(); p != null;) {
                 if (p.item != null)
                     if (++count == Integer.MAX_VALUE)
                         break;  // @see Collection.size()
                 if (p == (p = p.next))
-                    continue restartFromHead;
+                    continue restart;
             }
             return count;
         }
@@ -1159,12 +1162,12 @@
         // Copy c into a private chain of Nodes
         Node<E> beginningOfTheEnd = null, last = null;
         for (E e : c) {
-            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
-                last.lazySetNext(newNode);
-                newNode.lazySetPrev(last);
+                NEXT.set(last, newNode);
+                PREV.set(newNode, last);
                 last = newNode;
             }
         }
@@ -1184,16 +1187,16 @@
                     continue restartFromTail;
                 else {
                     // p is last node
-                    beginningOfTheEnd.lazySetPrev(p); // CAS piggyback
-                    if (p.casNext(null, beginningOfTheEnd)) {
+                    PREV.set(beginningOfTheEnd, p); // CAS piggyback
+                    if (NEXT.compareAndSet(p, null, beginningOfTheEnd)) {
                         // Successful CAS is the linearization point
                         // for all elements to be added to this deque.
-                        if (!casTail(t, last)) {
+                        if (!TAIL.weakCompareAndSet(this, t, last)) {
                             // Try a little harder to update tail,
                             // since we may be adding many elements.
                             t = tail;
                             if (last.next == null)
-                                casTail(t, last);
+                                TAIL.weakCompareAndSet(this, t, last);
                         }
                         return true;
                     }
@@ -1212,12 +1215,12 @@
 
     public String toString() {
         String[] a = null;
-        restartFromHead: for (;;) {
+        restart: for (;;) {
             int charLength = 0;
             int size = 0;
             for (Node<E> p = first(); p != null;) {
-                E item = p.item;
-                if (item != null) {
+                final E item;
+                if ((item = p.item) != null) {
                     if (a == null)
                         a = new String[4];
                     else if (size == a.length)
@@ -1227,7 +1230,7 @@
                     charLength += s.length();
                 }
                 if (p == (p = p.next))
-                    continue restartFromHead;
+                    continue restart;
             }
 
             if (size == 0)
@@ -1239,11 +1242,11 @@
 
     private Object[] toArrayInternal(Object[] a) {
         Object[] x = a;
-        restartFromHead: for (;;) {
+        restart: for (;;) {
             int size = 0;
             for (Node<E> p = first(); p != null;) {
-                E item = p.item;
-                if (item != null) {
+                final E item;
+                if ((item = p.item) != null) {
                     if (x == null)
                         x = new Object[4];
                     else if (size == x.length)
@@ -1251,7 +1254,7 @@
                     x[size++] = item;
                 }
                 if (p == (p = p.next))
-                    continue restartFromHead;
+                    continue restart;
             }
             if (x == null)
                 return new Object[0];
@@ -1395,8 +1398,8 @@
                     nextItem = null;
                     break;
                 }
-                E item = p.item;
-                if (item != null) {
+                final E item;
+                if ((item = p.item) != null) {
                     nextNode = p;
                     nextItem = item;
                     break;
@@ -1426,90 +1429,75 @@
 
     /** Forward iterator */
     private class Itr extends AbstractItr {
+        Itr() {}                        // prevent access constructor creation
         Node<E> startNode() { return first(); }
         Node<E> nextNode(Node<E> p) { return succ(p); }
     }
 
     /** Descending iterator */
     private class DescendingItr extends AbstractItr {
+        DescendingItr() {}              // prevent access constructor creation
         Node<E> startNode() { return last(); }
         Node<E> nextNode(Node<E> p) { return pred(p); }
     }
 
     /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class CLDSpliterator<E> implements Spliterator<E> {
+    final class CLDSpliterator implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final ConcurrentLinkedDeque<E> queue;
         Node<E> current;    // current node; null until initialized
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
-        CLDSpliterator(ConcurrentLinkedDeque<E> queue) {
-            this.queue = queue;
-        }
 
         public Spliterator<E> trySplit() {
-            Node<E> p;
-            final ConcurrentLinkedDeque<E> q = this.queue;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
-                if (p.item == null && p == (p = p.next))
-                    current = p = q.first();
-                if (p != null && p.next != null) {
-                    Object[] a = new Object[n];
-                    int i = 0;
-                    do {
-                        if ((a[i] = p.item) != null)
-                            ++i;
-                        if (p == (p = p.next))
-                            p = q.first();
-                    } while (p != null && i < n);
-                    if ((current = p) == null)
-                        exhausted = true;
-                    if (i > 0) {
-                        batch = i;
-                        return Spliterators.spliterator
-                            (a, 0, i, (Spliterator.ORDERED |
-                                       Spliterator.NONNULL |
-                                       Spliterator.CONCURRENT));
-                    }
+            Node<E> p, q;
+            if ((p = current()) == null || (q = p.next) == null)
+                return null;
+            int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+            Object[] a = null;
+            do {
+                final E e;
+                if ((e = p.item) != null) {
+                    if (a == null)
+                        a = new Object[n];
+                    a[i++] = e;
                 }
-            }
-            return null;
+                if (p == (p = q))
+                    p = first();
+            } while (p != null && (q = p.next) != null && i < n);
+            setCurrent(p);
+            return (i == 0) ? null :
+                Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+                                                   Spliterator.NONNULL |
+                                                   Spliterator.CONCURRENT));
         }
 
         public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
             Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedDeque<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
+            if ((p = current()) != null) {
+                current = null;
                 exhausted = true;
                 do {
-                    E e = p.item;
-                    if (p == (p = p.next))
-                        p = q.first();
-                    if (e != null)
+                    final E e;
+                    if ((e = p.item) != null)
                         action.accept(e);
+                    if (p == (p = p.next))
+                        p = first();
                 } while (p != null);
             }
         }
 
         public boolean tryAdvance(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
             Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedDeque<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
+            if ((p = current()) != null) {
                 E e;
                 do {
                     e = p.item;
                     if (p == (p = p.next))
-                        p = q.first();
+                        p = first();
                 } while (e == null && p != null);
-                if ((current = p) == null)
-                    exhausted = true;
+                setCurrent(p);
                 if (e != null) {
                     action.accept(e);
                     return true;
@@ -1518,11 +1506,24 @@
             return false;
         }
 
+        private void setCurrent(Node<E> p) {
+            if ((current = p) == null)
+                exhausted = true;
+        }
+
+        private Node<E> current() {
+            Node<E> p;
+            if ((p = current) == null && !exhausted)
+                setCurrent(p = first());
+            return p;
+        }
+
         public long estimateSize() { return Long.MAX_VALUE; }
 
         public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
+            return (Spliterator.ORDERED |
+                    Spliterator.NONNULL |
+                    Spliterator.CONCURRENT);
         }
     }
 
@@ -1543,7 +1544,7 @@
      * @since 1.8
      */
     public Spliterator<E> spliterator() {
-        return new CLDSpliterator<E>(this);
+        return new CLDSpliterator();
     }
 
     /**
@@ -1562,8 +1563,8 @@
 
         // Write out all elements in the proper order.
         for (Node<E> p = first(); p != null; p = succ(p)) {
-            E item = p.item;
-            if (item != null)
+            final E item;
+            if ((item = p.item) != null)
                 s.writeObject(item);
         }
 
@@ -1586,43 +1587,91 @@
         Node<E> h = null, t = null;
         for (Object item; (item = s.readObject()) != null; ) {
             @SuppressWarnings("unchecked")
-            Node<E> newNode = new Node<E>((E) item);
+            Node<E> newNode = newNode((E) item);
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
         initHeadTail(h, t);
     }
 
-    private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
     }
 
-    private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
     }
 
-    // Unsafe mechanics
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
+    /** Implementation of bulk remove methods. */
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        boolean removed = false;
+        for (Node<E> p = first(), succ; p != null; p = succ) {
+            succ = succ(p);
+            final E item;
+            if ((item = p.item) != null
+                && filter.test(item)
+                && ITEM.compareAndSet(p, item, null)) {
+                unlink(p);
+                removed = true;
+            }
+        }
+        return removed;
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        E item;
+        for (Node<E> p = first(); p != null; p = succ(p))
+            if ((item = p.item) != null)
+                action.accept(item);
+    }
+
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle PREV;
+    private static final VarHandle NEXT;
+    private static final VarHandle ITEM;
     static {
         PREV_TERMINATOR = new Node<Object>();
         PREV_TERMINATOR.next = PREV_TERMINATOR;
         NEXT_TERMINATOR = new Node<Object>();
         NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentLinkedDeque.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (ConcurrentLinkedDeque.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentLinkedDeque.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(ConcurrentLinkedDeque.class, "tail",
+                                   Node.class);
+            PREV = l.findVarHandle(Node.class, "prev", Node.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
+            ITEM = l.findVarHandle(Node.class, "item", Object.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
index 7997c60..eac8ee7 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -45,10 +47,7 @@
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.function.Consumer;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.function.Predicate;
 
 /**
  * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
@@ -82,12 +81,12 @@
  * asynchronous nature of these queues, 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 {@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 {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
  *
  * <p>This class and its iterator implement all of the <em>optional</em>
  * methods of the {@link Queue} and {@link Iterator} interfaces.
@@ -99,6 +98,10 @@
  * actions subsequent to the access or removal of that element from
  * the {@code ConcurrentLinkedQueue} in another thread.
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this queue
@@ -110,7 +113,7 @@
     /*
      * This is a modification of the Michael & Scott algorithm,
      * adapted for a garbage-collected environment, with support for
-     * interior node deletion (to support remove(Object)).  For
+     * interior node deletion (to support e.g. remove(Object)).  For
      * explanation, read the paper.
      *
      * Note that like most non-blocking algorithms in this package,
@@ -158,17 +161,17 @@
      * it is possible for tail to lag behind head (why not)?
      *
      * CASing a Node's item reference to null atomically removes the
-     * element from the queue.  Iterators skip over Nodes with null
-     * items.  Prior implementations of this class had a race between
-     * poll() and remove(Object) where the same element would appear
-     * to be successfully removed by two concurrent operations.  The
-     * method remove(Object) also lazily unlinks deleted Nodes, but
-     * this is merely an optimization.
+     * element from the queue, leaving a "dead" node that should later
+     * be unlinked (but unlinking is merely an optimization).
+     * Interior element removal methods (other than Iterator.remove())
+     * keep track of the predecessor node during traversal so that the
+     * node can be CAS-unlinked.  Some traversal methods try to unlink
+     * any deleted nodes encountered during traversal.  See comments
+     * in bulkRemove.
      *
      * When constructing a Node (before enqueuing it) we avoid paying
-     * for a volatile write to item by using Unsafe.putObject instead
-     * of a normal write.  This allows the cost of enqueue to be
-     * "one-and-a-half" CASes.
+     * for a volatile write to item.  This allows the cost of enqueue
+     * to be "one-and-a-half" CASes.
      *
      * Both head and tail may or may not point to a Node with a
      * non-null item.  If the queue is empty, all items must of course
@@ -178,31 +181,33 @@
      * optimization.
      */
 
-    private static class Node<E> {
+    static final class Node<E> {
         volatile E item;
         volatile Node<E> next;
-    }
 
-    /**
-     * Returns a new node holding item.  Uses relaxed write because item
-     * can only be seen after piggy-backing publication via casNext.
-     */
-    static <E> Node<E> newNode(E item) {
-        Node<E> node = new Node<E>();
-        U.putObject(node, ITEM, item);
-        return node;
-    }
+        /**
+         * Constructs a node holding item.  Uses relaxed write because
+         * item can only be seen after piggy-backing publication via CAS.
+         */
+        Node(E item) {
+            ITEM.set(this, item);
+        }
 
-    static <E> boolean casItem(Node<E> node, E cmp, E val) {
-        return U.compareAndSwapObject(node, ITEM, cmp, val);
-    }
+        /** Constructs a dead dummy node. */
+        Node() {}
 
-    static <E> void lazySetNext(Node<E> node, Node<E> val) {
-        U.putOrderedObject(node, NEXT, val);
-    }
+        void appendRelaxed(Node<E> next) {
+            // assert next != null;
+            // assert this.next == null;
+            NEXT.set(this, next);
+        }
 
-    static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(node, NEXT, cmp, val);
+        boolean casItem(E cmp, E val) {
+            // assert item == cmp || item == null;
+            // assert cmp != null;
+            // assert val == null;
+            return ITEM.compareAndSet(this, cmp, val);
+        }
     }
 
     /**
@@ -229,7 +234,7 @@
      * - tail.item may or may not be null.
      * - it is permitted for tail to lag behind head, that is, for tail
      *   to not be reachable from head!
-     * - tail.next may or may not be self-pointing to tail.
+     * - tail.next may or may not be self-linked.
      */
     private transient volatile Node<E> tail;
 
@@ -237,7 +242,7 @@
      * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
      */
     public ConcurrentLinkedQueue() {
-        head = tail = newNode(null);
+        head = tail = new Node<E>();
     }
 
     /**
@@ -252,16 +257,14 @@
     public ConcurrentLinkedQueue(Collection<? extends E> c) {
         Node<E> h = null, t = null;
         for (E e : c) {
-            Node<E> newNode = newNode(Objects.requireNonNull(e));
+            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
             if (h == null)
                 h = t = newNode;
-            else {
-                lazySetNext(t, newNode);
-                t = newNode;
-            }
+            else
+                t.appendRelaxed(t = newNode);
         }
         if (h == null)
-            h = t = newNode(null);
+            h = t = new Node<E>();
         head = h;
         tail = t;
     }
@@ -286,8 +289,8 @@
      */
     final void updateHead(Node<E> h, Node<E> p) {
         // assert h != null && p != null && (h == p || h.item == null);
-        if (h != p && casHead(h, p))
-            lazySetNext(h, h);
+        if (h != p && HEAD.compareAndSet(this, h, p))
+            NEXT.setRelease(h, h);
     }
 
     /**
@@ -296,8 +299,49 @@
      * stale pointer that is now off the list.
      */
     final Node<E> succ(Node<E> p) {
-        Node<E> next = p.next;
-        return (p == next) ? head : next;
+        if (p == (p = p.next))
+            p = head;
+        return p;
+    }
+
+    /**
+     * Tries to CAS pred.next (or head, if pred is null) from c to p.
+     * Caller must ensure that we're not unlinking the trailing node.
+     */
+    private boolean tryCasSuccessor(Node<E> pred, Node<E> c, Node<E> p) {
+        // assert p != null;
+        // assert c.item == null;
+        // assert c != p;
+        if (pred != null)
+            return NEXT.compareAndSet(pred, c, p);
+        if (HEAD.compareAndSet(this, c, p)) {
+            NEXT.setRelease(c, c);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Collapse dead nodes between pred and q.
+     * @param pred the last known live node, or null if none
+     * @param c the first dead node
+     * @param p the last dead node
+     * @param q p.next: the next live node, or null if at end
+     * @return either old pred or p if pred dead or CAS failed
+     */
+    private Node<E> skipDeadNodes(Node<E> pred, Node<E> c, Node<E> p, Node<E> q) {
+        // assert pred != c;
+        // assert p != q;
+        // assert c.item == null;
+        // assert p.item == null;
+        if (q == null) {
+            // Never unlink trailing node.
+            if (c == p) return pred;
+            q = p;
+        }
+        return (tryCasSuccessor(pred, c, q)
+                && (pred == null || ITEM.get(pred) != null))
+            ? pred : p;
     }
 
     /**
@@ -308,18 +352,18 @@
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
-        final Node<E> newNode = newNode(Objects.requireNonNull(e));
+        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
 
         for (Node<E> t = tail, p = t;;) {
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, newNode)) {
+                if (NEXT.compareAndSet(p, null, newNode)) {
                     // Successful CAS is the linearization point
                     // for e to become an element of this queue,
                     // and for newNode to become "live".
-                    if (p != t) // hop two nodes at a time
-                        casTail(t, newNode);  // Failure is OK.
+                    if (p != t) // hop two nodes at a time; failure is OK
+                        TAIL.weakCompareAndSet(this, t, newNode);
                     return true;
                 }
                 // Lost CAS race to another thread; re-read next
@@ -337,12 +381,10 @@
     }
 
     public E poll() {
-        restartFromHead:
-        for (;;) {
-            for (Node<E> h = head, p = h, q;;) {
-                E item = p.item;
-
-                if (item != null && casItem(p, item, null)) {
+        restartFromHead: for (;;) {
+            for (Node<E> h = head, p = h, q;; p = q) {
+                final E item;
+                if ((item = p.item) != null && p.casItem(item, null)) {
                     // Successful CAS is the linearization point
                     // for item to be removed from this queue.
                     if (p != h) // hop two nodes at a time
@@ -355,25 +397,21 @@
                 }
                 else if (p == q)
                     continue restartFromHead;
-                else
-                    p = q;
             }
         }
     }
 
     public E peek() {
-        restartFromHead:
-        for (;;) {
-            for (Node<E> h = head, p = h, q;;) {
-                E item = p.item;
-                if (item != null || (q = p.next) == null) {
+        restartFromHead: for (;;) {
+            for (Node<E> h = head, p = h, q;; p = q) {
+                final E item;
+                if ((item = p.item) != null
+                    || (q = p.next) == null) {
                     updateHead(h, p);
                     return item;
                 }
                 else if (p == q)
                     continue restartFromHead;
-                else
-                    p = q;
             }
         }
     }
@@ -387,9 +425,8 @@
      * of losing a race to a concurrent poll().
      */
     Node<E> first() {
-        restartFromHead:
-        for (;;) {
-            for (Node<E> h = head, p = h, q;;) {
+        restartFromHead: for (;;) {
+            for (Node<E> h = head, p = h, q;; p = q) {
                 boolean hasItem = (p.item != null);
                 if (hasItem || (q = p.next) == null) {
                     updateHead(h, p);
@@ -397,8 +434,6 @@
                 }
                 else if (p == q)
                     continue restartFromHead;
-                else
-                    p = q;
             }
         }
     }
@@ -451,14 +486,25 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        if (o != null) {
-            for (Node<E> p = first(); p != null; p = succ(p)) {
-                E item = p.item;
-                if (item != null && o.equals(item))
-                    return true;
+        if (o == null) return false;
+        restartFromHead: for (;;) {
+            for (Node<E> p = head, pred = null; p != null; ) {
+                Node<E> q = p.next;
+                final E item;
+                if ((item = p.item) != null) {
+                    if (o.equals(item))
+                        return true;
+                    pred = p; p = q; continue;
+                }
+                for (Node<E> c = p;; q = p.next) {
+                    if (q == null || q.item != null) {
+                        pred = skipDeadNodes(pred, c, p, q); p = q; break;
+                    }
+                    if (p == (p = q)) continue restartFromHead;
+                }
             }
+            return false;
         }
-        return false;
     }
 
     /**
@@ -473,27 +519,27 @@
      * @return {@code true} if this queue changed as a result of the call
      */
     public boolean remove(Object o) {
-        if (o != null) {
-            Node<E> next, pred = null;
-            for (Node<E> p = first(); p != null; pred = p, p = next) {
-                boolean removed = false;
-                E item = p.item;
-                if (item != null) {
-                    if (!o.equals(item)) {
-                        next = succ(p);
-                        continue;
+        if (o == null) return false;
+        restartFromHead: for (;;) {
+            for (Node<E> p = head, pred = null; p != null; ) {
+                Node<E> q = p.next;
+                final E item;
+                if ((item = p.item) != null) {
+                    if (o.equals(item) && p.casItem(item, null)) {
+                        skipDeadNodes(pred, p, p, q);
+                        return true;
                     }
-                    removed = casItem(p, item, null);
+                    pred = p; p = q; continue;
                 }
-
-                next = succ(p);
-                if (pred != null && next != null) // unlink
-                    casNext(pred, p, next);
-                if (removed)
-                    return true;
+                for (Node<E> c = p;; q = p.next) {
+                    if (q == null || q.item != null) {
+                        pred = skipDeadNodes(pred, c, p, q); p = q; break;
+                    }
+                    if (p == (p = q)) continue restartFromHead;
+                }
             }
+            return false;
         }
-        return false;
     }
 
     /**
@@ -516,13 +562,11 @@
         // Copy c into a private chain of Nodes
         Node<E> beginningOfTheEnd = null, last = null;
         for (E e : c) {
-            Node<E> newNode = newNode(Objects.requireNonNull(e));
+            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
-            else {
-                lazySetNext(last, newNode);
-                last = newNode;
-            }
+            else
+                last.appendRelaxed(last = newNode);
         }
         if (beginningOfTheEnd == null)
             return false;
@@ -532,15 +576,15 @@
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, beginningOfTheEnd)) {
+                if (NEXT.compareAndSet(p, null, beginningOfTheEnd)) {
                     // Successful CAS is the linearization point
                     // for all elements to be added to this queue.
-                    if (!casTail(t, last)) {
+                    if (!TAIL.weakCompareAndSet(this, t, last)) {
                         // Try a little harder to update tail,
                         // since we may be adding many elements.
                         t = tail;
                         if (last.next == null)
-                            casTail(t, last);
+                            TAIL.weakCompareAndSet(this, t, last);
                     }
                     return true;
                 }
@@ -564,8 +608,8 @@
             int charLength = 0;
             int size = 0;
             for (Node<E> p = first(); p != null;) {
-                E item = p.item;
-                if (item != null) {
+                final E item;
+                if ((item = p.item) != null) {
                     if (a == null)
                         a = new String[4];
                     else if (size == a.length)
@@ -590,8 +634,8 @@
         restartFromHead: for (;;) {
             int size = 0;
             for (Node<E> p = first(); p != null;) {
-                E item = p.item;
-                if (item != null) {
+                final E item;
+                if ((item = p.item) != null) {
                     if (x == null)
                         x = new Object[4];
                     else if (size == x.length)
@@ -668,7 +712,7 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        if (a == null) throw new NullPointerException();
+        Objects.requireNonNull(a);
         return (T[]) toArrayInternal(a);
     }
 
@@ -708,7 +752,7 @@
             restartFromHead: for (;;) {
                 Node<E> h, p, q;
                 for (p = h = head;; p = q) {
-                    E item;
+                    final E item;
                     if ((item = p.item) != null) {
                         nextNode = p;
                         nextItem = item;
@@ -744,10 +788,12 @@
                 }
                 // unlink deleted nodes
                 if ((q = succ(p)) != null)
-                    casNext(pred, p, q);
+                    NEXT.compareAndSet(pred, p, q);
             }
         }
 
+        // Default implementation of forEachRemaining is "good enough".
+
         public void remove() {
             Node<E> l = lastRet;
             if (l == null) throw new IllegalStateException();
@@ -773,8 +819,8 @@
 
         // Write out all elements in the proper order.
         for (Node<E> p = first(); p != null; p = succ(p)) {
-            Object item = p.item;
-            if (item != null)
+            final E item;
+            if ((item = p.item) != null)
                 s.writeObject(item);
         }
 
@@ -797,91 +843,69 @@
         Node<E> h = null, t = null;
         for (Object item; (item = s.readObject()) != null; ) {
             @SuppressWarnings("unchecked")
-            Node<E> newNode = newNode((E) item);
+            Node<E> newNode = new Node<E>((E) item);
             if (h == null)
                 h = t = newNode;
-            else {
-                lazySetNext(t, newNode);
-                t = newNode;
-            }
+            else
+                t.appendRelaxed(t = newNode);
         }
         if (h == null)
-            h = t = newNode(null);
+            h = t = new Node<E>();
         head = h;
         tail = t;
     }
 
     /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class CLQSpliterator<E> implements Spliterator<E> {
+    final class CLQSpliterator implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final ConcurrentLinkedQueue<E> queue;
         Node<E> current;    // current node; null until initialized
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
-        CLQSpliterator(ConcurrentLinkedQueue<E> queue) {
-            this.queue = queue;
-        }
 
         public Spliterator<E> trySplit() {
-            Node<E> p;
-            final ConcurrentLinkedQueue<E> q = this.queue;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null) &&
-                p.next != null) {
-                Object[] a = new Object[n];
-                int i = 0;
-                do {
-                    if ((a[i] = p.item) != null)
-                        ++i;
-                    if (p == (p = p.next))
-                        p = q.first();
-                } while (p != null && i < n);
-                if ((current = p) == null)
-                    exhausted = true;
-                if (i > 0) {
-                    batch = i;
-                    return Spliterators.spliterator
-                        (a, 0, i, (Spliterator.ORDERED |
-                                   Spliterator.NONNULL |
-                                   Spliterator.CONCURRENT));
+            Node<E> p, q;
+            if ((p = current()) == null || (q = p.next) == null)
+                return null;
+            int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+            Object[] a = null;
+            do {
+                final E e;
+                if ((e = p.item) != null) {
+                    if (a == null)
+                        a = new Object[n];
+                    a[i++] = e;
                 }
-            }
-            return null;
+                if (p == (p = q))
+                    p = first();
+            } while (p != null && (q = p.next) != null && i < n);
+            setCurrent(p);
+            return (i == 0) ? null :
+                Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+                                                   Spliterator.NONNULL |
+                                                   Spliterator.CONCURRENT));
         }
 
         public void forEachRemaining(Consumer<? super E> action) {
-            Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedQueue<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
+            Objects.requireNonNull(action);
+            final Node<E> p;
+            if ((p = current()) != null) {
+                current = null;
                 exhausted = true;
-                do {
-                    E e = p.item;
-                    if (p == (p = p.next))
-                        p = q.first();
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
+                forEachFrom(action, p);
             }
         }
 
         public boolean tryAdvance(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
             Node<E> p;
-            if (action == null) throw new NullPointerException();
-            final ConcurrentLinkedQueue<E> q = this.queue;
-            if (!exhausted &&
-                ((p = current) != null || (p = q.first()) != null)) {
+            if ((p = current()) != null) {
                 E e;
                 do {
                     e = p.item;
                     if (p == (p = p.next))
-                        p = q.first();
+                        p = first();
                 } while (e == null && p != null);
-                if ((current = p) == null)
-                    exhausted = true;
+                setCurrent(p);
                 if (e != null) {
                     action.accept(e);
                     return true;
@@ -890,11 +914,24 @@
             return false;
         }
 
+        private void setCurrent(Node<E> p) {
+            if ((current = p) == null)
+                exhausted = true;
+        }
+
+        private Node<E> current() {
+            Node<E> p;
+            if ((p = current) == null && !exhausted)
+                setCurrent(p = first());
+            return p;
+        }
+
         public long estimateSize() { return Long.MAX_VALUE; }
 
         public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
+            return (Spliterator.ORDERED |
+                    Spliterator.NONNULL |
+                    Spliterator.CONCURRENT);
         }
     }
 
@@ -916,36 +953,123 @@
      */
     @Override
     public Spliterator<E> spliterator() {
-        return new CLQSpliterator<E>(this);
+        return new CLQSpliterator();
     }
 
-    private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
     }
 
-    private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
     }
 
-    // Unsafe mechanics
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
-    private static final long ITEM;
-    private static final long NEXT;
+    public void clear() {
+        bulkRemove(e -> true);
+    }
+
+    /**
+     * Tolerate this many consecutive dead nodes before CAS-collapsing.
+     * Amortized cost of clear() is (1 + 1/MAX_HOPS) CASes per element.
+     */
+    private static final int MAX_HOPS = 8;
+
+    /** Implementation of bulk remove methods. */
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        boolean removed = false;
+        restartFromHead: for (;;) {
+            int hops = MAX_HOPS;
+            // c will be CASed to collapse intervening dead nodes between
+            // pred (or head if null) and p.
+            for (Node<E> p = head, c = p, pred = null, q; p != null; p = q) {
+                q = p.next;
+                final E item; boolean pAlive;
+                if (pAlive = ((item = p.item) != null)) {
+                    if (filter.test(item)) {
+                        if (p.casItem(item, null))
+                            removed = true;
+                        pAlive = false;
+                    }
+                }
+                if (pAlive || q == null || --hops == 0) {
+                    // p might already be self-linked here, but if so:
+                    // - CASing head will surely fail
+                    // - CASing pred's next will be useless but harmless.
+                    if ((c != p && !tryCasSuccessor(pred, c, c = p))
+                        || pAlive) {
+                        // if CAS failed or alive, abandon old pred
+                        hops = MAX_HOPS;
+                        pred = p;
+                        c = q;
+                    }
+                } else if (p == q)
+                    continue restartFromHead;
+            }
+            return removed;
+        }
+    }
+
+    /**
+     * Runs action on each element found during a traversal starting at p.
+     * If p is null, the action is not run.
+     */
+    void forEachFrom(Consumer<? super E> action, Node<E> p) {
+        for (Node<E> pred = null; p != null; ) {
+            Node<E> q = p.next;
+            final E item;
+            if ((item = p.item) != null) {
+                action.accept(item);
+                pred = p; p = q; continue;
+            }
+            for (Node<E> c = p;; q = p.next) {
+                if (q == null || q.item != null) {
+                    pred = skipDeadNodes(pred, c, p, q); p = q; break;
+                }
+                if (p == (p = q)) { pred = null; p = head; break; }
+            }
+        }
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        forEachFrom(action, head);
+    }
+
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    static final VarHandle ITEM;
+    static final VarHandle NEXT;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentLinkedQueue.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (ConcurrentLinkedQueue.class.getDeclaredField("tail"));
-            ITEM = U.objectFieldOffset
-                (Node.class.getDeclaredField("item"));
-            NEXT = U.objectFieldOffset
-                (Node.class.getDeclaredField("next"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentLinkedQueue.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(ConcurrentLinkedQueue.class, "tail",
+                                   Node.class);
+            ITEM = l.findVarHandle(Node.class, "item", Object.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentMap.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentMap.java
index 69dae6f..2037e31 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentMap.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentMap.java
@@ -41,14 +41,8 @@
 import java.util.function.BiFunction;
 import java.util.function.Function;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// fixed framework docs link to "Collection#optional"
-// END android-note
-
 /**
- * A {@link java.util.Map} providing thread safety and atomicity
- * guarantees.
+ * A {@link Map} providing thread safety and atomicity guarantees.
  *
  * <p>To maintain the specified guarantees, default implementations of
  * methods including {@link #putIfAbsent} inherited from {@link Map}
@@ -65,6 +59,10 @@
  * actions subsequent to the access or removal of that object from
  * the {@code ConcurrentMap} in another thread.
  *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <K> the type of keys maintained by this map
@@ -182,10 +180,10 @@
      *         is not supported by this map
      * @throws ClassCastException if the key or value is of an inappropriate
      *         type for this map
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified key or value is null,
      *         and this map does not permit null keys or values
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      */
     boolean remove(Object key, Object value);
 
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
index 94a90cd..1666c8b 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
@@ -38,14 +38,14 @@
 import java.util.NavigableMap;
 import java.util.NavigableSet;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
-
 /**
  * A {@link ConcurrentMap} supporting {@link NavigableMap} operations,
  * and recursively so for its navigable sub-maps.
  *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @author Doug Lea
  * @param <K> the type of keys maintained by this map
  * @param <V> the type of mapped values
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
index 583244b..92888f7 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.io.Serializable;
 import java.util.AbstractCollection;
 import java.util.AbstractMap;
@@ -46,7 +48,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.NavigableMap;
 import java.util.NavigableSet;
 import java.util.NoSuchElementException;
 import java.util.Set;
@@ -57,10 +58,7 @@
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.concurrent.atomic.LongAdder;
 
 /**
  * A scalable concurrent {@link ConcurrentNavigableMap} implementation.
@@ -89,12 +87,7 @@
  * 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 {@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 {@code putAll}, {@code equals},
+ * <p>Beware that 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 {@code putAll} operation
@@ -107,6 +100,10 @@
  * null return values cannot be reliably distinguished from the absence of
  * elements.
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @author Doug Lea
  * @param <K> the type of keys maintained by this map
  * @param <V> the type of mapped values
@@ -157,42 +154,35 @@
      * be slow and space-intensive using AtomicMarkedReference), nodes
      * use direct CAS'able next pointers.  On deletion, instead of
      * marking a pointer, they splice in another node that can be
-     * thought of as standing for a marked pointer (indicating this by
-     * using otherwise impossible field values).  Using plain nodes
-     * acts roughly like "boxed" implementations of marked pointers,
-     * but uses new nodes only when nodes are deleted, not for every
-     * link.  This requires less space and supports faster
-     * traversal. Even if marked references were better supported by
-     * JVMs, traversal using this technique might still be faster
-     * because any search need only read ahead one more node than
-     * otherwise required (to check for trailing marker) rather than
-     * unmasking mark bits or whatever on each read.
+     * thought of as standing for a marked pointer (see method
+     * unlinkNode).  Using plain nodes acts roughly like "boxed"
+     * implementations of marked pointers, but uses new nodes only
+     * when nodes are deleted, not for every link.  This requires less
+     * space and supports faster traversal. Even if marked references
+     * were better supported by JVMs, traversal using this technique
+     * might still be faster because any search need only read ahead
+     * one more node than otherwise required (to check for trailing
+     * marker) rather than unmasking mark bits or whatever on each
+     * read.
      *
      * This approach maintains the essential property needed in the HM
      * algorithm of changing the next-pointer of a deleted node so
      * that any other CAS of it will fail, but implements the idea by
-     * changing the pointer to point to a different node, not by
-     * marking it.  While it would be possible to further squeeze
-     * space by defining marker nodes not to have key/value fields, it
-     * isn't worth the extra type-testing overhead.  The deletion
-     * markers are rarely encountered during traversal and are
-     * normally quickly garbage collected. (Note that this technique
-     * would not work well in systems without garbage collection.)
+     * changing the pointer to point to a different node (with
+     * otherwise illegal null fields), not by marking it.  While it
+     * would be possible to further squeeze space by defining marker
+     * nodes not to have key/value fields, it isn't worth the extra
+     * type-testing overhead.  The deletion markers are rarely
+     * encountered during traversal, are easily detected via null
+     * checks that are needed anyway, and are normally quickly garbage
+     * collected. (Note that this technique would not work well in
+     * systems without garbage collection.)
      *
      * In addition to using deletion markers, the lists also use
      * nullness of value fields to indicate deletion, in a style
      * similar to typical lazy-deletion schemes.  If a node's value is
      * null, then it is considered logically deleted and ignored even
-     * though it is still reachable. This maintains proper control of
-     * concurrent replace vs delete operations -- an attempted replace
-     * must fail if a delete beat it by nulling field, and a delete
-     * must return the last non-null value held in the field. (Note:
-     * Null, rather than some special marker, is used for value fields
-     * here because it just so happens to mesh with the Map API
-     * requirement that method get returns null if there is no
-     * mapping, which allows nodes to remain concurrently readable
-     * even when deleted. Using any other marker value here would be
-     * messy at best.)
+     * though it is still reachable.
      *
      * Here's the sequence of events for a deletion of node n with
      * predecessor b and successor f, initially:
@@ -202,9 +192,8 @@
      *        +------+       +------+      +------+
      *
      * 1. CAS n's value field from non-null to null.
-     *    From this point on, no public operations encountering
-     *    the node consider this mapping to exist. However, other
-     *    ongoing insertions and deletions might still modify
+     *    Traversals encountering a node with null value ignore it.
+     *    However, ongoing insertions and deletions might still modify
      *    n's next pointer.
      *
      * 2. CAS n's next pointer to point to a new marker node.
@@ -227,12 +216,7 @@
      * thread noticed during a traversal a node with null value and
      * helped out by marking and/or unlinking.  This helping-out
      * ensures that no thread can become stuck waiting for progress of
-     * the deleting thread.  The use of marker nodes slightly
-     * complicates helping-out code because traversals must track
-     * consistent reads of up to four nodes (b, n, marker, f), not
-     * just (b, n, f), although the next field of a marker is
-     * immutable, and once a next field is CAS'ed to point to a
-     * marker, it never again changes, so this requires less care.
+     * the deleting thread.
      *
      * Skip lists add indexing to this scheme, so that the base-level
      * traversals start close to the locations being found, inserted
@@ -242,113 +226,101 @@
      * b) that are not (structurally) deleted, otherwise retrying
      * after processing the deletion.
      *
-     * Index levels are maintained as lists with volatile next fields,
-     * using CAS to link and unlink.  Races are allowed in index-list
-     * operations that can (rarely) fail to link in a new index node
-     * or delete one. (We can't do this of course for data nodes.)
-     * However, even when this happens, the index lists remain sorted,
-     * so correctly serve as indices.  This can impact performance,
-     * but since skip lists are probabilistic anyway, the net result
-     * is that under contention, the effective "p" value may be lower
-     * than its nominal value. And race windows are kept small enough
-     * that in practice these failures are rare, even under a lot of
-     * contention.
+     * Index levels are maintained using CAS to link and unlink
+     * successors ("right" fields).  Races are allowed in index-list
+     * operations that can (rarely) fail to link in a new index node.
+     * (We can't do this of course for data nodes.)  However, even
+     * when this happens, the index lists correctly guide search.
+     * This can impact performance, but since skip lists are
+     * probabilistic anyway, the net result is that under contention,
+     * the effective "p" value may be lower than its nominal value.
      *
-     * The fact that retries (for both base and index lists) are
-     * relatively cheap due to indexing allows some minor
-     * simplifications of retry logic. Traversal restarts are
-     * performed after most "helping-out" CASes. This isn't always
-     * strictly necessary, but the implicit backoffs tend to help
-     * reduce other downstream failed CAS's enough to outweigh restart
-     * cost.  This worsens the worst case, but seems to improve even
-     * highly contended cases.
-     *
-     * Unlike most skip-list implementations, index insertion and
-     * deletion here require a separate traversal pass occurring after
-     * the base-level action, to add or remove index nodes.  This adds
-     * to single-threaded overhead, but improves contended
-     * multithreaded performance by narrowing interference windows,
-     * and allows deletion to ensure that all index nodes will be made
-     * unreachable upon return from a public remove operation, thus
-     * avoiding unwanted garbage retention. This is more important
-     * here than in some other data structures because we cannot null
-     * out node fields referencing user keys since they might still be
-     * read by other ongoing traversals.
+     * Index insertion and deletion sometimes require a separate
+     * traversal pass occurring after the base-level action, to add or
+     * remove index nodes.  This adds to single-threaded overhead, but
+     * improves contended multithreaded performance by narrowing
+     * interference windows, and allows deletion to ensure that all
+     * index nodes will be made unreachable upon return from a public
+     * remove operation, thus avoiding unwanted garbage retention.
      *
      * Indexing uses skip list parameters that maintain good search
      * performance while using sparser-than-usual indices: The
-     * hardwired parameters k=1, p=0.5 (see method doPut) mean
-     * that about one-quarter of the nodes have indices. Of those that
-     * do, half have one level, a quarter have two, and so on (see
-     * Pugh's Skip List Cookbook, sec 3.4).  The expected total space
-     * requirement for a map is slightly less than for the current
-     * implementation of java.util.TreeMap.
+     * hardwired parameters k=1, p=0.5 (see method doPut) mean that
+     * about one-quarter of the nodes have indices. Of those that do,
+     * half have one level, a quarter have two, and so on (see Pugh's
+     * Skip List Cookbook, sec 3.4), up to a maximum of 62 levels
+     * (appropriate for up to 2^63 elements).  The expected total
+     * space requirement for a map is slightly less than for the
+     * current implementation of java.util.TreeMap.
      *
      * Changing the level of the index (i.e, the height of the
-     * tree-like structure) also uses CAS. The head index has initial
-     * level/height of one. Creation of an index with height greater
-     * than the current level adds a level to the head index by
-     * CAS'ing on a new top-most head. To maintain good performance
-     * after a lot of removals, deletion methods heuristically try to
-     * reduce the height if the topmost levels appear to be empty.
-     * This may encounter races in which it possible (but rare) to
-     * reduce and "lose" a level just as it is about to contain an
-     * index (that will then never be encountered). This does no
-     * structural harm, and in practice appears to be a better option
-     * than allowing unrestrained growth of levels.
+     * tree-like structure) also uses CAS.  Creation of an index with
+     * height greater than the current level adds a level to the head
+     * index by CAS'ing on a new top-most head. To maintain good
+     * performance after a lot of removals, deletion methods
+     * heuristically try to reduce the height if the topmost levels
+     * appear to be empty.  This may encounter races in which it is
+     * possible (but rare) to reduce and "lose" a level just as it is
+     * about to contain an index (that will then never be
+     * encountered). This does no structural harm, and in practice
+     * appears to be a better option than allowing unrestrained growth
+     * of levels.
      *
-     * The code for all this is more verbose than you'd like. Most
-     * operations entail locating an element (or position to insert an
-     * element). The code to do this can't be nicely factored out
-     * because subsequent uses require a snapshot of predecessor
-     * and/or successor and/or value fields which can't be returned
-     * all at once, at least not without creating yet another object
-     * to hold them -- creating such little objects is an especially
-     * bad idea for basic internal search operations because it adds
-     * to GC overhead.  (This is one of the few times I've wished Java
-     * had macros.) Instead, some traversal code is interleaved within
-     * insertion and removal operations.  The control logic to handle
-     * all the retry conditions is sometimes twisty. Most search is
-     * broken into 2 parts. findPredecessor() searches index nodes
-     * only, returning a base-level predecessor of the key. findNode()
-     * finishes out the base-level search. Even with this factoring,
-     * there is a fair amount of near-duplication of code to handle
-     * variants.
+     * This class provides concurrent-reader-style memory consistency,
+     * ensuring that read-only methods report status and/or values no
+     * staler than those holding at method entry. This is done by
+     * performing all publication and structural updates using
+     * (volatile) CAS, placing an acquireFence in a few access
+     * methods, and ensuring that linked objects are transitively
+     * acquired via dependent reads (normally once) unless performing
+     * a volatile-mode CAS operation (that also acts as an acquire and
+     * release).  This form of fence-hoisting is similar to RCU and
+     * related techniques (see McKenney's online book
+     * https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html)
+     * It minimizes overhead that may otherwise occur when using so
+     * many volatile-mode reads. Using explicit acquireFences is
+     * logistically easier than targeting particular fields to be read
+     * in acquire mode: fences are just hoisted up as far as possible,
+     * to the entry points or loop headers of a few methods. A
+     * potential disadvantage is that these few remaining fences are
+     * not easily optimized away by compilers under exclusively
+     * single-thread use.  It requires some care to avoid volatile
+     * mode reads of other fields. (Note that the memory semantics of
+     * a reference dependently read in plain mode exactly once are
+     * equivalent to those for atomic opaque mode.)  Iterators and
+     * other traversals encounter each node and value exactly once.
+     * Other operations locate an element (or position to insert an
+     * element) via a sequence of dereferences. This search is broken
+     * into two parts. Method findPredecessor (and its specialized
+     * embeddings) searches index nodes only, returning a base-level
+     * predecessor of the key. Callers carry out the base-level
+     * search, restarting if encountering a marker preventing link
+     * modification.  In some cases, it is possible to encounter a
+     * node multiple times while descending levels. For mutative
+     * operations, the reported value is validated using CAS (else
+     * retrying), preserving linearizability with respect to each
+     * other. Others may return any (non-null) value holding in the
+     * course of the method call.  (Search-based methods also include
+     * some useless-looking explicit null checks designed to allow
+     * more fields to be nulled out upon removal, to reduce floating
+     * garbage, but which is not currently done, pending discovery of
+     * a way to do this with less impact on other operations.)
      *
      * To produce random values without interference across threads,
      * we use within-JDK thread local random support (via the
      * "secondary seed", to avoid interference with user-level
      * ThreadLocalRandom.)
      *
-     * A previous version of this class wrapped non-comparable keys
-     * with their comparators to emulate Comparables when using
-     * comparators vs Comparables.  However, JVMs now appear to better
-     * handle infusing comparator-vs-comparable choice into search
-     * loops. Static method cpr(comparator, x, y) is used for all
-     * comparisons, which works well as long as the comparator
-     * argument is set up outside of loops (thus sometimes passed as
-     * an argument to internal methods) to avoid field re-reads.
-     *
      * For explanation of algorithms sharing at least a couple of
      * features with this one, see Mikhail Fomitchev's thesis
      * (http://www.cs.yorku.ca/~mikhail/), Keir Fraser's thesis
      * (http://www.cl.cam.ac.uk/users/kaf24/), and Hakan Sundell's
      * thesis (http://www.cs.chalmers.se/~phs/).
      *
-     * Given the use of tree-like index nodes, you might wonder why
-     * this doesn't use some kind of search tree instead, which would
-     * support somewhat faster search operations. The reason is that
-     * there are no known efficient lock-free insertion and deletion
-     * algorithms for search trees. The immutability of the "down"
-     * links of index nodes (as opposed to mutable "left" fields in
-     * true trees) makes this tractable using only CAS operations.
-     *
      * Notation guide for local variables
-     * Node:         b, n, f    for  predecessor, node, successor
+     * Node:         b, n, f, p for  predecessor, node, successor, aux
      * Index:        q, r, d    for index node, right, down.
-     *               t          for another index node
      * Head:         h
-     * Levels:       j
      * Keys:         k, key
      * Values:       v, value
      * Comparisons:  c
@@ -357,16 +329,6 @@
     private static final long serialVersionUID = -8627078645895051609L;
 
     /**
-     * Special value used to identify base-level header.
-     */
-    static final Object BASE_HEADER = new Object();
-
-    /**
-     * The topmost head index of the skiplist.
-     */
-    private transient volatile HeadIndex<K,V> head;
-
-    /**
      * The comparator used to maintain order in this map, or null if
      * using natural ordering.  (Non-private to simplify access in
      * nested classes.)
@@ -374,316 +336,152 @@
      */
     final Comparator<? super K> comparator;
 
+    /** Lazily initialized topmost index of the skiplist. */
+    private transient Index<K,V> head;
+    /** Lazily initialized element count */
+    private transient LongAdder adder;
     /** Lazily initialized key set */
     private transient KeySet<K,V> keySet;
-    /** Lazily initialized entry set */
-    private transient EntrySet<K,V> entrySet;
     /** Lazily initialized values collection */
     private transient Values<K,V> values;
-    /** Lazily initialized descending key set */
-    private transient ConcurrentNavigableMap<K,V> descendingMap;
-
-    /**
-     * Initializes or resets state. Needed by constructors, clone,
-     * clear, readObject. and ConcurrentSkipListSet.clone.
-     * (Note that comparator must be separately initialized.)
-     */
-    private void initialize() {
-        keySet = null;
-        entrySet = null;
-        values = null;
-        descendingMap = null;
-        head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
-                                  null, null, 1);
-    }
-
-    /**
-     * compareAndSet head node.
-     */
-    private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
-    }
-
-    /* ---------------- Nodes -------------- */
+    /** Lazily initialized entry set */
+    private transient EntrySet<K,V> entrySet;
+    /** Lazily initialized descending map */
+    private transient SubMap<K,V> descendingMap;
 
     /**
      * Nodes hold keys and values, and are singly linked in sorted
      * order, possibly with some intervening marker nodes. The list is
-     * headed by a dummy node accessible as head.node. The value field
-     * is declared only as Object because it takes special non-V
-     * values for marker and header nodes.
+     * headed by a header node accessible as head.node. Headers and
+     * marker nodes have null keys. The val field (but currently not
+     * the key field) is nulled out upon deletion.
      */
     static final class Node<K,V> {
-        final K key;
-        volatile Object value;
-        volatile Node<K,V> next;
-
-        /**
-         * Creates a new regular node.
-         */
-        Node(K key, Object value, Node<K,V> next) {
+        final K key; // currently, never detached
+        V val;
+        Node<K,V> next;
+        Node(K key, V value, Node<K,V> next) {
             this.key = key;
-            this.value = value;
+            this.val = value;
             this.next = next;
         }
-
-        /**
-         * Creates a new marker node. A marker is distinguished by
-         * having its value field point to itself.  Marker nodes also
-         * have null keys, a fact that is exploited in a few places,
-         * but this doesn't distinguish markers from the base-level
-         * header node (head.node), which also has a null key.
-         */
-        Node(Node<K,V> next) {
-            this.key = null;
-            this.value = this;
-            this.next = next;
-        }
-
-        /**
-         * compareAndSet value field.
-         */
-        boolean casValue(Object cmp, Object val) {
-            return U.compareAndSwapObject(this, VALUE, cmp, val);
-        }
-
-        /**
-         * compareAndSet next field.
-         */
-        boolean casNext(Node<K,V> cmp, Node<K,V> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
-        }
-
-        /**
-         * Returns true if this node is a marker. This method isn't
-         * actually called in any current code checking for markers
-         * 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.
-         *
-         * @return true if this node is a marker node
-         */
-        boolean isMarker() {
-            return value == this;
-        }
-
-        /**
-         * Returns true if this node is the header of base-level list.
-         * @return true if this node is header node
-         */
-        boolean isBaseHeader() {
-            return value == BASE_HEADER;
-        }
-
-        /**
-         * Tries to append a deletion marker to this node.
-         * @param f the assumed current successor of this node
-         * @return true if successful
-         */
-        boolean appendMarker(Node<K,V> f) {
-            return casNext(f, new Node<K,V>(f));
-        }
-
-        /**
-         * Helps out a deletion by appending marker or unlinking from
-         * predecessor. This is called during traversals when value
-         * field seen to be null.
-         * @param b predecessor
-         * @param f successor
-         */
-        void helpDelete(Node<K,V> b, Node<K,V> f) {
-            /*
-             * Rechecking links and then doing only one of the
-             * help-out stages per call tends to minimize CAS
-             * interference among helping threads.
-             */
-            if (f == next && this == b.next) {
-                if (f == null || f.value != f) // not already marked
-                    casNext(f, new Node<K,V>(f));
-                else
-                    b.casNext(this, f.next);
-            }
-        }
-
-        /**
-         * 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
-         */
-        V getValidValue() {
-            Object v = value;
-            if (v == this || v == BASE_HEADER)
-                return null;
-            @SuppressWarnings("unchecked") V vv = (V)v;
-            return vv;
-        }
-
-        /**
-         * Creates and returns a new SimpleImmutableEntry holding current
-         * mapping if this node holds a valid value, else null.
-         * @return new entry or null
-         */
-        AbstractMap.SimpleImmutableEntry<K,V> createSnapshot() {
-            Object v = value;
-            if (v == null || v == this || v == BASE_HEADER)
-                return null;
-            @SuppressWarnings("unchecked") V vv = (V)v;
-            return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
-        }
-
-        // Unsafe mechanics
-
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
-        private static final long NEXT;
-
-        static {
-            try {
-                VALUE = U.objectFieldOffset
-                    (Node.class.getDeclaredField("value"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-        }
     }
 
-    /* ---------------- Indexing -------------- */
-
     /**
-     * Index nodes represent the levels of the skip list.  Note that
-     * even though both Nodes and Indexes have forward-pointing
-     * fields, they have different types and are handled in different
-     * ways, that can't nicely be captured by placing field in a
-     * shared abstract class.
+     * Index nodes represent the levels of the skip list.
      */
-    static class Index<K,V> {
-        final Node<K,V> node;
+    static final class Index<K,V> {
+        final Node<K,V> node;  // currently, never detached
         final Index<K,V> down;
-        volatile Index<K,V> right;
-
-        /**
-         * Creates index node with given values.
-         */
+        Index<K,V> right;
         Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) {
             this.node = node;
             this.down = down;
             this.right = right;
         }
-
-        /**
-         * compareAndSet right field.
-         */
-        final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
-            return U.compareAndSwapObject(this, RIGHT, cmp, val);
-        }
-
-        /**
-         * Returns true if the node this indexes has been deleted.
-         * @return true if indexed node is known to be deleted
-         */
-        final boolean indexesDeletedNode() {
-            return node.value == null;
-        }
-
-        /**
-         * Tries to CAS newSucc as successor.  To minimize races with
-         * unlink that may lose this index node, if the node being
-         * indexed is known to be deleted, it doesn't try to link in.
-         * @param succ the expected current successor
-         * @param newSucc the new successor
-         * @return true if successful
-         */
-        final boolean link(Index<K,V> succ, Index<K,V> newSucc) {
-            Node<K,V> n = node;
-            newSucc.right = succ;
-            return n.value != null && casRight(succ, newSucc);
-        }
-
-        /**
-         * Tries to CAS right field to skip over apparent successor
-         * succ.  Fails (forcing a retraversal by caller) if this node
-         * is known to be deleted.
-         * @param succ the expected current successor
-         * @return true if successful
-         */
-        final boolean unlink(Index<K,V> succ) {
-            return node.value != null && casRight(succ, succ.right);
-        }
-
-        // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long RIGHT;
-        static {
-            try {
-                RIGHT = U.objectFieldOffset
-                    (Index.class.getDeclaredField("right"));
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-        }
     }
 
-    /* ---------------- Head nodes -------------- */
-
-    /**
-     * Nodes heading each level keep track of their level.
-     */
-    static final class HeadIndex<K,V> extends Index<K,V> {
-        final int level;
-        HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right, int level) {
-            super(node, down, right);
-            this.level = level;
-        }
-    }
-
-    /* ---------------- Comparison utilities -------------- */
+    /* ----------------  Utilities -------------- */
 
     /**
      * Compares using comparator or natural ordering if null.
      * Called only by methods that have performed required type checks.
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
-    static final int cpr(Comparator c, Object x, Object y) {
+    static int cpr(Comparator c, Object x, Object y) {
         return (c != null) ? c.compare(x, y) : ((Comparable)x).compareTo(y);
     }
 
+    /**
+     * Returns the header for base node list, or null if uninitialized
+     */
+    final Node<K,V> baseHead() {
+        Index<K,V> h;
+        VarHandle.acquireFence();
+        return ((h = head) == null) ? null : h.node;
+    }
+
+    /**
+     * Tries to unlink deleted node n from predecessor b (if both
+     * exist), by first splicing in a marker if not already present.
+     * Upon return, node n is sure to be unlinked from b, possibly
+     * via the actions of some other thread.
+     *
+     * @param b if nonnull, predecessor
+     * @param n if nonnull, node known to be deleted
+     */
+    static <K,V> void unlinkNode(Node<K,V> b, Node<K,V> n) {
+        if (b != null && n != null) {
+            Node<K,V> f, p;
+            for (;;) {
+                if ((f = n.next) != null && f.key == null) {
+                    p = f.next;               // already marked
+                    break;
+                }
+                else if (NEXT.compareAndSet(n, f,
+                                            new Node<K,V>(null, null, f))) {
+                    p = f;                    // add marker
+                    break;
+                }
+            }
+            NEXT.compareAndSet(b, n, p);
+        }
+    }
+
+    /**
+     * Adds to element count, initializing adder if necessary
+     *
+     * @param c count to add
+     */
+    private void addCount(long c) {
+        LongAdder a;
+        do {} while ((a = adder) == null &&
+                     !ADDER.compareAndSet(this, null, a = new LongAdder()));
+        a.add(c);
+    }
+
+    /**
+     * Returns element count, initializing adder if necessary.
+     */
+    final long getAdderCount() {
+        LongAdder a; long c;
+        do {} while ((a = adder) == null &&
+                     !ADDER.compareAndSet(this, null, a = new LongAdder()));
+        return ((c = a.sum()) <= 0L) ? 0L : c; // ignore transient negatives
+    }
+
     /* ---------------- Traversal -------------- */
 
     /**
-     * Returns a base-level node with key strictly less than given key,
-     * or the base-level header if there is no such node.  Also
-     * unlinks indexes to deleted nodes found along the way.  Callers
-     * rely on this side-effect of clearing indices to deleted nodes.
-     * @param key the key
-     * @return a predecessor of key
+     * Returns an index node with key strictly less than given key.
+     * Also unlinks indexes to deleted nodes found along the way.
+     * Callers rely on this side-effect of clearing indices to deleted
+     * nodes.
+     *
+     * @param key if nonnull the key
+     * @return a predecessor node of key, or null if uninitialized or null key
      */
     private Node<K,V> findPredecessor(Object key, Comparator<? super K> cmp) {
-        if (key == null)
-            throw new NullPointerException(); // don't postpone errors
-        for (;;) {
-            for (Index<K,V> q = head, r = q.right, d;;) {
-                if (r != null) {
-                    Node<K,V> n = r.node;
-                    K k = n.key;
-                    if (n.value == null) {
-                        if (!q.unlink(r))
-                            break;           // restart
-                        r = q.right;         // reread r
-                        continue;
-                    }
-                    if (cpr(cmp, key, k) > 0) {
+        Index<K,V> q;
+        VarHandle.acquireFence();
+        if ((q = head) == null || key == null)
+            return null;
+        else {
+            for (Index<K,V> r, d;;) {
+                while ((r = q.right) != null) {
+                    Node<K,V> p; K k;
+                    if ((p = r.node) == null || (k = p.key) == null ||
+                        p.val == null)  // unlink index to deleted node
+                        RIGHT.compareAndSet(q, r, r.right);
+                    else if (cpr(cmp, key, k) > 0)
                         q = r;
-                        r = r.right;
-                        continue;
-                    }
+                    else
+                        break;
                 }
-                if ((d = q.down) == null)
+                if ((d = q.down) != null)
+                    q = d;
+                else
                     return q.node;
-                q = d;
-                r = d.right;
             }
         }
     }
@@ -693,41 +491,11 @@
      * deleted nodes seen along the way.  Repeatedly traverses at
      * base-level looking for key starting at predecessor returned
      * from findPredecessor, processing base-level deletions as
-     * encountered. Some callers rely on this side-effect of clearing
-     * deleted nodes.
-     *
-     * Restarts occur, at traversal step centered on node n, if:
-     *
-     *   (1) After reading n's next field, n is no longer assumed
-     *       predecessor b's current successor, which means that
-     *       we don't have a consistent 3-node snapshot and so cannot
-     *       unlink any subsequent deleted nodes encountered.
-     *
-     *   (2) n's value field is null, indicating n is deleted, in
-     *       which case we help out an ongoing structural deletion
-     *       before retrying.  Even though there are cases where such
-     *       unlinking doesn't require restart, they aren't sorted out
-     *       here because doing so would not usually outweigh cost of
-     *       restarting.
-     *
-     *   (3) n is a marker or n's predecessor's value field is null,
-     *       indicating (among other possibilities) that
-     *       findPredecessor returned a deleted node. We can't unlink
-     *       the node because we don't know its predecessor, so rely
-     *       on another call to findPredecessor to notice and return
-     *       some earlier predecessor, which it will do. This check is
-     *       only strictly needed at beginning of loop, (and the
-     *       b.value check isn't strictly needed at all) but is done
-     *       each iteration to help avoid contention with other
-     *       threads by callers that will fail to be able to change
-     *       links, and so will retry anyway.
-     *
-     * The traversal loops in doPut, doRemove, and findNear all
-     * include the same three kinds of checks. And specialized
-     * versions appear in findFirst, and findLast and their variants.
-     * They can't easily share code because each uses the reads of
-     * fields held in locals occurring in the orders they were
-     * performed.
+     * encountered. Restarts occur, at traversal step encountering
+     * node n, if n's key field is null, indicating it is a marker, so
+     * its predecessor is deleted before continuing, which we help do
+     * by re-finding a valid predecessor.  The traversal loops in
+     * doPut, doRemove, and findNear all include the same checks.
      *
      * @param key the key
      * @return node holding key, or null if no such
@@ -736,67 +504,81 @@
         if (key == null)
             throw new NullPointerException(); // don't postpone errors
         Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v; int c;
-                if (n == null)
-                    break outer;
-                Node<K,V> f = n.next;
-                if (n != b.next)                // inconsistent read
-                    break;
-                if ((v = n.value) == null) {    // n is deleted
-                    n.helpDelete(b, f);
-                    break;
-                }
-                if (b.value == null || v == n)  // b is deleted
-                    break;
-                if ((c = cpr(cmp, key, n.key)) == 0)
+        Node<K,V> b;
+        outer: while ((b = findPredecessor(key, cmp)) != null) {
+            for (;;) {
+                Node<K,V> n; K k; V v; int c;
+                if ((n = b.next) == null)
+                    break outer;               // empty
+                else if ((k = n.key) == null)
+                    break;                     // b is deleted
+                else if ((v = n.val) == null)
+                    unlinkNode(b, n);          // n is deleted
+                else if ((c = cpr(cmp, key, k)) > 0)
+                    b = n;
+                else if (c == 0)
                     return n;
-                if (c < 0)
+                else
                     break outer;
-                b = n;
-                n = f;
             }
         }
         return null;
     }
 
     /**
-     * Gets value for key. Almost the same as findNode, but returns
-     * the found value (to avoid retries during re-reads)
+     * Gets value for key. Same idea as findNode, except skips over
+     * deletions and markers, and returns first encountered value to
+     * avoid possibly inconsistent rereads.
      *
      * @param key the key
      * @return the value, or null if absent
      */
     private V doGet(Object key) {
+        Index<K,V> q;
+        VarHandle.acquireFence();
         if (key == null)
             throw new NullPointerException();
         Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v; int c;
-                if (n == null)
-                    break outer;
-                Node<K,V> f = n.next;
-                if (n != b.next)                // inconsistent read
-                    break;
-                if ((v = n.value) == null) {    // n is deleted
-                    n.helpDelete(b, f);
+        V result = null;
+        if ((q = head) != null) {
+            outer: for (Index<K,V> r, d;;) {
+                while ((r = q.right) != null) {
+                    Node<K,V> p; K k; V v; int c;
+                    if ((p = r.node) == null || (k = p.key) == null ||
+                        (v = p.val) == null)
+                        RIGHT.compareAndSet(q, r, r.right);
+                    else if ((c = cpr(cmp, key, k)) > 0)
+                        q = r;
+                    else if (c == 0) {
+                        result = v;
+                        break outer;
+                    }
+                    else
+                        break;
+                }
+                if ((d = q.down) != null)
+                    q = d;
+                else {
+                    Node<K,V> b, n;
+                    if ((b = q.node) != null) {
+                        while ((n = b.next) != null) {
+                            V v; int c;
+                            K k = n.key;
+                            if ((v = n.val) == null || k == null ||
+                                (c = cpr(cmp, key, k)) > 0)
+                                b = n;
+                            else {
+                                if (c == 0)
+                                    result = v;
+                                break;
+                            }
+                        }
+                    }
                     break;
                 }
-                if (b.value == null || v == n)  // b is deleted
-                    break;
-                if ((c = cpr(cmp, key, n.key)) == 0) {
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    return vv;
-                }
-                if (c < 0)
-                    break outer;
-                b = n;
-                n = f;
             }
         }
-        return null;
+        return result;
     }
 
     /* ---------------- Insertion -------------- */
@@ -804,126 +586,160 @@
     /**
      * Main insertion method.  Adds element if not present, or
      * replaces value if present and onlyIfAbsent is false.
+     *
      * @param key the 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
      */
     private V doPut(K key, V value, boolean onlyIfAbsent) {
-        Node<K,V> z;             // added node
         if (key == null)
             throw new NullPointerException();
         Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                if (n != null) {
-                    Object v; int c;
-                    Node<K,V> f = n.next;
-                    if (n != b.next)               // inconsistent read
-                        break;
-                    if ((v = n.value) == null) {   // n is deleted
-                        n.helpDelete(b, f);
-                        break;
-                    }
-                    if (b.value == null || v == n) // b is deleted
-                        break;
-                    if ((c = cpr(cmp, key, n.key)) > 0) {
-                        b = n;
-                        n = f;
-                        continue;
-                    }
-                    if (c == 0) {
-                        if (onlyIfAbsent || n.casValue(v, value)) {
-                            @SuppressWarnings("unchecked") V vv = (V)v;
-                            return vv;
-                        }
-                        break; // restart if lost race to replace value
-                    }
-                    // else c < 0; fall through
-                }
-
-                z = new Node<K,V>(key, value, n);
-                if (!b.casNext(n, z))
-                    break;         // restart if lost race to append to b
-                break outer;
+        for (;;) {
+            Index<K,V> h; Node<K,V> b;
+            VarHandle.acquireFence();
+            int levels = 0;                    // number of levels descended
+            if ((h = head) == null) {          // try to initialize
+                Node<K,V> base = new Node<K,V>(null, null, null);
+                h = new Index<K,V>(base, null, null);
+                b = (HEAD.compareAndSet(this, null, h)) ? base : null;
             }
-        }
-
-        int rnd = ThreadLocalRandom.nextSecondarySeed();
-        if ((rnd & 0x80000001) == 0) { // test highest and lowest bits
-            int level = 1, max;
-            while (((rnd >>>= 1) & 1) != 0)
-                ++level;
-            Index<K,V> idx = null;
-            HeadIndex<K,V> h = head;
-            if (level <= (max = h.level)) {
-                for (int i = 1; i <= level; ++i)
-                    idx = new Index<K,V>(z, idx, null);
-            }
-            else { // try to grow by one level
-                level = max + 1; // hold in array and later pick the one to use
-                @SuppressWarnings("unchecked")Index<K,V>[] idxs =
-                    (Index<K,V>[])new Index<?,?>[level+1];
-                for (int i = 1; i <= level; ++i)
-                    idxs[i] = idx = new Index<K,V>(z, idx, null);
-                for (;;) {
-                    h = head;
-                    int oldLevel = h.level;
-                    if (level <= oldLevel) // lost race to add level
-                        break;
-                    HeadIndex<K,V> newh = h;
-                    Node<K,V> oldbase = h.node;
-                    for (int j = oldLevel+1; j <= level; ++j)
-                        newh = new HeadIndex<K,V>(oldbase, newh, idxs[j], j);
-                    if (casHead(h, newh)) {
-                        h = newh;
-                        idx = idxs[level = oldLevel];
-                        break;
-                    }
-                }
-            }
-            // find insertion points and splice in
-            splice: for (int insertionLevel = level;;) {
-                int j = h.level;
-                for (Index<K,V> q = h, r = q.right, t = idx;;) {
-                    if (q == null || t == null)
-                        break splice;
-                    if (r != null) {
-                        Node<K,V> n = r.node;
-                        // compare before deletion check avoids needing recheck
-                        int c = cpr(cmp, key, n.key);
-                        if (n.value == null) {
-                            if (!q.unlink(r))
-                                break;
-                            r = q.right;
-                            continue;
-                        }
-                        if (c > 0) {
+            else {
+                for (Index<K,V> q = h, r, d;;) { // count while descending
+                    while ((r = q.right) != null) {
+                        Node<K,V> p; K k;
+                        if ((p = r.node) == null || (k = p.key) == null ||
+                            p.val == null)
+                            RIGHT.compareAndSet(q, r, r.right);
+                        else if (cpr(cmp, key, k) > 0)
                             q = r;
-                            r = r.right;
-                            continue;
-                        }
+                        else
+                            break;
                     }
-
-                    if (j == insertionLevel) {
-                        if (!q.link(r, t))
-                            break; // restart
-                        if (t.node.value == null) {
-                            findNode(key);
-                            break splice;
-                        }
-                        if (--insertionLevel == 0)
-                            break splice;
+                    if ((d = q.down) != null) {
+                        ++levels;
+                        q = d;
                     }
+                    else {
+                        b = q.node;
+                        break;
+                    }
+                }
+            }
+            if (b != null) {
+                Node<K,V> z = null;              // new node, if inserted
+                for (;;) {                       // find insertion point
+                    Node<K,V> n, p; K k; V v; int c;
+                    if ((n = b.next) == null) {
+                        if (b.key == null)       // if empty, type check key now
+                            cpr(cmp, key, key);
+                        c = -1;
+                    }
+                    else if ((k = n.key) == null)
+                        break;                   // can't append; restart
+                    else if ((v = n.val) == null) {
+                        unlinkNode(b, n);
+                        c = 1;
+                    }
+                    else if ((c = cpr(cmp, key, k)) > 0)
+                        b = n;
+                    else if (c == 0 &&
+                             (onlyIfAbsent || VAL.compareAndSet(n, v, value)))
+                        return v;
 
-                    if (--j >= insertionLevel && j < level)
-                        t = t.down;
-                    q = q.down;
-                    r = q.right;
+                    if (c < 0 &&
+                        NEXT.compareAndSet(b, n,
+                                           p = new Node<K,V>(key, value, n))) {
+                        z = p;
+                        break;
+                    }
+                }
+
+                if (z != null) {
+                    int lr = ThreadLocalRandom.nextSecondarySeed();
+                    if ((lr & 0x3) == 0) {       // add indices with 1/4 prob
+                        int hr = ThreadLocalRandom.nextSecondarySeed();
+                        long rnd = ((long)hr << 32) | ((long)lr & 0xffffffffL);
+                        int skips = levels;      // levels to descend before add
+                        Index<K,V> x = null;
+                        for (;;) {               // create at most 62 indices
+                            x = new Index<K,V>(z, x, null);
+                            if (rnd >= 0L || --skips < 0)
+                                break;
+                            else
+                                rnd <<= 1;
+                        }
+                        if (addIndices(h, skips, x, cmp) && skips < 0 &&
+                            head == h) {         // try to add new level
+                            Index<K,V> hx = new Index<K,V>(z, x, null);
+                            Index<K,V> nh = new Index<K,V>(h.node, h, hx);
+                            HEAD.compareAndSet(this, h, nh);
+                        }
+                        if (z.val == null)       // deleted while adding indices
+                            findPredecessor(key, cmp); // clean
+                    }
+                    addCount(1L);
+                    return null;
                 }
             }
         }
-        return null;
+    }
+
+    /**
+     * Add indices after an insertion. Descends iteratively to the
+     * highest level of insertion, then recursively, to chain index
+     * nodes to lower ones. Returns null on (staleness) failure,
+     * disabling higher-level insertions. Recursion depths are
+     * exponentially less probable.
+     *
+     * @param q starting index for current level
+     * @param skips levels to skip before inserting
+     * @param x index for this insertion
+     * @param cmp comparator
+     */
+    static <K,V> boolean addIndices(Index<K,V> q, int skips, Index<K,V> x,
+                                    Comparator<? super K> cmp) {
+        Node<K,V> z; K key;
+        if (x != null && (z = x.node) != null && (key = z.key) != null &&
+            q != null) {                            // hoist checks
+            boolean retrying = false;
+            for (;;) {                              // find splice point
+                Index<K,V> r, d; int c;
+                if ((r = q.right) != null) {
+                    Node<K,V> p; K k;
+                    if ((p = r.node) == null || (k = p.key) == null ||
+                        p.val == null) {
+                        RIGHT.compareAndSet(q, r, r.right);
+                        c = 0;
+                    }
+                    else if ((c = cpr(cmp, key, k)) > 0)
+                        q = r;
+                    else if (c == 0)
+                        break;                      // stale
+                }
+                else
+                    c = -1;
+
+                if (c < 0) {
+                    if ((d = q.down) != null && skips > 0) {
+                        --skips;
+                        q = d;
+                    }
+                    else if (d != null && !retrying &&
+                             !addIndices(d, 0, x.down, cmp))
+                        break;
+                    else {
+                        x.right = r;
+                        if (RIGHT.compareAndSet(q, r, x))
+                            return true;
+                        else
+                            retrying = true;         // re-find splice point
+                    }
+                }
+            }
+        }
+        return false;
     }
 
     /* ---------------- Deletion -------------- */
@@ -933,15 +749,6 @@
      * deletion marker, unlinks predecessor, removes associated index
      * nodes, and possibly reduces head index level.
      *
-     * Index nodes are cleared out simply by calling findPredecessor.
-     * which unlinks indexes to deleted nodes found along path to key,
-     * which will include the indexes to this node.  This is done
-     * unconditionally. We can't check beforehand whether there are
-     * index nodes because it might be the case that some or all
-     * indexes hadn't been inserted yet for this node during initial
-     * search for it, and we'd like to ensure lack of garbage
-     * retention, so must call to be sure.
-     *
      * @param key the key
      * @param value if non-null, the value that must be
      * associated with key
@@ -951,43 +758,36 @@
         if (key == null)
             throw new NullPointerException();
         Comparator<? super K> cmp = comparator;
-        outer: for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v; int c;
-                if (n == null)
+        V result = null;
+        Node<K,V> b;
+        outer: while ((b = findPredecessor(key, cmp)) != null &&
+                      result == null) {
+            for (;;) {
+                Node<K,V> n; K k; V v; int c;
+                if ((n = b.next) == null)
                     break outer;
-                Node<K,V> f = n.next;
-                if (n != b.next)                    // inconsistent read
+                else if ((k = n.key) == null)
                     break;
-                if ((v = n.value) == null) {        // n is deleted
-                    n.helpDelete(b, f);
-                    break;
-                }
-                if (b.value == null || v == n)      // b is deleted
-                    break;
-                if ((c = cpr(cmp, key, n.key)) < 0)
-                    break outer;
-                if (c > 0) {
+                else if ((v = n.val) == null)
+                    unlinkNode(b, n);
+                else if ((c = cpr(cmp, key, k)) > 0)
                     b = n;
-                    n = f;
-                    continue;
-                }
-                if (value != null && !value.equals(v))
+                else if (c < 0)
                     break outer;
-                if (!n.casValue(v, null))
-                    break;
-                if (!n.appendMarker(f) || !b.casNext(n, f))
-                    findNode(key);                  // retry via findNode
-                else {
-                    findPredecessor(key, cmp);      // clean index
-                    if (head.right == null)
-                        tryReduceLevel();
+                else if (value != null && !value.equals(v))
+                    break outer;
+                else if (VAL.compareAndSet(n, v, null)) {
+                    result = v;
+                    unlinkNode(b, n);
+                    break; // loop to clean up
                 }
-                @SuppressWarnings("unchecked") V vv = (V)v;
-                return vv;
             }
         }
-        return null;
+        if (result != null) {
+            tryReduceLevel();
+            addCount(-1L);
+        }
+        return result;
     }
 
     /**
@@ -1011,125 +811,71 @@
      * reduction.
      */
     private void tryReduceLevel() {
-        HeadIndex<K,V> h = head;
-        HeadIndex<K,V> d;
-        HeadIndex<K,V> e;
-        if (h.level > 3 &&
-            (d = (HeadIndex<K,V>)h.down) != null &&
-            (e = (HeadIndex<K,V>)d.down) != null &&
-            e.right == null &&
-            d.right == null &&
-            h.right == null &&
-            casHead(h, d) && // try to set
-            h.right != null) // recheck
-            casHead(d, h);   // try to backout
+        Index<K,V> h, d, e;
+        if ((h = head) != null && h.right == null &&
+            (d = h.down) != null && d.right == null &&
+            (e = d.down) != null && e.right == null &&
+            HEAD.compareAndSet(this, h, d) &&
+            h.right != null)   // recheck
+            HEAD.compareAndSet(this, d, h);  // try to backout
     }
 
     /* ---------------- Finding and removing first element -------------- */
 
     /**
-     * Specialized variant of findNode to get first valid node.
+     * Gets first valid node, unlinking deleted nodes if encountered.
      * @return first node or null if empty
      */
     final Node<K,V> findFirst() {
-        for (Node<K,V> b, n;;) {
-            if ((n = (b = head.node).next) == null)
-                return null;
-            if (n.value != null)
-                return n;
-            n.helpDelete(b, n.next);
+        Node<K,V> b, n;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if (n.val == null)
+                    unlinkNode(b, n);
+                else
+                    return n;
+            }
         }
+        return null;
+    }
+
+    /**
+     * Entry snapshot version of findFirst
+     */
+    final AbstractMap.SimpleImmutableEntry<K,V> findFirstEntry() {
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if ((v = n.val) == null)
+                    unlinkNode(b, n);
+                else
+                    return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
+            }
+        }
+        return null;
     }
 
     /**
      * Removes first entry; returns its snapshot.
      * @return null if empty, else snapshot of first entry
      */
-    private Map.Entry<K,V> doRemoveFirstEntry() {
-        for (Node<K,V> b, n;;) {
-            if ((n = (b = head.node).next) == null)
-                return null;
-            Node<K,V> f = n.next;
-            if (n != b.next)
-                continue;
-            Object v = n.value;
-            if (v == null) {
-                n.helpDelete(b, f);
-                continue;
-            }
-            if (!n.casValue(v, null))
-                continue;
-            if (!n.appendMarker(f) || !b.casNext(n, f))
-                findFirst(); // retry
-            clearIndexToFirst();
-            @SuppressWarnings("unchecked") V vv = (V)v;
-            return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, vv);
-        }
-    }
-
-    /**
-     * Clears out index nodes associated with deleted first entry.
-     */
-    private void clearIndexToFirst() {
-        for (;;) {
-            for (Index<K,V> q = head;;) {
-                Index<K,V> r = q.right;
-                if (r != null && r.indexesDeletedNode() && !q.unlink(r))
-                    break;
-                if ((q = q.down) == null) {
-                    if (head.right == null)
+    private AbstractMap.SimpleImmutableEntry<K,V> doRemoveFirstEntry() {
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if ((v = n.val) == null || VAL.compareAndSet(n, v, null)) {
+                    K k = n.key;
+                    unlinkNode(b, n);
+                    if (v != null) {
                         tryReduceLevel();
-                    return;
+                        findPredecessor(k, comparator); // clean index
+                        addCount(-1L);
+                        return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+                    }
                 }
             }
         }
-    }
-
-    /**
-     * Removes last entry; returns its snapshot.
-     * Specialized variant of doRemove.
-     * @return null if empty, else snapshot of last entry
-     */
-    private Map.Entry<K,V> doRemoveLastEntry() {
-        for (;;) {
-            Node<K,V> b = findPredecessorOfLast();
-            Node<K,V> n = b.next;
-            if (n == null) {
-                if (b.isBaseHeader())               // empty
-                    return null;
-                else
-                    continue; // all b's successors are deleted; retry
-            }
-            for (;;) {
-                Node<K,V> f = n.next;
-                if (n != b.next)                    // inconsistent read
-                    break;
-                Object v = n.value;
-                if (v == null) {                    // n is deleted
-                    n.helpDelete(b, f);
-                    break;
-                }
-                if (b.value == null || v == n)      // b is deleted
-                    break;
-                if (f != null) {
-                    b = n;
-                    n = f;
-                    continue;
-                }
-                if (!n.casValue(v, null))
-                    break;
-                K key = n.key;
-                if (!n.appendMarker(f) || !b.casNext(n, f))
-                    findNode(key);                  // retry via findNode
-                else {                              // clean index
-                    findPredecessor(key, comparator);
-                    if (head.right == null)
-                        tryReduceLevel();
-                }
-                @SuppressWarnings("unchecked") V vv = (V)v;
-                return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
-            }
-        }
+        return null;
     }
 
     /* ---------------- Finding and removing last element -------------- */
@@ -1139,73 +885,115 @@
      * @return last node or null if empty
      */
     final Node<K,V> findLast() {
-        /*
-         * findPredecessor can't be used to traverse index level
-         * because this doesn't use comparisons.  So traversals of
-         * both levels are folded together.
-         */
-        Index<K,V> q = head;
-        for (;;) {
-            Index<K,V> d, r;
-            if ((r = q.right) != null) {
-                if (r.indexesDeletedNode()) {
-                    q.unlink(r);
-                    q = head; // restart
+        outer: for (;;) {
+            Index<K,V> q; Node<K,V> b;
+            VarHandle.acquireFence();
+            if ((q = head) == null)
+                break;
+            for (Index<K,V> r, d;;) {
+                while ((r = q.right) != null) {
+                    Node<K,V> p;
+                    if ((p = r.node) == null || p.val == null)
+                        RIGHT.compareAndSet(q, r, r.right);
+                    else
+                        q = r;
                 }
-                else
-                    q = r;
-            } else if ((d = q.down) != null) {
-                q = d;
-            } else {
-                for (Node<K,V> b = q.node, n = b.next;;) {
-                    if (n == null)
-                        return b.isBaseHeader() ? null : b;
-                    Node<K,V> f = n.next;            // inconsistent read
-                    if (n != b.next)
-                        break;
-                    Object v = n.value;
-                    if (v == null) {                 // n is deleted
-                        n.helpDelete(b, f);
-                        break;
-                    }
-                    if (b.value == null || v == n)      // b is deleted
-                        break;
-                    b = n;
-                    n = f;
+                if ((d = q.down) != null)
+                    q = d;
+                else {
+                    b = q.node;
+                    break;
                 }
-                q = head; // restart
             }
+            if (b != null) {
+                for (;;) {
+                    Node<K,V> n;
+                    if ((n = b.next) == null) {
+                        if (b.key == null) // empty
+                            break outer;
+                        else
+                            return b;
+                    }
+                    else if (n.key == null)
+                        break;
+                    else if (n.val == null)
+                        unlinkNode(b, n);
+                    else
+                        b = n;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Entry version of findLast
+     * @return Entry for last node or null if empty
+     */
+    final AbstractMap.SimpleImmutableEntry<K,V> findLastEntry() {
+        for (;;) {
+            Node<K,V> n; V v;
+            if ((n = findLast()) == null)
+                return null;
+            if ((v = n.val) != null)
+                return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
         }
     }
 
     /**
-     * Specialized variant of findPredecessor to get predecessor of last
-     * valid node.  Needed when removing the last entry.  It is possible
-     * that all successors of returned node will have been deleted upon
-     * return, in which case this method can be retried.
-     * @return likely predecessor of last node
+     * Removes last entry; returns its snapshot.
+     * Specialized variant of doRemove.
+     * @return null if empty, else snapshot of last entry
      */
-    private Node<K,V> findPredecessorOfLast() {
-        for (;;) {
-            for (Index<K,V> q = head;;) {
-                Index<K,V> d, r;
-                if ((r = q.right) != null) {
-                    if (r.indexesDeletedNode()) {
-                        q.unlink(r);
-                        break;    // must restart
-                    }
-                    // proceed as far across as possible without overshooting
-                    if (r.node.next != null) {
-                        q = r;
-                        continue;
-                    }
+    private Map.Entry<K,V> doRemoveLastEntry() {
+        outer: for (;;) {
+            Index<K,V> q; Node<K,V> b;
+            VarHandle.acquireFence();
+            if ((q = head) == null)
+                break;
+            for (;;) {
+                Index<K,V> d, r; Node<K,V> p;
+                while ((r = q.right) != null) {
+                    if ((p = r.node) == null || p.val == null)
+                        RIGHT.compareAndSet(q, r, r.right);
+                    else if (p.next != null)
+                        q = r;  // continue only if a successor
+                    else
+                        break;
                 }
                 if ((d = q.down) != null)
                     q = d;
-                else
-                    return q.node;
+                else {
+                    b = q.node;
+                    break;
+                }
+            }
+            if (b != null) {
+                for (;;) {
+                    Node<K,V> n; K k; V v;
+                    if ((n = b.next) == null) {
+                        if (b.key == null) // empty
+                            break outer;
+                        else
+                            break; // retry
+                    }
+                    else if ((k = n.key) == null)
+                        break;
+                    else if ((v = n.val) == null)
+                        unlinkNode(b, n);
+                    else if (n.next != null)
+                        b = n;
+                    else if (VAL.compareAndSet(n, v, null)) {
+                        unlinkNode(b, n);
+                        tryReduceLevel();
+                        findPredecessor(k, comparator); // clean index
+                        addCount(-1L);
+                        return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
+                    }
+                }
             }
         }
+        return null;
     }
 
     /* ---------------- Relational operations -------------- */
@@ -1225,47 +1013,52 @@
     final Node<K,V> findNear(K key, int rel, Comparator<? super K> cmp) {
         if (key == null)
             throw new NullPointerException();
-        for (;;) {
-            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
-                Object v;
-                if (n == null)
-                    return ((rel & LT) == 0 || b.isBaseHeader()) ? null : b;
-                Node<K,V> f = n.next;
-                if (n != b.next)                  // inconsistent read
-                    break;
-                if ((v = n.value) == null) {      // n is deleted
-                    n.helpDelete(b, f);
-                    break;
+        Node<K,V> result;
+        outer: for (Node<K,V> b;;) {
+            if ((b = findPredecessor(key, cmp)) == null) {
+                result = null;
+                break;                   // empty
+            }
+            for (;;) {
+                Node<K,V> n; K k; int c;
+                if ((n = b.next) == null) {
+                    result = ((rel & LT) != 0 && b.key != null) ? b : null;
+                    break outer;
                 }
-                if (b.value == null || v == n)      // b is deleted
+                else if ((k = n.key) == null)
                     break;
-                int c = cpr(cmp, key, n.key);
-                if ((c == 0 && (rel & EQ) != 0) ||
-                    (c <  0 && (rel & LT) == 0))
-                    return n;
-                if ( c <= 0 && (rel & LT) != 0)
-                    return b.isBaseHeader() ? null : b;
-                b = n;
-                n = f;
+                else if (n.val == null)
+                    unlinkNode(b, n);
+                else if (((c = cpr(cmp, key, k)) == 0 && (rel & EQ) != 0) ||
+                         (c < 0 && (rel & LT) == 0)) {
+                    result = n;
+                    break outer;
+                }
+                else if (c <= 0 && (rel & LT) != 0) {
+                    result = (b.key != null) ? b : null;
+                    break outer;
+                }
+                else
+                    b = n;
             }
         }
+        return result;
     }
 
     /**
-     * Returns SimpleImmutableEntry for results of findNear.
+     * Variant of findNear returning SimpleImmutableEntry
      * @param key the key
      * @param rel the relation -- OR'ed combination of EQ, LT, GT
      * @return Entry fitting relation, or null if no such
      */
-    final AbstractMap.SimpleImmutableEntry<K,V> getNear(K key, int rel) {
-        Comparator<? super K> cmp = comparator;
+    final AbstractMap.SimpleImmutableEntry<K,V> findNearEntry(K key, int rel,
+                                                              Comparator<? super K> cmp) {
         for (;;) {
-            Node<K,V> n = findNear(key, rel, cmp);
-            if (n == null)
+            Node<K,V> n; V v;
+            if ((n = findNear(key, rel, cmp)) == null)
                 return null;
-            AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
-            if (e != null)
-                return e;
+            if ((v = n.val) != null)
+                return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
         }
     }
 
@@ -1277,7 +1070,6 @@
      */
     public ConcurrentSkipListMap() {
         this.comparator = null;
-        initialize();
     }
 
     /**
@@ -1290,7 +1082,6 @@
      */
     public ConcurrentSkipListMap(Comparator<? super K> comparator) {
         this.comparator = comparator;
-        initialize();
     }
 
     /**
@@ -1306,7 +1097,6 @@
      */
     public ConcurrentSkipListMap(Map<? extends K, ? extends V> m) {
         this.comparator = null;
-        initialize();
         putAll(m);
     }
 
@@ -1321,8 +1111,7 @@
      */
     public ConcurrentSkipListMap(SortedMap<K, ? extends V> m) {
         this.comparator = m.comparator();
-        initialize();
-        buildFromSorted(m);
+        buildFromSorted(m); // initializes transients
     }
 
     /**
@@ -1336,7 +1125,11 @@
             @SuppressWarnings("unchecked")
             ConcurrentSkipListMap<K,V> clone =
                 (ConcurrentSkipListMap<K,V>) super.clone();
-            clone.initialize();
+            clone.keySet = null;
+            clone.entrySet = null;
+            clone.values = null;
+            clone.descendingMap = null;
+            clone.adder = null;
             clone.buildFromSorted(this);
             return clone;
         } catch (CloneNotSupportedException e) {
@@ -1352,58 +1145,49 @@
     private void buildFromSorted(SortedMap<K, ? extends V> map) {
         if (map == null)
             throw new NullPointerException();
-
-        HeadIndex<K,V> h = head;
-        Node<K,V> basepred = h.node;
-
-        // Track the current rightmost node at each level. Uses an
-        // ArrayList to avoid committing to initial or maximum level.
-        ArrayList<Index<K,V>> preds = new ArrayList<>();
-
-        // initialize
-        for (int i = 0; i <= h.level; ++i)
-            preds.add(null);
-        Index<K,V> q = h;
-        for (int i = h.level; i > 0; --i) {
-            preds.set(i, q);
-            q = q.down;
-        }
-
         Iterator<? extends Map.Entry<? extends K, ? extends V>> it =
             map.entrySet().iterator();
+
+        /*
+         * Add equally spaced indices at log intervals, using the bits
+         * of count during insertion. The maximum possible resulting
+         * level is less than the number of bits in a long (64). The
+         * preds array tracks the current rightmost node at each
+         * level.
+         */
+        @SuppressWarnings("unchecked")
+        Index<K,V>[] preds = (Index<K,V>[])new Index<?,?>[64];
+        Node<K,V> bp = new Node<K,V>(null, null, null);
+        Index<K,V> h = preds[0] = new Index<K,V>(bp, null, null);
+        long count = 0;
+
         while (it.hasNext()) {
             Map.Entry<? extends K, ? extends V> e = it.next();
-            int rnd = ThreadLocalRandom.current().nextInt();
-            int j = 0;
-            if ((rnd & 0x80000001) == 0) {
-                do {
-                    ++j;
-                } while (((rnd >>>= 1) & 1) != 0);
-                if (j > h.level) j = h.level + 1;
-            }
             K k = e.getKey();
             V v = e.getValue();
             if (k == null || v == null)
                 throw new NullPointerException();
             Node<K,V> z = new Node<K,V>(k, v, null);
-            basepred.next = z;
-            basepred = z;
-            if (j > 0) {
-                Index<K,V> idx = null;
-                for (int i = 1; i <= j; ++i) {
+            bp = bp.next = z;
+            if ((++count & 3L) == 0L) {
+                long m = count >>> 2;
+                int i = 0;
+                Index<K,V> idx = null, q;
+                do {
                     idx = new Index<K,V>(z, idx, null);
-                    if (i > h.level)
-                        h = new HeadIndex<K,V>(h.node, h, idx, i);
-
-                    if (i < preds.size()) {
-                        preds.get(i).right = idx;
-                        preds.set(i, idx);
-                    } else
-                        preds.add(idx);
-                }
+                    if ((q = preds[i]) == null)
+                        preds[i] = h = new Index<K,V>(h.node, h, idx);
+                    else
+                        preds[i] = q.right = idx;
+                } while (++i < preds.length && ((m >>>= 1) & 1L) != 0L);
             }
         }
-        head = h;
+        if (count != 0L) {
+            VarHandle.releaseFence(); // emulate volatile stores
+            addCount(count);
+            head = h;
+            VarHandle.fullFence();
+        }
     }
 
     /* ---------------- Serialization -------------- */
@@ -1425,11 +1209,14 @@
         s.defaultWriteObject();
 
         // Write out keys and values (alternating)
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            V v = n.getValidValue();
-            if (v != null) {
-                s.writeObject(n.key);
-                s.writeObject(v);
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if ((v = n.val) != null) {
+                    s.writeObject(n.key);
+                    s.writeObject(v);
+                }
+                b = n;
             }
         }
         s.writeObject(null);
@@ -1447,64 +1234,47 @@
         throws java.io.IOException, ClassNotFoundException {
         // Read in the Comparator and any hidden stuff
         s.defaultReadObject();
-        // Reset transients
-        initialize();
 
-        /*
-         * This is nearly identical to buildFromSorted, but is
-         * distinct because readObject calls can't be nicely adapted
-         * as the kind of iterator needed by buildFromSorted. (They
-         * can be, but doing so requires type cheats and/or creation
-         * of adapter classes.) It is simpler to just adapt the code.
-         */
-
-        HeadIndex<K,V> h = head;
-        Node<K,V> basepred = h.node;
-        ArrayList<Index<K,V>> preds = new ArrayList<>();
-        for (int i = 0; i <= h.level; ++i)
-            preds.add(null);
-        Index<K,V> q = h;
-        for (int i = h.level; i > 0; --i) {
-            preds.set(i, q);
-            q = q.down;
-        }
+        // Same idea as buildFromSorted
+        @SuppressWarnings("unchecked")
+        Index<K,V>[] preds = (Index<K,V>[])new Index<?,?>[64];
+        Node<K,V> bp = new Node<K,V>(null, null, null);
+        Index<K,V> h = preds[0] = new Index<K,V>(bp, null, null);
+        Comparator<? super K> cmp = comparator;
+        K prevKey = null;
+        long count = 0;
 
         for (;;) {
-            Object k = s.readObject();
+            K k = (K)s.readObject();
             if (k == null)
                 break;
-            Object v = s.readObject();
+            V v = (V)s.readObject();
             if (v == null)
                 throw new NullPointerException();
-            K key = (K) k;
-            V val = (V) v;
-            int rnd = ThreadLocalRandom.current().nextInt();
-            int j = 0;
-            if ((rnd & 0x80000001) == 0) {
+            if (prevKey != null && cpr(cmp, prevKey, k) > 0)
+                throw new IllegalStateException("out of order");
+            prevKey = k;
+            Node<K,V> z = new Node<K,V>(k, v, null);
+            bp = bp.next = z;
+            if ((++count & 3L) == 0L) {
+                long m = count >>> 2;
+                int i = 0;
+                Index<K,V> idx = null, q;
                 do {
-                    ++j;
-                } while (((rnd >>>= 1) & 1) != 0);
-                if (j > h.level) j = h.level + 1;
-            }
-            Node<K,V> z = new Node<K,V>(key, val, null);
-            basepred.next = z;
-            basepred = z;
-            if (j > 0) {
-                Index<K,V> idx = null;
-                for (int i = 1; i <= j; ++i) {
                     idx = new Index<K,V>(z, idx, null);
-                    if (i > h.level)
-                        h = new HeadIndex<K,V>(h.node, h, idx, i);
-
-                    if (i < preds.size()) {
-                        preds.get(i).right = idx;
-                        preds.set(i, idx);
-                    } else
-                        preds.add(idx);
-                }
+                    if ((q = preds[i]) == null)
+                        preds[i] = h = new Index<K,V>(h.node, h, idx);
+                    else
+                        preds[i] = q.right = idx;
+                } while (++i < preds.length && ((m >>>= 1) & 1L) != 0L);
             }
         }
-        head = h;
+        if (count != 0L) {
+            VarHandle.releaseFence();
+            addCount(count);
+            head = h;
+            VarHandle.fullFence();
+        }
     }
 
     /* ------ Map API methods ------ */
@@ -1605,42 +1375,30 @@
     public boolean containsValue(Object value) {
         if (value == null)
             throw new NullPointerException();
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            V v = n.getValidValue();
-            if (v != null && value.equals(v))
-                return true;
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if ((v = n.val) != null && value.equals(v))
+                    return true;
+                else
+                    b = n;
+            }
         }
         return false;
     }
 
     /**
-     * Returns the number of key-value mappings in this map.  If this map
-     * 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
-     * asynchronous nature of these maps, determining the current
-     * number of elements requires traversing them all to count them.
-     * Additionally, it is possible for the size to change during
-     * execution of this method, in which case the returned result
-     * will be inaccurate. Thus, this method is typically not very
-     * useful in concurrent applications.
-     *
-     * @return the number of elements in this map
+     * {@inheritDoc}
      */
     public int size() {
-        long count = 0;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            if (n.getValidValue() != null)
-                ++count;
-        }
-        return (count >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count;
+        long c;
+        return ((baseHead() == null) ? 0 :
+                ((c = getAdderCount()) >= Integer.MAX_VALUE) ?
+                Integer.MAX_VALUE : (int) c);
     }
 
     /**
-     * Returns {@code true} if this map contains no key-value mappings.
-     * @return {@code true} if this map contains no key-value mappings
+     * {@inheritDoc}
      */
     public boolean isEmpty() {
         return findFirst() == null;
@@ -1650,7 +1408,33 @@
      * Removes all of the mappings from this map.
      */
     public void clear() {
-        initialize();
+        Index<K,V> h, r, d; Node<K,V> b;
+        VarHandle.acquireFence();
+        while ((h = head) != null) {
+            if ((r = h.right) != null)        // remove indices
+                RIGHT.compareAndSet(h, r, null);
+            else if ((d = h.down) != null)    // remove levels
+                HEAD.compareAndSet(this, h, d);
+            else {
+                long count = 0L;
+                if ((b = h.node) != null) {    // remove nodes
+                    Node<K,V> n; V v;
+                    while ((n = b.next) != null) {
+                        if ((v = n.val) != null &&
+                            VAL.compareAndSet(n, v, null)) {
+                            --count;
+                            v = null;
+                        }
+                        if (v == null)
+                            unlinkNode(b, n);
+                    }
+                }
+                if (count != 0L)
+                    addCount(count);
+                else
+                    break;
+            }
+        }
     }
 
     /**
@@ -1696,16 +1480,15 @@
                               BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
         if (key == null || remappingFunction == null)
             throw new NullPointerException();
-        Node<K,V> n; Object v;
+        Node<K,V> n; V v;
         while ((n = findNode(key)) != null) {
-            if ((v = n.value) != null) {
-                @SuppressWarnings("unchecked") V vv = (V) v;
-                V r = remappingFunction.apply(key, vv);
+            if ((v = n.val) != null) {
+                V r = remappingFunction.apply(key, v);
                 if (r != null) {
-                    if (n.casValue(vv, r))
+                    if (VAL.compareAndSet(n, v, r))
                         return r;
                 }
-                else if (doRemove(key, vv) != null)
+                else if (doRemove(key, v) != null)
                     break;
             }
         }
@@ -1730,20 +1513,19 @@
         if (key == null || remappingFunction == null)
             throw new NullPointerException();
         for (;;) {
-            Node<K,V> n; Object v; V r;
+            Node<K,V> n; V v; V r;
             if ((n = findNode(key)) == null) {
                 if ((r = remappingFunction.apply(key, null)) == null)
                     break;
                 if (doPut(key, r, true) == null)
                     return r;
             }
-            else if ((v = n.value) != null) {
-                @SuppressWarnings("unchecked") V vv = (V) v;
-                if ((r = remappingFunction.apply(key, vv)) != null) {
-                    if (n.casValue(vv, r))
+            else if ((v = n.val) != null) {
+                if ((r = remappingFunction.apply(key, v)) != null) {
+                    if (VAL.compareAndSet(n, v, r))
                         return r;
                 }
-                else if (doRemove(key, vv) != null)
+                else if (doRemove(key, v) != null)
                     break;
             }
         }
@@ -1770,18 +1552,17 @@
         if (key == null || value == null || remappingFunction == null)
             throw new NullPointerException();
         for (;;) {
-            Node<K,V> n; Object v; V r;
+            Node<K,V> n; V v; V r;
             if ((n = findNode(key)) == null) {
                 if (doPut(key, value, true) == null)
                     return value;
             }
-            else if ((v = n.value) != null) {
-                @SuppressWarnings("unchecked") V vv = (V) v;
-                if ((r = remappingFunction.apply(vv, value)) != null) {
-                    if (n.casValue(vv, r))
+            else if ((v = n.val) != null) {
+                if ((r = remappingFunction.apply(v, value)) != null) {
+                    if (VAL.compareAndSet(n, v, r))
                         return r;
                 }
-                else if (doRemove(key, vv) != null)
+                else if (doRemove(key, v) != null)
                     return null;
             }
         }
@@ -1805,9 +1586,11 @@
      * The set's spliterator additionally reports {@link Spliterator#CONCURRENT},
      * {@link Spliterator#NONNULL}, {@link Spliterator#SORTED} and
      * {@link Spliterator#ORDERED}, with an encounter order that is ascending
-     * key order.  The spliterator's comparator (see
-     * {@link java.util.Spliterator#getComparator()}) is {@code null} if
-     * the map's comparator (see {@link #comparator()}) is {@code null}.
+     * key order.
+     *
+     * <p>The {@linkplain Spliterator#getComparator() spliterator's comparator}
+     * is {@code null} if the {@linkplain #comparator() map's comparator}
+     * is {@code null}.
      * Otherwise, the spliterator's comparator is the same as or imposes the
      * same total ordering as the map's comparator.
      *
@@ -1827,13 +1610,15 @@
      * @return a navigable set view of the keys in this map
      */
     public NavigableSet<K> keySet() {
-        KeySet<K,V> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<>(this));
+        KeySet<K,V> ks;
+        if ((ks = keySet) != null) return ks;
+        return keySet = new KeySet<>(this);
     }
 
     public NavigableSet<K> navigableKeySet() {
-        KeySet<K,V> ks = keySet;
-        return (ks != null) ? ks : (keySet = new KeySet<>(this));
+        KeySet<K,V> ks;
+        if ((ks = keySet) != null) return ks;
+        return keySet = new KeySet<>(this);
     }
 
     /**
@@ -1856,8 +1641,9 @@
      * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
      */
     public Collection<V> values() {
-        Values<K,V> vs = values;
-        return (vs != null) ? vs : (values = new Values<>(this));
+        Values<K,V> vs;
+        if ((vs = values) != null) return vs;
+        return values = new Values<>(this);
     }
 
     /**
@@ -1888,14 +1674,16 @@
      *         sorted in ascending key order
      */
     public Set<Map.Entry<K,V>> entrySet() {
-        EntrySet<K,V> es = entrySet;
-        return (es != null) ? es : (entrySet = new EntrySet<K,V>(this));
+        EntrySet<K,V> es;
+        if ((es = entrySet) != null) return es;
+        return entrySet = new EntrySet<K,V>(this);
     }
 
     public ConcurrentNavigableMap<K,V> descendingMap() {
-        ConcurrentNavigableMap<K,V> dm = descendingMap;
-        return (dm != null) ? dm : (descendingMap = new SubMap<K,V>
-                                    (this, null, false, null, false, true));
+        ConcurrentNavigableMap<K,V> dm;
+        if ((dm = descendingMap) != null) return dm;
+        return descendingMap =
+            new SubMap<K,V>(this, null, false, null, false, true);
     }
 
     public NavigableSet<K> descendingKeySet() {
@@ -1923,19 +1711,60 @@
             return false;
         Map<?,?> m = (Map<?,?>) o;
         try {
-            for (Map.Entry<K,V> e : this.entrySet())
-                if (! e.getValue().equals(m.get(e.getKey())))
-                    return false;
-            for (Map.Entry<?,?> e : m.entrySet()) {
-                Object k = e.getKey();
-                Object v = e.getValue();
-                if (k == null || v == null || !v.equals(get(k)))
-                    return false;
+            Comparator<? super K> cmp = comparator;
+            // See JDK-8223553 for Iterator type wildcard rationale
+            Iterator<? extends Map.Entry<?,?>> it = m.entrySet().iterator();
+            if (m instanceof SortedMap &&
+                ((SortedMap<?,?>)m).comparator() == cmp) {
+                Node<K,V> b, n;
+                if ((b = baseHead()) != null) {
+                    while ((n = b.next) != null) {
+                        K k; V v;
+                        if ((v = n.val) != null && (k = n.key) != null) {
+                            if (!it.hasNext())
+                                return false;
+                            Map.Entry<?,?> e = it.next();
+                            Object mk = e.getKey();
+                            Object mv = e.getValue();
+                            if (mk == null || mv == null)
+                                return false;
+                            try {
+                                if (cpr(cmp, k, mk) != 0)
+                                    return false;
+                            } catch (ClassCastException cce) {
+                                return false;
+                            }
+                            if (!mv.equals(v))
+                                return false;
+                        }
+                        b = n;
+                    }
+                }
+                return !it.hasNext();
             }
-            return true;
-        } catch (ClassCastException unused) {
-            return false;
-        } catch (NullPointerException unused) {
+            else {
+                while (it.hasNext()) {
+                    V v;
+                    Map.Entry<?,?> e = it.next();
+                    Object mk = e.getKey();
+                    Object mv = e.getValue();
+                    if (mk == null || mv == null ||
+                        (v = get(mk)) == null || !v.equals(mv))
+                        return false;
+                }
+                Node<K,V> b, n;
+                if ((b = baseHead()) != null) {
+                    K k; V v; Object mv;
+                    while ((n = b.next) != null) {
+                        if ((v = n.val) != null && (k = n.key) != null &&
+                            ((mv = m.get(k)) == null || !mv.equals(v)))
+                            return false;
+                        b = n;
+                    }
+                }
+                return true;
+            }
+        } catch (ClassCastException | NullPointerException unused) {
             return false;
         }
     }
@@ -1981,13 +1810,13 @@
         if (key == null || oldValue == null || newValue == null)
             throw new NullPointerException();
         for (;;) {
-            Node<K,V> n; Object v;
+            Node<K,V> n; V v;
             if ((n = findNode(key)) == null)
                 return false;
-            if ((v = n.value) != null) {
+            if ((v = n.val) != null) {
                 if (!oldValue.equals(v))
                     return false;
-                if (n.casValue(v, newValue))
+                if (VAL.compareAndSet(n, v, newValue))
                     return true;
             }
         }
@@ -2006,13 +1835,11 @@
         if (key == null || value == null)
             throw new NullPointerException();
         for (;;) {
-            Node<K,V> n; Object v;
+            Node<K,V> n; V v;
             if ((n = findNode(key)) == null)
                 return null;
-            if ((v = n.value) != null && n.casValue(v, value)) {
-                @SuppressWarnings("unchecked") V vv = (V)v;
-                return vv;
-            }
+            if ((v = n.val) != null && VAL.compareAndSet(n, v, value))
+                return v;
         }
     }
 
@@ -2122,7 +1949,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public Map.Entry<K,V> lowerEntry(K key) {
-        return getNear(key, LT);
+        return findNearEntry(key, LT, comparator);
     }
 
     /**
@@ -2145,7 +1972,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public Map.Entry<K,V> floorEntry(K key) {
-        return getNear(key, LT|EQ);
+        return findNearEntry(key, LT|EQ, comparator);
     }
 
     /**
@@ -2168,7 +1995,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public Map.Entry<K,V> ceilingEntry(K key) {
-        return getNear(key, GT|EQ);
+        return findNearEntry(key, GT|EQ, comparator);
     }
 
     /**
@@ -2191,7 +2018,7 @@
      * @throws NullPointerException if the specified key is null
      */
     public Map.Entry<K,V> higherEntry(K key) {
-        return getNear(key, GT);
+        return findNearEntry(key, GT, comparator);
     }
 
     /**
@@ -2211,14 +2038,7 @@
      * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> firstEntry() {
-        for (;;) {
-            Node<K,V> n = findFirst();
-            if (n == null)
-                return null;
-            AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
-            if (e != null)
-                return e;
-        }
+        return findFirstEntry();
     }
 
     /**
@@ -2228,14 +2048,7 @@
      * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> lastEntry() {
-        for (;;) {
-            Node<K,V> n = findLast();
-            if (n == null)
-                return null;
-            AbstractMap.SimpleImmutableEntry<K,V> e = n.createSnapshot();
-            if (e != null)
-                return e;
-        }
+        return findLastEntry();
     }
 
     /**
@@ -2258,11 +2071,10 @@
         return doRemoveLastEntry();
     }
 
-
     /* ---------------- Iterators -------------- */
 
     /**
-     * Base of iterator classes:
+     * Base of iterator classes
      */
     abstract class Iter<T> implements Iterator<T> {
         /** the last node returned by next() */
@@ -2274,14 +2086,7 @@
 
         /** Initializes ascending iterator for entire range. */
         Iter() {
-            while ((next = findFirst()) != null) {
-                Object x = next.value;
-                if (x != null && x != next) {
-                    @SuppressWarnings("unchecked") V vv = (V)x;
-                    nextValue = vv;
-                    break;
-                }
-            }
+            advance(baseHead());
         }
 
         public final boolean hasNext() {
@@ -2289,54 +2094,58 @@
         }
 
         /** Advances next to higher entry. */
-        final void advance() {
-            if (next == null)
-                throw new NoSuchElementException();
-            lastReturned = next;
-            while ((next = next.next) != null) {
-                Object x = next.value;
-                if (x != null && x != next) {
-                    @SuppressWarnings("unchecked") V vv = (V)x;
-                    nextValue = vv;
-                    break;
-                }
+        final void advance(Node<K,V> b) {
+            Node<K,V> n = null;
+            V v = null;
+            if ((lastReturned = b) != null) {
+                while ((n = b.next) != null && (v = n.val) == null)
+                    b = n;
             }
+            nextValue = v;
+            next = n;
         }
 
-        public void remove() {
-            Node<K,V> l = lastReturned;
-            if (l == null)
+        public final void remove() {
+            Node<K,V> n; K k;
+            if ((n = lastReturned) == null || (k = n.key) == null)
                 throw new IllegalStateException();
             // It would not be worth all of the overhead to directly
             // unlink from here. Using remove is fast enough.
-            ConcurrentSkipListMap.this.remove(l.key);
+            ConcurrentSkipListMap.this.remove(k);
             lastReturned = null;
         }
-
     }
 
     final class ValueIterator extends Iter<V> {
         public V next() {
-            V v = nextValue;
-            advance();
+            V v;
+            if ((v = nextValue) == null)
+                throw new NoSuchElementException();
+            advance(next);
             return v;
         }
     }
 
     final class KeyIterator extends Iter<K> {
         public K next() {
-            Node<K,V> n = next;
-            advance();
-            return n.key;
+            Node<K,V> n;
+            if ((n = next) == null)
+                throw new NoSuchElementException();
+            K k = n.key;
+            advance(n);
+            return k;
         }
     }
 
     final class EntryIterator extends Iter<Map.Entry<K,V>> {
         public Map.Entry<K,V> next() {
-            Node<K,V> n = next;
+            Node<K,V> n;
+            if ((n = next) == null)
+                throw new NoSuchElementException();
+            K k = n.key;
             V v = nextValue;
-            advance();
-            return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
+            advance(n);
+            return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
         }
     }
 
@@ -2393,9 +2202,7 @@
             Collection<?> c = (Collection<?>) o;
             try {
                 return containsAll(c) && c.containsAll(this);
-            } catch (ClassCastException unused) {
-                return false;
-            } catch (NullPointerException unused) {
+            } catch (ClassCastException | NullPointerException unused) {
                 return false;
             }
         }
@@ -2520,9 +2327,7 @@
             Collection<?> c = (Collection<?>) o;
             try {
                 return containsAll(c) && c.containsAll(this);
-            } catch (ClassCastException unused) {
-                return false;
-            } catch (NullPointerException unused) {
+            } catch (ClassCastException | NullPointerException unused) {
                 return false;
             }
         }
@@ -2564,7 +2369,7 @@
      * @serial include
      */
     static final class SubMap<K,V> extends AbstractMap<K,V>
-        implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable {
+        implements ConcurrentNavigableMap<K,V>, Serializable {
         private static final long serialVersionUID = -7647078645895051609L;
 
         /** Underlying map */
@@ -2582,8 +2387,8 @@
 
         // Lazily initialized view holders
         private transient KeySet<K,V> keySetView;
-        private transient Set<Map.Entry<K,V>> entrySetView;
-        private transient Collection<V> valuesView;
+        private transient Values<K,V> valuesView;
+        private transient EntrySet<K,V> entrySetView;
 
         /**
          * Creates a new submap, initializing all fields.
@@ -2642,9 +2447,7 @@
             if (k == null) // pass by markers and headers
                 return true;
             int c = cpr(cmp, k, hi);
-            if (c > 0 || (c == 0 && !hiInclusive))
-                return false;
-            return true;
+            return c < 0 || (c == 0 && hiInclusive);
         }
 
         /**
@@ -2702,38 +2505,34 @@
         Map.Entry<K,V> lowestEntry() {
             Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
-                if (!isBeforeEnd(n, cmp))
+                ConcurrentSkipListMap.Node<K,V> n; V v;
+                if ((n = loNode(cmp)) == null || !isBeforeEnd(n, cmp))
                     return null;
-                Map.Entry<K,V> e = n.createSnapshot();
-                if (e != null)
-                    return e;
+                else if ((v = n.val) != null)
+                    return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
             }
         }
 
         Map.Entry<K,V> highestEntry() {
             Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                ConcurrentSkipListMap.Node<K,V> n = hiNode(cmp);
-                if (n == null || !inBounds(n.key, cmp))
+                ConcurrentSkipListMap.Node<K,V> n; V v;
+                if ((n = hiNode(cmp)) == null || !inBounds(n.key, cmp))
                     return null;
-                Map.Entry<K,V> e = n.createSnapshot();
-                if (e != null)
-                    return e;
+                else if ((v = n.val) != null)
+                    return new AbstractMap.SimpleImmutableEntry<K,V>(n.key, v);
             }
         }
 
         Map.Entry<K,V> removeLowest() {
             Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                Node<K,V> n = loNode(cmp);
-                if (n == null)
+                ConcurrentSkipListMap.Node<K,V> n; K k; V v;
+                if ((n = loNode(cmp)) == null)
                     return null;
-                K k = n.key;
-                if (!inBounds(k, cmp))
+                else if (!inBounds((k = n.key), cmp))
                     return null;
-                V v = m.doRemove(k, null);
-                if (v != null)
+                else if ((v = m.doRemove(k, null)) != null)
                     return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
             }
         }
@@ -2741,20 +2540,18 @@
         Map.Entry<K,V> removeHighest() {
             Comparator<? super K> cmp = m.comparator;
             for (;;) {
-                Node<K,V> n = hiNode(cmp);
-                if (n == null)
+                ConcurrentSkipListMap.Node<K,V> n; K k; V v;
+                if ((n = hiNode(cmp)) == null)
                     return null;
-                K k = n.key;
-                if (!inBounds(k, cmp))
+                else if (!inBounds((k = n.key), cmp))
                     return null;
-                V v = m.doRemove(k, null);
-                if (v != null)
+                else if ((v = m.doRemove(k, null)) != null)
                     return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
             }
         }
 
         /**
-         * Submap version of ConcurrentSkipListMap.getNearEntry.
+         * Submap version of ConcurrentSkipListMap.findNearEntry.
          */
         Map.Entry<K,V> getNearEntry(K key, int rel) {
             Comparator<? super K> cmp = m.comparator;
@@ -2768,15 +2565,12 @@
                 return ((rel & LT) != 0) ? null : lowestEntry();
             if (tooHigh(key, cmp))
                 return ((rel & LT) != 0) ? highestEntry() : null;
-            for (;;) {
-                Node<K,V> n = m.findNear(key, rel, cmp);
-                if (n == null || !inBounds(n.key, cmp))
-                    return null;
-                K k = n.key;
-                V v = n.getValidValue();
-                if (v != null)
-                    return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
-            }
+            AbstractMap.SimpleImmutableEntry<K,V> e =
+                m.findNearEntry(key, rel, cmp);
+            if (e == null || !inBounds(e.getKey(), cmp))
+                return null;
+            else
+                return e;
         }
 
         // Almost the same as getNearEntry, except for keys
@@ -2811,10 +2605,8 @@
                 Node<K,V> n = m.findNear(key, rel, cmp);
                 if (n == null || !inBounds(n.key, cmp))
                     return null;
-                K k = n.key;
-                V v = n.getValidValue();
-                if (v != null)
-                    return k;
+                if (n.val != null)
+                    return n.key;
             }
         }
 
@@ -2845,7 +2637,7 @@
             for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
                  isBeforeEnd(n, cmp);
                  n = n.next) {
-                if (n.getValidValue() != null)
+                if (n.val != null)
                     ++count;
             }
             return count >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)count;
@@ -2863,7 +2655,7 @@
             for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
                  isBeforeEnd(n, cmp);
                  n = n.next) {
-                V v = n.getValidValue();
+                V v = n.val;
                 if (v != null && value.equals(v))
                     return true;
             }
@@ -2875,7 +2667,7 @@
             for (ConcurrentSkipListMap.Node<K,V> n = loNode(cmp);
                  isBeforeEnd(n, cmp);
                  n = n.next) {
-                if (n.getValidValue() != null)
+                if (n.val != null)
                     m.remove(n.key);
             }
         }
@@ -3049,23 +2841,27 @@
         /* ---------------- Submap Views -------------- */
 
         public NavigableSet<K> keySet() {
-            KeySet<K,V> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
+            KeySet<K,V> ks;
+            if ((ks = keySetView) != null) return ks;
+            return keySetView = new KeySet<>(this);
         }
 
         public NavigableSet<K> navigableKeySet() {
-            KeySet<K,V> ks = keySetView;
-            return (ks != null) ? ks : (keySetView = new KeySet<>(this));
+            KeySet<K,V> ks;
+            if ((ks = keySetView) != null) return ks;
+            return keySetView = new KeySet<>(this);
         }
 
         public Collection<V> values() {
-            Collection<V> vs = valuesView;
-            return (vs != null) ? vs : (valuesView = new Values<>(this));
+            Values<K,V> vs;
+            if ((vs = valuesView) != null) return vs;
+            return valuesView = new Values<>(this);
         }
 
         public Set<Map.Entry<K,V>> entrySet() {
-            Set<Map.Entry<K,V>> es = entrySetView;
-            return (es != null) ? es : (entrySetView = new EntrySet<K,V>(this));
+            EntrySet<K,V> es;
+            if ((es = entrySetView) != null) return es;
+            return entrySetView = new EntrySet<K,V>(this);
         }
 
         public NavigableSet<K> descendingKeySet() {
@@ -3085,19 +2881,18 @@
             V nextValue;
 
             SubMapIter() {
+                VarHandle.acquireFence();
                 Comparator<? super K> cmp = m.comparator;
                 for (;;) {
                     next = isDescending ? hiNode(cmp) : loNode(cmp);
                     if (next == null)
                         break;
-                    Object x = next.value;
-                    if (x != null && x != next) {
+                    V x = next.val;
+                    if (x != null) {
                         if (! inBounds(next.key, cmp))
                             next = null;
-                        else {
-                            @SuppressWarnings("unchecked") V vv = (V)x;
-                            nextValue = vv;
-                        }
+                        else
+                            nextValue = x;
                         break;
                     }
                 }
@@ -3123,14 +2918,12 @@
                     next = next.next;
                     if (next == null)
                         break;
-                    Object x = next.value;
-                    if (x != null && x != next) {
+                    V x = next.val;
+                    if (x != null) {
                         if (tooHigh(next.key, cmp))
                             next = null;
-                        else {
-                            @SuppressWarnings("unchecked") V vv = (V)x;
-                            nextValue = vv;
-                        }
+                        else
+                            nextValue = x;
                         break;
                     }
                 }
@@ -3142,14 +2935,12 @@
                     next = m.findNear(lastReturned.key, LT, cmp);
                     if (next == null)
                         break;
-                    Object x = next.value;
-                    if (x != null && x != next) {
+                    V x = next.val;
+                    if (x != null) {
                         if (tooLow(next.key, cmp))
                             next = null;
-                        else {
-                            @SuppressWarnings("unchecked") V vv = (V)x;
-                            nextValue = vv;
-                        }
+                        else
+                            nextValue = x;
                         break;
                     }
                 }
@@ -3229,22 +3020,28 @@
 
     public void forEach(BiConsumer<? super K, ? super V> action) {
         if (action == null) throw new NullPointerException();
-        V v;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            if ((v = n.getValidValue()) != null)
-                action.accept(n.key, v);
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if ((v = n.val) != null)
+                    action.accept(n.key, v);
+                b = n;
+            }
         }
     }
 
     public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
         if (function == null) throw new NullPointerException();
-        V v;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            while ((v = n.getValidValue()) != null) {
-                V r = function.apply(n.key, v);
-                if (r == null) throw new NullPointerException();
-                if (n.casValue(v, r))
-                    break;
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                while ((v = n.val) != null) {
+                    V r = function.apply(n.key, v);
+                    if (r == null) throw new NullPointerException();
+                    if (VAL.compareAndSet(n, v, r))
+                        break;
+                }
+                b = n;
             }
         }
     }
@@ -3255,13 +3052,16 @@
     boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
         if (function == null) throw new NullPointerException();
         boolean removed = false;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            V v;
-            if ((v = n.getValidValue()) != null) {
-                K k = n.key;
-                Map.Entry<K,V> e = new AbstractMap.SimpleImmutableEntry<>(k, v);
-                if (function.test(e) && remove(k, v))
-                    removed = true;
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if ((v = n.val) != null) {
+                    K k = n.key;
+                    Map.Entry<K,V> e = new AbstractMap.SimpleImmutableEntry<>(k, v);
+                    if (function.test(e) && remove(k, v))
+                        removed = true;
+                }
+                b = n;
             }
         }
         return removed;
@@ -3273,12 +3073,12 @@
     boolean removeValueIf(Predicate<? super V> function) {
         if (function == null) throw new NullPointerException();
         boolean removed = false;
-        for (Node<K,V> n = findFirst(); n != null; n = n.next) {
-            V v;
-            if ((v = n.getValidValue()) != null) {
-                K k = n.key;
-                if (function.test(v) && remove(k, v))
+        Node<K,V> b, n; V v;
+        if ((b = baseHead()) != null) {
+            while ((n = b.next) != null) {
+                if ((v = n.val) != null && function.test(v) && remove(n.key, v))
                     removed = true;
+                b = n;
             }
         }
         return removed;
@@ -3296,30 +3096,27 @@
      * off, or the end of row is encountered. Control of the number of
      * splits relies on some statistical estimation: The expected
      * remaining number of elements of a skip list when advancing
-     * either across or down decreases by about 25%. To make this
-     * observation useful, we need to know initial size, which we
-     * don't. But we can just use Integer.MAX_VALUE so that we
-     * don't prematurely zero out while splitting.
+     * either across or down decreases by about 25%.
      */
     abstract static class CSLMSpliterator<K,V> {
         final Comparator<? super K> comparator;
         final K fence;     // exclusive upper bound for keys, or null if to end
         Index<K,V> row;    // the level to split out
         Node<K,V> current; // current traversal node; initialize at origin
-        int est;           // pseudo-size estimate
+        long est;          // size estimate
         CSLMSpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                        Node<K,V> origin, K fence, int est) {
+                        Node<K,V> origin, K fence, long est) {
             this.comparator = comparator; this.row = row;
             this.current = origin; this.fence = fence; this.est = est;
         }
 
-        public final long estimateSize() { return (long)est; }
+        public final long estimateSize() { return est; }
     }
 
     static final class KeySpliterator<K,V> extends CSLMSpliterator<K,V>
         implements Spliterator<K> {
         KeySpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                       Node<K,V> origin, K fence, int est) {
+                       Node<K,V> origin, K fence, long est) {
             super(comparator, row, origin, fence, est);
         }
 
@@ -3331,7 +3128,7 @@
                 for (Index<K,V> q = row; q != null; q = row = q.down) {
                     Index<K,V> s; Node<K,V> b, n; K sk;
                     if ((s = q.right) != null && (b = s.node) != null &&
-                        (n = b.next) != null && n.value != null &&
+                        (n = b.next) != null && n.val != null &&
                         (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
                         (f == null || cpr(cmp, sk, f) < 0)) {
                         current = n;
@@ -3352,10 +3149,10 @@
             Node<K,V> e = current;
             current = null;
             for (; e != null; e = e.next) {
-                K k; Object v;
+                K k;
                 if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
                     break;
-                if ((v = e.value) != null && v != e)
+                if (e.val != null)
                     action.accept(k);
             }
         }
@@ -3366,12 +3163,12 @@
             K f = fence;
             Node<K,V> e = current;
             for (; e != null; e = e.next) {
-                K k; Object v;
+                K k;
                 if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
                     e = null;
                     break;
                 }
-                if ((v = e.value) != null && v != e) {
+                if (e.val != null) {
                     current = e.next;
                     action.accept(k);
                     return true;
@@ -3393,21 +3190,23 @@
     }
     // factory method for KeySpliterator
     final KeySpliterator<K,V> keySpliterator() {
-        Comparator<? super K> cmp = comparator;
-        for (;;) { // ensure h corresponds to origin p
-            HeadIndex<K,V> h; Node<K,V> p;
-            Node<K,V> b = (h = head).node;
-            if ((p = b.next) == null || p.value != null)
-                return new KeySpliterator<K,V>(cmp, h, p, null, (p == null) ?
-                                               0 : Integer.MAX_VALUE);
-            p.helpDelete(b, p.next);
+        Index<K,V> h; Node<K,V> n; long est;
+        VarHandle.acquireFence();
+        if ((h = head) == null) {
+            n = null;
+            est = 0L;
         }
+        else {
+            n = h.node;
+            est = getAdderCount();
+        }
+        return new KeySpliterator<K,V>(comparator, h, n, null, est);
     }
 
     static final class ValueSpliterator<K,V> extends CSLMSpliterator<K,V>
         implements Spliterator<V> {
         ValueSpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                       Node<K,V> origin, K fence, int est) {
+                       Node<K,V> origin, K fence, long est) {
             super(comparator, row, origin, fence, est);
         }
 
@@ -3419,7 +3218,7 @@
                 for (Index<K,V> q = row; q != null; q = row = q.down) {
                     Index<K,V> s; Node<K,V> b, n; K sk;
                     if ((s = q.right) != null && (b = s.node) != null &&
-                        (n = b.next) != null && n.value != null &&
+                        (n = b.next) != null && n.val != null &&
                         (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
                         (f == null || cpr(cmp, sk, f) < 0)) {
                         current = n;
@@ -3440,13 +3239,11 @@
             Node<K,V> e = current;
             current = null;
             for (; e != null; e = e.next) {
-                K k; Object v;
+                K k; V v;
                 if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
                     break;
-                if ((v = e.value) != null && v != e) {
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    action.accept(vv);
-                }
+                if ((v = e.val) != null)
+                    action.accept(v);
             }
         }
 
@@ -3456,15 +3253,14 @@
             K f = fence;
             Node<K,V> e = current;
             for (; e != null; e = e.next) {
-                K k; Object v;
+                K k; V v;
                 if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
                     e = null;
                     break;
                 }
-                if ((v = e.value) != null && v != e) {
+                if ((v = e.val) != null) {
                     current = e.next;
-                    @SuppressWarnings("unchecked") V vv = (V)v;
-                    action.accept(vv);
+                    action.accept(v);
                     return true;
                 }
             }
@@ -3480,21 +3276,23 @@
 
     // Almost the same as keySpliterator()
     final ValueSpliterator<K,V> valueSpliterator() {
-        Comparator<? super K> cmp = comparator;
-        for (;;) {
-            HeadIndex<K,V> h; Node<K,V> p;
-            Node<K,V> b = (h = head).node;
-            if ((p = b.next) == null || p.value != null)
-                return new ValueSpliterator<K,V>(cmp, h, p, null, (p == null) ?
-                                                 0 : Integer.MAX_VALUE);
-            p.helpDelete(b, p.next);
+        Index<K,V> h; Node<K,V> n; long est;
+        VarHandle.acquireFence();
+        if ((h = head) == null) {
+            n = null;
+            est = 0L;
         }
+        else {
+            n = h.node;
+            est = getAdderCount();
+        }
+        return new ValueSpliterator<K,V>(comparator, h, n, null, est);
     }
 
     static final class EntrySpliterator<K,V> extends CSLMSpliterator<K,V>
         implements Spliterator<Map.Entry<K,V>> {
         EntrySpliterator(Comparator<? super K> comparator, Index<K,V> row,
-                         Node<K,V> origin, K fence, int est) {
+                         Node<K,V> origin, K fence, long est) {
             super(comparator, row, origin, fence, est);
         }
 
@@ -3506,7 +3304,7 @@
                 for (Index<K,V> q = row; q != null; q = row = q.down) {
                     Index<K,V> s; Node<K,V> b, n; K sk;
                     if ((s = q.right) != null && (b = s.node) != null &&
-                        (n = b.next) != null && n.value != null &&
+                        (n = b.next) != null && n.val != null &&
                         (sk = n.key) != null && cpr(cmp, sk, ek) > 0 &&
                         (f == null || cpr(cmp, sk, f) < 0)) {
                         current = n;
@@ -3527,13 +3325,12 @@
             Node<K,V> e = current;
             current = null;
             for (; e != null; e = e.next) {
-                K k; Object v;
+                K k; V v;
                 if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0)
                     break;
-                if ((v = e.value) != null && v != e) {
-                    @SuppressWarnings("unchecked") V vv = (V)v;
+                if ((v = e.val) != null) {
                     action.accept
-                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, vv));
+                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, v));
                 }
             }
         }
@@ -3544,16 +3341,15 @@
             K f = fence;
             Node<K,V> e = current;
             for (; e != null; e = e.next) {
-                K k; Object v;
+                K k; V v;
                 if ((k = e.key) != null && f != null && cpr(cmp, f, k) <= 0) {
                     e = null;
                     break;
                 }
-                if ((v = e.value) != null && v != e) {
+                if ((v = e.val) != null) {
                     current = e.next;
-                    @SuppressWarnings("unchecked") V vv = (V)v;
                     action.accept
-                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, vv));
+                        (new AbstractMap.SimpleImmutableEntry<K,V>(k, v));
                     return true;
                 }
             }
@@ -3584,26 +3380,37 @@
 
     // Almost the same as keySpliterator()
     final EntrySpliterator<K,V> entrySpliterator() {
-        Comparator<? super K> cmp = comparator;
-        for (;;) { // almost same as key version
-            HeadIndex<K,V> h; Node<K,V> p;
-            Node<K,V> b = (h = head).node;
-            if ((p = b.next) == null || p.value != null)
-                return new EntrySpliterator<K,V>(cmp, h, p, null, (p == null) ?
-                                                 0 : Integer.MAX_VALUE);
-            p.helpDelete(b, p.next);
+        Index<K,V> h; Node<K,V> n; long est;
+        VarHandle.acquireFence();
+        if ((h = head) == null) {
+            n = null;
+            est = 0L;
         }
+        else {
+            n = h.node;
+            est = getAdderCount();
+        }
+        return new EntrySpliterator<K,V>(comparator, h, n, null, est);
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle ADDER;
+    private static final VarHandle NEXT;
+    private static final VarHandle VAL;
+    private static final VarHandle RIGHT;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentSkipListMap.class.getDeclaredField("head"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentSkipListMap.class, "head",
+                                   Index.class);
+            ADDER = l.findVarHandle(ConcurrentSkipListMap.class, "adder",
+                                    LongAdder.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
+            VAL = l.findVarHandle(Node.class, "val", Object.class);
+            RIGHT = l.findVarHandle(Index.class, "right", Index.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java b/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
index 2e11b17..140bde4 100644
--- a/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
+++ b/ojluni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
@@ -35,23 +35,18 @@
 
 package java.util.concurrent;
 
+import java.lang.reflect.Field;
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.NavigableMap;
 import java.util.NavigableSet;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.Spliterator;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// fixed framework docs link to "Collection#optional"
-// END android-note
-
 /**
  * A scalable concurrent {@link NavigableSet} implementation based on
  * a {@link ConcurrentSkipListMap}.  The elements of the set are kept
@@ -75,12 +70,12 @@
  * 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 {@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 {@code addAll} operation might view only some
- * of the added elements.
+ *
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe 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}
@@ -89,6 +84,10 @@
  * because {@code null} arguments and return values cannot be reliably
  * distinguished from the absence of elements.
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @author Doug Lea
  * @param <E> the type of elements maintained by this set
  * @since 1.6
@@ -310,9 +309,7 @@
         Collection<?> c = (Collection<?>) o;
         try {
             return containsAll(c) && c.containsAll(this);
-        } catch (ClassCastException unused) {
-            return false;
-        } catch (NullPointerException unused) {
+        } catch (ClassCastException | NullPointerException unused) {
             return false;
         }
     }
@@ -327,7 +324,7 @@
      * @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
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if the specified collection or any
      *         of its elements are null
      */
@@ -491,9 +488,9 @@
      * encounter order that is ascending order.  Overriding implementations
      * should document the reporting of additional characteristic values.
      *
-     * <p>The spliterator's comparator (see
-     * {@link java.util.Spliterator#getComparator()}) is {@code null} if
-     * the set's comparator (see {@link #comparator()}) is {@code null}.
+     * <p>The {@linkplain Spliterator#getComparator() spliterator's comparator}
+     * is {@code null} if the {@linkplain #comparator() set's comparator}
+     * is {@code null}.
      * Otherwise, the spliterator's comparator is the same as or imposes the
      * same total ordering as the set's comparator.
      *
@@ -506,18 +503,21 @@
             : ((ConcurrentSkipListMap.SubMap<E,?>)m).new SubMapKeyIterator();
     }
 
-    // Support for resetting map in clone
+    /** Initializes map field; for use in clone. */
     private void setMap(ConcurrentNavigableMap<E,Object> map) {
-        U.putObjectVolatile(this, MAP, map);
-    }
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long MAP;
-    static {
+        Field mapField = java.security.AccessController.doPrivileged(
+            (java.security.PrivilegedAction<Field>) () -> {
+                try {
+                    Field f = ConcurrentSkipListSet.class
+                        .getDeclaredField("m");
+                    f.setAccessible(true);
+                    return f;
+                } catch (ReflectiveOperationException e) {
+                    throw new Error(e);
+                }});
         try {
-            MAP = U.objectFieldOffset
-                (ConcurrentSkipListSet.class.getDeclaredField("m"));
-        } catch (ReflectiveOperationException e) {
+            mapField.set(this, map);
+        } catch (IllegalAccessException e) {
             throw new Error(e);
         }
     }
diff --git a/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java b/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
index ebcbbef..fb464e9 100644
--- a/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
+++ b/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
@@ -34,7 +34,9 @@
 
 package java.util.concurrent;
 
-import java.util.AbstractList;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
@@ -50,6 +52,7 @@
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.function.UnaryOperator;
+import jdk.internal.misc.SharedSecrets;
 
 // Android-changed: Removed javadoc link to collections framework docs
 /**
@@ -81,6 +84,10 @@
  * actions subsequent to the access or removal of that element from
  * the {@code CopyOnWriteArrayList} in another thread.
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this list
@@ -129,17 +136,18 @@
      * @throws NullPointerException if the specified collection is null
      */
     public CopyOnWriteArrayList(Collection<? extends E> c) {
-        Object[] elements;
+        Object[] es;
         if (c.getClass() == CopyOnWriteArrayList.class)
-            elements = ((CopyOnWriteArrayList<?>)c).getArray();
+            es = ((CopyOnWriteArrayList<?>)c).getArray();
         else {
-            elements = c.toArray();
-            // defend against c.toArray (incorrectly) not returning Object[]
-            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
-            if (elements.getClass() != Object[].class)
-                elements = Arrays.copyOf(elements, elements.length, Object[].class);
+            es = c.toArray();
+            // Android-changed: Defend against c.toArray (incorrectly) not returning Object[]
+            //                  (see b/204397945)
+            // if (c.getClass() != java.util.ArrayList.class)
+            if (es.getClass() != Object[].class)
+                es = Arrays.copyOf(es, es.length, Object[].class);
         }
-        setArray(elements);
+        setArray(es);
     }
 
     /**
@@ -175,20 +183,19 @@
      * static version of indexOf, to allow repeated calls without
      * needing to re-acquire array each time.
      * @param o element to search for
-     * @param elements the array
-     * @param index first index to search
-     * @param fence one past last index to search
+     * @param es the array
+     * @param from first index to search
+     * @param to one past last index to search
      * @return index of element, or -1 if absent
      */
-    private static int indexOf(Object o, Object[] elements,
-                               int index, int fence) {
+    private static int indexOfRange(Object o, Object[] es, int from, int to) {
         if (o == null) {
-            for (int i = index; i < fence; i++)
-                if (elements[i] == null)
+            for (int i = from; i < to; i++)
+                if (es[i] == null)
                     return i;
         } else {
-            for (int i = index; i < fence; i++)
-                if (o.equals(elements[i]))
+            for (int i = from; i < to; i++)
+                if (o.equals(es[i]))
                     return i;
         }
         return -1;
@@ -197,18 +204,19 @@
     /**
      * static version of lastIndexOf.
      * @param o element to search for
-     * @param elements the array
-     * @param index first index to search
+     * @param es the array
+     * @param from index of first element of range, last element to search
+     * @param to one past last element of range, first element to search
      * @return index of element, or -1 if absent
      */
-    private static int lastIndexOf(Object o, Object[] elements, int index) {
+    private static int lastIndexOfRange(Object o, Object[] es, int from, int to) {
         if (o == null) {
-            for (int i = index; i >= 0; i--)
-                if (elements[i] == null)
+            for (int i = to - 1; i >= from; i--)
+                if (es[i] == null)
                     return i;
         } else {
-            for (int i = index; i >= 0; i--)
-                if (o.equals(elements[i]))
+            for (int i = to - 1; i >= from; i--)
+                if (o.equals(es[i]))
                     return i;
         }
         return -1;
@@ -223,16 +231,15 @@
      * @return {@code true} if this list contains the specified element
      */
     public boolean contains(Object o) {
-        Object[] elements = getArray();
-        return indexOf(o, elements, 0, elements.length) >= 0;
+        return indexOf(o) >= 0;
     }
 
     /**
      * {@inheritDoc}
      */
     public int indexOf(Object o) {
-        Object[] elements = getArray();
-        return indexOf(o, elements, 0, elements.length);
+        Object[] es = getArray();
+        return indexOfRange(o, es, 0, es.length);
     }
 
     /**
@@ -251,16 +258,16 @@
      * @throws IndexOutOfBoundsException if the specified index is negative
      */
     public int indexOf(E e, int index) {
-        Object[] elements = getArray();
-        return indexOf(e, elements, index, elements.length);
+        Object[] es = getArray();
+        return indexOfRange(e, es, index, es.length);
     }
 
     /**
      * {@inheritDoc}
      */
     public int lastIndexOf(Object o) {
-        Object[] elements = getArray();
-        return lastIndexOf(o, elements, elements.length - 1);
+        Object[] es = getArray();
+        return lastIndexOfRange(o, es, 0, es.length);
     }
 
     /**
@@ -280,8 +287,8 @@
      *         than or equal to the current size of this list
      */
     public int lastIndexOf(E e, int index) {
-        Object[] elements = getArray();
-        return lastIndexOf(e, elements, index);
+        Object[] es = getArray();
+        return lastIndexOfRange(e, es, 0, index + 1);
     }
 
     /**
@@ -296,6 +303,9 @@
             CopyOnWriteArrayList<E> clone =
                 (CopyOnWriteArrayList<E>) super.clone();
             clone.resetLock();
+            // Unlike in readObject, here we cannot visibility-piggyback on the
+            // volatile write in setArray().
+            VarHandle.releaseFence();
             return clone;
         } catch (CloneNotSupportedException e) {
             // this shouldn't happen, since we are Cloneable
@@ -317,8 +327,7 @@
      * @return an array containing all the elements in this list
      */
     public Object[] toArray() {
-        Object[] elements = getArray();
-        return Arrays.copyOf(elements, elements.length);
+        return getArray().clone();
     }
 
     /**
@@ -361,12 +370,12 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        Object[] elements = getArray();
-        int len = elements.length;
+        Object[] es = getArray();
+        int len = es.length;
         if (a.length < len)
-            return (T[]) Arrays.copyOf(elements, len, a.getClass());
+            return (T[]) Arrays.copyOf(es, len, a.getClass());
         else {
-            System.arraycopy(elements, 0, a, 0, len);
+            System.arraycopy(es, 0, a, 0, len);
             if (a.length > len)
                 a[len] = null;
             return a;
@@ -376,7 +385,7 @@
     // Positional Access Operations
 
     @SuppressWarnings("unchecked")
-    private E get(Object[] a, int index) {
+    static <E> E elementAt(Object[] a, int index) {
         return (E) a[index];
     }
 
@@ -390,7 +399,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public E get(int index) {
-        return get(getArray(), index);
+        return elementAt(getArray(), index);
     }
 
     /**
@@ -401,18 +410,15 @@
      */
     public E set(int index, E element) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            E oldValue = get(elements, index);
+            Object[] es = getArray();
+            E oldValue = elementAt(es, index);
 
             if (oldValue != element) {
-                int len = elements.length;
-                Object[] newElements = Arrays.copyOf(elements, len);
-                newElements[index] = element;
-                setArray(newElements);
-            } else {
-                // Not quite a no-op; ensures volatile write semantics
-                setArray(elements);
+                es = es.clone();
+                es[index] = element;
             }
+            // Ensure volatile write semantics even when oldvalue == element
+            setArray(es);
             return oldValue;
         }
     }
@@ -425,11 +431,11 @@
      */
     public boolean add(E e) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            Object[] newElements = Arrays.copyOf(elements, len + 1);
-            newElements[len] = e;
-            setArray(newElements);
+            Object[] es = getArray();
+            int len = es.length;
+            es = Arrays.copyOf(es, len + 1);
+            es[len] = e;
+            setArray(es);
             return true;
         }
     }
@@ -443,18 +449,18 @@
      */
     public void add(int index, E element) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
+            Object[] es = getArray();
+            int len = es.length;
             if (index > len || index < 0)
                 throw new IndexOutOfBoundsException(outOfBounds(index, len));
             Object[] newElements;
             int numMoved = len - index;
             if (numMoved == 0)
-                newElements = Arrays.copyOf(elements, len + 1);
+                newElements = Arrays.copyOf(es, len + 1);
             else {
                 newElements = new Object[len + 1];
-                System.arraycopy(elements, 0, newElements, 0, index);
-                System.arraycopy(elements, index, newElements, index + 1,
+                System.arraycopy(es, 0, newElements, 0, index);
+                System.arraycopy(es, index, newElements, index + 1,
                                  numMoved);
             }
             newElements[index] = element;
@@ -471,19 +477,20 @@
      */
     public E remove(int index) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            E oldValue = get(elements, index);
+            Object[] es = getArray();
+            int len = es.length;
+            E oldValue = elementAt(es, index);
             int numMoved = len - index - 1;
+            Object[] newElements;
             if (numMoved == 0)
-                setArray(Arrays.copyOf(elements, len - 1));
+                newElements = Arrays.copyOf(es, len - 1);
             else {
-                Object[] newElements = new Object[len - 1];
-                System.arraycopy(elements, 0, newElements, 0, index);
-                System.arraycopy(elements, index + 1, newElements, index,
+                newElements = new Object[len - 1];
+                System.arraycopy(es, 0, newElements, 0, index);
+                System.arraycopy(es, index + 1, newElements, index,
                                  numMoved);
-                setArray(newElements);
             }
+            setArray(newElements);
             return oldValue;
         }
     }
@@ -502,8 +509,8 @@
      */
     public boolean remove(Object o) {
         Object[] snapshot = getArray();
-        int index = indexOf(o, snapshot, 0, snapshot.length);
-        return (index < 0) ? false : remove(o, snapshot, index);
+        int index = indexOfRange(o, snapshot, 0, snapshot.length);
+        return index >= 0 && remove(o, snapshot, index);
     }
 
     /**
@@ -527,7 +534,7 @@
                     return false;
                 if (current[index] == o)
                     break findIndex;
-                index = indexOf(o, current, index, len);
+                index = indexOfRange(o, current, index, len);
                 if (index < 0)
                     return false;
             }
@@ -555,19 +562,19 @@
      */
     void removeRange(int fromIndex, int toIndex) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
+            Object[] es = getArray();
+            int len = es.length;
 
             if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
                 throw new IndexOutOfBoundsException();
             int newlen = len - (toIndex - fromIndex);
             int numMoved = len - toIndex;
             if (numMoved == 0)
-                setArray(Arrays.copyOf(elements, newlen));
+                setArray(Arrays.copyOf(es, newlen));
             else {
                 Object[] newElements = new Object[newlen];
-                System.arraycopy(elements, 0, newElements, 0, fromIndex);
-                System.arraycopy(elements, toIndex, newElements,
+                System.arraycopy(es, 0, newElements, 0, fromIndex);
+                System.arraycopy(es, toIndex, newElements,
                                  fromIndex, numMoved);
                 setArray(newElements);
             }
@@ -582,8 +589,8 @@
      */
     public boolean addIfAbsent(E e) {
         Object[] snapshot = getArray();
-        return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
-            addIfAbsent(e, snapshot);
+        return indexOfRange(e, snapshot, 0, snapshot.length) < 0
+            && addIfAbsent(e, snapshot);
     }
 
     /**
@@ -601,7 +608,7 @@
                     if (current[i] != snapshot[i]
                         && Objects.equals(e, current[i]))
                         return false;
-                if (indexOf(e, current, common, len) >= 0)
+                if (indexOfRange(e, current, common, len) >= 0)
                         return false;
             }
             Object[] newElements = Arrays.copyOf(current, len + 1);
@@ -622,10 +629,10 @@
      * @see #contains(Object)
      */
     public boolean containsAll(Collection<?> c) {
-        Object[] elements = getArray();
-        int len = elements.length;
+        Object[] es = getArray();
+        int len = es.length;
         for (Object e : c) {
-            if (indexOf(e, elements, 0, len) < 0)
+            if (indexOfRange(e, es, 0, len) < 0)
                 return false;
         }
         return true;
@@ -640,34 +647,16 @@
      * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this list contains a null element and the
      *         specified collection does not permit null elements
-     * (<a href="../Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
     public boolean removeAll(Collection<?> c) {
-        if (c == null) throw new NullPointerException();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                // temp array holds those elements we know we want to keep
-                int newlen = 0;
-                Object[] temp = new Object[len];
-                for (int i = 0; i < len; ++i) {
-                    Object element = elements[i];
-                    if (!c.contains(element))
-                        temp[newlen++] = element;
-                }
-                if (newlen != len) {
-                    setArray(Arrays.copyOf(temp, newlen));
-                    return true;
-                }
-            }
-            return false;
-        }
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
     }
 
     /**
@@ -679,34 +668,16 @@
      * @return {@code true} if this list changed as a result of the call
      * @throws ClassCastException if the class of an element of this list
      *         is incompatible with the specified collection
-     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this list contains a null element and the
      *         specified collection does not permit null elements
-     * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
     public boolean retainAll(Collection<?> c) {
-        if (c == null) throw new NullPointerException();
-        synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len != 0) {
-                // temp array holds those elements we know we want to keep
-                int newlen = 0;
-                Object[] temp = new Object[len];
-                for (int i = 0; i < len; ++i) {
-                    Object element = elements[i];
-                    if (c.contains(element))
-                        temp[newlen++] = element;
-                }
-                if (newlen != len) {
-                    setArray(Arrays.copyOf(temp, newlen));
-                    return true;
-                }
-            }
-            return false;
-        }
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
     }
 
     /**
@@ -722,21 +693,24 @@
      */
     public int addAllAbsent(Collection<? extends E> c) {
         Object[] cs = c.toArray();
+        if (c.getClass() != ArrayList.class) {
+            cs = cs.clone();
+        }
         if (cs.length == 0)
             return 0;
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
+            Object[] es = getArray();
+            int len = es.length;
             int added = 0;
             // uniquify and compact elements in cs
             for (int i = 0; i < cs.length; ++i) {
                 Object e = cs[i];
-                if (indexOf(e, elements, 0, len) < 0 &&
-                    indexOf(e, cs, 0, added) < 0)
+                if (indexOfRange(e, es, 0, len) < 0 &&
+                    indexOfRange(e, cs, 0, added) < 0)
                     cs[added++] = e;
             }
             if (added > 0) {
-                Object[] newElements = Arrays.copyOf(elements, len + added);
+                Object[] newElements = Arrays.copyOf(es, len + added);
                 System.arraycopy(cs, 0, newElements, len, added);
                 setArray(newElements);
             }
@@ -770,15 +744,17 @@
         if (cs.length == 0)
             return false;
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (len == 0 && cs.getClass() == Object[].class)
-                setArray(cs);
-            else {
-                Object[] newElements = Arrays.copyOf(elements, len + cs.length);
+            Object[] es = getArray();
+            int len = es.length;
+            Object[] newElements;
+            if (len == 0 && (c.getClass() == CopyOnWriteArrayList.class ||
+                             c.getClass() == ArrayList.class)) {
+                newElements = cs;
+            } else {
+                newElements = Arrays.copyOf(es, len + cs.length);
                 System.arraycopy(cs, 0, newElements, len, cs.length);
-                setArray(newElements);
             }
+            setArray(newElements);
             return true;
         }
     }
@@ -802,8 +778,8 @@
     public boolean addAll(int index, Collection<? extends E> c) {
         Object[] cs = c.toArray();
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
+            Object[] es = getArray();
+            int len = es.length;
             if (index > len || index < 0)
                 throw new IndexOutOfBoundsException(outOfBounds(index, len));
             if (cs.length == 0)
@@ -811,11 +787,11 @@
             int numMoved = len - index;
             Object[] newElements;
             if (numMoved == 0)
-                newElements = Arrays.copyOf(elements, len + cs.length);
+                newElements = Arrays.copyOf(es, len + cs.length);
             else {
                 newElements = new Object[len + cs.length];
-                System.arraycopy(elements, 0, newElements, 0, index);
-                System.arraycopy(elements, index,
+                System.arraycopy(es, 0, newElements, 0, index);
+                System.arraycopy(es, index,
                                  newElements, index + cs.length,
                                  numMoved);
             }
@@ -825,65 +801,106 @@
         }
     }
 
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
     public void forEach(Consumer<? super E> action) {
-        if (action == null) throw new NullPointerException();
+        Objects.requireNonNull(action);
         for (Object x : getArray()) {
             @SuppressWarnings("unchecked") E e = (E) x;
             action.accept(e);
         }
     }
 
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
     public boolean removeIf(Predicate<? super E> filter) {
-        if (filter == null) throw new NullPointerException();
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    // A tiny bit set implementation
+
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
+    }
+
+    private boolean bulkRemove(Predicate<? super E> filter) {
         synchronized (lock) {
-            final Object[] elements = getArray();
-            final int len = elements.length;
-            int i;
-            for (i = 0; i < len; i++) {
-                @SuppressWarnings("unchecked") E e = (E) elements[i];
-                if (filter.test(e)) {
-                    int newlen = i;
-                    final Object[] newElements = new Object[len - 1];
-                    System.arraycopy(elements, 0, newElements, 0, newlen);
-                    for (i++; i < len; i++) {
-                        @SuppressWarnings("unchecked") E x = (E) elements[i];
-                        if (!filter.test(x))
-                            newElements[newlen++] = x;
-                    }
-                    setArray((newlen == len - 1)
-                             ? newElements // one match => one copy
-                             : Arrays.copyOf(newElements, newlen));
-                    return true;
+            return bulkRemove(filter, 0, getArray().length);
+        }
+    }
+
+    boolean bulkRemove(Predicate<? super E> filter, int i, int end) {
+        // assert Thread.holdsLock(lock);
+        final Object[] es = getArray();
+        // Optimize for initial run of survivors
+        for (; i < end && !filter.test(elementAt(es, i)); i++)
+            ;
+        if (i < end) {
+            final int beg = i;
+            final long[] deathRow = nBits(end - beg);
+            int deleted = 1;
+            deathRow[0] = 1L;   // set bit 0
+            for (i = beg + 1; i < end; i++)
+                if (filter.test(elementAt(es, i))) {
+                    setBit(deathRow, i - beg);
+                    deleted++;
                 }
-            }
-            return false;       // zero matches => zero copies
+            // Did filter reentrantly modify the list?
+            if (es != getArray())
+                throw new ConcurrentModificationException();
+            final Object[] newElts = Arrays.copyOf(es, es.length - deleted);
+            int w = beg;
+            for (i = beg; i < end; i++)
+                if (isClear(deathRow, i - beg))
+                    newElts[w++] = es[i];
+            System.arraycopy(es, i, newElts, w, es.length - i);
+            setArray(newElts);
+            return true;
+        } else {
+            if (es != getArray())
+                throw new ConcurrentModificationException();
+            return false;
         }
     }
 
     public void replaceAll(UnaryOperator<E> operator) {
-        if (operator == null) throw new NullPointerException();
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            Object[] newElements = Arrays.copyOf(elements, len);
-            for (int i = 0; i < len; ++i) {
-                @SuppressWarnings("unchecked") E e = (E) elements[i];
-                newElements[i] = operator.apply(e);
-            }
-            setArray(newElements);
+            replaceAllRange(operator, 0, getArray().length);
         }
     }
 
+    void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
+        // assert Thread.holdsLock(lock);
+        Objects.requireNonNull(operator);
+        final Object[] es = getArray().clone();
+        for (; i < end; i++)
+            es[i] = operator.apply(elementAt(es, i));
+        setArray(es);
+    }
+
     public void sort(Comparator<? super E> c) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            Object[] newElements = Arrays.copyOf(elements, elements.length);
-            @SuppressWarnings("unchecked") E[] es = (E[])newElements;
-            Arrays.sort(es, c);
-            setArray(newElements);
+            sortRange(c, 0, getArray().length);
         }
     }
 
+    @SuppressWarnings("unchecked")
+    void sortRange(Comparator<? super E> c, int i, int end) {
+        // assert Thread.holdsLock(lock);
+        final Object[] es = getArray().clone();
+        Arrays.sort(es, i, end, (Comparator<Object>)c);
+        setArray(es);
+    }
+
     /**
      * Saves this list to a stream (that is, serializes it).
      *
@@ -898,12 +915,12 @@
 
         s.defaultWriteObject();
 
-        Object[] elements = getArray();
+        Object[] es = getArray();
         // Write out array length
-        s.writeInt(elements.length);
+        s.writeInt(es.length);
 
         // Write out all elements in the proper order.
-        for (Object element : elements)
+        for (Object element : es)
             s.writeObject(element);
     }
 
@@ -924,12 +941,13 @@
 
         // Read in array length and allocate array
         int len = s.readInt();
-        Object[] elements = new Object[len];
+        SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, len);
+        Object[] es = new Object[len];
 
         // Read in all elements in the proper order.
         for (int i = 0; i < len; i++)
-            elements[i] = s.readObject();
-        setArray(elements);
+            es[i] = s.readObject();
+        setArray(es);
     }
 
     /**
@@ -969,13 +987,19 @@
 
         List<?> list = (List<?>)o;
         Iterator<?> it = list.iterator();
-        Object[] elements = getArray();
-        for (int i = 0, len = elements.length; i < len; i++)
-            if (!it.hasNext() || !Objects.equals(elements[i], it.next()))
+        for (Object element : getArray())
+            if (!it.hasNext() || !Objects.equals(element, it.next()))
                 return false;
-        if (it.hasNext())
-            return false;
-        return true;
+        return !it.hasNext();
+    }
+
+    private static int hashCodeOfRange(Object[] es, int from, int to) {
+        int hashCode = 1;
+        for (int i = from; i < to; i++) {
+            Object x = es[i];
+            hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode());
+        }
+        return hashCode;
     }
 
     /**
@@ -986,10 +1010,8 @@
      * @return the hash code value for this list
      */
     public int hashCode() {
-        int hashCode = 1;
-        for (Object x : getArray())
-            hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode());
-        return hashCode;
+        Object[] es = getArray();
+        return hashCodeOfRange(es, 0, es.length);
     }
 
     /**
@@ -1029,12 +1051,12 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
     public ListIterator<E> listIterator(int index) {
-        Object[] elements = getArray();
-        int len = elements.length;
+        Object[] es = getArray();
+        int len = es.length;
         if (index < 0 || index > len)
             throw new IndexOutOfBoundsException(outOfBounds(index, len));
 
-        return new COWIterator<E>(elements, index);
+        return new COWIterator<E>(es, index);
     }
 
     /**
@@ -1062,9 +1084,9 @@
         /** Index of element to be returned by subsequent call to next.  */
         private int cursor;
 
-        COWIterator(Object[] elements, int initialCursor) {
+        COWIterator(Object[] es, int initialCursor) {
             cursor = initialCursor;
-            snapshot = elements;
+            snapshot = es;
         }
 
         public boolean hasNext() {
@@ -1094,7 +1116,7 @@
         }
 
         public int previousIndex() {
-            return cursor-1;
+            return cursor - 1;
         }
 
         /**
@@ -1125,14 +1147,13 @@
         }
 
         @Override
-        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
             Objects.requireNonNull(action);
             final int size = snapshot.length;
-            for (int i = cursor; i < size; i++) {
-                action.accept((E) snapshot[i]);
-            }
+            int i = cursor;
             cursor = size;
+            for (; i < size; i++)
+                action.accept(elementAt(snapshot, i));
         }
     }
 
@@ -1153,324 +1174,358 @@
      */
     public List<E> subList(int fromIndex, int toIndex) {
         synchronized (lock) {
-            Object[] elements = getArray();
-            int len = elements.length;
-            if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
+            Object[] es = getArray();
+            int len = es.length;
+            int size = toIndex - fromIndex;
+            if (fromIndex < 0 || toIndex > len || size < 0)
                 throw new IndexOutOfBoundsException();
-            return new COWSubList<E>(this, fromIndex, toIndex);
+            return new COWSubList(es, fromIndex, size);
         }
     }
 
     /**
      * Sublist for CopyOnWriteArrayList.
-     * This class extends AbstractList merely for convenience, to
-     * avoid having to define addAll, etc. This doesn't hurt, but
-     * is wasteful.  This class does not need or use modCount
-     * mechanics in AbstractList, but does need to check for
-     * concurrent modification using similar mechanics.  On each
-     * operation, the array that we expect the backing list to use
-     * is checked and updated.  Since we do this for all of the
-     * base operations invoked by those defined in AbstractList,
-     * all is well.  While inefficient, this is not worth
-     * improving.  The kinds of list operations inherited from
-     * AbstractList are already so slow on COW sublists that
-     * adding a bit more space/time doesn't seem even noticeable.
      */
-    private static class COWSubList<E>
-        extends AbstractList<E>
-        implements RandomAccess
-    {
-        private final CopyOnWriteArrayList<E> l;
+    private class COWSubList implements List<E>, RandomAccess {
         private final int offset;
         private int size;
         private Object[] expectedArray;
 
-        // only call this holding l's lock
-        COWSubList(CopyOnWriteArrayList<E> list,
-                   int fromIndex, int toIndex) {
-            // assert Thread.holdsLock(list.lock);
-            l = list;
-            expectedArray = l.getArray();
-            offset = fromIndex;
-            size = toIndex - fromIndex;
+        COWSubList(Object[] es, int offset, int size) {
+            // assert Thread.holdsLock(lock);
+            expectedArray = es;
+            this.offset = offset;
+            this.size = size;
         }
 
-        // only call this holding l's lock
         private void checkForComodification() {
-            // assert Thread.holdsLock(l.lock);
-            if (l.getArray() != expectedArray)
+            // assert Thread.holdsLock(lock);
+            if (getArray() != expectedArray)
                 throw new ConcurrentModificationException();
         }
 
-        // only call this holding l's lock
+        private Object[] getArrayChecked() {
+            // assert Thread.holdsLock(lock);
+            Object[] a = getArray();
+            if (a != expectedArray)
+                throw new ConcurrentModificationException();
+            return a;
+        }
+
         private void rangeCheck(int index) {
-            // assert Thread.holdsLock(l.lock);
+            // assert Thread.holdsLock(lock);
             if (index < 0 || index >= size)
                 throw new IndexOutOfBoundsException(outOfBounds(index, size));
         }
 
+        private void rangeCheckForAdd(int index) {
+            // assert Thread.holdsLock(lock);
+            if (index < 0 || index > size)
+                throw new IndexOutOfBoundsException(outOfBounds(index, size));
+        }
+
+        public Object[] toArray() {
+            final Object[] es;
+            final int offset;
+            final int size;
+            synchronized (lock) {
+                es = getArrayChecked();
+                offset = this.offset;
+                size = this.size;
+            }
+            return Arrays.copyOfRange(es, offset, offset + size);
+        }
+
+        @SuppressWarnings("unchecked")
+        public <T> T[] toArray(T[] a) {
+            final Object[] es;
+            final int offset;
+            final int size;
+            synchronized (lock) {
+                es = getArrayChecked();
+                offset = this.offset;
+                size = this.size;
+            }
+            if (a.length < size)
+                return (T[]) Arrays.copyOfRange(
+                        es, offset, offset + size, a.getClass());
+            else {
+                System.arraycopy(es, offset, a, 0, size);
+                if (a.length > size)
+                    a[size] = null;
+                return a;
+            }
+        }
+
+        public int indexOf(Object o) {
+            final Object[] es;
+            final int offset;
+            final int size;
+            synchronized (lock) {
+                es = getArrayChecked();
+                offset = this.offset;
+                size = this.size;
+            }
+            int i = indexOfRange(o, es, offset, offset + size);
+            return (i == -1) ? -1 : i - offset;
+        }
+
+        public int lastIndexOf(Object o) {
+            final Object[] es;
+            final int offset;
+            final int size;
+            synchronized (lock) {
+                es = getArrayChecked();
+                offset = this.offset;
+                size = this.size;
+            }
+            int i = lastIndexOfRange(o, es, offset, offset + size);
+            return (i == -1) ? -1 : i - offset;
+        }
+
+        public boolean contains(Object o) {
+            return indexOf(o) >= 0;
+        }
+
+        public boolean containsAll(Collection<?> c) {
+            final Object[] es;
+            final int offset;
+            final int size;
+            synchronized (lock) {
+                es = getArrayChecked();
+                offset = this.offset;
+                size = this.size;
+            }
+            for (Object o : c)
+                if (indexOfRange(o, es, offset, offset + size) < 0)
+                    return false;
+            return true;
+        }
+
+        public boolean isEmpty() {
+            return size() == 0;
+        }
+
+        public String toString() {
+            return Arrays.toString(toArray());
+        }
+
+        public int hashCode() {
+            final Object[] es;
+            final int offset;
+            final int size;
+            synchronized (lock) {
+                es = getArrayChecked();
+                offset = this.offset;
+                size = this.size;
+            }
+            return hashCodeOfRange(es, offset, offset + size);
+        }
+
+        public boolean equals(Object o) {
+            if (o == this)
+                return true;
+            if (!(o instanceof List))
+                return false;
+            Iterator<?> it = ((List<?>)o).iterator();
+
+            final Object[] es;
+            final int offset;
+            final int size;
+            synchronized (lock) {
+                es = getArrayChecked();
+                offset = this.offset;
+                size = this.size;
+            }
+
+            for (int i = offset, end = offset + size; i < end; i++)
+                if (!it.hasNext() || !Objects.equals(es[i], it.next()))
+                    return false;
+            return !it.hasNext();
+        }
+
         public E set(int index, E element) {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 rangeCheck(index);
                 checkForComodification();
-                E x = l.set(index+offset, element);
-                expectedArray = l.getArray();
+                E x = CopyOnWriteArrayList.this.set(offset + index, element);
+                expectedArray = getArray();
                 return x;
             }
         }
 
         public E get(int index) {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 rangeCheck(index);
                 checkForComodification();
-                return l.get(index+offset);
+                return CopyOnWriteArrayList.this.get(offset + index);
             }
         }
 
         public int size() {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 checkForComodification();
                 return size;
             }
         }
 
-        public void add(int index, E element) {
-            synchronized (l.lock) {
+        public boolean add(E element) {
+            synchronized (lock) {
                 checkForComodification();
-                if (index < 0 || index > size)
-                    throw new IndexOutOfBoundsException
-                        (outOfBounds(index, size));
-                l.add(index+offset, element);
-                expectedArray = l.getArray();
+                CopyOnWriteArrayList.this.add(offset + size, element);
+                expectedArray = getArray();
+                size++;
+            }
+            return true;
+        }
+
+        public void add(int index, E element) {
+            synchronized (lock) {
+                checkForComodification();
+                rangeCheckForAdd(index);
+                CopyOnWriteArrayList.this.add(offset + index, element);
+                expectedArray = getArray();
                 size++;
             }
         }
 
+        public boolean addAll(Collection<? extends E> c) {
+            synchronized (lock) {
+                final Object[] oldArray = getArrayChecked();
+                boolean modified =
+                    CopyOnWriteArrayList.this.addAll(offset + size, c);
+                size += (expectedArray = getArray()).length - oldArray.length;
+                return modified;
+            }
+        }
+
+        public boolean addAll(int index, Collection<? extends E> c) {
+            synchronized (lock) {
+                rangeCheckForAdd(index);
+                final Object[] oldArray = getArrayChecked();
+                boolean modified =
+                    CopyOnWriteArrayList.this.addAll(offset + index, c);
+                size += (expectedArray = getArray()).length - oldArray.length;
+                return modified;
+            }
+        }
+
         public void clear() {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 checkForComodification();
-                l.removeRange(offset, offset+size);
-                expectedArray = l.getArray();
+                removeRange(offset, offset + size);
+                expectedArray = getArray();
                 size = 0;
             }
         }
 
         public E remove(int index) {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 rangeCheck(index);
                 checkForComodification();
-                E result = l.remove(index+offset);
-                expectedArray = l.getArray();
+                E result = CopyOnWriteArrayList.this.remove(offset + index);
+                expectedArray = getArray();
                 size--;
                 return result;
             }
         }
 
         public boolean remove(Object o) {
-            int index = indexOf(o);
-            if (index == -1)
-                return false;
-            remove(index);
-            return true;
-        }
-
-        public Iterator<E> iterator() {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 checkForComodification();
-                return new COWSubListIterator<E>(l, 0, offset, size);
+                int index = indexOf(o);
+                if (index == -1)
+                    return false;
+                remove(index);
+                return true;
             }
         }
 
+        public Iterator<E> iterator() {
+            return listIterator(0);
+        }
+
+        public ListIterator<E> listIterator() {
+            return listIterator(0);
+        }
+
         public ListIterator<E> listIterator(int index) {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 checkForComodification();
-                if (index < 0 || index > size)
-                    throw new IndexOutOfBoundsException
-                        (outOfBounds(index, size));
-                return new COWSubListIterator<E>(l, index, offset, size);
+                rangeCheckForAdd(index);
+                return new COWSubListIterator<E>(
+                    CopyOnWriteArrayList.this, index, offset, size);
             }
         }
 
         public List<E> subList(int fromIndex, int toIndex) {
-            synchronized (l.lock) {
+            synchronized (lock) {
                 checkForComodification();
                 if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
                     throw new IndexOutOfBoundsException();
-                return new COWSubList<E>(l, fromIndex + offset,
-                                         toIndex + offset);
+                return new COWSubList(expectedArray, fromIndex + offset, toIndex - fromIndex);
             }
         }
 
         public void forEach(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            int lo = offset;
-            int hi = offset + size;
-            Object[] a = expectedArray;
-            if (l.getArray() != a)
-                throw new ConcurrentModificationException();
-            if (lo < 0 || hi > a.length)
-                throw new IndexOutOfBoundsException();
-            for (int i = lo; i < hi; ++i) {
-                @SuppressWarnings("unchecked") E e = (E) a[i];
-                action.accept(e);
+            Objects.requireNonNull(action);
+            int i, end; final Object[] es;
+            synchronized (lock) {
+                es = getArrayChecked();
+                i = offset;
+                end = i + size;
             }
+            for (; i < end; i++)
+                action.accept(elementAt(es, i));
         }
 
         public void replaceAll(UnaryOperator<E> operator) {
-            if (operator == null) throw new NullPointerException();
-            synchronized (l.lock) {
-                int lo = offset;
-                int hi = offset + size;
-                Object[] elements = expectedArray;
-                if (l.getArray() != elements)
-                    throw new ConcurrentModificationException();
-                int len = elements.length;
-                if (lo < 0 || hi > len)
-                    throw new IndexOutOfBoundsException();
-                Object[] newElements = Arrays.copyOf(elements, len);
-                for (int i = lo; i < hi; ++i) {
-                    @SuppressWarnings("unchecked") E e = (E) elements[i];
-                    newElements[i] = operator.apply(e);
-                }
-                l.setArray(expectedArray = newElements);
+            synchronized (lock) {
+                checkForComodification();
+                replaceAllRange(operator, offset, offset + size);
+                expectedArray = getArray();
             }
         }
 
         public void sort(Comparator<? super E> c) {
-            synchronized (l.lock) {
-                int lo = offset;
-                int hi = offset + size;
-                Object[] elements = expectedArray;
-                if (l.getArray() != elements)
-                    throw new ConcurrentModificationException();
-                int len = elements.length;
-                if (lo < 0 || hi > len)
-                    throw new IndexOutOfBoundsException();
-                Object[] newElements = Arrays.copyOf(elements, len);
-                @SuppressWarnings("unchecked") E[] es = (E[])newElements;
-                Arrays.sort(es, lo, hi, c);
-                l.setArray(expectedArray = newElements);
+            synchronized (lock) {
+                checkForComodification();
+                sortRange(c, offset, offset + size);
+                expectedArray = getArray();
             }
         }
 
         public boolean removeAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        Object element = elements[i];
-                        if (!c.contains(element))
-                            temp[newSize++] = element;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
-            }
-            return removed;
+            Objects.requireNonNull(c);
+            return bulkRemove(e -> c.contains(e));
         }
 
         public boolean retainAll(Collection<?> c) {
-            if (c == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        Object element = elements[i];
-                        if (c.contains(element))
-                            temp[newSize++] = element;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
-            }
-            return removed;
+            Objects.requireNonNull(c);
+            return bulkRemove(e -> !c.contains(e));
         }
 
         public boolean removeIf(Predicate<? super E> filter) {
-            if (filter == null) throw new NullPointerException();
-            boolean removed = false;
-            synchronized (l.lock) {
-                int n = size;
-                if (n > 0) {
-                    int lo = offset;
-                    int hi = offset + n;
-                    Object[] elements = expectedArray;
-                    if (l.getArray() != elements)
-                        throw new ConcurrentModificationException();
-                    int len = elements.length;
-                    if (lo < 0 || hi > len)
-                        throw new IndexOutOfBoundsException();
-                    int newSize = 0;
-                    Object[] temp = new Object[n];
-                    for (int i = lo; i < hi; ++i) {
-                        @SuppressWarnings("unchecked") E e = (E) elements[i];
-                        if (!filter.test(e))
-                            temp[newSize++] = e;
-                    }
-                    if (newSize != n) {
-                        Object[] newElements = new Object[len - n + newSize];
-                        System.arraycopy(elements, 0, newElements, 0, lo);
-                        System.arraycopy(temp, 0, newElements, lo, newSize);
-                        System.arraycopy(elements, hi, newElements,
-                                         lo + newSize, len - hi);
-                        size = newSize;
-                        removed = true;
-                        l.setArray(expectedArray = newElements);
-                    }
-                }
+            Objects.requireNonNull(filter);
+            return bulkRemove(filter);
+        }
+
+        private boolean bulkRemove(Predicate<? super E> filter) {
+            synchronized (lock) {
+                final Object[] oldArray = getArrayChecked();
+                boolean modified = CopyOnWriteArrayList.this.bulkRemove(
+                    filter, offset, offset + size);
+                size += (expectedArray = getArray()).length - oldArray.length;
+                return modified;
             }
-            return removed;
         }
 
         public Spliterator<E> spliterator() {
-            int lo = offset;
-            int hi = offset + size;
-            Object[] a = expectedArray;
-            if (l.getArray() != a)
-                throw new ConcurrentModificationException();
-            if (lo < 0 || hi > a.length)
-                throw new IndexOutOfBoundsException();
-            return Spliterators.spliterator
-                (a, lo, hi, Spliterator.IMMUTABLE | Spliterator.ORDERED);
+            synchronized (lock) {
+                return Spliterators.spliterator(
+                        getArrayChecked(), offset, offset + size,
+                        Spliterator.IMMUTABLE | Spliterator.ORDERED);
+            }
         }
 
     }
@@ -1483,7 +1538,7 @@
         COWSubListIterator(List<E> l, int index, int offset, int size) {
             this.offset = offset;
             this.size = size;
-            it = l.listIterator(index+offset);
+            it = l.listIterator(index + offset);
         }
 
         public boolean hasNext() {
@@ -1532,23 +1587,27 @@
         @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
             Objects.requireNonNull(action);
-            while (nextIndex() < size) {
+            while (hasNext()) {
                 action.accept(it.next());
             }
         }
     }
 
-    // Support for resetting lock while deserializing
+    /** Initializes the lock; for use when deserializing or cloning. */
     private void resetLock() {
-        U.putObjectVolatile(this, LOCK, new Object());
-    }
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long LOCK;
-    static {
+        Field lockField = java.security.AccessController.doPrivileged(
+            (java.security.PrivilegedAction<Field>) () -> {
+                try {
+                    Field f = CopyOnWriteArrayList.class
+                        .getDeclaredField("lock");
+                    f.setAccessible(true);
+                    return f;
+                } catch (ReflectiveOperationException e) {
+                    throw new Error(e);
+                }});
         try {
-            LOCK = U.objectFieldOffset
-                (CopyOnWriteArrayList.class.getDeclaredField("lock"));
-        } catch (ReflectiveOperationException e) {
+            lockField.set(this, new Object());
+        } catch (IllegalAccessException e) {
             throw new Error(e);
         }
     }
diff --git a/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java b/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
index fb707dd..b14a3e8 100644
--- a/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
+++ b/ojluni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
@@ -45,13 +45,8 @@
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// fixed framework docs link to "Collection#optional"
-// END android-note
-
 /**
- * A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
+ * A {@link Set} that uses an internal {@link CopyOnWriteArrayList}
  * for all of its operations.  Thus, it shares the same basic properties:
  * <ul>
  *  <li>It is best suited for applications in which set sizes generally
@@ -91,6 +86,10 @@
  *   }
  * }}</pre>
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @see CopyOnWriteArrayList
  * @since 1.5
  * @author Doug Lea
@@ -341,10 +340,10 @@
      * @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
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this set contains a null element and the
      *         specified collection does not permit null elements
-     * (<a href="../Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
@@ -364,10 +363,10 @@
      * @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
-     * (<a href="../Collection.html#optional-restrictions">optional</a>)
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>)
      * @throws NullPointerException if this set contains a null element and the
      *         specified collection does not permit null elements
-     * (<a href="../Collection.html#optional-restrictions">optional</a>),
+     * (<a href="{@docRoot}/java.base/java/util/Collection.html#optional-restrictions">optional</a>),
      *         or if the specified collection is null
      * @see #remove(Object)
      */
@@ -412,10 +411,16 @@
                 && compareSets(al.getArray(), (Set<?>) o) == 0);
     }
 
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
     public boolean removeIf(Predicate<? super E> filter) {
         return al.removeIf(filter);
     }
 
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
     public void forEach(Consumer<? super E> action) {
         al.forEach(action);
     }
diff --git a/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java b/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java
index a29208e..a91d12d 100644
--- a/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java
+++ b/ojluni/src/main/java/java/util/concurrent/CountedCompleter.java
@@ -35,6 +35,9 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * A {@link ForkJoinTask} with a completion action performed when
  * triggered and there are no remaining pending actions.
@@ -54,8 +57,7 @@
  * 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
+ * components such as {@link Phaser} and {@link 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
@@ -117,102 +119,114 @@
  * 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.
+ * continuations, other tasks 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
+ * <p>For example, here is an initial version of a utility method 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 their 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()}).
+ * The utility method sets up the root task and invokes it (here,
+ * implicitly using the {@link ForkJoinPool#commonPool()}).  It is
+ * straightforward and reliable (but not optimal) to always set the
+ * pending count to the number of child tasks and call {@code
+ * tryComplete()} immediately before returning.
  *
  * <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
+ * public static <E> void forEach(E[] array, Consumer<E> action) {
+ *   class Task extends CountedCompleter<Void> {
+ *     final int lo, hi;
+ *     Task(Task parent, int lo, int hi) {
+ *       super(parent); this.lo = lo; this.hi = hi;
  *     }
- *     else if (hi > lo)
- *       op.apply(array[lo]);
- *     tryComplete();
+ *
+ *     public void compute() {
+ *       if (hi - lo >= 2) {
+ *         int mid = (lo + hi) >>> 1;
+ *         // must set pending count before fork
+ *         setPendingCount(2);
+ *         new Task(this, mid, hi).fork(); // right child
+ *         new Task(this, lo, mid).fork(); // left child
+ *       }
+ *       else if (hi > lo)
+ *         action.accept(array[lo]);
+ *       tryComplete();
+ *     }
  *   }
+ *   new Task(null, 0, array.length).invoke();
  * }}</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:
+ * of tail recursion removal.)  Also, when the last action in a task
+ * is to fork or invoke a subtask (a "tail call"), the call to {@code
+ * tryComplete()} can be optimized away, at the cost of making the
+ * pending count look "off by 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>
+ *     public void compute() {
+ *       if (hi - lo >= 2) {
+ *         int mid = (lo + hi) >>> 1;
+ *         setPendingCount(1); // looks off by one, but correct!
+ *         new Task(this, mid, hi).fork(); // right child
+ *         new Task(this, lo, mid).compute(); // direct invoke
+ *       } else {
+ *         if (hi > lo)
+ *           action.accept(array[lo]);
+ *         tryComplete();
+ *       }
+ *     }}</pre>
  *
  * As a further optimization, notice that the left task need not even exist.
- * Instead of creating a new one, we can iterate using the original task,
+ * Instead of creating a new one, we can continue using the original task,
  * and add a pending count for each fork.  Additionally, because no task
  * in this tree implements an {@link #onCompletion(CountedCompleter)} method,
- * {@code tryComplete()} can be replaced with {@link #propagateCompletion}.
+ * {@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;
+ *     public void compute() {
+ *       int n = hi - lo;
+ *       for (; n >= 2; n /= 2) {
+ *         addToPendingCount(1);
+ *         new Task(this, lo + n/2, lo + n).fork();
+ *       }
+ *       if (n > 0)
+ *         action.accept(array[lo]);
+ *       propagateCompletion();
+ *     }}</pre>
+ *
+ * When pending counts can be precomputed, they can be established in
+ * the constructor:
+ *
+ * <pre> {@code
+ * public static <E> void forEach(E[] array, Consumer<E> action) {
+ *   class Task extends CountedCompleter<Void> {
+ *     final int lo, hi;
+ *     Task(Task parent, int lo, int hi) {
+ *       super(parent, 31 - Integer.numberOfLeadingZeros(hi - lo));
+ *       this.lo = lo; this.hi = hi;
  *     }
- *     if (h > l)
- *       op.apply(array[l]);
- *     propagateCompletion();
+ *
+ *     public void compute() {
+ *       for (int n = hi - lo; n >= 2; n /= 2)
+ *         new Task(this, lo + n/2, lo + n).fork();
+ *       action.accept(array[lo]);
+ *       propagateCompletion();
+ *     }
  *   }
+ *   if (array.length > 0)
+ *     new Task(null, 0, array.length).invoke();
  * }}</pre>
  *
- * Additional optimizations 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.
+ * Additional optimizations of such classes might entail 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
@@ -524,7 +538,7 @@
      * @param delta the value to add
      */
     public final void addToPendingCount(int delta) {
-        U.getAndAddInt(this, PENDING, delta);
+        PENDING.getAndAdd(this, delta);
     }
 
     /**
@@ -536,7 +550,7 @@
      * @return {@code true} if successful
      */
     public final boolean compareAndSetPendingCount(int expected, int count) {
-        return U.compareAndSwapInt(this, PENDING, expected, count);
+        return PENDING.compareAndSet(this, expected, count);
     }
 
     /**
@@ -548,7 +562,7 @@
     public final int decrementPendingCountUnlessZero() {
         int c;
         do {} while ((c = pending) != 0 &&
-                     !U.compareAndSwapInt(this, PENDING, c, c - 1));
+                     !PENDING.weakCompareAndSet(this, c, c - 1));
         return c;
     }
 
@@ -581,7 +595,7 @@
                     return;
                 }
             }
-            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSet(a, c, c - 1))
                 return;
         }
     }
@@ -596,7 +610,7 @@
      * not, be invoked for each completer in a computation.
      */
     public final void propagateCompletion() {
-        CountedCompleter<?> a = this, s = a;
+        CountedCompleter<?> a = this, s;
         for (int c;;) {
             if ((c = a.pending) == 0) {
                 if ((a = (s = a).completer) == null) {
@@ -604,7 +618,7 @@
                     return;
                 }
             }
-            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSet(a, c, c - 1))
                 return;
         }
     }
@@ -649,7 +663,7 @@
         for (int c;;) {
             if ((c = pending) == 0)
                 return this;
-            else if (U.compareAndSwapInt(this, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSet(this, c, c - 1))
                 return null;
         }
     }
@@ -721,7 +735,7 @@
         CountedCompleter<?> a = this, s = a;
         while (a.onExceptionalCompletion(ex, s) &&
                (a = (s = a).completer) != null && a.status >= 0 &&
-               a.recordExceptionalCompletion(ex) == EXCEPTIONAL)
+               isExceptionalStatus(a.recordExceptionalCompletion(ex)))
             ;
     }
 
@@ -753,15 +767,15 @@
      */
     protected void setRawResult(T t) { }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long PENDING;
+    // VarHandle mechanics
+    private static final VarHandle PENDING;
     static {
         try {
-            PENDING = U.objectFieldOffset
-                (CountedCompleter.class.getDeclaredField("pending"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PENDING = l.findVarHandle(CountedCompleter.class, "pending", int.class);
+
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/CyclicBarrier.java b/ojluni/src/main/java/java/util/concurrent/CyclicBarrier.java
index 5e018f1..269bec4 100644
--- a/ojluni/src/main/java/java/util/concurrent/CyclicBarrier.java
+++ b/ojluni/src/main/java/java/util/concurrent/CyclicBarrier.java
@@ -82,8 +82,7 @@
  *   public Solver(float[][] matrix) {
  *     data = matrix;
  *     N = matrix.length;
- *     Runnable barrierAction =
- *       new Runnable() { public void run() { mergeRows(...); }};
+ *     Runnable barrierAction = () -> mergeRows(...);
  *     barrier = new CyclicBarrier(N, barrierAction);
  *
  *     List<Thread> threads = new ArrayList<>(N);
@@ -132,10 +131,10 @@
  * <i>happen-before</i> actions following a successful return from the
  * corresponding {@code await()} in other threads.
  *
- * @since 1.5
  * @see CountDownLatch
  *
  * @author Doug Lea
+ * @since 1.5
  */
 public class CyclicBarrier {
     /**
@@ -150,7 +149,8 @@
      * but no subsequent reset.
      */
     private static class Generation {
-        boolean broken;         // initially false
+        Generation() {}                 // prevent access constructor creation
+        boolean broken;                 // initially false
     }
 
     /** The lock for guarding barrier entry */
diff --git a/ojluni/src/main/java/java/util/concurrent/DelayQueue.java b/ojluni/src/main/java/java/util/concurrent/DelayQueue.java
index 04a83d9..bf0858d 100644
--- a/ojluni/src/main/java/java/util/concurrent/DelayQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/DelayQueue.java
@@ -41,14 +41,11 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.PriorityQueue;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
-
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} of
  * {@code Delayed} elements, in which an element can only be taken
@@ -63,11 +60,15 @@
  * returns the count of both expired and unexpired elements.
  * This queue does not permit null elements.
  *
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.  The Iterator provided in method {@link
- * #iterator()} is <em>not</em> guaranteed to traverse the elements of
- * the DelayQueue in any particular order.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ * The Iterator provided in method {@link #iterator()} is <em>not</em>
+ * guaranteed to traverse the elements of the DelayQueue in any
+ * particular order.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
  *
  * @since 1.5
  * @author Doug Lea
@@ -322,40 +323,13 @@
     }
 
     /**
-     * Returns first element only if it is expired.
-     * Used only by drainTo.  Call only when holding lock.
-     */
-    private E peekExpired() {
-        // assert lock.isHeldByCurrentThread();
-        E first = q.peek();
-        return (first == null || first.getDelay(NANOSECONDS) > 0) ?
-            null : first;
-    }
-
-    /**
      * @throws UnsupportedOperationException {@inheritDoc}
      * @throws ClassCastException            {@inheritDoc}
      * @throws NullPointerException          {@inheritDoc}
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c) {
-        if (c == null)
-            throw new NullPointerException();
-        if (c == this)
-            throw new IllegalArgumentException();
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            int n = 0;
-            for (E e; (e = peekExpired()) != null;) {
-                c.add(e);       // In this order, in case add() throws.
-                q.poll();
-                ++n;
-            }
-            return n;
-        } finally {
-            lock.unlock();
-        }
+        return drainTo(c, Integer.MAX_VALUE);
     }
 
     /**
@@ -365,8 +339,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         if (maxElements <= 0)
@@ -375,8 +348,11 @@
         lock.lock();
         try {
             int n = 0;
-            for (E e; n < maxElements && (e = peekExpired()) != null;) {
-                c.add(e);       // In this order, in case add() throws.
+            for (E first;
+                 n < maxElements
+                     && (first = q.peek()) != null
+                     && first.getDelay(NANOSECONDS) <= 0;) {
+                c.add(first);   // In this order, in case add() throws.
                 q.poll();
                 ++n;
             }
@@ -547,8 +523,7 @@
         public E next() {
             if (cursor >= array.length)
                 throw new NoSuchElementException();
-            lastRet = cursor;
-            return (E)array[cursor++];
+            return (E)array[lastRet = cursor++];
         }
 
         public void remove() {
diff --git a/ojluni/src/main/java/java/util/concurrent/Exchanger.java b/ojluni/src/main/java/java/util/concurrent/Exchanger.java
index f01a705..c55e5ac 100644
--- a/ojluni/src/main/java/java/util/concurrent/Exchanger.java
+++ b/ojluni/src/main/java/java/util/concurrent/Exchanger.java
@@ -36,6 +36,10 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.concurrent.locks.LockSupport;
+
 /**
  * A synchronization point at which threads can pair and swap elements
  * within pairs.  Each thread presents some object on entry to the
@@ -155,9 +159,7 @@
      * 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 (via
-     * @Contended) to Nodes, embedding "bound" as an Exchanger field,
-     * and reworking some park/unpark mechanics compared to
-     * LockSupport versions.
+     * @Contended) to Nodes, embedding "bound" as an Exchanger field.
      *
      * The arena starts out with only one used slot. We expand the
      * effective arena size by tracking collisions; i.e., failed CASes
@@ -233,29 +235,23 @@
      * 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.)
+     * mainly, here, bulky spin->yield->block/cancel code.  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.
+     * The index distance (as a shift value) between any two used slots
+     * in the arena, spacing them out to avoid false sharing.
      */
-    private static final int ASHIFT = 7;
+    private static final int ASHIFT = 5;
 
     /**
      * The maximum supported arena index. The maximum allocatable
@@ -306,8 +302,7 @@
      * Nodes hold partially exchanged data, plus other per-thread
      * bookkeeping. Padded via @Contended to reduce memory contention.
      */
-    // Android-removed: @Contended, this hint is not used by the Android runtime.
-    //@jdk.internal.vm.annotation.Contended
+    @jdk.internal.vm.annotation.Contended
     static final class Node {
         int index;              // Arena index
         int bound;              // Last recorded value of Exchanger.bound
@@ -358,27 +353,31 @@
      */
     private final Object arenaExchange(Object item, boolean timed, long ns) {
         Node[] a = arena;
+        int alen = a.length;
         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)) {
+            int b, m, c;
+            int j = (i << ASHIFT) + ((1 << ASHIFT) - 1);
+            if (j < 0 || j >= alen)
+                j = alen - 1;
+            Node q = (Node)AA.getAcquire(a, j);
+            if (q != null && AA.compareAndSet(a, j, q, null)) {
                 Object v = q.item;                     // release
                 q.match = item;
                 Thread w = q.parked;
                 if (w != null)
-                    U.unpark(w);
+                    LockSupport.unpark(w);
                 return v;
             }
             else if (i <= (m = (b = bound) & MMASK) && q == null) {
                 p.item = item;                         // offer
-                if (U.compareAndSwapObject(a, j, null, p)) {
+                if (AA.compareAndSet(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);
+                            MATCH.setRelease(p, null);
                             p.item = null;             // clear for next use
                             p.hash = h;
                             return v;
@@ -391,22 +390,24 @@
                                      (--spins & ((SPINS >>> 1) - 1)) == 0)
                                 Thread.yield();        // two yields per wait
                         }
-                        else if (U.getObjectVolatile(a, j) != p)
+                        else if (AA.getAcquire(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);
+                            if (AA.getAcquire(a, j) == p) {
+                                if (ns == 0L)
+                                    LockSupport.park(this);
+                                else
+                                    LockSupport.parkNanos(this, ns);
+                            }
                             p.parked = null;
-                            U.putObject(t, BLOCKER, null);
                         }
-                        else if (U.getObjectVolatile(a, j) == p &&
-                                 U.compareAndSwapObject(a, j, p, null)) {
+                        else if (AA.getAcquire(a, j) == p &&
+                                 AA.compareAndSet(a, j, p, null)) {
                             if (m != 0)                // try to shrink
-                                U.compareAndSwapInt(this, BOUND, b, b + SEQ - 1);
+                                BOUND.compareAndSet(this, b, b + SEQ - 1);
                             p.item = null;
                             p.hash = h;
                             i = p.index >>>= 1;        // descend
@@ -428,7 +429,7 @@
                     i = (i != m || m == 0) ? m : m - 1;
                 }
                 else if ((c = p.collides) < m || m == FULL ||
-                         !U.compareAndSwapInt(this, BOUND, b, b + SEQ + 1)) {
+                         !BOUND.compareAndSet(this, b, b + SEQ + 1)) {
                     p.collides = c + 1;
                     i = (i == 0) ? m : i - 1;          // cyclically traverse
                 }
@@ -457,24 +458,24 @@
 
         for (Node q;;) {
             if ((q = slot) != null) {
-                if (U.compareAndSwapObject(this, SLOT, q, null)) {
+                if (SLOT.compareAndSet(this, q, null)) {
                     Object v = q.item;
                     q.match = item;
                     Thread w = q.parked;
                     if (w != null)
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                     return v;
                 }
                 // create arena on contention, but continue until slot null
                 if (NCPU > 1 && bound == 0 &&
-                    U.compareAndSwapInt(this, BOUND, 0, SEQ))
+                    BOUND.compareAndSet(this, 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))
+                if (SLOT.compareAndSet(this, null, p))
                     break;
                 p.item = null;
             }
@@ -497,19 +498,21 @@
                 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);
+                if (slot == p) {
+                    if (ns == 0L)
+                        LockSupport.park(this);
+                    else
+                        LockSupport.parkNanos(this, ns);
+                }
                 p.parked = null;
-                U.putObject(t, BLOCKER, null);
             }
-            else if (U.compareAndSwapObject(this, SLOT, p, null)) {
+            else if (SLOT.compareAndSet(this, p, null)) {
                 v = timed && ns <= 0L && !t.isInterrupted() ? TIMED_OUT : null;
                 break;
             }
         }
-        U.putOrderedObject(p, MATCH, null);
+        MATCH.setRelease(p, null);
         p.item = null;
         p.hash = h;
         return v;
@@ -558,8 +561,9 @@
     @SuppressWarnings("unchecked")
     public V exchange(V x) throws InterruptedException {
         Object v;
+        Node[] a;
         Object item = (x == null) ? NULL_ITEM : x; // translate null args
-        if ((arena != null ||
+        if (((a = arena) != null ||
              (v = slotExchange(item, false, 0L)) == null) &&
             ((Thread.interrupted() || // disambiguates null return
               (v = arenaExchange(item, false, 0L)) == null)))
@@ -625,33 +629,20 @@
         return (v == NULL_ITEM) ? null : (V)v;
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    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;
+    // VarHandle mechanics
+    private static final VarHandle BOUND;
+    private static final VarHandle SLOT;
+    private static final VarHandle MATCH;
+    private static final VarHandle AA;
     static {
         try {
-            BOUND = U.objectFieldOffset
-                (Exchanger.class.getDeclaredField("bound"));
-            SLOT = U.objectFieldOffset
-                (Exchanger.class.getDeclaredField("slot"));
-
-            MATCH = U.objectFieldOffset
-                (Node.class.getDeclaredField("match"));
-
-            BLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
-
-            int scale = U.arrayIndexScale(Node[].class);
-            if ((scale & (scale - 1)) != 0 || scale > (1 << ASHIFT))
-                throw new Error("Unsupported array scale");
-            // ABASE absorbs padding in front of element 0
-            ABASE = U.arrayBaseOffset(Node[].class) + (1 << ASHIFT);
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            BOUND = l.findVarHandle(Exchanger.class, "bound", int.class);
+            SLOT = l.findVarHandle(Exchanger.class, "slot", Node.class);
+            MATCH = l.findVarHandle(Node.class, "match", Object.class);
+            AA = MethodHandles.arrayElementVarHandle(Node[].class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 
diff --git a/ojluni/src/main/java/java/util/concurrent/Executor.java b/ojluni/src/main/java/java/util/concurrent/Executor.java
index a615705..378cacd 100644
--- a/ojluni/src/main/java/java/util/concurrent/Executor.java
+++ b/ojluni/src/main/java/java/util/concurrent/Executor.java
@@ -87,14 +87,12 @@
  *     this.executor = executor;
  *   }
  *
- *   public synchronized void execute(final Runnable r) {
- *     tasks.add(new Runnable() {
- *       public void run() {
- *         try {
- *           r.run();
- *         } finally {
- *           scheduleNext();
- *         }
+ *   public synchronized void execute(Runnable r) {
+ *     tasks.add(() -> {
+ *       try {
+ *         r.run();
+ *       } finally {
+ *         scheduleNext();
  *       }
  *     });
  *     if (active == null) {
diff --git a/ojluni/src/main/java/java/util/concurrent/ExecutorCompletionService.java b/ojluni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
index a093844..d60d3dd 100644
--- a/ojluni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
+++ b/ojluni/src/main/java/java/util/concurrent/ExecutorCompletionService.java
@@ -56,13 +56,11 @@
  * void solve(Executor e,
  *            Collection<Callable<Result>> solvers)
  *     throws InterruptedException, ExecutionException {
- *   CompletionService<Result> ecs
- *       = new ExecutorCompletionService<Result>(e);
- *   for (Callable<Result> s : solvers)
- *     ecs.submit(s);
- *   int n = solvers.size();
- *   for (int i = 0; i < n; ++i) {
- *     Result r = ecs.take().get();
+ *   CompletionService<Result> cs
+ *       = new ExecutorCompletionService<>(e);
+ *   solvers.forEach(cs::submit);
+ *   for (int i = solvers.size(); i > 0; i--) {
+ *     Result r = cs.take().get();
  *     if (r != null)
  *       use(r);
  *   }
@@ -76,32 +74,31 @@
  * void solve(Executor e,
  *            Collection<Callable<Result>> solvers)
  *     throws InterruptedException {
- *   CompletionService<Result> ecs
- *       = new ExecutorCompletionService<Result>(e);
+ *   CompletionService<Result> cs
+ *       = new ExecutorCompletionService<>(e);
  *   int n = solvers.size();
  *   List<Future<Result>> futures = new ArrayList<>(n);
  *   Result result = null;
  *   try {
- *     for (Callable<Result> s : solvers)
- *       futures.add(ecs.submit(s));
- *     for (int i = 0; i < n; ++i) {
+ *     solvers.forEach(solver -> futures.add(cs.submit(solver)));
+ *     for (int i = n; i > 0; i--) {
  *       try {
- *         Result r = ecs.take().get();
+ *         Result r = cs.take().get();
  *         if (r != null) {
  *           result = r;
  *           break;
  *         }
  *       } catch (ExecutionException ignore) {}
  *     }
- *   }
- *   finally {
- *     for (Future<Result> f : futures)
- *       f.cancel(true);
+ *   } finally {
+ *     futures.forEach(future -> future.cancel(true));
  *   }
  *
  *   if (result != null)
  *     use(result);
  * }}</pre>
+ *
+ * @since 1.5
  */
 public class ExecutorCompletionService<V> implements CompletionService<V> {
     private final Executor executor;
@@ -177,6 +174,10 @@
         this.completionQueue = completionQueue;
     }
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public Future<V> submit(Callable<V> task) {
         if (task == null) throw new NullPointerException();
         RunnableFuture<V> f = newTaskFor(task);
@@ -184,6 +185,10 @@
         return f;
     }
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public Future<V> submit(Runnable task, V result) {
         if (task == null) throw new NullPointerException();
         RunnableFuture<V> f = newTaskFor(task, result);
diff --git a/ojluni/src/main/java/java/util/concurrent/Executors.java b/ojluni/src/main/java/java/util/concurrent/Executors.java
index 565fdeb..e8cc0c1 100644
--- a/ojluni/src/main/java/java/util/concurrent/Executors.java
+++ b/ojluni/src/main/java/java/util/concurrent/Executors.java
@@ -35,6 +35,7 @@
 
 package java.util.concurrent;
 
+import static java.lang.ref.Reference.reachabilityFence;
 import dalvik.annotation.optimization.ReachabilitySensitive;
 import java.security.AccessControlContext;
 import java.security.AccessControlException;
@@ -190,9 +191,7 @@
      * returned executor is guaranteed not to be reconfigurable to use
      * additional threads.
      *
-     * @param threadFactory the factory to use when creating new
-     * threads
-     *
+     * @param threadFactory the factory to use when creating new threads
      * @return the newly created single-threaded Executor
      * @throws NullPointerException if threadFactory is null
      */
@@ -231,6 +230,7 @@
      * will reuse previously constructed threads when they are
      * available, and uses the provided
      * ThreadFactory to create new threads when needed.
+     *
      * @param threadFactory the factory to use when creating new threads
      * @return the newly created thread pool
      * @throws NullPointerException if threadFactory is null
@@ -253,6 +253,7 @@
      * given time. Unlike the otherwise equivalent
      * {@code newScheduledThreadPool(1)} the returned executor is
      * guaranteed not to be reconfigurable to use additional threads.
+     *
      * @return the newly created scheduled executor
      */
     public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
@@ -271,9 +272,9 @@
      * 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
-     * threads
-     * @return a newly created scheduled executor
+     *
+     * @param threadFactory the factory to use when creating new threads
+     * @return the newly created scheduled executor
      * @throws NullPointerException if threadFactory is null
      */
     public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
@@ -286,7 +287,7 @@
      * given delay, or to execute periodically.
      * @param corePoolSize the number of threads to keep in the pool,
      * even if they are idle
-     * @return a newly created scheduled thread pool
+     * @return the newly created scheduled thread pool
      * @throws IllegalArgumentException if {@code corePoolSize < 0}
      */
     public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
@@ -300,7 +301,7 @@
      * even if they are idle
      * @param threadFactory the factory to use when the executor
      * creates a new thread
-     * @return a newly created scheduled thread pool
+     * @return the newly created scheduled thread pool
      * @throws IllegalArgumentException if {@code corePoolSize < 0}
      * @throws NullPointerException if threadFactory is null
      */
@@ -462,6 +463,9 @@
             task.run();
             return result;
         }
+        public String toString() {
+            return super.toString() + "[Wrapped task = " + task + "]";
+        }
     }
 
     /**
@@ -488,6 +492,10 @@
                 throw e.getException();
             }
         }
+
+        public String toString() {
+            return super.toString() + "[Wrapped task = " + task + "]";
+        }
     }
 
     /**
@@ -543,6 +551,10 @@
                 throw e.getException();
             }
         }
+
+        public String toString() {
+            return super.toString() + "[Wrapped task = " + task + "]";
+        }
     }
 
     /**
@@ -604,7 +616,7 @@
         public Thread newThread(final Runnable r) {
             return super.newThread(new Runnable() {
                 public void run() {
-                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    AccessController.doPrivileged(new PrivilegedAction<>() {
                         public Void run() {
                             Thread.currentThread().setContextClassLoader(ccl);
                             r.run();
@@ -621,47 +633,79 @@
      * of an ExecutorService implementation.
      */
     private static class DelegatedExecutorService
-            extends AbstractExecutorService {
+            implements ExecutorService {
         // Android-added: @ReachabilitySensitive
         // Needed for FinalizableDelegatedExecutorService below.
         @ReachabilitySensitive
         private final ExecutorService e;
         DelegatedExecutorService(ExecutorService executor) { e = executor; }
-        public void execute(Runnable command) { e.execute(command); }
+        public void execute(Runnable command) {
+            try {
+                e.execute(command);
+            } finally { reachabilityFence(this); }
+        }
         public void shutdown() { e.shutdown(); }
-        public List<Runnable> shutdownNow() { return e.shutdownNow(); }
-        public boolean isShutdown() { return e.isShutdown(); }
-        public boolean isTerminated() { return e.isTerminated(); }
+        public List<Runnable> shutdownNow() {
+            try {
+                return e.shutdownNow();
+            } finally { reachabilityFence(this); }
+        }
+        public boolean isShutdown() {
+            try {
+                return e.isShutdown();
+            } finally { reachabilityFence(this); }
+        }
+        public boolean isTerminated() {
+            try {
+                return e.isTerminated();
+            } finally { reachabilityFence(this); }
+        }
         public boolean awaitTermination(long timeout, TimeUnit unit)
             throws InterruptedException {
-            return e.awaitTermination(timeout, unit);
+            try {
+                return e.awaitTermination(timeout, unit);
+            } finally { reachabilityFence(this); }
         }
         public Future<?> submit(Runnable task) {
-            return e.submit(task);
+            try {
+                return e.submit(task);
+            } finally { reachabilityFence(this); }
         }
         public <T> Future<T> submit(Callable<T> task) {
-            return e.submit(task);
+            try {
+                return e.submit(task);
+            } finally { reachabilityFence(this); }
         }
         public <T> Future<T> submit(Runnable task, T result) {
-            return e.submit(task, result);
+            try {
+                return e.submit(task, result);
+            } finally { reachabilityFence(this); }
         }
         public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
             throws InterruptedException {
-            return e.invokeAll(tasks);
+            try {
+                return e.invokeAll(tasks);
+            } finally { reachabilityFence(this); }
         }
         public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                              long timeout, TimeUnit unit)
             throws InterruptedException {
-            return e.invokeAll(tasks, timeout, unit);
+            try {
+                return e.invokeAll(tasks, timeout, unit);
+            } finally { reachabilityFence(this); }
         }
         public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
             throws InterruptedException, ExecutionException {
-            return e.invokeAny(tasks);
+            try {
+                return e.invokeAny(tasks);
+            } finally { reachabilityFence(this); }
         }
         public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                                long timeout, TimeUnit unit)
             throws InterruptedException, ExecutionException, TimeoutException {
-            return e.invokeAny(tasks, timeout, unit);
+            try {
+                return e.invokeAny(tasks, timeout, unit);
+            } finally { reachabilityFence(this); }
         }
     }
 
@@ -670,6 +714,7 @@
         FinalizableDelegatedExecutorService(ExecutorService executor) {
             super(executor);
         }
+        @SuppressWarnings("deprecation")
         protected void finalize() {
             super.shutdown();
         }
diff --git a/ojluni/src/main/java/java/util/concurrent/Flow.java b/ojluni/src/main/java/java/util/concurrent/Flow.java
index 0231790..727a507 100644
--- a/ojluni/src/main/java/java/util/concurrent/Flow.java
+++ b/ojluni/src/main/java/java/util/concurrent/Flow.java
@@ -85,9 +85,9 @@
  *       this.executor = executor;
  *     }
  *     public synchronized void request(long n) {
- *       if (n != 0 && !completed) {
+ *       if (!completed) {
  *         completed = true;
- *         if (n < 0) {
+ *         if (n <= 0) {
  *           IllegalArgumentException ex = new IllegalArgumentException();
  *           executor.execute(() -> subscriber.onError(ex));
  *         } else {
diff --git a/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java b/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java
index 04ad7d7..109a63c 100644
--- a/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java
+++ b/ojluni/src/main/java/java/util/concurrent/ForkJoinPool.java
@@ -36,15 +36,19 @@
 package java.util.concurrent;
 
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.security.AccessController;
 import java.security.AccessControlContext;
+import java.security.Permission;
 import java.security.Permissions;
+import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Predicate;
 import java.util.concurrent.locks.LockSupport;
 
 /**
@@ -63,7 +67,8 @@
  * 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.
+ * tasks that are never joined. All worker threads are initialized
+ * with {@link Thread#isDaemon} set {@code true}.
  *
  * <p>A static {@link #commonPool()} is available and appropriate for
  * most applications. The common pool is used by any ForkJoinTask that
@@ -81,7 +86,9 @@
  * 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.
+ * synchronization accommodated. The default policies may be
+ * overridden using a constructor with parameters corresponding to
+ * those documented in class {@link ThreadPoolExecutor}.
  *
  * <p>In addition to execution and lifecycle control methods, this
  * class provides status check methods (for example
@@ -102,48 +109,54 @@
  * 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>
+ * <table class="plain">
  * <caption>Summary of task execution methods</caption>
  *  <tr>
  *    <td></td>
- *    <td ALIGN=CENTER> <b>Call from non-fork/join clients</b></td>
- *    <td ALIGN=CENTER> <b>Call from within fork/join computations</b></td>
+ *    <th scope="col"> Call from non-fork/join clients</th>
+ *    <th scope="col"> Call from within fork/join computations</th>
  *  </tr>
  *  <tr>
- *    <td> <b>Arrange async execution</b></td>
+ *    <th scope="row" style="text-align:left"> Arrange async execution</th>
  *    <td> {@link #execute(ForkJoinTask)}</td>
  *    <td> {@link ForkJoinTask#fork}</td>
  *  </tr>
  *  <tr>
- *    <td> <b>Await and obtain result</b></td>
+ *    <th scope="row" style="text-align:left"> Await and obtain result</th>
  *    <td> {@link #invoke(ForkJoinTask)}</td>
  *    <td> {@link ForkJoinTask#invoke}</td>
  *  </tr>
  *  <tr>
- *    <td> <b>Arrange exec and obtain Future</b></td>
+ *    <th scope="row" style="text-align:left"> Arrange exec and obtain Future</th>
  *    <td> {@link #submit(ForkJoinTask)}</td>
  *    <td> {@link ForkJoinTask#fork} (ForkJoinTasks <em>are</em> Futures)</td>
  *  </tr>
  * </table>
  *
- * <p>The common pool is by default constructed with default
- * parameters, but these may be controlled by setting three
- * {@linkplain System#getProperty system properties}:
+ * <p>The parameters used to construct the common pool may be controlled by
+ * setting the following {@linkplain System#getProperty system properties}:
  * <ul>
  * <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism}
  * - the parallelism level, a non-negative integer
  * <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory}
- * - the class name of a {@link ForkJoinWorkerThreadFactory}
+ * - the class name of a {@link ForkJoinWorkerThreadFactory}.
+ * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
+ * is used to load this class.
  * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
- * - the class name of a {@link UncaughtExceptionHandler}
+ * - the class name of a {@link UncaughtExceptionHandler}.
+ * The {@linkplain ClassLoader#getSystemClassLoader() system class loader}
+ * is used to load this class.
  * <li>{@code java.util.concurrent.ForkJoinPool.common.maximumSpares}
  * - the maximum number of allowed extra threads to maintain target
  * parallelism (default 256).
  * </ul>
- * If a {@link SecurityManager} is present and no factory is
- * specified, then the default pool uses a factory supplying
- * threads that have no {@link Permissions} enabled.
- * The system class loader is used to load these classes.
+ * If no thread factory is supplied via a system property, then the
+ * common pool uses a factory that uses the system class loader as the
+ * {@linkplain Thread#getContextClassLoader() thread context class loader}.
+ * In addition, if a {@link SecurityManager} is present, then
+ * the common pool uses a factory supplying threads that have no
+ * {@link Permissions} enabled.
+ *
  * Upon any error in establishing these settings, default parameters
  * are used. It is possible to disable or limit the use of threads in
  * the common pool by setting the parallelism property to zero, and/or
@@ -162,8 +175,7 @@
  * @since 1.7
  * @author Doug Lea
  */
-// Android-removed: @Contended, this hint is not used by the Android runtime.
-//@jdk.internal.vm.annotation.Contended
+@jdk.internal.vm.annotation.Contended
 public class ForkJoinPool extends AbstractExecutorService {
 
     /*
@@ -173,17 +185,22 @@
      * 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.  This framework began as vehicle for
-     * supporting tree-structured parallelism using work-stealing.
-     * Over time, its scalability advantages led to extensions and
-     * changes to better support more diverse usage contexts.  Because
-     * most internal methods and nested classes are interrelated,
-     * their main rationale and descriptions are presented here;
-     * individual methods and nested classes contain only brief
-     * comments about details.
+     * that may be stolen by other workers. Work-stealing based on
+     * randomized scans generally leads to better throughput than
+     * "work dealing" in which producers assign tasks to idle threads,
+     * in part because threads that have finished other tasks before
+     * the signalled thread wakes up (which can be a long time) can
+     * take the task instead.  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.  This framework began as vehicle for supporting
+     * tree-structured parallelism using work-stealing.  Over time,
+     * its scalability advantages led to extensions and changes to
+     * better support more diverse usage contexts.  Because most
+     * internal methods and nested classes are interrelated, their
+     * main rationale and descriptions are presented here; individual
+     * methods and nested classes contain only brief comments about
+     * details.
      *
      * WorkQueues
      * ==========
@@ -216,9 +233,10 @@
      *
      * (The actual code needs to null-check and size-check the array,
      * uses masking, not mod, for indexing a power-of-two-sized array,
-     * properly fences accesses, and possibly signals waiting workers
-     * to start scanning -- see below.)  Both a successful pop and
-     * poll mainly entail a CAS of a slot from non-null to null.
+     * adds a release fence for publication, and possibly signals
+     * waiting workers to start scanning -- see below.)  Both a
+     * successful pop and poll mainly entail a CAS of a slot from
+     * non-null to null.
      *
      * The pop operation (always performed by owner) is:
      *   if ((the task at top slot is not null) and
@@ -230,10 +248,14 @@
      *        (CAS slot to null))
      *           increment base and return task;
      *
-     * There are several variants of each of these; for example most
-     * versions of poll pre-screen the CAS by rechecking that the base
-     * has not changed since reading the slot, and most methods only
-     * attempt the CAS if base appears not to be equal to top.
+     * There are several variants of each of these. Most uses occur
+     * within operations that also interleave contention or emptiness
+     * tracking or inspection of elements before extracting them, so
+     * must interleave these with the above code. When performed by
+     * owner, getAndSet is used instead of CAS (see for example method
+     * nextLocalTask) which is usually more efficient, and possible
+     * because the top index cannot independently change during the
+     * operation.
      *
      * Memory ordering.  See "Correct and Efficient Work-Stealing for
      * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
@@ -242,33 +264,37 @@
      * algorithms similar to (but different than) the one used here.
      * Extracting tasks in array slots via (fully fenced) CAS provides
      * primary synchronization. The base and top indices imprecisely
-     * guide where to extract from. We do not always require strict
-     * orderings of array and index updates, so sometimes let them be
-     * subject to compiler and processor reorderings. However, the
-     * volatile "base" index also serves as a basis for memory
-     * ordering: Slot accesses are preceded by a read of base,
-     * ensuring happens-before ordering with respect to stealers (so
-     * the slots themselves can be read via plain array reads.)  The
-     * only other memory orderings relied on are maintained in the
-     * course of signalling and activation (see below).  A check that
-     * base == top indicates (momentary) emptiness, but otherwise may
-     * err on the side of possibly making the queue appear nonempty
-     * when a push, pop, or poll have not fully committed, or making
-     * it appear empty when an update of top has not yet been visibly
-     * written.  (Method isEmpty() checks the case of a partially
-     * completed removal of the last element.)  Because of this, 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) visibly completes.
-     * However, in the aggregate, we ensure at least probabilistic
+     * guide where to extract from. We do not usually require strict
+     * orderings of array and index updates. Many index accesses use
+     * plain mode, with ordering constrained by surrounding context
+     * (usually with respect to element CASes or the two WorkQueue
+     * volatile fields source and phase). When not otherwise already
+     * constrained, reads of "base" by queue owners use acquire-mode,
+     * and some externally callable methods preface accesses with
+     * acquire fences.  Additionally, to ensure that index update
+     * writes are not coalesced or postponed in loops etc, "opaque"
+     * mode is used in a few cases where timely writes are not
+     * otherwise ensured. The "locked" versions of push- and pop-
+     * based methods for shared queues differ from owned versions
+     * because locking already forces some of the ordering.
+     *
+     * Because indices and slot contents cannot always be consistent,
+     * a check that base == top indicates (momentary) emptiness, but
+     * otherwise may err on the side of possibly making the queue
+     * appear nonempty when a push, pop, or poll have not fully
+     * committed, or making it appear empty when an update of top has
+     * not yet been visibly written.  (Method isEmpty() checks the
+     * case of a partially completed removal of the last element.)
+     * Because of this, 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)
+     * visibly completes.  This can stall threads when required to
+     * consume from a given queue (see method poll()).  However, in
+     * the aggregate, we ensure at least probabilistic
      * non-blockingness.  If an attempted steal fails, a scanning
      * thief 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, which
-     * retries.)
+     * in-progress poll or new push on any empty queue to complete.
      *
      * This approach also enables support of a user mode in which
      * local task processing is in FIFO, not LIFO order, simply by
@@ -283,16 +309,13 @@
      * choosing existing queues, and 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).  Insertion of tasks in shared
-     * mode requires a lock but we use only a simple spinlock (using
-     * 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. Because it is used only as
-     * a spinlock, unlocking requires only a "releasing" store (using
-     * putOrderedInt).  The qlock is also used during termination
-     * detection, in which case it is forced to a negative
-     * non-lockable value.
+     * tasks that they submitted.  Insertion of tasks in shared mode
+     * requires a lock but we use only a simple spinlock (using field
+     * phase), because submitters encountering a busy queue move to a
+     * different position to use or create other queues -- they block
+     * only when creating and registering new queues. Because it is
+     * used only as a spinlock, unlocking requires only a "releasing"
+     * store (using setRelease) unless otherwise signalling.
      *
      * Management
      * ==========
@@ -306,43 +329,36 @@
      * There are only a few properties that we can globally track or
      * maintain, so we pack them into a small number of variables,
      * often maintaining atomicity without blocking or locking.
-     * Nearly all essentially atomic control state is held in two
+     * Nearly all essentially atomic control state is held in a few
      * volatile variables that are by far most often read (not
-     * written) as status and consistency checks. (Also, field
-     * "config" holds unchanging configuration state.)
+     * written) as status and consistency checks. We pack as much
+     * information into them as we can.
      *
      * Field "ctl" contains 64 bits holding 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
+     * atomically decide to add, enqueue (on an event queue), and
+     * dequeue and release 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
      * subfields.
      *
-     * Field "runState" holds lifetime status, atomically and
-     * monotonically setting STARTED, SHUTDOWN, STOP, and finally
-     * TERMINATED bits.
-     *
-     * Field "auxState" is a ReentrantLock subclass that also
-     * opportunistically holds some other bookkeeping fields accessed
-     * only when locked.  It is mainly used to lock (infrequent)
-     * updates to workQueues.  The auxState instance is itself lazily
-     * constructed (see tryInitialize), requiring a double-check-style
-     * bootstrapping use of field runState, and locking a private
-     * static.
+     * Field "mode" holds configuration parameters as well as lifetime
+     * status, atomically and monotonically setting SHUTDOWN, STOP,
+     * and finally TERMINATED bits.
      *
      * Field "workQueues" holds references to WorkQueues.  It is
-     * updated (only during worker creation and termination) under the
-     * lock, but is otherwise concurrently readable, and accessed
-     * directly. We also ensure that reads of the array reference
-     * itself never become too stale (for example, re-reading before
-     * each scan). 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.
+     * updated (only during worker creation and termination) under
+     * lock (using field workerNamePrefix as lock), but is otherwise
+     * concurrently readable, and accessed directly. We also ensure
+     * that uses of the array reference itself never become too stale
+     * in case of resizing, by arranging that (re-)reads are separated
+     * by at least one acquiring read access.  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 the array needs
+     * to expand to add more workers. Grouping them together in this
+     * way simplifies and speeds up task scanning.
      *
      * All worker thread creation is on-demand, triggered by task
      * submissions, replacement of terminated workers, and/or
@@ -361,30 +377,37 @@
      * 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. In many usages, ramp-up time
-     * to activate workers is the main limiting factor in overall
-     * performance, which is compounded at program start-up by JIT
-     * compilation and allocation. So we streamline this as much as
-     * possible.
+     * is the main limiting factor in overall performance, which is
+     * compounded at program start-up by JIT compilation and
+     * allocation. So we streamline this as much as possible.
      *
-     * The "ctl" field atomically maintains active and total worker
-     * counts as well as a queue to place waiting threads so they can
-     * be located for signalling. Active counts also play the role of
-     * quiescence indicators, so are decremented when workers believe
-     * that there are no more tasks to execute. The "queue" is
-     * actually a form of Treiber stack.  A stack is ideal for
-     * activating threads in most-recently used order. This improves
+     * The "ctl" field atomically maintains total worker and
+     * "released" worker counts, plus the head of the available worker
+     * queue (actually stack, represented by the lower 32bit subfield
+     * of ctl).  Released workers are those known to be scanning for
+     * and/or running tasks. Unreleased ("available") workers are
+     * recorded in the ctl stack. These workers are made available for
+     * signalling by enqueuing in ctl (see method runWorker).  The
+     * "queue" is a form of Treiber stack. This is ideal for
+     * activating threads in most-recently used order, and improves
      * performance and locality, outweighing the disadvantages of
      * being prone to contention and inability to release a worker
-     * unless it is topmost on stack.  We block/unblock workers after
-     * pushing on the idle worker stack (represented by the lower
-     * 32bit subfield of ctl) when they cannot find work.  The top
-     * stack state holds the value of the "scanState" field of the
-     * worker: its index and status, plus a version counter that, in
-     * addition to the count subfields (also serving as version
-     * stamps) provide protection against Treiber stack ABA effects.
+     * unless it is topmost on stack.  To avoid missed signal problems
+     * inherent in any wait/signal design, available workers rescan
+     * for (and if found run) tasks after enqueuing.  Normally their
+     * release status will be updated while doing so, but the released
+     * worker ctl count may underestimate the number of active
+     * threads. (However, it is still possible to determine quiescence
+     * via a validation traversal -- see isQuiescent).  After an
+     * unsuccessful rescan, available workers are blocked until
+     * signalled (see signalWork).  The top stack state holds the
+     * value of the "phase" field of the worker: its index and status,
+     * plus a version counter that, in addition to the count subfields
+     * (also serving as version stamps) provide protection against
+     * Treiber stack ABA effects.
      *
-     * Creating workers. To create a worker, we pre-increment total
-     * count (serving as a reservation), and attempt to construct a
+     * Creating workers. To create a worker, we pre-increment counts
+     * (serving as a reservation), and attempt to construct a
      * ForkJoinWorkerThread via its factory. Upon construction, the
      * new thread invokes registerWorker, where it constructs a
      * WorkQueue and is assigned an index in the workQueues array
@@ -406,15 +429,14 @@
      * submission queues for existing external threads (see
      * externalPush).
      *
-     * WorkQueue field scanState is used by both workers and the pool
-     * to manage and track whether a worker is UNSIGNALLED (possibly
-     * blocked waiting for a signal).  When a worker is inactivated,
-     * its scanState field is set, and is prevented from executing
-     * tasks, even though it must scan once for them to avoid queuing
-     * races. Note that scanState updates lag queue CAS releases so
-     * usage requires care. When queued, the lower 16 bits of
-     * scanState must hold its pool index. So we place the index there
-     * upon initialization (see registerWorker) and otherwise keep it
+     * WorkQueue field "phase" is used by both workers and the pool to
+     * manage and track whether a worker is UNSIGNALLED (possibly
+     * blocked waiting for a signal).  When a worker is enqueued its
+     * phase field is set. Note that phase field updates lag queue CAS
+     * releases so usage requires care -- seeing a negative phase does
+     * not guarantee that the worker is available. When queued, the
+     * lower 16 bits of scanState must hold its pool index. So we
+     * place the index there upon initialization and otherwise keep it
      * there or restore it when necessary.
      *
      * The ctl field also serves as the basis for memory
@@ -423,85 +445,68 @@
      * consumers sync with each other by both writing/CASing ctl (even
      * if to its current value).  This would be extremely costly. So
      * we relax it in several ways: (1) Producers only signal when
-     * their queue is empty. Other workers propagate this signal (in
-     * method scan) when they find tasks. (2) Workers only enqueue
-     * after scanning (see below) and not finding any tasks.  (3)
-     * Rather than CASing ctl to its current value in the common case
-     * where no action is required, we reduce write contention by
-     * equivalently prefacing signalWork when called by an external
-     * task producer using a memory access with full-volatile
-     * semantics or a "fullFence". (4) For internal task producers we
-     * rely on the fact that even if no other workers awaken, the
-     * producer itself will eventually see the task and execute it.
+     * their queue is possibly empty at some point during a push
+     * operation (which requires conservatively checking size zero or
+     * one to cover races). (2) Other workers propagate this signal
+     * when they find tasks in a queue with size greater than one. (3)
+     * Workers only enqueue after scanning (see below) and not finding
+     * any tasks.  (4) Rather than CASing ctl to its current value in
+     * the common case where no action is required, we reduce write
+     * contention by equivalently prefacing signalWork when called by
+     * an external task producer using a memory access with
+     * full-volatile semantics or a "fullFence".
      *
-     * Almost always, too many signals are issued. A task producer
-     * cannot in general tell if some existing worker is in the midst
-     * of finishing one task (or already scanning) and ready to take
-     * another without being signalled. So the producer might instead
-     * activate a different worker that does not find any work, and
-     * then inactivates. This scarcely matters in steady-state
-     * computations involving all workers, but can create contention
-     * and bookkeeping bottlenecks during ramp-up, ramp-down, and small
-     * computations involving only a few workers.
+     * Almost always, too many signals are issued, in part because a
+     * task producer cannot tell if some existing worker is in the
+     * midst of finishing one task (or already scanning) and ready to
+     * take another without being signalled. So the producer might
+     * instead activate a different worker that does not find any
+     * work, and then inactivates. This scarcely matters in
+     * steady-state computations involving all workers, but can create
+     * contention and bookkeeping bottlenecks during ramp-up,
+     * ramp-down, and small computations involving only a few workers.
      *
-     * Scanning. Method scan() performs top-level scanning for tasks.
-     * Each scan traverses (and tries to poll from) each queue in
-     * pseudorandom permutation order by randomly selecting an origin
-     * index and a step value.  (The pseudorandom generator need not
-     * have high-quality statistical properties in the long term, but
-     * just within computations; We use 64bit and 32bit Marsaglia
-     * XorShifts, which are cheap and suffice here.)  Scanning also
-     * employs contention reduction: When scanning workers fail a CAS
-     * polling for work, they soon restart with a different
-     * pseudorandom scan order (thus likely retrying at different
-     * intervals). This improves throughput when many threads are
-     * trying to take tasks from few queues.  Scans do not otherwise
-     * explicitly take into account core affinities, loads, cache
-     * localities, etc, However, they do exploit temporal locality
-     * (which usually approximates these) by preferring to re-poll (up
-     * to POLL_LIMIT times) from the same queue after a successful
-     * poll before trying others.  Restricted forms of scanning occur
-     * in methods helpComplete and findNonEmptyStealQueue, and take
-     * similar but simpler forms.
-     *
-     * Deactivation and waiting. Queuing encounters several intrinsic
-     * races; most notably that an inactivating scanning worker can
-     * miss seeing a task produced during a scan.  So when a worker
-     * cannot find a task to steal, it inactivates and enqueues, and
-     * then rescans to ensure that it didn't miss one, reactivating
-     * upon seeing one with probability approximately proportional to
-     * probability of a miss.  (In most cases, the worker will be
-     * signalled before self-signalling, avoiding cascades of multiple
-     * signals for the same task).
-     *
-     * Workers block (in method awaitWork) using park/unpark;
-     * advertising the need for signallers to unpark by setting their
-     * "parker" fields.
+     * Scanning. Method scan (from runWorker) performs top-level
+     * scanning for tasks. (Similar scans appear in helpQuiesce and
+     * pollScan.)  Each scan traverses and tries to poll from each
+     * queue starting at a random index. Scans are not performed in
+     * ideal random permutation order, to reduce cacheline
+     * contention. The pseudorandom generator need not have
+     * high-quality statistical properties in the long term, but just
+     * within computations; We use Marsaglia XorShifts (often via
+     * ThreadLocalRandom.nextSecondarySeed), which are cheap and
+     * suffice. Scanning also includes contention reduction: When
+     * scanning workers fail to extract an apparently existing task,
+     * they soon restart at a different pseudorandom index.  This form
+     * of backoff improves throughput when many threads are trying to
+     * take tasks from few queues, which can be common in some usages.
+     * Scans do not otherwise explicitly take into account core
+     * affinities, loads, cache localities, etc, However, they do
+     * exploit temporal locality (which usually approximates these) by
+     * preferring to re-poll from the same queue after a successful
+     * poll before trying others (see method topLevelExec). However
+     * this preference is bounded (see TOP_BOUND_SHIFT) as a safeguard
+     * against infinitely unfair looping under unbounded user task
+     * recursion, and also to reduce long-term contention when many
+     * threads poll few queues holding many small tasks. The bound is
+     * high enough to avoid much impact on locality and scheduling
+     * overhead.
      *
      * 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 (see awaitWork) if the pool has remained
-     * quiescent for period given by IDLE_TIMEOUT_MS, increasing the
-     * period as the number of threads decreases, eventually removing
-     * all workers.
+     * time out and terminate (see method runWorker) if the pool has
+     * remained quiescent for period given by field keepAlive.
      *
      * Shutdown and Termination. A call to shutdownNow invokes
      * tryTerminate to atomically set a runState bit. The calling
      * thread, as well as every other worker thereafter terminating,
-     * helps terminate others by setting their (qlock) status,
-     * cancelling their unprocessed tasks, and waking them up, doing
-     * so repeatedly until stable. Calls to non-abrupt shutdown()
-     * preface this by checking whether termination should commence.
-     * This relies primarily on the active count bits of "ctl"
-     * maintaining consensus -- tryTerminate is called from awaitWork
-     * whenever quiescent. However, external submitters do not take
-     * part in this consensus.  So, tryTerminate sweeps through queues
-     * (until stable) to ensure lack of in-flight submissions and
-     * workers about to process them before triggering the "STOP"
-     * phase of termination. (Note: there is an intrinsic conflict if
-     * helpQuiescePool is called when shutdown is enabled. Both wait
-     * for quiescence, but tryTerminate is biased to not trigger until
-     * helpQuiescePool completes.)
+     * helps terminate others by cancelling their unprocessed tasks,
+     * and waking them up, doing so repeatedly until stable. Calls to
+     * non-abrupt shutdown() preface this by checking whether
+     * termination should commence by sweeping through queues (until
+     * stable) to ensure lack of in-flight submissions and workers
+     * about to process them before triggering the "STOP" phase of
+     * termination.
      *
      * Joining Tasks
      * =============
@@ -509,12 +514,12 @@
      * 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 may need both
-     * an unblocked task and its continuation to progress.  Instead we
-     * combine two tactics:
+     * always 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 may
+     * 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.
@@ -527,79 +532,44 @@
      * 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).
+     * without the need for a compensation thread.
      *
      * The ManagedBlocker extension API can't use helping so relies
      * only on compensation in method awaitBlocker.
      *
-     * The algorithm in helpStealer entails a form of "linear
-     * helping".  Each worker records (in field currentSteal) the most
-     * recent task it stole from some other worker (or a submission).
-     * It also records (in field currentJoin) the task it is currently
-     * actively joining. Method helpStealer 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.  Thus, the joiner executes a task that would be on its
-     * own local deque had the to-be-joined task not been stolen. This
-     * is a conservative variant of the approach described 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 using checksums and fall back to suspending the
-     * worker and if necessary replacing it with another.
+     * The algorithm in awaitJoin entails a form of "linear helping".
+     * Each worker records (in field source) the id of the queue from
+     * which it last stole a task.  The scan in method awaitJoin 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.  Thus, the joiner executes a task that
+     * would be on its own local deque if the to-be-joined task had
+     * not been stolen. This is a conservative variant of the approach
+     * described in Wagner & Calder "Leapfrogging: a portable
+     * technique for implementing efficient futures" SIGPLAN Notices,
+     * 1993 (http://portal.acm.org/citation.cfm?id=155354). It differs
+     * mainly in that we only record queue ids, not full dependency
+     * links.  This requires a linear scan of the workQueues array to
+     * locate stealers, but isolates cost to when it is needed, rather
+     * than adding to per-task overhead. Searches can fail to locate
+     * stealers GC stalls and the like delay recording sources.
+     * Further, even when accurately identified, stealers might not
+     * ever produce a task that the joiner can in turn help with. So,
+     * compensation is tried upon failure to find tasks to run.
      *
-     * Helping actions for CountedCompleters do not require tracking
-     * currentJoins: Method helpComplete takes and executes any task
-     * with the same root as the task being waited on (preferring
-     * local pops to non-local polls). However, this still entails
-     * some traversal of completer chains, so is less efficient than
-     * using CountedCompleters without explicit joins.
-     *
-     * Compensation does not aim to keep exactly the target
+     * Compensation does not by default aim to keep exactly the target
      * parallelism number of unblocked threads running at any given
      * time. Some previous versions of this class employed immediate
      * compensations for any blocked join. However, in practice, the
      * vast majority of blockages are transient byproducts of GC and
-     * other JVM or OS activities that are made worse by replacement.
-     * Currently, compensation is attempted only after validating that
-     * all purportedly active threads are processing tasks by checking
-     * field WorkQueue.scanState, which eliminates most false
-     * positives.  Also, compensation is bypassed (tolerating fewer
-     * threads) in the most common case in which it is rarely
-     * beneficial: when a worker with an empty queue (thus no
-     * continuation tasks) blocks on a join and there still remain
-     * enough threads to ensure liveness.
-     *
-     * Spare threads are removed as soon as they notice that the
-     * target parallelism level has been exceeded, in method
-     * tryDropSpare. (Method scan arranges returns for rechecks upon
-     * each probe via the "bound" parameter.)
-     *
-     * The compensation mechanism may be bounded.  Bounds for the
+     * other JVM or OS activities that are made worse by replacement
+     * when they cause longer-term oversubscription.  Rather than
+     * impose arbitrary policies, we allow users to override the
+     * default of only adding threads upon apparent starvation.  The
+     * compensation mechanism may also be bounded.  Bounds for the
      * commonPool (see COMMON_MAX_SPARES) better enable JVMs to cope
      * with programming errors and abuse before running out of
-     * resources to do so. In other cases, users may supply factories
-     * that limit thread construction. The effects of bounding in this
-     * pool (like all others) is imprecise.  Total worker counts are
-     * decremented when threads deregister, not when they exit and
-     * resources are reclaimed by the JVM and OS. So the number of
-     * simultaneously live threads may transiently exceed bounds.
+     * resources to do so.
      *
      * Common Pool
      * ===========
@@ -607,9 +577,7 @@
      * The static common pool 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
-     * externalSubmit during the first submission to the pool.
+     * footprint to the setup of about a dozen fields.
      *
      * When external threads submit to the common pool, they can
      * perform subtask processing (see externalHelpComplete and
@@ -629,31 +597,39 @@
      * InnocuousForkJoinWorkerThread when there is a SecurityManager
      * present. These workers have no permissions set, do not belong
      * to any user-defined ThreadGroup, and erase all ThreadLocals
-     * after executing any top-level task (see WorkQueue.runTask).
-     * The associated mechanics (mainly in ForkJoinWorkerThread) may
-     * be JVM-dependent and must access particular Thread class fields
-     * to achieve this effect.
+     * after executing any top-level task (see
+     * WorkQueue.afterTopLevelExec).  The associated mechanics (mainly
+     * in ForkJoinWorkerThread) may be JVM-dependent and must access
+     * particular Thread class fields to achieve this effect.
+     *
+     * Memory placement
+     * ================
+     *
+     * Performance can be very sensitive to placement of instances of
+     * ForkJoinPool and WorkQueues and their queue arrays. To reduce
+     * false-sharing impact, the @Contended annotation isolates
+     * adjacent WorkQueue instances, as well as the ForkJoinPool.ctl
+     * field. WorkQueue arrays are allocated (by their threads) with
+     * larger initial sizes than most ever need, mostly to reduce
+     * false sharing with current garbage collectors that use cardmark
+     * tables.
      *
      * Style notes
      * ===========
      *
-     * Memory ordering relies mainly on Unsafe intrinsics that carry
-     * the further responsibility of explicitly performing null- and
-     * bounds- checks otherwise carried out implicitly by JVMs.  This
-     * can be awkward and ugly, but also reflects the need to control
+     * Memory ordering relies mainly on VarHandles.  This can be
+     * awkward and ugly, but also reflects the need to control
      * outcomes across the unusual cases that arise in very racy code
-     * with very few invariants. So these explicit checks would exist
-     * in some form anyway.  All fields are read into locals before
-     * use, and null-checked if they are references.  This is usually
-     * done in a "C"-like style of listing declarations at the heads
-     * of methods or blocks, and using inline assignments on first
-     * encounter.  Array bounds-checks are usually performed by
-     * masking with array.length-1, which relies on the invariant that
-     * these arrays are created with positive lengths, which is itself
-     * paranoically checked. Nearly all explicit checks lead to
-     * bypass/return, not exception throws, because they may
-     * legitimately arise due to cancellation/revocation during
-     * shutdown.
+     * with very few invariants. All fields are read into locals
+     * before use, and null-checked if they are references.  Array
+     * accesses using masked indices include checks (that are always
+     * true) that the array length is non-zero to avoid compilers
+     * inserting more expensive traps.  This is usually done in a
+     * "C"-like style of listing declarations at the heads of methods
+     * or blocks, and using inline assignments on first encounter.
+     * Nearly all explicit checks lead to bypass/return, not exception
+     * throws, because they may legitimately arise due to
+     * cancellation/revocation during shutdown.
      *
      * There is a lot of representation-level coupling among classes
      * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask.  The
@@ -663,10 +639,11 @@
      * representations will need to be accompanied by algorithmic
      * changes anyway. Several methods intrinsically sprawl because
      * they must accumulate sets of consistent reads of fields held in
-     * local variables.  There are also other coding oddities
-     * (including several unnecessary-looking hoisted null checks)
-     * that help some methods perform reasonably even when interpreted
-     * (not compiled).
+     * local variables. Some others are artificially broken up to
+     * reduce producer/consumer imbalances due to dynamic compilation.
+     * There are also other coding oddities (including several
+     * unnecessary-looking hoisted null checks) that help some methods
+     * perform reasonably even when interpreted (not compiled).
      *
      * The order of declarations in this file is (with a few exceptions):
      * (1) Static utility functions
@@ -702,6 +679,13 @@
     public static interface ForkJoinWorkerThreadFactory {
         /**
          * Returns a new worker thread operating in the given pool.
+         * Returning null or throwing an exception may result in tasks
+         * never being executed.  If this method throws an exception,
+         * it is relayed to the caller of the method (for example
+         * {@code execute}) causing attempted thread creation. If this
+         * method returns null or throws an exception, it is not
+         * retried until the next attempted creation (for example
+         * another call to {@code execute}).
          *
          * @param pool the pool this thread works in
          * @return the new worker thread, or {@code null} if the request
@@ -711,120 +695,97 @@
         public ForkJoinWorkerThread newThread(ForkJoinPool pool);
     }
 
+    static AccessControlContext contextWithPermissions(Permission ... perms) {
+        Permissions permissions = new Permissions();
+        for (Permission perm : perms)
+            permissions.add(perm);
+        return new AccessControlContext(
+            new ProtectionDomain[] { new ProtectionDomain(null, permissions) });
+    }
+
     /**
      * Default ForkJoinWorkerThreadFactory implementation; creates a
-     * new ForkJoinWorkerThread.
+     * new ForkJoinWorkerThread using the system class loader as the
+     * thread context class loader.
      */
     private static final class DefaultForkJoinWorkerThreadFactory
         implements ForkJoinWorkerThreadFactory {
+        private static final AccessControlContext ACC = contextWithPermissions(
+            new RuntimePermission("getClassLoader"),
+            new RuntimePermission("setContextClassLoader"));
+
         public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
-            return new ForkJoinWorkerThread(pool);
+            return AccessController.doPrivileged(
+                new PrivilegedAction<>() {
+                    public ForkJoinWorkerThread run() {
+                        return new ForkJoinWorkerThread(
+                            pool, ClassLoader.getSystemClassLoader()); }},
+                ACC);
         }
     }
 
-    /**
-     * 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.
-     */
-    private 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; }
-    }
-
-    /**
-     * Additional fields and lock created upon initialization.
-     */
-    private static final class AuxState extends ReentrantLock {
-        private static final long serialVersionUID = -6001602636862214147L;
-        volatile long stealCount;     // cumulative steal count
-        long indexSeed;               // index bits for registerWorker
-        AuxState() {}
-    }
-
     // Constants shared across ForkJoinPool and WorkQueue
 
     // Bounds
+    static final int SWIDTH       = 16;            // width of short
     static final int SMASK        = 0xffff;        // short bits == max index
     static final int MAX_CAP      = 0x7fff;        // max #workers - 1
-    static final int EVENMASK     = 0xfffe;        // even short bits
     static final int SQMASK       = 0x007e;        // max 64 (even) slots
 
-    // Masks and units for WorkQueue.scanState and ctl sp subfield
+    // Masks and units for WorkQueue.phase and ctl sp subfield
     static final int UNSIGNALLED  = 1 << 31;       // must be negative
     static final int SS_SEQ       = 1 << 16;       // version count
+    static final int QLOCK        = 1;             // must be 1
 
-    // Mode bits for ForkJoinPool.config and WorkQueue.config
-    static final int MODE_MASK    = 0xffff << 16;  // top half of int
-    static final int SPARE_WORKER = 1 << 17;       // set if tc > 0 on creation
-    static final int UNREGISTERED = 1 << 18;       // to skip some of deregister
-    static final int FIFO_QUEUE   = 1 << 31;       // must be negative
-    static final int LIFO_QUEUE   = 0;             // for clarity
-    static final int IS_OWNED     = 1;             // low bit 0 if shared
+    // Mode bits and sentinels, some also used in WorkQueue id and.source fields
+    static final int OWNED        = 1;             // queue has owner thread
+    static final int FIFO         = 1 << 16;       // fifo queue or access mode
+    static final int SHUTDOWN     = 1 << 18;
+    static final int TERMINATED   = 1 << 19;
+    static final int STOP         = 1 << 31;       // must be negative
+    static final int QUIET        = 1 << 30;       // not scanning or working
+    static final int DORMANT      = QUIET | UNSIGNALLED;
 
     /**
-     * The maximum number of task executions from the same queue
-     * before checking other queues, bounding unfairness and impact of
-     * infinite user task recursion.  Must be a power of two minus 1.
+     * Initial capacity of work-stealing queue array.
+     * Must be a power of two, at least 2.
      */
-    static final int POLL_LIMIT = (1 << 10) - 1;
+    static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
+
+    /**
+     * Maximum capacity 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
+
+    /**
+     * The maximum number of top-level polls per worker before
+     * checking other queues, expressed as a bit shift to, in effect,
+     * multiply by pool size, and then use as random value mask, so
+     * average bound is about poolSize*(1<<TOP_BOUND_SHIFT).  See
+     * above for rationale.
+     */
+    static final int TOP_BOUND_SHIFT = 10;
 
     /**
      * Queues supporting work-stealing as well as external task
      * submission. See above for descriptions and algorithms.
-     * 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. The @Contended annotation alerts
-     * JVMs to try to keep instances apart.
      */
-    // Android-removed: @Contended, this hint is not used by the Android runtime.
-    //@jdk.internal.vm.annotation.Contended
+    @jdk.internal.vm.annotation.Contended
     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
-
-        // Instance fields
-
-        volatile int scanState;    // versioned, negative if inactive
-        int stackPred;             // pool stack (ctl) predecessor
-        int nsteals;               // number of steals
-        int hint;                  // randomization and stealer index hint
-        int config;                // pool index and mode
-        volatile int qlock;        // 1: locked, < 0: terminate; else 0
-        volatile int base;         // index of next slot for poll
+        volatile int source;       // source queue id, or sentinel
+        int id;                    // pool index, mode, tag
+        int base;                  // index of next slot for poll
         int top;                   // index of next slot for push
-        ForkJoinTask<?>[] array;   // the elements (initially unallocated)
+        volatile int phase;        // versioned, negative: queued, 1: locked
+        int stackPred;             // pool stack (ctl) predecessor link
+        int nsteals;               // number of steals
+        ForkJoinTask<?>[] array;   // the queued tasks; power of 2 size
         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
-
-      // Android-removed: @Contended, this hint is not used by the Android runtime.
-      // @jdk.internal.vm.annotation.Contended("group2") // segregate
-        volatile ForkJoinTask<?> currentSteal; // nonnull when running some task
 
         WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
             this.pool = pool;
@@ -834,17 +795,28 @@
         }
 
         /**
+         * Tries to lock shared queue by CASing phase field.
+         */
+        final boolean tryLockPhase() {
+            return PHASE.compareAndSet(this, 0, 1);
+        }
+
+        final void releasePhaseLock() {
+            PHASE.setRelease(this, 0);
+        }
+
+        /**
          * Returns an exportable index (used by ForkJoinWorkerThread).
          */
         final int getPoolIndex() {
-            return (config & 0xffff) >>> 1; // ignore odd/even tag bit
+            return (id & 0xffff) >>> 1; // ignore odd/even tag bit
         }
 
         /**
          * Returns the approximate number of tasks in the queue.
          */
         final int queueSize() {
-            int n = base - top;       // read base first
+            int n = (int)BASE.getAcquire(this) - top;
             return (n >= 0) ? 0 : -n; // ignore transient negative
         }
 
@@ -854,11 +826,12 @@
          * near-empty queue has at least one unclaimed task.
          */
         final boolean isEmpty() {
-            ForkJoinTask<?>[] a; int n, al, s;
-            return ((n = base - (s = top)) >= 0 || // possibly one task
+            ForkJoinTask<?>[] a; int n, cap, b;
+            VarHandle.acquireFence(); // needed by external callers
+            return ((n = (b = base) - top) >= 0 || // possibly one task
                     (n == -1 && ((a = array) == null ||
-                                 (al = a.length) == 0 ||
-                                 a[(al - 1) & (s - 1)] == null)));
+                                 (cap = a.length) == 0 ||
+                                 a[(cap - 1) & b] == null)));
         }
 
         /**
@@ -868,116 +841,99 @@
          * @throws RejectedExecutionException if array cannot be resized
          */
         final void push(ForkJoinTask<?> task) {
-            U.storeFence();              // ensure safe publication
-            int s = top, al, d; ForkJoinTask<?>[] a;
-            if ((a = array) != null && (al = a.length) > 0) {
-                a[(al - 1) & s] = task;  // relaxed writes OK
+            ForkJoinTask<?>[] a;
+            int s = top, d, cap, m;
+            ForkJoinPool p = pool;
+            if ((a = array) != null && (cap = a.length) > 0) {
+                QA.setRelease(a, (m = cap - 1) & s, task);
                 top = s + 1;
-                ForkJoinPool p = pool;
-                if ((d = base - s) == 0 && p != null) {
-                    U.fullFence();
+                if (((d = s - (int)BASE.getAcquire(this)) & ~1) == 0 &&
+                    p != null) {                 // size 0 or 1
+                    VarHandle.fullFence();
                     p.signalWork();
                 }
-                else if (al + d == 1)
-                    growArray();
+                else if (d == m)
+                    growArray(false);
             }
         }
 
         /**
-         * 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.
+         * Version of push for shared queues. Call only with phase lock held.
+         * @return true if should signal work
          */
-        final ForkJoinTask<?>[] growArray() {
-            ForkJoinTask<?>[] oldA = array;
-            int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
-            if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY)
+        final boolean lockedPush(ForkJoinTask<?> task) {
+            ForkJoinTask<?>[] a;
+            boolean signal = false;
+            int s = top, b = base, cap, d;
+            if ((a = array) != null && (cap = a.length) > 0) {
+                a[(cap - 1) & s] = task;
+                top = s + 1;
+                if (b - s + cap - 1 == 0)
+                    growArray(true);
+                else {
+                    phase = 0; // full volatile unlock
+                    if (((s - base) & ~1) == 0) // size 0 or 1
+                        signal = true;
+                }
+            }
+            return signal;
+        }
+
+        /**
+         * 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 void growArray(boolean locked) {
+            ForkJoinTask<?>[] newA = null;
+            try {
+                ForkJoinTask<?>[] oldA; int oldSize, newSize;
+                if ((oldA = array) != null && (oldSize = oldA.length) > 0 &&
+                    (newSize = oldSize << 1) <= MAXIMUM_QUEUE_CAPACITY &&
+                    newSize > 0) {
+                    try {
+                        newA = new ForkJoinTask<?>[newSize];
+                    } catch (OutOfMemoryError ex) {
+                    }
+                    if (newA != null) { // poll from old array, push to new
+                        int oldMask = oldSize - 1, newMask = newSize - 1;
+                        for (int s = top - 1, k = oldMask; k >= 0; --k) {
+                            ForkJoinTask<?> x = (ForkJoinTask<?>)
+                                QA.getAndSet(oldA, s & oldMask, null);
+                            if (x != null)
+                                newA[s-- & newMask] = x;
+                            else
+                                break;
+                        }
+                        array = newA;
+                        VarHandle.releaseFence();
+                    }
+                }
+            } finally {
+                if (locked)
+                    phase = 0;
+            }
+            if (newA == null)
                 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 { // emulate poll from old array, push to new array
-                    int index = b & oldMask;
-                    long offset = ((long)index << ASHIFT) + ABASE;
-                    ForkJoinTask<?> x = (ForkJoinTask<?>)
-                        U.getObjectVolatile(oldA, offset);
-                    if (x != null &&
-                        U.compareAndSwapObject(oldA, offset, x, null))
-                        a[b & mask] = x;
-                } while (++b != t);
-                U.storeFence();
-            }
-            return a;
-        }
-
-        /**
-         * Takes next task, if one exists, in LIFO order.  Call only
-         * by owner in unshared queues.
-         */
-        final ForkJoinTask<?> pop() {
-            int b = base, s = top, al, i; ForkJoinTask<?>[] a;
-            if ((a = array) != null && b != s && (al = a.length) > 0) {
-                int index = (al - 1) & --s;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> t = (ForkJoinTask<?>)
-                    U.getObject(a, offset);
-                if (t != null &&
-                    U.compareAndSwapObject(a, offset, 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 helpStealer.
-         */
-        final ForkJoinTask<?> pollAt(int b) {
-            ForkJoinTask<?>[] a; int al;
-            if ((a = array) != null && (al = a.length) > 0) {
-                int index = (al - 1) & b;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> t = (ForkJoinTask<?>)
-                    U.getObjectVolatile(a, offset);
-                if (t != null && b++ == base &&
-                    U.compareAndSwapObject(a, offset, t, null)) {
-                    base = b;
-                    return t;
-                }
-            }
-            return null;
         }
 
         /**
          * Takes next task, if one exists, in FIFO order.
          */
         final ForkJoinTask<?> poll() {
-            for (;;) {
-                int b = base, s = top, d, al; ForkJoinTask<?>[] a;
-                if ((a = array) != null && (d = b - s) < 0 &&
-                    (al = a.length) > 0) {
-                    int index = (al - 1) & b;
-                    long offset = ((long)index << ASHIFT) + ABASE;
-                    ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getObjectVolatile(a, offset);
-                    if (b++ == base) {
-                        if (t != null) {
-                            if (U.compareAndSwapObject(a, offset, t, null)) {
-                                base = b;
-                                return t;
-                            }
-                        }
-                        else if (d == -1)
-                            break; // now empty
+            int b, k, cap; ForkJoinTask<?>[] a;
+            while ((a = array) != null && (cap = a.length) > 0 &&
+                   top - (b = base) > 0) {
+                ForkJoinTask<?> t = (ForkJoinTask<?>)
+                    QA.getAcquire(a, k = (cap - 1) & b);
+                if (base == b++) {
+                    if (t == null)
+                        Thread.yield(); // await index advance
+                    else if (QA.compareAndSet(a, k, t, null)) {
+                        BASE.setOpaque(this, b);
+                        return t;
                     }
                 }
-                else
-                    break;
             }
             return null;
         }
@@ -986,96 +942,59 @@
          * Takes next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> nextLocalTask() {
-            return (config < 0) ? poll() : pop();
+            ForkJoinTask<?> t = null;
+            int md = id, b, s, d, cap; ForkJoinTask<?>[] a;
+            if ((a = array) != null && (cap = a.length) > 0 &&
+                (d = (s = top) - (b = base)) > 0) {
+                if ((md & FIFO) == 0 || d == 1) {
+                    if ((t = (ForkJoinTask<?>)
+                         QA.getAndSet(a, (cap - 1) & --s, null)) != null)
+                        TOP.setOpaque(this, s);
+                }
+                else if ((t = (ForkJoinTask<?>)
+                          QA.getAndSet(a, (cap - 1) & b++, null)) != null) {
+                    BASE.setOpaque(this, b);
+                }
+                else // on contention in FIFO mode, use regular poll
+                    t = poll();
+            }
+            return t;
         }
 
         /**
          * Returns next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> peek() {
-            int al; ForkJoinTask<?>[] a;
-            return ((a = array) != null && (al = a.length) > 0) ?
-                a[(al - 1) & (config < 0 ? base : top - 1)] : null;
+            int cap; ForkJoinTask<?>[] a;
+            return ((a = array) != null && (cap = a.length) > 0) ?
+                a[(cap - 1) & ((id & FIFO) != 0 ? base : top - 1)] : null;
         }
 
         /**
          * Pops the given task only if it is at the current top.
          */
         final boolean tryUnpush(ForkJoinTask<?> task) {
-            int b = base, s = top, al; ForkJoinTask<?>[] a;
-            if ((a = array) != null && b != s && (al = a.length) > 0) {
-                int index = (al - 1) & --s;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                if (U.compareAndSwapObject(a, offset, task, null)) {
-                    top = s;
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Shared version of push. Fails if already locked.
-         *
-         * @return status: > 0 locked, 0 possibly was empty, < 0 was nonempty
-         */
-        final int sharedPush(ForkJoinTask<?> task) {
-            int stat;
-            if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                int b = base, s = top, al, d; ForkJoinTask<?>[] a;
-                if ((a = array) != null && (al = a.length) > 0 &&
-                    al - 1 + (d = b - s) > 0) {
-                    a[(al - 1) & s] = task;
-                    top = s + 1;                 // relaxed writes OK here
-                    qlock = 0;
-                    stat = (d < 0 && b == base) ? d : 0;
-                }
-                else {
-                    growAndSharedPush(task);
-                    stat = 0;
-                }
-            }
-            else
-                stat = 1;
-            return stat;
-        }
-
-        /**
-         * Helper for sharedPush; called only when locked and resize
-         * needed.
-         */
-        private void growAndSharedPush(ForkJoinTask<?> task) {
-            try {
-                growArray();
-                int s = top, al; ForkJoinTask<?>[] a;
-                if ((a = array) != null && (al = a.length) > 0) {
-                    a[(al - 1) & s] = task;
-                    top = s + 1;
-                }
-            } finally {
-                qlock = 0;
-            }
+            boolean popped = false;
+            int s, cap; ForkJoinTask<?>[] a;
+            if ((a = array) != null && (cap = a.length) > 0 &&
+                (s = top) != base &&
+                (popped = QA.compareAndSet(a, (cap - 1) & --s, task, null)))
+                TOP.setOpaque(this, s);
+            return popped;
         }
 
         /**
          * Shared version of tryUnpush.
          */
-        final boolean trySharedUnpush(ForkJoinTask<?> task) {
+        final boolean tryLockedUnpush(ForkJoinTask<?> task) {
             boolean popped = false;
-            int s = top - 1, al; ForkJoinTask<?>[] a;
-            if ((a = array) != null && (al = a.length) > 0) {
-                int index = (al - 1) & s;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> t = (ForkJoinTask<?>) U.getObject(a, offset);
-                if (t == task &&
-                    U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                    if (top == s + 1 && array == a &&
-                        U.compareAndSwapObject(a, offset, task, null)) {
-                        popped = true;
-                        top = s;
-                    }
-                    U.putOrderedInt(this, QLOCK, 0);
-                }
+            int s = top - 1, k, cap; ForkJoinTask<?>[] a;
+            if ((a = array) != null && (cap = a.length) > 0 &&
+                a[k = (cap - 1) & s] == task && tryLockPhase()) {
+                if (top == s + 1 && array == a &&
+                    (popped = QA.compareAndSet(a, k, task, null)))
+                    top = s;
+                releasePhaseLock();
             }
             return popped;
         }
@@ -1084,252 +1003,150 @@
          * Removes and cancels all known tasks, ignoring any exceptions.
          */
         final void cancelAll() {
-            ForkJoinTask<?> t;
-            if ((t = currentJoin) != null) {
-                currentJoin = null;
-                ForkJoinTask.cancelIgnoringExceptions(t);
-            }
-            if ((t = currentSteal) != null) {
-                currentSteal = null;
-                ForkJoinTask.cancelIgnoringExceptions(t);
-            }
-            while ((t = poll()) != null)
+            for (ForkJoinTask<?> t; (t = poll()) != null; )
                 ForkJoinTask.cancelIgnoringExceptions(t);
         }
 
         // Specialized execution methods
 
         /**
-         * Pops and executes up to POLL_LIMIT tasks or until empty.
+         * Runs the given (stolen) task if nonnull, as well as
+         * remaining local tasks and others available from the given
+         * queue, up to bound n (to avoid infinite unfairness).
          */
-        final void localPopAndExec() {
-            for (int nexec = 0;;) {
-                int b = base, s = top, al; ForkJoinTask<?>[] a;
-                if ((a = array) != null && b != s && (al = a.length) > 0) {
-                    int index = (al - 1) & --s;
-                    long offset = ((long)index << ASHIFT) + ABASE;
-                    ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getAndSetObject(a, offset, null);
-                    if (t != null) {
-                        top = s;
-                        (currentSteal = t).doExec();
-                        if (++nexec > POLL_LIMIT)
-                            break;
-                    }
-                    else
+        final void topLevelExec(ForkJoinTask<?> t, WorkQueue q, int n) {
+            if (t != null && q != null) { // hoist checks
+                int nstolen = 1;
+                for (;;) {
+                    t.doExec();
+                    if (n-- < 0)
                         break;
-                }
-                else
-                    break;
-            }
-        }
-
-        /**
-         * Polls and executes up to POLL_LIMIT tasks or until empty.
-         */
-        final void localPollAndExec() {
-            for (int nexec = 0;;) {
-                int b = base, s = top, al; ForkJoinTask<?>[] a;
-                if ((a = array) != null && b != s && (al = a.length) > 0) {
-                    int index = (al - 1) & b++;
-                    long offset = ((long)index << ASHIFT) + ABASE;
-                    ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getAndSetObject(a, offset, null);
-                    if (t != null) {
-                        base = b;
-                        t.doExec();
-                        if (++nexec > POLL_LIMIT)
+                    else if ((t = nextLocalTask()) == null) {
+                        if ((t = q.poll()) == null)
                             break;
+                        else
+                            ++nstolen;
                     }
                 }
-                else
-                    break;
-            }
-        }
-
-        /**
-         * Executes the given task and (some) remaining local tasks.
-         */
-        final void runTask(ForkJoinTask<?> task) {
-            if (task != null) {
-                task.doExec();
-                if (config < 0)
-                    localPollAndExec();
-                else
-                    localPopAndExec();
-                int ns = ++nsteals;
                 ForkJoinWorkerThread thread = owner;
-                currentSteal = null;
-                if (ns < 0)           // collect on overflow
-                    transferStealCount(pool);
+                nsteals += nstolen;
+                source = 0;
                 if (thread != null)
                     thread.afterTopLevelExec();
             }
         }
 
         /**
-         * Adds steal count to pool steal count if it exists, and resets.
+         * If present, removes task from queue and executes it.
          */
-        final void transferStealCount(ForkJoinPool p) {
-            AuxState aux;
-            if (p != null && (aux = p.auxState) != null) {
-                long s = nsteals;
-                nsteals = 0;            // if negative, correct for overflow
-                if (s < 0) s = Integer.MAX_VALUE;
-                aux.lock();
-                try {
-                    aux.stealCount += s;
-                } finally {
-                    aux.unlock();
-                }
-            }
-        }
-
-        /**
-         * If present, removes from queue and executes the given task,
-         * or any other cancelled task. Used only by awaitJoin.
-         *
-         * @return true if queue empty and task not known to be done
-         */
-        final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
-            if (task != null && task.status >= 0) {
-                int b, s, d, al; ForkJoinTask<?>[] a;
-                while ((d = (b = base) - (s = top)) < 0 &&
-                       (a = array) != null && (al = a.length) > 0) {
-                    for (;;) {      // traverse from s to b
-                        int index = --s & (al - 1);
-                        long offset = (index << ASHIFT) + ABASE;
-                        ForkJoinTask<?> t = (ForkJoinTask<?>)
-                            U.getObjectVolatile(a, offset);
-                        if (t == null)
-                            break;                   // restart
-                        else if (t == task) {
-                            boolean removed = false;
-                            if (s + 1 == top) {      // pop
-                                if (U.compareAndSwapObject(a, offset, t, null)) {
-                                    top = s;
-                                    removed = true;
-                                }
+        final void tryRemoveAndExec(ForkJoinTask<?> task) {
+            ForkJoinTask<?>[] a; int s, cap;
+            if ((a = array) != null && (cap = a.length) > 0 &&
+                (s = top) - base > 0) { // traverse from top
+                for (int m = cap - 1, ns = s - 1, i = ns; ; --i) {
+                    int index = i & m;
+                    ForkJoinTask<?> t = (ForkJoinTask<?>)QA.get(a, index);
+                    if (t == null)
+                        break;
+                    else if (t == task) {
+                        if (QA.compareAndSet(a, index, t, null)) {
+                            top = ns;   // safely shift down
+                            for (int j = i; j != ns; ++j) {
+                                ForkJoinTask<?> f;
+                                int pindex = (j + 1) & m;
+                                f = (ForkJoinTask<?>)QA.get(a, pindex);
+                                QA.setVolatile(a, pindex, null);
+                                int jindex = j & m;
+                                QA.setRelease(a, jindex, f);
                             }
-                            else if (base == b)      // replace with proxy
-                                removed = U.compareAndSwapObject(a, offset, t,
-                                                                 new EmptyTask());
-                            if (removed) {
-                                ForkJoinTask<?> ps = currentSteal;
-                                (currentSteal = task).doExec();
-                                currentSteal = ps;
-                            }
-                            break;
+                            VarHandle.releaseFence();
+                            t.doExec();
                         }
-                        else if (t.status < 0 && s + 1 == top) {
-                            if (U.compareAndSwapObject(a, offset, t, null)) {
-                                top = s;
-                            }
-                            break;                  // was cancelled
-                        }
-                        else if (++d == 0) {
-                            if (base != b)          // rescan
-                                break;
-                            return false;
-                        }
+                        break;
                     }
-                    if (task.status < 0)
-                        return false;
                 }
             }
-            return true;
         }
 
         /**
-         * Pops task if in the same CC computation as the given task,
-         * in either shared or owned mode. Used only by helpComplete.
+         * Tries to pop and run tasks within the target's computation
+         * until done, not found, or limit exceeded.
+         *
+         * @param task root of CountedCompleter computation
+         * @param limit max runs, or zero for no limit
+         * @param shared true if must lock to extract task
+         * @return task status on exit
          */
-        final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) {
-            int b = base, s = top, al; ForkJoinTask<?>[] a;
-            if ((a = array) != null && b != s && (al = a.length) > 0) {
-                int index = (al - 1) & (s - 1);
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> o = (ForkJoinTask<?>)
-                    U.getObjectVolatile(a, offset);
-                if (o instanceof CountedCompleter) {
-                    CountedCompleter<?> t = (CountedCompleter<?>)o;
-                    for (CountedCompleter<?> r = t;;) {
-                        if (r == task) {
-                            if ((mode & IS_OWNED) == 0) {
-                                boolean popped = false;
-                                if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+        final int helpCC(CountedCompleter<?> task, int limit, boolean shared) {
+            int status = 0;
+            if (task != null && (status = task.status) >= 0) {
+                int s, k, cap; ForkJoinTask<?>[] a;
+                while ((a = array) != null && (cap = a.length) > 0 &&
+                       (s = top) - base > 0) {
+                    CountedCompleter<?> v = null;
+                    ForkJoinTask<?> o = a[k = (cap - 1) & (s - 1)];
+                    if (o instanceof CountedCompleter) {
+                        CountedCompleter<?> t = (CountedCompleter<?>)o;
+                        for (CountedCompleter<?> f = t;;) {
+                            if (f != task) {
+                                if ((f = f.completer) == null)
+                                    break;
+                            }
+                            else if (shared) {
+                                if (tryLockPhase()) {
                                     if (top == s && array == a &&
-                                        U.compareAndSwapObject(a, offset,
-                                                               t, null)) {
-                                        popped = true;
+                                        QA.compareAndSet(a, k, t, null)) {
                                         top = s - 1;
+                                        v = t;
                                     }
-                                    U.putOrderedInt(this, QLOCK, 0);
-                                    if (popped)
-                                        return t;
+                                    releasePhaseLock();
                                 }
+                                break;
                             }
-                            else if (U.compareAndSwapObject(a, offset,
-                                                            t, null)) {
-                                top = s - 1;
-                                return t;
+                            else {
+                                if (QA.compareAndSet(a, k, t, null)) {
+                                    top = s - 1;
+                                    v = t;
+                                }
+                                break;
                             }
-                            break;
                         }
-                        else if ((r = r.completer) == null) // try parent
-                            break;
                     }
+                    if (v != null)
+                        v.doExec();
+                    if ((status = task.status) < 0 || v == null ||
+                        (limit != 0 && --limit == 0))
+                        break;
                 }
             }
-            return null;
+            return status;
         }
 
         /**
-         * Steals and runs a task in the same CC computation as the
-         * given task if one exists and can be taken without
-         * contention. Otherwise returns a checksum/control value for
-         * use by method helpComplete.
+         * Tries to poll and run AsynchronousCompletionTasks until
+         * none found or blocker is released
          *
-         * @return 1 if successful, 2 if retryable (lost to another
-         * stealer), -1 if non-empty but no matching task found, else
-         * the base index, forced negative.
+         * @param blocker the blocker
          */
-        final int pollAndExecCC(CountedCompleter<?> task) {
-            ForkJoinTask<?>[] a;
-            int b = base, s = top, al, h;
-            if ((a = array) != null && b != s && (al = a.length) > 0) {
-                int index = (al - 1) & b;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> o = (ForkJoinTask<?>)
-                    U.getObjectVolatile(a, offset);
-                if (o == null)
-                    h = 2;                      // retryable
-                else if (!(o instanceof CountedCompleter))
-                    h = -1;                     // unmatchable
-                else {
-                    CountedCompleter<?> t = (CountedCompleter<?>)o;
-                    for (CountedCompleter<?> r = t;;) {
-                        if (r == task) {
-                            if (b++ == base &&
-                                U.compareAndSwapObject(a, offset, t, null)) {
-                                base = b;
-                                t.doExec();
-                                h = 1;          // success
-                            }
-                            else
-                                h = 2;          // lost CAS
+        final void helpAsyncBlocker(ManagedBlocker blocker) {
+            if (blocker != null) {
+                int b, k, cap; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
+                while ((a = array) != null && (cap = a.length) > 0 &&
+                       top - (b = base) > 0) {
+                    t = (ForkJoinTask<?>)QA.getAcquire(a, k = (cap - 1) & b);
+                    if (blocker.isReleasable())
+                        break;
+                    else if (base == b++ && t != null) {
+                        if (!(t instanceof CompletableFuture.
+                              AsynchronousCompletionTask))
                             break;
-                        }
-                        else if ((r = r.completer) == null) {
-                            h = -1;             // unmatched
-                            break;
+                        else if (QA.compareAndSet(a, k, t, null)) {
+                            BASE.setOpaque(this, b);
+                            t.doExec();
                         }
                     }
                 }
             }
-            else
-                h = b | Integer.MIN_VALUE;      // to sense movement on re-poll
-            return h;
         }
 
         /**
@@ -1337,29 +1154,24 @@
          */
         final boolean isApparentlyUnblocked() {
             Thread wt; Thread.State s;
-            return (scanState >= 0 &&
-                    (wt = owner) != null &&
+            return ((wt = owner) != null &&
                     (s = wt.getState()) != Thread.State.BLOCKED &&
                     s != Thread.State.WAITING &&
                     s != Thread.State.TIMED_WAITING);
         }
 
-        // Unsafe mechanics. Note that some are (and must be) the same as in FJP
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long QLOCK;
-        private static final int ABASE;
-        private static final int ASHIFT;
+        // VarHandle mechanics.
+        static final VarHandle PHASE;
+        static final VarHandle BASE;
+        static final VarHandle TOP;
         static {
             try {
-                QLOCK = U.objectFieldOffset
-                    (WorkQueue.class.getDeclaredField("qlock"));
-                ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
-                int scale = U.arrayIndexScale(ForkJoinTask[].class);
-                if ((scale & (scale - 1)) != 0)
-                    throw new Error("array index scale not a power of two");
-                ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                PHASE = l.findVarHandle(WorkQueue.class, "phase", int.class);
+                BASE = l.findVarHandle(WorkQueue.class, "base", int.class);
+                TOP = l.findVarHandle(WorkQueue.class, "top", int.class);
             } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                throw new ExceptionInInitializerError(e);
             }
         }
     }
@@ -1375,7 +1187,7 @@
 
     /**
      * Permission required for callers of methods that may start or
-     * kill threads.  Also used as a static lock in tryInitialize.
+     * kill threads.
      */
     static final RuntimePermission modifyThreadPermission;
 
@@ -1416,18 +1228,15 @@
     // static configuration constants
 
     /**
-     * Initial timeout value (in milliseconds) 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).
+     * Default idle timeout value (in milliseconds) for the thread
+     * triggering quiescence to park waiting for new work
      */
-    private static final long IDLE_TIMEOUT_MS = 2000L; // 2sec
+    private static final long DEFAULT_KEEPALIVE = 60_000L;
 
     /**
-     * Tolerance for idle timeouts, to cope with timer undershoots.
+     * Undershoot tolerance for idle timeouts
      */
-    private static final long TIMEOUT_SLOP_MS =   20L; // 20ms
+    private static final long TIMEOUT_SLOP = 20L;
 
     /**
      * The default value for COMMON_MAX_SPARES.  Overridable using the
@@ -1447,7 +1256,7 @@
 
     /*
      * Bits and masks for field ctl, packed with 4 16 bit subfields:
-     * AC: Number of active running workers minus target parallelism
+     * RC: Number of released (unqueued) workers minus target parallelism
      * TC: Number of total workers minus target parallelism
      * SS: version count and status of top waiting thread
      * ID: poolIndex of top of Treiber stack of waiters
@@ -1456,26 +1265,30 @@
      * (including version bits) as sp=(int)ctl.  The offsets of counts
      * by the target 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
+     * fields: When ac is negative, there are not enough unqueued
      * workers, when tc is negative, there are not enough total
      * workers.  When sp is non-zero, there are waiting workers.  To
      * deal with possibly negative fields, we use casts in and out of
      * "short" and/or signed shifts to maintain signedness.
      *
-     * Because it occupies uppermost bits, we can add one active count
-     * using getAndAddLong of AC_UNIT, rather than CAS, when returning
+     * Because it occupies uppermost bits, we can add one release count
+     * using getAndAddLong of RC_UNIT, rather than CAS, when returning
      * from a blocked join.  Other updates entail multiple subfields
      * and masking, requiring CAS.
+     *
+     * The limits packed in field "bounds" are also offset by the
+     * parallelism level to make them comparable to the ctl rc and tc
+     * fields.
      */
 
     // Lower and upper word masks
     private static final long SP_MASK    = 0xffffffffL;
     private static final long UC_MASK    = ~SP_MASK;
 
-    // Active counts
-    private static final int  AC_SHIFT   = 48;
-    private static final long AC_UNIT    = 0x0001L << AC_SHIFT;
-    private static final long AC_MASK    = 0xffffL << AC_SHIFT;
+    // Release counts
+    private static final int  RC_SHIFT   = 48;
+    private static final long RC_UNIT    = 0x0001L << RC_SHIFT;
+    private static final long RC_MASK    = 0xffffL << RC_SHIFT;
 
     // Total counts
     private static final int  TC_SHIFT   = 32;
@@ -1483,52 +1296,21 @@
     private static final long TC_MASK    = 0xffffL << TC_SHIFT;
     private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign
 
-    // runState bits: SHUTDOWN must be negative, others arbitrary powers of two
-    private static final int  STARTED    = 1;
-    private static final int  STOP       = 1 << 1;
-    private static final int  TERMINATED = 1 << 2;
-    private static final int  SHUTDOWN   = 1 << 31;
-
     // Instance fields
-    volatile long ctl;                   // main pool control
-    volatile int runState;
-    final int config;                    // parallelism, mode
-    AuxState auxState;                   // lock, steal counts
-    volatile WorkQueue[] workQueues;     // main registry
-    final String workerNamePrefix;       // to create worker name string
+
+    volatile long stealCount;            // collects worker nsteals
+    final long keepAlive;                // milliseconds before dropping if idle
+    int indexSeed;                       // next worker index
+    final int bounds;                    // min, max threads packed as shorts
+    volatile int mode;                   // parallelism, runstate, queue mode
+    WorkQueue[] workQueues;              // main registry
+    final String workerNamePrefix;       // for worker thread string; sync lock
     final ForkJoinWorkerThreadFactory factory;
     final UncaughtExceptionHandler ueh;  // per-worker UEH
+    final Predicate<? super ForkJoinPool> saturate;
 
-    /**
-     * Instantiates fields upon first submission, or upon shutdown if
-     * no submissions. If checkTermination true, also responds to
-     * termination by external calls submitting tasks.
-     */
-    private void tryInitialize(boolean checkTermination) {
-        if (runState == 0) { // bootstrap by locking static field
-            int p = config & SMASK;
-            int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots
-            n |= n >>> 1;    // create workQueues array with size a power of two
-            n |= n >>> 2;
-            n |= n >>> 4;
-            n |= n >>> 8;
-            n |= n >>> 16;
-            n = ((n + 1) << 1) & SMASK;
-            AuxState aux = new AuxState();
-            WorkQueue[] ws = new WorkQueue[n];
-            synchronized (modifyThreadPermission) { // double-check
-                if (runState == 0) {
-                    workQueues = ws;
-                    auxState = aux;
-                    runState = STARTED;
-                }
-            }
-        }
-        if (checkTermination && runState < 0) {
-            tryTerminate(false, false); // help terminate
-            throw new RejectedExecutionException();
-        }
-    }
+    @jdk.internal.vm.annotation.Contended("fjpctl") // segregate
+    volatile long ctl;                   // main pool control
 
     // Creating, registering and deregistering workers
 
@@ -1537,18 +1319,14 @@
      * count has already been incremented as a reservation.  Invokes
      * deregisterWorker on any failure.
      *
-     * @param isSpare true if this is a spare thread
      * @return true if successful
      */
-    private boolean createWorker(boolean isSpare) {
+    private boolean createWorker() {
         ForkJoinWorkerThreadFactory fac = factory;
         Throwable ex = null;
         ForkJoinWorkerThread wt = null;
-        WorkQueue q;
         try {
             if (fac != null && (wt = fac.newThread(this)) != null) {
-                if (isSpare && (q = wt.workQueue) != null)
-                    q.config |= SPARE_WORKER;
                 wt.start();
                 return true;
             }
@@ -1569,10 +1347,10 @@
      */
     private void tryAddWorker(long c) {
         do {
-            long nc = ((AC_MASK & (c + AC_UNIT)) |
+            long nc = ((RC_MASK & (c + RC_UNIT)) |
                        (TC_MASK & (c + TC_UNIT)));
-            if (ctl == c && U.compareAndSwapLong(this, CTL, c, nc)) {
-                createWorker(false);
+            if (ctl == c && CTL.compareAndSet(this, c, nc)) {
+                createWorker();
                 break;
             }
         } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
@@ -1587,41 +1365,55 @@
      */
     final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
         UncaughtExceptionHandler handler;
-        AuxState aux;
-        wt.setDaemon(true);                           // configure thread
+        wt.setDaemon(true);                             // configure thread
         if ((handler = ueh) != null)
             wt.setUncaughtExceptionHandler(handler);
+        int tid = 0;                                    // for thread name
+        int idbits = mode & FIFO;
+        String prefix = workerNamePrefix;
         WorkQueue w = new WorkQueue(this, wt);
-        int i = 0;                                    // assign a pool index
-        int mode = config & MODE_MASK;
-        if ((aux = auxState) != null) {
-            aux.lock();
-            try {
-                int s = (int)(aux.indexSeed += SEED_INCREMENT), n, m;
-                WorkQueue[] ws = workQueues;
-                if (ws != null && (n = ws.length) > 0) {
-                    i = (m = n - 1) & ((s << 1) | 1); // odd-numbered indices
-                    if (ws[i] != null) {              // collision
-                        int probes = 0;               // step by approx half n
-                        int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
-                        while (ws[i = (i + step) & m] != null) {
-                            if (++probes >= n) {
-                                workQueues = ws = Arrays.copyOf(ws, n <<= 1);
-                                m = n - 1;
-                                probes = 0;
-                            }
+        if (prefix != null) {
+            synchronized (prefix) {
+                WorkQueue[] ws = workQueues; int n;
+                int s = indexSeed += SEED_INCREMENT;
+                idbits |= (s & ~(SMASK | FIFO | DORMANT));
+                if (ws != null && (n = ws.length) > 1) {
+                    int m = n - 1;
+                    tid = m & ((s << 1) | 1);           // odd-numbered indices
+                    for (int probes = n >>> 1;;) {      // find empty slot
+                        WorkQueue q;
+                        if ((q = ws[tid]) == null || q.phase == QUIET)
+                            break;
+                        else if (--probes == 0) {
+                            tid = n | 1;                // resize below
+                            break;
                         }
+                        else
+                            tid = (tid + 2) & m;
                     }
-                    w.hint = s;                       // use as random seed
-                    w.config = i | mode;
-                    w.scanState = i | (s & 0x7fff0000); // random seq bits
-                    ws[i] = w;
+                    w.phase = w.id = tid | idbits;      // now publishable
+
+                    if (tid < n)
+                        ws[tid] = w;
+                    else {                              // expand array
+                        int an = n << 1;
+                        WorkQueue[] as = new WorkQueue[an];
+                        as[tid] = w;
+                        int am = an - 1;
+                        for (int j = 0; j < n; ++j) {
+                            WorkQueue v;                // copy external queue
+                            if ((v = ws[j]) != null)    // position may change
+                                as[v.id & am & SQMASK] = v;
+                            if (++j >= n)
+                                break;
+                            as[j] = ws[j];              // copy worker
+                        }
+                        workQueues = as;
+                    }
                 }
-            } finally {
-                aux.unlock();
             }
+            wt.setName(prefix.concat(Integer.toString(tid)));
         }
-        wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
         return w;
     }
 
@@ -1636,64 +1428,48 @@
      */
     final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
         WorkQueue w = null;
+        int phase = 0;
         if (wt != null && (w = wt.workQueue) != null) {
-            AuxState aux; WorkQueue[] ws;          // remove index from array
-            int idx = w.config & SMASK;
-            int ns = w.nsteals;
-            if ((aux = auxState) != null) {
-                aux.lock();
-                try {
-                    if ((ws = workQueues) != null && ws.length > idx &&
-                        ws[idx] == w)
-                        ws[idx] = null;
-                    aux.stealCount += ns;
-                } finally {
-                    aux.unlock();
+            Object lock = workerNamePrefix;
+            int wid = w.id;
+            long ns = (long)w.nsteals & 0xffffffffL;
+            if (lock != null) {
+                synchronized (lock) {
+                    WorkQueue[] ws; int n, i;         // remove index from array
+                    if ((ws = workQueues) != null && (n = ws.length) > 0 &&
+                        ws[i = wid & (n - 1)] == w)
+                        ws[i] = null;
+                    stealCount += ns;
                 }
             }
+            phase = w.phase;
         }
-        if (w == null || (w.config & UNREGISTERED) == 0) { // else pre-adjusted
+        if (phase != QUIET) {                         // else pre-adjusted
             long c;                                   // decrement counts
-            do {} while (!U.compareAndSwapLong
-                         (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
-                                               (TC_MASK & (c - TC_UNIT)) |
-                                               (SP_MASK & c))));
+            do {} while (!CTL.weakCompareAndSet
+                         (this, c = ctl, ((RC_MASK & (c - RC_UNIT)) |
+                                          (TC_MASK & (c - TC_UNIT)) |
+                                          (SP_MASK & c))));
         }
-        if (w != null) {
-            w.currentSteal = null;
-            w.qlock = -1;                             // ensure set
+        if (w != null)
             w.cancelAll();                            // cancel remaining tasks
-        }
-        while (tryTerminate(false, false) >= 0) {     // possibly replace
-            WorkQueue[] ws; int wl, sp; long c;
-            if (w == null || w.array == null ||
-                (ws = workQueues) == null || (wl = ws.length) <= 0)
-                break;
-            else if ((sp = (int)(c = ctl)) != 0) {    // wake up replacement
-                if (tryRelease(c, ws[(wl - 1) & sp], AC_UNIT))
-                    break;
-            }
-            else if (ex != null && (c & ADD_WORKER) != 0L) {
-                tryAddWorker(c);                      // create replacement
-                break;
-            }
-            else                                      // don't need replacement
-                break;
-        }
+
+        if (!tryTerminate(false, false) &&            // possibly replace worker
+            w != null && w.array != null)             // avoid repeated failures
+            signalWork();
+
         if (ex == null)                               // help clean on way out
             ForkJoinTask.helpExpungeStaleExceptions();
         else                                          // rethrow
             ForkJoinTask.rethrow(ex);
     }
 
-    // Signalling
-
     /**
-     * Tries to create or activate a worker if too few are active.
+     * Tries to create or release a worker if too few are running.
      */
     final void signalWork() {
         for (;;) {
-            long c; int sp, i; WorkQueue v; WorkQueue[] ws;
+            long c; int sp; WorkQueue[] ws; int i; WorkQueue v;
             if ((c = ctl) >= 0L)                      // enough workers
                 break;
             else if ((sp = (int)c) == 0) {            // no idle workers
@@ -1708,12 +1484,14 @@
             else if ((v = ws[i]) == null)
                 break;                                // terminating
             else {
-                int ns = sp & ~UNSIGNALLED;
-                int vs = v.scanState;
-                long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
-                if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
-                    v.scanState = ns;
-                    LockSupport.unpark(v.parker);
+                int np = sp & ~UNSIGNALLED;
+                int vp = v.phase;
+                long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + RC_UNIT));
+                Thread vt = v.owner;
+                if (sp == vp && CTL.compareAndSet(this, c, nc)) {
+                    v.phase = np;
+                    if (vt != null && v.source < 0)
+                        LockSupport.unpark(vt);
                     break;
                 }
             }
@@ -1721,502 +1499,181 @@
     }
 
     /**
-     * Signals and releases worker v if it is top of idle worker
-     * stack.  This performs a one-shot version of signalWork only if
-     * there is (apparently) at least one idle worker.
+     * Tries to decrement counts (sometimes implicitly) and possibly
+     * arrange for a compensating worker in preparation for blocking:
+     * If not all core workers yet exist, creates one, else if any are
+     * unreleased (possibly including caller) releases one, else if
+     * fewer than the minimum allowed number of workers running,
+     * checks to see that they are all active, and if so creates an
+     * extra worker unless over maximum limit and policy is to
+     * saturate.  Most of these steps can fail due to interference, in
+     * which case 0 is returned so caller will retry. A negative
+     * return value indicates that the caller doesn't need to
+     * re-adjust counts when later unblocked.
      *
-     * @param c incoming ctl value
-     * @param v if non-null, a worker
-     * @param inc the increment to active count (zero when compensating)
-     * @return true if successful
+     * @return 1: block then adjust, -1: block without adjust, 0 : retry
      */
-    private boolean tryRelease(long c, WorkQueue v, long inc) {
-        int sp = (int)c, ns = sp & ~UNSIGNALLED;
-        if (v != null) {
-            int vs = v.scanState;
-            long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + inc));
-            if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.scanState = ns;
-                LockSupport.unpark(v.parker);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * With approx probability of a missed signal, tries (once) to
-     * reactivate worker w (or some other worker), failing if stale or
-     * known to be already active.
-     *
-     * @param w the worker
-     * @param ws the workQueue array to use
-     * @param r random seed
-     */
-    private void tryReactivate(WorkQueue w, WorkQueue[] ws, int r) {
-        long c; int sp, wl; WorkQueue v;
-        if ((sp = (int)(c = ctl)) != 0 && w != null &&
-            ws != null && (wl = ws.length) > 0 &&
-            ((sp ^ r) & SS_SEQ) == 0 &&
-            (v = ws[(wl - 1) & sp]) != null) {
-            long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
-            int ns = sp & ~UNSIGNALLED;
-            if (w.scanState < 0 &&
-                v.scanState == sp &&
-                U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.scanState = ns;
-                LockSupport.unpark(v.parker);
-            }
-        }
-    }
-
-    /**
-     * If worker w exists and is active, enqueues and sets status to inactive.
-     *
-     * @param w the worker
-     * @param ss current (non-negative) scanState
-     */
-    private void inactivate(WorkQueue w, int ss) {
-        int ns = (ss + SS_SEQ) | UNSIGNALLED;
-        long lc = ns & SP_MASK, nc, c;
-        if (w != null) {
-            w.scanState = ns;
-            do {
-                nc = lc | (UC_MASK & ((c = ctl) - AC_UNIT));
-                w.stackPred = (int)c;
-            } while (!U.compareAndSwapLong(this, CTL, c, nc));
-        }
-    }
-
-    /**
-     * Possibly blocks worker w waiting for signal, or returns
-     * negative status if the worker should terminate. May return
-     * without status change if multiple stale unparks and/or
-     * interrupts occur.
-     *
-     * @param w the calling worker
-     * @return negative if w should terminate
-     */
-    private int awaitWork(WorkQueue w) {
-        int stat = 0;
-        if (w != null && w.scanState < 0) {
-            long c = ctl;
-            if ((int)(c >> AC_SHIFT) + (config & SMASK) <= 0)
-                stat = timedAwaitWork(w, c);     // possibly quiescent
-            else if ((runState & STOP) != 0)
-                stat = w.qlock = -1;             // pool terminating
-            else if (w.scanState < 0) {
-                w.parker = Thread.currentThread();
-                if (w.scanState < 0)             // recheck after write
-                    LockSupport.park(this);
-                w.parker = null;
-                if ((runState & STOP) != 0)
-                    stat = w.qlock = -1;         // recheck
-                else if (w.scanState < 0)
-                    Thread.interrupted();        // clear status
-            }
-        }
-        return stat;
-    }
-
-    /**
-     * Possibly triggers shutdown and tries (once) to block worker
-     * when pool is (or may be) quiescent. Waits up to a duration
-     * determined by number of workers.  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
-     * @return negative if w should terminate
-     */
-    private int timedAwaitWork(WorkQueue w, long c) {
-        int stat = 0;
-        int scale = 1 - (short)(c >>> TC_SHIFT);
-        long deadline = (((scale <= 0) ? 1 : scale) * IDLE_TIMEOUT_MS +
-                         System.currentTimeMillis());
-        if ((runState >= 0 || (stat = tryTerminate(false, false)) > 0) &&
-            w != null && w.scanState < 0) {
-            int ss; AuxState aux;
-            w.parker = Thread.currentThread();
-            if (w.scanState < 0)
-                LockSupport.parkUntil(this, deadline);
-            w.parker = null;
-            if ((runState & STOP) != 0)
-                stat = w.qlock = -1;         // pool terminating
-            else if ((ss = w.scanState) < 0 && !Thread.interrupted() &&
-                     (int)c == ss && (aux = auxState) != null && ctl == c &&
-                     deadline - System.currentTimeMillis() <= TIMEOUT_SLOP_MS) {
-                aux.lock();
-                try {                        // pre-deregister
-                    WorkQueue[] ws;
-                    int cfg = w.config, idx = cfg & SMASK;
-                    long nc = ((UC_MASK & (c - TC_UNIT)) |
-                               (SP_MASK & w.stackPred));
-                    if ((runState & STOP) == 0 &&
-                        (ws = workQueues) != null &&
-                        idx < ws.length && idx >= 0 && ws[idx] == w &&
-                        U.compareAndSwapLong(this, CTL, c, nc)) {
-                        ws[idx] = null;
-                        w.config = cfg | UNREGISTERED;
-                        stat = w.qlock = -1;
+    private int tryCompensate(WorkQueue w) {
+        int t, n, sp;
+        long c = ctl;
+        WorkQueue[] ws = workQueues;
+        if ((t = (short)(c >>> TC_SHIFT)) >= 0) {
+            if (ws == null || (n = ws.length) <= 0 || w == null)
+                return 0;                        // disabled
+            else if ((sp = (int)c) != 0) {       // replace or release
+                WorkQueue v = ws[sp & (n - 1)];
+                int wp = w.phase;
+                long uc = UC_MASK & ((wp < 0) ? c + RC_UNIT : c);
+                int np = sp & ~UNSIGNALLED;
+                if (v != null) {
+                    int vp = v.phase;
+                    Thread vt = v.owner;
+                    long nc = ((long)v.stackPred & SP_MASK) | uc;
+                    if (vp == sp && CTL.compareAndSet(this, c, nc)) {
+                        v.phase = np;
+                        if (vt != null && v.source < 0)
+                            LockSupport.unpark(vt);
+                        return (wp < 0) ? -1 : 1;
                     }
-                } finally {
-                    aux.unlock();
                 }
+                return 0;
             }
-        }
-        return stat;
-    }
-
-    /**
-     * If the given worker is a spare with no queued tasks, and there
-     * are enough existing workers, drops it from ctl counts and sets
-     * its state to terminated.
-     *
-     * @param w the calling worker -- must be a spare
-     * @return true if dropped (in which case it must not process more tasks)
-     */
-    private boolean tryDropSpare(WorkQueue w) {
-        if (w != null && w.isEmpty()) {           // no local tasks
-            long c; int sp, wl; WorkQueue[] ws; WorkQueue v;
-            while ((short)((c = ctl) >> TC_SHIFT) > 0 &&
-                   ((sp = (int)c) != 0 || (int)(c >> AC_SHIFT) > 0) &&
-                   (ws = workQueues) != null && (wl = ws.length) > 0) {
-                boolean dropped, canDrop;
-                if (sp == 0) {                    // no queued workers
-                    long nc = ((AC_MASK & (c - AC_UNIT)) |
-                               (TC_MASK & (c - TC_UNIT)) | (SP_MASK & c));
-                    dropped = U.compareAndSwapLong(this, CTL, c, nc);
+            else if ((int)(c >> RC_SHIFT) -      // reduce parallelism
+                     (short)(bounds & SMASK) > 0) {
+                long nc = ((RC_MASK & (c - RC_UNIT)) | (~RC_MASK & c));
+                return CTL.compareAndSet(this, c, nc) ? 1 : 0;
+            }
+            else {                               // validate
+                int md = mode, pc = md & SMASK, tc = pc + t, bc = 0;
+                boolean unstable = false;
+                for (int i = 1; i < n; i += 2) {
+                    WorkQueue q; Thread wt; Thread.State ts;
+                    if ((q = ws[i]) != null) {
+                        if (q.source == 0) {
+                            unstable = true;
+                            break;
+                        }
+                        else {
+                            --tc;
+                            if ((wt = q.owner) != null &&
+                                ((ts = wt.getState()) == Thread.State.BLOCKED ||
+                                 ts == Thread.State.WAITING))
+                                ++bc;            // worker is blocking
+                        }
+                    }
                 }
-                else if (
-                    (v = ws[(wl - 1) & sp]) == null || v.scanState != sp)
-                    dropped = false;              // stale; retry
-                else {
-                    long nc = v.stackPred & SP_MASK;
-                    if (w == v || w.scanState >= 0) {
-                        canDrop = true;           // w unqueued or topmost
-                        nc |= ((AC_MASK & c) |    // ensure replacement
-                               (TC_MASK & (c - TC_UNIT)));
-                    }
-                    else {                        // w may be queued
-                        canDrop = false;          // help uncover
-                        nc |= ((AC_MASK & (c + AC_UNIT)) |
-                               (TC_MASK & c));
-                    }
-                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                        v.scanState = sp & ~UNSIGNALLED;
-                        LockSupport.unpark(v.parker);
-                        dropped = canDrop;
+                if (unstable || tc != 0 || ctl != c)
+                    return 0;                    // inconsistent
+                else if (t + pc >= MAX_CAP || t >= (bounds >>> SWIDTH)) {
+                    Predicate<? super ForkJoinPool> sat;
+                    if ((sat = saturate) != null && sat.test(this))
+                        return -1;
+                    else if (bc < pc) {          // lagging
+                        Thread.yield();          // for retry spins
+                        return 0;
                     }
                     else
-                        dropped = false;
-                }
-                if (dropped) {                    // pre-deregister
-                    int cfg = w.config, idx = cfg & SMASK;
-                    if (idx >= 0 && idx < ws.length && ws[idx] == w)
-                        ws[idx] = null;
-                    w.config = cfg | UNREGISTERED;
-                    w.qlock = -1;
-                    return true;
+                        throw new RejectedExecutionException(
+                            "Thread limit exceeded replacing blocked worker");
                 }
             }
         }
-        return false;
+
+        long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK); // expand pool
+        return CTL.compareAndSet(this, c, nc) && createWorker() ? 1 : 0;
     }
 
     /**
      * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
+     * See above for explanation.
      */
     final void runWorker(WorkQueue w) {
-        w.growArray();                                  // allocate queue
-        int bound = (w.config & SPARE_WORKER) != 0 ? 0 : POLL_LIMIT;
-        long seed = w.hint * 0xdaba0b6eb09322e3L;       // initial random seed
-        if ((runState & STOP) == 0) {
-            for (long r = (seed == 0L) ? 1L : seed;;) { // ensure nonzero
-                if (bound == 0 && tryDropSpare(w))
-                    break;
-                // high bits of prev seed for step; current low bits for idx
-                int step = (int)(r >>> 48) | 1;
-                r ^= r >>> 12; r ^= r << 25; r ^= r >>> 27; // xorshift
-                if (scan(w, bound, step, (int)r) < 0 && awaitWork(w) < 0)
-                    break;
+        int r = (w.id ^ ThreadLocalRandom.nextSecondarySeed()) | FIFO; // rng
+        w.array = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY]; // initialize
+        for (;;) {
+            int phase;
+            if (scan(w, r)) {                     // scan until apparently empty
+                r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // move (xorshift)
             }
-        }
-    }
-
-    // Scanning for tasks
-
-    /**
-     * Repeatedly scans for and tries to steal and execute (via
-     * workQueue.runTask) a queued task. Each scan traverses queues in
-     * pseudorandom permutation. Upon finding a non-empty queue, makes
-     * at most the given bound attempts to re-poll (fewer if
-     * contended) on the same queue before returning (impossible
-     * scanState value) 0 to restart scan. Else returns after at least
-     * 1 and at most 32 full scans.
-     *
-     * @param w the worker (via its WorkQueue)
-     * @param bound repoll bound as bitmask (0 if spare)
-     * @param step (circular) index increment per iteration (must be odd)
-     * @param r a random seed for origin index
-     * @return negative if should await signal
-     */
-    private int scan(WorkQueue w, int bound, int step, int r) {
-        int stat = 0, wl; WorkQueue[] ws;
-        if ((ws = workQueues) != null && w != null && (wl = ws.length) > 0) {
-            for (int m = wl - 1,
-                     origin = m & r, idx = origin,
-                     npolls = 0,
-                     ss = w.scanState;;) {         // negative if inactive
-                WorkQueue q; ForkJoinTask<?>[] a; int b, al;
-                if ((q = ws[idx]) != null && (b = q.base) - q.top < 0 &&
-                    (a = q.array) != null && (al = a.length) > 0) {
-                    int index = (al - 1) & b;
-                    long offset = ((long)index << ASHIFT) + ABASE;
-                    ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getObjectVolatile(a, offset);
-                    if (t == null)
-                        break;                     // empty or busy
-                    else if (b++ != q.base)
-                        break;                     // busy
-                    else if (ss < 0) {
-                        tryReactivate(w, ws, r);
-                        break;                     // retry upon rescan
-                    }
-                    else if (!U.compareAndSwapObject(a, offset, t, null))
-                        break;                     // contended
-                    else {
-                        q.base = b;
-                        w.currentSteal = t;
-                        if (b != q.top)            // propagate signal
-                            signalWork();
-                        w.runTask(t);
-                        if (++npolls > bound)
-                            break;
-                    }
-                }
-                else if (npolls != 0)              // rescan
+            else if ((phase = w.phase) >= 0) {    // enqueue, then rescan
+                long np = (w.phase = (phase + SS_SEQ) | UNSIGNALLED) & SP_MASK;
+                long c, nc;
+                do {
+                    w.stackPred = (int)(c = ctl);
+                    nc = ((c - RC_UNIT) & UC_MASK) | np;
+                } while (!CTL.weakCompareAndSet(this, c, nc));
+            }
+            else {                                // already queued
+                int pred = w.stackPred;
+                Thread.interrupted();             // clear before park
+                w.source = DORMANT;               // enable signal
+                long c = ctl;
+                int md = mode, rc = (md & SMASK) + (int)(c >> RC_SHIFT);
+                if (md < 0)                       // terminating
                     break;
-                else if ((idx = (idx + step) & m) == origin) {
-                    if (ss < 0) {                  // await signal
-                        stat = ss;
+                else if (rc <= 0 && (md & SHUTDOWN) != 0 &&
+                         tryTerminate(false, false))
+                    break;                        // quiescent shutdown
+                else if (rc <= 0 && pred != 0 && phase == (int)c) {
+                    long nc = (UC_MASK & (c - TC_UNIT)) | (SP_MASK & pred);
+                    long d = keepAlive + System.currentTimeMillis();
+                    LockSupport.parkUntil(this, d);
+                    if (ctl == c &&               // drop on timeout if all idle
+                        d - System.currentTimeMillis() <= TIMEOUT_SLOP &&
+                        CTL.compareAndSet(this, c, nc)) {
+                        w.phase = QUIET;
                         break;
                     }
-                    else if (r >= 0) {
-                        inactivate(w, ss);
-                        break;
-                    }
-                    else
-                        r <<= 1;                   // at most 31 rescans
                 }
+                else if (w.phase < 0)
+                    LockSupport.park(this);       // OK if spuriously woken
+                w.source = 0;                     // disable signal
             }
         }
-        return stat;
     }
 
-    // Joining tasks
-
     /**
-     * Tries to steal and run tasks within the target's computation.
-     * Uses a variant of the top-level algorithm, restricted to tasks
-     * with the given task as ancestor: It prefers taking and running
-     * eligible tasks popped from the worker's own queue (via
-     * popCC). Otherwise it scans others, randomly moving on
-     * contention or execution, deciding to give up based on a
-     * checksum (via return codes from pollAndExecCC). The maxTasks
-     * argument supports external usages; internal calls use zero,
-     * allowing unbounded steps (external calls trap non-positive
-     * values).
+     * Scans for and if found executes one or more top-level tasks from a queue.
      *
-     * @param w caller
-     * @param maxTasks if non-zero, the maximum number of other tasks to run
-     * @return task status on exit
+     * @return true if found an apparently non-empty queue, and
+     * possibly ran task(s).
      */
-    final int helpComplete(WorkQueue w, CountedCompleter<?> task,
-                           int maxTasks) {
-        WorkQueue[] ws; int s = 0, wl;
-        if ((ws = workQueues) != null && (wl = ws.length) > 1 &&
-            task != null && w != null) {
-            for (int m = wl - 1,
-                     mode = w.config,
-                     r = ~mode,                  // scanning seed
-                     origin = r & m, k = origin, // first queue to scan
-                     step = 3,                   // first scan step
-                     h = 1,                      // 1:ran, >1:contended, <0:hash
-                     oldSum = 0, checkSum = 0;;) {
-                CountedCompleter<?> p; WorkQueue q; int i;
-                if ((s = task.status) < 0)
+    private boolean scan(WorkQueue w, int r) {
+        WorkQueue[] ws; int n;
+        if ((ws = workQueues) != null && (n = ws.length) > 0 && w != null) {
+            for (int m = n - 1, j = r & m;;) {
+                WorkQueue q; int b;
+                if ((q = ws[j]) != null && q.top != (b = q.base)) {
+                    int qid = q.id;
+                    ForkJoinTask<?>[] a; int cap, k; ForkJoinTask<?> t;
+                    if ((a = q.array) != null && (cap = a.length) > 0) {
+                        t = (ForkJoinTask<?>)QA.getAcquire(a, k = (cap - 1) & b);
+                        if (q.base == b++ && t != null &&
+                            QA.compareAndSet(a, k, t, null)) {
+                            q.base = b;
+                            w.source = qid;
+                            if (q.top - b > 0)
+                                signalWork();
+                            w.topLevelExec(t, q,  // random fairness bound
+                                           r & ((n << TOP_BOUND_SHIFT) - 1));
+                        }
+                    }
+                    return true;
+                }
+                else if (--n > 0)
+                    j = (j + 1) & m;
+                else
                     break;
-                if (h == 1 && (p = w.popCC(task, mode)) != null) {
-                    p.doExec();                  // run local task
-                    if (maxTasks != 0 && --maxTasks == 0)
-                        break;
-                    origin = k;                  // reset
-                    oldSum = checkSum = 0;
-                }
-                else {                           // poll other worker queues
-                    if ((i = k | 1) < 0 || i > m || (q = ws[i]) == null)
-                        h = 0;
-                    else if ((h = q.pollAndExecCC(task)) < 0)
-                        checkSum += h;
-                    if (h > 0) {
-                        if (h == 1 && maxTasks != 0 && --maxTasks == 0)
-                            break;
-                        step = (r >>> 16) | 3;
-                        r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
-                        k = origin = r & m;      // move and restart
-                        oldSum = checkSum = 0;
-                    }
-                    else if ((k = (k + step) & m) == origin) {
-                        if (oldSum == (oldSum = checkSum))
-                            break;
-                        checkSum = 0;
-                    }
-                }
             }
         }
-        return s;
-    }
-
-    /**
-     * 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.
-     *
-     * @param w caller
-     * @param task the task to join
-     */
-    private void helpStealer(WorkQueue w, ForkJoinTask<?> task) {
-        if (task != null && w != null) {
-            ForkJoinTask<?> ps = w.currentSteal;
-            WorkQueue[] ws; int wl, oldSum = 0;
-            outer: while (w.tryRemoveAndExec(task) && task.status >= 0 &&
-                          (ws = workQueues) != null && (wl = ws.length) > 0) {
-                ForkJoinTask<?> subtask;
-                int m = wl - 1, checkSum = 0;          // for stability check
-                WorkQueue j = w, v;                    // v is subtask stealer
-                descent: for (subtask = task; subtask.status >= 0; ) {
-                    for (int h = j.hint | 1, k = 0, i;;) {
-                        if ((v = ws[i = (h + (k << 1)) & m]) != null) {
-                            if (v.currentSteal == subtask) {
-                                j.hint = i;
-                                break;
-                            }
-                            checkSum += v.base;
-                        }
-                        if (++k > m)                   // can't find stealer
-                            break outer;
-                    }
-
-                    for (;;) {                         // help v or descend
-                        ForkJoinTask<?>[] a; int b, al;
-                        if (subtask.status < 0)        // too late to help
-                            break descent;
-                        checkSum += (b = v.base);
-                        ForkJoinTask<?> next = v.currentJoin;
-                        ForkJoinTask<?> t = null;
-                        if ((a = v.array) != null && (al = a.length) > 0) {
-                            int index = (al - 1) & b;
-                            long offset = ((long)index << ASHIFT) + ABASE;
-                            t = (ForkJoinTask<?>)
-                                U.getObjectVolatile(a, offset);
-                            if (t != null && b++ == v.base) {
-                                if (j.currentJoin != subtask ||
-                                    v.currentSteal != subtask ||
-                                    subtask.status < 0)
-                                    break descent;     // stale
-                                if (U.compareAndSwapObject(a, offset, t, null)) {
-                                    v.base = b;
-                                    w.currentSteal = t;
-                                    for (int top = w.top;;) {
-                                        t.doExec();    // help
-                                        w.currentSteal = ps;
-                                        if (task.status < 0)
-                                            break outer;
-                                        if (w.top == top)
-                                            break;     // run local tasks
-                                        if ((t = w.pop()) == null)
-                                            break descent;
-                                        w.currentSteal = t;
-                                    }
-                                }
-                            }
-                        }
-                        if (t == null && b == v.base && b - v.top >= 0) {
-                            if ((subtask = next) == null) {  // try to descend
-                                if (next == v.currentJoin &&
-                                    oldSum == (oldSum = checkSum))
-                                    break outer;
-                                break descent;
-                            }
-                            j = v;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Tries to decrement active count (sometimes implicitly) and
-     * possibly release or create a compensating worker in preparation
-     * for blocking. Returns false (retryable by caller), on
-     * contention, detected staleness, instability, or termination.
-     *
-     * @param w caller
-     */
-    private boolean tryCompensate(WorkQueue w) {
-        boolean canBlock; int wl;
-        long c = ctl;
-        WorkQueue[] ws = workQueues;
-        int pc = config & SMASK;
-        int ac = pc + (int)(c >> AC_SHIFT);
-        int tc = pc + (short)(c >> TC_SHIFT);
-        if (w == null || w.qlock < 0 || pc == 0 ||  // terminating or disabled
-            ws == null || (wl = ws.length) <= 0)
-            canBlock = false;
-        else {
-            int m = wl - 1, sp;
-            boolean busy = true;                    // validate ac
-            for (int i = 0; i <= m; ++i) {
-                int k; WorkQueue v;
-                if ((k = (i << 1) | 1) <= m && k >= 0 && (v = ws[k]) != null &&
-                    v.scanState >= 0 && v.currentSteal == null) {
-                    busy = false;
-                    break;
-                }
-            }
-            if (!busy || ctl != c)
-                canBlock = false;                   // unstable or stale
-            else if ((sp = (int)c) != 0)            // release idle worker
-                canBlock = tryRelease(c, ws[m & sp], 0L);
-            else if (tc >= pc && ac > 1 && w.isEmpty()) {
-                long nc = ((AC_MASK & (c - AC_UNIT)) |
-                           (~AC_MASK & c));         // uncompensated
-                canBlock = U.compareAndSwapLong(this, CTL, c, nc);
-            }
-            else if (tc >= MAX_CAP ||
-                     (this == common && tc >= pc + COMMON_MAX_SPARES))
-                throw new RejectedExecutionException(
-                    "Thread limit exceeded replacing blocked worker");
-            else {                                  // similar to tryAddWorker
-                boolean isSpare = (tc >= pc);
-                long nc = (AC_MASK & c) | (TC_MASK & (c + TC_UNIT));
-                canBlock = (U.compareAndSwapLong(this, CTL, c, nc) &&
-                            createWorker(isSpare)); // throws on exception
-            }
-        }
-        return canBlock;
+        return false;
     }
 
     /**
      * Helps and/or blocks until the given task is done or timeout.
+     * First tries locally helping, then scans other queues for a task
+     * produced by one of w's stealers; compensating and blocking if
+     * none are found (rescanning if tryCompensate fails).
      *
      * @param w caller
      * @param task the task
@@ -2225,62 +1682,165 @@
      */
     final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
         int s = 0;
-        if (w != null) {
-            ForkJoinTask<?> prevJoin = w.currentJoin;
-            if (task != null && (s = task.status) >= 0) {
-                w.currentJoin = task;
-                CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
-                    (CountedCompleter<?>)task : null;
-                for (;;) {
-                    if (cc != null)
-                        helpComplete(w, cc, 0);
-                    else
-                        helpStealer(w, task);
-                    if ((s = task.status) < 0)
+        int seed = ThreadLocalRandom.nextSecondarySeed();
+        if (w != null && task != null &&
+            (!(task instanceof CountedCompleter) ||
+             (s = w.helpCC((CountedCompleter<?>)task, 0, false)) >= 0)) {
+            w.tryRemoveAndExec(task);
+            int src = w.source, id = w.id;
+            int r = (seed >>> 16) | 1, step = (seed & ~1) | 2;
+            s = task.status;
+            while (s >= 0) {
+                WorkQueue[] ws;
+                int n = (ws = workQueues) == null ? 0 : ws.length, m = n - 1;
+                while (n > 0) {
+                    WorkQueue q; int b;
+                    if ((q = ws[r & m]) != null && q.source == id &&
+                        q.top != (b = q.base)) {
+                        ForkJoinTask<?>[] a; int cap, k;
+                        int qid = q.id;
+                        if ((a = q.array) != null && (cap = a.length) > 0) {
+                            ForkJoinTask<?> t = (ForkJoinTask<?>)
+                                QA.getAcquire(a, k = (cap - 1) & b);
+                            if (q.source == id && q.base == b++ &&
+                                t != null && QA.compareAndSet(a, k, t, null)) {
+                                q.base = b;
+                                w.source = qid;
+                                t.doExec();
+                                w.source = src;
+                            }
+                        }
                         break;
-                    long ms, ns;
-                    if (deadline == 0L)
-                        ms = 0L;
-                    else if ((ns = deadline - System.nanoTime()) <= 0L)
-                        break;
-                    else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
-                        ms = 1L;
-                    if (tryCompensate(w)) {
-                        task.internalWait(ms);
-                        U.getAndAddLong(this, CTL, AC_UNIT);
                     }
-                    if ((s = task.status) < 0)
-                        break;
+                    else {
+                        r += step;
+                        --n;
+                    }
                 }
-                w.currentJoin = prevJoin;
+                if ((s = task.status) < 0)
+                    break;
+                else if (n == 0) { // empty scan
+                    long ms, ns; int block;
+                    if (deadline == 0L)
+                        ms = 0L;                       // untimed
+                    else if ((ns = deadline - System.nanoTime()) <= 0L)
+                        break;                         // timeout
+                    else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
+                        ms = 1L;                       // avoid 0 for timed wait
+                    if ((block = tryCompensate(w)) != 0) {
+                        task.internalWait(ms);
+                        CTL.getAndAdd(this, (block > 0) ? RC_UNIT : 0L);
+                    }
+                    s = task.status;
+                }
             }
         }
         return s;
     }
 
-    // Specialized scanning
+    /**
+     * Runs tasks until {@code isQuiescent()}. Rather than blocking
+     * when tasks cannot be found, rescans until all others cannot
+     * find tasks either.
+     */
+    final void helpQuiescePool(WorkQueue w) {
+        int prevSrc = w.source;
+        int seed = ThreadLocalRandom.nextSecondarySeed();
+        int r = seed >>> 16, step = r | 1;
+        for (int source = prevSrc, released = -1;;) { // -1 until known
+            ForkJoinTask<?> localTask; WorkQueue[] ws;
+            while ((localTask = w.nextLocalTask()) != null)
+                localTask.doExec();
+            if (w.phase >= 0 && released == -1)
+                released = 1;
+            boolean quiet = true, empty = true;
+            int n = (ws = workQueues) == null ? 0 : ws.length;
+            for (int m = n - 1; n > 0; r += step, --n) {
+                WorkQueue q; int b;
+                if ((q = ws[r & m]) != null) {
+                    int qs = q.source;
+                    if (q.top != (b = q.base)) {
+                        quiet = empty = false;
+                        ForkJoinTask<?>[] a; int cap, k;
+                        int qid = q.id;
+                        if ((a = q.array) != null && (cap = a.length) > 0) {
+                            if (released == 0) {    // increment
+                                released = 1;
+                                CTL.getAndAdd(this, RC_UNIT);
+                            }
+                            ForkJoinTask<?> t = (ForkJoinTask<?>)
+                                QA.getAcquire(a, k = (cap - 1) & b);
+                            if (q.base == b++ && t != null &&
+                                QA.compareAndSet(a, k, t, null)) {
+                                q.base = b;
+                                w.source = qid;
+                                t.doExec();
+                                w.source = source = prevSrc;
+                            }
+                        }
+                        break;
+                    }
+                    else if ((qs & QUIET) == 0)
+                        quiet = false;
+                }
+            }
+            if (quiet) {
+                if (released == 0)
+                    CTL.getAndAdd(this, RC_UNIT);
+                w.source = prevSrc;
+                break;
+            }
+            else if (empty) {
+                if (source != QUIET)
+                    w.source = source = QUIET;
+                if (released == 1) {                 // decrement
+                    released = 0;
+                    CTL.getAndAdd(this, RC_MASK & -RC_UNIT);
+                }
+            }
+        }
+    }
 
     /**
-     * Returns a (probably) non-empty steal queue, if one is found
-     * during a scan, else null.  This method must be retried by
-     * caller if, by the time it tries to use the queue, it is empty.
+     * Scans for and returns a polled task, if available.
+     * Used only for untracked polls.
+     *
+     * @param submissionsOnly if true, only scan submission queues
      */
-    private WorkQueue findNonEmptyStealQueue() {
-        WorkQueue[] ws; int wl;  // one-shot version of scan loop
-        int r = ThreadLocalRandom.nextSecondarySeed();
-        if ((ws = workQueues) != null && (wl = ws.length) > 0) {
-            int m = wl - 1, origin = r & m;
-            for (int k = origin, oldSum = 0, checkSum = 0;;) {
-                WorkQueue q; int b;
-                if ((q = ws[k]) != null) {
-                    if ((b = q.base) - q.top < 0)
-                        return q;
-                    checkSum += b;
+    private ForkJoinTask<?> pollScan(boolean submissionsOnly) {
+        WorkQueue[] ws; int n;
+        rescan: while ((mode & STOP) == 0 && (ws = workQueues) != null &&
+                      (n = ws.length) > 0) {
+            int m = n - 1;
+            int r = ThreadLocalRandom.nextSecondarySeed();
+            int h = r >>> 16;
+            int origin, step;
+            if (submissionsOnly) {
+                origin = (r & ~1) & m;         // even indices and steps
+                step = (h & ~1) | 2;
+            }
+            else {
+                origin = r & m;
+                step = h | 1;
+            }
+            boolean nonempty = false;
+            for (int i = origin, oldSum = 0, checkSum = 0;;) {
+                WorkQueue q;
+                if ((q = ws[i]) != null) {
+                    int b; ForkJoinTask<?> t;
+                    if (q.top - (b = q.base) > 0) {
+                        nonempty = true;
+                        if ((t = q.poll()) != null)
+                            return t;
+                    }
+                    else
+                        checkSum += b + q.id;
                 }
-                if ((k = (k + 1) & m) == origin) {
-                    if (oldSum == (oldSum = checkSum))
-                        break;
+                if ((i = (i + step) & m) == origin) {
+                    if (!nonempty && oldSum == (oldSum = checkSum))
+                        break rescan;
                     checkSum = 0;
+                    nonempty = false;
                 }
             }
         }
@@ -2288,58 +1848,129 @@
     }
 
     /**
-     * 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.
-     */
-    final void helpQuiescePool(WorkQueue w) {
-        ForkJoinTask<?> ps = w.currentSteal; // save context
-        int wc = w.config;
-        for (boolean active = true;;) {
-            long c; WorkQueue q; ForkJoinTask<?> t;
-            if (wc >= 0 && (t = w.pop()) != null) { // run locals if LIFO
-                (w.currentSteal = t).doExec();
-                w.currentSteal = ps;
-            }
-            else if ((q = findNonEmptyStealQueue()) != null) {
-                if (!active) {      // re-establish active count
-                    active = true;
-                    U.getAndAddLong(this, CTL, AC_UNIT);
-                }
-                if ((t = q.pollAt(q.base)) != null) {
-                    (w.currentSteal = t).doExec();
-                    w.currentSteal = ps;
-                    if (++w.nsteals < 0)
-                        w.transferStealCount(this);
-                }
-            }
-            else if (active) {      // decrement active count without queuing
-                long nc = (AC_MASK & ((c = ctl) - AC_UNIT)) | (~AC_MASK & c);
-                if (U.compareAndSwapLong(this, CTL, c, nc))
-                    active = false;
-            }
-            else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) <= 0 &&
-                     U.compareAndSwapLong(this, CTL, c, c + AC_UNIT))
-                break;
-        }
-    }
-
-    /**
      * Gets and removes a local or stolen task for the given worker.
      *
      * @return a task, if available
      */
     final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
-        for (ForkJoinTask<?> t;;) {
-            WorkQueue q;
-            if ((t = w.nextLocalTask()) != null)
-                return t;
-            if ((q = findNonEmptyStealQueue()) == null)
-                return null;
-            if ((t = q.pollAt(q.base)) != null)
-                return t;
+        ForkJoinTask<?> t;
+        if (w == null || (t = w.nextLocalTask()) == null)
+            t = pollScan(false);
+        return t;
+    }
+
+    // External operations
+
+    /**
+     * Adds the given task to a submission queue at submitter's
+     * current queue, creating one if null or contended.
+     *
+     * @param task the task. Caller must ensure non-null.
+     */
+    final void externalPush(ForkJoinTask<?> task) {
+        int r;                                // initialize caller's probe
+        if ((r = ThreadLocalRandom.getProbe()) == 0) {
+            ThreadLocalRandom.localInit();
+            r = ThreadLocalRandom.getProbe();
         }
+        for (;;) {
+            WorkQueue q;
+            int md = mode, n;
+            WorkQueue[] ws = workQueues;
+            if ((md & SHUTDOWN) != 0 || ws == null || (n = ws.length) <= 0)
+                throw new RejectedExecutionException();
+            else if ((q = ws[(n - 1) & r & SQMASK]) == null) { // add queue
+                int qid = (r | QUIET) & ~(FIFO | OWNED);
+                Object lock = workerNamePrefix;
+                ForkJoinTask<?>[] qa =
+                    new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
+                q = new WorkQueue(this, null);
+                q.array = qa;
+                q.id = qid;
+                q.source = QUIET;
+                if (lock != null) {     // unless disabled, lock pool to install
+                    synchronized (lock) {
+                        WorkQueue[] vs; int i, vn;
+                        if ((vs = workQueues) != null && (vn = vs.length) > 0 &&
+                            vs[i = qid & (vn - 1) & SQMASK] == null)
+                            vs[i] = q;  // else another thread already installed
+                    }
+                }
+            }
+            else if (!q.tryLockPhase()) // move if busy
+                r = ThreadLocalRandom.advanceProbe(r);
+            else {
+                if (q.lockedPush(task))
+                    signalWork();
+                return;
+            }
+        }
+    }
+
+    /**
+     * Pushes a possibly-external submission.
+     */
+    private <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) {
+        Thread t; ForkJoinWorkerThread w; WorkQueue q;
+        if (task == null)
+            throw new NullPointerException();
+        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
+            (w = (ForkJoinWorkerThread)t).pool == this &&
+            (q = w.workQueue) != null)
+            q.push(task);
+        else
+            externalPush(task);
+        return task;
+    }
+
+    /**
+     * Returns common pool queue for an external thread.
+     */
+    static WorkQueue commonSubmitterQueue() {
+        ForkJoinPool p = common;
+        int r = ThreadLocalRandom.getProbe();
+        WorkQueue[] ws; int n;
+        return (p != null && (ws = p.workQueues) != null &&
+                (n = ws.length) > 0) ?
+            ws[(n - 1) & r & SQMASK] : null;
+    }
+
+    /**
+     * Performs tryUnpush for an external submitter.
+     */
+    final boolean tryExternalUnpush(ForkJoinTask<?> task) {
+        int r = ThreadLocalRandom.getProbe();
+        WorkQueue[] ws; WorkQueue w; int n;
+        return ((ws = workQueues) != null &&
+                (n = ws.length) > 0 &&
+                (w = ws[(n - 1) & r & SQMASK]) != null &&
+                w.tryLockedUnpush(task));
+    }
+
+    /**
+     * Performs helpComplete for an external submitter.
+     */
+    final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
+        int r = ThreadLocalRandom.getProbe();
+        WorkQueue[] ws; WorkQueue w; int n;
+        return ((ws = workQueues) != null && (n = ws.length) > 0 &&
+                (w = ws[(n - 1) & r & SQMASK]) != null) ?
+            w.helpCC(task, maxTasks, true) : 0;
+    }
+
+    /**
+     * Tries to steal and run tasks within the target's computation.
+     * The maxTasks argument supports external usages; internal calls
+     * use zero, allowing unbounded steps (external calls trap
+     * non-positive values).
+     *
+     * @param w caller
+     * @param maxTasks if non-zero, the maximum number of other tasks to run
+     * @return task status on exit
+     */
+    final int helpComplete(WorkQueue w, CountedCompleter<?> task,
+                           int maxTasks) {
+        return (w == null) ? 0 : w.helpCC(task, maxTasks, false);
     }
 
     /**
@@ -2386,10 +2017,12 @@
      */
     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;
+        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
+            (pool = (wt = (ForkJoinWorkerThread)t).pool) != null &&
+            (q = wt.workQueue) != null) {
+            int p = pool.mode & SMASK;
+            int a = p + (int)(pool.ctl >> RC_SHIFT);
+            int n = q.top - q.base;
             return n - (a > (p >>>= 1) ? 0 :
                         a > (p >>>= 1) ? 1 :
                         a > (p >>>= 1) ? 2 :
@@ -2399,7 +2032,7 @@
         return 0;
     }
 
-    //  Termination
+    // Termination
 
     /**
      * Possibly initiates and/or completes termination.
@@ -2407,198 +2040,89 @@
      * @param now if true, unconditionally terminate, else only
      * if no work and no active workers
      * @param enable if true, terminate when next possible
-     * @return -1: terminating/terminated, 0: retry if internal caller, else 1
+     * @return true if terminating or terminated
      */
-    private int tryTerminate(boolean now, boolean enable) {
-        int rs; // 3 phases: try to set SHUTDOWN, then STOP, then TERMINATED
+    private boolean tryTerminate(boolean now, boolean enable) {
+        int md; // 3 phases: try to set SHUTDOWN, then STOP, then TERMINATED
 
-        while ((rs = runState) >= 0) {
+        while (((md = mode) & SHUTDOWN) == 0) {
             if (!enable || this == common)        // cannot shutdown
-                return 1;
-            else if (rs == 0)
-                tryInitialize(false);             // ensure initialized
+                return false;
             else
-                U.compareAndSwapInt(this, RUNSTATE, rs, rs | SHUTDOWN);
+                MODE.compareAndSet(this, md, md | SHUTDOWN);
         }
 
-        if ((rs & STOP) == 0) {                   // try to initiate termination
-            if (!now) {                           // check quiescence
+        while (((md = mode) & STOP) == 0) {       // try to initiate termination
+            if (!now) {                           // check if quiescent & empty
                 for (long oldSum = 0L;;) {        // repeat until stable
-                    WorkQueue[] ws; WorkQueue w; int b;
+                    boolean running = false;
                     long checkSum = ctl;
-                    if ((int)(checkSum >> AC_SHIFT) + (config & SMASK) > 0)
-                        return 0;                 // still active workers
-                    if ((ws = workQueues) != null) {
+                    WorkQueue[] ws = workQueues;
+                    if ((md & SMASK) + (int)(checkSum >> RC_SHIFT) > 0)
+                        running = true;
+                    else if (ws != null) {
+                        WorkQueue w;
                         for (int i = 0; i < ws.length; ++i) {
                             if ((w = ws[i]) != null) {
-                                checkSum += (b = w.base);
-                                if (w.currentSteal != null || b != w.top)
-                                    return 0;     // retry if internal caller
+                                int s = w.source, p = w.phase;
+                                int d = w.id, b = w.base;
+                                if (b != w.top ||
+                                    ((d & 1) == 1 && (s >= 0 || p >= 0))) {
+                                    running = true;
+                                    break;     // working, scanning, or have work
+                                }
+                                checkSum += (((long)s << 48) + ((long)p << 32) +
+                                             ((long)b << 16) + (long)d);
                             }
                         }
                     }
-                    if (oldSum == (oldSum = checkSum))
+                    if (((md = mode) & STOP) != 0)
+                        break;                 // already triggered
+                    else if (running)
+                        return false;
+                    else if (workQueues == ws && oldSum == (oldSum = checkSum))
                         break;
                 }
             }
-            do {} while (!U.compareAndSwapInt(this, RUNSTATE,
-                                              rs = runState, rs | STOP));
+            if ((md & STOP) == 0)
+                MODE.compareAndSet(this, md, md | STOP);
         }
 
-        for (long oldSum = 0L;;) {                // repeat until stable
-            WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt;
-            long checkSum = ctl;
-            if ((ws = workQueues) != null) {      // help terminate others
-                for (int i = 0; i < ws.length; ++i) {
-                    if ((w = ws[i]) != null) {
-                        w.cancelAll();            // clear queues
-                        checkSum += w.base;
-                        if (w.qlock >= 0) {
-                            w.qlock = -1;         // racy set OK
-                            if ((wt = w.owner) != null) {
+        while (((md = mode) & TERMINATED) == 0) { // help terminate others
+            for (long oldSum = 0L;;) {            // repeat until stable
+                WorkQueue[] ws; WorkQueue w;
+                long checkSum = ctl;
+                if ((ws = workQueues) != null) {
+                    for (int i = 0; i < ws.length; ++i) {
+                        if ((w = ws[i]) != null) {
+                            ForkJoinWorkerThread wt = w.owner;
+                            w.cancelAll();        // clear queues
+                            if (wt != null) {
                                 try {             // unblock join or park
                                     wt.interrupt();
                                 } catch (Throwable ignore) {
                                 }
                             }
+                            checkSum += ((long)w.phase << 32) + w.base;
                         }
                     }
                 }
+                if (((md = mode) & TERMINATED) != 0 ||
+                    (workQueues == ws && oldSum == (oldSum = checkSum)))
+                    break;
             }
-            if (oldSum == (oldSum = checkSum))
+            if ((md & TERMINATED) != 0)
                 break;
-        }
-
-        if ((short)(ctl >>> TC_SHIFT) + (config & SMASK) <= 0) {
-            runState = (STARTED | SHUTDOWN | STOP | TERMINATED); // final write
-            synchronized (this) {
-                notifyAll();                      // for awaitTermination
-            }
-        }
-
-        return -1;
-    }
-
-    // External operations
-
-    /**
-     * Constructs and tries to install a new external queue,
-     * failing if the workQueues array already has a queue at
-     * the given index.
-     *
-     * @param index the index of the new queue
-     */
-    private void tryCreateExternalQueue(int index) {
-        AuxState aux;
-        if ((aux = auxState) != null && index >= 0) {
-            WorkQueue q = new WorkQueue(this, null);
-            q.config = index;
-            q.scanState = ~UNSIGNALLED;
-            q.qlock = 1;                   // lock queue
-            boolean installed = false;
-            aux.lock();
-            try {                          // lock pool to install
-                WorkQueue[] ws;
-                if ((ws = workQueues) != null && index < ws.length &&
-                    ws[index] == null) {
-                    ws[index] = q;         // else throw away
-                    installed = true;
+            else if ((md & SMASK) + (short)(ctl >>> TC_SHIFT) > 0)
+                break;
+            else if (MODE.compareAndSet(this, md, md | TERMINATED)) {
+                synchronized (this) {
+                    notifyAll();                  // for awaitTermination
                 }
-            } finally {
-                aux.unlock();
-            }
-            if (installed) {
-                try {
-                    q.growArray();
-                } finally {
-                    q.qlock = 0;
-                }
-            }
-        }
-    }
-
-    /**
-     * Adds the given task to a submission queue at submitter's
-     * current queue. Also performs secondary initialization upon the
-     * first submission of the first task to the pool, and detects
-     * first submission by an external thread and creates a new shared
-     * queue if the one at index if empty or contended.
-     *
-     * @param task the task. Caller must ensure non-null.
-     */
-    final void externalPush(ForkJoinTask<?> task) {
-        int r;                            // initialize caller's probe
-        if ((r = ThreadLocalRandom.getProbe()) == 0) {
-            ThreadLocalRandom.localInit();
-            r = ThreadLocalRandom.getProbe();
-        }
-        for (;;) {
-            WorkQueue q; int wl, k, stat;
-            int rs = runState;
-            WorkQueue[] ws = workQueues;
-            if (rs <= 0 || ws == null || (wl = ws.length) <= 0)
-                tryInitialize(true);
-            else if ((q = ws[k = (wl - 1) & r & SQMASK]) == null)
-                tryCreateExternalQueue(k);
-            else if ((stat = q.sharedPush(task)) < 0)
-                break;
-            else if (stat == 0) {
-                signalWork();
                 break;
             }
-            else                          // move if busy
-                r = ThreadLocalRandom.advanceProbe(r);
         }
-    }
-
-    /**
-     * Pushes a possibly-external submission.
-     */
-    private <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) {
-        Thread t; ForkJoinWorkerThread w; WorkQueue q;
-        if (task == null)
-            throw new NullPointerException();
-        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
-            (w = (ForkJoinWorkerThread)t).pool == this &&
-            (q = w.workQueue) != null)
-            q.push(task);
-        else
-            externalPush(task);
-        return task;
-    }
-
-    /**
-     * Returns common pool queue for an external thread.
-     */
-    static WorkQueue commonSubmitterQueue() {
-        ForkJoinPool p = common;
-        int r = ThreadLocalRandom.getProbe();
-        WorkQueue[] ws; int wl;
-        return (p != null && (ws = p.workQueues) != null &&
-                (wl = ws.length) > 0) ?
-            ws[(wl - 1) & r & SQMASK] : null;
-    }
-
-    /**
-     * Performs tryUnpush for an external submitter.
-     */
-    final boolean tryExternalUnpush(ForkJoinTask<?> task) {
-        int r = ThreadLocalRandom.getProbe();
-        WorkQueue[] ws; WorkQueue w; int wl;
-        return ((ws = workQueues) != null &&
-                (wl = ws.length) > 0 &&
-                (w = ws[(wl - 1) & r & SQMASK]) != null &&
-                w.trySharedUnpush(task));
-    }
-
-    /**
-     * Performs helpComplete for an external submitter.
-     */
-    final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
-        WorkQueue[] ws; int wl;
-        int r = ThreadLocalRandom.getProbe();
-        return ((ws = workQueues) != null && (wl = ws.length) > 0) ?
-            helpComplete(ws[(wl - 1) & r & SQMASK], task, maxTasks) : 0;
+        return true;
     }
 
     // Exported methods
@@ -2607,9 +2131,10 @@
 
     /**
      * Creates a {@code ForkJoinPool} with parallelism equal to {@link
-     * java.lang.Runtime#availableProcessors}, using the {@linkplain
-     * #defaultForkJoinWorkerThreadFactory default thread factory},
-     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
+     * java.lang.Runtime#availableProcessors}, using defaults for all
+     * other parameters (see {@link #ForkJoinPool(int,
+     * ForkJoinWorkerThreadFactory, UncaughtExceptionHandler, boolean,
+     * int, int, int, Predicate, long, TimeUnit)}).
      *
      * @throws SecurityException if a security manager exists and
      *         the caller is not permitted to modify threads
@@ -2618,14 +2143,16 @@
      */
     public ForkJoinPool() {
         this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
-             defaultForkJoinWorkerThreadFactory, null, false);
+             defaultForkJoinWorkerThreadFactory, null, false,
+             0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
     }
 
     /**
      * Creates a {@code ForkJoinPool} with the indicated parallelism
-     * level, the {@linkplain
-     * #defaultForkJoinWorkerThreadFactory default thread factory},
-     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
+     * level, using defaults for all other parameters (see {@link
+     * #ForkJoinPool(int, ForkJoinWorkerThreadFactory,
+     * UncaughtExceptionHandler, boolean, int, int, int, Predicate,
+     * long, TimeUnit)}).
      *
      * @param parallelism the parallelism level
      * @throws IllegalArgumentException if parallelism less than or
@@ -2636,11 +2163,15 @@
      *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public ForkJoinPool(int parallelism) {
-        this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
+        this(parallelism, defaultForkJoinWorkerThreadFactory, null, false,
+             0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
     }
 
     /**
-     * Creates a {@code ForkJoinPool} with the given parameters.
+     * Creates a {@code ForkJoinPool} with the given parameters (using
+     * defaults for others -- see {@link #ForkJoinPool(int,
+     * ForkJoinWorkerThreadFactory, UncaughtExceptionHandler, boolean,
+     * int, int, int, Predicate, long, TimeUnit)}).
      *
      * @param parallelism the parallelism level. For default value,
      * use {@link java.lang.Runtime#availableProcessors}.
@@ -2667,43 +2198,186 @@
                         ForkJoinWorkerThreadFactory factory,
                         UncaughtExceptionHandler handler,
                         boolean asyncMode) {
-        this(checkParallelism(parallelism),
-             checkFactory(factory),
-             handler,
-             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
-             "ForkJoinPool-" + nextPoolId() + "-worker-");
-        checkPermission();
-    }
-
-    private static int checkParallelism(int parallelism) {
-        if (parallelism <= 0 || parallelism > MAX_CAP)
-            throw new IllegalArgumentException();
-        return parallelism;
-    }
-
-    private static ForkJoinWorkerThreadFactory checkFactory
-        (ForkJoinWorkerThreadFactory factory) {
-        if (factory == null)
-            throw new NullPointerException();
-        return factory;
+        this(parallelism, factory, handler, asyncMode,
+             0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
     }
 
     /**
-     * Creates a {@code ForkJoinPool} with the given parameters, without
-     * any security checks or parameter validation.  Invoked directly by
-     * makeCommonPool.
+     * Creates a {@code ForkJoinPool} with the given parameters.
+     *
+     * @param parallelism the parallelism level. For default value,
+     * use {@link java.lang.Runtime#availableProcessors}.
+     *
+     * @param factory the factory for creating new threads. For
+     * default value, use {@link #defaultForkJoinWorkerThreadFactory}.
+     *
+     * @param handler the handler for internal worker threads that
+     * terminate due to unrecoverable errors encountered while
+     * executing tasks. For default value, use {@code null}.
+     *
+     * @param asyncMode if true, establishes local first-in-first-out
+     * scheduling mode for forked tasks that are never joined. This
+     * mode may be more appropriate than default locally stack-based
+     * mode in applications in which worker threads only process
+     * event-style asynchronous tasks.  For default value, use {@code
+     * false}.
+     *
+     * @param corePoolSize the number of threads to keep in the pool
+     * (unless timed out after an elapsed keep-alive). Normally (and
+     * by default) this is the same value as the parallelism level,
+     * but may be set to a larger value to reduce dynamic overhead if
+     * tasks regularly block. Using a smaller value (for example
+     * {@code 0}) has the same effect as the default.
+     *
+     * @param maximumPoolSize the maximum number of threads allowed.
+     * When the maximum is reached, attempts to replace blocked
+     * threads fail.  (However, because creation and termination of
+     * different threads may overlap, and may be managed by the given
+     * thread factory, this value may be transiently exceeded.)  To
+     * arrange the same value as is used by default for the common
+     * pool, use {@code 256} plus the {@code parallelism} level. (By
+     * default, the common pool allows a maximum of 256 spare
+     * threads.)  Using a value (for example {@code
+     * Integer.MAX_VALUE}) larger than the implementation's total
+     * thread limit has the same effect as using this limit (which is
+     * the default).
+     *
+     * @param minimumRunnable the minimum allowed number of core
+     * threads not blocked by a join or {@link ManagedBlocker}.  To
+     * ensure progress, when too few unblocked threads exist and
+     * unexecuted tasks may exist, new threads are constructed, up to
+     * the given maximumPoolSize.  For the default value, use {@code
+     * 1}, that ensures liveness.  A larger value might improve
+     * throughput in the presence of blocked activities, but might
+     * not, due to increased overhead.  A value of zero may be
+     * acceptable when submitted tasks cannot have dependencies
+     * requiring additional threads.
+     *
+     * @param saturate if non-null, a predicate invoked upon attempts
+     * to create more than the maximum total allowed threads.  By
+     * default, when a thread is about to block on a join or {@link
+     * ManagedBlocker}, but cannot be replaced because the
+     * maximumPoolSize would be exceeded, a {@link
+     * RejectedExecutionException} is thrown.  But if this predicate
+     * returns {@code true}, then no exception is thrown, so the pool
+     * continues to operate with fewer than the target number of
+     * runnable threads, which might not ensure progress.
+     *
+     * @param keepAliveTime the elapsed time since last use before
+     * a thread is terminated (and then later replaced if needed).
+     * For the default value, use {@code 60, TimeUnit.SECONDS}.
+     *
+     * @param unit the time unit for the {@code keepAliveTime} argument
+     *
+     * @throws IllegalArgumentException if parallelism is less than or
+     *         equal to zero, or is greater than implementation limit,
+     *         or if maximumPoolSize is less than parallelism,
+     *         of if the keepAliveTime is less than or equal to zero.
+     * @throws NullPointerException if the factory is null
+     * @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")}
+     * @since 9
      */
-    private ForkJoinPool(int parallelism,
-                         ForkJoinWorkerThreadFactory factory,
-                         UncaughtExceptionHandler handler,
-                         int mode,
-                         String workerNamePrefix) {
-        this.workerNamePrefix = workerNamePrefix;
+    public ForkJoinPool(int parallelism,
+                        ForkJoinWorkerThreadFactory factory,
+                        UncaughtExceptionHandler handler,
+                        boolean asyncMode,
+                        int corePoolSize,
+                        int maximumPoolSize,
+                        int minimumRunnable,
+                        Predicate<? super ForkJoinPool> saturate,
+                        long keepAliveTime,
+                        TimeUnit unit) {
+        // check, encode, pack parameters
+        if (parallelism <= 0 || parallelism > MAX_CAP ||
+            maximumPoolSize < parallelism || keepAliveTime <= 0L)
+            throw new IllegalArgumentException();
+        if (factory == null)
+            throw new NullPointerException();
+        long ms = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);
+
+        int corep = Math.min(Math.max(corePoolSize, parallelism), MAX_CAP);
+        long c = ((((long)(-corep)       << TC_SHIFT) & TC_MASK) |
+                  (((long)(-parallelism) << RC_SHIFT) & RC_MASK));
+        int m = parallelism | (asyncMode ? FIFO : 0);
+        int maxSpares = Math.min(maximumPoolSize, MAX_CAP) - parallelism;
+        int minAvail = Math.min(Math.max(minimumRunnable, 0), MAX_CAP);
+        int b = ((minAvail - parallelism) & SMASK) | (maxSpares << SWIDTH);
+        int n = (parallelism > 1) ? parallelism - 1 : 1; // at least 2 slots
+        n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
+        n = (n + 1) << 1; // power of two, including space for submission queues
+
+        this.workerNamePrefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
+        this.workQueues = new WorkQueue[n];
         this.factory = factory;
         this.ueh = handler;
-        this.config = (parallelism & SMASK) | mode;
-        long np = (long)(-parallelism); // offset ctl counts
-        this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
+        this.saturate = saturate;
+        this.keepAlive = ms;
+        this.bounds = b;
+        this.mode = m;
+        this.ctl = c;
+        checkPermission();
+    }
+
+    private static Object newInstanceFromSystemProperty(String property)
+        throws ReflectiveOperationException {
+        String className = System.getProperty(property);
+        return (className == null)
+            ? null
+            : ClassLoader.getSystemClassLoader().loadClass(className)
+            .getConstructor().newInstance();
+    }
+
+    /**
+     * Constructor for common pool using parameters possibly
+     * overridden by system properties
+     */
+    private ForkJoinPool(byte forCommonPoolOnly) {
+        int parallelism = -1;
+        ForkJoinWorkerThreadFactory fac = null;
+        UncaughtExceptionHandler handler = null;
+        try {  // ignore exceptions in accessing/parsing properties
+            String pp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.parallelism");
+            if (pp != null)
+                parallelism = Integer.parseInt(pp);
+            fac = (ForkJoinWorkerThreadFactory) newInstanceFromSystemProperty(
+                "java.util.concurrent.ForkJoinPool.common.threadFactory");
+            handler = (UncaughtExceptionHandler) newInstanceFromSystemProperty(
+                "java.util.concurrent.ForkJoinPool.common.exceptionHandler");
+        } catch (Exception ignore) {
+        }
+
+        if (fac == null) {
+            if (System.getSecurityManager() == null)
+                fac = defaultForkJoinWorkerThreadFactory;
+            else // use security-managed default
+                fac = new InnocuousForkJoinWorkerThreadFactory();
+        }
+        if (parallelism < 0 && // default 1 less than #cores
+            (parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)
+            parallelism = 1;
+        if (parallelism > MAX_CAP)
+            parallelism = MAX_CAP;
+
+        long c = ((((long)(-parallelism) << TC_SHIFT) & TC_MASK) |
+                  (((long)(-parallelism) << RC_SHIFT) & RC_MASK));
+        int b = ((1 - parallelism) & SMASK) | (COMMON_MAX_SPARES << SWIDTH);
+        int n = (parallelism > 1) ? parallelism - 1 : 1;
+        n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
+        n = (n + 1) << 1;
+
+        this.workerNamePrefix = "ForkJoinPool.commonPool-worker-";
+        this.workQueues = new WorkQueue[n];
+        this.factory = fac;
+        this.ueh = handler;
+        this.saturate = null;
+        this.keepAlive = DEFAULT_KEEPALIVE;
+        this.bounds = b;
+        this.mode = parallelism;
+        this.ctl = c;
     }
 
     /**
@@ -2817,15 +2491,13 @@
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
      */
+    @SuppressWarnings("unchecked")
     public ForkJoinTask<?> submit(Runnable task) {
         if (task == null)
             throw new NullPointerException();
-        ForkJoinTask<?> job;
-        if (task instanceof ForkJoinTask<?>) // avoid re-wrap
-            job = (ForkJoinTask<?>) task;
-        else
-            job = new ForkJoinTask.AdaptedRunnableAction(task);
-        return externalSubmit(job);
+        return externalSubmit((task instanceof ForkJoinTask<?>)
+            ? (ForkJoinTask<Void>) task // avoid re-wrap
+            : new ForkJoinTask.AdaptedRunnableAction(task));
     }
 
     /**
@@ -2879,8 +2551,8 @@
      * @return the targeted parallelism level of this pool
      */
     public int getParallelism() {
-        int par;
-        return ((par = config & SMASK) > 0) ? par : 1;
+        int par = mode & SMASK;
+        return (par > 0) ? par : 1;
     }
 
     /**
@@ -2902,7 +2574,7 @@
      * @return the number of worker threads
      */
     public int getPoolSize() {
-        return (config & SMASK) + (short)(ctl >>> TC_SHIFT);
+        return ((mode & SMASK) + (short)(ctl >>> TC_SHIFT));
     }
 
     /**
@@ -2912,7 +2584,7 @@
      * @return {@code true} if this pool uses async mode
      */
     public boolean getAsyncMode() {
-        return (config & FIFO_QUEUE) != 0;
+        return (mode & FIFO) != 0;
     }
 
     /**
@@ -2924,8 +2596,9 @@
      * @return the number of worker threads
      */
     public int getRunningThreadCount() {
-        int rc = 0;
         WorkQueue[] ws; WorkQueue w;
+        VarHandle.acquireFence();
+        int rc = 0;
         if ((ws = workQueues) != null) {
             for (int i = 1; i < ws.length; i += 2) {
                 if ((w = ws[i]) != null && w.isApparentlyUnblocked())
@@ -2943,7 +2616,7 @@
      * @return the number of active threads
      */
     public int getActiveThreadCount() {
-        int r = (config & SMASK) + (int)(ctl >> AC_SHIFT);
+        int r = (mode & SMASK) + (int)(ctl >> RC_SHIFT);
         return (r <= 0) ? 0 : r; // suppress momentarily negative values
     }
 
@@ -2959,7 +2632,30 @@
      * @return {@code true} if all threads are currently idle
      */
     public boolean isQuiescent() {
-        return (config & SMASK) + (int)(ctl >> AC_SHIFT) <= 0;
+        for (;;) {
+            long c = ctl;
+            int md = mode, pc = md & SMASK;
+            int tc = pc + (short)(c >>> TC_SHIFT);
+            int rc = pc + (int)(c >> RC_SHIFT);
+            if ((md & (STOP | TERMINATED)) != 0)
+                return true;
+            else if (rc > 0)
+                return false;
+            else {
+                WorkQueue[] ws; WorkQueue v;
+                if ((ws = workQueues) != null) {
+                    for (int i = 1; i < ws.length; i += 2) {
+                        if ((v = ws[i]) != null) {
+                            if (v.source > 0)
+                                return false;
+                            --tc;
+                        }
+                    }
+                }
+                if (tc == 0 && ctl == c)
+                    return true;
+            }
+        }
     }
 
     /**
@@ -2974,13 +2670,12 @@
      * @return the number of steals
      */
     public long getStealCount() {
-        AuxState sc = auxState;
-        long count = (sc == null) ? 0L : sc.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;
+                    count += (long)w.nsteals & 0xffffffffL;
             }
         }
         return count;
@@ -2997,8 +2692,9 @@
      * @return the number of queued tasks
      */
     public long getQueuedTaskCount() {
-        long count = 0;
         WorkQueue[] ws; WorkQueue w;
+        VarHandle.acquireFence();
+        int count = 0;
         if ((ws = workQueues) != null) {
             for (int i = 1; i < ws.length; i += 2) {
                 if ((w = ws[i]) != null)
@@ -3016,8 +2712,9 @@
      * @return the number of queued submissions
      */
     public int getQueuedSubmissionCount() {
-        int count = 0;
         WorkQueue[] ws; WorkQueue w;
+        VarHandle.acquireFence();
+        int count = 0;
         if ((ws = workQueues) != null) {
             for (int i = 0; i < ws.length; i += 2) {
                 if ((w = ws[i]) != null)
@@ -3035,6 +2732,7 @@
      */
     public boolean hasQueuedSubmissions() {
         WorkQueue[] ws; WorkQueue w;
+        VarHandle.acquireFence();
         if ((ws = workQueues) != null) {
             for (int i = 0; i < ws.length; i += 2) {
                 if ((w = ws[i]) != null && !w.isEmpty())
@@ -3052,15 +2750,7 @@
      * @return the next submission, or {@code null} if none
      */
     protected ForkJoinTask<?> pollSubmission() {
-        WorkQueue[] ws; int wl; WorkQueue w; ForkJoinTask<?> t;
-        int r = ThreadLocalRandom.nextSecondarySeed();
-        if ((ws = workQueues) != null && (wl = ws.length) > 0) {
-            for (int m = wl - 1, i = 0; i < wl; ++i) {
-                if ((w = ws[(i << 1) & m]) != null && (t = w.poll()) != null)
-                    return t;
-            }
-        }
-        return null;
+        return pollScan(true);
     }
 
     /**
@@ -3081,8 +2771,9 @@
      * @return the number of elements transferred
      */
     protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
-        int count = 0;
         WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
+        VarHandle.acquireFence();
+        int count = 0;
         if ((ws = workQueues) != null) {
             for (int i = 0; i < ws.length; ++i) {
                 if ((w = ws[i]) != null) {
@@ -3105,10 +2796,10 @@
      */
     public String toString() {
         // Use a single pass through workQueues to collect counts
-        long qt = 0L, qs = 0L; int rc = 0;
-        AuxState sc = auxState;
-        long st = (sc == null) ? 0L : sc.stealCount;
+        int md = mode; // read volatile fields first
         long c = ctl;
+        long st = stealCount;
+        long qt = 0L, qs = 0L; int rc = 0;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
             for (int i = 0; i < ws.length; ++i) {
@@ -3118,22 +2809,22 @@
                         qs += size;
                     else {
                         qt += size;
-                        st += w.nsteals;
+                        st += (long)w.nsteals & 0xffffffffL;
                         if (w.isApparentlyUnblocked())
                             ++rc;
                     }
                 }
             }
         }
-        int pc = (config & SMASK);
+
+        int pc = (md & SMASK);
         int tc = pc + (short)(c >>> TC_SHIFT);
-        int ac = pc + (int)(c >> AC_SHIFT);
+        int ac = pc + (int)(c >> RC_SHIFT);
         if (ac < 0) // ignore transient negative
             ac = 0;
-        int rs = runState;
-        String level = ((rs & TERMINATED) != 0 ? "Terminated" :
-                        (rs & STOP)       != 0 ? "Terminating" :
-                        (rs & SHUTDOWN)   != 0 ? "Shutting down" :
+        String level = ((md & TERMINATED) != 0 ? "Terminated" :
+                        (md & STOP)       != 0 ? "Terminating" :
+                        (md & SHUTDOWN)   != 0 ? "Shutting down" :
                         "Running");
         return super.toString() +
             "[" + level +
@@ -3196,7 +2887,7 @@
      * @return {@code true} if all tasks have completed following shut down
      */
     public boolean isTerminated() {
-        return (runState & TERMINATED) != 0;
+        return (mode & TERMINATED) != 0;
     }
 
     /**
@@ -3213,8 +2904,8 @@
      * @return {@code true} if terminating but not yet terminated
      */
     public boolean isTerminating() {
-        int rs = runState;
-        return (rs & STOP) != 0 && (rs & TERMINATED) == 0;
+        int md = mode;
+        return (md & STOP) != 0 && (md & TERMINATED) == 0;
     }
 
     /**
@@ -3223,7 +2914,7 @@
      * @return {@code true} if this pool has been shut down
      */
     public boolean isShutdown() {
-        return (runState & SHUTDOWN) != 0;
+        return (mode & SHUTDOWN) != 0;
     }
 
     /**
@@ -3287,30 +2978,19 @@
             helpQuiescePool(wt.workQueue);
             return true;
         }
-        long startTime = System.nanoTime();
-        WorkQueue[] ws;
-        int r = 0, wl;
-        boolean found = true;
-        while (!isQuiescent() && (ws = workQueues) != null &&
-               (wl = ws.length) > 0) {
-            if (!found) {
-                if ((System.nanoTime() - startTime) > nanos)
+        else {
+            for (long startTime = System.nanoTime();;) {
+                ForkJoinTask<?> t;
+                if ((t = pollScan(false)) != null)
+                    t.doExec();
+                else if (isQuiescent())
+                    return true;
+                else if ((System.nanoTime() - startTime) > nanos)
                     return false;
-                Thread.yield(); // cannot block
-            }
-            found = false;
-            for (int m = wl - 1, j = (m + 1) << 2; j >= 0; --j) {
-                ForkJoinTask<?> t; WorkQueue q; int b, k;
-                if ((k = r++ & m) <= m && k >= 0 && (q = ws[k]) != null &&
-                    (b = q.base) - q.top < 0) {
-                    found = true;
-                    if ((t = q.pollAt(b)) != null)
-                        t.doExec();
-                    break;
-                }
+                else
+                    Thread.yield(); // cannot block
             }
         }
-        return true;
     }
 
     /**
@@ -3423,19 +3103,22 @@
      */
     public static void managedBlock(ManagedBlocker blocker)
         throws InterruptedException {
+        if (blocker == null) throw new NullPointerException();
         ForkJoinPool p;
         ForkJoinWorkerThread wt;
+        WorkQueue w;
         Thread t = Thread.currentThread();
         if ((t instanceof ForkJoinWorkerThread) &&
-            (p = (wt = (ForkJoinWorkerThread)t).pool) != null) {
-            WorkQueue w = wt.workQueue;
+            (p = (wt = (ForkJoinWorkerThread)t).pool) != null &&
+            (w = wt.workQueue) != null) {
+            int block;
             while (!blocker.isReleasable()) {
-                if (p.tryCompensate(w)) {
+                if ((block = p.tryCompensate(w)) != 0) {
                     try {
                         do {} while (!blocker.isReleasable() &&
                                      !blocker.block());
                     } finally {
-                        U.getAndAddLong(p, CTL, AC_UNIT);
+                        CTL.getAndAdd(p, (block > 0) ? RC_UNIT : 0L);
                     }
                     break;
                 }
@@ -3447,6 +3130,29 @@
         }
     }
 
+    /**
+     * If the given executor is a ForkJoinPool, poll and execute
+     * AsynchronousCompletionTasks from worker's queue until none are
+     * available or blocker is released.
+     */
+    static void helpAsyncBlocker(Executor e, ManagedBlocker blocker) {
+        if (e instanceof ForkJoinPool) {
+            WorkQueue w; ForkJoinWorkerThread wt; WorkQueue[] ws; int r, n;
+            ForkJoinPool p = (ForkJoinPool)e;
+            Thread thread = Thread.currentThread();
+            if (thread instanceof ForkJoinWorkerThread &&
+                (wt = (ForkJoinWorkerThread)thread).pool == p)
+                w = wt.workQueue;
+            else if ((r = ThreadLocalRandom.getProbe()) != 0 &&
+                     (ws = p.workQueues) != null && (n = ws.length) > 0)
+                w = ws[(n - 1) & r & SQMASK];
+            else
+                w = null;
+            if (w != null)
+                w.helpAsyncBlocker(blocker);
+        }
+    }
+
     // AbstractExecutorService overrides.  These rely on undocumented
     // fact that ForkJoinTask.adapt returns ForkJoinTasks that also
     // implement RunnableFuture.
@@ -3459,26 +3165,19 @@
         return new ForkJoinTask.AdaptedCallable<T>(callable);
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long CTL;
-    private static final long RUNSTATE;
-    private static final int ABASE;
-    private static final int ASHIFT;
+    // VarHandle mechanics
+    private static final VarHandle CTL;
+    private static final VarHandle MODE;
+    static final VarHandle QA;
 
     static {
         try {
-            CTL = U.objectFieldOffset
-                (ForkJoinPool.class.getDeclaredField("ctl"));
-            RUNSTATE = U.objectFieldOffset
-                (ForkJoinPool.class.getDeclaredField("runState"));
-            ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
-            int scale = U.arrayIndexScale(ForkJoinTask[].class);
-            if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
-            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            CTL = l.findVarHandle(ForkJoinPool.class, "ctl", long.class);
+            MODE = l.findVarHandle(ForkJoinPool.class, "mode", int.class);
+            QA = MethodHandles.arrayElementVarHandle(ForkJoinTask[].class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
 
         // Reduce the risk of rare disastrous classloading in first call to
@@ -3498,52 +3197,11 @@
             new DefaultForkJoinWorkerThreadFactory();
         modifyThreadPermission = new RuntimePermission("modifyThread");
 
-        common = java.security.AccessController.doPrivileged
-            (new java.security.PrivilegedAction<ForkJoinPool>() {
-                public ForkJoinPool run() { return makeCommonPool(); }});
+        common = AccessController.doPrivileged(new PrivilegedAction<>() {
+            public ForkJoinPool run() {
+                return new ForkJoinPool((byte)0); }});
 
-        // report 1 even if threads disabled
-        COMMON_PARALLELISM = Math.max(common.config & SMASK, 1);
-    }
-
-    /**
-     * Creates and returns the common pool, respecting user settings
-     * specified via system properties.
-     */
-    static ForkJoinPool makeCommonPool() {
-        int parallelism = -1;
-        ForkJoinWorkerThreadFactory factory = null;
-        UncaughtExceptionHandler handler = null;
-        try {  // ignore exceptions in accessing/parsing properties
-            String pp = System.getProperty
-                ("java.util.concurrent.ForkJoinPool.common.parallelism");
-            String fp = System.getProperty
-                ("java.util.concurrent.ForkJoinPool.common.threadFactory");
-            String hp = System.getProperty
-                ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
-            if (pp != null)
-                parallelism = Integer.parseInt(pp);
-            if (fp != null)
-                factory = ((ForkJoinWorkerThreadFactory)ClassLoader.
-                           getSystemClassLoader().loadClass(fp).newInstance());
-            if (hp != null)
-                handler = ((UncaughtExceptionHandler)ClassLoader.
-                           getSystemClassLoader().loadClass(hp).newInstance());
-        } catch (Exception ignore) {
-        }
-        if (factory == null) {
-            if (System.getSecurityManager() == null)
-                factory = defaultForkJoinWorkerThreadFactory;
-            else // use security-managed default
-                factory = new InnocuousForkJoinWorkerThreadFactory();
-        }
-        if (parallelism < 0 && // default 1 less than #cores
-            (parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)
-            parallelism = 1;
-        if (parallelism > MAX_CAP)
-            parallelism = MAX_CAP;
-        return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE,
-                                "ForkJoinPool.commonPool-worker-");
+        COMMON_PARALLELISM = Math.max(common.mode & SMASK, 1);
     }
 
     /**
@@ -3556,27 +3214,20 @@
          * An ACC to restrict permissions for the factory itself.
          * The constructed workers have no permissions set.
          */
-        private static final AccessControlContext innocuousAcc;
-        static {
-            Permissions innocuousPerms = new Permissions();
-            innocuousPerms.add(modifyThreadPermission);
-            innocuousPerms.add(new RuntimePermission(
-                                   "enableContextClassLoaderOverride"));
-            innocuousPerms.add(new RuntimePermission(
-                                   "modifyThreadGroup"));
-            innocuousAcc = new AccessControlContext(new ProtectionDomain[] {
-                    new ProtectionDomain(null, innocuousPerms)
-                });
-        }
+        private static final AccessControlContext ACC = contextWithPermissions(
+            modifyThreadPermission,
+            new RuntimePermission("enableContextClassLoaderOverride"),
+            new RuntimePermission("modifyThreadGroup"),
+            new RuntimePermission("getClassLoader"),
+            new RuntimePermission("setContextClassLoader"));
 
         public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
-            return java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
+            return AccessController.doPrivileged(
+                new PrivilegedAction<>() {
                     public ForkJoinWorkerThread run() {
                         return new ForkJoinWorkerThread.
-                            InnocuousForkJoinWorkerThread(pool);
-                    }}, innocuousAcc);
+                            InnocuousForkJoinWorkerThread(pool); }},
+                ACC);
         }
     }
-
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java b/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java
index efccfa5..fd28e84 100644
--- a/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java
+++ b/ojluni/src/main/java/java/util/concurrent/ForkJoinTask.java
@@ -36,6 +36,8 @@
 package java.util.concurrent;
 
 import java.io.Serializable;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Constructor;
@@ -96,7 +98,7 @@
  * 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
+ * but doing so 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
@@ -136,11 +138,11 @@
  * {@link #isCompletedNormally} is true if a task completed without
  * cancellation or encountering an exception; {@link #isCancelled} is
  * true if the task was cancelled (in which case {@link #getException}
- * returns a {@link java.util.concurrent.CancellationException}); and
+ * returns a {@link CancellationException}); and
  * {@link #isCompletedAbnormally} is true if a task was either
  * cancelled or encountered an exception, in which case {@link
  * #getException} will return either the encountered exception or
- * {@link java.util.concurrent.CancellationException}.
+ * {@link CancellationException}.
  *
  * <p>The ForkJoinTask class is not usually directly subclassed.
  * Instead, you subclass one of the abstract classes that support a
@@ -221,52 +223,59 @@
      * methods in a way that flows well in javadocs.
      */
 
-    /*
+    /**
      * 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 (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.
+     * single int to ensure atomicity.  Status is initially zero, and
+     * takes on nonnegative values until completed, upon which it
+     * holds (sign bit) DONE, possibly with ABNORMAL (cancelled or
+     * exceptional) and THROWN (in which case an exception has been
+     * stored). Tasks with dependent blocked waiting joiners have the
+     * SIGNAL bit set.  Completion of a task with SIGNAL set awakens
+     * any waiters via notifyAll. (Waiters also help signal others
+     * upon completion.)
      *
      * 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
-    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
+
+    private static final int DONE     = 1 << 31; // must be negative
+    private static final int ABNORMAL = 1 << 18; // set atomically with DONE
+    private static final int THROWN   = 1 << 17; // set atomically with ABNORMAL
+    private static final int SIGNAL   = 1 << 16; // true if joiner waiting
+    private static final int SMASK    = 0xffff;  // short bits for tags
+
+    static boolean isExceptionalStatus(int s) {  // needed by subclasses
+        return (s & THROWN) != 0;
+    }
 
     /**
-     * Marks completion and wakes up threads waiting to join this
-     * task.
+     * Sets DONE status and wakes up threads waiting to join this task.
      *
-     * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
-     * @return completion status on exit
+     * @return status on exit
      */
-    private int setCompletion(int completion) {
-        for (int s;;) {
+    private int setDone() {
+        int s;
+        if (((s = (int)STATUS.getAndBitwiseOr(this, DONE)) & SIGNAL) != 0)
+            synchronized (this) { notifyAll(); }
+        return s | DONE;
+    }
+
+    /**
+     * Marks cancelled or exceptional completion unless already done.
+     *
+     * @param completion must be DONE | ABNORMAL, ORed with THROWN if exceptional
+     * @return status on exit
+     */
+    private int abnormalCompletion(int completion) {
+        for (int s, ns;;) {
             if ((s = status) < 0)
                 return s;
-            if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
-                if ((s >>> 16) != 0)
+            else if (STATUS.weakCompareAndSet(this, s, ns = s | completion)) {
+                if ((s & SIGNAL) != 0)
                     synchronized (this) { notifyAll(); }
-                return completion;
+                return ns;
             }
         }
     }
@@ -284,10 +293,11 @@
             try {
                 completed = exec();
             } catch (Throwable rex) {
-                return setExceptionalCompletion(rex);
+                completed = false;
+                s = setExceptionalCompletion(rex);
             }
             if (completed)
-                s = setCompletion(NORMAL);
+                s = setDone();
         }
         return s;
     }
@@ -299,9 +309,7 @@
      * @param timeout using Object.wait conventions.
      */
     final void internalWait(long timeout) {
-        int s;
-        if ((s = status) >= 0 && // force completer to issue notify
-            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+        if ((int)STATUS.getAndBitwiseOr(this, SIGNAL) >= 0) {
             synchronized (this) {
                 if (status >= 0)
                     try { wait(timeout); } catch (InterruptedException ie) { }
@@ -316,27 +324,24 @@
      * @return status upon completion
      */
     private int externalAwaitDone() {
-        int s = ((this instanceof CountedCompleter) ? // try helping
-                 ForkJoinPool.common.externalHelpComplete(
-                     (CountedCompleter<?>)this, 0) :
-                 ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
-        if (s >= 0 && (s = status) >= 0) {
+        int s = tryExternalHelp();
+        if (s >= 0 && (s = (int)STATUS.getAndBitwiseOr(this, SIGNAL)) >= 0) {
             boolean interrupted = false;
-            do {
-                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                    synchronized (this) {
-                        if (status >= 0) {
-                            try {
-                                wait(0L);
-                            } catch (InterruptedException ie) {
-                                interrupted = true;
-                            }
+            synchronized (this) {
+                for (;;) {
+                    if ((s = status) >= 0) {
+                        try {
+                            wait(0L);
+                        } catch (InterruptedException ie) {
+                            interrupted = true;
                         }
-                        else
-                            notifyAll();
+                    }
+                    else {
+                        notifyAll();
+                        break;
                     }
                 }
-            } while ((s = status) >= 0);
+            }
             if (interrupted)
                 Thread.currentThread().interrupt();
         }
@@ -347,30 +352,40 @@
      * Blocks a non-worker-thread until completion or interruption.
      */
     private int externalInterruptibleAwaitDone() throws InterruptedException {
-        int s;
-        if (Thread.interrupted())
-            throw new InterruptedException();
-        if ((s = status) >= 0 &&
-            (s = ((this instanceof CountedCompleter) ?
-                  ForkJoinPool.common.externalHelpComplete(
-                      (CountedCompleter<?>)this, 0) :
-                  ForkJoinPool.common.tryExternalUnpush(this) ? doExec() :
-                  0)) >= 0) {
-            while ((s = status) >= 0) {
-                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
-                    synchronized (this) {
-                        if (status >= 0)
-                            wait(0L);
-                        else
-                            notifyAll();
+        int s = tryExternalHelp();
+        if (s >= 0 && (s = (int)STATUS.getAndBitwiseOr(this, SIGNAL)) >= 0) {
+            synchronized (this) {
+                for (;;) {
+                    if ((s = status) >= 0)
+                        wait(0L);
+                    else {
+                        notifyAll();
+                        break;
                     }
                 }
             }
         }
+        else if (Thread.interrupted())
+            throw new InterruptedException();
         return s;
     }
 
     /**
+     * Tries to help with tasks allowed for external callers.
+     *
+     * @return current status
+     */
+    private int tryExternalHelp() {
+        int s;
+        return ((s = status) < 0 ? s:
+                (this instanceof CountedCompleter) ?
+                ForkJoinPool.common.externalHelpComplete(
+                    (CountedCompleter<?>)this, 0) :
+                ForkJoinPool.common.tryExternalUnpush(this) ?
+                doExec() : 0);
+    }
+
+    /**
      * Implementation for join, get, quietlyJoin. Directly handles
      * only cases of already-completed, external wait, and
      * unfork+exec.  Others are relayed to ForkJoinPool.awaitJoin.
@@ -404,22 +419,24 @@
     // Exception table support
 
     /**
-     * Table of exceptions thrown by tasks, to enable reporting by
-     * callers. Because exceptions are rare, we don't directly keep
+     * Hash table of exceptions thrown by tasks, to enable reporting
+     * by callers. Because exceptions are rare, we don't directly keep
      * them with task objects, but instead use a weak ref table.  Note
      * that cancellation exceptions don't appear in the table, but are
      * instead recorded as status values.
      *
-     * Note: These statics are initialized below in static block.
+     * The exception table has a fixed capacity.
      */
-    private static final ExceptionNode[] exceptionTable;
-    private static final ReentrantLock exceptionTableLock;
-    private static final ReferenceQueue<Object> exceptionTableRefQueue;
+    private static final ExceptionNode[] exceptionTable
+        = new ExceptionNode[32];
 
-    /**
-     * Fixed capacity for exceptionTable.
-     */
-    private static final int EXCEPTION_MAP_CAPACITY = 32;
+    /** Lock protecting access to exceptionTable. */
+    private static final ReentrantLock exceptionTableLock
+        = new ReentrantLock();
+
+    /** Reference queue of stale exceptionally completed tasks. */
+    private static final ReferenceQueue<ForkJoinTask<?>> exceptionTableRefQueue
+        = new ReferenceQueue<>();
 
     /**
      * Key-value nodes for exception table.  The chained hash table
@@ -439,7 +456,7 @@
         final long thrower;  // use id not ref to avoid weak cycles
         final int hashCode;  // store task hashCode before weak ref disappears
         ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next,
-                      ReferenceQueue<Object> exceptionTableRefQueue) {
+                      ReferenceQueue<ForkJoinTask<?>> exceptionTableRefQueue) {
             super(task, exceptionTableRefQueue);
             this.ex = ex;
             this.next = next;
@@ -475,7 +492,7 @@
             } finally {
                 lock.unlock();
             }
-            s = setCompletion(EXCEPTIONAL);
+            s = abnormalCompletion(DONE | ABNORMAL | THROWN);
         }
         return s;
     }
@@ -487,7 +504,7 @@
      */
     private int setExceptionalCompletion(Throwable ex) {
         int s = recordExceptionalCompletion(ex);
-        if ((s & DONE_MASK) == EXCEPTIONAL)
+        if ((s & THROWN) != 0)
             internalPropagateException(ex);
         return s;
     }
@@ -603,9 +620,8 @@
     private static void expungeStaleExceptions() {
         for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
             if (x instanceof ExceptionNode) {
-                int hashCode = ((ExceptionNode)x).hashCode;
                 ExceptionNode[] t = exceptionTable;
-                int i = hashCode & (t.length - 1);
+                int i = ((ExceptionNode)x).hashCode & (t.length - 1);
                 ExceptionNode e = t[i];
                 ExceptionNode pred = null;
                 while (e != null) {
@@ -663,10 +679,8 @@
      * Throws exception, if any, associated with the given status.
      */
     private void reportException(int s) {
-        if (s == CANCELLED)
-            throw new CancellationException();
-        if (s == EXCEPTIONAL)
-            rethrow(getThrowableException());
+        rethrow((s & THROWN) != 0 ? getThrowableException() :
+                new CancellationException());
     }
 
     // public methods
@@ -696,19 +710,19 @@
     }
 
     /**
-     * Returns the result of the computation when it {@link #isDone is
-     * done}.  This method differs from {@link #get()} in that
-     * abnormal completion results in {@code RuntimeException} or
-     * {@code Error}, not {@code ExecutionException}, and that
-     * interrupts of the calling thread do <em>not</em> cause the
-     * method to abruptly return by throwing {@code
-     * InterruptedException}.
+     * Returns the result of the computation when it
+     * {@linkplain #isDone is done}.
+     * This method differs from {@link #get()} in that abnormal
+     * completion results in {@code RuntimeException} or {@code Error},
+     * not {@code ExecutionException}, and that interrupts of the
+     * calling thread do <em>not</em> cause the method to abruptly
+     * return by throwing {@code InterruptedException}.
      *
      * @return the computed result
      */
     public final V join() {
         int s;
-        if ((s = doJoin() & DONE_MASK) != NORMAL)
+        if (((s = doJoin()) & ABNORMAL) != 0)
             reportException(s);
         return getRawResult();
     }
@@ -723,7 +737,7 @@
      */
     public final V invoke() {
         int s;
-        if ((s = doInvoke() & DONE_MASK) != NORMAL)
+        if (((s = doInvoke()) & ABNORMAL) != 0)
             reportException(s);
         return getRawResult();
     }
@@ -748,9 +762,9 @@
     public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
         int s1, s2;
         t2.fork();
-        if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL)
+        if (((s1 = t1.doInvoke()) & ABNORMAL) != 0)
             t1.reportException(s1);
-        if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL)
+        if (((s2 = t2.doJoin()) & ABNORMAL) != 0)
             t2.reportException(s2);
     }
 
@@ -780,7 +794,7 @@
             }
             else if (i != 0)
                 t.fork();
-            else if (t.doInvoke() < NORMAL && ex == null)
+            else if ((t.doInvoke() & ABNORMAL) != 0 && ex == null)
                 ex = t.getException();
         }
         for (int i = 1; i <= last; ++i) {
@@ -788,7 +802,7 @@
             if (t != null) {
                 if (ex != null)
                     t.cancel(false);
-                else if (t.doJoin() < NORMAL)
+                else if ((t.doJoin() & ABNORMAL) != 0)
                     ex = t.getException();
             }
         }
@@ -816,7 +830,7 @@
      */
     public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> tasks) {
         if (!(tasks instanceof RandomAccess) || !(tasks instanceof List<?>)) {
-            invokeAll(tasks.toArray(new ForkJoinTask<?>[tasks.size()]));
+            invokeAll(tasks.toArray(new ForkJoinTask<?>[0]));
             return tasks;
         }
         @SuppressWarnings("unchecked")
@@ -832,7 +846,7 @@
             }
             else if (i != 0)
                 t.fork();
-            else if (t.doInvoke() < NORMAL && ex == null)
+            else if ((t.doInvoke() & ABNORMAL) != 0 && ex == null)
                 ex = t.getException();
         }
         for (int i = 1; i <= last; ++i) {
@@ -840,7 +854,7 @@
             if (t != null) {
                 if (ex != null)
                     t.cancel(false);
-                else if (t.doJoin() < NORMAL)
+                else if ((t.doJoin() & ABNORMAL) != 0)
                     ex = t.getException();
             }
         }
@@ -877,7 +891,8 @@
      * @return {@code true} if this task is now cancelled
      */
     public boolean cancel(boolean mayInterruptIfRunning) {
-        return (setCompletion(CANCELLED) & DONE_MASK) == CANCELLED;
+        int s = abnormalCompletion(DONE | ABNORMAL);
+        return (s & (ABNORMAL | THROWN)) == ABNORMAL;
     }
 
     public final boolean isDone() {
@@ -885,7 +900,7 @@
     }
 
     public final boolean isCancelled() {
-        return (status & DONE_MASK) == CANCELLED;
+        return (status & (ABNORMAL | THROWN)) == ABNORMAL;
     }
 
     /**
@@ -894,7 +909,7 @@
      * @return {@code true} if this task threw an exception or was cancelled
      */
     public final boolean isCompletedAbnormally() {
-        return status < NORMAL;
+        return (status & ABNORMAL) != 0;
     }
 
     /**
@@ -905,7 +920,7 @@
      * exception and was not cancelled
      */
     public final boolean isCompletedNormally() {
-        return (status & DONE_MASK) == NORMAL;
+        return (status & (DONE | ABNORMAL)) == DONE;
     }
 
     /**
@@ -916,9 +931,9 @@
      * @return the exception, or {@code null} if none
      */
     public final Throwable getException() {
-        int s = status & DONE_MASK;
-        return ((s >= NORMAL)    ? null :
-                (s == CANCELLED) ? new CancellationException() :
+        int s = status;
+        return ((s & ABNORMAL) == 0 ? null :
+                (s & THROWN)   == 0 ? new CancellationException() :
                 getThrowableException());
     }
 
@@ -962,7 +977,7 @@
             setExceptionalCompletion(rex);
             return;
         }
-        setCompletion(NORMAL);
+        setDone();
     }
 
     /**
@@ -974,7 +989,7 @@
      * @since 1.8
      */
     public final void quietlyComplete() {
-        setCompletion(NORMAL);
+        setDone();
     }
 
     /**
@@ -991,11 +1006,12 @@
     public final V get() throws InterruptedException, ExecutionException {
         int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
             doJoin() : externalInterruptibleAwaitDone();
-        if ((s &= DONE_MASK) == CANCELLED)
-            throw new CancellationException();
-        if (s == EXCEPTIONAL)
+        if ((s & THROWN) != 0)
             throw new ExecutionException(getThrowableException());
-        return getRawResult();
+        else if ((s & ABNORMAL) != 0)
+            throw new CancellationException();
+        else
+            return getRawResult();
     }
 
     /**
@@ -1035,7 +1051,7 @@
                 while ((s = status) >= 0 &&
                        (ns = deadline - System.nanoTime()) > 0L) {
                     if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
-                        U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                        (s = (int)STATUS.getAndBitwiseOr(this, SIGNAL)) >= 0) {
                         synchronized (this) {
                             if (status >= 0)
                                 wait(ms); // OK to throw InterruptedException
@@ -1047,15 +1063,13 @@
             }
         }
         if (s >= 0)
-            s = status;
-        if ((s &= DONE_MASK) != NORMAL) {
-            if (s == CANCELLED)
-                throw new CancellationException();
-            if (s != EXCEPTIONAL)
-                throw new TimeoutException();
+            throw new TimeoutException();
+        else if ((s & THROWN) != 0)
             throw new ExecutionException(getThrowableException());
-        }
-        return getRawResult();
+        else if ((s & ABNORMAL) != 0)
+            throw new CancellationException();
+        else
+            return getRawResult();
     }
 
     /**
@@ -1111,7 +1125,7 @@
      * setRawResult(null)}.
      */
     public void reinitialize() {
-        if ((status & DONE_MASK) == EXCEPTIONAL)
+        if ((status & THROWN) != 0)
             clearExceptionalCompletion();
         else
             status = 0;
@@ -1329,8 +1343,8 @@
      */
     public final short setForkJoinTaskTag(short newValue) {
         for (int s;;) {
-            if (U.compareAndSwapInt(this, STATUS, s = status,
-                                    (s & ~SMASK) | (newValue & SMASK)))
+            if (STATUS.weakCompareAndSet(this, s = status,
+                                         (s & ~SMASK) | (newValue & SMASK)))
                 return (short)s;
         }
     }
@@ -1353,8 +1367,8 @@
         for (int s;;) {
             if ((short)(s = status) != expect)
                 return false;
-            if (U.compareAndSwapInt(this, STATUS, s,
-                                    (s & ~SMASK) | (update & SMASK)))
+            if (STATUS.weakCompareAndSet(this, s,
+                                         (s & ~SMASK) | (update & SMASK)))
                 return true;
         }
     }
@@ -1377,6 +1391,9 @@
         public final void setRawResult(T v) { result = v; }
         public final boolean exec() { runnable.run(); return true; }
         public final void run() { invoke(); }
+        public String toString() {
+            return super.toString() + "[Wrapped task = " + runnable + "]";
+        }
         private static final long serialVersionUID = 5232453952276885070L;
     }
 
@@ -1394,6 +1411,9 @@
         public final void setRawResult(Void v) { }
         public final boolean exec() { runnable.run(); return true; }
         public final void run() { invoke(); }
+        public String toString() {
+            return super.toString() + "[Wrapped task = " + runnable + "]";
+        }
         private static final long serialVersionUID = 5232453952276885070L;
     }
 
@@ -1439,6 +1459,9 @@
             }
         }
         public final void run() { invoke(); }
+        public String toString() {
+            return super.toString() + "[Wrapped task = " + callable + "]";
+        }
         private static final long serialVersionUID = 2838392045355241008L;
     }
 
@@ -1515,19 +1538,14 @@
             setExceptionalCompletion((Throwable)ex);
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long STATUS;
-
+    // VarHandle mechanics
+    private static final VarHandle STATUS;
     static {
-        exceptionTableLock = new ReentrantLock();
-        exceptionTableRefQueue = new ReferenceQueue<Object>();
-        exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
         try {
-            STATUS = U.objectFieldOffset
-                (ForkJoinTask.class.getDeclaredField("status"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATUS = l.findVarHandle(ForkJoinTask.class, "status", int.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 
diff --git a/ojluni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java b/ojluni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
index e98ba99..26c6db1 100644
--- a/ojluni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/ojluni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
@@ -36,6 +36,8 @@
 package java.util.concurrent;
 
 import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 
 /**
@@ -47,7 +49,9 @@
  * and termination methods surrounding the main task processing loop.
  * If you do create such a subclass, you will also need to supply a
  * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
- * {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}.
+ * {@linkplain ForkJoinPool#ForkJoinPool(int, ForkJoinWorkerThreadFactory,
+ * UncaughtExceptionHandler, boolean, int, int, int, Predicate, long, TimeUnit)
+ * use it} in a {@code ForkJoinPool}.
  *
  * @since 1.7
  * @author Doug Lea
@@ -66,13 +70,19 @@
      * owning thread.
      *
      * Support for (non-public) subclass InnocuousForkJoinWorkerThread
-     * requires that we break quite a lot of encapsulation (via Unsafe)
-     * both here and in the subclass to access and set Thread fields.
+     * requires that we break quite a lot of encapsulation (via helper
+     * methods in ThreadLocalRandom) both here and in the subclass to
+     * access and set Thread fields.
      */
 
     final ForkJoinPool pool;                // the pool this thread works in
     final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
 
+    /** An AccessControlContext supporting no privileges */
+    private static final AccessControlContext INNOCUOUS_ACC =
+        new AccessControlContext(
+            new ProtectionDomain[] { new ProtectionDomain(null, null) });
+
     /**
      * Creates a ForkJoinWorkerThread operating in the given pool.
      *
@@ -87,13 +97,29 @@
     }
 
     /**
+     * Version for use by the default pool.  Supports setting the
+     * context class loader.  This is a separate constructor to avoid
+     * affecting the protected constructor.
+     */
+    ForkJoinWorkerThread(ForkJoinPool pool, ClassLoader ccl) {
+        super("aForkJoinWorkerThread");
+        super.setContextClassLoader(ccl);
+        ThreadLocalRandom.setInheritedAccessControlContext(this, INNOCUOUS_ACC);
+        this.pool = pool;
+        this.workQueue = pool.registerWorker(this);
+    }
+
+    /**
      * Version for InnocuousForkJoinWorkerThread.
      */
-    ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
+    ForkJoinWorkerThread(ForkJoinPool pool,
+                         ClassLoader ccl,
+                         ThreadGroup threadGroup,
                          AccessControlContext acc) {
         super(threadGroup, null, "aForkJoinWorkerThread");
-        U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
-        eraseThreadLocals(); // clear before registering
+        super.setContextClassLoader(ccl);
+        ThreadLocalRandom.setInheritedAccessControlContext(this, acc);
+        ThreadLocalRandom.eraseThreadLocals(this); // clear before registering
         this.pool = pool;
         this.workQueue = pool.registerWorker(this);
     }
@@ -171,66 +197,39 @@
     }
 
     /**
-     * Erases ThreadLocals by nulling out Thread maps.
-     */
-    final void eraseThreadLocals() {
-        U.putObject(this, THREADLOCALS, null);
-        U.putObject(this, INHERITABLETHREADLOCALS, null);
-    }
-
-    /**
      * Non-public hook method for InnocuousForkJoinWorkerThread.
      */
     void afterTopLevelExec() {
     }
 
-    // Set up to allow setting thread fields in constructor
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long THREADLOCALS;
-    private static final long INHERITABLETHREADLOCALS;
-    private static final long INHERITEDACCESSCONTROLCONTEXT;
-    static {
-        try {
-            THREADLOCALS = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocals"));
-            INHERITABLETHREADLOCALS = U.objectFieldOffset
-                (Thread.class.getDeclaredField("inheritableThreadLocals"));
-            INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
-                (Thread.class.getDeclaredField("inheritedAccessControlContext"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
     /**
      * A worker thread that has no permissions, is not a member of any
-     * user-defined ThreadGroup, and erases all ThreadLocals after
+     * user-defined ThreadGroup, uses the system class loader as
+     * thread context class loader, and erases all ThreadLocals after
      * running each top-level task.
      */
     static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
         /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
         private static final ThreadGroup innocuousThreadGroup =
-            createThreadGroup();
-
-        /** An AccessControlContext supporting no privileges */
-        private static final AccessControlContext INNOCUOUS_ACC =
-            new AccessControlContext(
-                new ProtectionDomain[] {
-                    new ProtectionDomain(null, null)
-                });
+            AccessController.doPrivileged(new PrivilegedAction<>() {
+                public ThreadGroup run() {
+                    ThreadGroup group = Thread.currentThread().getThreadGroup();
+                    for (ThreadGroup p; (p = group.getParent()) != null; )
+                        group = p;
+                    return new ThreadGroup(
+                        group, "InnocuousForkJoinWorkerThreadGroup");
+                }});
 
         InnocuousForkJoinWorkerThread(ForkJoinPool pool) {
-            super(pool, innocuousThreadGroup, INNOCUOUS_ACC);
+            super(pool,
+                  ClassLoader.getSystemClassLoader(),
+                  innocuousThreadGroup,
+                  INNOCUOUS_ACC);
         }
 
         @Override // to erase ThreadLocals
         void afterTopLevelExec() {
-            eraseThreadLocals();
-        }
-
-        @Override // to always report system loader
-        public ClassLoader getContextClassLoader() {
-            return ClassLoader.getSystemClassLoader();
+            ThreadLocalRandom.eraseThreadLocals(this);
         }
 
         @Override // to silently fail
@@ -240,34 +239,5 @@
         public void setContextClassLoader(ClassLoader cl) {
             throw new SecurityException("setContextClassLoader");
         }
-
-        /**
-         * Returns a new group with the system ThreadGroup (the
-         * topmost, parent-less group) as parent.  Uses Unsafe to
-         * traverse Thread.group and ThreadGroup.parent fields.
-         */
-        private static ThreadGroup createThreadGroup() {
-            try {
-                sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
-                long tg = u.objectFieldOffset
-                    (Thread.class.getDeclaredField("group"));
-                long gp = u.objectFieldOffset
-                    (ThreadGroup.class.getDeclaredField("parent"));
-                ThreadGroup group = (ThreadGroup)
-                    u.getObject(Thread.currentThread(), tg);
-                while (group != null) {
-                    ThreadGroup parent = (ThreadGroup)u.getObject(group, gp);
-                    if (parent == null)
-                        return new ThreadGroup(group,
-                                               "InnocuousForkJoinWorkerThreadGroup");
-                    group = parent;
-                }
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-            // fall through if null as cannot-happen safeguard
-            throw new Error("Cannot create ThreadGroup");
-        }
     }
-
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/Future.java b/ojluni/src/main/java/java/util/concurrent/Future.java
index 9bd05d6..6099c7c 100644
--- a/ojluni/src/main/java/java/util/concurrent/Future.java
+++ b/ojluni/src/main/java/java/util/concurrent/Future.java
@@ -50,8 +50,7 @@
  * declare types of the form {@code Future<?>} and
  * return {@code null} as a result of the underlying task.
  *
- * <p>
- * <b>Sample Usage</b> (Note that the following classes are all
+ * <p><b>Sample Usage</b> (Note that the following classes are all
  * made-up.)
  *
  * <pre> {@code
@@ -59,13 +58,9 @@
  * class App {
  *   ExecutorService executor = ...
  *   ArchiveSearcher searcher = ...
- *   void showSearch(final String target)
- *       throws InterruptedException {
- *     Future<String> future
- *       = executor.submit(new Callable<String>() {
- *         public String call() {
- *             return searcher.search(target);
- *         }});
+ *   void showSearch(String target) throws InterruptedException {
+ *     Callable<String> task = () -> searcher.search(target);
+ *     Future<String> future = executor.submit(task);
  *     displayOtherThings(); // do other things while searching
  *     try {
  *       displayText(future.get()); // use future
@@ -77,11 +72,7 @@
  * 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<>(new Callable<String>() {
- *     public String call() {
- *       return searcher.search(target);
- *   }});
+ * FutureTask<String> future = new FutureTask<>(task);
  * executor.execute(future);}</pre>
  *
  * <p>Memory consistency effects: Actions taken by the asynchronous computation
diff --git a/ojluni/src/main/java/java/util/concurrent/FutureTask.java b/ojluni/src/main/java/java/util/concurrent/FutureTask.java
index 62c2bfc..e913ef3 100644
--- a/ojluni/src/main/java/java/util/concurrent/FutureTask.java
+++ b/ojluni/src/main/java/java/util/concurrent/FutureTask.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.locks.LockSupport;
 
 /**
@@ -69,9 +71,6 @@
      * cancellation races. Sync control in the current design relies
      * on a "state" field updated via CAS to track completion, along
      * with a simple Treiber stack to hold waiting threads.
-     *
-     * Style note: As usual, we bypass overhead of using
-     * AtomicXFieldUpdaters and instead directly use Unsafe intrinsics.
      */
 
     /**
@@ -163,9 +162,8 @@
     }
 
     public boolean cancel(boolean mayInterruptIfRunning) {
-        if (!(state == NEW &&
-              U.compareAndSwapInt(this, STATE, NEW,
-                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
+        if (!(state == NEW && STATE.compareAndSet
+              (this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
             return false;
         try {    // in case call to interrupt throws exception
             if (mayInterruptIfRunning) {
@@ -174,7 +172,7 @@
                     if (t != null)
                         t.interrupt();
                 } finally { // final state
-                    U.putOrderedInt(this, STATE, INTERRUPTED);
+                    STATE.setRelease(this, INTERRUPTED);
                 }
             }
         } finally {
@@ -228,9 +226,9 @@
      * @param v the value
      */
     protected void set(V v) {
-        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
+        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
             outcome = v;
-            U.putOrderedInt(this, STATE, NORMAL); // final state
+            STATE.setRelease(this, NORMAL); // final state
             finishCompletion();
         }
     }
@@ -246,16 +244,16 @@
      * @param t the cause of failure
      */
     protected void setException(Throwable t) {
-        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
+        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
             outcome = t;
-            U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
+            STATE.setRelease(this, EXCEPTIONAL); // final state
             finishCompletion();
         }
     }
 
     public void run() {
         if (state != NEW ||
-            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
+            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
             return;
         try {
             Callable<V> c = callable;
@@ -296,7 +294,7 @@
      */
     protected boolean runAndReset() {
         if (state != NEW ||
-            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
+            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
             return false;
         boolean ran = false;
         int s = state;
@@ -363,7 +361,7 @@
     private void finishCompletion() {
         // assert state > COMPLETING;
         for (WaitNode q; (q = waiters) != null;) {
-            if (U.compareAndSwapObject(this, WAITERS, q, null)) {
+            if (WAITERS.weakCompareAndSet(this, q, null)) {
                 for (;;) {
                     Thread t = q.thread;
                     if (t != null) {
@@ -425,8 +423,7 @@
                 q = new WaitNode();
             }
             else if (!queued)
-                queued = U.compareAndSwapObject(this, WAITERS,
-                                                q.next = waiters, q);
+                queued = WAITERS.weakCompareAndSet(this, q.next = waiters, q);
             else if (timed) {
                 final long parkNanos;
                 if (startTime == 0L) { // first time
@@ -475,7 +472,7 @@
                         if (pred.thread == null) // check for race
                             continue retry;
                     }
-                    else if (!U.compareAndSwapObject(this, WAITERS, q, s))
+                    else if (!WAITERS.compareAndSet(this, q, s))
                         continue retry;
                 }
                 break;
@@ -483,21 +480,53 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long RUNNER;
-    private static final long WAITERS;
+    /**
+     * Returns a string representation of this FutureTask.
+     *
+     * @implSpec
+     * The default implementation returns a string identifying this
+     * FutureTask, as well as its completion state.  The state, in
+     * brackets, contains one of the strings {@code "Completed Normally"},
+     * {@code "Completed Exceptionally"}, {@code "Cancelled"}, or {@code
+     * "Not completed"}.
+     *
+     * @return a string representation of this FutureTask
+     */
+    public String toString() {
+        final String status;
+        switch (state) {
+        case NORMAL:
+            status = "[Completed normally]";
+            break;
+        case EXCEPTIONAL:
+            status = "[Completed exceptionally: " + outcome + "]";
+            break;
+        case CANCELLED:
+        case INTERRUPTING:
+        case INTERRUPTED:
+            status = "[Cancelled]";
+            break;
+        default:
+            final Callable<?> callable = this.callable;
+            status = (callable == null)
+                ? "[Not completed]"
+                : "[Not completed, task = " + callable + "]";
+        }
+        return super.toString() + status;
+    }
+
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle RUNNER;
+    private static final VarHandle WAITERS;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("state"));
-            RUNNER = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("runner"));
-            WAITERS = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("waiters"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(FutureTask.class, "state", int.class);
+            RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
+            WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
 
         // Reduce the risk of rare disastrous classloading in first call to
diff --git a/ojluni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java b/ojluni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
index 9829c9c..f55998e 100644
--- a/ojluni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
+++ b/ojluni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
@@ -39,15 +39,13 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.function.Predicate;
 
 /**
  * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
@@ -66,9 +64,12 @@
  * contains}, {@link #iterator iterator.remove()}, and the bulk
  * operations, all of which run in linear time.
  *
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
  *
  * @since 1.6
  * @author  Doug Lea
@@ -194,18 +195,7 @@
      */
     public LinkedBlockingDeque(Collection<? extends E> c) {
         this(Integer.MAX_VALUE);
-        final ReentrantLock lock = this.lock;
-        lock.lock(); // Never contended, but necessary for visibility
-        try {
-            for (E e : c) {
-                if (e == null)
-                    throw new NullPointerException();
-                if (!linkLast(new Node<E>(e)))
-                    throw new IllegalStateException("Deque full");
-            }
-        } finally {
-            lock.unlock();
-        }
+        addAll(c);
     }
 
 
@@ -298,6 +288,7 @@
      */
     void unlink(Node<E> x) {
         // assert lock.isHeldByCurrentThread();
+        // assert x.item != null;
         Node<E> p = x.prev;
         Node<E> n = x.next;
         if (p == null) {
@@ -660,7 +651,7 @@
 
     /**
      * Retrieves and removes the head of the queue represented by this deque.
-     * This method differs from {@link #poll poll} only in that it throws an
+     * This method differs from {@link #poll() poll()} only in that it throws an
      * exception if this deque is empty.
      *
      * <p>This method is equivalent to {@link #removeFirst() removeFirst}.
@@ -686,7 +677,7 @@
 
     /**
      * Retrieves, but does not remove, the head of the queue represented by
-     * this deque.  This method differs from {@link #peek peek} only in that
+     * this deque.  This method differs from {@link #peek() peek()} only in that
      * it throws an exception if this deque is empty.
      *
      * <p>This method is equivalent to {@link #getFirst() getFirst}.
@@ -740,8 +731,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         if (maxElements <= 0)
@@ -834,46 +824,65 @@
         }
     }
 
-    /*
-     * TODO: Add support for more efficient bulk operations.
+    /**
+     * Appends all of the elements in the specified collection to the end of
+     * this deque, in the order that they are returned by the specified
+     * collection's iterator.  Attempts to {@code addAll} of a deque to
+     * itself result in {@code IllegalArgumentException}.
      *
-     * We don't want to acquire the lock for every iteration, but we
-     * also want other threads a chance to interact with the
-     * collection, especially when count is close to capacity.
+     * @param c the elements to be inserted into this deque
+     * @return {@code true} if this deque changed as a result of the call
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
+     * @throws IllegalArgumentException if the collection is this deque
+     * @throws IllegalStateException if this deque is full
+     * @see #add(Object)
      */
+    public boolean addAll(Collection<? extends E> c) {
+        if (c == this)
+            // As historically specified in AbstractQueue#addAll
+            throw new IllegalArgumentException();
 
-//     /**
-//      * Adds all of the elements in the specified collection to this
-//      * queue.  Attempts to addAll of a queue to itself result in
-//      * {@code IllegalArgumentException}. Further, 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 queue
-//      * @return {@code true} if this queue changed as a result of the call
-//      * @throws ClassCastException            {@inheritDoc}
-//      * @throws NullPointerException          {@inheritDoc}
-//      * @throws IllegalArgumentException      {@inheritDoc}
-//      * @throws IllegalStateException if this deque is full
-//      * @see #add(Object)
-//      */
-//     public boolean addAll(Collection<? extends E> c) {
-//         if (c == null)
-//             throw new NullPointerException();
-//         if (c == this)
-//             throw new IllegalArgumentException();
-//         final ReentrantLock lock = this.lock;
-//         lock.lock();
-//         try {
-//             boolean modified = false;
-//             for (E e : c)
-//                 if (linkLast(e))
-//                     modified = true;
-//             return modified;
-//         } finally {
-//             lock.unlock();
-//         }
-//     }
+        // Copy c into a private chain of Nodes
+        Node<E> beg = null, end = null;
+        int n = 0;
+        for (E e : c) {
+            Objects.requireNonNull(e);
+            n++;
+            Node<E> newNode = new Node<E>(e);
+            if (beg == null)
+                beg = end = newNode;
+            else {
+                end.next = newNode;
+                newNode.prev = end;
+                end = newNode;
+            }
+        }
+        if (beg == null)
+            return false;
+
+        // Atomically append the chain at the end
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            if (count + n <= capacity) {
+                beg.prev = last;
+                if (first == null)
+                    first = beg;
+                else
+                    last.next = beg;
+                last = end;
+                count += n;
+                notEmpty.signalAll();
+                return true;
+            }
+        } finally {
+            lock.unlock();
+        }
+        // Fall back to historic non-atomic implementation, failing
+        // with IllegalStateException when the capacity is exceeded.
+        return super.addAll(c);
+    }
 
     /**
      * Returns an array containing all of the elements in this deque, in
@@ -986,6 +995,18 @@
     }
 
     /**
+     * Used for any element traversal that is not entirely under lock.
+     * Such traversals must handle both:
+     * - dequeued nodes (p.next == p)
+     * - (possibly multiple) interior removed nodes (p.item == null)
+     */
+    Node<E> succ(Node<E> p) {
+        if (p == (p = p.next))
+            p = first;
+        return p;
+    }
+
+    /**
      * Returns an iterator over the elements in this deque in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
@@ -1024,8 +1045,8 @@
         /**
          * nextItem holds on to item fields because once we claim that
          * an element exists in hasNext(), we must return item read
-         * under lock (in advance()) even if it was in the process of
-         * being removed when hasNext() was called.
+         * under lock even if it was in the process of being removed
+         * when hasNext() was called.
          */
         E nextItem;
 
@@ -1038,48 +1059,19 @@
         abstract Node<E> firstNode();
         abstract Node<E> nextNode(Node<E> n);
 
+        private Node<E> succ(Node<E> p) {
+            if (p == (p = nextNode(p)))
+                p = firstNode();
+            return p;
+        }
+
         AbstractItr() {
             // set to initial position
             final ReentrantLock lock = LinkedBlockingDeque.this.lock;
             lock.lock();
             try {
-                next = firstNode();
-                nextItem = (next == null) ? null : next.item;
-            } finally {
-                lock.unlock();
-            }
-        }
-
-        /**
-         * Returns the successor node of the given non-null, but
-         * possibly previously deleted, node.
-         */
-        private Node<E> succ(Node<E> n) {
-            // Chains of deleted nodes ending in null or self-links
-            // are possible if multiple interior nodes are removed.
-            for (;;) {
-                Node<E> s = nextNode(n);
-                if (s == null)
-                    return null;
-                else if (s.item != null)
-                    return s;
-                else if (s == n)
-                    return firstNode();
-                else
-                    n = s;
-            }
-        }
-
-        /**
-         * Advances next.
-         */
-        void advance() {
-            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
-            lock.lock();
-            try {
-                // assert next != null;
-                next = succ(next);
-                nextItem = (next == null) ? null : next.item;
+                if ((next = firstNode()) != null)
+                    nextItem = next.item;
             } finally {
                 lock.unlock();
             }
@@ -1090,14 +1082,65 @@
         }
 
         public E next() {
-            if (next == null)
+            Node<E> p;
+            if ((p = next) == null)
                 throw new NoSuchElementException();
-            lastRet = next;
+            lastRet = p;
             E x = nextItem;
-            advance();
+            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+            lock.lock();
+            try {
+                E e = null;
+                for (p = nextNode(p); p != null && (e = p.item) == null; )
+                    p = succ(p);
+                next = p;
+                nextItem = e;
+            } finally {
+                lock.unlock();
+            }
             return x;
         }
 
+        public void forEachRemaining(Consumer<? super E> action) {
+            // A variant of forEachFrom
+            Objects.requireNonNull(action);
+            Node<E> p;
+            if ((p = next) == null) return;
+            lastRet = p;
+            next = null;
+            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+            final int batchSize = 64;
+            Object[] es = null;
+            int n, len = 1;
+            do {
+                lock.lock();
+                try {
+                    if (es == null) {
+                        p = nextNode(p);
+                        for (Node<E> q = p; q != null; q = succ(q))
+                            if (q.item != null && ++len == batchSize)
+                                break;
+                        es = new Object[len];
+                        es[0] = nextItem;
+                        nextItem = null;
+                        n = 1;
+                    } else
+                        n = 0;
+                    for (; p != null && n < len; p = succ(p))
+                        if ((es[n] = p.item) != null) {
+                            lastRet = p;
+                            n++;
+                        }
+                } finally {
+                    lock.unlock();
+                }
+                for (int i = 0; i < n; i++) {
+                    @SuppressWarnings("unchecked") E e = (E) es[i];
+                    action.accept(e);
+                }
+            } while (n > 0 && p != null);
+        }
+
         public void remove() {
             Node<E> n = lastRet;
             if (n == null)
@@ -1116,51 +1159,49 @@
 
     /** Forward iterator */
     private class Itr extends AbstractItr {
+        Itr() {}                        // prevent access constructor creation
         Node<E> firstNode() { return first; }
         Node<E> nextNode(Node<E> n) { return n.next; }
     }
 
     /** Descending iterator */
     private class DescendingItr extends AbstractItr {
+        DescendingItr() {}              // prevent access constructor creation
         Node<E> firstNode() { return last; }
         Node<E> nextNode(Node<E> n) { return n.prev; }
     }
 
-    /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class LBDSpliterator<E> implements Spliterator<E> {
+    /**
+     * A customized variant of Spliterators.IteratorSpliterator.
+     * Keep this class in sync with (very similar) LBQSpliterator.
+     */
+    private final class LBDSpliterator implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final LinkedBlockingDeque<E> queue;
         Node<E> current;    // current node; null until initialized
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
-        long est;           // size estimate
-        LBDSpliterator(LinkedBlockingDeque<E> queue) {
-            this.queue = queue;
-            this.est = queue.size();
-        }
+        long est = size();  // size estimate
+
+        LBDSpliterator() {}
 
         public long estimateSize() { return est; }
 
         public Spliterator<E> trySplit() {
             Node<E> h;
-            final LinkedBlockingDeque<E> q = this.queue;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
             if (!exhausted &&
-                ((h = current) != null || (h = q.first) != null) &&
-                h.next != null) {
+                ((h = current) != null || (h = first) != null)
+                && h.next != null) {
+                int n = batch = Math.min(batch + 1, MAX_BATCH);
                 Object[] a = new Object[n];
-                final ReentrantLock lock = q.lock;
+                final ReentrantLock lock = LinkedBlockingDeque.this.lock;
                 int i = 0;
                 Node<E> p = current;
                 lock.lock();
                 try {
-                    if (p != null || (p = q.first) != null) {
-                        do {
+                    if (p != null || (p = first) != null)
+                        for (; p != null && i < n; p = succ(p))
                             if ((a[i] = p.item) != null)
-                                ++i;
-                        } while ((p = p.next) != null && i < n);
-                    }
+                                i++;
                 } finally {
                     lock.unlock();
                 }
@@ -1170,66 +1211,33 @@
                 }
                 else if ((est -= i) < 0L)
                     est = 0L;
-                if (i > 0) {
-                    batch = i;
+                if (i > 0)
                     return Spliterators.spliterator
                         (a, 0, i, (Spliterator.ORDERED |
                                    Spliterator.NONNULL |
                                    Spliterator.CONCURRENT));
-                }
             }
             return null;
         }
 
-        public void forEachRemaining(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingDeque<E> q = this.queue;
-            final ReentrantLock lock = q.lock;
-            if (!exhausted) {
-                exhausted = true;
-                Node<E> p = current;
-                do {
-                    E e = null;
-                    lock.lock();
-                    try {
-                        if (p == null)
-                            p = q.first;
-                        while (p != null) {
-                            e = p.item;
-                            p = p.next;
-                            if (e != null)
-                                break;
-                        }
-                    } finally {
-                        lock.unlock();
-                    }
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
-            }
-        }
-
         public boolean tryAdvance(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingDeque<E> q = this.queue;
-            final ReentrantLock lock = q.lock;
+            Objects.requireNonNull(action);
             if (!exhausted) {
                 E e = null;
+                final ReentrantLock lock = LinkedBlockingDeque.this.lock;
                 lock.lock();
                 try {
-                    if (current == null)
-                        current = q.first;
-                    while (current != null) {
-                        e = current.item;
-                        current = current.next;
-                        if (e != null)
-                            break;
-                    }
+                    Node<E> p;
+                    if ((p = current) != null || (p = first) != null)
+                        do {
+                            e = p.item;
+                            p = succ(p);
+                        } while (e == null && p != null);
+                    if ((current = p) == null)
+                        exhausted = true;
                 } finally {
                     lock.unlock();
                 }
-                if (current == null)
-                    exhausted = true;
                 if (e != null) {
                     action.accept(e);
                     return true;
@@ -1238,9 +1246,20 @@
             return false;
         }
 
+        public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            if (!exhausted) {
+                exhausted = true;
+                Node<E> p = current;
+                current = null;
+                forEachFrom(action, p);
+            }
+        }
+
         public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
+            return (Spliterator.ORDERED |
+                    Spliterator.NONNULL |
+                    Spliterator.CONCURRENT);
         }
     }
 
@@ -1261,7 +1280,127 @@
      * @since 1.8
      */
     public Spliterator<E> spliterator() {
-        return new LBDSpliterator<E>(this);
+        return new LBDSpliterator();
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        forEachFrom(action, null);
+    }
+
+    /**
+     * Runs action on each element found during a traversal starting at p.
+     * If p is null, traversal starts at head.
+     */
+    void forEachFrom(Consumer<? super E> action, Node<E> p) {
+        // Extract batches of elements while holding the lock; then
+        // run the action on the elements while not
+        final ReentrantLock lock = this.lock;
+        final int batchSize = 64;       // max number of elements per batch
+        Object[] es = null;             // container for batch of elements
+        int n, len = 0;
+        do {
+            lock.lock();
+            try {
+                if (es == null) {
+                    if (p == null) p = first;
+                    for (Node<E> q = p; q != null; q = succ(q))
+                        if (q.item != null && ++len == batchSize)
+                            break;
+                    es = new Object[len];
+                }
+                for (n = 0; p != null && n < len; p = succ(p))
+                    if ((es[n] = p.item) != null)
+                        n++;
+            } finally {
+                lock.unlock();
+            }
+            for (int i = 0; i < n; i++) {
+                @SuppressWarnings("unchecked") E e = (E) es[i];
+                action.accept(e);
+            }
+        } while (n > 0 && p != null);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    /** Implementation of bulk remove methods. */
+    @SuppressWarnings("unchecked")
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        boolean removed = false;
+        final ReentrantLock lock = this.lock;
+        Node<E> p = null;
+        Node<E>[] nodes = null;
+        int n, len = 0;
+        do {
+            // 1. Extract batch of up to 64 elements while holding the lock.
+            lock.lock();
+            try {
+                if (nodes == null) {  // first batch; initialize
+                    p = first;
+                    for (Node<E> q = p; q != null; q = succ(q))
+                        if (q.item != null && ++len == 64)
+                            break;
+                    nodes = (Node<E>[]) new Node<?>[len];
+                }
+                for (n = 0; p != null && n < len; p = succ(p))
+                    nodes[n++] = p;
+            } finally {
+                lock.unlock();
+            }
+
+            // 2. Run the filter on the elements while lock is free.
+            long deathRow = 0L;       // "bitset" of size 64
+            for (int i = 0; i < n; i++) {
+                final E e;
+                if ((e = nodes[i].item) != null && filter.test(e))
+                    deathRow |= 1L << i;
+            }
+
+            // 3. Remove any filtered elements while holding the lock.
+            if (deathRow != 0) {
+                lock.lock();
+                try {
+                    for (int i = 0; i < n; i++) {
+                        final Node<E> q;
+                        if ((deathRow & (1L << i)) != 0L
+                            && (q = nodes[i]).item != null) {
+                            unlink(q);
+                            removed = true;
+                        }
+                        nodes[i] = null; // help GC
+                    }
+                } finally {
+                    lock.unlock();
+                }
+            }
+        } while (n > 0 && p != null);
+        return removed;
     }
 
     /**
@@ -1304,12 +1443,21 @@
         last = null;
         // Read in all elements and place in queue
         for (;;) {
-            @SuppressWarnings("unchecked")
-            E item = (E)s.readObject();
+            @SuppressWarnings("unchecked") E item = (E)s.readObject();
             if (item == null)
                 break;
             add(item);
         }
     }
 
+    void checkInvariants() {
+        // assert lock.isHeldByCurrentThread();
+        // Nodes may get self-linked or lose their item, but only
+        // after being unlinked and becoming unreachable from first.
+        for (Node<E> p = first; p != null; p = p.next) {
+            // assert p.next != p;
+            // assert p.item != null;
+        }
+    }
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java b/ojluni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
index cf2d447..4ba6c1e 100644
--- a/ojluni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
@@ -39,16 +39,14 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.function.Predicate;
 
 /**
  * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
@@ -69,9 +67,12 @@
  * dynamically created upon each insertion unless this would bring the
  * queue above capacity.
  *
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
  *
  * @since 1.5
  * @author Doug Lea
@@ -234,14 +235,6 @@
         putLock.unlock();
     }
 
-//     /**
-//      * Tells whether both locks are held by current thread.
-//      */
-//     boolean isFullyLocked() {
-//         return (putLock.isHeldByCurrentThread() &&
-//                 takeLock.isHeldByCurrentThread());
-//     }
-
     /**
      * Creates a {@code LinkedBlockingQueue} with a capacity of
      * {@link Integer#MAX_VALUE}.
@@ -330,10 +323,8 @@
      */
     public void put(E e) throws InterruptedException {
         if (e == null) throw new NullPointerException();
-        // Note: convention in all put/take/etc is to preset local var
-        // holding count negative to indicate failure unless set.
-        int c = -1;
-        Node<E> node = new Node<E>(e);
+        final int c;
+        final Node<E> node = new Node<E>(e);
         final ReentrantLock putLock = this.putLock;
         final AtomicInteger count = this.count;
         putLock.lockInterruptibly();
@@ -374,7 +365,7 @@
 
         if (e == null) throw new NullPointerException();
         long nanos = unit.toNanos(timeout);
-        int c = -1;
+        final int c;
         final ReentrantLock putLock = this.putLock;
         final AtomicInteger count = this.count;
         putLock.lockInterruptibly();
@@ -412,28 +403,28 @@
         final AtomicInteger count = this.count;
         if (count.get() == capacity)
             return false;
-        int c = -1;
-        Node<E> node = new Node<E>(e);
+        final int c;
+        final Node<E> node = new Node<E>(e);
         final ReentrantLock putLock = this.putLock;
         putLock.lock();
         try {
-            if (count.get() < capacity) {
-                enqueue(node);
-                c = count.getAndIncrement();
-                if (c + 1 < capacity)
-                    notFull.signal();
-            }
+            if (count.get() == capacity)
+                return false;
+            enqueue(node);
+            c = count.getAndIncrement();
+            if (c + 1 < capacity)
+                notFull.signal();
         } finally {
             putLock.unlock();
         }
         if (c == 0)
             signalNotEmpty();
-        return c >= 0;
+        return true;
     }
 
     public E take() throws InterruptedException {
-        E x;
-        int c = -1;
+        final E x;
+        final int c;
         final AtomicInteger count = this.count;
         final ReentrantLock takeLock = this.takeLock;
         takeLock.lockInterruptibly();
@@ -454,8 +445,8 @@
     }
 
     public E poll(long timeout, TimeUnit unit) throws InterruptedException {
-        E x = null;
-        int c = -1;
+        final E x;
+        final int c;
         long nanos = unit.toNanos(timeout);
         final AtomicInteger count = this.count;
         final ReentrantLock takeLock = this.takeLock;
@@ -482,17 +473,17 @@
         final AtomicInteger count = this.count;
         if (count.get() == 0)
             return null;
-        E x = null;
-        int c = -1;
+        final E x;
+        final int c;
         final ReentrantLock takeLock = this.takeLock;
         takeLock.lock();
         try {
-            if (count.get() > 0) {
-                x = dequeue();
-                c = count.getAndDecrement();
-                if (c > 1)
-                    notEmpty.signal();
-            }
+            if (count.get() == 0)
+                return null;
+            x = dequeue();
+            c = count.getAndDecrement();
+            if (c > 1)
+                notEmpty.signal();
         } finally {
             takeLock.unlock();
         }
@@ -502,6 +493,7 @@
     }
 
     public E peek() {
+        final AtomicInteger count = this.count;
         if (count.get() == 0)
             return null;
         final ReentrantLock takeLock = this.takeLock;
@@ -514,16 +506,17 @@
     }
 
     /**
-     * Unlinks interior Node p with predecessor trail.
+     * Unlinks interior Node p with predecessor pred.
      */
-    void unlink(Node<E> p, Node<E> trail) {
-        // assert isFullyLocked();
+    void unlink(Node<E> p, Node<E> pred) {
+        // assert putLock.isHeldByCurrentThread();
+        // assert takeLock.isHeldByCurrentThread();
         // p.next is not changed, to allow iterators that are
         // traversing p to maintain their weak-consistency guarantee.
         p.item = null;
-        trail.next = p.next;
+        pred.next = p.next;
         if (last == p)
-            last = trail;
+            last = pred;
         if (count.getAndDecrement() == capacity)
             notFull.signal();
     }
@@ -543,11 +536,11 @@
         if (o == null) return false;
         fullyLock();
         try {
-            for (Node<E> trail = head, p = trail.next;
+            for (Node<E> pred = head, p = pred.next;
                  p != null;
-                 trail = p, p = p.next) {
+                 pred = p, p = p.next) {
                 if (o.equals(p.item)) {
-                    unlink(p, trail);
+                    unlink(p, pred);
                     return true;
                 }
             }
@@ -701,8 +694,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         if (maxElements <= 0)
@@ -741,6 +733,18 @@
     }
 
     /**
+     * Used for any element traversal that is not entirely under lock.
+     * Such traversals must handle both:
+     * - dequeued nodes (p.next == p)
+     * - (possibly multiple) interior removed nodes (p.item == null)
+     */
+    Node<E> succ(Node<E> p) {
+        if (p == (p = p.next))
+            p = head.next;
+        return p;
+    }
+
+    /**
      * Returns an iterator over the elements in this queue in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
      *
@@ -753,71 +757,103 @@
         return new Itr();
     }
 
+    /**
+     * Weakly-consistent iterator.
+     *
+     * Lazily updated ancestor field provides expected O(1) remove(),
+     * but still O(n) in the worst case, whenever the saved ancestor
+     * is concurrently deleted.
+     */
     private class Itr implements Iterator<E> {
-        /*
-         * Basic weakly-consistent iterator.  At all times hold the next
-         * 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> next;           // Node holding nextItem
+        private E nextItem;             // next item to hand out
         private Node<E> lastRet;
-        private E currentElement;
+        private Node<E> ancestor;       // Helps unlink lastRet on remove()
 
         Itr() {
             fullyLock();
             try {
-                current = head.next;
-                if (current != null)
-                    currentElement = current.item;
+                if ((next = head.next) != null)
+                    nextItem = next.item;
             } finally {
                 fullyUnlock();
             }
         }
 
         public boolean hasNext() {
-            return current != null;
+            return next != null;
         }
 
         public E next() {
+            Node<E> p;
+            if ((p = next) == null)
+                throw new NoSuchElementException();
+            lastRet = p;
+            E x = nextItem;
             fullyLock();
             try {
-                if (current == null)
-                    throw new NoSuchElementException();
-                lastRet = current;
-                E item = null;
-                // Unlike other traversal methods, iterators must handle both:
-                // - dequeued nodes (p.next == p)
-                // - (possibly multiple) interior removed nodes (p.item == null)
-                for (Node<E> p = current, q;; p = q) {
-                    if ((q = p.next) == p)
-                        q = head.next;
-                    if (q == null || (item = q.item) != null) {
-                        current = q;
-                        E x = currentElement;
-                        currentElement = item;
-                        return x;
-                    }
-                }
+                E e = null;
+                for (p = p.next; p != null && (e = p.item) == null; )
+                    p = succ(p);
+                next = p;
+                nextItem = e;
             } finally {
                 fullyUnlock();
             }
+            return x;
+        }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            // A variant of forEachFrom
+            Objects.requireNonNull(action);
+            Node<E> p;
+            if ((p = next) == null) return;
+            lastRet = p;
+            next = null;
+            final int batchSize = 64;
+            Object[] es = null;
+            int n, len = 1;
+            do {
+                fullyLock();
+                try {
+                    if (es == null) {
+                        p = p.next;
+                        for (Node<E> q = p; q != null; q = succ(q))
+                            if (q.item != null && ++len == batchSize)
+                                break;
+                        es = new Object[len];
+                        es[0] = nextItem;
+                        nextItem = null;
+                        n = 1;
+                    } else
+                        n = 0;
+                    for (; p != null && n < len; p = succ(p))
+                        if ((es[n] = p.item) != null) {
+                            lastRet = p;
+                            n++;
+                        }
+                } finally {
+                    fullyUnlock();
+                }
+                for (int i = 0; i < n; i++) {
+                    @SuppressWarnings("unchecked") E e = (E) es[i];
+                    action.accept(e);
+                }
+            } while (n > 0 && p != null);
         }
 
         public void remove() {
-            if (lastRet == null)
+            Node<E> p = lastRet;
+            if (p == null)
                 throw new IllegalStateException();
+            lastRet = null;
             fullyLock();
             try {
-                Node<E> node = lastRet;
-                lastRet = null;
-                for (Node<E> trail = head, p = trail.next;
-                     p != null;
-                     trail = p, p = p.next) {
-                    if (p == node) {
-                        unlink(p, trail);
-                        break;
-                    }
+                if (p.item != null) {
+                    if (ancestor == null)
+                        ancestor = head;
+                    ancestor = findPred(p, ancestor);
+                    unlink(p, ancestor);
                 }
             } finally {
                 fullyUnlock();
@@ -825,42 +861,38 @@
         }
     }
 
-    /** A customized variant of Spliterators.IteratorSpliterator */
-    static final class LBQSpliterator<E> implements Spliterator<E> {
+    /**
+     * A customized variant of Spliterators.IteratorSpliterator.
+     * Keep this class in sync with (very similar) LBDSpliterator.
+     */
+    private final class LBQSpliterator implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
-        final LinkedBlockingQueue<E> queue;
         Node<E> current;    // current node; null until initialized
         int batch;          // batch size for splits
         boolean exhausted;  // true when no more nodes
-        long est;           // size estimate
-        LBQSpliterator(LinkedBlockingQueue<E> queue) {
-            this.queue = queue;
-            this.est = queue.size();
-        }
+        long est = size();  // size estimate
+
+        LBQSpliterator() {}
 
         public long estimateSize() { return est; }
 
         public Spliterator<E> trySplit() {
             Node<E> h;
-            final LinkedBlockingQueue<E> q = this.queue;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
             if (!exhausted &&
-                ((h = current) != null || (h = q.head.next) != null) &&
-                h.next != null) {
+                ((h = current) != null || (h = head.next) != null)
+                && h.next != null) {
+                int n = batch = Math.min(batch + 1, MAX_BATCH);
                 Object[] a = new Object[n];
                 int i = 0;
                 Node<E> p = current;
-                q.fullyLock();
+                fullyLock();
                 try {
-                    if (p != null || (p = q.head.next) != null) {
-                        do {
+                    if (p != null || (p = head.next) != null)
+                        for (; p != null && i < n; p = succ(p))
                             if ((a[i] = p.item) != null)
-                                ++i;
-                        } while ((p = p.next) != null && i < n);
-                    }
+                                i++;
                 } finally {
-                    q.fullyUnlock();
+                    fullyUnlock();
                 }
                 if ((current = p) == null) {
                     est = 0L;
@@ -868,64 +900,32 @@
                 }
                 else if ((est -= i) < 0L)
                     est = 0L;
-                if (i > 0) {
-                    batch = i;
+                if (i > 0)
                     return Spliterators.spliterator
                         (a, 0, i, (Spliterator.ORDERED |
                                    Spliterator.NONNULL |
                                    Spliterator.CONCURRENT));
-                }
             }
             return null;
         }
 
-        public void forEachRemaining(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingQueue<E> q = this.queue;
-            if (!exhausted) {
-                exhausted = true;
-                Node<E> p = current;
-                do {
-                    E e = null;
-                    q.fullyLock();
-                    try {
-                        if (p == null)
-                            p = q.head.next;
-                        while (p != null) {
-                            e = p.item;
-                            p = p.next;
-                            if (e != null)
-                                break;
-                        }
-                    } finally {
-                        q.fullyUnlock();
-                    }
-                    if (e != null)
-                        action.accept(e);
-                } while (p != null);
-            }
-        }
-
         public boolean tryAdvance(Consumer<? super E> action) {
-            if (action == null) throw new NullPointerException();
-            final LinkedBlockingQueue<E> q = this.queue;
+            Objects.requireNonNull(action);
             if (!exhausted) {
                 E e = null;
-                q.fullyLock();
+                fullyLock();
                 try {
-                    if (current == null)
-                        current = q.head.next;
-                    while (current != null) {
-                        e = current.item;
-                        current = current.next;
-                        if (e != null)
-                            break;
-                    }
+                    Node<E> p;
+                    if ((p = current) != null || (p = head.next) != null)
+                        do {
+                            e = p.item;
+                            p = succ(p);
+                        } while (e == null && p != null);
+                    if ((current = p) == null)
+                        exhausted = true;
                 } finally {
-                    q.fullyUnlock();
+                    fullyUnlock();
                 }
-                if (current == null)
-                    exhausted = true;
                 if (e != null) {
                     action.accept(e);
                     return true;
@@ -934,9 +934,20 @@
             return false;
         }
 
+        public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            if (!exhausted) {
+                exhausted = true;
+                Node<E> p = current;
+                current = null;
+                forEachFrom(action, p);
+            }
+        }
+
         public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
+            return (Spliterator.ORDERED |
+                    Spliterator.NONNULL |
+                    Spliterator.CONCURRENT);
         }
     }
 
@@ -957,7 +968,140 @@
      * @since 1.8
      */
     public Spliterator<E> spliterator() {
-        return new LBQSpliterator<E>(this);
+        return new LBQSpliterator();
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        forEachFrom(action, null);
+    }
+
+    /**
+     * Runs action on each element found during a traversal starting at p.
+     * If p is null, traversal starts at head.
+     */
+    void forEachFrom(Consumer<? super E> action, Node<E> p) {
+        // Extract batches of elements while holding the lock; then
+        // run the action on the elements while not
+        final int batchSize = 64;       // max number of elements per batch
+        Object[] es = null;             // container for batch of elements
+        int n, len = 0;
+        do {
+            fullyLock();
+            try {
+                if (es == null) {
+                    if (p == null) p = head.next;
+                    for (Node<E> q = p; q != null; q = succ(q))
+                        if (q.item != null && ++len == batchSize)
+                            break;
+                    es = new Object[len];
+                }
+                for (n = 0; p != null && n < len; p = succ(p))
+                    if ((es[n] = p.item) != null)
+                        n++;
+            } finally {
+                fullyUnlock();
+            }
+            for (int i = 0; i < n; i++) {
+                @SuppressWarnings("unchecked") E e = (E) es[i];
+                action.accept(e);
+            }
+        } while (n > 0 && p != null);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    /**
+     * Returns the predecessor of live node p, given a node that was
+     * once a live ancestor of p (or head); allows unlinking of p.
+     */
+    Node<E> findPred(Node<E> p, Node<E> ancestor) {
+        // assert p.item != null;
+        if (ancestor.item == null)
+            ancestor = head;
+        // Fails with NPE if precondition not satisfied
+        for (Node<E> q; (q = ancestor.next) != p; )
+            ancestor = q;
+        return ancestor;
+    }
+
+    /** Implementation of bulk remove methods. */
+    @SuppressWarnings("unchecked")
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        boolean removed = false;
+        Node<E> p = null, ancestor = head;
+        Node<E>[] nodes = null;
+        int n, len = 0;
+        do {
+            // 1. Extract batch of up to 64 elements while holding the lock.
+            fullyLock();
+            try {
+                if (nodes == null) {  // first batch; initialize
+                    p = head.next;
+                    for (Node<E> q = p; q != null; q = succ(q))
+                        if (q.item != null && ++len == 64)
+                            break;
+                    nodes = (Node<E>[]) new Node<?>[len];
+                }
+                for (n = 0; p != null && n < len; p = succ(p))
+                    nodes[n++] = p;
+            } finally {
+                fullyUnlock();
+            }
+
+            // 2. Run the filter on the elements while lock is free.
+            long deathRow = 0L;       // "bitset" of size 64
+            for (int i = 0; i < n; i++) {
+                final E e;
+                if ((e = nodes[i].item) != null && filter.test(e))
+                    deathRow |= 1L << i;
+            }
+
+            // 3. Remove any filtered elements while holding the lock.
+            if (deathRow != 0) {
+                fullyLock();
+                try {
+                    for (int i = 0; i < n; i++) {
+                        final Node<E> q;
+                        if ((deathRow & (1L << i)) != 0L
+                            && (q = nodes[i]).item != null) {
+                            ancestor = findPred(q, ancestor);
+                            unlink(q, ancestor);
+                            removed = true;
+                        }
+                        nodes[i] = null; // help GC
+                    }
+                } finally {
+                    fullyUnlock();
+                }
+            }
+        } while (n > 0 && p != null);
+        return removed;
     }
 
     /**
diff --git a/ojluni/src/main/java/java/util/concurrent/LinkedTransferQueue.java b/ojluni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
index e282b42..06d04e22 100644
--- a/ojluni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
@@ -35,20 +35,20 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Queue;
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.concurrent.locks.LockSupport;
 import java.util.function.Consumer;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.function.Predicate;
 
 /**
  * An unbounded {@link TransferQueue} based on linked nodes.
@@ -63,16 +63,15 @@
  * asynchronous nature of these queues, 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 {@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 {@code addAll} operation might view only some
- * of the added elements.
  *
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.
+ * <p>Bulk operations that add, remove, or examine multiple elements,
+ * such as {@link #addAll}, {@link #removeIf} or {@link #forEach},
+ * are <em>not</em> guaranteed to be performed atomically.
+ * For example, a {@code forEach} traversal concurrent with an {@code
+ * addAll} operation might observe only some of the added elements.
+ *
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
  *
  * <p>Memory consistency effects: As with other concurrent
  * collections, actions in a thread prior to placing an object into a
@@ -81,6 +80,10 @@
  * actions subsequent to the access or removal of that element from
  * the {@code LinkedTransferQueue} in another thread.
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.7
  * @author Doug Lea
  * @param <E> the type of elements held in this queue
@@ -93,8 +96,8 @@
      * *** Overview of Dual Queues with Slack ***
      *
      * Dual Queues, introduced by Scherer and Scott
-     * (http://www.cs.rice.edu/~wns1/papers/2004-DISC-DDS.pdf) are
-     * (linked) queues in which nodes may represent either data or
+     * (http://www.cs.rochester.edu/~scott/papers/2004_DISC_dual_DS.pdf)
+     * are (linked) queues in which nodes may represent either data or
      * requests.  When a thread tries to enqueue a data node, but
      * encounters a request node, it instead "matches" and removes it;
      * and vice versa for enqueuing requests. Blocking Dual Queues
@@ -156,9 +159,8 @@
      * correctly perform enqueue and dequeue operations by traversing
      * from a pointer to the initial node; CASing the item of the
      * first unmatched node on match and CASing the next field of the
-     * trailing node on appends. (Plus some special-casing when
-     * initially empty).  While this would be a terrible idea in
-     * itself, it does have the benefit of not requiring ANY atomic
+     * trailing node on appends.  While this would be a terrible idea
+     * in itself, it does have the benefit of not requiring ANY atomic
      * updates on head/tail fields.
      *
      * We introduce here an approach that lies between the extremes of
@@ -194,15 +196,15 @@
      * with a given probability per traversal step.
      *
      * In any strategy along these lines, because CASes updating
-     * fields may fail, the actual slack may exceed targeted
-     * slack. However, they may be retried at any time to maintain
-     * targets.  Even when using very small slack values, this
-     * approach works well for dual queues because it allows all
-     * operations up to the point of matching or appending an item
-     * (hence potentially allowing progress by another thread) to be
-     * read-only, thus not introducing any further contention. As
-     * described below, we implement this by performing slack
-     * maintenance retries only after these points.
+     * fields may fail, the actual slack may exceed targeted slack.
+     * However, they may be retried at any time to maintain targets.
+     * Even when using very small slack values, this approach works
+     * well for dual queues because it allows all operations up to the
+     * point of matching or appending an item (hence potentially
+     * allowing progress by another thread) to be read-only, thus not
+     * introducing any further contention.  As described below, we
+     * implement this by performing slack maintenance retries only
+     * after these points.
      *
      * As an accompaniment to such techniques, traversal overhead can
      * be further reduced without increasing contention of head
@@ -221,7 +223,7 @@
      * (Similar issues arise in non-GC environments.)  To cope with
      * this in our implementation, upon CASing to advance the head
      * pointer, we set the "next" link of the previous head to point
-     * only to itself; thus limiting the length of connected dead lists.
+     * only to itself; thus limiting the length of chains of dead nodes.
      * (We also take similar care to wipe out possibly garbage
      * retaining values held in other Node fields.)  However, doing so
      * adds some further complexity to traversal: If any "next"
@@ -264,15 +266,6 @@
      * interior nodes) except in the case of cancellation/removal (see
      * below).
      *
-     * We allow both the head and tail fields to be null before any
-     * nodes are enqueued; initializing upon first append.  This
-     * simplifies some other logic, as well as providing more
-     * efficient explicit control paths instead of letting JVMs insert
-     * implicit NullPointerExceptions when they are null.  While not
-     * currently fully implemented, we also leave open the possibility
-     * of re-nulling these fields when empty (which is complicated to
-     * arrange, for little benefit.)
-     *
      * All enqueue/dequeue operations are handled by the single method
      * "xfer" with parameters indicating whether to act as some form
      * of offer, put, poll, take, or transfer (each possibly with
@@ -280,44 +273,40 @@
      * method outweighs the code bulk and maintenance problems of
      * using separate methods for each case.
      *
-     * Operation consists of up to three phases. The first is
-     * implemented within method xfer, the second in tryAppend, and
-     * the third in method awaitMatch.
+     * Operation consists of up to two phases. The first is implemented
+     * in method xfer, the second in method awaitMatch.
      *
-     * 1. Try to match an existing node
+     * 1. Traverse until matching or appending (method xfer)
      *
-     *    Starting at head, skip already-matched nodes until finding
-     *    an unmatched node of opposite mode, if one exists, in which
-     *    case matching it and returning, also if necessary updating
-     *    head to one past the matched node (or the node itself if the
-     *    list has no other unmatched nodes). If the CAS misses, then
-     *    a loop retries advancing head by two steps until either
-     *    success or the slack is at most two. By requiring that each
-     *    attempt advances head by two (if applicable), we ensure that
-     *    the slack does not grow without bound. Traversals also check
-     *    if the initial head is now off-list, in which case they
-     *    start at the new head.
+     *    Conceptually, we simply traverse all nodes starting from head.
+     *    If we encounter an unmatched node of opposite mode, we match
+     *    it and return, also updating head (by at least 2 hops) to
+     *    one past the matched node (or the node itself if it's the
+     *    pinned trailing node).  Traversals also check for the
+     *    possibility of falling off-list, in which case they restart.
      *
-     *    If no candidates are found and the call was untimed
-     *    poll/offer, (argument "how" is NOW) return.
+     *    If the trailing node of the list is reached, a match is not
+     *    possible.  If this call was untimed poll or tryTransfer
+     *    (argument "how" is NOW), return empty-handed immediately.
+     *    Else a new node is CAS-appended.  On successful append, if
+     *    this call was ASYNC (e.g. offer), an element was
+     *    successfully added to the end of the queue and we return.
      *
-     * 2. Try to append a new node (method tryAppend)
+     *    Of course, this naive traversal is O(n) when no match is
+     *    possible.  We optimize the traversal by maintaining a tail
+     *    pointer, which is expected to be "near" the end of the list.
+     *    It is only safe to fast-forward to tail (in the presence of
+     *    arbitrary concurrent changes) if it is pointing to a node of
+     *    the same mode, even if it is dead (in this case no preceding
+     *    node could still be matchable by this traversal).  If we
+     *    need to restart due to falling off-list, we can again
+     *    fast-forward to tail, but only if it has changed since the
+     *    last traversal (else we might loop forever).  If tail cannot
+     *    be used, traversal starts at head (but in this case we
+     *    expect to be able to match near head).  As with head, we
+     *    CAS-advance the tail pointer by at least two hops.
      *
-     *    Starting at current tail pointer, find the actual last node
-     *    and try to append a new node (or if head was null, establish
-     *    the first node). Nodes can be appended only if their
-     *    predecessors are either already matched or are of the same
-     *    mode. If we detect otherwise, then a new node with opposite
-     *    mode must have been appended during traversal, so we must
-     *    restart at phase 1. The traversal and update steps are
-     *    otherwise similar to phase 1: Retrying upon CAS misses and
-     *    checking for staleness.  In particular, if a self-link is
-     *    encountered, then we can safely jump to a node on the list
-     *    by continuing the traversal at current head.
-     *
-     *    On successful append, if the call was ASYNC, return.
-     *
-     * 3. Await match or cancellation (method awaitMatch)
+     * 2. Await match or cancellation (method awaitMatch)
      *
      *    Wait for another thread to match node; instead cancelling if
      *    the current thread was interrupted or the wait timed out. On
@@ -371,12 +360,12 @@
      * from, the head of list.
      *
      * Without taking these into account, it would be possible for an
-     * unbounded number of supposedly removed nodes to remain
-     * reachable.  Situations leading to such buildup are uncommon but
-     * can occur in practice; for example when a series of short timed
-     * calls to poll repeatedly time out but never otherwise fall off
-     * the list because of an untimed call to take at the front of the
-     * queue.
+     * unbounded number of supposedly removed nodes to remain reachable.
+     * Situations leading to such buildup are uncommon but can occur
+     * in practice; for example when a series of short timed calls to
+     * poll repeatedly time out at the trailing node but otherwise
+     * never fall off the list because of an untimed call to take() at
+     * the front of the queue.
      *
      * When these cases arise, rather than always retraversing the
      * entire list to find an actual predecessor to unlink (which
@@ -389,10 +378,9 @@
      * We perform sweeps by the thread hitting threshold (rather than
      * background threads or by spreading work to other threads)
      * because in the main contexts in which removal occurs, the
-     * caller is already timed-out, cancelled, or performing a
-     * potentially O(n) operation (e.g. remove(x)), none of which are
-     * time-critical enough to warrant the overhead that alternatives
-     * would impose on other threads.
+     * caller is timed-out or cancelled, which are not time-critical
+     * enough to warrant the overhead that alternatives would impose
+     * on other threads.
      *
      * Because the sweepVotes estimate is conservative, and because
      * nodes become unlinked "naturally" as they fall off the head of
@@ -404,6 +392,13 @@
      * quiescent queues. The value defined below was chosen
      * empirically to balance these under various timeout scenarios.
      *
+     * Because traversal operations on the linked list of nodes are a
+     * natural opportunity to sweep dead nodes, we generally do so,
+     * including all the operations that might remove elements as they
+     * traverse, such as removeIf and Iterator.remove.  This largely
+     * eliminates long chains of dead interior nodes, except from
+     * cancelled or timed out blocking operations.
+     *
      * Note that we cannot self-link unlinked interior nodes during
      * sweeps. However, the associated garbage chains terminate when
      * some successor ultimately falls off the head of the list and is
@@ -444,55 +439,72 @@
 
     /**
      * Queue nodes. Uses Object, not E, for items to allow forgetting
-     * them after use.  Relies heavily on Unsafe mechanics to minimize
-     * unnecessary ordering constraints: Writes that are intrinsically
-     * ordered wrt other accesses or CASes use simple relaxed forms.
+     * them after use.  Writes that are intrinsically ordered wrt
+     * other accesses or CASes use simple relaxed forms.
      */
     static final class Node {
         final boolean isData;   // false if this is a request node
         volatile Object item;   // initially non-null if isData; CASed to match
         volatile Node next;
-        volatile Thread waiter; // null until waiting
+        volatile Thread waiter; // null when not waiting for a match
 
-        // CAS methods for fields
+        /**
+         * Constructs a data node holding item if item is non-null,
+         * else a request node.  Uses relaxed write because item can
+         * only be seen after piggy-backing publication via CAS.
+         */
+        Node(Object item) {
+            ITEM.set(this, item);
+            isData = (item != null);
+        }
+
+        /** Constructs a (matched data) dummy node. */
+        Node() {
+            isData = true;
+        }
+
         final boolean casNext(Node cmp, Node val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            // assert val != null;
+            return NEXT.compareAndSet(this, cmp, val);
         }
 
         final boolean casItem(Object cmp, Object val) {
-            // assert cmp == null || cmp.getClass() != Node.class;
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
-        }
-
-        /**
-         * Constructs a new node.  Uses relaxed write because item can
-         * only be seen after publication via casNext.
-         */
-        Node(Object item, boolean isData) {
-            U.putObject(this, ITEM, item); // relaxed write
-            this.isData = isData;
+            // assert isData == (cmp != null);
+            // assert isData == (val == null);
+            // assert !(cmp instanceof Node);
+            return ITEM.compareAndSet(this, cmp, val);
         }
 
         /**
          * Links node to itself to avoid garbage retention.  Called
          * only after CASing head field, so uses relaxed write.
          */
-        final void forgetNext() {
-            U.putObject(this, NEXT, this);
+        final void selfLink() {
+            // assert isMatched();
+            NEXT.setRelease(this, this);
+        }
+
+        final void appendRelaxed(Node next) {
+            // assert next != null;
+            // assert this.next == null;
+            NEXT.set(this, next);
         }
 
         /**
-         * Sets item to self and waiter to null, to avoid garbage
-         * retention after matching or cancelling. Uses relaxed writes
-         * because order is already constrained in the only calling
-         * contexts: item is forgotten only after volatile/atomic
-         * mechanics that extract items.  Similarly, clearing waiter
-         * follows either CAS or return from park (if ever parked;
-         * else we don't care).
+         * Sets item (of a request node) to self and waiter to null,
+         * to avoid garbage retention after matching or cancelling.
+         * Uses relaxed writes because order is already constrained in
+         * the only calling contexts: item is forgotten only after
+         * volatile/atomic mechanics that extract items, and visitors
+         * of request nodes only ever check whether item is null.
+         * Similarly, clearing waiter follows either CAS or return
+         * from park (if ever parked; else we don't care).
          */
         final void forgetContents() {
-            U.putObject(this, ITEM, this);
-            U.putObject(this, WAITER, null);
+            // assert isMatched();
+            if (!isData)
+                ITEM.set(this, this);
+            WAITER.set(this, null);
         }
 
         /**
@@ -500,15 +512,16 @@
          * case of artificial matches due to cancellation.
          */
         final boolean isMatched() {
-            Object x = item;
-            return (x == this) || ((x == null) == isData);
+            return isData == (item == null);
         }
 
-        /**
-         * Returns true if this is an unmatched request node.
-         */
-        final boolean isUnmatchedRequest() {
-            return !isData && item == null;
+        /** Tries to CAS-match this node; if successful, wakes waiter. */
+        final boolean tryMatch(Object cmp, Object val) {
+            if (casItem(cmp, val)) {
+                LockSupport.unpark(waiter);
+                return true;
+            }
+            return false;
         }
 
         /**
@@ -518,69 +531,118 @@
          */
         final boolean cannotPrecede(boolean haveData) {
             boolean d = isData;
-            Object x;
-            return d != haveData && (x = item) != this && (x != null) == d;
-        }
-
-        /**
-         * Tries to artificially match a data node -- used by remove.
-         */
-        final boolean tryMatchData() {
-            // assert isData;
-            Object x = item;
-            if (x != null && x != this && casItem(x, null)) {
-                LockSupport.unpark(waiter);
-                return true;
-            }
-            return false;
+            return d != haveData && d != (item == null);
         }
 
         private static final long serialVersionUID = -3375979862319811754L;
-
-        // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long ITEM;
-        private static final long NEXT;
-        private static final long WAITER;
-        static {
-            try {
-                ITEM = U.objectFieldOffset
-                    (Node.class.getDeclaredField("item"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-                WAITER = U.objectFieldOffset
-                    (Node.class.getDeclaredField("waiter"));
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-        }
     }
 
-    /** head of the queue; null until first enqueue */
+    /**
+     * A node from which the first live (non-matched) node (if any)
+     * can be reached in O(1) time.
+     * Invariants:
+     * - all live nodes are reachable from head via .next
+     * - head != null
+     * - (tmp = head).next != tmp || tmp != head
+     * Non-invariants:
+     * - head may or may not be live
+     * - it is permitted for tail to lag behind head, that is, for tail
+     *   to not be reachable from head!
+     */
     transient volatile Node head;
 
-    /** tail of the queue; null until first append */
+    /**
+     * A node from which the last node on list (that is, the unique
+     * node with node.next == null) can be reached in O(1) time.
+     * Invariants:
+     * - the last node is always reachable from tail via .next
+     * - tail != null
+     * Non-invariants:
+     * - tail may or may not be live
+     * - it is permitted for tail to lag behind head, that is, for tail
+     *   to not be reachable from head!
+     * - tail.next may or may not be self-linked.
+     */
     private transient volatile Node tail;
 
-    /** The number of apparent failures to unsplice removed nodes */
+    /** The number of apparent failures to unsplice cancelled nodes */
     private transient volatile int sweepVotes;
 
-    // CAS methods for fields
     private boolean casTail(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+        // assert cmp != null;
+        // assert val != null;
+        return TAIL.compareAndSet(this, cmp, val);
     }
 
     private boolean casHead(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return HEAD.compareAndSet(this, cmp, val);
     }
 
-    private boolean casSweepVotes(int cmp, int val) {
-        return U.compareAndSwapInt(this, SWEEPVOTES, cmp, val);
+    /** Atomic version of ++sweepVotes. */
+    private int incSweepVotes() {
+        return (int) SWEEPVOTES.getAndAdd(this, 1) + 1;
     }
 
-    /*
-     * Possible values for "how" argument in xfer method.
+    /**
+     * Tries to CAS pred.next (or head, if pred is null) from c to p.
+     * Caller must ensure that we're not unlinking the trailing node.
      */
+    private boolean tryCasSuccessor(Node pred, Node c, Node p) {
+        // assert p != null;
+        // assert c.isData != (c.item != null);
+        // assert c != p;
+        if (pred != null)
+            return pred.casNext(c, p);
+        if (casHead(c, p)) {
+            c.selfLink();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Collapses dead (matched) nodes between pred and q.
+     * @param pred the last known live node, or null if none
+     * @param c the first dead node
+     * @param p the last dead node
+     * @param q p.next: the next live node, or null if at end
+     * @return pred if pred still alive and CAS succeeded; else p
+     */
+    private Node skipDeadNodes(Node pred, Node c, Node p, Node q) {
+        // assert pred != c;
+        // assert p != q;
+        // assert c.isMatched();
+        // assert p.isMatched();
+        if (q == null) {
+            // Never unlink trailing node.
+            if (c == p) return pred;
+            q = p;
+        }
+        return (tryCasSuccessor(pred, c, q)
+                && (pred == null || !pred.isMatched()))
+            ? pred : p;
+    }
+
+    /**
+     * Collapses dead (matched) nodes from h (which was once head) to p.
+     * Caller ensures all nodes from h up to and including p are dead.
+     */
+    private void skipDeadNodesNearHead(Node h, Node p) {
+        // assert h != null;
+        // assert h != p;
+        // assert p.isMatched();
+        for (;;) {
+            final Node q;
+            if ((q = p.next) == null) break;
+            else if (!q.isMatched()) { p = q; break; }
+            else if (p == (p = q)) return;
+        }
+        if (casHead(h, p))
+            h.selfLink();
+    }
+
+    /* Possible values for "how" argument in xfer method. */
+
     private static final int NOW   = 0; // for untimed poll, tryTransfer
     private static final int ASYNC = 1; // for offer, put, add
     private static final int SYNC  = 2; // for transfer, take
@@ -596,84 +658,32 @@
      * @return an item if matched, else e
      * @throws NullPointerException if haveData mode but e is null
      */
+    @SuppressWarnings("unchecked")
     private E xfer(E e, boolean haveData, int how, long nanos) {
         if (haveData && (e == null))
             throw new NullPointerException();
-        Node s = null;                        // the node to append, if needed
 
-        retry:
-        for (;;) {                            // restart on append race
-
-            for (Node h = head, p = h; p != null;) { // find & match first node
-                boolean isData = p.isData;
-                Object item = p.item;
-                if (item != p && (item != null) == isData) { // unmatched
-                    if (isData == haveData)   // can't match
-                        break;
-                    if (p.casItem(item, e)) { // match
-                        for (Node q = p; q != h;) {
-                            Node n = q.next;  // update by 2 unless singleton
-                            if (head == h && casHead(h, n == null ? q : n)) {
-                                h.forgetNext();
-                                break;
-                            }                 // advance and retry
-                            if ((h = head)   == null ||
-                                (q = h.next) == null || !q.isMatched())
-                                break;        // unless slack < 2
-                        }
-                        LockSupport.unpark(p.waiter);
-                        @SuppressWarnings("unchecked") E itemE = (E) item;
-                        return itemE;
+        restart: for (Node s = null, t = null, h = null;;) {
+            for (Node p = (t != (t = tail) && t.isData == haveData) ? t
+                     : (h = head);; ) {
+                final Node q; final Object item;
+                if (p.isData != haveData
+                    && haveData == ((item = p.item) == null)) {
+                    if (h == null) h = head;
+                    if (p.tryMatch(item, e)) {
+                        if (h != p) skipDeadNodesNearHead(h, p);
+                        return (E) item;
                     }
                 }
-                Node n = p.next;
-                p = (p != n) ? n : (h = head); // Use head if p offlist
-            }
-
-            if (how != NOW) {                 // No matches available
-                if (s == null)
-                    s = new Node(e, haveData);
-                Node pred = tryAppend(s, haveData);
-                if (pred == null)
-                    continue retry;           // lost race vs opposite mode
-                if (how != ASYNC)
-                    return awaitMatch(s, pred, e, (how == TIMED), nanos);
-            }
-            return e; // not waiting
-        }
-    }
-
-    /**
-     * Tries to append node s as tail.
-     *
-     * @param s the node to append
-     * @param haveData true if appending in data mode
-     * @return null on failure due to losing race with append in
-     * different mode, else s's predecessor, or s itself if no
-     * predecessor
-     */
-    private Node tryAppend(Node s, boolean haveData) {
-        for (Node t = tail, p = t;;) {        // move p to last node and append
-            Node n, u;                        // temps for reads of next & tail
-            if (p == null && (p = head) == null) {
-                if (casHead(null, s))
-                    return s;                 // initialize
-            }
-            else if (p.cannotPrecede(haveData))
-                return null;                  // lost race vs opposite mode
-            else if ((n = p.next) != null)    // not last; keep traversing
-                p = p != t && t != (u = tail) ? (t = u) : // stale tail
-                    (p != n) ? n : null;      // restart if off list
-            else if (!p.casNext(null, s))
-                p = p.next;                   // re-read on CAS failure
-            else {
-                if (p != t) {                 // update if slack now >= 2
-                    while ((tail != t || !casTail(t, s)) &&
-                           (t = tail)   != null &&
-                           (s = t.next) != null && // advance and retry
-                           (s = s.next) != null && s != t);
+                if ((q = p.next) == null) {
+                    if (how == NOW) return e;
+                    if (s == null) s = new Node(e);
+                    if (!p.casNext(null, s)) continue;
+                    if (p != t) casTail(t, s);
+                    if (how == ASYNC) return e;
+                    return awaitMatch(s, p, e, (how == TIMED), nanos);
                 }
-                return p;
+                if (p == (p = q)) continue restart;
             }
         }
     }
@@ -682,9 +692,9 @@
      * Spins/yields/blocks until node s is matched or caller gives up.
      *
      * @param s the waiting node
-     * @param pred the predecessor of s, or s itself if it has no
-     * predecessor, or null if unknown (the null case does not occur
-     * in any current calls but may in possible future extensions)
+     * @param pred the predecessor of s, or null if unknown (the null
+     * case does not occur in any current calls but may in possible
+     * future extensions)
      * @param e the comparison value for checking match
      * @param timed if true, wait only until timeout elapses
      * @param nanos timeout in nanosecs, used only if timed is true
@@ -697,17 +707,20 @@
         ThreadLocalRandom randomYields = null; // bound if needed
 
         for (;;) {
-            Object item = s.item;
-            if (item != e) {                  // matched
+            final Object item;
+            if ((item = s.item) != e) {       // matched
                 // assert item != s;
                 s.forgetContents();           // avoid garbage
                 @SuppressWarnings("unchecked") E itemE = (E) item;
                 return itemE;
             }
             else if (w.isInterrupted() || (timed && nanos <= 0L)) {
-                unsplice(pred, s);           // try to unlink and cancel
-                if (s.casItem(e, s))         // return normally if lost CAS
+                // try to cancel and unlink
+                if (s.casItem(e, s.isData ? null : s)) {
+                    unsplice(pred, s);
                     return e;
+                }
+                // return normally if lost CAS
             }
             else if (spins < 0) {            // establish spins at/near front
                 if ((spins = spinsFor(pred, s.isData)) > 0)
@@ -751,34 +764,32 @@
     /* -------------- Traversal methods -------------- */
 
     /**
-     * Returns the successor of p, or the head node if p.next has been
-     * linked to self, which will only be true if traversing with a
-     * stale pointer that is now off the list.
-     */
-    final Node succ(Node p) {
-        Node next = p.next;
-        return (p == next) ? head : next;
-    }
-
-    /**
      * Returns the first unmatched data node, or null if none.
-     * Callers must recheck if the returned node's item field is null
-     * or self-linked before using.
+     * Callers must recheck if the returned node is unmatched
+     * before using.
      */
     final Node firstDataNode() {
+        Node first = null;
         restartFromHead: for (;;) {
-            for (Node p = head; p != null;) {
-                Object item = p.item;
-                if (p.isData) {
-                    if (item != null && item != p)
-                        return p;
+            Node h = head, p = h;
+            while (p != null) {
+                if (p.item != null) {
+                    if (p.isData) {
+                        first = p;
+                        break;
+                    }
                 }
-                else if (item == null)
+                else if (!p.isData)
                     break;
-                if (p == (p = p.next))
+                final Node q;
+                if ((q = p.next) == null)
+                    break;
+                if (p == (p = q))
                     continue restartFromHead;
             }
-            return null;
+            if (p != h && casHead(h, p))
+                h.selfLink();
+            return first;
         }
     }
 
@@ -811,7 +822,7 @@
             for (Node p = head; p != null;) {
                 Object item = p.item;
                 if (p.isData) {
-                    if (item != null && item != p) {
+                    if (item != null) {
                         if (a == null)
                             a = new String[4];
                         else if (size == a.length)
@@ -840,7 +851,7 @@
             for (Node p = head; p != null;) {
                 Object item = p.item;
                 if (p.isData) {
-                    if (item != null && item != p) {
+                    if (item != null) {
                         if (x == null)
                             x = new Object[4];
                         else if (size == x.length)
@@ -919,76 +930,50 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
-        if (a == null) throw new NullPointerException();
+        Objects.requireNonNull(a);
         return (T[]) toArrayInternal(a);
     }
 
+    /**
+     * Weakly-consistent iterator.
+     *
+     * Lazily updated ancestor is expected to be amortized O(1) remove(),
+     * but O(n) in the worst case, when lastRet is concurrently deleted.
+     */
     final class Itr implements Iterator<E> {
         private Node nextNode;   // next node to return item for
         private E nextItem;      // the corresponding item
         private Node lastRet;    // last returned node, to support remove
-        private Node lastPred;   // predecessor to unlink lastRet
+        private Node ancestor;   // Helps unlink lastRet on remove()
 
         /**
-         * Moves to next node after prev, or first node if prev null.
+         * Moves to next node after pred, or first node if pred null.
          */
-        private void advance(Node prev) {
-            /*
-             * To track and avoid buildup of deleted nodes in the face
-             * of calls to both Queue.remove and Itr.remove, we must
-             * include variants of unsplice and sweep upon each
-             * advance: Upon Itr.remove, we may need to catch up links
-             * from lastPred, and upon other removes, we might need to
-             * skip ahead from stale nodes and unsplice deleted ones
-             * found while advancing.
-             */
-
-            Node r, b; // reset lastPred upon possible deletion of lastRet
-            if ((r = lastRet) != null && !r.isMatched())
-                lastPred = r;    // next lastPred is old lastRet
-            else if ((b = lastPred) == null || b.isMatched())
-                lastPred = null; // at start of list
-            else {
-                Node s, n;       // help with removal of lastPred.next
-                while ((s = b.next) != null &&
-                       s != b && s.isMatched() &&
-                       (n = s.next) != null && n != s)
-                    b.casNext(s, n);
-            }
-
-            this.lastRet = prev;
-
-            for (Node p = prev, s, n;;) {
-                s = (p == null) ? head : p.next;
-                if (s == null)
-                    break;
-                else if (s == p) {
-                    p = null;
-                    continue;
+        @SuppressWarnings("unchecked")
+        private void advance(Node pred) {
+            for (Node p = (pred == null) ? head : pred.next, c = p;
+                 p != null; ) {
+                final Object item;
+                if ((item = p.item) != null && p.isData) {
+                    nextNode = p;
+                    nextItem = (E) item;
+                    if (c != p)
+                        tryCasSuccessor(pred, c, p);
+                    return;
                 }
-                Object item = s.item;
-                if (s.isData) {
-                    if (item != null && item != s) {
-                        @SuppressWarnings("unchecked") E itemE = (E) item;
-                        nextItem = itemE;
-                        nextNode = s;
-                        return;
-                    }
+                else if (!p.isData && item == null)
+                    break;
+                if (c != p && !tryCasSuccessor(pred, c, c = p)) {
+                    pred = p;
+                    c = p = p.next;
                 }
-                else if (item == null)
-                    break;
-                // assert s.isMatched();
-                if (p == null)
-                    p = s;
-                else if ((n = s.next) == null)
-                    break;
-                else if (s == n)
-                    p = null;
-                else
-                    p.casNext(s, n);
+                else if (p == (p = p.next)) {
+                    pred = null;
+                    c = p = head;
+                }
             }
-            nextNode = null;
             nextItem = null;
+            nextNode = null;
         }
 
         Itr() {
@@ -1000,25 +985,67 @@
         }
 
         public final E next() {
-            Node p = nextNode;
-            if (p == null) throw new NoSuchElementException();
+            final Node p;
+            if ((p = nextNode) == null) throw new NoSuchElementException();
             E e = nextItem;
-            advance(p);
+            advance(lastRet = p);
             return e;
         }
 
+        public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            Node q = null;
+            for (Node p; (p = nextNode) != null; advance(q = p))
+                action.accept(nextItem);
+            if (q != null)
+                lastRet = q;
+        }
+
         public final void remove() {
             final Node lastRet = this.lastRet;
             if (lastRet == null)
                 throw new IllegalStateException();
             this.lastRet = null;
-            if (lastRet.tryMatchData())
-                unsplice(lastPred, lastRet);
+            if (lastRet.item == null)   // already deleted?
+                return;
+            // Advance ancestor, collapsing intervening dead nodes
+            Node pred = ancestor;
+            for (Node p = (pred == null) ? head : pred.next, c = p, q;
+                 p != null; ) {
+                if (p == lastRet) {
+                    final Object item;
+                    if ((item = p.item) != null)
+                        p.tryMatch(item, null);
+                    if ((q = p.next) == null) q = p;
+                    if (c != q) tryCasSuccessor(pred, c, q);
+                    ancestor = pred;
+                    return;
+                }
+                final Object item; final boolean pAlive;
+                if (pAlive = ((item = p.item) != null && p.isData)) {
+                    // exceptionally, nothing to do
+                }
+                else if (!p.isData && item == null)
+                    break;
+                if ((c != p && !tryCasSuccessor(pred, c, c = p)) || pAlive) {
+                    pred = p;
+                    c = p = p.next;
+                }
+                else if (p == (p = p.next)) {
+                    pred = null;
+                    c = p = head;
+                }
+            }
+            // traversal failed to find lastRet; must have been deleted;
+            // leave ancestor at original location to avoid overshoot;
+            // better luck next time!
+
+            // assert lastRet.isMatched();
         }
     }
 
     /** A customized variant of Spliterators.IteratorSpliterator */
-    final class LTQSpliterator<E> implements Spliterator<E> {
+    final class LTQSpliterator implements Spliterator<E> {
         static final int MAX_BATCH = 1 << 25;  // max batch array size;
         Node current;       // current node; null until initialized
         int batch;          // batch size for splits
@@ -1026,79 +1053,90 @@
         LTQSpliterator() {}
 
         public Spliterator<E> trySplit() {
-            Node p;
-            int b = batch;
-            int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
-            if (!exhausted &&
-                ((p = current) != null || (p = firstDataNode()) != null) &&
-                p.next != null) {
-                Object[] a = new Object[n];
-                int i = 0;
-                do {
-                    Object e = p.item;
-                    if (e != p && (a[i] = e) != null)
-                        ++i;
-                    if (p == (p = p.next))
-                        p = firstDataNode();
-                } while (p != null && i < n && p.isData);
-                if ((current = p) == null)
-                    exhausted = true;
-                if (i > 0) {
-                    batch = i;
-                    return Spliterators.spliterator
-                        (a, 0, i, (Spliterator.ORDERED |
-                                   Spliterator.NONNULL |
-                                   Spliterator.CONCURRENT));
+            Node p, q;
+            if ((p = current()) == null || (q = p.next) == null)
+                return null;
+            int i = 0, n = batch = Math.min(batch + 1, MAX_BATCH);
+            Object[] a = null;
+            do {
+                final Object item = p.item;
+                if (p.isData) {
+                    if (item != null) {
+                        if (a == null)
+                            a = new Object[n];
+                        a[i++] = item;
+                    }
+                } else if (item == null) {
+                    p = null;
+                    break;
                 }
-            }
-            return null;
+                if (p == (p = q))
+                    p = firstDataNode();
+            } while (p != null && (q = p.next) != null && i < n);
+            setCurrent(p);
+            return (i == 0) ? null :
+                Spliterators.spliterator(a, 0, i, (Spliterator.ORDERED |
+                                                   Spliterator.NONNULL |
+                                                   Spliterator.CONCURRENT));
         }
 
-        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
-            Node p;
-            if (action == null) throw new NullPointerException();
-            if (!exhausted &&
-                ((p = current) != null || (p = firstDataNode()) != null)) {
+            Objects.requireNonNull(action);
+            final Node p;
+            if ((p = current()) != null) {
+                current = null;
                 exhausted = true;
-                do {
-                    Object e = p.item;
-                    if (e != null && e != p)
-                        action.accept((E)e);
-                    if (p == (p = p.next))
-                        p = firstDataNode();
-                } while (p != null && p.isData);
+                forEachFrom(action, p);
             }
         }
 
         @SuppressWarnings("unchecked")
         public boolean tryAdvance(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
             Node p;
-            if (action == null) throw new NullPointerException();
-            if (!exhausted &&
-                ((p = current) != null || (p = firstDataNode()) != null)) {
-                Object e;
+            if ((p = current()) != null) {
+                E e = null;
                 do {
-                    if ((e = p.item) == p)
-                        e = null;
+                    final Object item = p.item;
+                    final boolean isData = p.isData;
                     if (p == (p = p.next))
-                        p = firstDataNode();
-                } while (e == null && p != null && p.isData);
-                if ((current = p) == null)
-                    exhausted = true;
+                        p = head;
+                    if (isData) {
+                        if (item != null) {
+                            e = (E) item;
+                            break;
+                        }
+                    }
+                    else if (item == null)
+                        p = null;
+                } while (p != null);
+                setCurrent(p);
                 if (e != null) {
-                    action.accept((E)e);
+                    action.accept(e);
                     return true;
                 }
             }
             return false;
         }
 
+        private void setCurrent(Node p) {
+            if ((current = p) == null)
+                exhausted = true;
+        }
+
+        private Node current() {
+            Node p;
+            if ((p = current) == null && !exhausted)
+                setCurrent(p = firstDataNode());
+            return p;
+        }
+
         public long estimateSize() { return Long.MAX_VALUE; }
 
         public int characteristics() {
-            return Spliterator.ORDERED | Spliterator.NONNULL |
-                Spliterator.CONCURRENT;
+            return (Spliterator.ORDERED |
+                    Spliterator.NONNULL |
+                    Spliterator.CONCURRENT);
         }
     }
 
@@ -1119,7 +1157,7 @@
      * @since 1.8
      */
     public Spliterator<E> spliterator() {
-        return new LTQSpliterator<E>();
+        return new LTQSpliterator();
     }
 
     /* -------------- Removal methods -------------- */
@@ -1129,10 +1167,15 @@
      * the given predecessor.
      *
      * @param pred a node that was at one time known to be the
-     * predecessor of s, or null or s itself if s is/was at head
+     * predecessor of s
      * @param s the node to be unspliced
      */
     final void unsplice(Node pred, Node s) {
+        // assert pred != null;
+        // assert pred != s;
+        // assert s != null;
+        // assert s.isMatched();
+        // assert (SWEEP_THRESHOLD & (SWEEP_THRESHOLD - 1)) == 0;
         s.waiter = null; // disable signals
         /*
          * See above for rationale. Briefly: if pred still points to
@@ -1141,13 +1184,13 @@
          * nor s are head or offlist, add to sweepVotes, and if enough
          * votes have accumulated, sweep.
          */
-        if (pred != null && pred != s && pred.next == s) {
+        if (pred != null && pred.next == s) {
             Node n = s.next;
             if (n == null ||
                 (n != s && pred.casNext(s, n) && pred.isMatched())) {
                 for (;;) {               // check if at, or could be, head
                     Node h = head;
-                    if (h == pred || h == s || h == null)
+                    if (h == pred || h == s)
                         return;          // at head or list empty
                     if (!h.isMatched())
                         break;
@@ -1155,21 +1198,12 @@
                     if (hn == null)
                         return;          // now empty
                     if (hn != h && casHead(h, hn))
-                        h.forgetNext();  // advance head
+                        h.selfLink();  // advance head
                 }
-                if (pred.next != pred && s.next != s) { // recheck if offlist
-                    for (;;) {           // sweep now if enough votes
-                        int v = sweepVotes;
-                        if (v < SWEEP_THRESHOLD) {
-                            if (casSweepVotes(v, v + 1))
-                                break;
-                        }
-                        else if (casSweepVotes(v, 0)) {
-                            sweep();
-                            break;
-                        }
-                    }
-                }
+                // sweep every SWEEP_THRESHOLD votes
+                if (pred.next != pred && s.next != s // recheck if offlist
+                    && (incSweepVotes() & (SWEEP_THRESHOLD - 1)) == 0)
+                    sweep();
             }
         }
     }
@@ -1194,35 +1228,10 @@
     }
 
     /**
-     * Main implementation of remove(Object)
-     */
-    private boolean findAndRemove(Object e) {
-        if (e != null) {
-            for (Node pred = null, p = head; p != null; ) {
-                Object item = p.item;
-                if (p.isData) {
-                    if (item != null && item != p && e.equals(item) &&
-                        p.tryMatchData()) {
-                        unsplice(pred, p);
-                        return true;
-                    }
-                }
-                else if (item == null)
-                    break;
-                pred = p;
-                if ((p = p.next) == pred) { // stale
-                    pred = null;
-                    p = head;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
      * Creates an initially empty {@code LinkedTransferQueue}.
      */
     public LinkedTransferQueue() {
+        head = tail = new Node();
     }
 
     /**
@@ -1235,8 +1244,18 @@
      *         of its elements are null
      */
     public LinkedTransferQueue(Collection<? extends E> c) {
-        this();
-        addAll(c);
+        Node h = null, t = null;
+        for (E e : c) {
+            Node newNode = new Node(Objects.requireNonNull(e));
+            if (h == null)
+                h = t = newNode;
+            else
+                t.appendRelaxed(t = newNode);
+        }
+        if (h == null)
+            h = t = new Node();
+        head = h;
+        tail = t;
     }
 
     /**
@@ -1255,8 +1274,7 @@
      * return {@code false}.
      *
      * @return {@code true} (as specified by
-     *  {@link java.util.concurrent.BlockingQueue#offer(Object,long,TimeUnit)
-     *  BlockingQueue.offer})
+     *  {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e, long timeout, TimeUnit unit) {
@@ -1368,15 +1386,12 @@
      * @throws IllegalArgumentException {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         int n = 0;
-        for (E e; (e = poll()) != null;) {
+        for (E e; (e = poll()) != null; n++)
             c.add(e);
-            ++n;
-        }
         return n;
     }
 
@@ -1385,15 +1400,12 @@
      * @throws IllegalArgumentException {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         int n = 0;
-        for (E e; n < maxElements && (e = poll()) != null;) {
+        for (E e; n < maxElements && (e = poll()) != null; n++)
             c.add(e);
-            ++n;
-        }
         return n;
     }
 
@@ -1415,7 +1427,7 @@
             for (Node p = head; p != null;) {
                 Object item = p.item;
                 if (p.isData) {
-                    if (item != null && item != p) {
+                    if (item != null) {
                         @SuppressWarnings("unchecked") E e = (E) item;
                         return e;
                     }
@@ -1443,7 +1455,7 @@
             for (Node p = head; p != null;) {
                 Object item = p.item;
                 if (p.isData) {
-                    if (item != null && item != p)
+                    if (item != null)
                         break;
                 }
                 else if (item == null)
@@ -1487,7 +1499,31 @@
      * @return {@code true} if this queue changed as a result of the call
      */
     public boolean remove(Object o) {
-        return findAndRemove(o);
+        if (o == null) return false;
+        restartFromHead: for (;;) {
+            for (Node p = head, pred = null; p != null; ) {
+                Node q = p.next;
+                final Object item;
+                if ((item = p.item) != null) {
+                    if (p.isData) {
+                        if (o.equals(item) && p.tryMatch(item, null)) {
+                            skipDeadNodes(pred, p, p, q);
+                            return true;
+                        }
+                        pred = p; p = q; continue;
+                    }
+                }
+                else if (!p.isData)
+                    break;
+                for (Node c = p;; q = p.next) {
+                    if (q == null || !q.isMatched()) {
+                        pred = skipDeadNodes(pred, c, p, q); p = q; break;
+                    }
+                    if (p == (p = q)) continue restartFromHead;
+                }
+            }
+            return false;
+        }
     }
 
     /**
@@ -1499,18 +1535,29 @@
      * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
-        if (o != null) {
-            for (Node p = head; p != null; p = succ(p)) {
-                Object item = p.item;
-                if (p.isData) {
-                    if (item != null && item != p && o.equals(item))
-                        return true;
+        if (o == null) return false;
+        restartFromHead: for (;;) {
+            for (Node p = head, pred = null; p != null; ) {
+                Node q = p.next;
+                final Object item;
+                if ((item = p.item) != null) {
+                    if (p.isData) {
+                        if (o.equals(item))
+                            return true;
+                        pred = p; p = q; continue;
+                    }
                 }
-                else if (item == null)
+                else if (!p.isData)
                     break;
+                for (Node c = p;; q = p.next) {
+                    if (q == null || !q.isMatched()) {
+                        pred = skipDeadNodes(pred, c, p, q); p = q; break;
+                    }
+                    if (p == (p = q)) continue restartFromHead;
+                }
             }
+            return false;
         }
-        return false;
     }
 
     /**
@@ -1518,8 +1565,7 @@
      * {@code LinkedTransferQueue} is not capacity constrained.
      *
      * @return {@code Integer.MAX_VALUE} (as specified by
-     *         {@link java.util.concurrent.BlockingQueue#remainingCapacity()
-     *         BlockingQueue.remainingCapacity})
+     *         {@link BlockingQueue#remainingCapacity()})
      */
     public int remainingCapacity() {
         return Integer.MAX_VALUE;
@@ -1551,33 +1597,149 @@
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
-        s.defaultReadObject();
-        for (;;) {
-            @SuppressWarnings("unchecked")
-            E item = (E) s.readObject();
-            if (item == null)
-                break;
+
+        // Read in elements until trailing null sentinel found
+        Node h = null, t = null;
+        for (Object item; (item = s.readObject()) != null; ) {
+            Node newNode = new Node(item);
+            if (h == null)
+                h = t = newNode;
             else
-                offer(item);
+                t.appendRelaxed(t = newNode);
+        }
+        if (h == null)
+            h = t = new Node();
+        head = h;
+        tail = t;
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    public void clear() {
+        bulkRemove(e -> true);
+    }
+
+    /**
+     * Tolerate this many consecutive dead nodes before CAS-collapsing.
+     * Amortized cost of clear() is (1 + 1/MAX_HOPS) CASes per element.
+     */
+    private static final int MAX_HOPS = 8;
+
+    /** Implementation of bulk remove methods. */
+    @SuppressWarnings("unchecked")
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        boolean removed = false;
+        restartFromHead: for (;;) {
+            int hops = MAX_HOPS;
+            // c will be CASed to collapse intervening dead nodes between
+            // pred (or head if null) and p.
+            for (Node p = head, c = p, pred = null, q; p != null; p = q) {
+                q = p.next;
+                final Object item; boolean pAlive;
+                if (pAlive = ((item = p.item) != null && p.isData)) {
+                    if (filter.test((E) item)) {
+                        if (p.tryMatch(item, null))
+                            removed = true;
+                        pAlive = false;
+                    }
+                }
+                else if (!p.isData && item == null)
+                    break;
+                if (pAlive || q == null || --hops == 0) {
+                    // p might already be self-linked here, but if so:
+                    // - CASing head will surely fail
+                    // - CASing pred's next will be useless but harmless.
+                    if ((c != p && !tryCasSuccessor(pred, c, c = p))
+                        || pAlive) {
+                        // if CAS failed or alive, abandon old pred
+                        hops = MAX_HOPS;
+                        pred = p;
+                        c = q;
+                    }
+                } else if (p == q)
+                    continue restartFromHead;
+            }
+            return removed;
         }
     }
 
-    // Unsafe mechanics
+    /**
+     * Runs action on each element found during a traversal starting at p.
+     * If p is null, the action is not run.
+     */
+    @SuppressWarnings("unchecked")
+    void forEachFrom(Consumer<? super E> action, Node p) {
+        for (Node pred = null; p != null; ) {
+            Node q = p.next;
+            final Object item;
+            if ((item = p.item) != null) {
+                if (p.isData) {
+                    action.accept((E) item);
+                    pred = p; p = q; continue;
+                }
+            }
+            else if (!p.isData)
+                break;
+            for (Node c = p;; q = p.next) {
+                if (q == null || !q.isMatched()) {
+                    pred = skipDeadNodes(pred, c, p, q); p = q; break;
+                }
+                if (p == (p = q)) { pred = null; p = head; break; }
+            }
+        }
+    }
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
-    private static final long SWEEPVOTES;
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        forEachFrom(action, head);
+    }
+
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle SWEEPVOTES;
+    static final VarHandle ITEM;
+    static final VarHandle NEXT;
+    static final VarHandle WAITER;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("tail"));
-            SWEEPVOTES = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("sweepVotes"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(LinkedTransferQueue.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(LinkedTransferQueue.class, "tail",
+                                   Node.class);
+            SWEEPVOTES = l.findVarHandle(LinkedTransferQueue.class, "sweepVotes",
+                                         int.class);
+            ITEM = l.findVarHandle(Node.class, "item", Object.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
+            WAITER = l.findVarHandle(Node.class, "waiter", Thread.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
 
         // Reduce the risk of rare disastrous classloading in first call to
diff --git a/ojluni/src/main/java/java/util/concurrent/Phaser.java b/ojluni/src/main/java/java/util/concurrent/Phaser.java
index 9ef9936..76cd707 100644
--- a/ojluni/src/main/java/java/util/concurrent/Phaser.java
+++ b/ojluni/src/main/java/java/util/concurrent/Phaser.java
@@ -35,14 +35,15 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.LockSupport;
 
 /**
  * A reusable synchronization barrier, similar in functionality to
- * {@link java.util.concurrent.CyclicBarrier CyclicBarrier} and
- * {@link java.util.concurrent.CountDownLatch CountDownLatch}
- * but supporting more flexible usage.
+ * {@link CyclicBarrier} and {@link CountDownLatch} but supporting
+ * more flexible usage.
  *
  * <p><b>Registration.</b> Unlike the case for other barriers, the
  * number of parties <em>registered</em> to synchronize on a phaser
@@ -152,49 +153,46 @@
  * <p>A {@code Phaser} may be used instead of a {@code CountDownLatch}
  * to control a one-shot action serving a variable number of parties.
  * The typical idiom is for the method setting this up to first
- * register, then start the actions, then deregister, as in:
+ * register, then start all the actions, then deregister, as in:
  *
  * <pre> {@code
  * void runTasks(List<Runnable> tasks) {
- *   final Phaser phaser = new Phaser(1); // "1" to register self
+ *   Phaser startingGate = new Phaser(1); // "1" to register self
  *   // create and start threads
- *   for (final Runnable task : tasks) {
- *     phaser.register();
- *     new Thread() {
- *       public void run() {
- *         phaser.arriveAndAwaitAdvance(); // await all creation
- *         task.run();
- *       }
- *     }.start();
+ *   for (Runnable task : tasks) {
+ *     startingGate.register();
+ *     new Thread(() -> {
+ *       startingGate.arriveAndAwaitAdvance();
+ *       task.run();
+ *     }).start();
  *   }
  *
- *   // allow threads to start and deregister self
- *   phaser.arriveAndDeregister();
+ *   // deregister self to allow threads to proceed
+ *   startingGate.arriveAndDeregister();
  * }}</pre>
  *
  * <p>One way to cause a set of threads to repeatedly perform actions
  * for a given number of iterations is to override {@code onAdvance}:
  *
  * <pre> {@code
- * void startTasks(List<Runnable> tasks, final int iterations) {
- *   final Phaser phaser = new Phaser() {
+ * void startTasks(List<Runnable> tasks, int iterations) {
+ *   Phaser phaser = new Phaser() {
  *     protected boolean onAdvance(int phase, int registeredParties) {
- *       return phase >= iterations || registeredParties == 0;
+ *       return phase >= iterations - 1 || registeredParties == 0;
  *     }
  *   };
  *   phaser.register();
- *   for (final Runnable task : tasks) {
+ *   for (Runnable task : tasks) {
  *     phaser.register();
- *     new Thread() {
- *       public void run() {
- *         do {
- *           task.run();
- *           phaser.arriveAndAwaitAdvance();
- *         } while (!phaser.isTerminated());
- *       }
- *     }.start();
+ *     new Thread(() -> {
+ *       do {
+ *         task.run();
+ *         phaser.arriveAndAwaitAdvance();
+ *       } while (!phaser.isTerminated());
+ *     }).start();
  *   }
- *   phaser.arriveAndDeregister(); // deregister self, don't wait
+ *   // allow threads to proceed; don't wait for them
+ *   phaser.arriveAndDeregister();
  * }}</pre>
  *
  * If the main task must later await termination, it
@@ -221,7 +219,6 @@
  *   phaser.arriveAndDeregister();
  * }}</pre>
  *
- *
  * <p>To create a set of {@code n} tasks using a tree of phasers, you
  * could use code of the following form, assuming a Task class with a
  * constructor accepting a {@code Phaser} that it registers with upon
@@ -348,10 +345,6 @@
     private final AtomicReference<QNode> evenQ;
     private final AtomicReference<QNode> oddQ;
 
-    private AtomicReference<QNode> queueFor(int phase) {
-        return ((phase & 1) == 0) ? evenQ : oddQ;
-    }
-
     /**
      * Returns message string for bounds exceptions on arrival.
      */
@@ -388,7 +381,7 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (U.compareAndSwapLong(this, STATE, s, s-=adjust)) {
+            if (STATE.compareAndSet(this, s, s-=adjust)) {
                 if (unarrived == 1) {
                     long n = s & PARTIES_MASK;  // base of next state
                     int nextUnarrived = (int)n >>> PARTIES_SHIFT;
@@ -401,12 +394,12 @@
                             n |= nextUnarrived;
                         int nextPhase = (phase + 1) & MAX_PHASE;
                         n |= (long)nextPhase << PHASE_SHIFT;
-                        U.compareAndSwapLong(this, STATE, s, n);
+                        STATE.compareAndSet(this, s, n);
                         releaseWaiters(phase);
                     }
                     else if (nextUnarrived == 0) { // propagate deregistration
                         phase = parent.doArrive(ONE_DEREGISTER);
-                        U.compareAndSwapLong(this, STATE, s, s | EMPTY);
+                        STATE.compareAndSet(this, s, s | EMPTY);
                     }
                     else
                         phase = parent.doArrive(ONE_ARRIVAL);
@@ -441,13 +434,13 @@
                 if (parent == null || reconcileState() == s) {
                     if (unarrived == 0)             // wait out advance
                         root.internalAwaitAdvance(phase, null);
-                    else if (U.compareAndSwapLong(this, STATE, s, s + adjust))
+                    else if (STATE.compareAndSet(this, s, s + adjust))
                         break;
                 }
             }
             else if (parent == null) {              // 1st root registration
                 long next = ((long)phase << PHASE_SHIFT) | adjust;
-                if (U.compareAndSwapLong(this, STATE, s, next))
+                if (STATE.compareAndSet(this, s, next))
                     break;
             }
             else {
@@ -459,8 +452,8 @@
                         // finish registration whenever parent registration
                         // succeeded, even when racing with termination,
                         // since these are part of the same "transaction".
-                        while (!U.compareAndSwapLong
-                               (this, STATE, s,
+                        while (!STATE.weakCompareAndSet
+                               (this, s,
                                 ((long)phase << PHASE_SHIFT) | adjust)) {
                             s = state;
                             phase = (int)(root.state >>> PHASE_SHIFT);
@@ -491,8 +484,8 @@
             // CAS to root phase with current parties, tripping unarrived
             while ((phase = (int)(root.state >>> PHASE_SHIFT)) !=
                    (int)(s >>> PHASE_SHIFT) &&
-                   !U.compareAndSwapLong
-                   (this, STATE, s,
+                   !STATE.weakCompareAndSet
+                   (this, s,
                     s = (((long)phase << PHASE_SHIFT) |
                          ((phase < 0) ? (s & COUNTS_MASK) :
                           (((p = (int)s >>> PARTIES_SHIFT) == 0) ? EMPTY :
@@ -681,7 +674,7 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (U.compareAndSwapLong(this, STATE, s, s -= ONE_ARRIVAL)) {
+            if (STATE.compareAndSet(this, s, s -= ONE_ARRIVAL)) {
                 if (unarrived > 1)
                     return root.internalAwaitAdvance(phase, null);
                 if (root != this)
@@ -696,7 +689,7 @@
                     n |= nextUnarrived;
                 int nextPhase = (phase + 1) & MAX_PHASE;
                 n |= (long)nextPhase << PHASE_SHIFT;
-                if (!U.compareAndSwapLong(this, STATE, s, n))
+                if (!STATE.compareAndSet(this, s, n))
                     return (int)(state >>> PHASE_SHIFT); // terminated
                 releaseWaiters(phase);
                 return nextPhase;
@@ -812,7 +805,7 @@
         final Phaser root = this.root;
         long s;
         while ((s = root.state) >= 0) {
-            if (U.compareAndSwapLong(root, STATE, s, s | TERMINATION_BIT)) {
+            if (STATE.compareAndSet(root, s, s | TERMINATION_BIT)) {
                 // signal all threads
                 releaseWaiters(0); // Waiters on evenQ
                 releaseWaiters(1); // Waiters on oddQ
@@ -1047,6 +1040,9 @@
                     node = new QNode(this, phase, false, false, 0L);
                     node.wasInterrupted = interrupted;
                 }
+                // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+                // else
+                //     Thread.onSpinWait();
             }
             else if (node.isReleasable()) // done or aborted
                 break;
@@ -1135,16 +1131,14 @@
         }
     }
 
-    // Unsafe mechanics
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long STATE;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (Phaser.class.getDeclaredField("state"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(Phaser.class, "state", long.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
 
         // Reduce the risk of rare disastrous classloading in first call to
diff --git a/ojluni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java b/ojluni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
index 644de86..c068dee 100644
--- a/ojluni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
@@ -35,12 +35,15 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.PriorityQueue;
 import java.util.Queue;
 import java.util.SortedSet;
@@ -48,10 +51,8 @@
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Consumer;
-
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
+import java.util.function.Predicate;
+import jdk.internal.misc.SharedSecrets;
 
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} that uses
@@ -64,15 +65,15 @@
  * non-comparable objects (doing so results in
  * {@code ClassCastException}).
  *
- * <p>This class and its iterator implement all of the
- * <em>optional</em> methods of the {@link Collection} and {@link
- * Iterator} interfaces.  The Iterator provided in method {@link
- * #iterator()} is <em>not</em> guaranteed to traverse the elements of
- * the PriorityBlockingQueue in any particular order. If you need
- * ordered traversal, consider using
- * {@code Arrays.sort(pq.toArray())}.  Also, method {@code drainTo}
- * can be used to <em>remove</em> some or all elements in priority
- * order and place them in another collection.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ * The Iterator provided in method {@link #iterator()} and the
+ * Spliterator provided in method {@link #spliterator()} are <em>not</em>
+ * guaranteed to traverse the elements of the PriorityBlockingQueue in
+ * any particular order. If you need ordered traversal, consider using
+ * {@code Arrays.sort(pq.toArray())}.  Also, method {@code drainTo} can
+ * be used to <em>remove</em> some or all elements in priority order and
+ * place them in another collection.
  *
  * <p>Operations on this class make no guarantees about the ordering
  * of elements with equal priority. If you need to enforce an
@@ -101,6 +102,10 @@
  *   }
  * }}</pre>
  *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this queue
@@ -163,12 +168,12 @@
     /**
      * Lock used for all public operations.
      */
-    private final ReentrantLock lock;
+    private final ReentrantLock lock = new ReentrantLock();
 
     /**
      * Condition for blocking when empty.
      */
-    private final Condition notEmpty;
+    private final Condition notEmpty = lock.newCondition();
 
     /**
      * Spinlock for allocation, acquired via CAS.
@@ -220,10 +225,8 @@
                                  Comparator<? super E> comparator) {
         if (initialCapacity < 1)
             throw new IllegalArgumentException();
-        this.lock = new ReentrantLock();
-        this.notEmpty = lock.newCondition();
         this.comparator = comparator;
-        this.queue = new Object[initialCapacity];
+        this.queue = new Object[Math.max(1, initialCapacity)];
     }
 
     /**
@@ -243,8 +246,6 @@
      *         of its elements are null
      */
     public PriorityBlockingQueue(Collection<? extends E> c) {
-        this.lock = new ReentrantLock();
-        this.notEmpty = lock.newCondition();
         boolean heapify = true; // true if not known to be in heap order
         boolean screen = true;  // true if must screen for nulls
         if (c instanceof SortedSet<?>) {
@@ -260,22 +261,29 @@
             if (pq.getClass() == PriorityBlockingQueue.class) // exact match
                 heapify = false;
         }
-        Object[] a = c.toArray();
-        int n = a.length;
-        // If c.toArray incorrectly doesn't return Object[], copy it.
-        if (a.getClass() != Object[].class)
-            a = Arrays.copyOf(a, n, Object[].class);
+        Object[] es = c.toArray();
+        int n = es.length;
+        // Android-changed: Defend against c.toArray (incorrectly) not returning Object[]
+        //                  (see b/204397945)
+        // if (c.getClass() != java.util.ArrayList.class)
+        if (es.getClass() != Object[].class)
+            es = Arrays.copyOf(es, n, Object[].class);
         if (screen && (n == 1 || this.comparator != null)) {
-            for (int i = 0; i < n; ++i)
-                if (a[i] == null)
+            for (Object e : es)
+                if (e == null)
                     throw new NullPointerException();
         }
-        this.queue = a;
+        this.queue = ensureNonEmpty(es);
         this.size = n;
         if (heapify)
             heapify();
     }
 
+    /** Ensures that queue[0] exists, helping peek() and poll(). */
+    private static Object[] ensureNonEmpty(Object[] es) {
+        return (es.length > 0) ? es : new Object[1];
+    }
+
     /**
      * Tries to grow array to accommodate at least one more element
      * (but normally expand by about 50%), giving up (allowing retry)
@@ -289,7 +297,7 @@
         lock.unlock(); // must release and then re-acquire main lock
         Object[] newArray = null;
         if (allocationSpinLock == 0 &&
-            U.compareAndSwapInt(this, ALLOCATIONSPINLOCK, 0, 1)) {
+            ALLOCATIONSPINLOCK.compareAndSet(this, 0, 1)) {
             try {
                 int newCap = oldCap + ((oldCap < 64) ?
                                        (oldCap + 2) : // grow faster if small
@@ -319,22 +327,23 @@
      * Mechanics for poll().  Call only while holding lock.
      */
     private E dequeue() {
-        int n = size - 1;
-        if (n < 0)
-            return null;
-        else {
-            Object[] array = queue;
-            E result = (E) array[0];
-            E x = (E) array[n];
-            array[n] = null;
-            Comparator<? super E> cmp = comparator;
-            if (cmp == null)
-                siftDownComparable(0, x, array, n);
-            else
-                siftDownUsingComparator(0, x, array, n, cmp);
-            size = n;
-            return result;
+        // assert lock.isHeldByCurrentThread();
+        final Object[] es;
+        final E result;
+
+        if ((result = (E) ((es = queue)[0])) != null) {
+            final int n;
+            final E x = (E) es[(n = --size)];
+            es[n] = null;
+            if (n > 0) {
+                final Comparator<? super E> cmp;
+                if ((cmp = comparator) == null)
+                    siftDownComparable(0, x, es, n);
+                else
+                    siftDownUsingComparator(0, x, es, n, cmp);
+            }
         }
+        return result;
     }
 
     /**
@@ -342,40 +351,38 @@
      * promoting x up the tree until it is greater than or equal to
      * its parent, or is the root.
      *
-     * To simplify and speed up coercions and comparisons. the
+     * To simplify and speed up coercions and comparisons, the
      * Comparable and Comparator versions are separated into different
      * methods that are otherwise identical. (Similarly for siftDown.)
-     * These methods are static, with heap state as arguments, to
-     * simplify use in light of possible comparator exceptions.
      *
      * @param k the position to fill
      * @param x the item to insert
-     * @param array the heap array
+     * @param es the heap array
      */
-    private static <T> void siftUpComparable(int k, T x, Object[] array) {
+    private static <T> void siftUpComparable(int k, T x, Object[] es) {
         Comparable<? super T> key = (Comparable<? super T>) x;
         while (k > 0) {
             int parent = (k - 1) >>> 1;
-            Object e = array[parent];
+            Object e = es[parent];
             if (key.compareTo((T) e) >= 0)
                 break;
-            array[k] = e;
+            es[k] = e;
             k = parent;
         }
-        array[k] = key;
+        es[k] = key;
     }
 
-    private static <T> void siftUpUsingComparator(int k, T x, Object[] array,
-                                       Comparator<? super T> cmp) {
+    private static <T> void siftUpUsingComparator(
+        int k, T x, Object[] es, Comparator<? super T> cmp) {
         while (k > 0) {
             int parent = (k - 1) >>> 1;
-            Object e = array[parent];
+            Object e = es[parent];
             if (cmp.compare(x, (T) e) >= 0)
                 break;
-            array[k] = e;
+            es[k] = e;
             k = parent;
         }
-        array[k] = x;
+        es[k] = x;
     }
 
     /**
@@ -385,67 +392,61 @@
      *
      * @param k the position to fill
      * @param x the item to insert
-     * @param array the heap array
+     * @param es the heap array
      * @param n heap size
      */
-    private static <T> void siftDownComparable(int k, T x, Object[] array,
-                                               int n) {
-        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;
+    private static <T> void siftDownComparable(int k, T x, Object[] es, int n) {
+        // assert 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 = es[child];
+            int right = child + 1;
+            if (right < n &&
+                ((Comparable<? super T>) c).compareTo((T) es[right]) > 0)
+                c = es[child = right];
+            if (key.compareTo((T) c) <= 0)
+                break;
+            es[k] = c;
+            k = child;
         }
+        es[k] = key;
     }
 
-    private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
-                                                    int n,
-                                                    Comparator<? super T> cmp) {
-        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;
+    private static <T> void siftDownUsingComparator(
+        int k, T x, Object[] es, int n, Comparator<? super T> cmp) {
+        // assert n > 0;
+        int half = n >>> 1;
+        while (k < half) {
+            int child = (k << 1) + 1;
+            Object c = es[child];
+            int right = child + 1;
+            if (right < n && cmp.compare((T) c, (T) es[right]) > 0)
+                c = es[child = right];
+            if (cmp.compare(x, (T) c) <= 0)
+                break;
+            es[k] = c;
+            k = child;
         }
+        es[k] = x;
     }
 
     /**
      * Establishes the heap invariant (described above) in the entire tree,
      * assuming nothing about the order of the elements prior to the call.
+     * This classic algorithm due to Floyd (1964) is known to be O(size).
      */
     private void heapify() {
-        Object[] array = queue;
-        int n = size;
-        int half = (n >>> 1) - 1;
-        Comparator<? super E> cmp = comparator;
-        if (cmp == null) {
-            for (int i = half; i >= 0; i--)
-                siftDownComparable(i, (E) array[i], array, n);
-        }
-        else {
-            for (int i = half; i >= 0; i--)
-                siftDownUsingComparator(i, (E) array[i], array, n, cmp);
-        }
+        final Object[] es = queue;
+        int n = size, i = (n >>> 1) - 1;
+        final Comparator<? super E> cmp;
+        if ((cmp = comparator) == null)
+            for (; i >= 0; i--)
+                siftDownComparable(i, (E) es[i], es, n);
+        else
+            for (; i >= 0; i--)
+                siftDownUsingComparator(i, (E) es[i], es, n, cmp);
     }
 
     /**
@@ -479,15 +480,15 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         int n, cap;
-        Object[] array;
-        while ((n = size) >= (cap = (array = queue).length))
-            tryGrow(array, cap);
+        Object[] es;
+        while ((n = size) >= (cap = (es = queue).length))
+            tryGrow(es, cap);
         try {
-            Comparator<? super E> cmp = comparator;
-            if (cmp == null)
-                siftUpComparable(n, e, array);
+            final Comparator<? super E> cmp;
+            if ((cmp = comparator) == null)
+                siftUpComparable(n, e, es);
             else
-                siftUpUsingComparator(n, e, array, cmp);
+                siftUpUsingComparator(n, e, es, cmp);
             size = n + 1;
             notEmpty.signal();
         } finally {
@@ -570,7 +571,7 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return (size == 0) ? null : (E) queue[0];
+            return (E) queue[0];
         } finally {
             lock.unlock();
         }
@@ -610,10 +611,9 @@
 
     private int indexOf(Object o) {
         if (o != null) {
-            Object[] array = queue;
-            int n = size;
-            for (int i = 0; i < n; i++)
-                if (o.equals(array[i]))
+            final Object[] es = queue;
+            for (int i = 0, n = size; i < n; i++)
+                if (o.equals(es[i]))
                     return i;
         }
         return -1;
@@ -623,23 +623,23 @@
      * Removes the ith element from queue.
      */
     private void removeAt(int i) {
-        Object[] array = queue;
-        int n = size - 1;
+        final Object[] es = queue;
+        final int n = size - 1;
         if (n == i) // removed last element
-            array[i] = null;
+            es[i] = null;
         else {
-            E moved = (E) array[n];
-            array[n] = null;
-            Comparator<? super E> cmp = comparator;
-            if (cmp == null)
-                siftDownComparable(i, moved, array, n);
+            E moved = (E) es[n];
+            es[n] = null;
+            final Comparator<? super E> cmp;
+            if ((cmp = comparator) == null)
+                siftDownComparable(i, moved, es, n);
             else
-                siftDownUsingComparator(i, moved, array, n, cmp);
-            if (array[i] == moved) {
+                siftDownUsingComparator(i, moved, es, n, cmp);
+            if (es[i] == moved) {
                 if (cmp == null)
-                    siftUpComparable(i, moved, array);
+                    siftUpComparable(i, moved, es);
                 else
-                    siftUpUsingComparator(i, moved, array, cmp);
+                    siftUpUsingComparator(i, moved, es, cmp);
             }
         }
         size = n;
@@ -672,14 +672,16 @@
 
     /**
      * Identity-based version for use in Itr.remove.
+     *
+     * @param o element to be removed from this queue, if present
      */
-    void removeEQ(Object o) {
+    void removeEq(Object o) {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            Object[] array = queue;
+            final Object[] es = queue;
             for (int i = 0, n = size; i < n; i++) {
-                if (o == array[i]) {
+                if (o == es[i]) {
                     removeAt(i);
                     break;
                 }
@@ -728,8 +730,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         if (maxElements <= 0)
@@ -756,11 +757,10 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            Object[] array = queue;
-            int n = size;
+            final Object[] es = queue;
+            for (int i = 0, n = size; i < n; i++)
+                es[i] = null;
             size = 0;
-            for (int i = 0; i < n; i++)
-                array[i] = null;
         } finally {
             lock.unlock();
         }
@@ -861,10 +861,9 @@
     final class Itr implements Iterator<E> {
         final Object[] array; // Array of all elements
         int cursor;           // index of next element to return
-        int lastRet;          // index of last element, or -1 if no such
+        int lastRet = -1;     // index of last element, or -1 if no such
 
         Itr(Object[] array) {
-            lastRet = -1;
             this.array = array;
         }
 
@@ -875,16 +874,28 @@
         public E next() {
             if (cursor >= array.length)
                 throw new NoSuchElementException();
-            lastRet = cursor;
-            return (E)array[cursor++];
+            return (E)array[lastRet = cursor++];
         }
 
         public void remove() {
             if (lastRet < 0)
                 throw new IllegalStateException();
-            removeEQ(array[lastRet]);
+            removeEq(array[lastRet]);
             lastRet = -1;
         }
+
+        public void forEachRemaining(Consumer<? super E> action) {
+            Objects.requireNonNull(action);
+            final Object[] es = array;
+            int i;
+            if ((i = cursor) < es.length) {
+                lastRet = -1;
+                cursor = es.length;
+                for (; i < es.length; i++)
+                    action.accept((E) es[i]);
+                lastRet = es.length - 1;
+            }
+        }
     }
 
     /**
@@ -922,7 +933,9 @@
         throws java.io.IOException, ClassNotFoundException {
         try {
             s.defaultReadObject();
-            this.queue = new Object[q.size()];
+            int sz = q.size();
+            SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, sz);
+            this.queue = new Object[Math.max(1, sz)];
             comparator = q.comparator();
             addAll(q);
         } finally {
@@ -930,68 +943,65 @@
         }
     }
 
-    // Similar to Collections.ArraySnapshotSpliterator but avoids
-    // commitment to toArray until needed
-    static final class PBQSpliterator<E> implements Spliterator<E> {
-        final PriorityBlockingQueue<E> queue;
-        Object[] array;
+    /**
+     * Immutable snapshot spliterator that binds to elements "late".
+     */
+    final class PBQSpliterator implements Spliterator<E> {
+        Object[] array;        // null until late-bound-initialized
         int index;
         int fence;
 
-        PBQSpliterator(PriorityBlockingQueue<E> queue, Object[] array,
-                       int index, int fence) {
-            this.queue = queue;
+        PBQSpliterator() {}
+
+        PBQSpliterator(Object[] array, int index, int fence) {
             this.array = array;
             this.index = index;
             this.fence = fence;
         }
 
-        final int getFence() {
-            int hi;
-            if ((hi = fence) < 0)
-                hi = fence = (array = queue.toArray()).length;
-            return hi;
+        private int getFence() {
+            if (array == null)
+                fence = (array = toArray()).length;
+            return fence;
         }
 
-        public PBQSpliterator<E> trySplit() {
+        public PBQSpliterator trySplit() {
             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
             return (lo >= mid) ? null :
-                new PBQSpliterator<E>(queue, array, lo, index = mid);
+                new PBQSpliterator(array, lo, index = mid);
         }
 
-        @SuppressWarnings("unchecked")
         public void forEachRemaining(Consumer<? super E> action) {
-            Object[] a; int i, hi; // hoist accesses and checks from loop
-            if (action == null)
-                throw new NullPointerException();
-            if ((a = array) == null)
-                fence = (a = queue.toArray()).length;
-            if ((hi = fence) <= a.length &&
-                (i = index) >= 0 && i < (index = hi)) {
-                do { action.accept((E)a[i]); } while (++i < hi);
-            }
+            Objects.requireNonNull(action);
+            final int hi = getFence(), lo = index;
+            final Object[] es = array;
+            index = hi;                 // ensure exhaustion
+            for (int i = lo; i < hi; i++)
+                action.accept((E) es[i]);
         }
 
         public boolean tryAdvance(Consumer<? super E> action) {
-            if (action == null)
-                throw new NullPointerException();
+            Objects.requireNonNull(action);
             if (getFence() > index && index >= 0) {
-                @SuppressWarnings("unchecked") E e = (E) array[index++];
-                action.accept(e);
+                action.accept((E) array[index++]);
                 return true;
             }
             return false;
         }
 
-        public long estimateSize() { return (long)(getFence() - index); }
+        public long estimateSize() { return getFence() - index; }
 
         public int characteristics() {
-            return Spliterator.NONNULL | Spliterator.SIZED | Spliterator.SUBSIZED;
+            return (Spliterator.NONNULL |
+                    Spliterator.SIZED |
+                    Spliterator.SUBSIZED);
         }
     }
 
     /**
      * Returns a {@link Spliterator} over the elements in this queue.
+     * The spliterator does not traverse elements in any particular order
+     * (the {@link Spliterator#ORDERED ORDERED} characteristic is not reported).
      *
      * <p>The returned spliterator is
      * <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
@@ -1006,18 +1016,106 @@
      * @since 1.8
      */
     public Spliterator<E> spliterator() {
-        return new PBQSpliterator<E>(this, null, 0, -1);
+        return new PBQSpliterator();
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long ALLOCATIONSPINLOCK;
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeIf(Predicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        return bulkRemove(filter);
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean removeAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> c.contains(e));
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean retainAll(Collection<?> c) {
+        Objects.requireNonNull(c);
+        return bulkRemove(e -> !c.contains(e));
+    }
+
+    // A tiny bit set implementation
+
+    private static long[] nBits(int n) {
+        return new long[((n - 1) >> 6) + 1];
+    }
+    private static void setBit(long[] bits, int i) {
+        bits[i >> 6] |= 1L << i;
+    }
+    private static boolean isClear(long[] bits, int i) {
+        return (bits[i >> 6] & (1L << i)) == 0;
+    }
+
+    /** Implementation of bulk remove methods. */
+    private boolean bulkRemove(Predicate<? super E> filter) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            final Object[] es = queue;
+            final int end = size;
+            int i;
+            // Optimize for initial run of survivors
+            for (i = 0; i < end && !filter.test((E) es[i]); i++)
+                ;
+            if (i >= end)
+                return false;
+            // Tolerate predicates that reentrantly access the
+            // collection for read, so traverse once to find elements
+            // to delete, a second pass to physically expunge.
+            final int beg = i;
+            final long[] deathRow = nBits(end - beg);
+            deathRow[0] = 1L;   // set bit 0
+            for (i = beg + 1; i < end; i++)
+                if (filter.test((E) es[i]))
+                    setBit(deathRow, i - beg);
+            int w = beg;
+            for (i = beg; i < end; i++)
+                if (isClear(deathRow, i - beg))
+                    es[w++] = es[i];
+            for (i = size = w; i < end; i++)
+                es[i] = null;
+            heapify();
+            return true;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public void forEach(Consumer<? super E> action) {
+        Objects.requireNonNull(action);
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            final Object[] es = queue;
+            for (int i = 0, n = size; i < n; i++)
+                action.accept((E) es[i]);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    // VarHandle mechanics
+    private static final VarHandle ALLOCATIONSPINLOCK;
     static {
         try {
-            ALLOCATIONSPINLOCK = U.objectFieldOffset
-                (PriorityBlockingQueue.class.getDeclaredField("allocationSpinLock"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            ALLOCATIONSPINLOCK = l.findVarHandle(PriorityBlockingQueue.class,
+                                                 "allocationSpinLock",
+                                                 int.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java b/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
index 6b9fcc3..be75ff4 100644
--- a/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
+++ b/ojluni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
@@ -77,14 +77,11 @@
  *     Executors.newScheduledThreadPool(1);
  *
  *   public void beepForAnHour() {
- *     final Runnable beeper = new Runnable() {
- *       public void run() { System.out.println("beep"); }
- *     };
- *     final ScheduledFuture&lt;?&lt; beeperHandle =
+ *     Runnable beeper = () -> System.out.println("beep");
+ *     ScheduledFuture<?> beeperHandle =
  *       scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
- *     scheduler.schedule(new Runnable() {
- *       public void run() { beeperHandle.cancel(true); }
- *     }, 60 * 60, SECONDS);
+ *     Runnable canceller = () -> beeperHandle.cancel(false);
+ *     scheduler.schedule(canceller, 1, HOURS);
  *   }
  * }}</pre>
  *
@@ -94,8 +91,7 @@
 public interface ScheduledExecutorService extends ExecutorService {
 
     /**
-     * Creates and executes a one-shot action that becomes enabled
-     * after the given delay.
+     * Submits a one-shot task that becomes enabled after the given delay.
      *
      * @param command the task to execute
      * @param delay the time from now to delay execution
@@ -105,14 +101,14 @@
      *         {@code null} upon completion
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
-     * @throws NullPointerException if command is null
+     * @throws NullPointerException if command or unit is null
      */
     public ScheduledFuture<?> schedule(Runnable command,
                                        long delay, TimeUnit unit);
 
     /**
-     * Creates and executes a ScheduledFuture that becomes enabled after the
-     * given delay.
+     * Submits a value-returning one-shot task that becomes enabled
+     * after the given delay.
      *
      * @param callable the function to execute
      * @param delay the time from now to delay execution
@@ -121,15 +117,15 @@
      * @return a ScheduledFuture that can be used to extract result or cancel
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
-     * @throws NullPointerException if callable is null
+     * @throws NullPointerException if callable or unit is null
      */
     public <V> ScheduledFuture<V> schedule(Callable<V> callable,
                                            long delay, TimeUnit unit);
 
     /**
-     * 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
+     * Submits a periodic action that becomes enabled first after the
+     * given initial delay, and subsequently with the given period;
+     * that is, executions will commence after
      * {@code initialDelay}, then {@code initialDelay + period}, then
      * {@code initialDelay + 2 * period}, and so on.
      *
@@ -140,8 +136,8 @@
      * via the returned future.
      * <li>The executor terminates, also resulting in task cancellation.
      * <li>An execution of the task throws an exception.  In this case
-     * calling {@link Future#get() get} on the returned future will
-     * throw {@link ExecutionException}.
+     * calling {@link Future#get() get} on the returned future will throw
+     * {@link ExecutionException}, holding the exception as its cause.
      * </ul>
      * Subsequent executions are suppressed.  Subsequent calls to
      * {@link Future#isDone isDone()} on the returned future will
@@ -162,7 +158,7 @@
      *         abnormal termination of a task execution.
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
-     * @throws NullPointerException if command is null
+     * @throws NullPointerException if command or unit is null
      * @throws IllegalArgumentException if period less than or equal to zero
      */
     public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
@@ -171,10 +167,10 @@
                                                   TimeUnit unit);
 
     /**
-     * Creates and executes a periodic action that becomes enabled first
-     * after the given initial delay, and subsequently with the
-     * given delay between the termination of one execution and the
-     * commencement of the next.
+     * Submits a periodic action that becomes enabled first after the
+     * given initial delay, and subsequently with the given delay
+     * between the termination of one execution and the commencement of
+     * the next.
      *
      * <p>The sequence of task executions continues indefinitely until
      * one of the following exceptional completions occur:
@@ -183,8 +179,8 @@
      * via the returned future.
      * <li>The executor terminates, also resulting in task cancellation.
      * <li>An execution of the task throws an exception.  In this case
-     * calling {@link Future#get() get} on the returned future will
-     * throw {@link ExecutionException}.
+     * calling {@link Future#get() get} on the returned future will throw
+     * {@link ExecutionException}, holding the exception as its cause.
      * </ul>
      * Subsequent executions are suppressed.  Subsequent calls to
      * {@link Future#isDone isDone()} on the returned future will
@@ -202,7 +198,7 @@
      *         abnormal termination of a task execution.
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
-     * @throws NullPointerException if command is null
+     * @throws NullPointerException if command or unit is null
      * @throws IllegalArgumentException if delay less than or equal to zero
      */
     public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
diff --git a/ojluni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java b/ojluni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
index 4249872..192df25 100644
--- a/ojluni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
+++ b/ojluni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -44,6 +44,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.ReentrantLock;
@@ -89,6 +90,11 @@
  * use {@code allowCoreThreadTimeOut} because this may leave the pool
  * without threads to handle tasks once they become eligible to run.
  *
+ * <p>As with {@code ThreadPoolExecutor}, if not otherwise specified,
+ * this class uses {@link Executors#defaultThreadFactory} as the
+ * default thread factory, and {@link ThreadPoolExecutor.AbortPolicy}
+ * as the default rejected execution handler.
+ *
  * <p><b>Extension notes:</b> This class overrides the
  * {@link ThreadPoolExecutor#execute(Runnable) execute} and
  * {@link AbstractExecutorService#submit(Runnable) submit}
@@ -162,6 +168,7 @@
      */
     private volatile boolean continueExistingPeriodicTasksAfterShutdown;
 
+    // Android-changed: Preserving behaviour on expired tasks (b/202927404)
     /**
      * False if should cancel non-periodic tasks on shutdown.
      */
@@ -294,10 +301,9 @@
          * Overrides FutureTask version so as to reset/requeue if periodic.
          */
         public void run() {
-            boolean periodic = isPeriodic();
-            if (!canRunInCurrentRunState(periodic))
+            if (!canRunInCurrentRunState(this))
                 cancel(false);
-            else if (!periodic)
+            else if (!isPeriodic())
                 super.run();
             else if (super.runAndReset()) {
                 setNextRunTime();
@@ -307,15 +313,20 @@
     }
 
     /**
-     * Returns true if can run a task given current run state
-     * and run-after-shutdown parameters.
-     *
-     * @param periodic true if this task periodic, false if delayed
+     * Returns true if can run a task given current run state and
+     * run-after-shutdown parameters.
      */
-    boolean canRunInCurrentRunState(boolean periodic) {
-        return isRunningOrShutdown(periodic ?
-                                   continueExistingPeriodicTasksAfterShutdown :
-                                   executeExistingDelayedTasksAfterShutdown);
+    boolean canRunInCurrentRunState(RunnableScheduledFuture<?> task) {
+        if (!isShutdown())
+            return true;
+        if (isStopped())
+            return false;
+        return task.isPeriodic()
+            ? continueExistingPeriodicTasksAfterShutdown
+            : (executeExistingDelayedTasksAfterShutdown
+            // Android-changed: Preserving behaviour on expired tasks (b/202927404)
+            //   || task.getDelay(NANOSECONDS) <= 0);
+              );
     }
 
     /**
@@ -334,9 +345,7 @@
             reject(task);
         else {
             super.getQueue().add(task);
-            if (isShutdown() &&
-                !canRunInCurrentRunState(task.isPeriodic()) &&
-                remove(task))
+            if (!canRunInCurrentRunState(task) && remove(task))
                 task.cancel(false);
             else
                 ensurePrestart();
@@ -350,13 +359,14 @@
      * @param task the task
      */
     void reExecutePeriodic(RunnableScheduledFuture<?> task) {
-        if (canRunInCurrentRunState(true)) {
+        if (canRunInCurrentRunState(task)) {
             super.getQueue().add(task);
-            if (!canRunInCurrentRunState(true) && remove(task))
-                task.cancel(false);
-            else
+            if (canRunInCurrentRunState(task) || !remove(task)) {
                 ensurePrestart();
+                return;
+            }
         }
+        task.cancel(false);
     }
 
     /**
@@ -369,23 +379,20 @@
             getExecuteExistingDelayedTasksAfterShutdownPolicy();
         boolean keepPeriodic =
             getContinueExistingPeriodicTasksAfterShutdownPolicy();
-        if (!keepDelayed && !keepPeriodic) {
-            for (Object e : q.toArray())
-                if (e instanceof RunnableScheduledFuture<?>)
-                    ((RunnableScheduledFuture<?>) e).cancel(false);
-            q.clear();
-        }
-        else {
-            // Traverse snapshot to avoid iterator exceptions
-            for (Object e : q.toArray()) {
-                if (e instanceof RunnableScheduledFuture) {
-                    RunnableScheduledFuture<?> t =
-                        (RunnableScheduledFuture<?>)e;
-                    if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
-                        t.isCancelled()) { // also remove if already cancelled
-                        if (q.remove(t))
-                            t.cancel(false);
-                    }
+        // Traverse snapshot to avoid iterator exceptions
+        // TODO: implement and use efficient removeIf
+        // super.getQueue().removeIf(...);
+        for (Object e : q.toArray()) {
+            if (e instanceof RunnableScheduledFuture) {
+                RunnableScheduledFuture<?> t = (RunnableScheduledFuture<?>)e;
+                if ((t.isPeriodic()
+                     ? !keepPeriodic
+                     // Android-changed: Preserving behaviour on expired tasks (b/202927404)
+                     // : (!keepDelayed && t.getDelay(NANOSECONDS) > 0))
+                     : !keepDelayed)
+                    || t.isCancelled()) { // also remove if already cancelled
+                    if (q.remove(t))
+                        t.cancel(false);
                 }
             }
         }
@@ -581,6 +588,34 @@
     }
 
     /**
+     * Submits a periodic action that becomes enabled first after the
+     * given initial delay, and subsequently with the given period;
+     * that is, executions will commence after
+     * {@code initialDelay}, then {@code initialDelay + period}, then
+     * {@code initialDelay + 2 * period}, and so on.
+     *
+     * <p>The sequence of task executions continues indefinitely until
+     * one of the following exceptional completions occur:
+     * <ul>
+     * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+     * via the returned future.
+     * <li>Method {@link #shutdown} is called and the {@linkplain
+     * #getContinueExistingPeriodicTasksAfterShutdownPolicy policy on
+     * whether to continue after shutdown} is not set true, or method
+     * {@link #shutdownNow} is called; also resulting in task
+     * cancellation.
+     * <li>An execution of the task throws an exception.  In this case
+     * calling {@link Future#get() get} on the returned future will throw
+     * {@link ExecutionException}, holding the exception as its cause.
+     * </ul>
+     * Subsequent executions are suppressed.  Subsequent calls to
+     * {@link Future#isDone isDone()} on the returned future will
+     * return {@code true}.
+     *
+     * <p>If any execution of this task takes longer than its period, then
+     * subsequent executions may start late, but will not concurrently
+     * execute.
+     *
      * @throws RejectedExecutionException {@inheritDoc}
      * @throws NullPointerException       {@inheritDoc}
      * @throws IllegalArgumentException   {@inheritDoc}
@@ -606,6 +641,29 @@
     }
 
     /**
+     * Submits a periodic action that becomes enabled first after the
+     * given initial delay, and subsequently with the given delay
+     * between the termination of one execution and the commencement of
+     * the next.
+     *
+     * <p>The sequence of task executions continues indefinitely until
+     * one of the following exceptional completions occur:
+     * <ul>
+     * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+     * via the returned future.
+     * <li>Method {@link #shutdown} is called and the {@linkplain
+     * #getContinueExistingPeriodicTasksAfterShutdownPolicy policy on
+     * whether to continue after shutdown} is not set true, or method
+     * {@link #shutdownNow} is called; also resulting in task
+     * cancellation.
+     * <li>An execution of the task throws an exception.  In this case
+     * calling {@link Future#get() get} on the returned future will throw
+     * {@link ExecutionException}, holding the exception as its cause.
+     * </ul>
+     * Subsequent executions are suppressed.  Subsequent calls to
+     * {@link Future#isDone isDone()} on the returned future will
+     * return {@code true}.
+     *
      * @throws RejectedExecutionException {@inheritDoc}
      * @throws NullPointerException       {@inheritDoc}
      * @throws IllegalArgumentException   {@inheritDoc}
@@ -683,9 +741,8 @@
     /**
      * Sets the policy on whether to continue executing existing
      * periodic tasks even when this executor has been {@code shutdown}.
-     * In this case, these tasks will only terminate upon
-     * {@code shutdownNow} or after setting the policy to
-     * {@code false} when already shutdown.
+     * In this case, executions will continue until {@code shutdownNow}
+     * or the policy is set to {@code false} when already shutdown.
      * This value is by default {@code false}.
      *
      * @param value if {@code true}, continue after shutdown, else don't
@@ -700,9 +757,8 @@
     /**
      * Gets the policy on whether to continue executing existing
      * periodic tasks even when this executor has been {@code shutdown}.
-     * In this case, these tasks will only terminate upon
-     * {@code shutdownNow} or after setting the policy to
-     * {@code false} when already shutdown.
+     * In this case, executions will continue until {@code shutdownNow}
+     * or the policy is set to {@code false} when already shutdown.
      * This value is by default {@code false}.
      *
      * @return {@code true} if will continue after shutdown
@@ -905,7 +961,7 @@
         /**
          * Sets f's heapIndex if it is a ScheduledFutureTask.
          */
-        private void setIndex(RunnableScheduledFuture<?> f, int idx) {
+        private static void setIndex(RunnableScheduledFuture<?> f, int idx) {
             if (f instanceof ScheduledFutureTask)
                 ((ScheduledFutureTask)f).heapIndex = idx;
         }
@@ -1203,41 +1259,12 @@
             }
         }
 
-        /**
-         * Returns first element only if it is expired.
-         * Used only by drainTo.  Call only when holding lock.
-         */
-        private RunnableScheduledFuture<?> peekExpired() {
-            // assert lock.isHeldByCurrentThread();
-            RunnableScheduledFuture<?> first = queue[0];
-            return (first == null || first.getDelay(NANOSECONDS) > 0) ?
-                null : first;
-        }
-
         public int drainTo(Collection<? super Runnable> c) {
-            if (c == null)
-                throw new NullPointerException();
-            if (c == this)
-                throw new IllegalArgumentException();
-            final ReentrantLock lock = this.lock;
-            lock.lock();
-            try {
-                RunnableScheduledFuture<?> first;
-                int n = 0;
-                while ((first = peekExpired()) != null) {
-                    c.add(first);   // In this order, in case add() throws.
-                    finishPoll(first);
-                    ++n;
-                }
-                return n;
-            } finally {
-                lock.unlock();
-            }
+            return drainTo(c, Integer.MAX_VALUE);
         }
 
         public int drainTo(Collection<? super Runnable> c, int maxElements) {
-            if (c == null)
-                throw new NullPointerException();
+            Objects.requireNonNull(c);
             if (c == this)
                 throw new IllegalArgumentException();
             if (maxElements <= 0)
@@ -1245,9 +1272,11 @@
             final ReentrantLock lock = this.lock;
             lock.lock();
             try {
-                RunnableScheduledFuture<?> first;
                 int n = 0;
-                while (n < maxElements && (first = peekExpired()) != null) {
+                for (RunnableScheduledFuture<?> first;
+                     n < maxElements
+                         && (first = queue[0]) != null
+                         && first.getDelay(NANOSECONDS) <= 0;) {
                     c.add(first);   // In this order, in case add() throws.
                     finishPoll(first);
                     ++n;
@@ -1285,7 +1314,13 @@
         }
 
         public Iterator<Runnable> iterator() {
-            return new Itr(Arrays.copyOf(queue, size));
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return new Itr(Arrays.copyOf(queue, size));
+            } finally {
+                lock.unlock();
+            }
         }
 
         /**
@@ -1307,8 +1342,7 @@
             public Runnable next() {
                 if (cursor >= array.length)
                     throw new NoSuchElementException();
-                lastRet = cursor;
-                return array[cursor++];
+                return array[lastRet = cursor++];
             }
 
             public void remove() {
diff --git a/ojluni/src/main/java/java/util/concurrent/Semaphore.java b/ojluni/src/main/java/java/util/concurrent/Semaphore.java
index 1298a6e..86ee638 100644
--- a/ojluni/src/main/java/java/util/concurrent/Semaphore.java
+++ b/ojluni/src/main/java/java/util/concurrent/Semaphore.java
@@ -72,8 +72,8 @@
  *   protected synchronized Object getNextAvailableItem() {
  *     for (int i = 0; i < MAX_AVAILABLE; ++i) {
  *       if (!used[i]) {
- *          used[i] = true;
- *          return items[i];
+ *         used[i] = true;
+ *         return items[i];
  *       }
  *     }
  *     return null; // not reached
@@ -82,11 +82,11 @@
  *   protected synchronized boolean markAsUnused(Object item) {
  *     for (int i = 0; i < MAX_AVAILABLE; ++i) {
  *       if (item == items[i]) {
- *          if (used[i]) {
- *            used[i] = false;
- *            return true;
- *          } else
- *            return false;
+ *         if (used[i]) {
+ *           used[i] = false;
+ *           return true;
+ *         } else
+ *           return false;
  *       }
  *     }
  *     return false;
@@ -359,7 +359,7 @@
      * This &quot;barging&quot; behavior can be useful in certain
      * circumstances, even though it breaks fairness. If you want to honor
      * the fairness setting, then use
-     * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) }
+     * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS)}
      * which is almost equivalent (it also detects interruption).
      *
      * @return {@code true} if a permit was acquired and {@code false}
@@ -523,7 +523,7 @@
      * &quot;barging&quot; behavior can be useful in certain
      * circumstances, even though it breaks fairness. If you want to
      * honor the fairness setting, then use {@link #tryAcquire(int,
-     * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS) }
+     * long, TimeUnit) tryAcquire(permits, 0, TimeUnit.SECONDS)}
      * which is almost equivalent (it also detects interruption).
      *
      * @param permits the number of permits to acquire
@@ -631,9 +631,12 @@
     }
 
     /**
-     * Acquires and returns all permits that are immediately available.
+     * Acquires and returns all permits that are immediately
+     * available, or if negative permits are available, releases them.
+     * Upon return, zero permits are available.
      *
-     * @return the number of permits acquired
+     * @return the number of permits acquired or, if negative, the
+     * number released
      */
     public int drainPermits() {
         return sync.drainPermits();
diff --git a/ojluni/src/main/java/java/util/concurrent/SubmissionPublisher.java b/ojluni/src/main/java/java/util/concurrent/SubmissionPublisher.java
new file mode 100644
index 0000000..9efb01d
--- /dev/null
+++ b/ojluni/src/main/java/java/util/concurrent/SubmissionPublisher.java
@@ -0,0 +1,1477 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * 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;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.locks.LockSupport;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import static java.util.concurrent.Flow.Publisher;
+import static java.util.concurrent.Flow.Subscriber;
+import static java.util.concurrent.Flow.Subscription;
+
+/**
+ * A {@link Flow.Publisher} that asynchronously issues submitted
+ * (non-null) items to current subscribers until it is closed.  Each
+ * current subscriber receives newly submitted items in the same order
+ * unless drops or exceptions are encountered.  Using a
+ * SubmissionPublisher allows item generators to act as compliant <a
+ * href="http://www.reactive-streams.org/"> reactive-streams</a>
+ * Publishers relying on drop handling and/or blocking for flow
+ * control.
+ *
+ * <p>A SubmissionPublisher uses the {@link Executor} supplied in its
+ * constructor for delivery to subscribers. The best choice of
+ * Executor depends on expected usage. If the generator(s) of
+ * submitted items run in separate threads, and the number of
+ * subscribers can be estimated, consider using a {@link
+ * Executors#newFixedThreadPool}. Otherwise consider using the
+ * default, normally the {@link ForkJoinPool#commonPool}.
+ *
+ * <p>Buffering allows producers and consumers to transiently operate
+ * at different rates.  Each subscriber uses an independent buffer.
+ * Buffers are created upon first use and expanded as needed up to the
+ * given maximum. (The enforced capacity may be rounded up to the
+ * nearest power of two and/or bounded by the largest value supported
+ * by this implementation.)  Invocations of {@link
+ * Flow.Subscription#request(long) request} do not directly result in
+ * buffer expansion, but risk saturation if unfilled requests exceed
+ * the maximum capacity.  The default value of {@link
+ * Flow#defaultBufferSize()} may provide a useful starting point for
+ * choosing a capacity based on expected rates, resources, and usages.
+ *
+ * <p>A single SubmissionPublisher may be shared among multiple
+ * sources. Actions in a source thread prior to publishing an item or
+ * issuing a signal <a href="package-summary.html#MemoryVisibility">
+ * <i>happen-before</i></a> actions subsequent to the corresponding
+ * access by each subscriber. But reported estimates of lag and demand
+ * are designed for use in monitoring, not for synchronization
+ * control, and may reflect stale or inaccurate views of progress.
+ *
+ * <p>Publication methods support different policies about what to do
+ * when buffers are saturated. Method {@link #submit(Object) submit}
+ * blocks until resources are available. This is simplest, but least
+ * responsive.  The {@code offer} methods may drop items (either
+ * immediately or with bounded timeout), but provide an opportunity to
+ * interpose a handler and then retry.
+ *
+ * <p>If any Subscriber method throws an exception, its subscription
+ * is cancelled.  If a handler is supplied as a constructor argument,
+ * it is invoked before cancellation upon an exception in method
+ * {@link Flow.Subscriber#onNext onNext}, but exceptions in methods
+ * {@link Flow.Subscriber#onSubscribe onSubscribe},
+ * {@link Flow.Subscriber#onError(Throwable) onError} and
+ * {@link Flow.Subscriber#onComplete() onComplete} are not recorded or
+ * handled before cancellation.  If the supplied Executor throws
+ * {@link RejectedExecutionException} (or any other RuntimeException
+ * or Error) when attempting to execute a task, or a drop handler
+ * throws an exception when processing a dropped item, then the
+ * exception is rethrown. In these cases, not all subscribers will
+ * have been issued the published item. It is usually good practice to
+ * {@link #closeExceptionally closeExceptionally} in these cases.
+ *
+ * <p>Method {@link #consume(Consumer)} simplifies support for a
+ * common case in which the only action of a subscriber is to request
+ * and process all items using a supplied function.
+ *
+ * <p>This class may also serve as a convenient base for subclasses
+ * that generate items, and use the methods in this class to publish
+ * them.  For example here is a class that periodically publishes the
+ * items generated from a supplier. (In practice you might add methods
+ * to independently start and stop generation, to share Executors
+ * among publishers, and so on, or use a SubmissionPublisher as a
+ * component rather than a superclass.)
+ *
+ * <pre> {@code
+ * class PeriodicPublisher<T> extends SubmissionPublisher<T> {
+ *   final ScheduledFuture<?> periodicTask;
+ *   final ScheduledExecutorService scheduler;
+ *   PeriodicPublisher(Executor executor, int maxBufferCapacity,
+ *                     Supplier<? extends T> supplier,
+ *                     long period, TimeUnit unit) {
+ *     super(executor, maxBufferCapacity);
+ *     scheduler = new ScheduledThreadPoolExecutor(1);
+ *     periodicTask = scheduler.scheduleAtFixedRate(
+ *       () -> submit(supplier.get()), 0, period, unit);
+ *   }
+ *   public void close() {
+ *     periodicTask.cancel(false);
+ *     scheduler.shutdown();
+ *     super.close();
+ *   }
+ * }}</pre>
+ *
+ * <p>Here is an example of a {@link Flow.Processor} implementation.
+ * It uses single-step requests to its publisher for simplicity of
+ * illustration. A more adaptive version could monitor flow using the
+ * lag estimate returned from {@code submit}, along with other utility
+ * methods.
+ *
+ * <pre> {@code
+ * class TransformProcessor<S,T> extends SubmissionPublisher<T>
+ *   implements Flow.Processor<S,T> {
+ *   final Function<? super S, ? extends T> function;
+ *   Flow.Subscription subscription;
+ *   TransformProcessor(Executor executor, int maxBufferCapacity,
+ *                      Function<? super S, ? extends T> function) {
+ *     super(executor, maxBufferCapacity);
+ *     this.function = function;
+ *   }
+ *   public void onSubscribe(Flow.Subscription subscription) {
+ *     (this.subscription = subscription).request(1);
+ *   }
+ *   public void onNext(S item) {
+ *     subscription.request(1);
+ *     submit(function.apply(item));
+ *   }
+ *   public void onError(Throwable ex) { closeExceptionally(ex); }
+ *   public void onComplete() { close(); }
+ * }}</pre>
+ *
+ * @param <T> the published item type
+ * @author Doug Lea
+ * @since 9
+ */
+public class SubmissionPublisher<T> implements Publisher<T>,
+                                               AutoCloseable {
+    /*
+     * Most mechanics are handled by BufferedSubscription. This class
+     * mainly tracks subscribers and ensures sequentiality, by using
+     * built-in synchronization locks across public methods. Using
+     * built-in locks works well in the most typical case in which
+     * only one thread submits items. We extend this idea in
+     * submission methods by detecting single-ownership to reduce
+     * producer-consumer synchronization strength.
+     */
+
+    /** The largest possible power of two array size. */
+    static final int BUFFER_CAPACITY_LIMIT = 1 << 30;
+
+    /**
+     * Initial buffer capacity used when maxBufferCapacity is
+     * greater. Must be a power of two.
+     */
+    static final int INITIAL_CAPACITY = 32;
+
+    /** Round capacity to power of 2, at most limit. */
+    static final int roundCapacity(int cap) {
+        int n = cap - 1;
+        n |= n >>> 1;
+        n |= n >>> 2;
+        n |= n >>> 4;
+        n |= n >>> 8;
+        n |= n >>> 16;
+        return (n <= 0) ? 1 : // at least 1
+            (n >= BUFFER_CAPACITY_LIMIT) ? BUFFER_CAPACITY_LIMIT : n + 1;
+    }
+
+    // default Executor setup; nearly the same as CompletableFuture
+
+    /**
+     * Default executor -- ForkJoinPool.commonPool() unless it cannot
+     * support parallelism.
+     */
+    private static final Executor ASYNC_POOL =
+        (ForkJoinPool.getCommonPoolParallelism() > 1) ?
+        ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
+
+    /** Fallback if ForkJoinPool.commonPool() cannot support parallelism */
+    private static final class ThreadPerTaskExecutor implements Executor {
+        ThreadPerTaskExecutor() {}      // prevent access constructor creation
+        public void execute(Runnable r) { new Thread(r).start(); }
+    }
+
+    /**
+     * Clients (BufferedSubscriptions) are maintained in a linked list
+     * (via their "next" fields). This works well for publish loops.
+     * It requires O(n) traversal to check for duplicate subscribers,
+     * but we expect that subscribing is much less common than
+     * publishing. Unsubscribing occurs only during traversal loops,
+     * when BufferedSubscription methods return negative values
+     * signifying that they have been closed.  To reduce
+     * head-of-line blocking, submit and offer methods first call
+     * BufferedSubscription.offer on each subscriber, and place
+     * saturated ones in retries list (using nextRetry field), and
+     * retry, possibly blocking or dropping.
+     */
+    BufferedSubscription<T> clients;
+
+    /** Run status, updated only within locks */
+    volatile boolean closed;
+    /** Set true on first call to subscribe, to initialize possible owner */
+    boolean subscribed;
+    /** The first caller thread to subscribe, or null if thread ever changed */
+    Thread owner;
+    /** If non-null, the exception in closeExceptionally */
+    volatile Throwable closedException;
+
+    // Parameters for constructing BufferedSubscriptions
+    final Executor executor;
+    final BiConsumer<? super Subscriber<? super T>, ? super Throwable> onNextHandler;
+    final int maxBufferCapacity;
+
+    /**
+     * Creates a new SubmissionPublisher using the given Executor for
+     * async delivery to subscribers, with the given maximum buffer size
+     * for each subscriber, and, if non-null, the given handler invoked
+     * when any Subscriber throws an exception in method {@link
+     * Flow.Subscriber#onNext(Object) onNext}.
+     *
+     * @param executor the executor to use for async delivery,
+     * supporting creation of at least one independent thread
+     * @param maxBufferCapacity the maximum capacity for each
+     * subscriber's buffer (the enforced capacity may be rounded up to
+     * the nearest power of two and/or bounded by the largest value
+     * supported by this implementation; method {@link #getMaxBufferCapacity}
+     * returns the actual value)
+     * @param handler if non-null, procedure to invoke upon exception
+     * thrown in method {@code onNext}
+     * @throws NullPointerException if executor is null
+     * @throws IllegalArgumentException if maxBufferCapacity not
+     * positive
+     */
+    public SubmissionPublisher(Executor executor, int maxBufferCapacity,
+                               BiConsumer<? super Subscriber<? super T>, ? super Throwable> handler) {
+        if (executor == null)
+            throw new NullPointerException();
+        if (maxBufferCapacity <= 0)
+            throw new IllegalArgumentException("capacity must be positive");
+        this.executor = executor;
+        this.onNextHandler = handler;
+        this.maxBufferCapacity = roundCapacity(maxBufferCapacity);
+    }
+
+    /**
+     * Creates a new SubmissionPublisher using the given Executor for
+     * async delivery to subscribers, with the given maximum buffer size
+     * for each subscriber, and no handler for Subscriber exceptions in
+     * method {@link Flow.Subscriber#onNext(Object) onNext}.
+     *
+     * @param executor the executor to use for async delivery,
+     * supporting creation of at least one independent thread
+     * @param maxBufferCapacity the maximum capacity for each
+     * subscriber's buffer (the enforced capacity may be rounded up to
+     * the nearest power of two and/or bounded by the largest value
+     * supported by this implementation; method {@link #getMaxBufferCapacity}
+     * returns the actual value)
+     * @throws NullPointerException if executor is null
+     * @throws IllegalArgumentException if maxBufferCapacity not
+     * positive
+     */
+    public SubmissionPublisher(Executor executor, int maxBufferCapacity) {
+        this(executor, maxBufferCapacity, null);
+    }
+
+    /**
+     * Creates a new SubmissionPublisher using the {@link
+     * ForkJoinPool#commonPool()} for async delivery to subscribers
+     * (unless it does not support a parallelism level of at least two,
+     * in which case, a new Thread is created to run each task), with
+     * maximum buffer capacity of {@link Flow#defaultBufferSize}, and no
+     * handler for Subscriber exceptions in method {@link
+     * Flow.Subscriber#onNext(Object) onNext}.
+     */
+    public SubmissionPublisher() {
+        this(ASYNC_POOL, Flow.defaultBufferSize(), null);
+    }
+
+    /**
+     * Adds the given Subscriber unless already subscribed.  If already
+     * subscribed, the Subscriber's {@link
+     * Flow.Subscriber#onError(Throwable) onError} method is invoked on
+     * the existing subscription with an {@link IllegalStateException}.
+     * Otherwise, upon success, the Subscriber's {@link
+     * Flow.Subscriber#onSubscribe onSubscribe} method is invoked
+     * asynchronously with a new {@link Flow.Subscription}.  If {@link
+     * Flow.Subscriber#onSubscribe onSubscribe} throws an exception, the
+     * subscription is cancelled. Otherwise, if this SubmissionPublisher
+     * was closed exceptionally, then the subscriber's {@link
+     * Flow.Subscriber#onError onError} method is invoked with the
+     * corresponding exception, or if closed without exception, the
+     * subscriber's {@link Flow.Subscriber#onComplete() onComplete}
+     * method is invoked.  Subscribers may enable receiving items by
+     * invoking the {@link Flow.Subscription#request(long) request}
+     * method of the new Subscription, and may unsubscribe by invoking
+     * its {@link Flow.Subscription#cancel() cancel} method.
+     *
+     * @param subscriber the subscriber
+     * @throws NullPointerException if subscriber is null
+     */
+    public void subscribe(Subscriber<? super T> subscriber) {
+        if (subscriber == null) throw new NullPointerException();
+        int max = maxBufferCapacity; // allocate initial array
+        Object[] array = new Object[max < INITIAL_CAPACITY ?
+                                    max : INITIAL_CAPACITY];
+        BufferedSubscription<T> subscription =
+            new BufferedSubscription<T>(subscriber, executor, onNextHandler,
+                                        array, max);
+        synchronized (this) {
+            if (!subscribed) {
+                subscribed = true;
+                owner = Thread.currentThread();
+            }
+            for (BufferedSubscription<T> b = clients, pred = null;;) {
+                if (b == null) {
+                    Throwable ex;
+                    subscription.onSubscribe();
+                    if ((ex = closedException) != null)
+                        subscription.onError(ex);
+                    else if (closed)
+                        subscription.onComplete();
+                    else if (pred == null)
+                        clients = subscription;
+                    else
+                        pred.next = subscription;
+                    break;
+                }
+                BufferedSubscription<T> next = b.next;
+                if (b.isClosed()) {   // remove
+                    b.next = null;    // detach
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else if (subscriber.equals(b.subscriber)) {
+                    b.onError(new IllegalStateException("Duplicate subscribe"));
+                    break;
+                }
+                else
+                    pred = b;
+                b = next;
+            }
+        }
+    }
+
+    /**
+     * Common implementation for all three forms of submit and offer.
+     * Acts as submit if nanos == Long.MAX_VALUE, else offer.
+     */
+    private int doOffer(T item, long nanos,
+                        BiPredicate<Subscriber<? super T>, ? super T> onDrop) {
+        if (item == null) throw new NullPointerException();
+        int lag = 0;
+        boolean complete, unowned;
+        synchronized (this) {
+            Thread t = Thread.currentThread(), o;
+            BufferedSubscription<T> b = clients;
+            if ((unowned = ((o = owner) != t)) && o != null)
+                owner = null;                     // disable bias
+            if (b == null)
+                complete = closed;
+            else {
+                complete = false;
+                boolean cleanMe = false;
+                BufferedSubscription<T> retries = null, rtail = null, next;
+                do {
+                    next = b.next;
+                    int stat = b.offer(item, unowned);
+                    if (stat == 0) {              // saturated; add to retry list
+                        b.nextRetry = null;       // avoid garbage on exceptions
+                        if (rtail == null)
+                            retries = b;
+                        else
+                            rtail.nextRetry = b;
+                        rtail = b;
+                    }
+                    else if (stat < 0)            // closed
+                        cleanMe = true;           // remove later
+                    else if (stat > lag)
+                        lag = stat;
+                } while ((b = next) != null);
+
+                if (retries != null || cleanMe)
+                    lag = retryOffer(item, nanos, onDrop, retries, lag, cleanMe);
+            }
+        }
+        if (complete)
+            throw new IllegalStateException("Closed");
+        else
+            return lag;
+    }
+
+    /**
+     * Helps, (timed) waits for, and/or drops buffers on list; returns
+     * lag or negative drops (for use in offer).
+     */
+    private int retryOffer(T item, long nanos,
+                           BiPredicate<Subscriber<? super T>, ? super T> onDrop,
+                           BufferedSubscription<T> retries, int lag,
+                           boolean cleanMe) {
+        for (BufferedSubscription<T> r = retries; r != null;) {
+            BufferedSubscription<T> nextRetry = r.nextRetry;
+            r.nextRetry = null;
+            if (nanos > 0L)
+                r.awaitSpace(nanos);
+            int stat = r.retryOffer(item);
+            if (stat == 0 && onDrop != null && onDrop.test(r.subscriber, item))
+                stat = r.retryOffer(item);
+            if (stat == 0)
+                lag = (lag >= 0) ? -1 : lag - 1;
+            else if (stat < 0)
+                cleanMe = true;
+            else if (lag >= 0 && stat > lag)
+                lag = stat;
+            r = nextRetry;
+        }
+        if (cleanMe)
+            cleanAndCount();
+        return lag;
+    }
+
+    /**
+     * Returns current list count after removing closed subscribers.
+     * Call only while holding lock.  Used mainly by retryOffer for
+     * cleanup.
+     */
+    private int cleanAndCount() {
+        int count = 0;
+        BufferedSubscription<T> pred = null, next;
+        for (BufferedSubscription<T> b = clients; b != null; b = next) {
+            next = b.next;
+            if (b.isClosed()) {
+                b.next = null;
+                if (pred == null)
+                    clients = next;
+                else
+                    pred.next = next;
+            }
+            else {
+                pred = b;
+                ++count;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Publishes the given item to each current subscriber by
+     * asynchronously invoking its {@link Flow.Subscriber#onNext(Object)
+     * onNext} method, blocking uninterruptibly while resources for any
+     * subscriber are unavailable. This method returns an estimate of
+     * the maximum lag (number of items submitted but not yet consumed)
+     * among all current subscribers. This value is at least one
+     * (accounting for this submitted item) if there are any
+     * subscribers, else zero.
+     *
+     * <p>If the Executor for this publisher throws a
+     * RejectedExecutionException (or any other RuntimeException or
+     * Error) when attempting to asynchronously notify subscribers,
+     * then this exception is rethrown, in which case not all
+     * subscribers will have been issued this item.
+     *
+     * @param item the (non-null) item to publish
+     * @return the estimated maximum lag among subscribers
+     * @throws IllegalStateException if closed
+     * @throws NullPointerException if item is null
+     * @throws RejectedExecutionException if thrown by Executor
+     */
+    public int submit(T item) {
+        return doOffer(item, Long.MAX_VALUE, null);
+    }
+
+    /**
+     * Publishes the given item, if possible, to each current subscriber
+     * by asynchronously invoking its {@link
+     * Flow.Subscriber#onNext(Object) onNext} method. The item may be
+     * dropped by one or more subscribers if resource limits are
+     * exceeded, in which case the given handler (if non-null) is
+     * invoked, and if it returns true, retried once.  Other calls to
+     * methods in this class by other threads are blocked while the
+     * handler is invoked.  Unless recovery is assured, options are
+     * usually limited to logging the error and/or issuing an {@link
+     * Flow.Subscriber#onError(Throwable) onError} signal to the
+     * subscriber.
+     *
+     * <p>This method returns a status indicator: If negative, it
+     * represents the (negative) number of drops (failed attempts to
+     * issue the item to a subscriber). Otherwise it is an estimate of
+     * the maximum lag (number of items submitted but not yet
+     * consumed) among all current subscribers. This value is at least
+     * one (accounting for this submitted item) if there are any
+     * subscribers, else zero.
+     *
+     * <p>If the Executor for this publisher throws a
+     * RejectedExecutionException (or any other RuntimeException or
+     * Error) when attempting to asynchronously notify subscribers, or
+     * the drop handler throws an exception when processing a dropped
+     * item, then this exception is rethrown.
+     *
+     * @param item the (non-null) item to publish
+     * @param onDrop if non-null, the handler invoked upon a drop to a
+     * subscriber, with arguments of the subscriber and item; if it
+     * returns true, an offer is re-attempted (once)
+     * @return if negative, the (negative) number of drops; otherwise
+     * an estimate of maximum lag
+     * @throws IllegalStateException if closed
+     * @throws NullPointerException if item is null
+     * @throws RejectedExecutionException if thrown by Executor
+     */
+    public int offer(T item,
+                     BiPredicate<Subscriber<? super T>, ? super T> onDrop) {
+        return doOffer(item, 0L, onDrop);
+    }
+
+    /**
+     * Publishes the given item, if possible, to each current subscriber
+     * by asynchronously invoking its {@link
+     * Flow.Subscriber#onNext(Object) onNext} method, blocking while
+     * resources for any subscription are unavailable, up to the
+     * specified timeout or until the caller thread is interrupted, at
+     * which point the given handler (if non-null) is invoked, and if it
+     * returns true, retried once. (The drop handler may distinguish
+     * timeouts from interrupts by checking whether the current thread
+     * is interrupted.)  Other calls to methods in this class by other
+     * threads are blocked while the handler is invoked.  Unless
+     * recovery is assured, options are usually limited to logging the
+     * error and/or issuing an {@link Flow.Subscriber#onError(Throwable)
+     * onError} signal to the subscriber.
+     *
+     * <p>This method returns a status indicator: If negative, it
+     * represents the (negative) number of drops (failed attempts to
+     * issue the item to a subscriber). Otherwise it is an estimate of
+     * the maximum lag (number of items submitted but not yet
+     * consumed) among all current subscribers. This value is at least
+     * one (accounting for this submitted item) if there are any
+     * subscribers, else zero.
+     *
+     * <p>If the Executor for this publisher throws a
+     * RejectedExecutionException (or any other RuntimeException or
+     * Error) when attempting to asynchronously notify subscribers, or
+     * the drop handler throws an exception when processing a dropped
+     * item, then this exception is rethrown.
+     *
+     * @param item the (non-null) item to publish
+     * @param timeout how long to wait for resources for any subscriber
+     * before giving up, in units of {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     * {@code timeout} parameter
+     * @param onDrop if non-null, the handler invoked upon a drop to a
+     * subscriber, with arguments of the subscriber and item; if it
+     * returns true, an offer is re-attempted (once)
+     * @return if negative, the (negative) number of drops; otherwise
+     * an estimate of maximum lag
+     * @throws IllegalStateException if closed
+     * @throws NullPointerException if item is null
+     * @throws RejectedExecutionException if thrown by Executor
+     */
+    public int offer(T item, long timeout, TimeUnit unit,
+                     BiPredicate<Subscriber<? super T>, ? super T> onDrop) {
+        long nanos = unit.toNanos(timeout);
+        // distinguishes from untimed (only wrt interrupt policy)
+        if (nanos == Long.MAX_VALUE) --nanos;
+        return doOffer(item, nanos, onDrop);
+    }
+
+    /**
+     * Unless already closed, issues {@link
+     * Flow.Subscriber#onComplete() onComplete} signals to current
+     * subscribers, and disallows subsequent attempts to publish.
+     * Upon return, this method does <em>NOT</em> guarantee that all
+     * subscribers have yet completed.
+     */
+    public void close() {
+        if (!closed) {
+            BufferedSubscription<T> b;
+            synchronized (this) {
+                // no need to re-check closed here
+                b = clients;
+                clients = null;
+                owner = null;
+                closed = true;
+            }
+            while (b != null) {
+                BufferedSubscription<T> next = b.next;
+                b.next = null;
+                b.onComplete();
+                b = next;
+            }
+        }
+    }
+
+    /**
+     * Unless already closed, issues {@link
+     * Flow.Subscriber#onError(Throwable) onError} signals to current
+     * subscribers with the given error, and disallows subsequent
+     * attempts to publish.  Future subscribers also receive the given
+     * error. Upon return, this method does <em>NOT</em> guarantee
+     * that all subscribers have yet completed.
+     *
+     * @param error the {@code onError} argument sent to subscribers
+     * @throws NullPointerException if error is null
+     */
+    public void closeExceptionally(Throwable error) {
+        if (error == null)
+            throw new NullPointerException();
+        if (!closed) {
+            BufferedSubscription<T> b;
+            synchronized (this) {
+                b = clients;
+                if (!closed) {  // don't clobber racing close
+                    closedException = error;
+                    clients = null;
+                    owner = null;
+                    closed = true;
+                }
+            }
+            while (b != null) {
+                BufferedSubscription<T> next = b.next;
+                b.next = null;
+                b.onError(error);
+                b = next;
+            }
+        }
+    }
+
+    /**
+     * Returns true if this publisher is not accepting submissions.
+     *
+     * @return true if closed
+     */
+    public boolean isClosed() {
+        return closed;
+    }
+
+    /**
+     * Returns the exception associated with {@link
+     * #closeExceptionally(Throwable) closeExceptionally}, or null if
+     * not closed or if closed normally.
+     *
+     * @return the exception, or null if none
+     */
+    public Throwable getClosedException() {
+        return closedException;
+    }
+
+    /**
+     * Returns true if this publisher has any subscribers.
+     *
+     * @return true if this publisher has any subscribers
+     */
+    public boolean hasSubscribers() {
+        boolean nonEmpty = false;
+        synchronized (this) {
+            for (BufferedSubscription<T> b = clients; b != null;) {
+                BufferedSubscription<T> next = b.next;
+                if (b.isClosed()) {
+                    b.next = null;
+                    b = clients = next;
+                }
+                else {
+                    nonEmpty = true;
+                    break;
+                }
+            }
+        }
+        return nonEmpty;
+    }
+
+    /**
+     * Returns the number of current subscribers.
+     *
+     * @return the number of current subscribers
+     */
+    public int getNumberOfSubscribers() {
+        synchronized (this) {
+            return cleanAndCount();
+        }
+    }
+
+    /**
+     * Returns the Executor used for asynchronous delivery.
+     *
+     * @return the Executor used for asynchronous delivery
+     */
+    public Executor getExecutor() {
+        return executor;
+    }
+
+    /**
+     * Returns the maximum per-subscriber buffer capacity.
+     *
+     * @return the maximum per-subscriber buffer capacity
+     */
+    public int getMaxBufferCapacity() {
+        return maxBufferCapacity;
+    }
+
+    /**
+     * Returns a list of current subscribers for monitoring and
+     * tracking purposes, not for invoking {@link Flow.Subscriber}
+     * methods on the subscribers.
+     *
+     * @return list of current subscribers
+     */
+    public List<Subscriber<? super T>> getSubscribers() {
+        ArrayList<Subscriber<? super T>> subs = new ArrayList<>();
+        synchronized (this) {
+            BufferedSubscription<T> pred = null, next;
+            for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                next = b.next;
+                if (b.isClosed()) {
+                    b.next = null;
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else {
+                    subs.add(b.subscriber);
+                    pred = b;
+                }
+            }
+        }
+        return subs;
+    }
+
+    /**
+     * Returns true if the given Subscriber is currently subscribed.
+     *
+     * @param subscriber the subscriber
+     * @return true if currently subscribed
+     * @throws NullPointerException if subscriber is null
+     */
+    public boolean isSubscribed(Subscriber<? super T> subscriber) {
+        if (subscriber == null) throw new NullPointerException();
+        if (!closed) {
+            synchronized (this) {
+                BufferedSubscription<T> pred = null, next;
+                for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                    next = b.next;
+                    if (b.isClosed()) {
+                        b.next = null;
+                        if (pred == null)
+                            clients = next;
+                        else
+                            pred.next = next;
+                    }
+                    else if (subscriber.equals(b.subscriber))
+                        return true;
+                    else
+                        pred = b;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns an estimate of the minimum number of items requested
+     * (via {@link Flow.Subscription#request(long) request}) but not
+     * yet produced, among all current subscribers.
+     *
+     * @return the estimate, or zero if no subscribers
+     */
+    public long estimateMinimumDemand() {
+        long min = Long.MAX_VALUE;
+        boolean nonEmpty = false;
+        synchronized (this) {
+            BufferedSubscription<T> pred = null, next;
+            for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                int n; long d;
+                next = b.next;
+                if ((n = b.estimateLag()) < 0) {
+                    b.next = null;
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else {
+                    if ((d = b.demand - n) < min)
+                        min = d;
+                    nonEmpty = true;
+                    pred = b;
+                }
+            }
+        }
+        return nonEmpty ? min : 0;
+    }
+
+    /**
+     * Returns an estimate of the maximum number of items produced but
+     * not yet consumed among all current subscribers.
+     *
+     * @return the estimate
+     */
+    public int estimateMaximumLag() {
+        int max = 0;
+        synchronized (this) {
+            BufferedSubscription<T> pred = null, next;
+            for (BufferedSubscription<T> b = clients; b != null; b = next) {
+                int n;
+                next = b.next;
+                if ((n = b.estimateLag()) < 0) {
+                    b.next = null;
+                    if (pred == null)
+                        clients = next;
+                    else
+                        pred.next = next;
+                }
+                else {
+                    if (n > max)
+                        max = n;
+                    pred = b;
+                }
+            }
+        }
+        return max;
+    }
+
+    /**
+     * Processes all published items using the given Consumer function.
+     * Returns a CompletableFuture that is completed normally when this
+     * publisher signals {@link Flow.Subscriber#onComplete()
+     * onComplete}, or completed exceptionally upon any error, or an
+     * exception is thrown by the Consumer, or the returned
+     * CompletableFuture is cancelled, in which case no further items
+     * are processed.
+     *
+     * @param consumer the function applied to each onNext item
+     * @return a CompletableFuture that is completed normally
+     * when the publisher signals onComplete, and exceptionally
+     * upon any error or cancellation
+     * @throws NullPointerException if consumer is null
+     */
+    public CompletableFuture<Void> consume(Consumer<? super T> consumer) {
+        if (consumer == null)
+            throw new NullPointerException();
+        CompletableFuture<Void> status = new CompletableFuture<>();
+        subscribe(new ConsumerSubscriber<T>(status, consumer));
+        return status;
+    }
+
+    /** Subscriber for method consume */
+    static final class ConsumerSubscriber<T> implements Subscriber<T> {
+        final CompletableFuture<Void> status;
+        final Consumer<? super T> consumer;
+        Subscription subscription;
+        ConsumerSubscriber(CompletableFuture<Void> status,
+                           Consumer<? super T> consumer) {
+            this.status = status; this.consumer = consumer;
+        }
+        public final void onSubscribe(Subscription subscription) {
+            this.subscription = subscription;
+            status.whenComplete((v, e) -> subscription.cancel());
+            if (!status.isDone())
+                subscription.request(Long.MAX_VALUE);
+        }
+        public final void onError(Throwable ex) {
+            status.completeExceptionally(ex);
+        }
+        public final void onComplete() {
+            status.complete(null);
+        }
+        public final void onNext(T item) {
+            try {
+                consumer.accept(item);
+            } catch (Throwable ex) {
+                subscription.cancel();
+                status.completeExceptionally(ex);
+            }
+        }
+    }
+
+    /**
+     * A task for consuming buffer items and signals, created and
+     * executed whenever they become available. A task consumes as
+     * many items/signals as possible before terminating, at which
+     * point another task is created when needed. The dual Runnable
+     * and ForkJoinTask declaration saves overhead when executed by
+     * ForkJoinPools, without impacting other kinds of Executors.
+     */
+    @SuppressWarnings("serial")
+    static final class ConsumerTask<T> extends ForkJoinTask<Void>
+        implements Runnable, CompletableFuture.AsynchronousCompletionTask {
+        final BufferedSubscription<T> consumer;
+        ConsumerTask(BufferedSubscription<T> consumer) {
+            this.consumer = consumer;
+        }
+        public final Void getRawResult() { return null; }
+        public final void setRawResult(Void v) {}
+        public final boolean exec() { consumer.consume(); return false; }
+        public final void run() { consumer.consume(); }
+    }
+
+    /**
+     * A resizable array-based ring buffer with integrated control to
+     * start a consumer task whenever items are available.  The buffer
+     * algorithm is specialized for the case of at most one concurrent
+     * producer and consumer, and power of two buffer sizes. It relies
+     * primarily on atomic operations (CAS or getAndSet) at the next
+     * array slot to put or take an element, at the "tail" and "head"
+     * indices written only by the producer and consumer respectively.
+     *
+     * We ensure internally that there is at most one active consumer
+     * task at any given time. The publisher guarantees a single
+     * producer via its lock. Sync among producers and consumers
+     * relies on volatile fields "ctl", "demand", and "waiting" (along
+     * with element access). Other variables are accessed in plain
+     * mode, relying on outer ordering and exclusion, and/or enclosing
+     * them within other volatile accesses. Some atomic operations are
+     * avoided by tracking single threaded ownership by producers (in
+     * the style of biased locking).
+     *
+     * Execution control and protocol state are managed using field
+     * "ctl".  Methods to subscribe, close, request, and cancel set
+     * ctl bits (mostly using atomic boolean method getAndBitwiseOr),
+     * and ensure that a task is running. (The corresponding consumer
+     * side actions are in method consume.)  To avoid starting a new
+     * task on each action, ctl also includes a keep-alive bit
+     * (ACTIVE) that is refreshed if needed on producer actions.
+     * (Maintaining agreement about keep-alives requires most atomic
+     * updates to be full SC/Volatile strength, which is still much
+     * cheaper than using one task per item.)  Error signals
+     * additionally null out items and/or fields to reduce termination
+     * latency.  The cancel() method is supported by treating as ERROR
+     * but suppressing onError signal.
+     *
+     * Support for blocking also exploits the fact that there is only
+     * one possible waiter. ManagedBlocker-compatible control fields
+     * are placed in this class itself rather than in wait-nodes.
+     * Blocking control relies on the "waiting" and "waiter"
+     * fields. Producers set them before trying to block. Signalling
+     * unparks and clears fields. If the producer and/or consumer are
+     * using a ForkJoinPool, the producer attempts to help run
+     * consumer tasks via ForkJoinPool.helpAsyncBlocker before
+     * blocking.
+     *
+     * Usages of this class may encounter any of several forms of
+     * memory contention. We try to ameliorate across them without
+     * unduly impacting footprints in low-contention usages where it
+     * isn't needed. Buffer arrays start out small and grow only as
+     * needed.  The class uses @Contended and heuristic field
+     * declaration ordering to reduce false-sharing memory contention
+     * across instances of BufferedSubscription (as in, multiple
+     * subscribers per publisher).  We additionally segregate some
+     * fields that would otherwise nearly always encounter cache line
+     * contention among producers and consumers. To reduce contention
+     * across time (vs space), consumers only periodically update
+     * other fields (see method takeItems), at the expense of possibly
+     * staler reporting of lags and demand (bounded at 12.5% == 1/8
+     * capacity) and possibly more atomic operations.
+     *
+     * Other forms of imbalance and slowdowns can occur during startup
+     * when producer and consumer methods are compiled and/or memory
+     * is allocated at different rates.  This is ameliorated by
+     * artificially subdividing some consumer methods, including
+     * isolation of all subscriber callbacks.  This code also includes
+     * typical power-of-two array screening idioms to avoid compilers
+     * generating traps, along with the usual SSA-based inline
+     * assignment coding style. Also, all methods and fields have
+     * default visibility to simplify usage by callers.
+     */
+    @SuppressWarnings("serial")
+    @jdk.internal.vm.annotation.Contended
+    static final class BufferedSubscription<T>
+        implements Subscription, ForkJoinPool.ManagedBlocker {
+        long timeout;                      // Long.MAX_VALUE if untimed wait
+        int head;                          // next position to take
+        int tail;                          // next position to put
+        final int maxCapacity;             // max buffer size
+        volatile int ctl;                  // atomic run state flags
+        Object[] array;                    // buffer
+        final Subscriber<? super T> subscriber;
+        final BiConsumer<? super Subscriber<? super T>, ? super Throwable> onNextHandler;
+        Executor executor;                 // null on error
+        Thread waiter;                     // blocked producer thread
+        Throwable pendingError;            // holds until onError issued
+        BufferedSubscription<T> next;      // used only by publisher
+        BufferedSubscription<T> nextRetry; // used only by publisher
+
+        @jdk.internal.vm.annotation.Contended("c") // segregate
+        volatile long demand;              // # unfilled requests
+        @jdk.internal.vm.annotation.Contended("c")
+        volatile int waiting;              // nonzero if producer blocked
+
+        // ctl bit values
+        static final int CLOSED   = 0x01;  // if set, other bits ignored
+        static final int ACTIVE   = 0x02;  // keep-alive for consumer task
+        static final int REQS     = 0x04;  // (possibly) nonzero demand
+        static final int ERROR    = 0x08;  // issues onError when noticed
+        static final int COMPLETE = 0x10;  // issues onComplete when done
+        static final int RUN      = 0x20;  // task is or will be running
+        static final int OPEN     = 0x40;  // true after subscribe
+
+        static final long INTERRUPTED = -1L; // timeout vs interrupt sentinel
+
+        BufferedSubscription(Subscriber<? super T> subscriber,
+                             Executor executor,
+                             BiConsumer<? super Subscriber<? super T>,
+                             ? super Throwable> onNextHandler,
+                             Object[] array,
+                             int maxBufferCapacity) {
+            this.subscriber = subscriber;
+            this.executor = executor;
+            this.onNextHandler = onNextHandler;
+            this.array = array;
+            this.maxCapacity = maxBufferCapacity;
+        }
+
+        // Wrappers for some VarHandle methods
+
+        final boolean weakCasCtl(int cmp, int val) {
+            return CTL.weakCompareAndSet(this, cmp, val);
+        }
+
+        final int getAndBitwiseOrCtl(int bits) {
+            return (int)CTL.getAndBitwiseOr(this, bits);
+        }
+
+        final long subtractDemand(int k) {
+            long n = (long)(-k);
+            return n + (long)DEMAND.getAndAdd(this, n);
+        }
+
+        final boolean casDemand(long cmp, long val) {
+            return DEMAND.compareAndSet(this, cmp, val);
+        }
+
+        // Utilities used by SubmissionPublisher
+
+        /**
+         * Returns true if closed (consumer task may still be running).
+         */
+        final boolean isClosed() {
+            return (ctl & CLOSED) != 0;
+        }
+
+        /**
+         * Returns estimated number of buffered items, or negative if
+         * closed.
+         */
+        final int estimateLag() {
+            int c = ctl, n = tail - head;
+            return ((c & CLOSED) != 0) ? -1 : (n < 0) ? 0 : n;
+        }
+
+        // Methods for submitting items
+
+        /**
+         * Tries to add item and start consumer task if necessary.
+         * @return negative if closed, 0 if saturated, else estimated lag
+         */
+        final int offer(T item, boolean unowned) {
+            Object[] a;
+            int stat = 0, cap = ((a = array) == null) ? 0 : a.length;
+            int t = tail, i = t & (cap - 1), n = t + 1 - head;
+            if (cap > 0) {
+                boolean added;
+                if (n >= cap && cap < maxCapacity) // resize
+                    added = growAndOffer(item, a, t);
+                else if (n >= cap || unowned)      // need volatile CAS
+                    added = QA.compareAndSet(a, i, null, item);
+                else {                             // can use release mode
+                    QA.setRelease(a, i, item);
+                    added = true;
+                }
+                if (added) {
+                    tail = t + 1;
+                    stat = n;
+                }
+            }
+            return startOnOffer(stat);
+        }
+
+        /**
+         * Tries to expand buffer and add item, returning true on
+         * success. Currently fails only if out of memory.
+         */
+        final boolean growAndOffer(T item, Object[] a, int t) {
+            int cap = 0, newCap = 0;
+            Object[] newArray = null;
+            if (a != null && (cap = a.length) > 0 && (newCap = cap << 1) > 0) {
+                try {
+                    newArray = new Object[newCap];
+                } catch (OutOfMemoryError ex) {
+                }
+            }
+            if (newArray == null)
+                return false;
+            else {                                // take and move items
+                int newMask = newCap - 1;
+                newArray[t-- & newMask] = item;
+                for (int mask = cap - 1, k = mask; k >= 0; --k) {
+                    Object x = QA.getAndSet(a, t & mask, null);
+                    if (x == null)
+                        break;                    // already consumed
+                    else
+                        newArray[t-- & newMask] = x;
+                }
+                array = newArray;
+                VarHandle.releaseFence();         // release array and slots
+                return true;
+            }
+        }
+
+        /**
+         * Version of offer for retries (no resize or bias)
+         */
+        final int retryOffer(T item) {
+            Object[] a;
+            int stat = 0, t = tail, h = head, cap;
+            if ((a = array) != null && (cap = a.length) > 0 &&
+                QA.compareAndSet(a, (cap - 1) & t, null, item))
+                stat = (tail = t + 1) - h;
+            return startOnOffer(stat);
+        }
+
+        /**
+         * Tries to start consumer task after offer.
+         * @return negative if now closed, else argument
+         */
+        final int startOnOffer(int stat) {
+            int c; // start or keep alive if requests exist and not active
+            if (((c = ctl) & (REQS | ACTIVE)) == REQS &&
+                ((c = getAndBitwiseOrCtl(RUN | ACTIVE)) & (RUN | CLOSED)) == 0)
+                tryStart();
+            else if ((c & CLOSED) != 0)
+                stat = -1;
+            return stat;
+        }
+
+        /**
+         * Tries to start consumer task. Sets error state on failure.
+         */
+        final void tryStart() {
+            try {
+                Executor e;
+                ConsumerTask<T> task = new ConsumerTask<T>(this);
+                if ((e = executor) != null)   // skip if disabled on error
+                    e.execute(task);
+            } catch (RuntimeException | Error ex) {
+                getAndBitwiseOrCtl(ERROR | CLOSED);
+                throw ex;
+            }
+        }
+
+        // Signals to consumer tasks
+
+        /**
+         * Sets the given control bits, starting task if not running or closed.
+         * @param bits state bits, assumed to include RUN but not CLOSED
+         */
+        final void startOnSignal(int bits) {
+            if ((ctl & bits) != bits &&
+                (getAndBitwiseOrCtl(bits) & (RUN | CLOSED)) == 0)
+                tryStart();
+        }
+
+        final void onSubscribe() {
+            startOnSignal(RUN | ACTIVE);
+        }
+
+        final void onComplete() {
+            startOnSignal(RUN | ACTIVE | COMPLETE);
+        }
+
+        final void onError(Throwable ex) {
+            int c; Object[] a;      // to null out buffer on async error
+            if (ex != null)
+                pendingError = ex;  // races are OK
+            if (((c = getAndBitwiseOrCtl(ERROR | RUN | ACTIVE)) & CLOSED) == 0) {
+                if ((c & RUN) == 0)
+                    tryStart();
+                else if ((a = array) != null)
+                    Arrays.fill(a, null);
+            }
+        }
+
+        public final void cancel() {
+            onError(null);
+        }
+
+        public final void request(long n) {
+            if (n > 0L) {
+                for (;;) {
+                    long p = demand, d = p + n;  // saturate
+                    if (casDemand(p, d < p ? Long.MAX_VALUE : d))
+                        break;
+                }
+                startOnSignal(RUN | ACTIVE | REQS);
+            }
+            else
+                onError(new IllegalArgumentException(
+                            "non-positive subscription request"));
+        }
+
+        // Consumer task actions
+
+        /**
+         * Consumer loop, called from ConsumerTask, or indirectly when
+         * helping during submit.
+         */
+        final void consume() {
+            Subscriber<? super T> s;
+            if ((s = subscriber) != null) {          // hoist checks
+                subscribeOnOpen(s);
+                long d = demand;
+                for (int h = head, t = tail;;) {
+                    int c, taken; boolean empty;
+                    if (((c = ctl) & ERROR) != 0) {
+                        closeOnError(s, null);
+                        break;
+                    }
+                    else if ((taken = takeItems(s, d, h)) > 0) {
+                        head = h += taken;
+                        d = subtractDemand(taken);
+                    }
+                    else if ((d = demand) == 0L && (c & REQS) != 0)
+                        weakCasCtl(c, c & ~REQS);    // exhausted demand
+                    else if (d != 0L && (c & REQS) == 0)
+                        weakCasCtl(c, c | REQS);     // new demand
+                    else if (t == (t = tail)) {      // stability check
+                        if ((empty = (t == h)) && (c & COMPLETE) != 0) {
+                            closeOnComplete(s);      // end of stream
+                            break;
+                        }
+                        else if (empty || d == 0L) {
+                            int bit = ((c & ACTIVE) != 0) ? ACTIVE : RUN;
+                            if (weakCasCtl(c, c & ~bit) && bit == RUN)
+                                break;               // un-keep-alive or exit
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Consumes some items until unavailable or bound or error.
+         *
+         * @param s subscriber
+         * @param d current demand
+         * @param h current head
+         * @return number taken
+         */
+        final int takeItems(Subscriber<? super T> s, long d, int h) {
+            Object[] a;
+            int k = 0, cap;
+            if ((a = array) != null && (cap = a.length) > 0) {
+                int m = cap - 1, b = (m >>> 3) + 1; // min(1, cap/8)
+                int n = (d < (long)b) ? (int)d : b;
+                for (; k < n; ++h, ++k) {
+                    Object x = QA.getAndSet(a, h & m, null);
+                    if (waiting != 0)
+                        signalWaiter();
+                    if (x == null)
+                        break;
+                    else if (!consumeNext(s, x))
+                        break;
+                }
+            }
+            return k;
+        }
+
+        final boolean consumeNext(Subscriber<? super T> s, Object x) {
+            try {
+                @SuppressWarnings("unchecked") T y = (T) x;
+                if (s != null)
+                    s.onNext(y);
+                return true;
+            } catch (Throwable ex) {
+                handleOnNext(s, ex);
+                return false;
+            }
+        }
+
+        /**
+         * Processes exception in Subscriber.onNext.
+         */
+        final void handleOnNext(Subscriber<? super T> s, Throwable ex) {
+            BiConsumer<? super Subscriber<? super T>, ? super Throwable> h;
+            try {
+                if ((h = onNextHandler) != null)
+                    h.accept(s, ex);
+            } catch (Throwable ignore) {
+            }
+            closeOnError(s, ex);
+        }
+
+        /**
+         * Issues subscriber.onSubscribe if this is first signal.
+         */
+        final void subscribeOnOpen(Subscriber<? super T> s) {
+            if ((ctl & OPEN) == 0 && (getAndBitwiseOrCtl(OPEN) & OPEN) == 0)
+                consumeSubscribe(s);
+        }
+
+        final void consumeSubscribe(Subscriber<? super T> s) {
+            try {
+                if (s != null) // ignore if disabled
+                    s.onSubscribe(this);
+            } catch (Throwable ex) {
+                closeOnError(s, ex);
+            }
+        }
+
+        /**
+         * Issues subscriber.onComplete unless already closed.
+         */
+        final void closeOnComplete(Subscriber<? super T> s) {
+            if ((getAndBitwiseOrCtl(CLOSED) & CLOSED) == 0)
+                consumeComplete(s);
+        }
+
+        final void consumeComplete(Subscriber<? super T> s) {
+            try {
+                if (s != null)
+                    s.onComplete();
+            } catch (Throwable ignore) {
+            }
+        }
+
+        /**
+         * Issues subscriber.onError, and unblocks producer if needed.
+         */
+        final void closeOnError(Subscriber<? super T> s, Throwable ex) {
+            if ((getAndBitwiseOrCtl(ERROR | CLOSED) & CLOSED) == 0) {
+                if (ex == null)
+                    ex = pendingError;
+                pendingError = null;  // detach
+                executor = null;      // suppress racing start calls
+                signalWaiter();
+                consumeError(s, ex);
+            }
+        }
+
+        final void consumeError(Subscriber<? super T> s, Throwable ex) {
+            try {
+                if (ex != null && s != null)
+                    s.onError(ex);
+            } catch (Throwable ignore) {
+            }
+        }
+
+        // Blocking support
+
+        /**
+         * Unblocks waiting producer.
+         */
+        final void signalWaiter() {
+            Thread w;
+            waiting = 0;
+            if ((w = waiter) != null)
+                LockSupport.unpark(w);
+        }
+
+        /**
+         * Returns true if closed or space available.
+         * For ManagedBlocker.
+         */
+        public final boolean isReleasable() {
+            Object[] a; int cap;
+            return ((ctl & CLOSED) != 0 ||
+                    ((a = array) != null && (cap = a.length) > 0 &&
+                     QA.getAcquire(a, (cap - 1) & tail) == null));
+        }
+
+        /**
+         * Helps or blocks until timeout, closed, or space available.
+         */
+        final void awaitSpace(long nanos) {
+            if (!isReleasable()) {
+                ForkJoinPool.helpAsyncBlocker(executor, this);
+                if (!isReleasable()) {
+                    timeout = nanos;
+                    try {
+                        ForkJoinPool.managedBlock(this);
+                    } catch (InterruptedException ie) {
+                        timeout = INTERRUPTED;
+                    }
+                    if (timeout == INTERRUPTED)
+                        Thread.currentThread().interrupt();
+                }
+            }
+        }
+
+        /**
+         * Blocks until closed, space available or timeout.
+         * For ManagedBlocker.
+         */
+        public final boolean block() {
+            long nanos = timeout;
+            boolean timed = (nanos < Long.MAX_VALUE);
+            long deadline = timed ? System.nanoTime() + nanos : 0L;
+            while (!isReleasable()) {
+                if (Thread.interrupted()) {
+                    timeout = INTERRUPTED;
+                    if (timed)
+                        break;
+                }
+                else if (timed && (nanos = deadline - System.nanoTime()) <= 0L)
+                    break;
+                else if (waiter == null)
+                    waiter = Thread.currentThread();
+                else if (waiting == 0)
+                    waiting = 1;
+                else if (timed)
+                    LockSupport.parkNanos(this, nanos);
+                else
+                    LockSupport.park(this);
+            }
+            waiter = null;
+            waiting = 0;
+            return true;
+        }
+
+        // VarHandle mechanics
+        static final VarHandle CTL;
+        static final VarHandle DEMAND;
+        static final VarHandle QA;
+
+        static {
+            try {
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                CTL = l.findVarHandle(BufferedSubscription.class, "ctl",
+                                      int.class);
+                DEMAND = l.findVarHandle(BufferedSubscription.class, "demand",
+                                         long.class);
+                QA = MethodHandles.arrayElementVarHandle(Object[].class);
+            } catch (ReflectiveOperationException e) {
+                throw new ExceptionInInitializerError(e);
+            }
+
+            // Reduce the risk of rare disastrous classloading in first call to
+            // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+            Class<?> ensureLoaded = LockSupport.class;
+        }
+    }
+}
diff --git a/ojluni/src/main/java/java/util/concurrent/SynchronousQueue.java b/ojluni/src/main/java/java/util/concurrent/SynchronousQueue.java
index 9655205..d15c3b5 100644
--- a/ojluni/src/main/java/java/util/concurrent/SynchronousQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/SynchronousQueue.java
@@ -36,19 +36,18 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.Objects;
 import java.util.Spliterator;
 import java.util.Spliterators;
 import java.util.concurrent.locks.LockSupport;
 import java.util.concurrent.locks.ReentrantLock;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
-
 /**
  * A {@linkplain BlockingQueue blocking queue} in which each insert
  * operation must wait for a corresponding remove operation by another
@@ -77,9 +76,12 @@
  * is not guaranteed. However, a queue constructed with fairness set
  * 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
- * Iterator} interfaces.
+ * <p>This class and its iterator implement all of the <em>optional</em>
+ * methods of the {@link Collection} and {@link Iterator} interfaces.
+ *
+ * <p>This class is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
  *
  * @since 1.5
  * @author Doug Lea and Bill Scherer and Michael Scott
@@ -247,7 +249,7 @@
 
             boolean casNext(SNode cmp, SNode val) {
                 return cmp == next &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    SNEXT.compareAndSet(this, cmp, val);
             }
 
             /**
@@ -260,7 +262,7 @@
              */
             boolean tryMatch(SNode s) {
                 if (match == null &&
-                    U.compareAndSwapObject(this, MATCH, null, s)) {
+                    SMATCH.compareAndSet(this, null, s)) {
                     Thread w = waiter;
                     if (w != null) {    // waiters need at most one unpark
                         waiter = null;
@@ -275,26 +277,23 @@
              * Tries to cancel a wait by matching node to itself.
              */
             void tryCancel() {
-                U.compareAndSwapObject(this, MATCH, null, this);
+                SMATCH.compareAndSet(this, null, this);
             }
 
             boolean isCancelled() {
                 return match == this;
             }
 
-            // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-            private static final long MATCH;
-            private static final long NEXT;
-
+            // VarHandle mechanics
+            private static final VarHandle SMATCH;
+            private static final VarHandle SNEXT;
             static {
                 try {
-                    MATCH = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("match"));
-                    NEXT = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("next"));
+                    MethodHandles.Lookup l = MethodHandles.lookup();
+                    SMATCH = l.findVarHandle(SNode.class, "match", SNode.class);
+                    SNEXT = l.findVarHandle(SNode.class, "next", SNode.class);
                 } catch (ReflectiveOperationException e) {
-                    throw new Error(e);
+                    throw new ExceptionInInitializerError(e);
                 }
             }
         }
@@ -304,7 +303,7 @@
 
         boolean casHead(SNode h, SNode nh) {
             return h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh);
+                SHEAD.compareAndSet(this, h, nh);
         }
 
         /**
@@ -451,8 +450,11 @@
                         continue;
                     }
                 }
-                if (spins > 0)
+                if (spins > 0) {
+                    // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+                    // Thread.onSpinWait();
                     spins = shouldSpin(s) ? (spins - 1) : 0;
+                }
                 else if (s.waiter == null)
                     s.waiter = w; // establish waiter so can park next iter
                 else if (!timed)
@@ -508,15 +510,14 @@
             }
         }
 
-        // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long HEAD;
+        // VarHandle mechanics
+        private static final VarHandle SHEAD;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferStack.class.getDeclaredField("head"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                SHEAD = l.findVarHandle(TransferStack.class, "head", SNode.class);
             } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                throw new ExceptionInInitializerError(e);
             }
         }
     }
@@ -546,19 +547,19 @@
 
             boolean casNext(QNode cmp, QNode val) {
                 return next == cmp &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    QNEXT.compareAndSet(this, cmp, val);
             }
 
             boolean casItem(Object cmp, Object val) {
                 return item == cmp &&
-                    U.compareAndSwapObject(this, ITEM, cmp, val);
+                    QITEM.compareAndSet(this, cmp, val);
             }
 
             /**
              * Tries to cancel by CAS'ing ref to this as item.
              */
             void tryCancel(Object cmp) {
-                U.compareAndSwapObject(this, ITEM, cmp, this);
+                QITEM.compareAndSet(this, cmp, this);
             }
 
             boolean isCancelled() {
@@ -574,19 +575,16 @@
                 return next == this;
             }
 
-            // Unsafe mechanics
-            private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-            private static final long ITEM;
-            private static final long NEXT;
-
+            // VarHandle mechanics
+            private static final VarHandle QITEM;
+            private static final VarHandle QNEXT;
             static {
                 try {
-                    ITEM = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("item"));
-                    NEXT = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("next"));
+                    MethodHandles.Lookup l = MethodHandles.lookup();
+                    QITEM = l.findVarHandle(QNode.class, "item", Object.class);
+                    QNEXT = l.findVarHandle(QNode.class, "next", QNode.class);
                 } catch (ReflectiveOperationException e) {
-                    throw new Error(e);
+                    throw new ExceptionInInitializerError(e);
                 }
             }
         }
@@ -614,7 +612,7 @@
          */
         void advanceHead(QNode h, QNode nh) {
             if (h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh))
+                QHEAD.compareAndSet(this, h, nh))
                 h.next = h; // forget old next
         }
 
@@ -623,7 +621,7 @@
          */
         void advanceTail(QNode t, QNode nt) {
             if (tail == t)
-                U.compareAndSwapObject(this, TAIL, t, nt);
+                QTAIL.compareAndSet(this, t, nt);
         }
 
         /**
@@ -631,7 +629,7 @@
          */
         boolean casCleanMe(QNode cmp, QNode val) {
             return cleanMe == cmp &&
-                U.compareAndSwapObject(this, CLEANME, cmp, val);
+                QCLEANME.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -752,8 +750,11 @@
                         continue;
                     }
                 }
-                if (spins > 0)
+                if (spins > 0) {
                     --spins;
+                    // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+                    // Thread.onSpinWait();
+                }
                 else if (s.waiter == null)
                     s.waiter = w;
                 else if (!timed)
@@ -817,20 +818,21 @@
             }
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long HEAD;
-        private static final long TAIL;
-        private static final long CLEANME;
+        // VarHandle mechanics
+        private static final VarHandle QHEAD;
+        private static final VarHandle QTAIL;
+        private static final VarHandle QCLEANME;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("head"));
-                TAIL = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("tail"));
-                CLEANME = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("cleanMe"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                QHEAD = l.findVarHandle(TransferQueue.class, "head",
+                                        QNode.class);
+                QTAIL = l.findVarHandle(TransferQueue.class, "tail",
+                                        QNode.class);
+                QCLEANME = l.findVarHandle(TransferQueue.class, "cleanMe",
+                                           QNode.class);
             } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                throw new ExceptionInInitializerError(e);
             }
         }
     }
@@ -1066,7 +1068,7 @@
 
     /**
      * Returns an empty spliterator in which calls to
-     * {@link java.util.Spliterator#trySplit()} always return {@code null}.
+     * {@link Spliterator#trySplit() trySplit} always return {@code null}.
      *
      * @return an empty spliterator
      * @since 1.8
@@ -1112,15 +1114,12 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         int n = 0;
-        for (E e; (e = poll()) != null;) {
+        for (E e; (e = poll()) != null; n++)
             c.add(e);
-            ++n;
-        }
         return n;
     }
 
@@ -1131,15 +1130,12 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c, int maxElements) {
-        if (c == null)
-            throw new NullPointerException();
+        Objects.requireNonNull(c);
         if (c == this)
             throw new IllegalArgumentException();
         int n = 0;
-        for (E e; n < maxElements && (e = poll()) != null;) {
+        for (E e; n < maxElements && (e = poll()) != null; n++)
             c.add(e);
-            ++n;
-        }
         return n;
     }
 
diff --git a/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java b/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
index 195f8ac..c20d2b3 100644
--- a/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
+++ b/ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java
@@ -36,6 +36,7 @@
 package java.util.concurrent;
 
 import java.io.ObjectStreamField;
+import java.security.AccessControlContext;
 import java.util.Random;
 import java.util.Spliterator;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -47,6 +48,8 @@
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
 import java.util.stream.StreamSupport;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.misc.VM;
 
 /**
  * A random number generator isolated to the current thread.  Like the
@@ -64,7 +67,7 @@
  * {@code ThreadLocalRandom.current().nextX(...)} (where
  * {@code X} is {@code Int}, {@code Long}, etc).
  * When all usages are of this form, it is never possible to
- * accidently share a {@code ThreadLocalRandom} across multiple threads.
+ * accidentally share a {@code ThreadLocalRandom} across multiple threads.
  *
  * <p>This class also provides additional commonly used bounded random
  * generation methods.
@@ -95,7 +98,9 @@
      * ThreadLocalRandom sequence.  The dual use is a marriage of
      * convenience, but is a simple and efficient way of reducing
      * application-level overhead and footprint of most concurrent
-     * programs.
+     * programs. Even more opportunistically, we also define here
+     * other package-private utilities that access Thread class
+     * fields.
      *
      * Even though this class subclasses java.util.Random, it uses the
      * same basic algorithm as java.util.SplittableRandom.  (See its
@@ -193,9 +198,17 @@
         return r;
     }
 
-    // We must define this, but never use it.
+    /**
+     * Generates a pseudorandom number with the indicated number of
+     * low-order bits.  Because this class has no subclasses, this
+     * method cannot be invoked or overridden.
+     *
+     * @param  bits random bits
+     * @return the next pseudorandom value from this random number
+     *         generator's sequence
+     */
     protected int next(int bits) {
-        return (int)(mix64(nextSeed()) >>> (64 - bits));
+        return nextInt() >>> (32 - bits);
     }
 
     /**
@@ -455,7 +468,7 @@
             s = v1 * v1 + v2 * v2;
         } while (s >= 1 || s == 0);
         double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s)/s);
-        nextLocalGaussian.set(new Double(v2 * multiplier));
+        nextLocalGaussian.set(Double.valueOf(v2 * multiplier));
         return v1 * multiplier;
     }
 
@@ -687,8 +700,7 @@
      * @return a stream of pseudorandom {@code double} values,
      *         each with the given origin (inclusive) and bound (exclusive)
      * @throws IllegalArgumentException if {@code streamSize} is
-     *         less than zero
-     * @throws IllegalArgumentException if {@code randomNumberOrigin}
+     *         less than zero, or {@code randomNumberOrigin}
      *         is greater than or equal to {@code randomNumberBound}
      * @since 1.8
      */
@@ -958,6 +970,21 @@
         return r;
     }
 
+    // Support for other package-private ThreadLocal access
+
+    /**
+     * Erases ThreadLocals by nulling out Thread maps.
+     */
+    static final void eraseThreadLocals(Thread thread) {
+        U.putObject(thread, THREADLOCALS, null);
+        U.putObject(thread, INHERITABLETHREADLOCALS, null);
+    }
+
+    static final void setInheritedAccessControlContext(Thread thread,
+                                                       AccessControlContext acc) {
+        U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
+    }
+
     // Serialization support
 
     private static final long serialVersionUID = -5851777807851030925L;
@@ -1012,7 +1039,10 @@
      */
     private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
 
-    // Constants from SplittableRandom
+    /**
+     * The least non-zero value returned by nextDouble(). This value
+     * is scaled by a random value of 53 bits to produce a result.
+     */
     private static final double DOUBLE_UNIT = 0x1.0p-53;  // 1.0  / (1L << 53)
     private static final float  FLOAT_UNIT  = 0x1.0p-24f; // 1.0f / (1 << 24)
 
@@ -1022,22 +1052,19 @@
     static final String BAD_SIZE  = "size must be non-negative";
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long SEED;
-    private static final long PROBE;
-    private static final long SECONDARY;
-    static {
-        try {
-            SEED = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocalRandomSeed"));
-            PROBE = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocalRandomProbe"));
-            SECONDARY = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
+    private static final Unsafe U = Unsafe.getUnsafe();
+    private static final long SEED = U.objectFieldOffset
+            (Thread.class, "threadLocalRandomSeed");
+    private static final long PROBE = U.objectFieldOffset
+            (Thread.class, "threadLocalRandomProbe");
+    private static final long SECONDARY = U.objectFieldOffset
+            (Thread.class, "threadLocalRandomSecondarySeed");
+    private static final long THREADLOCALS = U.objectFieldOffset
+            (Thread.class, "threadLocals");
+    private static final long INHERITABLETHREADLOCALS = U.objectFieldOffset
+            (Thread.class, "inheritableThreadLocals");
+    private static final long INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
+            (Thread.class, "inheritedAccessControlContext");
 
     /** Rarely-used holder for the second of a pair of Gaussians */
     private static final ThreadLocal<Double> nextLocalGaussian =
@@ -1058,11 +1085,8 @@
 
     // at end of <clinit> to survive static initialization circularity
     static {
-        if (java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Boolean>() {
-                public Boolean run() {
-                    return Boolean.getBoolean("java.util.secureRandomSeed");
-                }})) {
+        String sec = VM.getSavedProperty("java.util.secureRandomSeed");
+        if (Boolean.parseBoolean(sec)) {
             byte[] seedBytes = java.security.SecureRandom.getSeed(8);
             long s = (long)seedBytes[0] & 0xffL;
             for (int i = 1; i < 8; ++i)
diff --git a/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index b0096a4..0d88feb 100644
--- a/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -79,31 +79,28 @@
  *
  * <dt>Core and maximum pool sizes</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * A {@code ThreadPoolExecutor} will automatically adjust the
+ * <dd>A {@code ThreadPoolExecutor} will automatically adjust the
  * pool size (see {@link #getPoolSize})
  * according to the bounds set by
  * corePoolSize (see {@link #getCorePoolSize}) and
  * maximumPoolSize (see {@link #getMaximumPoolSize}).
  *
  * When a new task is submitted in method {@link #execute(Runnable)},
- * and fewer than corePoolSize threads are running, a new thread is
+ * if 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>
+ * idle.  Else if fewer than maximumPoolSize threads are running, a
+ * new thread will be created to handle the request 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 style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * 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
@@ -111,8 +108,7 @@
  *
  * <dt>Creating new threads</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * New threads are created using a {@link ThreadFactory}.  If not
+ * <dd>New threads are created using a {@link ThreadFactory}.  If not
  * otherwise specified, a {@link Executors#defaultThreadFactory} is
  * used, that creates threads to all be in the same {@link
  * ThreadGroup} and with the same {@code NORM_PRIORITY} priority and
@@ -129,8 +125,7 @@
  *
  * <dt>Keep-alive times</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * If the pool currently has more than corePoolSize threads,
+ * <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(TimeUnit)}).
  * This provides a means of reducing resource consumption when the
@@ -147,8 +142,7 @@
  *
  * <dt>Queuing</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * Any {@link BlockingQueue} may be used to transfer and hold
+ * <dd>Any {@link BlockingQueue} may be used to transfer and hold
  * submitted tasks.  The use of this queue interacts with pool sizing:
  *
  * <ul>
@@ -213,8 +207,7 @@
  *
  * <dt>Rejected tasks</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * New tasks submitted in method {@link #execute(Runnable)} will be
+ * <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
@@ -225,9 +218,8 @@
  *
  * <ol>
  *
- * <li>In the default {@link ThreadPoolExecutor.AbortPolicy}, the
- * handler throws a runtime {@link RejectedExecutionException} upon
- * rejection.
+ * <li>In the default {@link ThreadPoolExecutor.AbortPolicy}, the handler
+ * throws a runtime {@link RejectedExecutionException} upon rejection.
  *
  * <li>In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread
  * that invokes {@code execute} itself runs the task. This provides a
@@ -251,8 +243,7 @@
  *
  * <dt>Hook methods</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * This class provides {@code protected} overridable
+ * <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
@@ -268,22 +259,19 @@
  *
  * <dt>Queue maintenance</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * Method {@link #getQueue()} allows access to the work queue
+ * <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>
+ * <dt>Reclamation</dt>
  *
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * 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
- * that unused threads eventually die, by setting appropriate
+ * <dd>A pool that is no longer referenced in a program <em>AND</em>
+ * has no remaining threads may be reclaimed (garbage collected)
+ * without being explicitly shutdown. You can configure a pool to
+ * allow all unused threads to eventually die by setting appropriate
  * keep-alive times, using a lower bound of zero core threads and/or
  * setting {@link #allowCoreThreadTimeOut(boolean)}.  </dd>
  *
@@ -374,7 +362,7 @@
      * time, but need not hit each state. The transitions are:
      *
      * RUNNING -> SHUTDOWN
-     *    On invocation of shutdown(), perhaps implicitly in finalize()
+     *    On invocation of shutdown()
      * (RUNNING or SHUTDOWN) -> STOP
      *    On invocation of shutdownNow()
      * SHUTDOWN -> TIDYING
@@ -398,7 +386,7 @@
     @ReachabilitySensitive
     private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
     private static final int COUNT_BITS = Integer.SIZE - 3;
-    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
+    private static final int COUNT_MASK = (1 << COUNT_BITS) - 1;
 
     // runState is stored in the high-order bits
     private static final int RUNNING    = -1 << COUNT_BITS;
@@ -408,8 +396,8 @@
     private static final int TERMINATED =  3 << COUNT_BITS;
 
     // Packing and unpacking ctl
-    private static int runStateOf(int c)     { return c & ~CAPACITY; }
-    private static int workerCountOf(int c)  { return c & CAPACITY; }
+    private static int runStateOf(int c)     { return c & ~COUNT_MASK; }
+    private static int workerCountOf(int c)  { return c & COUNT_MASK; }
     private static int ctlOf(int rs, int wc) { return rs | wc; }
 
     /*
@@ -449,7 +437,7 @@
      * decrements are performed within getTask.
      */
     private void decrementWorkerCount() {
-        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
+        ctl.addAndGet(-1);
     }
 
     /**
@@ -555,12 +543,17 @@
      * Core pool size is the minimum number of workers to keep alive
      * (and not allow to time out etc) unless allowCoreThreadTimeOut
      * is set, in which case the minimum is zero.
+     *
+     * Since the worker count is actually stored in COUNT_BITS bits,
+     * the effective limit is {@code corePoolSize & COUNT_MASK}.
      */
     private volatile int corePoolSize;
 
     /**
-     * Maximum pool size. Note that the actual maximum is internally
-     * bounded by CAPACITY.
+     * Maximum pool size.
+     *
+     * Since the worker count is actually stored in COUNT_BITS bits,
+     * the effective limit is {@code maximumPoolSize & COUNT_MASK}.
      */
     private volatile int maximumPoolSize;
 
@@ -626,6 +619,9 @@
         /** Per-thread task counter */
         volatile long completedTasks;
 
+        // TODO: switch to AbstractQueuedLongSynchronizer and move
+        // completedTasks into the lock word.
+
         /**
          * Creates with given first task and thread from ThreadFactory.
          * @param firstTask the first task (null if none)
@@ -716,7 +712,7 @@
             int c = ctl.get();
             if (isRunning(c) ||
                 runStateAtLeast(c, TIDYING) ||
-                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
+                (runStateLessThan(c, STOP) && ! workQueue.isEmpty()))
                 return;
             if (workerCountOf(c) != 0) { // Eligible to terminate
                 interruptIdleWorkers(ONLY_ONE);
@@ -755,17 +751,12 @@
      * specially.
      */
     private void checkShutdownAccess() {
+        // assert mainLock.isHeldByCurrentThread();
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkPermission(shutdownPerm);
-            final ReentrantLock mainLock = this.mainLock;
-            mainLock.lock();
-            try {
-                for (Worker w : workers)
-                    security.checkAccess(w.thread);
-            } finally {
-                mainLock.unlock();
-            }
+            for (Worker w : workers)
+                security.checkAccess(w.thread);
         }
     }
 
@@ -774,14 +765,9 @@
      * (in which case some threads may remain uninterrupted).
      */
     private void interruptWorkers() {
-        final ReentrantLock mainLock = this.mainLock;
-        mainLock.lock();
-        try {
-            for (Worker w : workers)
-                w.interruptIfStarted();
-        } finally {
-            mainLock.unlock();
-        }
+        // assert mainLock.isHeldByCurrentThread();
+        for (Worker w : workers)
+            w.interruptIfStarted();
     }
 
     /**
@@ -857,17 +843,6 @@
     }
 
     /**
-     * State check needed by ScheduledThreadPoolExecutor to
-     * enable running tasks during shutdown.
-     *
-     * @param shutdownOK true if should return true if SHUTDOWN
-     */
-    final boolean isRunningOrShutdown(boolean shutdownOK) {
-        int rs = runStateOf(ctl.get());
-        return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
-    }
-
-    /**
      * Drains the task queue into a new list, normally using
      * drainTo. But if the queue is a DelayQueue or any other kind of
      * queue for which poll or drainTo may fail to remove some
@@ -918,26 +893,22 @@
      */
     private boolean addWorker(Runnable firstTask, boolean core) {
         retry:
-        for (;;) {
-            int c = ctl.get();
-            int rs = runStateOf(c);
-
+        for (int c = ctl.get();;) {
             // Check if queue empty only if necessary.
-            if (rs >= SHUTDOWN &&
-                ! (rs == SHUTDOWN &&
-                   firstTask == null &&
-                   ! workQueue.isEmpty()))
+            if (runStateAtLeast(c, SHUTDOWN)
+                && (runStateAtLeast(c, STOP)
+                    || firstTask != null
+                    || workQueue.isEmpty()))
                 return false;
 
             for (;;) {
-                int wc = workerCountOf(c);
-                if (wc >= CAPACITY ||
-                    wc >= (core ? corePoolSize : maximumPoolSize))
+                if (workerCountOf(c)
+                    >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
                     return false;
                 if (compareAndIncrementWorkerCount(c))
                     break retry;
                 c = ctl.get();  // Re-read ctl
-                if (runStateOf(c) != rs)
+                if (runStateAtLeast(c, SHUTDOWN))
                     continue retry;
                 // else CAS failed due to workerCount change; retry inner loop
             }
@@ -956,17 +927,17 @@
                     // Recheck while holding lock.
                     // Back out on ThreadFactory failure or if
                     // shut down before lock acquired.
-                    int rs = runStateOf(ctl.get());
+                    int c = ctl.get();
 
-                    if (rs < SHUTDOWN ||
-                        (rs == SHUTDOWN && firstTask == null)) {
-                        if (t.isAlive()) // precheck that t is startable
+                    if (isRunning(c) ||
+                        (runStateLessThan(c, STOP) && firstTask == null)) {
+                        if (t.getState() != Thread.State.NEW)
                             throw new IllegalThreadStateException();
                         workers.add(w);
+                        workerAdded = true;
                         int s = workers.size();
                         if (s > largestPoolSize)
                             largestPoolSize = s;
-                        workerAdded = true;
                     }
                 } finally {
                     mainLock.unlock();
@@ -1066,10 +1037,10 @@
 
         for (;;) {
             int c = ctl.get();
-            int rs = runStateOf(c);
 
             // Check if queue empty only if necessary.
-            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
+            if (runStateAtLeast(c, SHUTDOWN)
+                && (runStateAtLeast(c, STOP) || workQueue.isEmpty())) {
                 decrementWorkerCount();
                 return null;
             }
@@ -1162,17 +1133,12 @@
                     wt.interrupt();
                 try {
                     beforeExecute(wt, task);
-                    Throwable thrown = null;
                     try {
                         task.run();
-                    } catch (RuntimeException x) {
-                        thrown = x; throw x;
-                    } catch (Error x) {
-                        thrown = x; throw x;
-                    } catch (Throwable x) {
-                        thrown = x; throw new Error(x);
-                    } finally {
-                        afterExecute(task, thrown);
+                        afterExecute(task, null);
+                    } catch (Throwable ex) {
+                        afterExecute(task, ex);
+                        throw ex;
                     }
                 } finally {
                     task = null;
@@ -1190,9 +1156,11 @@
 
     /**
      * Creates a new {@code ThreadPoolExecutor} with the given initial
-     * parameters and default thread factory and rejected execution handler.
-     * It may be more convenient to use one of the {@link Executors} factory
-     * methods instead of this general purpose constructor.
+     * parameters, the default thread factory and the default rejected
+     * execution handler.
+     *
+     * <p>It may be more convenient to use one of the {@link Executors}
+     * factory methods instead of this general purpose constructor.
      *
      * @param corePoolSize the number of threads to keep in the pool, even
      *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -1223,7 +1191,8 @@
 
     /**
      * Creates a new {@code ThreadPoolExecutor} with the given initial
-     * parameters and default rejected execution handler.
+     * parameters and {@linkplain ThreadPoolExecutor.AbortPolicy
+     * default rejected execution handler}.
      *
      * @param corePoolSize the number of threads to keep in the pool, even
      *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -1258,7 +1227,8 @@
 
     /**
      * Creates a new {@code ThreadPoolExecutor} with the given initial
-     * parameters and default thread factory.
+     * parameters and
+     * {@linkplain Executors#defaultThreadFactory default thread factory}.
      *
      * @param corePoolSize the number of threads to keep in the pool, even
      *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -1346,7 +1316,7 @@
      *
      * If the task cannot be submitted for execution, either because this
      * executor has been shutdown or because its capacity has been reached,
-     * the task is handled by the current {@code RejectedExecutionHandler}.
+     * the task is handled by the current {@link RejectedExecutionHandler}.
      *
      * @param command the task to execute
      * @throws RejectedExecutionException at discretion of
@@ -1451,7 +1421,12 @@
     }
 
     public boolean isShutdown() {
-        return ! isRunning(ctl.get());
+        return runStateAtLeast(ctl.get(), SHUTDOWN);
+    }
+
+    /** Used by ScheduledThreadPoolExecutor. */
+    boolean isStopped() {
+        return runStateAtLeast(ctl.get(), STOP);
     }
 
     /**
@@ -1467,7 +1442,7 @@
      */
     public boolean isTerminating() {
         int c = ctl.get();
-        return ! isRunning(c) && runStateLessThan(c, TERMINATED);
+        return runStateAtLeast(c, SHUTDOWN) && runStateLessThan(c, TERMINATED);
     }
 
     public boolean isTerminated() {
@@ -1480,7 +1455,7 @@
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            while (!runStateAtLeast(ctl.get(), TERMINATED)) {
+            while (runStateLessThan(ctl.get(), TERMINATED)) {
                 if (nanos <= 0L)
                     return false;
                 nanos = termination.awaitNanos(nanos);
@@ -1491,13 +1466,21 @@
         }
     }
 
+    // Override without "throws Throwable" for compatibility with subclasses
+    // whose finalize method invokes super.finalize() (as is recommended).
+    // Before JDK 11, finalize() had a non-empty method body.
+
+    // Android-added: The @deprecated javadoc tag
     /**
-     * Invokes {@code shutdown} when this executor is no longer
-     * referenced and it has no threads.
+     * @implNote Previous versions of this class had a finalize method
+     * that shut down this executor, but in this version, finalize
+     * does nothing.
+     *
+     * @deprecated Subclass is not recommended to override finalize(). If it
+     * must, please always invoke super.finalize().
      */
-    protected void finalize() {
-        shutdown();
-    }
+    @Deprecated(since="9")
+    protected void finalize() {}
 
     /**
      * Sets the thread factory used to create new threads.
@@ -1946,7 +1929,7 @@
         }
         int c = ctl.get();
         String runState =
-            runStateLessThan(c, SHUTDOWN) ? "Running" :
+            isRunning(c) ? "Running" :
             runStateAtLeast(c, TERMINATED) ? "Terminated" :
             "Shutting down";
         return super.toString() +
@@ -2065,7 +2048,10 @@
 
     /**
      * A handler for rejected tasks that throws a
-     * {@code RejectedExecutionException}.
+     * {@link RejectedExecutionException}.
+     *
+     * This is the default handler for {@link ThreadPoolExecutor} and
+     * {@link ScheduledThreadPoolExecutor}.
      */
     public static class AbortPolicy implements RejectedExecutionHandler {
         /**
diff --git a/ojluni/src/main/java/java/util/concurrent/TimeUnit.java b/ojluni/src/main/java/java/util/concurrent/TimeUnit.java
index 44d7964..f02aa9f 100644
--- a/ojluni/src/main/java/java/util/concurrent/TimeUnit.java
+++ b/ojluni/src/main/java/java/util/concurrent/TimeUnit.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
 import java.util.Objects;
 
 /**
@@ -74,136 +76,93 @@
     /**
      * Time unit representing one thousandth of a microsecond.
      */
-    NANOSECONDS {
-        public long toNanos(long d)   { return d; }
-        public long toMicros(long d)  { return d/(C1/C0); }
-        public long toMillis(long d)  { return d/(C2/C0); }
-        public long toSeconds(long d) { return d/(C3/C0); }
-        public long toMinutes(long d) { return d/(C4/C0); }
-        public long toHours(long d)   { return d/(C5/C0); }
-        public long toDays(long d)    { return d/(C6/C0); }
-        public long convert(long d, TimeUnit u) { return u.toNanos(d); }
-        int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
-    },
-
+    NANOSECONDS(TimeUnit.NANO_SCALE),
     /**
      * Time unit representing one thousandth of a millisecond.
      */
-    MICROSECONDS {
-        public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
-        public long toMicros(long d)  { return d; }
-        public long toMillis(long d)  { return d/(C2/C1); }
-        public long toSeconds(long d) { return d/(C3/C1); }
-        public long toMinutes(long d) { return d/(C4/C1); }
-        public long toHours(long d)   { return d/(C5/C1); }
-        public long toDays(long d)    { return d/(C6/C1); }
-        public long convert(long d, TimeUnit u) { return u.toMicros(d); }
-        int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
-    },
-
+    MICROSECONDS(TimeUnit.MICRO_SCALE),
     /**
      * Time unit representing one thousandth of a second.
      */
-    MILLISECONDS {
-        public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
-        public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
-        public long toMillis(long d)  { return d; }
-        public long toSeconds(long d) { return d/(C3/C2); }
-        public long toMinutes(long d) { return d/(C4/C2); }
-        public long toHours(long d)   { return d/(C5/C2); }
-        public long toDays(long d)    { return d/(C6/C2); }
-        public long convert(long d, TimeUnit u) { return u.toMillis(d); }
-        int excessNanos(long d, long m) { return 0; }
-    },
-
+    MILLISECONDS(TimeUnit.MILLI_SCALE),
     /**
      * Time unit representing one second.
      */
-    SECONDS {
-        public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
-        public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
-        public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
-        public long toSeconds(long d) { return d; }
-        public long toMinutes(long d) { return d/(C4/C3); }
-        public long toHours(long d)   { return d/(C5/C3); }
-        public long toDays(long d)    { return d/(C6/C3); }
-        public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
-        int excessNanos(long d, long m) { return 0; }
-    },
-
+    SECONDS(TimeUnit.SECOND_SCALE),
     /**
      * Time unit representing sixty seconds.
      * @since 1.6
      */
-    MINUTES {
-        public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
-        public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
-        public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
-        public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
-        public long toMinutes(long d) { return d; }
-        public long toHours(long d)   { return d/(C5/C4); }
-        public long toDays(long d)    { return d/(C6/C4); }
-        public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
-        int excessNanos(long d, long m) { return 0; }
-    },
-
+    MINUTES(TimeUnit.MINUTE_SCALE),
     /**
      * Time unit representing sixty minutes.
      * @since 1.6
      */
-    HOURS {
-        public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
-        public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
-        public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
-        public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
-        public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
-        public long toHours(long d)   { return d; }
-        public long toDays(long d)    { return d/(C6/C5); }
-        public long convert(long d, TimeUnit u) { return u.toHours(d); }
-        int excessNanos(long d, long m) { return 0; }
-    },
-
+    HOURS(TimeUnit.HOUR_SCALE),
     /**
      * Time unit representing twenty four hours.
      * @since 1.6
      */
-    DAYS {
-        public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
-        public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
-        public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
-        public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
-        public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
-        public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
-        public long toDays(long d)    { return d; }
-        public long convert(long d, TimeUnit u) { return u.toDays(d); }
-        int excessNanos(long d, long m) { return 0; }
-    };
+    DAYS(TimeUnit.DAY_SCALE);
 
-    // Handy constants for conversion methods
-    static final long C0 = 1L;
-    static final long C1 = C0 * 1000L;
-    static final long C2 = C1 * 1000L;
-    static final long C3 = C2 * 1000L;
-    static final long C4 = C3 * 60L;
-    static final long C5 = C4 * 60L;
-    static final long C6 = C5 * 24L;
+    // Scales as constants
+    private static final long NANO_SCALE   = 1L;
+    private static final long MICRO_SCALE  = 1000L * NANO_SCALE;
+    private static final long MILLI_SCALE  = 1000L * MICRO_SCALE;
+    private static final long SECOND_SCALE = 1000L * MILLI_SCALE;
+    private static final long MINUTE_SCALE = 60L * SECOND_SCALE;
+    private static final long HOUR_SCALE   = 60L * MINUTE_SCALE;
+    private static final long DAY_SCALE    = 24L * HOUR_SCALE;
 
-    static final long MAX = Long.MAX_VALUE;
-
-    /**
-     * Scale d by m, checking for overflow.
-     * This has a short name to make above code more readable.
+    /*
+     * Instances cache conversion ratios and saturation cutoffs for
+     * the units up through SECONDS. Other cases compute them, in
+     * method cvt.
      */
-    static long x(long d, long m, long over) {
-        if (d > +over) return Long.MAX_VALUE;
-        if (d < -over) return Long.MIN_VALUE;
-        return d * m;
+
+    private final long scale;
+    private final long maxNanos;
+    private final long maxMicros;
+    private final long maxMillis;
+    private final long maxSecs;
+    private final long microRatio;
+    private final int milliRatio;   // fits in 32 bits
+    private final int secRatio;     // fits in 32 bits
+
+    private TimeUnit(long s) {
+        this.scale = s;
+        this.maxNanos = Long.MAX_VALUE / s;
+        long ur = (s >= MICRO_SCALE) ? (s / MICRO_SCALE) : (MICRO_SCALE / s);
+        this.microRatio = ur;
+        this.maxMicros = Long.MAX_VALUE / ur;
+        long mr = (s >= MILLI_SCALE) ? (s / MILLI_SCALE) : (MILLI_SCALE / s);
+        this.milliRatio = (int)mr;
+        this.maxMillis = Long.MAX_VALUE / mr;
+        long sr = (s >= SECOND_SCALE) ? (s / SECOND_SCALE) : (SECOND_SCALE / s);
+        this.secRatio = (int)sr;
+        this.maxSecs = Long.MAX_VALUE / sr;
     }
 
-    // To maintain full signature compatibility with 1.5, and to improve the
-    // clarity of the generated javadoc (see 6287639: Abstract methods in
-    // enum classes should not be listed as abstract), method convert
-    // etc. are not declared abstract but otherwise act as abstract methods.
+    /**
+     * General conversion utility.
+     *
+     * @param d duration
+     * @param dst result unit scale
+     * @param src source unit scale
+     */
+    private static long cvt(long d, long dst, long src) {
+        long r, m;
+        if (src == dst)
+            return d;
+        else if (src < dst)
+            return d / (dst / src);
+        else if (d > (m = Long.MAX_VALUE / (r = src / dst)))
+            return Long.MAX_VALUE;
+        else if (d < -m)
+            return Long.MIN_VALUE;
+        else
+            return d * r;
+    }
 
     /**
      * Converts the given time duration in the given unit to this unit.
@@ -220,11 +179,65 @@
      * @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 {@code Long.MIN_VALUE} if conversion would negatively
-     * overflow, or {@code Long.MAX_VALUE} 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();
+        switch (this) {
+        case NANOSECONDS:  return sourceUnit.toNanos(sourceDuration);
+        case MICROSECONDS: return sourceUnit.toMicros(sourceDuration);
+        case MILLISECONDS: return sourceUnit.toMillis(sourceDuration);
+        case SECONDS:      return sourceUnit.toSeconds(sourceDuration);
+        default: return cvt(sourceDuration, scale, sourceUnit.scale);
+        }
+    }
+
+    /**
+     * Converts the given time duration to this unit.
+     *
+     * <p>For any TimeUnit {@code unit},
+     * {@code unit.convert(Duration.ofNanos(n))}
+     * is equivalent to
+     * {@code unit.convert(n, NANOSECONDS)}, and
+     * {@code unit.convert(Duration.of(n, unit.toChronoUnit()))}
+     * is equivalent to {@code n} (in the absence of overflow).
+     *
+     * @apiNote
+     * This method differs from {@link Duration#toNanos()} in that it
+     * does not throw {@link ArithmeticException} on numeric overflow.
+     *
+     * @param duration the time duration
+     * @return the converted duration in this unit,
+     * or {@code Long.MIN_VALUE} if conversion would negatively overflow,
+     * or {@code Long.MAX_VALUE} if it would positively overflow.
+     * @throws NullPointerException if {@code duration} is null
+     * @see Duration#of(long,TemporalUnit)
+     * @since 11
+     */
+    public long convert(Duration duration) {
+        long secs = duration.getSeconds();
+        int nano = duration.getNano();
+        if (secs < 0 && nano > 0) {
+            // use representation compatible with integer division
+            secs++;
+            nano -= (int) SECOND_SCALE;
+        }
+        final long s, nanoVal;
+        // Optimize for the common case - NANOSECONDS without overflow
+        if (this == NANOSECONDS)
+            nanoVal = nano;
+        else if ((s = scale) < SECOND_SCALE)
+            nanoVal = nano / s;
+        else if (this == SECONDS)
+            return secs;
+        else
+            return secs / secRatio;
+        long val = secs * secRatio + nanoVal;
+        return ((secs < maxSecs && secs > -maxSecs) ||
+                (secs == maxSecs && val > 0) ||
+                (secs == -maxSecs && val < 0))
+            ? val
+            : (secs > 0) ? Long.MAX_VALUE : Long.MIN_VALUE;
     }
 
     /**
@@ -232,11 +245,19 @@
      * {@link #convert(long, TimeUnit) NANOSECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or {@code Long.MIN_VALUE} if conversion would negatively
-     * overflow, or {@code Long.MAX_VALUE} 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 toNanos(long duration) {
-        throw new AbstractMethodError();
+        long s, m;
+        if ((s = scale) == NANO_SCALE)
+            return duration;
+        else if (duration > (m = maxNanos))
+            return Long.MAX_VALUE;
+        else if (duration < -m)
+            return Long.MIN_VALUE;
+        else
+            return duration * s;
     }
 
     /**
@@ -244,11 +265,19 @@
      * {@link #convert(long, TimeUnit) MICROSECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or {@code Long.MIN_VALUE} if conversion would negatively
-     * overflow, or {@code Long.MAX_VALUE} 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 toMicros(long duration) {
-        throw new AbstractMethodError();
+        long s, m;
+        if ((s = scale) <= MICRO_SCALE)
+            return (s == MICRO_SCALE) ? duration : duration / microRatio;
+        else if (duration > (m = maxMicros))
+            return Long.MAX_VALUE;
+        else if (duration < -m)
+            return Long.MIN_VALUE;
+        else
+            return duration * microRatio;
     }
 
     /**
@@ -256,11 +285,19 @@
      * {@link #convert(long, TimeUnit) MILLISECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or {@code Long.MIN_VALUE} if conversion would negatively
-     * overflow, or {@code Long.MAX_VALUE} 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 toMillis(long duration) {
-        throw new AbstractMethodError();
+        long s, m;
+        if ((s = scale) <= MILLI_SCALE)
+            return (s == MILLI_SCALE) ? duration : duration / milliRatio;
+        else if (duration > (m = maxMillis))
+            return Long.MAX_VALUE;
+        else if (duration < -m)
+            return Long.MIN_VALUE;
+        else
+            return duration * milliRatio;
     }
 
     /**
@@ -268,11 +305,19 @@
      * {@link #convert(long, TimeUnit) SECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or {@code Long.MIN_VALUE} if conversion would negatively
-     * overflow, or {@code Long.MAX_VALUE} 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 toSeconds(long duration) {
-        throw new AbstractMethodError();
+        long s, m;
+        if ((s = scale) <= SECOND_SCALE)
+            return (s == SECOND_SCALE) ? duration : duration / secRatio;
+        else if (duration > (m = maxSecs))
+            return Long.MAX_VALUE;
+        else if (duration < -m)
+            return Long.MIN_VALUE;
+        else
+            return duration * secRatio;
     }
 
     /**
@@ -280,12 +325,12 @@
      * {@link #convert(long, TimeUnit) MINUTES.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or {@code Long.MIN_VALUE} if conversion would negatively
-     * overflow, or {@code Long.MAX_VALUE} 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.
      * @since 1.6
      */
     public long toMinutes(long duration) {
-        throw new AbstractMethodError();
+        return cvt(duration, MINUTE_SCALE, scale);
     }
 
     /**
@@ -293,12 +338,12 @@
      * {@link #convert(long, TimeUnit) HOURS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or {@code Long.MIN_VALUE} if conversion would negatively
-     * overflow, or {@code Long.MAX_VALUE} 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.
      * @since 1.6
      */
     public long toHours(long duration) {
-        throw new AbstractMethodError();
+        return cvt(duration, HOUR_SCALE, scale);
     }
 
     /**
@@ -309,7 +354,7 @@
      * @since 1.6
      */
     public long toDays(long duration) {
-        throw new AbstractMethodError();
+        return cvt(duration, DAY_SCALE, scale);
     }
 
     /**
@@ -319,7 +364,15 @@
      * @param m the number of milliseconds
      * @return the number of nanoseconds
      */
-    abstract int excessNanos(long d, long m);
+    private int excessNanos(long d, long m) {
+        long s;
+        if ((s = scale) == NANO_SCALE)
+            return (int)(d - (m * MILLI_SCALE));
+        else if (s == MICRO_SCALE)
+            return (int)((d * 1000L) - (m * MILLI_SCALE));
+        else
+            return 0;
+    }
 
     /**
      * Performs a timed {@link Object#wait(long, int) Object.wait}
@@ -327,16 +380,18 @@
      * This is a convenience method that converts timeout arguments
      * into the form required by the {@code Object.wait} method.
      *
-     * <p>For example, you could implement a blocking {@code poll}
-     * method (see {@link BlockingQueue#poll BlockingQueue.poll})
+     * <p>For example, you could implement a blocking {@code poll} method
+     * (see {@link BlockingQueue#poll(long, TimeUnit) BlockingQueue.poll})
      * using:
      *
      * <pre> {@code
-     * public synchronized Object poll(long timeout, TimeUnit unit)
+     * public E poll(long timeout, TimeUnit unit)
      *     throws InterruptedException {
-     *   while (empty) {
-     *     unit.timedWait(this, timeout);
-     *     ...
+     *   synchronized (lock) {
+     *     while (isEmpty()) {
+     *       unit.timedWait(lock, timeout);
+     *       ...
+     *     }
      *   }
      * }}</pre>
      *
@@ -392,14 +447,12 @@
         }
     }
 
-    // BEGIN Android-removed: OpenJDK 9 ChronoUnit related code.
-    /*
     /**
      * Converts this {@code TimeUnit} to the equivalent {@code ChronoUnit}.
      *
      * @return the converted equivalent ChronoUnit
      * @since 9
-     *
+     */
     public ChronoUnit toChronoUnit() {
         switch (this) {
         case NANOSECONDS:  return ChronoUnit.NANOS;
@@ -422,7 +475,7 @@
      *         equivalent TimeUnit
      * @throws NullPointerException if {@code chronoUnit} is null
      * @since 9
-     *
+     */
     public static TimeUnit of(ChronoUnit chronoUnit) {
         switch (Objects.requireNonNull(chronoUnit, "chronoUnit")) {
         case NANOS:   return TimeUnit.NANOSECONDS;
@@ -437,7 +490,5 @@
                 "No TimeUnit equivalent for " + chronoUnit);
         }
     }
-    */
-    // END Android-removed: OpenJDK 9 ChronoUnit related code.
 
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/TransferQueue.java b/ojluni/src/main/java/java/util/concurrent/TransferQueue.java
index 53da597..72a4108 100644
--- a/ojluni/src/main/java/java/util/concurrent/TransferQueue.java
+++ b/ojluni/src/main/java/java/util/concurrent/TransferQueue.java
@@ -35,10 +35,6 @@
 
 package java.util.concurrent;
 
-// BEGIN android-note
-// removed link to collections framework docs
-// END android-note
-
 /**
  * A {@link BlockingQueue} in which producers may wait for consumers
  * to receive elements.  A {@code TransferQueue} may be useful for
@@ -61,6 +57,10 @@
  * with zero capacity, such as {@link SynchronousQueue}, {@code put}
  * and {@code transfer} are effectively synonymous.
  *
+ * <p>This interface is a member of the
+ * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
+ * Java Collections Framework</a>.
+ *
  * @since 1.7
  * @author Doug Lea
  * @param <E> the type of elements held in this queue
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
index b2a2390..9e2acf5 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
@@ -35,29 +35,28 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * A {@code boolean} value that may be updated atomically. See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicBoolean} is used in applications such as atomically
- * updated flags, and cannot be used as a replacement for a
- * {@link java.lang.Boolean}.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicBoolean} is used in
+ * applications such as atomically updated flags, and cannot be used
+ * as a replacement for a {@link java.lang.Boolean}.
  *
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicBoolean implements java.io.Serializable {
     private static final long serialVersionUID = 4654671469794556979L;
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicBoolean.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicBoolean.class, "value", int.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 
@@ -79,7 +78,8 @@
     }
 
     /**
-     * Returns the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -88,40 +88,63 @@
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(boolean expect, boolean update) {
-        return U.compareAndSwapInt(this, VALUE,
-                                   (expect ? 1 : 0),
-                                   (update ? 1 : 0));
+    public final boolean compareAndSet(boolean expectedValue, boolean newValue) {
+        return VALUE.compareAndSet(this,
+                                   (expectedValue ? 1 : 0),
+                                   (newValue ? 1 : 0));
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
      *
-     * <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}.
+     * @deprecated This method has plain memory effects but the method
+     * name implies volatile memory effects (see methods such as
+     * {@link #compareAndExchange} and {@link #compareAndSet}).  To avoid
+     * confusion over plain or volatile memory effects it is recommended that
+     * the method {@link #weakCompareAndSetPlain} be used instead.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
+     * @see #weakCompareAndSetPlain
      */
-    public boolean weakCompareAndSet(boolean expect, boolean update) {
-        return U.compareAndSwapInt(this, VALUE,
-                                   (expect ? 1 : 0),
-                                   (update ? 1 : 0));
+    @Deprecated(since="9")
+    public boolean weakCompareAndSet(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetPlain(this,
+                                            (expectedValue ? 1 : 0),
+                                            (newValue ? 1 : 0));
     }
 
     /**
-     * Unconditionally sets to the given value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public boolean weakCompareAndSetPlain(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetPlain(this,
+                                            (expectedValue ? 1 : 0),
+                                            (newValue ? 1 : 0));
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -130,27 +153,25 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(boolean newValue) {
-        U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
+        VALUE.setRelease(this, (newValue ? 1 : 0));
     }
 
     /**
-     * Atomically sets to the given value and returns the previous value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     public final boolean getAndSet(boolean newValue) {
-        boolean prev;
-        do {
-            prev = get();
-        } while (!compareAndSet(prev, newValue));
-        return prev;
+        return (int)VALUE.getAndSet(this, (newValue ? 1 : 0)) != 0;
     }
 
     /**
@@ -161,4 +182,178 @@
         return Boolean.toString(get());
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getPlain() {
+        return (int)VALUE.get(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(boolean newValue) {
+        VALUE.set(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getOpaque() {
+        return (int)VALUE.getOpaque(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(boolean newValue) {
+        VALUE.setOpaque(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getAcquire() {
+        return (int)VALUE.getAcquire(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(boolean newValue) {
+        VALUE.setRelease(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchange(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchange(this,
+                                             (expectedValue ? 1 : 0),
+                                             (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchangeAcquire(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchangeAcquire(this,
+                                                    (expectedValue ? 1 : 0),
+                                                    (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchangeRelease(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchangeRelease(this,
+                                                    (expectedValue ? 1 : 0),
+                                                    (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSet(this,
+                                       (expectedValue ? 1 : 0),
+                                       (newValue ? 1 : 0));
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetAcquire(this,
+                                              (expectedValue ? 1 : 0),
+                                              (newValue ? 1 : 0));
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetRelease(this,
+                                              (expectedValue ? 1 : 0),
+                                              (newValue ? 1 : 0));
+    }
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
index 19b3418..090b419 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
@@ -35,18 +35,19 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
 
 /**
  * An {@code int} value that may be updated atomically.  See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicInteger} is used in applications such as atomically
- * incremented counters, and cannot be used as a replacement for an
- * {@link java.lang.Integer}. However, this class does extend
- * {@code Number} to allow uniform access by tools and utilities that
- * deal with numerically-based classes.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicInteger} is used in
+ * applications such as atomically incremented counters, and cannot be
+ * used as a replacement for an {@link java.lang.Integer}. However,
+ * this class does extend {@code Number} to allow uniform access by
+ * tools and utilities that deal with numerically-based classes.
  *
  * @since 1.5
  * @author Doug Lea
@@ -54,17 +55,23 @@
 public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    /*
+     * This class intended to be implemented using VarHandles, but there
+     * are unresolved cyclic startup dependencies.
+     */
+    // BEGIN Android-changed: Using VarHandle instead of Unsafe
+    // private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    // private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value");
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicInteger.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicInteger.class, "value", int.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
+    // END Android-changed: Using VarHandle instead of Unsafe
 
     private volatile int value;
 
@@ -84,7 +91,8 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -93,7 +101,8 @@
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -102,112 +111,171 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int newValue) {
-        U.putOrderedInt(this, VALUE, newValue);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putIntRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     public final int getAndSet(int newValue) {
-        return U.getAndSetInt(this, VALUE, newValue);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndSetInt(this, VALUE, newValue);
+        return (int)VALUE.getAndSet(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int expect, int update) {
-        return U.compareAndSwapInt(this, VALUE, expect, update);
+    public final boolean compareAndSet(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndSetInt(this, VALUE, expectedValue, newValue);
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
      *
-     * <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}.
+     * @deprecated This method has plain memory effects but the method
+     * name implies volatile memory effects (see methods such as
+     * {@link #compareAndExchange} and {@link #compareAndSet}).  To avoid
+     * confusion over plain or volatile memory effects it is recommended that
+     * the method {@link #weakCompareAndSetPlain} be used instead.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
+     * @see #weakCompareAndSetPlain
      */
-    public final boolean weakCompareAndSet(int expect, int update) {
-        return U.compareAndSwapInt(this, VALUE, expect, update);
+    @Deprecated(since="9")
+    public final boolean weakCompareAndSet(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetIntPlain(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetPlain(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetIntPlain(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(1)}.
      *
      * @return the previous value
      */
     public final int getAndIncrement() {
-        return U.getAndAddInt(this, VALUE, 1);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddInt(this, VALUE, 1);
+        return (int)VALUE.getAndAdd(this, 1);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(-1)}.
      *
      * @return the previous value
      */
     public final int getAndDecrement() {
-        return U.getAndAddInt(this, VALUE, -1);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddInt(this, VALUE, -1);
+        return (int)VALUE.getAndAdd(this, -1);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the previous value
      */
     public final int getAndAdd(int delta) {
-        return U.getAndAddInt(this, VALUE, delta);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddInt(this, VALUE, delta);
+        return (int)VALUE.getAndAdd(this, delta);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(1)}.
      *
      * @return the updated value
      */
     public final int incrementAndGet() {
-        return U.getAndAddInt(this, VALUE, 1) + 1;
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddInt(this, VALUE, 1) + 1;
+        return (int)VALUE.getAndAdd(this, 1) + 1;
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(-1)}.
      *
      * @return the updated value
      */
     public final int decrementAndGet() {
-        return U.getAndAddInt(this, VALUE, -1) - 1;
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddInt(this, VALUE, -1) - 1;
+        return (int)VALUE.getAndAdd(this, -1) - 1;
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the updated value
      */
     public final int addAndGet(int delta) {
-        return U.getAndAddInt(this, VALUE, delta) + delta;
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddInt(this, VALUE, delta) + delta;
+        return (int)VALUE.getAndAdd(this, delta) + delta;
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function, returning the previous value. The
      * function should be side-effect-free, since it may be re-applied
      * when attempted updates fail due to contention among threads.
@@ -217,16 +285,19 @@
      * @since 1.8
      */
     public final int getAndUpdate(IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function, returning the updated value. The
      * function should be side-effect-free, since it may be re-applied
      * when attempted updates fail due to contention among threads.
@@ -236,22 +307,25 @@
      * @since 1.8
      */
     public final int updateAndGet(IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function to the current and given values,
      * returning the previous value. The function should be
      * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * updates fail due to contention among threads.  The function is
+     * applied with the current value as its first argument, and the
+     * given update as the second argument.
      *
      * @param x the update value
      * @param accumulatorFunction a side-effect-free function of two arguments
@@ -260,22 +334,25 @@
      */
     public final int getAndAccumulate(int x,
                                       IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function to the current and given values,
      * returning the updated value. The function should be
      * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * updates fail due to contention among threads.  The function is
+     * applied with the current value as its first argument, and the
+     * given update as the second argument.
      *
      * @param x the update value
      * @param accumulatorFunction a side-effect-free function of two arguments
@@ -284,12 +361,14 @@
      */
     public final int accumulateAndGet(int x,
                                       IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -301,7 +380,10 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as an {@code int}.
+     * Returns the current value of this {@code AtomicInteger} as an
+     * {@code int},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
+     *
      * Equivalent to {@link #get()}.
      */
     public int intValue() {
@@ -309,8 +391,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code long}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code long} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public long longValue() {
@@ -318,8 +401,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code float}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code float} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
@@ -327,12 +411,199 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code double}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code double} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getPlain() {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getInt(this, VALUE);
+        return (int)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putInt(this, VALUE, newValue);
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getOpaque() {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getIntOpaque(this, VALUE);
+        return (int)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putIntOpaque(this, VALUE, newValue);
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getAcquire() {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getIntAcquire(this, VALUE);
+        return (int)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putIntRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchange(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndExchangeInt(this, VALUE, expectedValue, newValue);
+        return (int)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeAcquire(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndExchangeIntAcquire(this, VALUE, expectedValue, newValue);
+        return (int)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeRelease(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndExchangeIntRelease(this, VALUE, expectedValue, newValue);
+        return (int)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        //return U.weakCompareAndSetInt(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetIntAcquire(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int expectedValue, int newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetIntRelease(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index 2ea9a27..f59327d 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -35,44 +35,24 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
 
 /**
  * An {@code int} array in which elements may be updated atomically.
- * See the {@link java.util.concurrent.atomic} package
- * specification for description of the properties of atomic
- * variables.
+ * See the {@link VarHandle} specification for descriptions of the
+ * properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicIntegerArray implements java.io.Serializable {
     private static final long serialVersionUID = 2862133569453604235L;
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(int[].class);
     private final int[] array;
 
-    static {
-        ABASE = U.arrayBaseOffset(int[].class);
-        int scale = U.arrayIndexScale(int[].class);
-        if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicIntegerArray of the given length, with all
      * elements initially zero.
@@ -105,154 +85,187 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
     public final int get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    private int getRaw(long offset) {
-        return U.getIntVolatile(array, offset);
+        return (int)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, int newValue) {
-        U.putIntVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, int newValue) {
-        U.putOrderedInt(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * value and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
      * @return the previous value
      */
     public final int getAndSet(int i, int newValue) {
-        return U.getAndSetInt(array, checkedByteOffset(i), newValue);
+        return (int)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int i, int expect, int update) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, int expect, int update) {
-        return U.compareAndSwapInt(array, offset, expect, update);
+    public final boolean compareAndSet(int i, int expectedValue, int newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
      *
-     * <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}.
+     * @deprecated This method has plain memory effects but the method
+     * name implies volatile memory effects (see methods such as
+     * {@link #compareAndExchange} and {@link #compareAndSet}).  To avoid
+     * confusion over plain or volatile memory effects it is recommended that
+     * the method {@link #weakCompareAndSetPlain} be used instead.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
+     * @see #weakCompareAndSetPlain
      */
-    public final boolean weakCompareAndSet(int i, int expect, int update) {
-        return compareAndSet(i, expect, update);
+    @Deprecated(since="9")
+    public final boolean weakCompareAndSet(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetPlain(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, 1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final int getAndIncrement(int i) {
-        return getAndAdd(i, 1);
+        return (int)AA.getAndAdd(array, i, 1);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, -1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final int getAndDecrement(int i) {
-        return getAndAdd(i, -1);
+        return (int)AA.getAndAdd(array, i, -1);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the previous value
      */
     public final int getAndAdd(int i, int delta) {
-        return U.getAndAddInt(array, checkedByteOffset(i), delta);
+        return (int)AA.getAndAdd(array, i, delta);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, 1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final int incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return (int)AA.getAndAdd(array, i, 1) + 1;
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, -1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final int decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return (int)AA.getAndAdd(array, i, -1) - 1;
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the updated value
      */
     public final int addAndGet(int i, int delta) {
-        return getAndAdd(i, delta) + delta;
+        return (int)AA.getAndAdd(array, i, delta) + delta;
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function, returning the
+     * previous value. The function should be side-effect-free, since
+     * it may be re-applied when attempted updates fail due to
+     * contention among threads.
      *
      * @param i the index
      * @param updateFunction a side-effect-free function
@@ -260,20 +273,23 @@
      * @since 1.8
      */
     public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function, returning the
+     * updated value. The function should be side-effect-free, since it
+     * may be re-applied when attempted updates fail due to contention
+     * among threads.
      *
      * @param i the index
      * @param updateFunction a side-effect-free function
@@ -281,23 +297,26 @@
      * @since 1.8
      */
     public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function to the current and
      * given values, returning the previous value. The function should
      * be side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -307,23 +326,26 @@
      */
     public final int getAndAccumulate(int i, int x,
                                       IntBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function to the current and
      * given values, returning the updated value. The function should
      * be side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -333,13 +355,14 @@
      */
     public final int accumulateAndGet(int i, int x,
                                       IntBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -354,11 +377,190 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
         }
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getPlain(int i) {
+        return (int)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, int newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getOpaque(int i) {
+        return (int)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, int newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getAcquire(int i) {
+        return (int)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, int newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchange(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeAcquire(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeRelease(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
+    }
+
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index 589d5da..07d5d60 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -40,10 +40,13 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
+import java.lang.invoke.VarHandle;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -59,6 +62,10 @@
  * guarantee atomicity only with respect to other invocations of
  * {@code compareAndSet} and {@code set} on the same updater.
  *
+ * <p>Object arguments for parameters of type {@code T} that are not
+ * instances of the class passed to {@link #newUpdater} will result in
+ * a {@link ClassCastException} being thrown.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
@@ -104,8 +111,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean compareAndSet(T obj, int expect, int update);
 
@@ -124,8 +129,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean weakCompareAndSet(T obj, int expect, int update);
 
@@ -150,8 +153,8 @@
     public abstract void lazySet(T obj, int newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -273,10 +276,12 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the previous
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given
+     * function, returning the previous value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
+     * updates fail due to contention among threads.
      *
      * @param obj An object whose field to get and set
      * @param updateFunction a side-effect-free function
@@ -293,10 +298,12 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the updated
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given
+     * function, returning the updated value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
+     * updates fail due to contention among threads.
      *
      * @param obj An object whose field to get and set
      * @param updateFunction a side-effect-free function
@@ -313,13 +320,14 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given function
+     * to the current and given values, returning the previous value.
+     * The function should be side-effect-free, since it may be
+     * re-applied when attempted updates fail due to contention among
+     * threads.  The function is applied with the current value as its
+     * first argument, and the given update as the second argument.
      *
      * @param obj An object whose field to get and set
      * @param x the update value
@@ -338,13 +346,14 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given function
+     * to the current and given values, returning the updated value.
+     * The function should be side-effect-free, since it may be
+     * re-applied when attempted updates fail due to contention among
+     * threads.  The function is applied with the current value as its
+     * first argument, and the given update as the second argument.
      *
      * @param obj An object whose field to get and set
      * @param x the update value
@@ -367,7 +376,7 @@
      */
     private static final class AtomicIntegerFieldUpdaterImpl<T>
         extends AtomicIntegerFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
@@ -423,7 +432,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.offset = U.objectFieldOffset(field);
         }
@@ -449,6 +468,15 @@
         // END Android-removed: isAncestor()'s only usage was removed above.
 
         /**
+         * Returns true if the two classes have the same class loader and
+         * package qualifier
+         */
+        private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+            return class1.getClassLoader() == class2.getClassLoader()
+                   && Objects.equals(class1.getPackageName(), class2.getPackageName());
+        }
+
+        /**
          * Checks that target argument is instance of cclass.  On
          * failure, throws cause.
          */
@@ -477,12 +505,12 @@
 
         public final boolean compareAndSet(T obj, int expect, int update) {
             accessCheck(obj);
-            return U.compareAndSwapInt(obj, offset, expect, update);
+            return U.compareAndSetInt(obj, offset, expect, update);
         }
 
         public final boolean weakCompareAndSet(T obj, int expect, int update) {
             accessCheck(obj);
-            return U.compareAndSwapInt(obj, offset, expect, update);
+            return U.compareAndSetInt(obj, offset, expect, update);
         }
 
         public final void set(T obj, int newValue) {
@@ -492,7 +520,7 @@
 
         public final void lazySet(T obj, int newValue) {
             accessCheck(obj);
-            U.putOrderedInt(obj, offset, newValue);
+            U.putIntRelease(obj, offset, newValue);
         }
 
         public final int get(T obj) {
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLong.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
index b919f1e..8d8ba86 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
@@ -35,18 +35,19 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
 
 /**
  * A {@code long} value that may be updated atomically.  See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicLong} is used in applications such as atomically
- * incremented sequence numbers, and cannot be used as a replacement
- * for a {@link java.lang.Long}. However, this class does extend
- * {@code Number} to allow uniform access by tools and utilities that
- * deal with numerically-based classes.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicLong} is used in applications
+ * such as atomically incremented sequence numbers, and cannot be used
+ * as a replacement for a {@link java.lang.Long}. However, this class
+ * does extend {@code Number} to allow uniform access by tools and
+ * utilities that deal with numerically-based classes.
  *
  * @since 1.5
  * @author Doug Lea
@@ -54,12 +55,9 @@
 public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
 
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
     /**
      * Records whether the underlying JVM supports lockless
-     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
+     * compareAndSet for longs. While the intrinsic compareAndSetLong
      * method works in either case, some constructions should be
      * handled at Java level to avoid locking user-visible locks.
      */
@@ -71,14 +69,23 @@
      */
     private static native boolean VMSupportsCS8();
 
+    /*
+     * This class intended to be implemented using VarHandles, but there
+     * are unresolved cyclic startup dependencies.
+     */
+    // BEGIN Android-changed: Using VarHandle instead of Unsafe
+    // private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    // private static final long VALUE = U.objectFieldOffset(AtomicLong.class, "value");
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicLong.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicLong.class, "value", long.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
+    // END Android-changed: Using VarHandle instead of Unsafe
 
     private volatile long value;
 
@@ -98,7 +105,8 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -107,123 +115,184 @@
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
     public final void set(long newValue) {
-        // Use putLongVolatile instead of ordinary volatile store when
-        // using compareAndSwapLong, for sake of some 32bit systems.
-        U.putLongVolatile(this, VALUE, newValue);
+        // See JDK-8180620: Clarify VarHandle mixed-access subtleties
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putLongVolatile(this, VALUE, newValue);
+        VALUE.setVolatile(this, newValue);
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(long newValue) {
-        U.putOrderedLong(this, VALUE, newValue);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putLongRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     public final long getAndSet(long newValue) {
-        return U.getAndSetLong(this, VALUE, newValue);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndSetLong(this, VALUE, newValue);
+        return (long)VALUE.getAndSet(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(long expect, long update) {
-        return U.compareAndSwapLong(this, VALUE, expect, update);
+    public final boolean compareAndSet(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndSetLong(this, VALUE, expectedValue, newValue);
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
      *
-     * <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}.
+     * @deprecated This method has plain memory effects but the method
+     * name implies volatile memory effects (see methods such as
+     * {@link #compareAndExchange} and {@link #compareAndSet}).  To avoid
+     * confusion over plain or volatile memory effects it is recommended that
+     * the method {@link #weakCompareAndSetPlain} be used instead.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
+     * @see #weakCompareAndSetPlain
      */
-    public final boolean weakCompareAndSet(long expect, long update) {
-        return U.compareAndSwapLong(this, VALUE, expect, update);
+    @Deprecated(since="9")
+    public final boolean weakCompareAndSet(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetLongPlain(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetPlain(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetLongPlain(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(1)}.
      *
      * @return the previous value
      */
     public final long getAndIncrement() {
-        return U.getAndAddLong(this, VALUE, 1L);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddLong(this, VALUE, 1L);
+        return (long)VALUE.getAndAdd(this, 1L);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(-1)}.
      *
      * @return the previous value
      */
     public final long getAndDecrement() {
-        return U.getAndAddLong(this, VALUE, -1L);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddLong(this, VALUE, -1L);
+        return (long)VALUE.getAndAdd(this, -1L);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the previous value
      */
     public final long getAndAdd(long delta) {
-        return U.getAndAddLong(this, VALUE, delta);
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddLong(this, VALUE, delta);
+        return (long)VALUE.getAndAdd(this, delta);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(1)}.
      *
      * @return the updated value
      */
     public final long incrementAndGet() {
-        return U.getAndAddLong(this, VALUE, 1L) + 1L;
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddLong(this, VALUE, 1L) + 1L;
+        return (long)VALUE.getAndAdd(this, 1L) + 1L;
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(-1)}.
      *
      * @return the updated value
      */
     public final long decrementAndGet() {
-        return U.getAndAddLong(this, VALUE, -1L) - 1L;
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddLong(this, VALUE, -1L) - 1L;
+        return (long)VALUE.getAndAdd(this, -1L) - 1L;
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the updated value
      */
     public final long addAndGet(long delta) {
-        return U.getAndAddLong(this, VALUE, delta) + delta;
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getAndAddLong(this, VALUE, delta) + delta;
+        return (long)VALUE.getAndAdd(this, delta) + delta;
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function, returning the previous value. The
      * function should be side-effect-free, since it may be re-applied
      * when attempted updates fail due to contention among threads.
@@ -233,16 +302,19 @@
      * @since 1.8
      */
     public final long getAndUpdate(LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function, returning the updated value. The
      * function should be side-effect-free, since it may be re-applied
      * when attempted updates fail due to contention among threads.
@@ -252,22 +324,25 @@
      * @since 1.8
      */
     public final long updateAndGet(LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function to the current and given values,
      * returning the previous value. The function should be
      * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * updates fail due to contention among threads.  The function is
+     * applied with the current value as its first argument, and the
+     * given update as the second argument.
      *
      * @param x the update value
      * @param accumulatorFunction a side-effect-free function of two arguments
@@ -276,22 +351,25 @@
      */
     public final long getAndAccumulate(long x,
                                        LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function to the current and given values,
      * returning the updated value. The function should be
      * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * updates fail due to contention among threads.  The function is
+     * applied with the current value as its first argument, and the
+     * given update as the second argument.
      *
      * @param x the update value
      * @param accumulatorFunction a side-effect-free function of two arguments
@@ -300,12 +378,14 @@
      */
     public final long accumulateAndGet(long x,
                                        LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -317,8 +397,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as an {@code int}
-     * after a narrowing primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as an {@code int}
+     * after a narrowing primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public int intValue() {
@@ -326,7 +407,8 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code long}.
+     * Returns the current value of this {@code AtomicLong} as a {@code long},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * Equivalent to {@link #get()}.
      */
     public long longValue() {
@@ -334,8 +416,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code float}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as a {@code float}
+     * after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
@@ -343,12 +426,199 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code double}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as a {@code double}
+     * after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as if the
+     * variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getPlain() {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getLong(this, VALUE);
+        return (long)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putLong(this, VALUE, newValue);
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getOpaque() {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getLongOpaque(this, VALUE);
+        return (long)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putLongOpaque(this, VALUE, newValue);
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getAcquire() {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.getLongAcquire(this, VALUE);
+        return (long)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // U.putLongRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchange(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndExchangeLong(this, VALUE, expectedValue, newValue);
+        return (long)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeAcquire(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndExchangeLongAcquire(this, VALUE, expectedValue, newValue);
+        return (long)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeRelease(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.compareAndExchangeLongRelease(this, VALUE, expectedValue, newValue);
+        return (long)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetLong(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetLongAcquire(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(long expectedValue, long newValue) {
+        // Android-changed: Using VarHandle instead of Unsafe
+        // return U.weakCompareAndSetLongRelease(this, VALUE, expectedValue, newValue);
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index d1af039..24e42a1 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -35,43 +35,24 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
 
 /**
  * A {@code long} array in which elements may be updated atomically.
- * See the {@link java.util.concurrent.atomic} package specification
- * for description of the properties of atomic variables.
+ * See the {@link VarHandle} specification for descriptions of the
+ * properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicLongArray implements java.io.Serializable {
     private static final long serialVersionUID = -2308431214976778248L;
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(long[].class);
     private final long[] array;
 
-    static {
-        ABASE = U.arrayBaseOffset(long[].class);
-        int scale = U.arrayIndexScale(long[].class);
-        if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicLongArray of the given length, with all
      * elements initially zero.
@@ -104,154 +85,187 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
     public final long get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    private long getRaw(long offset) {
-        return U.getLongVolatile(array, offset);
+        return (long)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, long newValue) {
-        U.putLongVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, long newValue) {
-        U.putOrderedLong(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given value
-     * and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
      * @return the previous value
      */
     public final long getAndSet(int i, long newValue) {
-        return U.getAndSetLong(array, checkedByteOffset(i), newValue);
+        return (long)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int i, long expect, long update) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, long expect, long update) {
-        return U.compareAndSwapLong(array, offset, expect, update);
+    public final boolean compareAndSet(int i, long expectedValue, long newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
      *
-     * <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}.
+     * @deprecated This method has plain memory effects but the method
+     * name implies volatile memory effects (see methods such as
+     * {@link #compareAndExchange} and {@link #compareAndSet}).  To avoid
+     * confusion over plain or volatile memory effects it is recommended that
+     * the method {@link #weakCompareAndSetPlain} be used instead.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
+     * @see #weakCompareAndSetPlain
      */
-    public final boolean weakCompareAndSet(int i, long expect, long update) {
-        return compareAndSet(i, expect, update);
+    @Deprecated(since="9")
+    public final boolean weakCompareAndSet(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetPlain(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, 1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final long getAndIncrement(int i) {
-        return getAndAdd(i, 1);
+        return (long)AA.getAndAdd(array, i, 1L);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, -1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final long getAndDecrement(int i) {
-        return getAndAdd(i, -1);
+        return (long)AA.getAndAdd(array, i, -1L);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the previous value
      */
     public final long getAndAdd(int i, long delta) {
-        return U.getAndAddLong(array, checkedByteOffset(i), delta);
+        return (long)AA.getAndAdd(array, i, delta);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, 1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final long incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return (long)AA.getAndAdd(array, i, 1L) + 1L;
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, -1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final long decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return (long)AA.getAndAdd(array, i, -1L) - 1L;
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the updated value
      */
     public long addAndGet(int i, long delta) {
-        return getAndAdd(i, delta) + delta;
+        return (long)AA.getAndAdd(array, i, delta) + delta;
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function, returning the
+     * previous value. The function should be side-effect-free, since
+     * it may be re-applied when attempted updates fail due to
+     * contention among threads.
      *
      * @param i the index
      * @param updateFunction a side-effect-free function
@@ -259,20 +273,23 @@
      * @since 1.8
      */
     public final long getAndUpdate(int i, LongUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function, returning the
+     * updated value. The function should be side-effect-free, since it
+     * may be re-applied when attempted updates fail due to contention
+     * among threads.
      *
      * @param i the index
      * @param updateFunction a side-effect-free function
@@ -280,23 +297,26 @@
      * @since 1.8
      */
     public final long updateAndGet(int i, LongUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function to the current and
      * given values, returning the previous value. The function should
      * be side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -306,23 +326,26 @@
      */
     public final long getAndAccumulate(int i, long x,
                                       LongBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function to the current and
      * given values, returning the updated value. The function should
      * be side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -332,13 +355,14 @@
      */
     public final long accumulateAndGet(int i, long x,
                                       LongBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -353,11 +377,189 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
         }
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getPlain(int i) {
+        return (long)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, long newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getOpaque(int i) {
+        return (long)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, long newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getAcquire(int i) {
+        return (long)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, long newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchange(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeAcquire(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeRelease(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
+    }
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index 447a642..34a200b 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -40,10 +40,13 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
+import java.lang.invoke.VarHandle;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -59,6 +62,10 @@
  * guarantee atomicity only with respect to other invocations of
  * {@code compareAndSet} and {@code set} on the same updater.
  *
+ * <p>Object arguments for parameters of type {@code T} that are not
+ * instances of the class passed to {@link #newUpdater} will result in
+ * a {@link ClassCastException} being thrown.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
@@ -107,8 +114,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean compareAndSet(T obj, long expect, long update);
 
@@ -127,8 +132,6 @@
      * @param expect the expected value
      * @param update the new value
      * @return {@code true} if successful
-     * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor
      */
     public abstract boolean weakCompareAndSet(T obj, long expect, long update);
 
@@ -153,8 +156,8 @@
     public abstract void lazySet(T obj, long newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -276,10 +279,12 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the previous
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given
+     * function, returning the previous value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
+     * updates fail due to contention among threads.
      *
      * @param obj An object whose field to get and set
      * @param updateFunction a side-effect-free function
@@ -296,10 +301,12 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the updated
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given
+     * function, returning the updated value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
+     * updates fail due to contention among threads.
      *
      * @param obj An object whose field to get and set
      * @param updateFunction a side-effect-free function
@@ -316,13 +323,14 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given function
+     * to the current and given values, returning the previous value.
+     * The function should be side-effect-free, since it may be
+     * re-applied when attempted updates fail due to contention among
+     * threads.  The function is applied with the current value as its
+     * first argument, and the given update as the second argument.
      *
      * @param obj An object whose field to get and set
      * @param x the update value
@@ -341,13 +349,14 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given function
+     * to the current and given values, returning the updated value.
+     * The function should be side-effect-free, since it may be
+     * re-applied when attempted updates fail due to contention among
+     * threads.  The function is applied with the current value as its
+     * first argument, and the given update as the second argument.
      *
      * @param obj An object whose field to get and set
      * @param x the update value
@@ -366,7 +375,7 @@
     }
 
     private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
@@ -418,7 +427,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.offset = U.objectFieldOffset(field);
         }
@@ -452,12 +471,12 @@
 
         public final boolean compareAndSet(T obj, long expect, long update) {
             accessCheck(obj);
-            return U.compareAndSwapLong(obj, offset, expect, update);
+            return U.compareAndSetLong(obj, offset, expect, update);
         }
 
         public final boolean weakCompareAndSet(T obj, long expect, long update) {
             accessCheck(obj);
-            return U.compareAndSwapLong(obj, offset, expect, update);
+            return U.compareAndSetLong(obj, offset, expect, update);
         }
 
         public final void set(T obj, long newValue) {
@@ -467,7 +486,7 @@
 
         public final void lazySet(T obj, long newValue) {
             accessCheck(obj);
-            U.putOrderedLong(obj, offset, newValue);
+            U.putLongRelease(obj, offset, newValue);
         }
 
         public final long get(T obj) {
@@ -507,7 +526,7 @@
     }
 
     private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
@@ -519,8 +538,8 @@
 
         LockedUpdater(final Class<T> tclass, final String fieldName,
                       final Class<?> caller) {
-            Field field = null;
-            int modifiers = 0;
+            final Field field;
+            final int modifiers;
             try {
                 // Android-changed: Skip privilege escalation which is a noop on Android.
                 /*
@@ -559,7 +578,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.offset = U.objectFieldOffset(field);
         }
@@ -643,4 +672,13 @@
         return false;
     }
     */
+
+    /**
+     * Returns true if the two classes have the same class loader and
+     * package qualifier
+     */
+    static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+        return class1.getClassLoader() == class2.getClassLoader()
+            && Objects.equals(class1.getPackageName(), class2.getPackageName());
+    }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
index b49118b..51ea84c 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -35,6 +35,9 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * An {@code AtomicMarkableReference} maintains an object reference
  * along with a mark bit, that can be updated atomically.
@@ -188,20 +191,19 @@
              casPair(current, Pair.of(expectedReference, newMark)));
     }
 
-    // Unsafe mechanics
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
+    // VarHandle mechanics
+    private static final VarHandle PAIR;
     static {
         try {
-            PAIR = U.objectFieldOffset
-                (AtomicMarkableReference.class.getDeclaredField("pair"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PAIR = l.findVarHandle(AtomicMarkableReference.class, "pair",
+                                   Pair.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return PAIR.compareAndSet(this, cmp, val);
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReference.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
index dbc6685..70832ff 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
@@ -35,29 +35,28 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
 
 /**
- * An object reference that may be updated atomically. See the {@link
- * java.util.concurrent.atomic} package specification for description
- * of the properties of atomic variables.
+ * An object reference that may be updated atomically.  See the {@link
+ * VarHandle} specification for descriptions of the properties of
+ * atomic accesses.
  * @since 1.5
  * @author Doug Lea
  * @param <V> The type of object referred to by this reference
  */
 public class AtomicReference<V> implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicReference.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 
@@ -79,7 +78,8 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -88,7 +88,8 @@
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -97,56 +98,80 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(V newValue) {
-        U.putOrderedObject(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
-     * @param expect the expected value
-     * @param update the new value
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(V expect, V update) {
-        return U.compareAndSwapObject(this, VALUE, expect, update);
+    public final boolean compareAndSet(V expectedValue, V newValue) {
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
      *
-     * <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}.
+     * @deprecated This method has plain memory effects but the method
+     * name implies volatile memory effects (see methods such as
+     * {@link #compareAndExchange} and {@link #compareAndSet}).  To avoid
+     * confusion over plain or volatile memory effects it is recommended that
+     * the method {@link #weakCompareAndSetPlain} be used instead.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
+     * @see #weakCompareAndSetPlain
      */
-    public final boolean weakCompareAndSet(V expect, V update) {
-        return U.compareAndSwapObject(this, VALUE, expect, update);
+    @Deprecated(since="9")
+    public final boolean weakCompareAndSet(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetPlain(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     @SuppressWarnings("unchecked")
     public final V getAndSet(V newValue) {
-        return (V)U.getAndSetObject(this, VALUE, newValue);
+        return (V)VALUE.getAndSet(this, newValue);
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function, returning the previous value. The
      * function should be side-effect-free, since it may be re-applied
      * when attempted updates fail due to contention among threads.
@@ -156,16 +181,19 @@
      * @since 1.8
      */
     public final V getAndUpdate(UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function, returning the updated value. The
      * function should be side-effect-free, since it may be re-applied
      * when attempted updates fail due to contention among threads.
@@ -175,22 +203,25 @@
      * @since 1.8
      */
     public final V updateAndGet(UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function to the current and given values,
      * returning the previous value. The function should be
      * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * updates fail due to contention among threads.  The function is
+     * applied with the current value as its first argument, and the
+     * given update as the second argument.
      *
      * @param x the update value
      * @param accumulatorFunction a side-effect-free function of two arguments
@@ -199,22 +230,25 @@
      */
     public final V getAndAccumulate(V x,
                                     BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
-     * Atomically updates the current value with the results of
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the current value with the results of
      * applying the given function to the current and given values,
      * returning the updated value. The function should be
      * side-effect-free, since it may be re-applied when attempted
-     * updates fail due to contention among threads.  The function
-     * is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * updates fail due to contention among threads.  The function is
+     * applied with the current value as its first argument, and the
+     * given update as the second argument.
      *
      * @param x the update value
      * @param accumulatorFunction a side-effect-free function of two arguments
@@ -223,12 +257,14 @@
      */
     public final V accumulateAndGet(V x,
                                     BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -239,4 +275,166 @@
         return String.valueOf(get());
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getPlain() {
+        return (V)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(V newValue) {
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getOpaque() {
+        return (V)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(V newValue) {
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getAcquire() {
+        return (V)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(V newValue) {
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchange(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchangeAcquire(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchangeRelease(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index cce148e..b3193a2 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -35,54 +35,28 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.lang.reflect.Array;
+import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
 
 /**
  * An array of object references in which elements may be updated
- * atomically.  See the {@link java.util.concurrent.atomic} package
- * specification for description of the properties of atomic
- * variables.
+ * atomically.  See the {@link VarHandle} specification for
+ * descriptions of the properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  * @param <E> The base class of elements held in this array
  */
 public class AtomicReferenceArray<E> implements java.io.Serializable {
     private static final long serialVersionUID = -6209656149925076980L;
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long ARRAY;
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(Object[].class);
     private final Object[] array; // must have exact type Object[]
 
-    static {
-        try {
-            ARRAY = U.objectFieldOffset
-                (AtomicReferenceArray.class.getDeclaredField("array"));
-            ABASE = U.arrayBaseOffset(Object[].class);
-            int scale = U.arrayIndexScale(Object[].class);
-            if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
-            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicReferenceArray of the given length, with all
      * elements initially null.
@@ -115,44 +89,44 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
-    public final E get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
     @SuppressWarnings("unchecked")
-    private E getRaw(long offset) {
-        return (E) U.getObjectVolatile(array, offset);
+    public final E get(int i) {
+        return (E)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, E newValue) {
-        U.putObjectVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, E newValue) {
-        U.putOrderedObject(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * value and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
@@ -160,49 +134,68 @@
      */
     @SuppressWarnings("unchecked")
     public final E getAndSet(int i, E newValue) {
-        return (E)U.getAndSetObject(array, checkedByteOffset(i), newValue);
+        return (E)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int i, E expect, E update) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, E expect, E update) {
-        return U.compareAndSwapObject(array, offset, expect, update);
+    public final boolean compareAndSet(int i, E expectedValue, E newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
      *
-     * <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}.
+     * @deprecated This method has plain memory effects but the method
+     * name implies volatile memory effects (see methods such as
+     * {@link #compareAndExchange} and {@link #compareAndSet}).  To avoid
+     * confusion over plain or volatile memory effects it is recommended that
+     * the method {@link #weakCompareAndSetPlain} be used instead.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
+     * @see #weakCompareAndSetPlain
      */
-    public final boolean weakCompareAndSet(int i, E expect, E update) {
-        return compareAndSet(i, expect, update);
+    @Deprecated(since="9")
+    public final boolean weakCompareAndSet(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetPlain(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function, returning the
+     * previous value. The function should be side-effect-free, since
+     * it may be re-applied when attempted updates fail due to
+     * contention among threads.
      *
      * @param i the index
      * @param updateFunction a side-effect-free function
@@ -210,20 +203,23 @@
      * @since 1.8
      */
     public final E getAndUpdate(int i, UnaryOperator<E> updateFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the results
-     * of applying the given function, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function, returning the
+     * updated value. The function should be side-effect-free, since it
+     * may be re-applied when attempted updates fail due to contention
+     * among threads.
      *
      * @param i the index
      * @param updateFunction a side-effect-free function
@@ -231,23 +227,26 @@
      * @since 1.8
      */
     public final E updateAndGet(int i, UnaryOperator<E> updateFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function to the current and
      * given values, returning the previous value. The function should
      * be side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -257,23 +256,26 @@
      */
     public final E getAndAccumulate(int i, E x,
                                     BinaryOperator<E> accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
-     * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the element at index {@code i} with
+     * the results of applying the given function to the current and
      * given values, returning the updated value. The function should
      * be side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -283,13 +285,14 @@
      */
     public final E accumulateAndGet(int i, E x,
                                     BinaryOperator<E> accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -304,7 +307,7 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
@@ -326,7 +329,199 @@
             throw new java.io.InvalidObjectException("Not array type");
         if (a.getClass() != Object[].class)
             a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class);
-        U.putObjectVolatile(this, ARRAY, a);
+        Field arrayField = java.security.AccessController.doPrivileged(
+            (java.security.PrivilegedAction<Field>) () -> {
+                try {
+                    Field f = AtomicReferenceArray.class
+                        .getDeclaredField("array");
+                    f.setAccessible(true);
+                    return f;
+                } catch (ReflectiveOperationException e) {
+                    throw new Error(e);
+                }});
+        try {
+            arrayField.set(this, a);
+        } catch (IllegalAccessException e) {
+            throw new Error(e);
+        }
+    }
+
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getPlain(int i) {
+        return (E)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, E newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getOpaque(int i) {
+        return (E)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, E newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getAcquire(int i) {
+        return (E)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, E newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchange(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchangeAcquire(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchangeRelease(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
     }
 
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index 17423ad..513a243 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -40,10 +40,13 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
-import sun.reflect.CallerSensitive;
-import sun.reflect.Reflection;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
+import java.lang.invoke.VarHandle;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -76,6 +79,10 @@
  * guarantee atomicity only with respect to other invocations of
  * {@code compareAndSet} and {@code set} on the same updater.
  *
+ * <p>Object arguments for parameters of type {@code T} that are not
+ * instances of the class passed to {@link #newUpdater} will result in
+ * a {@link ClassCastException} being thrown.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
@@ -168,8 +175,8 @@
     public abstract void lazySet(T obj, V newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -193,10 +200,12 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the previous
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given
+     * function, returning the previous value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
+     * updates fail due to contention among threads.
      *
      * @param obj An object whose field to get and set
      * @param updateFunction a side-effect-free function
@@ -213,10 +222,12 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this updater
-     * with the results of applying the given function, returning the updated
-     * value. The function should be side-effect-free, since it may be
-     * re-applied when attempted updates fail due to contention among threads.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given
+     * function, returning the updated value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
+     * updates fail due to contention among threads.
      *
      * @param obj An object whose field to get and set
      * @param updateFunction a side-effect-free function
@@ -233,13 +244,14 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the previous value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given function
+     * to the current and given values, returning the previous value.
+     * The function should be side-effect-free, since it may be
+     * re-applied when attempted updates fail due to contention among
+     * threads.  The function is applied with the current value as its
+     * first argument, and the given update as the second argument.
      *
      * @param obj An object whose field to get and set
      * @param x the update value
@@ -258,13 +270,14 @@
     }
 
     /**
-     * Atomically updates the field of the given object managed by this
-     * updater with the results of applying the given function to the
-     * current and given values, returning the updated value. The
-     * function should be side-effect-free, since it may be re-applied
-     * when attempted updates fail due to contention among threads.  The
-     * function is applied with the current value as its first argument,
-     * and the given update as the second argument.
+     * Atomically updates (with memory effects as specified by {@link
+     * VarHandle#compareAndSet}) the field of the given object managed
+     * by this updater with the results of applying the given function
+     * to the current and given values, returning the updated value.
+     * The function should be side-effect-free, since it may be
+     * re-applied when attempted updates fail due to contention among
+     * threads.  The function is applied with the current value as its
+     * first argument, and the given update as the second argument.
      *
      * @param obj An object whose field to get and set
      * @param x the update value
@@ -284,7 +297,7 @@
 
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
         extends AtomicReferenceFieldUpdater<T,V> {
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
@@ -356,7 +369,17 @@
             if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
-            this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
+            // Access to protected field members is restricted to receivers only
+            // of the accessing class, or one of its subclasses, and the
+            // accessing class must in turn be a subclass (or package sibling)
+            // of the protected member's defining class.
+            // If the updater refers to a protected field of a declaring class
+            // outside the current package, the receiver argument will be
+            // narrowed to the type of the accessing class.
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           tclass.isAssignableFrom(caller) &&
+                           !isSamePackage(tclass, caller))
+                          ? caller : tclass;
             this.tclass = tclass;
             this.vclass = vclass;
             this.offset = U.objectFieldOffset(field);
@@ -382,6 +405,15 @@
         */
 
         /**
+         * Returns true if the two classes have the same class loader and
+         * package qualifier
+         */
+        private static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+            return class1.getClassLoader() == class2.getClassLoader()
+                   && Objects.equals(class1.getPackageName(), class2.getPackageName());
+        }
+
+        /**
          * Checks that target argument is instance of cclass.  On
          * failure, throws cause.
          */
@@ -420,14 +452,14 @@
         public final boolean compareAndSet(T obj, V expect, V update) {
             accessCheck(obj);
             valueCheck(update);
-            return U.compareAndSwapObject(obj, offset, expect, update);
+            return U.compareAndSetObject(obj, offset, expect, update);
         }
 
         public final boolean weakCompareAndSet(T obj, V expect, V update) {
             // same implementation as strong form for now
             accessCheck(obj);
             valueCheck(update);
-            return U.compareAndSwapObject(obj, offset, expect, update);
+            return U.compareAndSetObject(obj, offset, expect, update);
         }
 
         public final void set(T obj, V newValue) {
@@ -439,7 +471,7 @@
         public final void lazySet(T obj, V newValue) {
             accessCheck(obj);
             valueCheck(newValue);
-            U.putOrderedObject(obj, offset, newValue);
+            U.putObjectRelease(obj, offset, newValue);
         }
 
         @SuppressWarnings("unchecked")
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
index 40ceeb2..47b7c7b 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -35,6 +35,9 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * An {@code AtomicStampedReference} maintains an object reference
  * along with an integer "stamp", that can be updated atomically.
@@ -188,20 +191,19 @@
              casPair(current, Pair.of(expectedReference, newStamp)));
     }
 
-    // Unsafe mechanics
-
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
+    // VarHandle mechanics
+    private static final VarHandle PAIR;
     static {
         try {
-            PAIR = U.objectFieldOffset
-                (AtomicStampedReference.class.getDeclaredField("pair"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PAIR = l.findVarHandle(AtomicStampedReference.class, "pair",
+                                   Pair.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return PAIR.compareAndSet(this, cmp, val);
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java b/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java
index f3e3531..1800730 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAccumulator.java
@@ -35,6 +35,9 @@
 
 package java.util.concurrent.atomic;
 
+import static java.lang.Double.doubleToRawLongBits;
+import static java.lang.Double.longBitsToDouble;
+
 import java.io.Serializable;
 import java.util.function.DoubleBinaryOperator;
 
@@ -53,11 +56,13 @@
  *
  * <p>The supplied accumulator function should be side-effect-free,
  * since it may be re-applied when attempted updates fail due to
- * contention among threads. The function is applied with the current
- * value as its first argument, and the given update as the second
- * argument.  For example, to maintain a running maximum value, you
- * could supply {@code Double::max} along with {@code
- * Double.NEGATIVE_INFINITY} as the identity. The order of
+ * contention among threads.  For predictable results, the accumulator
+ * function should be commutative and associative within the floating
+ * point tolerance required in usage contexts. The function is applied
+ * with an existing value (or identity) as one argument, and a given
+ * update as the other argument. For example, to maintain a running
+ * maximum value, you could supply {@code Double::max} along with
+ * {@code Double.NEGATIVE_INFINITY} as the identity. The order of
  * accumulation within or across threads is not guaranteed. Thus, this
  * class may not be applicable if numerical stability is required,
  * especially when combining values of substantially different orders
@@ -91,7 +96,7 @@
     public DoubleAccumulator(DoubleBinaryOperator accumulatorFunction,
                              double identity) {
         this.function = accumulatorFunction;
-        base = this.identity = Double.doubleToRawLongBits(identity);
+        base = this.identity = doubleToRawLongBits(identity);
     }
 
     /**
@@ -100,19 +105,20 @@
      * @param x the value
      */
     public void accumulate(double x) {
-        Cell[] as; long b, v, r; int m; Cell a;
-        if ((as = cells) != null ||
-            (r = Double.doubleToRawLongBits
-             (function.applyAsDouble
-              (Double.longBitsToDouble(b = base), x))) != b  && !casBase(b, r)) {
+        Cell[] cs; long b, v, r; int m; Cell c;
+        if ((cs = cells) != null
+            || ((r = doubleToRawLongBits
+                (function.applyAsDouble(longBitsToDouble(b = base), x))) != b
+                && !casBase(b, r))) {
             boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended =
-                  (r = Double.doubleToRawLongBits
-                   (function.applyAsDouble
-                    (Double.longBitsToDouble(v = a.value), x))) == v ||
-                  a.cas(v, r)))
+            if (cs == null
+                || (m = cs.length - 1) < 0
+                || (c = cs[getProbe() & m]) == null
+                || !(uncontended =
+                     ((r = doubleToRawLongBits
+                       (function.applyAsDouble
+                        (longBitsToDouble(v = c.value), x))) == v)
+                     || c.cas(v, r)))
                 doubleAccumulate(x, function, uncontended);
         }
     }
@@ -127,13 +133,13 @@
      * @return the current value
      */
     public double get() {
-        Cell[] as = cells;
-        double result = Double.longBitsToDouble(base);
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
+        Cell[] cs = cells;
+        double result = longBitsToDouble(base);
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
                     result = function.applyAsDouble
-                        (result, Double.longBitsToDouble(a.value));
+                        (result, longBitsToDouble(c.value));
         }
         return result;
     }
@@ -147,12 +153,12 @@
      * updating.
      */
     public void reset() {
-        Cell[] as = cells;
+        Cell[] cs = cells;
         base = identity;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset(identity);
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
+                    c.reset(identity);
         }
     }
 
@@ -167,14 +173,12 @@
      * @return the value before reset
      */
     public double getThenReset() {
-        Cell[] as = cells;
-        double result = Double.longBitsToDouble(base);
-        base = identity;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    double v = Double.longBitsToDouble(a.value);
-                    a.reset(identity);
+        Cell[] cs = cells;
+        double result = longBitsToDouble(getAndSetBase(identity));
+        if (cs != null) {
+            for (Cell c : cs) {
+                if (c != null) {
+                    double v = longBitsToDouble(c.getAndSet(identity));
                     result = function.applyAsDouble(result, v);
                 }
             }
@@ -267,9 +271,9 @@
          * held by this proxy
          */
         private Object readResolve() {
-            double d = Double.longBitsToDouble(identity);
+            double d = longBitsToDouble(identity);
             DoubleAccumulator a = new DoubleAccumulator(function, d);
-            a.base = Double.doubleToRawLongBits(value);
+            a.base = doubleToRawLongBits(value);
             return a;
         }
     }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java b/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java
index 57bd8c5..3f3343f 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/DoubleAdder.java
@@ -87,15 +87,15 @@
      * @param x the value to add
      */
     public void add(double x) {
-        Cell[] as; long b, v; int m; Cell a;
-        if ((as = cells) != null ||
+        Cell[] cs; long b, v; int m; Cell c;
+        if ((cs = cells) != null ||
             !casBase(b = base,
                      Double.doubleToRawLongBits
                      (Double.longBitsToDouble(b) + x))) {
             boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended = a.cas(v = a.value,
+            if (cs == null || (m = cs.length - 1) < 0 ||
+                (c = cs[getProbe() & m]) == null ||
+                !(uncontended = c.cas(v = c.value,
                                       Double.doubleToRawLongBits
                                       (Double.longBitsToDouble(v) + x))))
                 doubleAccumulate(x, null, uncontended);
@@ -115,12 +115,12 @@
      * @return the sum
      */
     public double sum() {
-        Cell[] as = cells;
+        Cell[] cs = cells;
         double sum = Double.longBitsToDouble(base);
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    sum += Double.longBitsToDouble(a.value);
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
+                    sum += Double.longBitsToDouble(c.value);
         }
         return sum;
     }
@@ -133,12 +133,12 @@
      * known that no threads are concurrently updating.
      */
     public void reset() {
-        Cell[] as = cells;
+        Cell[] cs = cells;
         base = 0L; // relies on fact that double 0 must have same rep as long
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset();
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
+                    c.reset();
         }
     }
 
@@ -153,16 +153,12 @@
      * @return the sum
      */
     public double sumThenReset() {
-        Cell[] as = cells;
-        double sum = Double.longBitsToDouble(base);
-        base = 0L;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    long v = a.value;
-                    a.reset();
-                    sum += Double.longBitsToDouble(v);
-                }
+        Cell[] cs = cells;
+        double sum = Double.longBitsToDouble(getAndSetBase(0L));
+        if (cs != null) {
+            for (Cell c : cs) {
+                if (c != null)
+                    sum += Double.longBitsToDouble(c.getAndSet(0L));
             }
         }
         return sum;
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java b/ojluni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java
index 0e9a8f5..ed9b4ba 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/LongAccumulator.java
@@ -59,16 +59,17 @@
  * applicable to functions for which the order of accumulation does
  * not matter. The supplied accumulator function should be
  * side-effect-free, since it may be re-applied when attempted updates
- * fail due to contention among threads. The function is applied with
- * the current value as its first argument, and the given update as
- * the second argument.  For example, to maintain a running maximum
- * value, you could supply {@code Long::max} along with {@code
- * Long.MIN_VALUE} as the identity.
+ * fail due to contention among threads. For predictable results, the
+ * accumulator function should be associative and commutative. The
+ * function is applied with an existing value (or identity) as one
+ * argument, and a given update as the other argument.  For example,
+ * to maintain a running maximum value, you could supply {@code
+ * Long::max} along with {@code Long.MIN_VALUE} as the identity.
  *
  * <p>Class {@link LongAdder} provides analogs of the functionality of
  * this class for the common special case of maintaining counts and
  * sums.  The call {@code new LongAdder()} is equivalent to {@code new
- * LongAccumulator((x, y) -> x + y, 0L}.
+ * LongAccumulator((x, y) -> x + y, 0L)}.
  *
  * <p>This class extends {@link Number}, but does <em>not</em> define
  * methods such as {@code equals}, {@code hashCode} and {@code
@@ -102,15 +103,17 @@
      * @param x the value
      */
     public void accumulate(long x) {
-        Cell[] as; long b, v, r; int m; Cell a;
-        if ((as = cells) != null ||
-            (r = function.applyAsLong(b = base, x)) != b && !casBase(b, r)) {
+        Cell[] cs; long b, v, r; int m; Cell c;
+        if ((cs = cells) != null
+            || ((r = function.applyAsLong(b = base, x)) != b
+                && !casBase(b, r))) {
             boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended =
-                  (r = function.applyAsLong(v = a.value, x)) == v ||
-                  a.cas(v, r)))
+            if (cs == null
+                || (m = cs.length - 1) < 0
+                || (c = cs[getProbe() & m]) == null
+                || !(uncontended =
+                     (r = function.applyAsLong(v = c.value, x)) == v
+                     || c.cas(v, r)))
                 longAccumulate(x, function, uncontended);
         }
     }
@@ -125,12 +128,12 @@
      * @return the current value
      */
     public long get() {
-        Cell[] as = cells;
+        Cell[] cs = cells;
         long result = base;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    result = function.applyAsLong(result, a.value);
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
+                    result = function.applyAsLong(result, c.value);
         }
         return result;
     }
@@ -144,12 +147,12 @@
      * updating.
      */
     public void reset() {
-        Cell[] as = cells;
+        Cell[] cs = cells;
         base = identity;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset(identity);
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
+                    c.reset(identity);
         }
     }
 
@@ -164,14 +167,12 @@
      * @return the value before reset
      */
     public long getThenReset() {
-        Cell[] as = cells;
-        long result = base;
-        base = identity;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    long v = a.value;
-                    a.reset(identity);
+        Cell[] cs = cells;
+        long result = getAndSetBase(identity);
+        if (cs != null) {
+            for (Cell c : cs) {
+                if (c != null) {
+                    long v = c.getAndSet(identity);
                     result = function.applyAsLong(result, v);
                 }
             }
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/LongAdder.java b/ojluni/src/main/java/java/util/concurrent/atomic/LongAdder.java
index 0248fad..e0fdc18 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/LongAdder.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/LongAdder.java
@@ -83,12 +83,12 @@
      * @param x the value to add
      */
     public void add(long x) {
-        Cell[] as; long b, v; int m; Cell a;
-        if ((as = cells) != null || !casBase(b = base, b + x)) {
+        Cell[] cs; long b, v; int m; Cell c;
+        if ((cs = cells) != null || !casBase(b = base, b + x)) {
             boolean uncontended = true;
-            if (as == null || (m = as.length - 1) < 0 ||
-                (a = as[getProbe() & m]) == null ||
-                !(uncontended = a.cas(v = a.value, v + x)))
+            if (cs == null || (m = cs.length - 1) < 0 ||
+                (c = cs[getProbe() & m]) == null ||
+                !(uncontended = c.cas(v = c.value, v + x)))
                 longAccumulate(x, null, uncontended);
         }
     }
@@ -117,12 +117,12 @@
      * @return the sum
      */
     public long sum() {
-        Cell[] as = cells;
+        Cell[] cs = cells;
         long sum = base;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    sum += a.value;
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
+                    sum += c.value;
         }
         return sum;
     }
@@ -135,12 +135,12 @@
      * known that no threads are concurrently updating.
      */
     public void reset() {
-        Cell[] as = cells;
+        Cell[] cs = cells;
         base = 0L;
-        if (as != null) {
-            for (Cell a : as)
-                if (a != null)
-                    a.reset();
+        if (cs != null) {
+            for (Cell c : cs)
+                if (c != null)
+                    c.reset();
         }
     }
 
@@ -155,15 +155,12 @@
      * @return the sum
      */
     public long sumThenReset() {
-        Cell[] as = cells;
-        long sum = base;
-        base = 0L;
-        if (as != null) {
-            for (Cell a : as) {
-                if (a != null) {
-                    sum += a.value;
-                    a.reset();
-                }
+        Cell[] cs = cells;
+        long sum = getAndSetBase(0L);
+        if (cs != null) {
+            for (Cell c : cs) {
+                if (c != null)
+                    sum += c.getAndSet(0L);
             }
         }
         return sum;
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java b/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java
index 2a8f327..1bd059f 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/Striped64.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.Arrays;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.function.DoubleBinaryOperator;
@@ -119,30 +121,31 @@
      * JVM intrinsics note: It would be possible to use a release-only
      * form of CAS here, if it were provided.
      */
-    // Android-removed: @Contended, this hint is not used by the Android runtime.
-    // @jdk.internal.vm.annotation.Contended
+    @jdk.internal.vm.annotation.Contended
     static final class Cell {
         volatile long value;
         Cell(long x) { value = x; }
         final boolean cas(long cmp, long val) {
-            return U.compareAndSwapLong(this, VALUE, cmp, val);
+            return VALUE.compareAndSet(this, cmp, val);
         }
         final void reset() {
-            U.putLongVolatile(this, VALUE, 0L);
+            VALUE.setVolatile(this, 0L);
         }
         final void reset(long identity) {
-            U.putLongVolatile(this, VALUE, identity);
+            VALUE.setVolatile(this, identity);
+        }
+        final long getAndSet(long val) {
+            return (long)VALUE.getAndSet(this, val);
         }
 
-        // Unsafe mechanics
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
+        // VarHandle mechanics
+        private static final VarHandle VALUE;
         static {
             try {
-                VALUE = U.objectFieldOffset
-                    (Cell.class.getDeclaredField("value"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                VALUE = l.findVarHandle(Cell.class, "value", long.class);
             } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                throw new ExceptionInInitializerError(e);
             }
         }
     }
@@ -176,14 +179,18 @@
      * CASes the base field.
      */
     final boolean casBase(long cmp, long val) {
-        return U.compareAndSwapLong(this, BASE, cmp, val);
+        return BASE.compareAndSet(this, cmp, val);
+    }
+
+    final long getAndSetBase(long val) {
+        return (long)BASE.getAndSet(this, val);
     }
 
     /**
      * CASes the cellsBusy field from 0 to 1 to acquire lock.
      */
     final boolean casCellsBusy() {
-        return U.compareAndSwapInt(this, CELLSBUSY, 0, 1);
+        return CELLSBUSY.compareAndSet(this, 0, 1);
     }
 
     /**
@@ -191,7 +198,7 @@
      * Duplicated from ThreadLocalRandom because of packaging restrictions.
      */
     static final int getProbe() {
-        return U.getInt(Thread.currentThread(), PROBE);
+        return (int) THREAD_PROBE.get(Thread.currentThread());
     }
 
     /**
@@ -203,7 +210,7 @@
         probe ^= probe << 13;   // xorshift
         probe ^= probe >>> 17;
         probe ^= probe << 5;
-        U.putInt(Thread.currentThread(), PROBE, probe);
+        THREAD_PROBE.set(Thread.currentThread(), probe);
         return probe;
     }
 
@@ -229,9 +236,9 @@
         }
         boolean collide = false;                // True if last slot nonempty
         done: for (;;) {
-            Cell[] as; Cell a; int n; long v;
-            if ((as = cells) != null && (n = as.length) > 0) {
-                if ((a = as[(n - 1) & h]) == null) {
+            Cell[] cs; Cell c; int n; long v;
+            if ((cs = cells) != null && (n = cs.length) > 0) {
+                if ((c = cs[(n - 1) & h]) == null) {
                     if (cellsBusy == 0) {       // Try to attach new Cell
                         Cell r = new Cell(x);   // Optimistically create
                         if (cellsBusy == 0 && casCellsBusy()) {
@@ -253,17 +260,17 @@
                 }
                 else if (!wasUncontended)       // CAS already known to fail
                     wasUncontended = true;      // Continue after rehash
-                else if (a.cas(v = a.value,
+                else if (c.cas(v = c.value,
                                (fn == null) ? v + x : fn.applyAsLong(v, x)))
                     break;
-                else if (n >= NCPU || cells != as)
+                else if (n >= NCPU || cells != cs)
                     collide = false;            // At max size or stale
                 else if (!collide)
                     collide = true;
                 else if (cellsBusy == 0 && casCellsBusy()) {
                     try {
-                        if (cells == as)        // Expand table unless stale
-                            cells = Arrays.copyOf(as, n << 1);
+                        if (cells == cs)        // Expand table unless stale
+                            cells = Arrays.copyOf(cs, n << 1);
                     } finally {
                         cellsBusy = 0;
                     }
@@ -272,9 +279,9 @@
                 }
                 h = advanceProbe(h);
             }
-            else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
+            else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
                 try {                           // Initialize table
-                    if (cells == as) {
+                    if (cells == cs) {
                         Cell[] rs = new Cell[2];
                         rs[h & 1] = new Cell(x);
                         cells = rs;
@@ -313,9 +320,9 @@
         }
         boolean collide = false;                // True if last slot nonempty
         done: for (;;) {
-            Cell[] as; Cell a; int n; long v;
-            if ((as = cells) != null && (n = as.length) > 0) {
-                if ((a = as[(n - 1) & h]) == null) {
+            Cell[] cs; Cell c; int n; long v;
+            if ((cs = cells) != null && (n = cs.length) > 0) {
+                if ((c = cs[(n - 1) & h]) == null) {
                     if (cellsBusy == 0) {       // Try to attach new Cell
                         Cell r = new Cell(Double.doubleToRawLongBits(x));
                         if (cellsBusy == 0 && casCellsBusy()) {
@@ -337,16 +344,16 @@
                 }
                 else if (!wasUncontended)       // CAS already known to fail
                     wasUncontended = true;      // Continue after rehash
-                else if (a.cas(v = a.value, apply(fn, v, x)))
+                else if (c.cas(v = c.value, apply(fn, v, x)))
                     break;
-                else if (n >= NCPU || cells != as)
+                else if (n >= NCPU || cells != cs)
                     collide = false;            // At max size or stale
                 else if (!collide)
                     collide = true;
                 else if (cellsBusy == 0 && casCellsBusy()) {
                     try {
-                        if (cells == as)        // Expand table unless stale
-                            cells = Arrays.copyOf(as, n << 1);
+                        if (cells == cs)        // Expand table unless stale
+                            cells = Arrays.copyOf(cs, n << 1);
                     } finally {
                         cellsBusy = 0;
                     }
@@ -355,9 +362,9 @@
                 }
                 h = advanceProbe(h);
             }
-            else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
+            else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
                 try {                           // Initialize table
-                    if (cells == as) {
+                    if (cells == cs) {
                         Cell[] rs = new Cell[2];
                         rs[h & 1] = new Cell(Double.doubleToRawLongBits(x));
                         cells = rs;
@@ -373,22 +380,30 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long BASE;
-    private static final long CELLSBUSY;
-    private static final long PROBE;
+    // VarHandle mechanics
+    private static final VarHandle BASE;
+    private static final VarHandle CELLSBUSY;
+    private static final VarHandle THREAD_PROBE;
     static {
         try {
-            BASE = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("base"));
-            CELLSBUSY = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("cellsBusy"));
-
-            PROBE = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            BASE = l.findVarHandle(Striped64.class,
+                    "base", long.class);
+            CELLSBUSY = l.findVarHandle(Striped64.class,
+                    "cellsBusy", int.class);
+            l = java.security.AccessController.doPrivileged(
+                    new java.security.PrivilegedAction<>() {
+                        public MethodHandles.Lookup run() {
+                            try {
+                                return MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup());
+                            } catch (ReflectiveOperationException e) {
+                                throw new ExceptionInInitializerError(e);
+                            }
+                        }});
+            THREAD_PROBE = l.findVarHandle(Thread.class,
+                    "threadLocalRandomProbe", int.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 
diff --git a/ojluni/src/main/java/java/util/concurrent/atomic/package-info.java b/ojluni/src/main/java/java/util/concurrent/atomic/package-info.java
index a8e1ff3..8390ff3 100644
--- a/ojluni/src/main/java/java/util/concurrent/atomic/package-info.java
+++ b/ojluni/src/main/java/java/util/concurrent/atomic/package-info.java
@@ -35,26 +35,10 @@
 
 /**
  * A small toolkit of classes that support lock-free thread-safe
- * programming on single variables.  In essence, the classes in this
- * package extend the notion of {@code volatile} values, fields, and
- * array elements to those that also provide an atomic conditional update
- * operation of the form:
- *
- * <pre> {@code boolean compareAndSet(expectedValue, updateValue);}</pre>
- *
- * <p>This method (which varies in argument types across different
- * classes) atomically sets a variable to the {@code updateValue} if it
- * currently holds the {@code expectedValue}, reporting {@code true} on
- * success.  The classes in this package also contain methods to get and
- * unconditionally set values, as well as a weaker conditional atomic
- * update operation {@code weakCompareAndSet} described below.
- *
- * <p>The specifications of these methods enable implementations to
- * employ efficient machine-level atomic instructions that are available
- * on contemporary processors.  However on some platforms, support may
- * entail some form of internal locking.  Thus the methods are not
- * strictly guaranteed to be non-blocking --
- * a thread may block transiently before performing the operation.
+ * programming on single variables.  Instances of Atomic classes
+ * maintain values that are accessed and updated using methods
+ * otherwise available for fields using associated atomic {@link
+ * java.lang.invoke.VarHandle} operations.
  *
  * <p>Instances of classes
  * {@link java.util.concurrent.atomic.AtomicBoolean},
@@ -76,61 +60,30 @@
  *   }
  * }}</pre>
  *
- * <p>It is straightforward to define new utility functions that, like
- * {@code getAndIncrement}, apply a function to a value atomically.
- * For example, given some transformation
- * <pre> {@code long transform(long input)}</pre>
+ * <p>Arbitrary transformations of the contained value are provided both
+ * by low-level read-modify-write operations such as {@code compareAndSet}
+ * and by higher-level methods such as {@code getAndUpdate}.
  *
- * write your utility method as follows:
- * <pre> {@code
- * long getAndTransform(AtomicLong var) {
- *   long prev, next;
- *   do {
- *     prev = var.get();
- *     next = transform(prev);
- *   } while (!var.compareAndSet(prev, next));
- *   return prev; // return next; for transformAndGet
- * }}</pre>
+ * <p>These classes are not general purpose replacements for {@code
+ * java.lang.Integer} and related classes.  They do <em>not</em>
+ * 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.
  *
- * <p>The memory effects for accesses and updates of atomics generally
- * follow the rules for volatiles, as stated in
- * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
- * Chapter 17 of
- * <cite>The Java&trade; Language Specification</cite></a>:
+ * <p>The
+ * {@link java.util.concurrent.atomic.AtomicIntegerArray},
+ * {@link java.util.concurrent.atomic.AtomicLongArray}, and
+ * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
+ * further extend atomic operation support to arrays of these types.
+ * These classes are also notable in providing {@code volatile} access
+ * semantics for their array elements.
  *
- * <ul>
- *
- *   <li>{@code get} has the memory effects of reading a
- * {@code volatile} variable.
- *
- *   <li>{@code set} has the memory effects of writing (assigning) a
- * {@code volatile} variable.
- *
- *   <li>{@code lazySet} has the memory effects of writing (assigning)
- *   a {@code volatile} variable except that it permits reorderings with
- *   subsequent (but not previous) memory actions that do not themselves
- *   impose reordering constraints with ordinary non-{@code volatile}
- *   writes.  Among other usage contexts, {@code lazySet} may apply when
- *   nulling out, for the sake of garbage collection, a reference that is
- *   never accessed again.
- *
- *   <li>{@code weakCompareAndSet} atomically reads and conditionally
- *   writes a variable but does <em>not</em>
- *   create any happens-before orderings, so provides no guarantees
- *   with respect to previous or subsequent reads and writes of any
- *   variables other than the target of the {@code weakCompareAndSet}.
- *
- *   <li>{@code compareAndSet}
- *   and all other read-and-update operations such as {@code getAndIncrement}
- *   have the memory effects of both reading and
- *   writing {@code volatile} variables.
- * </ul>
- *
- * <p>In addition to classes representing single values, this package
- * contains <em>Updater</em> classes that can be used to obtain
- * {@code compareAndSet} operations on any selected {@code volatile}
- * field of any selected class.
- *
+ * <p>In addition to classes representing single values and arrays,
+ * this package contains <em>Updater</em> classes that can be used to
+ * obtain {@code compareAndSet} and related operations on any selected
+ * {@code volatile} field of any selected class. These classes
+ * predate the introduction of {@link
+ * java.lang.invoke.VarHandle}, and are of more limited use.
  * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater},
  * {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and
  * {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are
@@ -143,38 +96,6 @@
  * reflection-based setup, less convenient usage, and weaker
  * guarantees.
  *
- * <p>The
- * {@link java.util.concurrent.atomic.AtomicIntegerArray},
- * {@link java.util.concurrent.atomic.AtomicLongArray}, and
- * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
- * further extend atomic operation support to arrays of these types.
- * These classes are also notable in providing {@code volatile} access
- * semantics for their array elements, which is not supported for
- * ordinary arrays.
- *
- * <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
- * attempting to set the variable will eventually succeed.  (Such
- * spurious failures may for example be due to memory contention effects
- * that are unrelated to whether the expected and current values are
- * equal.)  Additionally {@code weakCompareAndSet} does not provide
- * ordering guarantees that are usually needed for synchronization
- * control.  However, the method may be useful for updating counters and
- * statistics when such updates are unrelated to the other
- * happens-before orderings of a program.  When a thread sees an update
- * to an atomic variable caused by a {@code weakCompareAndSet}, it does
- * not necessarily see updates to any <em>other</em> variables that
- * occurred before the {@code weakCompareAndSet}.  This may be
- * acceptable when, for example, updating performance statistics, but
- * rarely otherwise.
- *
  * <p>The {@link java.util.concurrent.atomic.AtomicMarkableReference}
  * class associates a single boolean with a reference.  For example, this
  * bit might be used inside a data structure to mean that the object
@@ -185,29 +106,6 @@
  * used for example, to represent version numbers corresponding to
  * series of updates.
  *
- * <p>Atomic classes are designed primarily as building blocks for
- * implementing non-blocking data structures and related infrastructure
- * classes.  The {@code compareAndSet} method is not a general
- * replacement for locking.  It applies only when critical updates for an
- * object are confined to a <em>single</em> variable.
- *
- * <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 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
- * intended applications.  For example, there is no atomic class for
- * representing {@code byte}.  In those infrequent cases where you would
- * like to do so, you can use an {@code AtomicInteger} to hold
- * {@code byte} values, and cast appropriately.
- *
- * You can also hold floats using
- * {@link java.lang.Float#floatToRawIntBits} and
- * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using
- * {@link java.lang.Double#doubleToRawLongBits} and
- * {@link java.lang.Double#longBitsToDouble} conversions.
- *
  * @since 1.5
  */
 package java.util.concurrent.atomic;
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
index fb610fb..5ed5771 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -65,11 +67,11 @@
     private static final long serialVersionUID = 7373984972572414692L;
 
     /*
-      To keep sources in sync, the remainder of this source file is
-      exactly cloned from AbstractQueuedSynchronizer, replacing class
-      name and changing ints related with sync state to longs. Please
-      keep it that way.
-    */
+     * To keep sources in sync, the remainder of this source file is
+     * exactly cloned from AbstractQueuedSynchronizer, replacing class
+     * name and changing ints related with sync state to longs. Please
+     * keep it that way.
+     */
 
     /**
      * Creates a new {@code AbstractQueuedLongSynchronizer} instance
@@ -111,9 +113,8 @@
      * @param newState the new state value
      */
     protected final void setState(long newState) {
-        // Use putLongVolatile instead of ordinary volatile store when
-        // using compareAndSwapLong, for sake of some 32bit systems.
-        U.putLongVolatile(this, STATE, newState);
+        // See JDK-8180620: Clarify VarHandle mixed-access subtleties
+        STATE.setVolatile(this, newState);
     }
 
     /**
@@ -128,7 +129,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(long expect, long update) {
-        return U.compareAndSwapLong(this, STATE, expect, update);
+        return STATE.compareAndSet(this, expect, update);
     }
 
     // Queuing utilities
@@ -149,7 +150,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return oldTail;
@@ -172,7 +173,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return node;
@@ -319,7 +320,9 @@
 
         // predNext is the apparent node to unsplice. CASes below will
         // fail if not, in which case, we lost race vs another cancel
-        // or signal, so no further action is necessary.
+        // or signal, so no further action is necessary, although with
+        // a possibility that a cancelled node may transiently remain
+        // reachable.
         Node predNext = pred.next;
 
         // Can use unconditional write instead of CAS here.
@@ -421,8 +424,8 @@
      * @return {@code true} if interrupted while waiting
      */
     final boolean acquireQueued(final Node node, long arg) {
+        boolean interrupted = false;
         try {
-            boolean interrupted = false;
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
@@ -430,12 +433,13 @@
                     p.next = null; // help GC
                     return interrupted;
                 }
-                if (shouldParkAfterFailedAcquire(p, node) &&
-                    parkAndCheckInterrupt())
-                    interrupted = true;
+                if (shouldParkAfterFailedAcquire(p, node))
+                    interrupted |= parkAndCheckInterrupt();
             }
         } catch (Throwable t) {
             cancelAcquire(node);
+            if (interrupted)
+                selfInterrupt();
             throw t;
         }
     }
@@ -509,8 +513,8 @@
      */
     private void doAcquireShared(long arg) {
         final Node node = addWaiter(Node.SHARED);
+        boolean interrupted = false;
         try {
-            boolean interrupted = false;
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head) {
@@ -518,18 +522,18 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
-                        if (interrupted)
-                            selfInterrupt();
                         return;
                     }
                 }
-                if (shouldParkAfterFailedAcquire(p, node) &&
-                    parkAndCheckInterrupt())
-                    interrupted = true;
+                if (shouldParkAfterFailedAcquire(p, node))
+                    interrupted |= parkAndCheckInterrupt();
             }
         } catch (Throwable t) {
             cancelAcquire(node);
             throw t;
+        } finally {
+            if (interrupted)
+                selfInterrupt();
         }
     }
 
@@ -724,8 +728,7 @@
     /**
      * Returns {@code true} if synchronization is held exclusively with
      * respect to the current (calling) thread.  This method is invoked
-     * upon each call to a non-waiting {@link ConditionObject} method.
-     * (Waiting methods instead invoke {@link #release}.)
+     * upon each call to a {@link ConditionObject} method.
      *
      * <p>The default implementation throws {@link
      * UnsupportedOperationException}. This method is invoked
@@ -911,13 +914,13 @@
      * at any time, a {@code true} return does not guarantee that any
      * other thread will ever acquire.
      *
-     * <p>In this implementation, this operation returns in
-     * constant time.
-     *
      * @return {@code true} if there may be other threads waiting to acquire
      */
     public final boolean hasQueuedThreads() {
-        return head != tail;
+        for (Node p = tail, h = head; p != h && p != null; p = p.prev)
+            if (p.waitStatus <= 0)
+                return true;
+        return false;
     }
 
     /**
@@ -1066,17 +1069,21 @@
      * @since 1.7
      */
     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.
-        Node t = tail; // Read fields in reverse initialization order
-        Node h = head;
-        Node s;
-        return h != t &&
-            ((s = h.next) == null || s.thread != Thread.currentThread());
+        Node h, s;
+        if ((h = head) != null) {
+            if ((s = h.next) == null || s.waitStatus > 0) {
+                s = null; // traverse in case of concurrent cancellation
+                for (Node p = tail; p != h && p != null; p = p.prev) {
+                    if (p.waitStatus <= 0)
+                        s = p;
+                }
+            }
+            if (s != null && s.thread != Thread.currentThread())
+                return true;
+        }
+        return false;
     }
 
-
     // Instrumentation and monitoring methods
 
     /**
@@ -1365,9 +1372,8 @@
     }
 
     /**
-     * Condition implementation for a {@link
-     * AbstractQueuedLongSynchronizer} serving as the basis of a {@link
-     * Lock} implementation.
+     * Condition implementation for a {@link AbstractQueuedLongSynchronizer}
+     * serving as the basis of a {@link Lock} implementation.
      *
      * <p>Method documentation for this class describes mechanics,
      * not behavioral specifications from the point of view of Lock
@@ -1400,6 +1406,8 @@
          * @return its new wait node
          */
         private Node addConditionWaiter() {
+            if (!isHeldExclusively())
+                throw new IllegalMonitorStateException();
             Node t = lastWaiter;
             // If lastWaiter is cancelled, clean out.
             if (t != null && t.waitStatus != Node.CONDITION) {
@@ -1810,30 +1818,19 @@
         }
     }
 
-    /**
-     * Setup to support compareAndSet. We need to natively implement
-     * this here: For the sake of permitting future enhancements, we
-     * cannot explicitly subclass AtomicLong, which would be
-     * efficient and useful otherwise. So, as the lesser of evils, we
-     * natively implement using hotspot intrinsics API. And while we
-     * are at it, we do the same for other CASable fields (which could
-     * otherwise be done with atomic field updaters).
-     */
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
 
     static {
         try {
-            STATE = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "state", long.class);
+            HEAD = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "head", Node.class);
+            TAIL = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "tail", Node.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
 
         // Reduce the risk of rare disastrous classloading in first call to
@@ -1846,7 +1843,7 @@
      */
     private final void initializeSyncQueue() {
         Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
+        if (HEAD.compareAndSet(this, null, (h = new Node())))
             tail = h;
     }
 
@@ -1854,6 +1851,6 @@
      * CASes tail field.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return TAIL.compareAndSet(this, expect, update);
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index 602b5ce..4ecfff0 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -192,19 +194,13 @@
  * represent the locked state. While a non-reentrant lock
  * does not strictly require recording of the current owner
  * thread, this class does so anyway to make usage easier to monitor.
- * It also supports conditions and exposes
- * one of the instrumentation methods:
+ * It also supports conditions and exposes some instrumentation methods:
  *
  * <pre> {@code
  * class Mutex implements Lock, java.io.Serializable {
  *
  *   // Our internal helper class
  *   private static class Sync extends AbstractQueuedSynchronizer {
- *     // Reports whether in locked state
- *     protected boolean isHeldExclusively() {
- *       return getState() == 1;
- *     }
- *
  *     // Acquires the lock if state is zero
  *     public boolean tryAcquire(int acquires) {
  *       assert acquires == 1; // Otherwise unused
@@ -218,14 +214,27 @@
  *     // Releases the lock by setting state to zero
  *     protected boolean tryRelease(int releases) {
  *       assert releases == 1; // Otherwise unused
- *       if (getState() == 0) throw new IllegalMonitorStateException();
+ *       if (!isHeldExclusively())
+ *         throw new IllegalMonitorStateException();
  *       setExclusiveOwnerThread(null);
  *       setState(0);
  *       return true;
  *     }
  *
+ *     // Reports whether in locked state
+ *     public boolean isLocked() {
+ *       return getState() != 0;
+ *     }
+ *
+ *     public boolean isHeldExclusively() {
+ *       // a data race, but safe due to out-of-thin-air guarantees
+ *       return getExclusiveOwnerThread() == Thread.currentThread();
+ *     }
+ *
  *     // Provides a Condition
- *     Condition newCondition() { return new ConditionObject(); }
+ *     public Condition newCondition() {
+ *       return new ConditionObject();
+ *     }
  *
  *     // Deserializes properly
  *     private void readObject(ObjectInputStream s)
@@ -238,12 +247,17 @@
  *   // The sync object does all the hard work. We just forward to it.
  *   private final Sync sync = new Sync();
  *
- *   public void lock()                { sync.acquire(1); }
- *   public boolean tryLock()          { return sync.tryAcquire(1); }
- *   public void unlock()              { sync.release(1); }
- *   public Condition newCondition()   { return sync.newCondition(); }
- *   public boolean isLocked()         { return sync.isHeldExclusively(); }
- *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+ *   public void lock()              { sync.acquire(1); }
+ *   public boolean tryLock()        { return sync.tryAcquire(1); }
+ *   public void unlock()            { sync.release(1); }
+ *   public Condition newCondition() { return sync.newCondition(); }
+ *   public boolean isLocked()       { return sync.isLocked(); }
+ *   public boolean isHeldByCurrentThread() {
+ *     return sync.isHeldExclusively();
+ *   }
+ *   public boolean hasQueuedThreads() {
+ *     return sync.hasQueuedThreads();
+ *   }
  *   public void lockInterruptibly() throws InterruptedException {
  *     sync.acquireInterruptibly(1);
  *   }
@@ -491,7 +505,7 @@
          *
          * @return the predecessor of this node
          */
-        final Node predecessor() throws NullPointerException {
+        final Node predecessor() {
             Node p = prev;
             if (p == null)
                 throw new NullPointerException();
@@ -505,42 +519,43 @@
         /** Constructor used by addWaiter. */
         Node(Node nextWaiter) {
             this.nextWaiter = nextWaiter;
-            U.putObject(this, THREAD, Thread.currentThread());
+            THREAD.set(this, Thread.currentThread());
         }
 
         /** Constructor used by addConditionWaiter. */
         Node(int waitStatus) {
-            U.putInt(this, WAITSTATUS, waitStatus);
-            U.putObject(this, THREAD, Thread.currentThread());
+            WAITSTATUS.set(this, waitStatus);
+            THREAD.set(this, Thread.currentThread());
         }
 
         /** CASes waitStatus field. */
         final boolean compareAndSetWaitStatus(int expect, int update) {
-            return U.compareAndSwapInt(this, WAITSTATUS, expect, update);
+            return WAITSTATUS.compareAndSet(this, expect, update);
         }
 
         /** CASes next field. */
         final boolean compareAndSetNext(Node expect, Node update) {
-            return U.compareAndSwapObject(this, NEXT, expect, update);
+            return NEXT.compareAndSet(this, expect, update);
         }
 
-        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-        private static final long NEXT;
-        static final long PREV;
-        private static final long THREAD;
-        private static final long WAITSTATUS;
+        final void setPrevRelaxed(Node p) {
+            PREV.set(this, p);
+        }
+
+        // VarHandle mechanics
+        private static final VarHandle NEXT;
+        private static final VarHandle PREV;
+        private static final VarHandle THREAD;
+        private static final VarHandle WAITSTATUS;
         static {
             try {
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-                PREV = U.objectFieldOffset
-                    (Node.class.getDeclaredField("prev"));
-                THREAD = U.objectFieldOffset
-                    (Node.class.getDeclaredField("thread"));
-                WAITSTATUS = U.objectFieldOffset
-                    (Node.class.getDeclaredField("waitStatus"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                NEXT = l.findVarHandle(Node.class, "next", Node.class);
+                PREV = l.findVarHandle(Node.class, "prev", Node.class);
+                THREAD = l.findVarHandle(Node.class, "thread", Thread.class);
+                WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class);
             } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                throw new ExceptionInInitializerError(e);
             }
         }
     }
@@ -594,7 +609,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(int expect, int update) {
-        return U.compareAndSwapInt(this, STATE, expect, update);
+        return STATE.compareAndSet(this, expect, update);
     }
 
     // Queuing utilities
@@ -615,7 +630,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return oldTail;
@@ -638,7 +653,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return node;
@@ -785,7 +800,9 @@
 
         // predNext is the apparent node to unsplice. CASes below will
         // fail if not, in which case, we lost race vs another cancel
-        // or signal, so no further action is necessary.
+        // or signal, so no further action is necessary, although with
+        // a possibility that a cancelled node may transiently remain
+        // reachable.
         Node predNext = pred.next;
 
         // Can use unconditional write instead of CAS here.
@@ -886,11 +903,9 @@
      * @param arg the acquire argument
      * @return {@code true} if interrupted while waiting
      */
-    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-    // @ReservedStackAccess
     final boolean acquireQueued(final Node node, int arg) {
+        boolean interrupted = false;
         try {
-            boolean interrupted = false;
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
@@ -898,12 +913,13 @@
                     p.next = null; // help GC
                     return interrupted;
                 }
-                if (shouldParkAfterFailedAcquire(p, node) &&
-                    parkAndCheckInterrupt())
-                    interrupted = true;
+                if (shouldParkAfterFailedAcquire(p, node))
+                    interrupted |= parkAndCheckInterrupt();
             }
         } catch (Throwable t) {
             cancelAcquire(node);
+            if (interrupted)
+                selfInterrupt();
             throw t;
         }
     }
@@ -977,8 +993,8 @@
      */
     private void doAcquireShared(int arg) {
         final Node node = addWaiter(Node.SHARED);
+        boolean interrupted = false;
         try {
-            boolean interrupted = false;
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head) {
@@ -986,18 +1002,18 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
-                        if (interrupted)
-                            selfInterrupt();
                         return;
                     }
                 }
-                if (shouldParkAfterFailedAcquire(p, node) &&
-                    parkAndCheckInterrupt())
-                    interrupted = true;
+                if (shouldParkAfterFailedAcquire(p, node))
+                    interrupted |= parkAndCheckInterrupt();
             }
         } catch (Throwable t) {
             cancelAcquire(node);
             throw t;
+        } finally {
+            if (interrupted)
+                selfInterrupt();
         }
     }
 
@@ -1192,8 +1208,7 @@
     /**
      * Returns {@code true} if synchronization is held exclusively with
      * respect to the current (calling) thread.  This method is invoked
-     * upon each call to a non-waiting {@link ConditionObject} method.
-     * (Waiting methods instead invoke {@link #release}.)
+     * upon each call to a {@link ConditionObject} method.
      *
      * <p>The default implementation throws {@link
      * UnsupportedOperationException}. This method is invoked
@@ -1220,8 +1235,6 @@
      *        {@link #tryAcquire} but is otherwise uninterpreted and
      *        can represent anything you like.
      */
-    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-    // @ReservedStackAccess
     public final void acquire(int arg) {
         if (!tryAcquire(arg) &&
             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
@@ -1285,8 +1298,6 @@
      *        can represent anything you like.
      * @return the value returned from {@link #tryRelease}
      */
-    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-    // @ReservedStackAccess
     public final boolean release(int arg) {
         if (tryRelease(arg)) {
             Node h = head;
@@ -1367,8 +1378,6 @@
      *        and can represent anything you like.
      * @return the value returned from {@link #tryReleaseShared}
      */
-    // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-    // @ReservedStackAccess
     public final boolean releaseShared(int arg) {
         if (tryReleaseShared(arg)) {
             doReleaseShared();
@@ -1385,13 +1394,13 @@
      * at any time, a {@code true} return does not guarantee that any
      * other thread will ever acquire.
      *
-     * <p>In this implementation, this operation returns in
-     * constant time.
-     *
      * @return {@code true} if there may be other threads waiting to acquire
      */
     public final boolean hasQueuedThreads() {
-        return head != tail;
+        for (Node p = tail, h = head; p != h && p != null; p = p.prev)
+            if (p.waitStatus <= 0)
+                return true;
+        return false;
     }
 
     /**
@@ -1540,17 +1549,21 @@
      * @since 1.7
      */
     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.
-        Node t = tail; // Read fields in reverse initialization order
-        Node h = head;
-        Node s;
-        return h != t &&
-            ((s = h.next) == null || s.thread != Thread.currentThread());
+        Node h, s;
+        if ((h = head) != null) {
+            if ((s = h.next) == null || s.waitStatus > 0) {
+                s = null; // traverse in case of concurrent cancellation
+                for (Node p = tail; p != h && p != null; p = p.prev) {
+                    if (p.waitStatus <= 0)
+                        s = p;
+                }
+            }
+            if (s != null && s.thread != Thread.currentThread())
+                return true;
+        }
+        return false;
     }
 
-
     // Instrumentation and monitoring methods
 
     /**
@@ -1839,9 +1852,8 @@
     }
 
     /**
-     * Condition implementation for a {@link
-     * AbstractQueuedSynchronizer} serving as the basis of a {@link
-     * Lock} implementation.
+     * Condition implementation for a {@link AbstractQueuedSynchronizer}
+     * serving as the basis of a {@link Lock} implementation.
      *
      * <p>Method documentation for this class describes mechanics,
      * not behavioral specifications from the point of view of Lock
@@ -1872,6 +1884,8 @@
          * @return its new wait node
          */
         private Node addConditionWaiter() {
+            if (!isHeldExclusively())
+                throw new IllegalMonitorStateException();
             Node t = lastWaiter;
             // If lastWaiter is cancelled, clean out.
             if (t != null && t.waitStatus != Node.CONDITION) {
@@ -2282,30 +2296,19 @@
         }
     }
 
-    /**
-     * Setup to support compareAndSet. We need to natively implement
-     * this here: For the sake of permitting future enhancements, we
-     * cannot explicitly subclass AtomicInteger, which would be
-     * efficient and useful otherwise. So, as the lesser of evils, we
-     * natively implement using hotspot intrinsics API. And while we
-     * are at it, we do the same for other CASable fields (which could
-     * otherwise be done with atomic field updaters).
-     */
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
 
     static {
         try {
-            STATE = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(AbstractQueuedSynchronizer.class, "state", int.class);
+            HEAD = l.findVarHandle(AbstractQueuedSynchronizer.class, "head", Node.class);
+            TAIL = l.findVarHandle(AbstractQueuedSynchronizer.class, "tail", Node.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
 
         // Reduce the risk of rare disastrous classloading in first call to
@@ -2318,7 +2321,7 @@
      */
     private final void initializeSyncQueue() {
         Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
+        if (HEAD.compareAndSet(this, null, (h = new Node())))
             tail = h;
     }
 
@@ -2326,6 +2329,6 @@
      * CASes tail field.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return TAIL.compareAndSet(this, expect, update);
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/Condition.java b/ojluni/src/main/java/java/util/concurrent/locks/Condition.java
index 79181fd..cf747024 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/Condition.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/Condition.java
@@ -73,7 +73,7 @@
  * available in the buffer. This can be achieved using two
  * {@link Condition} instances.
  * <pre>
- * class BoundedBuffer {
+ * class BoundedBuffer&lt;E&gt; {
  *   <b>final Lock lock = new ReentrantLock();</b>
  *   final Condition notFull  = <b>lock.newCondition(); </b>
  *   final Condition notEmpty = <b>lock.newCondition(); </b>
@@ -81,7 +81,7 @@
  *   final Object[] items = new Object[100];
  *   int putptr, takeptr, count;
  *
- *   public void put(Object x) throws InterruptedException {
+ *   public void put(E x) throws InterruptedException {
  *     <b>lock.lock();
  *     try {</b>
  *       while (count == items.length)
@@ -95,12 +95,12 @@
  *     }</b>
  *   }
  *
- *   public Object take() throws InterruptedException {
+ *   public E take() throws InterruptedException {
  *     <b>lock.lock();
  *     try {</b>
  *       while (count == 0)
  *         <b>notEmpty.await();</b>
- *       Object x = items[takeptr];
+ *       E x = (E) items[takeptr];
  *       if (++takeptr == items.length) takeptr = 0;
  *       --count;
  *       <b>notFull.signal();</b>
@@ -310,16 +310,18 @@
      * the following form:
      *
      * <pre> {@code
-     * boolean aMethod(long timeout, TimeUnit unit) {
-     *   long nanos = unit.toNanos(timeout);
+     * boolean aMethod(long timeout, TimeUnit unit)
+     *     throws InterruptedException {
+     *   long nanosRemaining = unit.toNanos(timeout);
      *   lock.lock();
      *   try {
      *     while (!conditionBeingWaitedFor()) {
-     *       if (nanos <= 0L)
+     *       if (nanosRemaining <= 0L)
      *         return false;
-     *       nanos = theCondition.awaitNanos(nanos);
+     *       nanosRemaining = theCondition.awaitNanos(nanosRemaining);
      *     }
      *     // ...
+     *     return true;
      *   } finally {
      *     lock.unlock();
      *   }
@@ -396,7 +398,6 @@
      * re-acquire the lock associated with this condition. When the
      * thread returns it is <em>guaranteed</em> to hold this lock.
      *
-     *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
@@ -408,11 +409,11 @@
      * case, whether or not the test for interruption occurs before the lock
      * is released.
      *
-     *
      * <p>The return value indicates whether the deadline has elapsed,
      * which can be used as follows:
      * <pre> {@code
-     * boolean aMethod(Date deadline) {
+     * boolean aMethod(Date deadline)
+     *     throws InterruptedException {
      *   boolean stillWaiting = true;
      *   lock.lock();
      *   try {
@@ -422,6 +423,7 @@
      *       stillWaiting = theCondition.awaitUntil(deadline);
      *     }
      *     // ...
+     *     return true;
      *   } finally {
      *     lock.unlock();
      *   }
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/LockSupport.java b/ojluni/src/main/java/java/util/concurrent/locks/LockSupport.java
index 4c57596..b3ef8d0 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/LockSupport.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/LockSupport.java
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.locks;
 
+import jdk.internal.misc.Unsafe;
+
 /**
  * Basic thread blocking primitives for creating locks and other
  * synchronization classes.
@@ -131,6 +133,8 @@
  *     Class<?> ensureLoaded = LockSupport.class;
  *   }
  * }}</pre>
+ *
+ * @since 1.5
  */
 public class LockSupport {
     private LockSupport() {} // Cannot be instantiated.
@@ -405,19 +409,23 @@
         return r;
     }
 
-    // Hotspot implementation via intrinsics API
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long PARKBLOCKER;
-    private static final long SECONDARY;
-    static {
-        try {
-            PARKBLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
-            SECONDARY = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
+    /**
+     * Returns the thread id for the given thread.  We must access
+     * this directly rather than via method Thread.getId() because
+     * getId() has been known to be overridden in ways that do not
+     * preserve unique mappings.
+     */
+    static final long getThreadId(Thread thread) {
+        return U.getLong(thread, TID);
     }
 
+    // Hotspot implementation via intrinsics API
+    private static final Unsafe U = Unsafe.getUnsafe();
+    private static final long PARKBLOCKER = U.objectFieldOffset
+            (Thread.class, "parkBlocker");
+    private static final long SECONDARY = U.objectFieldOffset
+            (Thread.class, "threadLocalRandomSecondarySeed");
+    private static final long TID = U.objectFieldOffset
+            (Thread.class, "tid");
+
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java b/ojluni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
index 00fb845..8455944 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
@@ -79,7 +79,6 @@
  * and measurement will establish whether the use of a read-write lock is
  * suitable for your application.
  *
- *
  * <p>Although the basic operation of a read-write lock is straight-forward,
  * there are many policy decisions that an implementation must make, which
  * may affect the effectiveness of the read-write lock in a given application.
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java b/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
index 3c1c492..1cb7d89 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
@@ -37,6 +37,7 @@
 
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * A reentrant mutual exclusion {@link Lock} with the same basic
@@ -118,17 +119,10 @@
         private static final long serialVersionUID = -5179523762034025860L;
 
         /**
-         * Performs {@link Lock#lock}. The main reason for subclassing
-         * is to allow fast path for nonfair version.
-         */
-        abstract void lock();
-
-        /**
          * Performs non-fair tryLock.  tryAcquire is implemented in
          * subclasses, but both need nonfair try for trylock method.
          */
-        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-        // @ReservedStackAccess
+        @ReservedStackAccess
         final boolean nonfairTryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
@@ -148,8 +142,7 @@
             return false;
         }
 
-        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-        // @ReservedStackAccess
+        @ReservedStackAccess
         protected final boolean tryRelease(int releases) {
             int c = getState() - releases;
             if (Thread.currentThread() != getExclusiveOwnerThread())
@@ -202,20 +195,6 @@
      */
     static final class NonfairSync extends Sync {
         private static final long serialVersionUID = 7316153563782823691L;
-
-        /**
-         * Performs lock.  Try immediate barge, backing up to normal
-         * acquire on failure.
-         */
-        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-        // @ReservedStackAccess
-        final void lock() {
-            if (compareAndSetState(0, 1))
-                setExclusiveOwnerThread(Thread.currentThread());
-            else
-                acquire(1);
-        }
-
         protected final boolean tryAcquire(int acquires) {
             return nonfairTryAcquire(acquires);
         }
@@ -226,17 +205,11 @@
      */
     static final class FairSync extends Sync {
         private static final long serialVersionUID = -3000897897090466540L;
-
-        final void lock() {
-            acquire(1);
-        }
-
         /**
          * Fair version of tryAcquire.  Don't grant access unless
          * recursive call or no waiters or is first.
          */
-        // Android-removed: @ReservedStackAccess from OpenJDK 9, not available on Android.
-        // @ReservedStackAccess
+        @ReservedStackAccess
         protected final boolean tryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
@@ -291,7 +264,7 @@
      * at which time the lock hold count is set to one.
      */
     public void lock() {
-        sync.lock();
+        sync.acquire(1);
     }
 
     /**
@@ -357,7 +330,7 @@
      * This &quot;barging&quot; behavior can be useful in certain
      * circumstances, even though it breaks fairness. If you want to honor
      * the fairness setting for this lock, then use
-     * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+     * {@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
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java b/ojluni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
index 9d98f37..c92e213 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -37,6 +37,7 @@
 
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * An implementation of {@link ReadWriteLock} supporting similar
@@ -52,16 +53,14 @@
  *
  * <dl>
  * <dt><b><i>Non-fair mode (default)</i></b>
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * When constructed as non-fair (the default), the order of entry
+ * <dd>When constructed as non-fair (the default), the order of entry
  * to the read and write lock is unspecified, subject to reentrancy
  * constraints.  A nonfair lock that is continuously contended may
  * indefinitely postpone one or more reader or writer threads, but
  * will normally have higher throughput than a fair lock.
  *
  * <dt><b><i>Fair mode</i></b>
- * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
- * 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
@@ -137,7 +136,7 @@
  * <pre> {@code
  * class CachedData {
  *   Object data;
- *   volatile boolean cacheValid;
+ *   boolean cacheValid;
  *   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  *
  *   void processCachedData() {
@@ -278,7 +277,7 @@
         static final class HoldCounter {
             int count;          // initially 0
             // Use id, not reference, to avoid garbage retention
-            final long tid = getThreadId(Thread.currentThread());
+            final long tid = LockSupport.getThreadId(Thread.currentThread());
         }
 
         /**
@@ -367,7 +366,7 @@
          * both read and write holds that are all released during a
          * condition wait and re-established in tryAcquire.
          */
-
+        @ReservedStackAccess
         protected final boolean tryRelease(int releases) {
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
@@ -379,6 +378,7 @@
             return free;
         }
 
+        @ReservedStackAccess
         protected final boolean tryAcquire(int acquires) {
             /*
              * Walkthrough:
@@ -411,6 +411,7 @@
             return true;
         }
 
+        @ReservedStackAccess
         protected final boolean tryReleaseShared(int unused) {
             Thread current = Thread.currentThread();
             if (firstReader == current) {
@@ -421,7 +422,8 @@
                     firstReaderHoldCount--;
             } else {
                 HoldCounter rh = cachedHoldCounter;
-                if (rh == null || rh.tid != getThreadId(current))
+                if (rh == null ||
+                    rh.tid != LockSupport.getThreadId(current))
                     rh = readHolds.get();
                 int count = rh.count;
                 if (count <= 1) {
@@ -442,11 +444,12 @@
             }
         }
 
-        private IllegalMonitorStateException unmatchedUnlockException() {
+        private static IllegalMonitorStateException unmatchedUnlockException() {
             return new IllegalMonitorStateException(
                 "attempt to unlock read lock, not locked by current thread");
         }
 
+        @ReservedStackAccess
         protected final int tryAcquireShared(int unused) {
             /*
              * Walkthrough:
@@ -479,7 +482,8 @@
                     firstReaderHoldCount++;
                 } else {
                     HoldCounter rh = cachedHoldCounter;
-                    if (rh == null || rh.tid != getThreadId(current))
+                    if (rh == null ||
+                        rh.tid != LockSupport.getThreadId(current))
                         cachedHoldCounter = rh = readHolds.get();
                     else if (rh.count == 0)
                         readHolds.set(rh);
@@ -516,7 +520,8 @@
                     } else {
                         if (rh == null) {
                             rh = cachedHoldCounter;
-                            if (rh == null || rh.tid != getThreadId(current)) {
+                            if (rh == null ||
+                                rh.tid != LockSupport.getThreadId(current)) {
                                 rh = readHolds.get();
                                 if (rh.count == 0)
                                     readHolds.remove();
@@ -537,7 +542,8 @@
                     } else {
                         if (rh == null)
                             rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null ||
+                            rh.tid != LockSupport.getThreadId(current))
                             rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -554,6 +560,7 @@
          * This is identical in effect to tryAcquire except for lack
          * of calls to writerShouldBlock.
          */
+        @ReservedStackAccess
         final boolean tryWriteLock() {
             Thread current = Thread.currentThread();
             int c = getState();
@@ -575,6 +582,7 @@
          * This is identical in effect to tryAcquireShared except for
          * lack of calls to readerShouldBlock.
          */
+        @ReservedStackAccess
         final boolean tryReadLock() {
             Thread current = Thread.currentThread();
             for (;;) {
@@ -593,7 +601,8 @@
                         firstReaderHoldCount++;
                     } else {
                         HoldCounter rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null ||
+                            rh.tid != LockSupport.getThreadId(current))
                             cachedHoldCounter = rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -644,7 +653,7 @@
                 return firstReaderHoldCount;
 
             HoldCounter rh = cachedHoldCounter;
-            if (rh != null && rh.tid == getThreadId(current))
+            if (rh != null && rh.tid == LockSupport.getThreadId(current))
                 return rh.count;
 
             int count = readHolds.get().count;
@@ -788,7 +797,7 @@
          * can be useful in certain circumstances, even though it
          * breaks fairness. If you want to honor the fairness setting
          * for this lock, then use {@link #tryLock(long, TimeUnit)
-         * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
+         * tryLock(0, TimeUnit.SECONDS)} which is almost equivalent
          * (it also detects interruption).
          *
          * <p>If the write lock is held by another thread then
@@ -1020,7 +1029,7 @@
          * behavior can be useful in certain circumstances, even
          * though it breaks fairness. If you want to honor the
          * fairness setting for this lock, then use {@link
-         * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
+         * #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
@@ -1490,26 +1499,4 @@
             "[Write locks = " + w + ", Read locks = " + r + "]";
     }
 
-    /**
-     * Returns the thread id for the given thread.  We must access
-     * this directly rather than via method Thread.getId() because
-     * getId() is not final, and has been known to be overridden in
-     * ways that do not preserve unique mappings.
-     */
-    static final long getThreadId(Thread thread) {
-        return U.getLongVolatile(thread, TID);
-    }
-
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long TID;
-    static {
-        try {
-            TID = U.objectFieldOffset
-                (Thread.class.getDeclaredField("tid"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/locks/StampedLock.java b/ojluni/src/main/java/java/util/concurrent/locks/StampedLock.java
index d689599..dbcf9c3 100644
--- a/ojluni/src/main/java/java/util/concurrent/locks/StampedLock.java
+++ b/ojluni/src/main/java/java/util/concurrent/locks/StampedLock.java
@@ -35,7 +35,10 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * A capability-based lock with three modes for controlling read/write
@@ -108,6 +111,10 @@
  * into initial unlocked state, so they are not useful for remote
  * locking.
  *
+ * <p>Like {@link java.util.concurrent.Semaphore Semaphore}, but unlike most
+ * {@link Lock} implementations, StampedLocks have no notion of ownership.
+ * Locks acquired in one thread can be released or converted in another.
+ *
  * <p>The scheduling policy of StampedLock does not consistently
  * prefer readers over writers or vice versa.  All "try" methods are
  * best-effort and do not necessarily conform to any scheduling or
@@ -126,14 +133,15 @@
  * in a class that maintains simple two-dimensional points. The sample
  * code illustrates some try/catch conventions even though they are
  * not strictly needed here because no exceptions can occur in their
- * bodies.<br>
+ * bodies.
  *
  * <pre> {@code
  * class Point {
  *   private double x, y;
  *   private final StampedLock sl = new StampedLock();
  *
- *   void move(double deltaX, double deltaY) { // an exclusively locked method
+ *   // an exclusively locked method
+ *   void move(double deltaX, double deltaY) {
  *     long stamp = sl.writeLock();
  *     try {
  *       x += deltaX;
@@ -143,23 +151,57 @@
  *     }
  *   }
  *
- *   double distanceFromOrigin() { // A read-only method
+ *   // a read-only method
+ *   // upgrade from optimistic read to read lock
+ *   double distanceFromOrigin() {
  *     long stamp = sl.tryOptimisticRead();
- *     double currentX = x, currentY = y;
- *     if (!sl.validate(stamp)) {
- *        stamp = sl.readLock();
- *        try {
- *          currentX = x;
- *          currentY = y;
- *        } finally {
- *           sl.unlockRead(stamp);
- *        }
+ *     try {
+ *       retryHoldingLock: for (;; stamp = sl.readLock()) {
+ *         if (stamp == 0L)
+ *           continue retryHoldingLock;
+ *         // possibly racy reads
+ *         double currentX = x;
+ *         double currentY = y;
+ *         if (!sl.validate(stamp))
+ *           continue retryHoldingLock;
+ *         return Math.hypot(currentX, currentY);
+ *       }
+ *     } finally {
+ *       if (StampedLock.isReadLockStamp(stamp))
+ *         sl.unlockRead(stamp);
  *     }
- *     return Math.sqrt(currentX * currentX + currentY * currentY);
  *   }
  *
- *   void moveIfAtOrigin(double newX, double newY) { // upgrade
- *     // Could instead start with optimistic, not read mode
+ *   // upgrade from optimistic read to write lock
+ *   void moveIfAtOrigin(double newX, double newY) {
+ *     long stamp = sl.tryOptimisticRead();
+ *     try {
+ *       retryHoldingLock: for (;; stamp = sl.writeLock()) {
+ *         if (stamp == 0L)
+ *           continue retryHoldingLock;
+ *         // possibly racy reads
+ *         double currentX = x;
+ *         double currentY = y;
+ *         if (!sl.validate(stamp))
+ *           continue retryHoldingLock;
+ *         if (currentX != 0.0 || currentY != 0.0)
+ *           break;
+ *         stamp = sl.tryConvertToWriteLock(stamp);
+ *         if (stamp == 0L)
+ *           continue retryHoldingLock;
+ *         // exclusive access
+ *         x = newX;
+ *         y = newY;
+ *         return;
+ *       }
+ *     } finally {
+ *       if (StampedLock.isWriteLockStamp(stamp))
+ *         sl.unlockWrite(stamp);
+ *     }
+ *   }
+ *
+ *   // Upgrade read lock to write lock
+ *   void moveIfAtOrigin(double newX, double newY) {
  *     long stamp = sl.readLock();
  *     try {
  *       while (x == 0.0 && y == 0.0) {
@@ -234,9 +276,7 @@
      * used in the acquire methods to reduce (increasingly expensive)
      * context switching while also avoiding sustained memory
      * thrashing among many threads.  We limit spins to the head of
-     * queue. A thread spin-waits up to SPINS times (where each
-     * iteration decreases spin count with 50% probability) before
-     * blocking. If, upon wakening it fails to obtain lock, and is
+     * queue. If, upon wakening, a thread fails to obtain lock, and is
      * still (or becomes) the first waiting thread (which indicates
      * that some other thread barged and obtained lock), it escalates
      * spins (up to MAX_HEAD_SPINS) to reduce the likelihood of
@@ -251,8 +291,53 @@
      * method validate()) requires stricter ordering rules than apply
      * to normal volatile reads (of "state").  To force orderings of
      * reads before a validation and the validation itself in those
-     * cases where this is not already forced, we use
-     * Unsafe.loadFence.
+     * cases where this is not already forced, we use acquireFence.
+     * Unlike in that paper, we allow writers to use plain writes.
+     * One would not expect reorderings of such writes with the lock
+     * acquisition CAS because there is a "control dependency", but it
+     * is theoretically possible, so we additionally add a
+     * storeStoreFence after lock acquisition CAS.
+     *
+     * ----------------------------------------------------------------
+     * Here's an informal proof that plain reads by _successful_
+     * readers see plain writes from preceding but not following
+     * writers (following Boehm and the C++ standard [atomics.fences]):
+     *
+     * Because of the total synchronization order of accesses to
+     * volatile long state containing the sequence number, writers and
+     * _successful_ readers can be globally sequenced.
+     *
+     * int x, y;
+     *
+     * Writer 1:
+     * inc sequence (odd - "locked")
+     * storeStoreFence();
+     * x = 1; y = 2;
+     * inc sequence (even - "unlocked")
+     *
+     * Successful Reader:
+     * read sequence (even)
+     * // must see writes from Writer 1 but not Writer 2
+     * r1 = x; r2 = y;
+     * acquireFence();
+     * read sequence (even - validated unchanged)
+     * // use r1 and r2
+     *
+     * Writer 2:
+     * inc sequence (odd - "locked")
+     * storeStoreFence();
+     * x = 3; y = 4;
+     * inc sequence (even - "unlocked")
+     *
+     * Visibility of writer 1's stores is normal - reader's initial
+     * read of state synchronizes with writer 1's final write to state.
+     * Lack of visibility of writer 2's plain writes is less obvious.
+     * If reader's read of x or y saw writer 2's write, then (assuming
+     * semantics of C++ fences) the storeStoreFence would "synchronize"
+     * with reader's acquireFence and reader's validation read must see
+     * writer 2's initial write to state and so validation must fail.
+     * But making this "proof" formal and rigorous is an open problem!
+     * ----------------------------------------------------------------
      *
      * The memory layout keeps lock state and queue pointers together
      * (normally on the same cache line). This usually works well for
@@ -267,14 +352,14 @@
     /** Number of processors, for spin control */
     private static final int NCPU = Runtime.getRuntime().availableProcessors();
 
-    /** Maximum number of retries before enqueuing on acquisition */
-    private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
+    /** Maximum number of retries before enqueuing on acquisition; at least 1 */
+    private static final int SPINS = (NCPU > 1) ? 1 << 6 : 1;
 
-    /** Maximum number of retries before blocking at head on acquisition */
-    private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
+    /** Maximum number of tries before blocking at head on acquisition */
+    private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 1;
 
     /** Maximum number of retries before re-blocking */
-    private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
+    private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 1;
 
     /** The period for yielding when waiting for overflow spinlock */
     private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
@@ -290,7 +375,20 @@
     private static final long ABITS = RBITS | WBIT;
     private static final long SBITS = ~RBITS; // note overlap with ABITS
 
-    // Initial value for lock state; avoid failure value zero
+    /*
+     * 3 stamp modes can be distinguished by examining (m = stamp & ABITS):
+     * write mode: m == WBIT
+     * optimistic read mode: m == 0L (even when read lock is held)
+     * read mode: m > 0L && m <= RFULL (the stamp is a copy of state, but the
+     * read hold count in the stamp is unused other than to determine mode)
+     *
+     * This differs slightly from the encoding of state:
+     * (state & ABITS) == 0L indicates the lock is currently unlocked.
+     * (state & ABITS) == RBITS is a special transient value
+     * indicating spin-locked to manipulate reader bits overflow.
+     */
+
+    /** Initial value for lock state; avoids failure value zero. */
     private static final long ORIGIN = WBIT << 1;
 
     // Special value from cancelled acquire methods so caller can throw IE
@@ -337,30 +435,42 @@
         state = ORIGIN;
     }
 
+    private boolean casState(long expectedValue, long newValue) {
+        return STATE.compareAndSet(this, expectedValue, newValue);
+    }
+
+    private long tryWriteLock(long s) {
+        // assert (s & ABITS) == 0L;
+        long next;
+        if (casState(s, next = s | WBIT)) {
+            VarHandle.storeStoreFence();
+            return next;
+        }
+        return 0L;
+    }
+
     /**
      * Exclusively acquires the lock, blocking if necessary
      * until available.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a write stamp that can be used to unlock or convert mode
      */
+    @ReservedStackAccess
     public long writeLock() {
-        long s, next;  // bypass acquireWrite in fully unlocked case only
-        return ((((s = state) & ABITS) == 0L &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
-                next : acquireWrite(false, 0L));
+        long next;
+        return ((next = tryWriteLock()) != 0L) ? next : acquireWrite(false, 0L);
     }
 
     /**
      * Exclusively acquires the lock if it is immediately available.
      *
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a write stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      */
+    @ReservedStackAccess
     public long tryWriteLock() {
-        long s, next;
-        return ((((s = state) & ABITS) == 0L &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
-                next : 0L);
+        long s;
+        return (((s = state) & ABITS) == 0L) ? tryWriteLock(s) : 0L;
     }
 
     /**
@@ -371,7 +481,7 @@
      *
      * @param time the maximum time to wait for the lock
      * @param unit the time unit of the {@code time} argument
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a write stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
@@ -399,10 +509,11 @@
      * Behavior under interruption matches that specified
      * for method {@link Lock#lockInterruptibly()}.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a write stamp that can be used to unlock or convert mode
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
      */
+    @ReservedStackAccess
     public long writeLockInterruptibly() throws InterruptedException {
         long next;
         if (!Thread.interrupted() &&
@@ -415,33 +526,37 @@
      * Non-exclusively acquires the lock, blocking if necessary
      * until available.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a read stamp that can be used to unlock or convert mode
      */
+    @ReservedStackAccess
     public long readLock() {
-        long s = state, next;  // bypass acquireRead on common uncontended case
-        return ((whead == wtail && (s & ABITS) < RFULL &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
-                next : acquireRead(false, 0L));
+        long s, next;
+        // bypass acquireRead on common uncontended case
+        return (whead == wtail
+                && ((s = state) & ABITS) < RFULL
+                && casState(s, next = s + RUNIT))
+            ? next
+            : acquireRead(false, 0L);
     }
 
     /**
      * Non-exclusively acquires the lock if it is immediately available.
      *
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a read stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      */
+    @ReservedStackAccess
     public long tryReadLock() {
-        for (;;) {
-            long s, m, next;
-            if ((m = (s = state) & ABITS) == WBIT)
-                return 0L;
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
+        long s, m, next;
+        while ((m = (s = state) & ABITS) != WBIT) {
+            if (m < RFULL) {
+                if (casState(s, next = s + RUNIT))
                     return next;
             }
             else if ((next = tryIncReaderOverflow(s)) != 0L)
                 return next;
         }
+        return 0L;
     }
 
     /**
@@ -452,11 +567,12 @@
      *
      * @param time the maximum time to wait for the lock
      * @param unit the time unit of the {@code time} argument
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a read stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
      */
+    @ReservedStackAccess
     public long tryReadLock(long time, TimeUnit unit)
         throws InterruptedException {
         long s, m, next, deadline;
@@ -464,7 +580,7 @@
         if (!Thread.interrupted()) {
             if ((m = (s = state) & ABITS) != WBIT) {
                 if (m < RFULL) {
-                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
+                    if (casState(s, next = s + RUNIT))
                         return next;
                 }
                 else if ((next = tryIncReaderOverflow(s)) != 0L)
@@ -486,14 +602,20 @@
      * Behavior under interruption matches that specified
      * for method {@link Lock#lockInterruptibly()}.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a read stamp that can be used to unlock or convert mode
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
      */
+    @ReservedStackAccess
     public long readLockInterruptibly() throws InterruptedException {
-        long next;
-        if (!Thread.interrupted() &&
-            (next = acquireRead(true, 0L)) != INTERRUPTED)
+        long s, next;
+        if (!Thread.interrupted()
+            // bypass acquireRead on common uncontended case
+            && ((whead == wtail
+                 && ((s = state) & ABITS) < RFULL
+                 && casState(s, next = s + RUNIT))
+                ||
+                (next = acquireRead(true, 0L)) != INTERRUPTED))
             return next;
         throw new InterruptedException();
     }
@@ -502,7 +624,7 @@
      * Returns a stamp that can later be validated, or zero
      * if exclusively locked.
      *
-     * @return a stamp, or zero if exclusively locked
+     * @return a valid optimistic read stamp, or zero if exclusively locked
      */
     public long tryOptimisticRead() {
         long s;
@@ -522,11 +644,29 @@
      * since issuance of the given stamp; else false
      */
     public boolean validate(long stamp) {
-        U.loadFence();
+        VarHandle.acquireFence();
         return (stamp & SBITS) == (state & SBITS);
     }
 
     /**
+     * Returns an unlocked state, incrementing the version and
+     * avoiding special failure value 0L.
+     *
+     * @param s a write-locked state (or stamp)
+     */
+    private static long unlockWriteState(long s) {
+        return ((s += WBIT) == 0L) ? ORIGIN : s;
+    }
+
+    private long unlockWriteInternal(long s) {
+        long next; WNode h;
+        STATE.setVolatile(this, next = unlockWriteState(s));
+        if ((h = whead) != null && h.status != 0)
+            release(h);
+        return next;
+    }
+
+    /**
      * If the lock state matches the given stamp, releases the
      * exclusive lock.
      *
@@ -534,13 +674,11 @@
      * @throws IllegalMonitorStateException if the stamp does
      * not match the current state of this lock
      */
+    @ReservedStackAccess
     public void unlockWrite(long stamp) {
-        WNode h;
         if (state != stamp || (stamp & WBIT) == 0L)
             throw new IllegalMonitorStateException();
-        U.putLongVolatile(this, STATE, (stamp += WBIT) == 0L ? ORIGIN : stamp);
-        if ((h = whead) != null && h.status != 0)
-            release(h);
+        unlockWriteInternal(stamp);
     }
 
     /**
@@ -551,22 +689,23 @@
      * @throws IllegalMonitorStateException if the stamp does
      * not match the current state of this lock
      */
+    @ReservedStackAccess
     public void unlockRead(long stamp) {
         long s, m; WNode h;
-        for (;;) {
-            if (((s = state) & SBITS) != (stamp & SBITS) ||
-                (stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT)
-                throw new IllegalMonitorStateException();
+        while (((s = state) & SBITS) == (stamp & SBITS)
+               && (stamp & RBITS) > 0L
+               && ((m = s & RBITS) > 0L)) {
             if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
+                if (casState(s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
-                    break;
+                    return;
                 }
             }
             else if (tryDecReaderOverflow(s) != 0L)
-                break;
+                return;
         }
+        throw new IllegalMonitorStateException();
     }
 
     /**
@@ -577,32 +716,12 @@
      * @throws IllegalMonitorStateException if the stamp does
      * not match the current state of this lock
      */
+    @ReservedStackAccess
     public void unlock(long stamp) {
-        long a = stamp & ABITS, m, s; WNode h;
-        while (((s = state) & SBITS) == (stamp & SBITS)) {
-            if ((m = s & ABITS) == 0L)
-                break;
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return;
-            }
-            else if (a == 0L || a >= WBIT)
-                break;
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
-                    if (m == RUNIT && (h = whead) != null && h.status != 0)
-                        release(h);
-                    return;
-                }
-            }
-            else if (tryDecReaderOverflow(s) != 0L)
-                return;
-        }
-        throw new IllegalMonitorStateException();
+        if ((stamp & WBIT) != 0L)
+            unlockWrite(stamp);
+        else
+            unlockRead(stamp);
     }
 
     /**
@@ -623,7 +742,7 @@
             if ((m = s & ABITS) == 0L) {
                 if (a != 0L)
                     break;
-                if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
+                if ((next = tryWriteLock(s)) != 0L)
                     return next;
             }
             else if (m == WBIT) {
@@ -632,9 +751,10 @@
                 return stamp;
             }
             else if (m == RUNIT && a != 0L) {
-                if (U.compareAndSwapLong(this, STATE, s,
-                                         next = s - RUNIT + WBIT))
+                if (casState(s, next = s - RUNIT + WBIT)) {
+                    VarHandle.storeStoreFence();
                     return next;
+                }
             }
             else
                 break;
@@ -654,30 +774,32 @@
      * @return a valid read stamp, or zero on failure
      */
     public long tryConvertToReadLock(long stamp) {
-        long a = stamp & ABITS, m, s, next; WNode h;
+        long a, s, next; WNode h;
         while (((s = state) & SBITS) == (stamp & SBITS)) {
-            if ((m = s & ABITS) == 0L) {
-                if (a != 0L)
+            if ((a = stamp & ABITS) >= WBIT) {
+                // write stamp
+                if (s != stamp)
                     break;
-                else if (m < RFULL) {
-                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
+                STATE.setVolatile(this, next = unlockWriteState(s) + RUNIT);
+                if ((h = whead) != null && h.status != 0)
+                    release(h);
+                return next;
+            }
+            else if (a == 0L) {
+                // optimistic read stamp
+                if ((s & ABITS) < RFULL) {
+                    if (casState(s, next = s + RUNIT))
                         return next;
                 }
                 else if ((next = tryIncReaderOverflow(s)) != 0L)
                     return next;
             }
-            else if (m == WBIT) {
-                if (a != m)
+            else {
+                // already a read stamp
+                if ((s & ABITS) == 0L)
                     break;
-                U.putLongVolatile(this, STATE, next = s + (WBIT + RUNIT));
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return next;
-            }
-            else if (a != 0L && a < WBIT)
                 return stamp;
-            else
-                break;
+            }
         }
         return 0L;
     }
@@ -693,29 +815,22 @@
      * @return a valid optimistic read stamp, or zero on failure
      */
     public long tryConvertToOptimisticRead(long stamp) {
-        long a = stamp & ABITS, m, s, next; WNode h;
-        U.loadFence();
-        for (;;) {
-            if (((s = state) & SBITS) != (stamp & SBITS))
-                break;
-            if ((m = s & ABITS) == 0L) {
-                if (a != 0L)
+        long a, m, s, next; WNode h;
+        VarHandle.acquireFence();
+        while (((s = state) & SBITS) == (stamp & SBITS)) {
+            if ((a = stamp & ABITS) >= WBIT) {
+                // write stamp
+                if (s != stamp)
                     break;
-                return s;
+                return unlockWriteInternal(s);
             }
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                U.putLongVolatile(this, STATE,
-                                  next = (s += WBIT) == 0L ? ORIGIN : s);
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return next;
-            }
-            else if (a == 0L || a >= WBIT)
+            else if (a == 0L)
+                // already an optimistic read stamp
+                return stamp;
+            else if ((m = s & ABITS) == 0L) // invalid read stamp
                 break;
             else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
+                if (casState(s, next = s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return next & SBITS;
@@ -734,12 +849,11 @@
      *
      * @return {@code true} if the lock was held, else false
      */
+    @ReservedStackAccess
     public boolean tryUnlockWrite() {
-        long s; WNode h;
+        long s;
         if (((s = state) & WBIT) != 0L) {
-            U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-            if ((h = whead) != null && h.status != 0)
-                release(h);
+            unlockWriteInternal(s);
             return true;
         }
         return false;
@@ -752,11 +866,12 @@
      *
      * @return {@code true} if the read lock was held, else false
      */
+    @ReservedStackAccess
     public boolean tryUnlockRead() {
         long s, m; WNode h;
         while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
             if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
+                if (casState(s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return true;
@@ -800,6 +915,92 @@
     }
 
     /**
+     * Tells whether a stamp represents holding a lock exclusively.
+     * This method may be useful in conjunction with
+     * {@link #tryConvertToWriteLock}, for example: <pre> {@code
+     * long stamp = sl.tryOptimisticRead();
+     * try {
+     *   ...
+     *   stamp = sl.tryConvertToWriteLock(stamp);
+     *   ...
+     * } finally {
+     *   if (StampedLock.isWriteLockStamp(stamp))
+     *     sl.unlockWrite(stamp);
+     * }}</pre>
+     *
+     * @param stamp a stamp returned by a previous StampedLock operation
+     * @return {@code true} if the stamp was returned by a successful
+     *   write-lock operation
+     * @since 10
+     */
+    public static boolean isWriteLockStamp(long stamp) {
+        return (stamp & ABITS) == WBIT;
+    }
+
+    /**
+     * Tells whether a stamp represents holding a lock non-exclusively.
+     * This method may be useful in conjunction with
+     * {@link #tryConvertToReadLock}, for example: <pre> {@code
+     * long stamp = sl.tryOptimisticRead();
+     * try {
+     *   ...
+     *   stamp = sl.tryConvertToReadLock(stamp);
+     *   ...
+     * } finally {
+     *   if (StampedLock.isReadLockStamp(stamp))
+     *     sl.unlockRead(stamp);
+     * }}</pre>
+     *
+     * @param stamp a stamp returned by a previous StampedLock operation
+     * @return {@code true} if the stamp was returned by a successful
+     *   read-lock operation
+     * @since 10
+     */
+    public static boolean isReadLockStamp(long stamp) {
+        return (stamp & RBITS) != 0L;
+    }
+
+    /**
+     * Tells whether a stamp represents holding a lock.
+     * This method may be useful in conjunction with
+     * {@link #tryConvertToReadLock} and {@link #tryConvertToWriteLock},
+     * for example: <pre> {@code
+     * long stamp = sl.tryOptimisticRead();
+     * try {
+     *   ...
+     *   stamp = sl.tryConvertToReadLock(stamp);
+     *   ...
+     *   stamp = sl.tryConvertToWriteLock(stamp);
+     *   ...
+     * } finally {
+     *   if (StampedLock.isLockStamp(stamp))
+     *     sl.unlock(stamp);
+     * }}</pre>
+     *
+     * @param stamp a stamp returned by a previous StampedLock operation
+     * @return {@code true} if the stamp was returned by a successful
+     *   read-lock or write-lock operation
+     * @since 10
+     */
+    public static boolean isLockStamp(long stamp) {
+        return (stamp & ABITS) != 0L;
+    }
+
+    /**
+     * Tells whether a stamp represents a successful optimistic read.
+     *
+     * @param stamp a stamp returned by a previous StampedLock operation
+     * @return {@code true} if the stamp was returned by a successful
+     *   optimistic read operation, that is, a non-zero return from
+     *   {@link #tryOptimisticRead()} or
+     *   {@link #tryConvertToOptimisticRead(long)}
+     * @since 10
+     */
+    public static boolean isOptimisticReadStamp(long stamp) {
+        return (stamp & ABITS) == 0L && stamp != 0L;
+    }
+
+    /**
      * Queries the number of read locks held for this lock. This
      * method is designed for use in monitoring system state, not for
      * synchronization control.
@@ -832,32 +1033,30 @@
      * Returns a plain {@link Lock} view of this StampedLock in which
      * the {@link Lock#lock} method is mapped to {@link #readLock},
      * and similarly for other methods. The returned Lock does not
-     * support a {@link Condition}; method {@link
-     * Lock#newCondition()} throws {@code
-     * UnsupportedOperationException}.
+     * support a {@link Condition}; method {@link Lock#newCondition()}
+     * throws {@code UnsupportedOperationException}.
      *
      * @return the lock
      */
     public Lock asReadLock() {
         ReadLockView v;
-        return ((v = readLockView) != null ? v :
-                (readLockView = new ReadLockView()));
+        if ((v = readLockView) != null) return v;
+        return readLockView = new ReadLockView();
     }
 
     /**
      * Returns a plain {@link Lock} view of this StampedLock in which
      * the {@link Lock#lock} method is mapped to {@link #writeLock},
      * and similarly for other methods. The returned Lock does not
-     * support a {@link Condition}; method {@link
-     * Lock#newCondition()} throws {@code
-     * UnsupportedOperationException}.
+     * support a {@link Condition}; method {@link Lock#newCondition()}
+     * throws {@code UnsupportedOperationException}.
      *
      * @return the lock
      */
     public Lock asWriteLock() {
         WriteLockView v;
-        return ((v = writeLockView) != null ? v :
-                (writeLockView = new WriteLockView()));
+        if ((v = writeLockView) != null) return v;
+        return writeLockView = new WriteLockView();
     }
 
     /**
@@ -870,8 +1069,8 @@
      */
     public ReadWriteLock asReadWriteLock() {
         ReadWriteLockView v;
-        return ((v = readWriteLockView) != null ? v :
-                (readWriteLockView = new ReadWriteLockView()));
+        if ((v = readWriteLockView) != null) return v;
+        return readWriteLockView = new ReadWriteLockView();
     }
 
     // view classes
@@ -917,35 +1116,32 @@
     // Needed because view-class lock methods throw away stamps.
 
     final void unstampedUnlockWrite() {
-        WNode h; long s;
+        long s;
         if (((s = state) & WBIT) == 0L)
             throw new IllegalMonitorStateException();
-        U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-        if ((h = whead) != null && h.status != 0)
-            release(h);
+        unlockWriteInternal(s);
     }
 
     final void unstampedUnlockRead() {
-        for (;;) {
-            long s, m; WNode h;
-            if ((m = (s = state) & ABITS) == 0L || m >= WBIT)
-                throw new IllegalMonitorStateException();
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
+        long s, m; WNode h;
+        while ((m = (s = state) & RBITS) > 0L) {
+            if (m < RFULL) {
+                if (casState(s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
-                    break;
+                    return;
                 }
             }
             else if (tryDecReaderOverflow(s) != 0L)
-                break;
+                return;
         }
+        throw new IllegalMonitorStateException();
     }
 
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();
-        U.putLongVolatile(this, STATE, ORIGIN); // reset to unlocked state
+        STATE.setVolatile(this, ORIGIN); // reset to unlocked state
     }
 
     // internals
@@ -961,15 +1157,17 @@
     private long tryIncReaderOverflow(long s) {
         // assert (s & ABITS) >= RFULL;
         if ((s & ABITS) == RFULL) {
-            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
+            if (casState(s, s | RBITS)) {
                 ++readerOverflow;
-                U.putLongVolatile(this, STATE, s);
+                STATE.setVolatile(this, s);
                 return s;
             }
         }
-        else if ((LockSupport.nextSecondarySeed() &
-                  OVERFLOW_YIELD_RATE) == 0)
+        else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
             Thread.yield();
+        // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+        // else
+        //     Thread.onSpinWait();
         return 0L;
     }
 
@@ -982,7 +1180,7 @@
     private long tryDecReaderOverflow(long s) {
         // assert (s & ABITS) >= RFULL;
         if ((s & ABITS) == RFULL) {
-            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
+            if (casState(s, s | RBITS)) {
                 int r; long next;
                 if ((r = readerOverflow) > 0) {
                     readerOverflow = r - 1;
@@ -990,13 +1188,15 @@
                 }
                 else
                     next = s - RUNIT;
-                U.putLongVolatile(this, STATE, next);
+                STATE.setVolatile(this, next);
                 return next;
             }
         }
-        else if ((LockSupport.nextSecondarySeed() &
-                  OVERFLOW_YIELD_RATE) == 0)
+        else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
             Thread.yield();
+        // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+        // else
+        //     Thread.onSpinWait();
         return 0L;
     }
 
@@ -1010,14 +1210,14 @@
     private void release(WNode h) {
         if (h != null) {
             WNode q; Thread w;
-            U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
+            WSTATUS.compareAndSet(h, WAITING, 0);
             if ((q = h.next) == null || q.status == CANCELLED) {
                 for (WNode t = wtail; t != null && t != h; t = t.prev)
                     if (t.status <= 0)
                         q = t;
             }
             if (q != null && (w = q.thread) != null)
-                U.unpark(w);
+                LockSupport.unpark(w);
         }
     }
 
@@ -1035,25 +1235,26 @@
         for (int spins = -1;;) { // spin while enqueuing
             long m, s, ns;
             if ((m = (s = state) & ABITS) == 0L) {
-                if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
+                if ((ns = tryWriteLock(s)) != 0L)
                     return ns;
             }
             else if (spins < 0)
                 spins = (m == WBIT && wtail == whead) ? SPINS : 0;
             else if (spins > 0) {
-                if (LockSupport.nextSecondarySeed() >= 0)
-                    --spins;
+                --spins;
+                // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+                // Thread.onSpinWait();
             }
             else if ((p = wtail) == null) { // initialize queue
                 WNode hd = new WNode(WMODE, null);
-                if (U.compareAndSwapObject(this, WHEAD, null, hd))
+                if (WHEAD.weakCompareAndSet(this, null, hd))
                     wtail = hd;
             }
             else if (node == null)
                 node = new WNode(WMODE, p);
             else if (node.prev != p)
                 node.prev = p;
-            else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
+            else if (WTAIL.weakCompareAndSet(this, p, node)) {
                 p.next = node;
                 break;
             }
@@ -1067,11 +1268,10 @@
                     spins = HEAD_SPINS;
                 else if (spins < MAX_HEAD_SPINS)
                     spins <<= 1;
-                for (int k = spins;;) { // spin at head
+                for (int k = spins; k > 0; --k) { // spin at head
                     long s, ns;
                     if (((s = state) & ABITS) == 0L) {
-                        if (U.compareAndSwapLong(this, STATE, s,
-                                                 ns = s + WBIT)) {
+                        if ((ns = tryWriteLock(s)) != 0L) {
                             whead = node;
                             node.prev = null;
                             if (wasInterrupted)
@@ -1079,17 +1279,17 @@
                             return ns;
                         }
                     }
-                    else if (LockSupport.nextSecondarySeed() >= 0 &&
-                             --k <= 0)
-                        break;
+                    // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+                    // else
+                    //     Thread.onSpinWait();
                 }
             }
             else if (h != null) { // help release stale waiters
                 WNode c; Thread w;
                 while ((c = h.cowait) != null) {
-                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
+                    if (WCOWAIT.weakCompareAndSet(h, c, c.cowait) &&
                         (w = c.thread) != null)
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                 }
             }
             if (whead == h) {
@@ -1098,7 +1298,7 @@
                         (p = np).next = node;   // stale
                 }
                 else if ((ps = p.status) == 0)
-                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
+                    WSTATUS.compareAndSet(p, 0, WAITING);
                 else if (ps == CANCELLED) {
                     if ((pp = p.prev) != null) {
                         node.prev = pp;
@@ -1112,13 +1312,15 @@
                     else if ((time = deadline - System.nanoTime()) <= 0L)
                         return cancelWaiter(node, node, false);
                     Thread wt = Thread.currentThread();
-                    U.putObject(wt, PARKBLOCKER, this);
                     node.thread = wt;
                     if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
-                        whead == h && node.prev == p)
-                        U.park(false, time);  // emulate LockSupport.park
+                        whead == h && node.prev == p) {
+                        if (time == 0L)
+                            LockSupport.park(this);
+                        else
+                            LockSupport.parkNanos(this, time);
+                    }
                     node.thread = null;
-                    U.putObject(wt, PARKBLOCKER, null);
                     if (Thread.interrupted()) {
                         if (interruptible)
                             return cancelWaiter(node, node, true);
@@ -1146,7 +1348,7 @@
             if ((h = whead) == (p = wtail)) {
                 for (long m, s, ns;;) {
                     if ((m = (s = state) & ABITS) < RFULL ?
-                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
+                        casState(s, ns = s + RUNIT) :
                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                         if (wasInterrupted)
                             Thread.currentThread().interrupt();
@@ -1154,8 +1356,9 @@
                     }
                     else if (m >= WBIT) {
                         if (spins > 0) {
-                            if (LockSupport.nextSecondarySeed() >= 0)
-                                --spins;
+                            --spins;
+                            // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+                            // Thread.onSpinWait();
                         }
                         else {
                             if (spins == 0) {
@@ -1170,7 +1373,7 @@
             }
             if (p == null) { // initialize queue
                 WNode hd = new WNode(WMODE, null);
-                if (U.compareAndSwapObject(this, WHEAD, null, hd))
+                if (WHEAD.weakCompareAndSet(this, null, hd))
                     wtail = hd;
             }
             else if (node == null)
@@ -1178,27 +1381,30 @@
             else if (h == p || p.mode != RMODE) {
                 if (node.prev != p)
                     node.prev = p;
-                else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
+                else if (WTAIL.weakCompareAndSet(this, p, node)) {
                     p.next = node;
                     break;
                 }
             }
-            else if (!U.compareAndSwapObject(p, WCOWAIT,
-                                             node.cowait = p.cowait, node))
+            else if (!WCOWAIT.compareAndSet(p, node.cowait = p.cowait, node))
                 node.cowait = null;
             else {
                 for (;;) {
                     WNode pp, c; Thread w;
                     if ((h = whead) != null && (c = h.cowait) != null &&
-                        U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
+                        WCOWAIT.compareAndSet(h, c, c.cowait) &&
                         (w = c.thread) != null) // help release
-                        U.unpark(w);
+                        LockSupport.unpark(w);
+                    if (Thread.interrupted()) {
+                        if (interruptible)
+                            return cancelWaiter(node, p, true);
+                        wasInterrupted = true;
+                    }
                     if (h == (pp = p.prev) || h == p || pp == null) {
                         long m, s, ns;
                         do {
                             if ((m = (s = state) & ABITS) < RFULL ?
-                                U.compareAndSwapLong(this, STATE, s,
-                                                     ns = s + RUNIT) :
+                                casState(s, ns = s + RUNIT) :
                                 (m < WBIT &&
                                  (ns = tryIncReaderOverflow(s)) != 0L)) {
                                 if (wasInterrupted)
@@ -1221,18 +1427,15 @@
                             return cancelWaiter(node, p, false);
                         }
                         Thread wt = Thread.currentThread();
-                        U.putObject(wt, PARKBLOCKER, this);
                         node.thread = wt;
                         if ((h != pp || (state & ABITS) == WBIT) &&
-                            whead == h && p.prev == pp)
-                            U.park(false, time);
-                        node.thread = null;
-                        U.putObject(wt, PARKBLOCKER, null);
-                        if (Thread.interrupted()) {
-                            if (interruptible)
-                                return cancelWaiter(node, p, true);
-                            wasInterrupted = true;
+                            whead == h && p.prev == pp) {
+                            if (time == 0L)
+                                LockSupport.park(this);
+                            else
+                                LockSupport.parkNanos(this, time);
                         }
+                        node.thread = null;
                     }
                 }
             }
@@ -1248,32 +1451,33 @@
                 for (int k = spins;;) { // spin at head
                     long m, s, ns;
                     if ((m = (s = state) & ABITS) < RFULL ?
-                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
+                        casState(s, ns = s + RUNIT) :
                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                         WNode c; Thread w;
                         whead = node;
                         node.prev = null;
                         while ((c = node.cowait) != null) {
-                            if (U.compareAndSwapObject(node, WCOWAIT,
-                                                       c, c.cowait) &&
+                            if (WCOWAIT.compareAndSet(node, c, c.cowait) &&
                                 (w = c.thread) != null)
-                                U.unpark(w);
+                                LockSupport.unpark(w);
                         }
                         if (wasInterrupted)
                             Thread.currentThread().interrupt();
                         return ns;
                     }
-                    else if (m >= WBIT &&
-                             LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
+                    else if (m >= WBIT && --k <= 0)
                         break;
+                    // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
+                    // else
+                    //     Thread.onSpinWait();
                 }
             }
             else if (h != null) {
                 WNode c; Thread w;
                 while ((c = h.cowait) != null) {
-                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
+                    if (WCOWAIT.compareAndSet(h, c, c.cowait) &&
                         (w = c.thread) != null)
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                 }
             }
             if (whead == h) {
@@ -1282,7 +1486,7 @@
                         (p = np).next = node;   // stale
                 }
                 else if ((ps = p.status) == 0)
-                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
+                    WSTATUS.compareAndSet(p, 0, WAITING);
                 else if (ps == CANCELLED) {
                     if ((pp = p.prev) != null) {
                         node.prev = pp;
@@ -1296,14 +1500,16 @@
                     else if ((time = deadline - System.nanoTime()) <= 0L)
                         return cancelWaiter(node, node, false);
                     Thread wt = Thread.currentThread();
-                    U.putObject(wt, PARKBLOCKER, this);
                     node.thread = wt;
                     if (p.status < 0 &&
                         (p != h || (state & ABITS) == WBIT) &&
-                        whead == h && node.prev == p)
-                        U.park(false, time);
+                        whead == h && node.prev == p) {
+                            if (time == 0L)
+                                LockSupport.park(this);
+                            else
+                                LockSupport.parkNanos(this, time);
+                    }
                     node.thread = null;
-                    U.putObject(wt, PARKBLOCKER, null);
                     if (Thread.interrupted()) {
                         if (interruptible)
                             return cancelWaiter(node, node, true);
@@ -1325,7 +1531,7 @@
      * AbstractQueuedSynchronizer (see its detailed explanation in AQS
      * internal documentation).
      *
-     * @param node if nonnull, the waiter
+     * @param node if non-null, the waiter
      * @param group either node or the group node is cowaiting with
      * @param interrupted if already interrupted
      * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
@@ -1337,7 +1543,7 @@
             // unsplice cancelled nodes from group
             for (WNode p = group, q; (q = p.cowait) != null;) {
                 if (q.status == CANCELLED) {
-                    U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
+                    WCOWAIT.compareAndSet(p, q, q.cowait);
                     p = group; // restart
                 }
                 else
@@ -1346,7 +1552,7 @@
             if (group == node) {
                 for (WNode r = group.cowait; r != null; r = r.cowait) {
                     if ((w = r.thread) != null)
-                        U.unpark(w);       // wake up uncancelled co-waiters
+                        LockSupport.unpark(w); // wake up uncancelled co-waiters
                 }
                 for (WNode pred = node.prev; pred != null; ) { // unsplice
                     WNode succ, pp;        // find valid successor
@@ -1357,23 +1563,23 @@
                             if (t.status != CANCELLED)
                                 q = t;     // don't link if succ cancelled
                         if (succ == q ||   // ensure accurate successor
-                            U.compareAndSwapObject(node, WNEXT,
-                                                   succ, succ = q)) {
+                            WNEXT.compareAndSet(node, succ, succ = q)) {
                             if (succ == null && node == wtail)
-                                U.compareAndSwapObject(this, WTAIL, node, pred);
+                                WTAIL.compareAndSet(this, node, pred);
                             break;
                         }
                     }
                     if (pred.next == node) // unsplice pred link
-                        U.compareAndSwapObject(pred, WNEXT, node, succ);
+                        WNEXT.compareAndSet(pred, node, succ);
                     if (succ != null && (w = succ.thread) != null) {
+                        // wake up succ to observe new pred
                         succ.thread = null;
-                        U.unpark(w);       // wake up succ to observe new pred
+                        LockSupport.unpark(w);
                     }
                     if (pred.status != CANCELLED || (pp = pred.prev) == null)
                         break;
                     node.prev = pp;        // repeat if new pred wrong/cancelled
-                    U.compareAndSwapObject(pp, WNEXT, pred, succ);
+                    WNEXT.compareAndSet(pp, pred, succ);
                     pred = pp;
                 }
             }
@@ -1397,36 +1603,24 @@
         return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
     }
 
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long WHEAD;
-    private static final long WTAIL;
-    private static final long WNEXT;
-    private static final long WSTATUS;
-    private static final long WCOWAIT;
-    private static final long PARKBLOCKER;
-
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle WHEAD;
+    private static final VarHandle WTAIL;
+    private static final VarHandle WNEXT;
+    private static final VarHandle WSTATUS;
+    private static final VarHandle WCOWAIT;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("state"));
-            WHEAD = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("whead"));
-            WTAIL = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("wtail"));
-
-            WSTATUS = U.objectFieldOffset
-                (WNode.class.getDeclaredField("status"));
-            WNEXT = U.objectFieldOffset
-                (WNode.class.getDeclaredField("next"));
-            WCOWAIT = U.objectFieldOffset
-                (WNode.class.getDeclaredField("cowait"));
-
-            PARKBLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(StampedLock.class, "state", long.class);
+            WHEAD = l.findVarHandle(StampedLock.class, "whead", WNode.class);
+            WTAIL = l.findVarHandle(StampedLock.class, "wtail", WNode.class);
+            WSTATUS = l.findVarHandle(WNode.class, "status", int.class);
+            WNEXT = l.findVarHandle(WNode.class, "next", WNode.class);
+            WCOWAIT = l.findVarHandle(WNode.class, "cowait", WNode.class);
         } catch (ReflectiveOperationException e) {
-            throw new Error(e);
+            throw new ExceptionInInitializerError(e);
         }
     }
 }
diff --git a/ojluni/src/main/java/java/util/concurrent/package-info.java b/ojluni/src/main/java/java/util/concurrent/package-info.java
index 387068d..0e992a2 100644
--- a/ojluni/src/main/java/java/util/concurrent/package-info.java
+++ b/ojluni/src/main/java/java/util/concurrent/package-info.java
@@ -200,7 +200,7 @@
  * concurrent collection is thread-safe, but not governed by a
  * single exclusion lock.  In the particular case of
  * ConcurrentHashMap, it safely permits any number of
- * concurrent reads as well as a tunable number of concurrent
+ * concurrent reads as well as a large number of concurrent
  * writes.  "Synchronized" classes can be useful when you need
  * to prevent all access to a collection via a single lock, at
  * the expense of poorer scalability.  In other cases in which
@@ -262,7 +262,6 @@
  *
  * </ul>
  *
- *
  * The methods of all classes in {@code java.util.concurrent} and its
  * subpackages extend these guarantees to higher-level
  * synchronization.  In particular:
diff --git a/ojluni/src/main/java/java/util/function/Predicate.java b/ojluni/src/main/java/java/util/function/Predicate.java
index e2f448b..b34febb 100644
--- a/ojluni/src/main/java/java/util/function/Predicate.java
+++ b/ojluni/src/main/java/java/util/function/Predicate.java
@@ -116,4 +116,25 @@
                 ? Objects::isNull
                 : object -> targetRef.equals(object);
     }
+
+    /**
+     * Returns a predicate that is the negation of the supplied predicate.
+     * This is accomplished by returning result of the calling
+     * {@code target.negate()}.
+     *
+     * @param <T>     the type of arguments to the specified predicate
+     * @param target  predicate to negate
+     *
+     * @return a predicate that negates the results of the supplied
+     *         predicate
+     *
+     * @throws NullPointerException if target is null
+     *
+     * @since 11
+     */
+    @SuppressWarnings("unchecked")
+    static <T> Predicate<T> not(Predicate<? super T> target) {
+        Objects.requireNonNull(target);
+        return (Predicate<T>)target.negate();
+    }
 }
diff --git a/ojluni/src/main/java/java/util/function/package-info.java b/ojluni/src/main/java/java/util/function/package-info.java
index 31a1c46..905fa7d 100644
--- a/ojluni/src/main/java/java/util/function/package-info.java
+++ b/ojluni/src/main/java/java/util/function/package-info.java
@@ -74,7 +74,7 @@
  *     {@link java.util.function.Function} (unary function from {@code T} to {@code R}),
  *     {@link java.util.function.Consumer} (unary function from {@code T} to {@code void}),
  *     {@link java.util.function.Predicate} (unary function from {@code T} to {@code boolean}),
- *     and {@link java.util.function.Supplier} (nilary function to {@code R}).
+ *     and {@link java.util.function.Supplier} (nullary function to {@code R}).
  *     </li>
  *
  *     <li>Function shapes have a natural arity based on how they are most
diff --git a/ojluni/src/main/java/java/util/jar/JarEntry.java b/ojluni/src/main/java/java/util/jar/JarEntry.java
index b0e6841..a483842 100644
--- a/ojluni/src/main/java/java/util/jar/JarEntry.java
+++ b/ojluni/src/main/java/java/util/jar/JarEntry.java
@@ -32,6 +32,8 @@
 
 /**
  * This class is used to represent a JAR file entry.
+ *
+ * @since 1.2
  */
 public
 class JarEntry extends ZipEntry {
@@ -126,4 +128,25 @@
     public CodeSigner[] getCodeSigners() {
         return signers == null ? null : signers.clone();
     }
+
+    /**
+     * Returns the real name of this {@code JarEntry}.
+     *
+     * If this {@code JarEntry} is an entry of a
+     * <a href="JarFile.html#multirelease">multi-release jar file</a> and the
+     * {@code JarFile} is configured to be processed as such, the name returned
+     * by this method is the path name of the versioned entry that the
+     * {@code JarEntry} represents, rather than the path name of the base entry
+     * that {@link #getName()} returns. If the {@code JarEntry} does not represent
+     * a versioned entry of a multi-release {@code JarFile} or the {@code JarFile}
+     * is not configured for processing a multi-release jar file, this method
+     * returns the same name that {@link #getName()} returns.
+     *
+     * @return the real name of the JarEntry
+     *
+     * @since 10
+     */
+    public String getRealName() {
+        return super.getName();
+    }
 }
diff --git a/ojluni/src/main/java/java/util/jar/Pack200.java b/ojluni/src/main/java/java/util/jar/Pack200.java
index 26b2ce3..9211f0a 100644
--- a/ojluni/src/main/java/java/util/jar/Pack200.java
+++ b/ojluni/src/main/java/java/util/jar/Pack200.java
@@ -96,7 +96,7 @@
  * The deployment applications can use "Accept-Encoding=pack200-gzip". This
  * indicates to the server that the client application desires a version of
  * the file encoded with Pack200 and further compressed with gzip. Please
- * refer to  <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/deployment/deployment-guide/pack200.html">Java Deployment Guide</a> for more details and
+ * refer to  <a href="{@docRoot}/../technotes/guides/deployment/deployment-guide/pack200.html">Java Deployment Guide</a> for more details and
  * techniques.
  * <p>
  * Unless otherwise noted, passing a <tt>null</tt> argument to a constructor or
diff --git a/ojluni/src/main/java/java/util/logging/LogManager.java b/ojluni/src/main/java/java/util/logging/LogManager.java
index 0d51b0f..e8f9027 100644
--- a/ojluni/src/main/java/java/util/logging/LogManager.java
+++ b/ojluni/src/main/java/java/util/logging/LogManager.java
@@ -759,7 +759,8 @@
             }
             LoggerWeakRef ref = namedLoggers.get(name);
             if (ref != null) {
-                if (ref.get() == null) {
+                // Android-changed: Use refersTo().
+                if (ref.refersTo(null)) {
                     // It's possible that the Logger was GC'ed after a
                     // drainLoggerRefQueueBounded() call above so allow
                     // a new one to be registered.
diff --git a/ojluni/src/main/java/java/util/regex/MatchResult.java b/ojluni/src/main/java/java/util/regex/MatchResult.java
index 4f42eae..1e69638 100644
--- a/ojluni/src/main/java/java/util/regex/MatchResult.java
+++ b/ojluni/src/main/java/java/util/regex/MatchResult.java
@@ -31,7 +31,7 @@
  * <p>This interface contains query methods used to determine the
  * results of a match against a regular expression. The match boundaries,
  * groups and group boundaries can be seen but not modified through
- * a <code>MatchResult</code>.
+ * a {@code MatchResult}.
  *
  * @author  Michael McCloskey
  * @see Matcher
@@ -56,14 +56,14 @@
      *
      * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
      * to right, starting at one.  Group zero denotes the entire pattern, so
-     * the expression <i>m.</i><tt>start(0)</tt> is equivalent to
-     * <i>m.</i><tt>start()</tt>.  </p>
+     * the expression <i>m.</i>{@code start(0)} is equivalent to
+     * <i>m.</i>{@code start()}.  </p>
      *
      * @param  group
      *         The index of a capturing group in this matcher's pattern
      *
      * @return  The index of the first character captured by the group,
-     *          or <tt>-1</tt> if the match was successful but the group
+     *          or {@code -1} if the match was successful but the group
      *          itself did not match anything
      *
      * @throws  IllegalStateException
@@ -93,14 +93,14 @@
      *
      * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
      * to right, starting at one.  Group zero denotes the entire pattern, so
-     * the expression <i>m.</i><tt>end(0)</tt> is equivalent to
-     * <i>m.</i><tt>end()</tt>.  </p>
+     * the expression <i>m.</i>{@code end(0)} is equivalent to
+     * <i>m.</i>{@code end()}.  </p>
      *
      * @param  group
      *         The index of a capturing group in this matcher's pattern
      *
      * @return  The offset after the last character captured by the group,
-     *          or <tt>-1</tt> if the match was successful
+     *          or {@code -1} if the match was successful
      *          but the group itself did not match anything
      *
      * @throws  IllegalStateException
@@ -117,11 +117,11 @@
      * Returns the input subsequence matched by the previous match.
      *
      * <p> For a matcher <i>m</i> with input sequence <i>s</i>,
-     * the expressions <i>m.</i><tt>group()</tt> and
-     * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt>&nbsp;<i>m.</i><tt>end())</tt>
+     * the expressions <i>m.</i>{@code group()} and
+     * <i>s.</i>{@code substring(}<i>m.</i>{@code start(),}&nbsp;<i>m.</i>{@code end())}
      * are equivalent.  </p>
      *
-     * <p> Note that some patterns, for example <tt>a*</tt>, match the empty
+     * <p> Note that some patterns, for example {@code a*}, match the empty
      * string.  This method will return the empty string when the pattern
      * successfully matches the empty string in the input.  </p>
      *
@@ -139,18 +139,19 @@
      * previous match operation.
      *
      * <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
-     * <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
-     * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt>&nbsp;<i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
+     * <i>g</i>, the expressions <i>m.</i>{@code group(}<i>g</i>{@code )} and
+     * <i>s.</i>{@code substring(}<i>m.</i>{@code start(}<i>g</i>{@code
+     * ),}&nbsp;<i>m.</i>{@code end(}<i>g</i>{@code ))}
      * are equivalent.  </p>
      *
      * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
      * to right, starting at one.  Group zero denotes the entire pattern, so
-     * the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
+     * the expression {@code m.group(0)} is equivalent to {@code m.group()}.
      * </p>
      *
      * <p> If the match was successful but the group specified failed to match
-     * any part of the input sequence, then <tt>null</tt> is returned. Note
-     * that some groups, for example <tt>(a*)</tt>, match the empty string.
+     * any part of the input sequence, then {@code null} is returned. Note
+     * that some groups, for example {@code (a*)}, match the empty string.
      * This method will return the empty string when such a group successfully
      * matches the empty string in the input.  </p>
      *
@@ -158,7 +159,7 @@
      *         The index of a capturing group in this matcher's pattern
      *
      * @return  The (possibly empty) subsequence captured by the group
-     *          during the previous match, or <tt>null</tt> if the group
+     *          during the previous match, or {@code null} if the group
      *          failed to match part of the input
      *
      * @throws  IllegalStateException
diff --git a/ojluni/src/main/java/java/util/regex/Pattern.java b/ojluni/src/main/java/java/util/regex/Pattern.java
index bd7ba5b..428087c 100644
--- a/ojluni/src/main/java/java/util/regex/Pattern.java
+++ b/ojluni/src/main/java/java/util/regex/Pattern.java
@@ -675,6 +675,16 @@
  * available through the same <tt>\p{</tt><i>prop</i><tt>}</tt> syntax where
  * the specified property has the name <tt>java<i>methodname</i></tt></a>.
  *
+ * <h3> Behavior starting from API level 10 (Android 2.3) </h3>
+ *
+ * <p> Starting from Android 2.3 Gingerbread, ICU4C becomes the backend of the regular expression
+ * implementation. Android could behave differently compared with other regex implementation, e.g.
+ * literal right brace ('}') has to be escaped on Android.</p>
+ *
+ * <p> Some other behavior differences can be found in the
+ * <a href="https://unicode-org.github.io/icu/userguide/strings/regexp.html#differences-with-java-regular-expressions">
+ * ICU documentation</a>. </p>
+ *
  * <h3> Comparison to Perl 5 </h3>
  *
  * <p>The <code>Pattern</code> engine performs traditional NFA-based matching
@@ -1215,8 +1225,15 @@
             return null;
         }
         char ch = re.charAt(0);
-        if (len == 1 && FASTSPLIT_METACHARACTERS.indexOf(ch) == -1) {
-            // We're looking for a single non-metacharacter. Easy.
+        if (len == 1) {
+            if (Character.isSurrogate(ch)) {
+                // Single surrogate is an invalid UTF-16 sequence.
+                return null;
+            } else if (FASTSPLIT_METACHARACTERS.indexOf(ch) != -1) {
+                // We don't allow a single metacharacter.
+                return null;
+            }
+            // pass through
         } else if (len == 2 && ch == '\\') {
             // We're looking for a quoted character.
             // Quoted metacharacters are effectively single non-metacharacters.
diff --git a/ojluni/src/main/java/java/util/regex/PatternSyntaxException.java b/ojluni/src/main/java/java/util/regex/PatternSyntaxException.java
index d6ac72a..999f34b 100644
--- a/ojluni/src/main/java/java/util/regex/PatternSyntaxException.java
+++ b/ojluni/src/main/java/java/util/regex/PatternSyntaxException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,6 @@
 
 package java.util.regex;
 
-import sun.security.action.GetPropertyAction;
-
-
 /**
  * Unchecked exception thrown to indicate a syntax error in a
  * regular-expression pattern.
@@ -57,7 +54,7 @@
      *
      * @param  index
      *         The approximate index in the pattern of the error,
-     *         or <tt>-1</tt> if the index is not known
+     *         or {@code -1} if the index is not known
      */
     public PatternSyntaxException(String desc, String regex, int index) {
         this.desc = desc;
@@ -69,7 +66,7 @@
      * Retrieves the error index.
      *
      * @return  The approximate index in the pattern of the error,
-     *         or <tt>-1</tt> if the index is not known
+     *         or {@code -1} if the index is not known
      */
     public int getIndex() {
         return index;
@@ -93,10 +90,6 @@
         return pattern;
     }
 
-    private static final String nl =
-        java.security.AccessController
-            .doPrivileged(new GetPropertyAction("line.separator"));
-
     /**
      * Returns a multi-line string containing the description of the syntax
      * error and its index, the erroneous regular-expression pattern, and a
@@ -105,16 +98,16 @@
      * @return  The full detail message
      */
     public String getMessage() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append(desc);
         if (index >= 0) {
             sb.append(" near index ");
             sb.append(index);
         }
-        sb.append(nl);
+        sb.append(System.lineSeparator());
         sb.append(pattern);
-        if (index >= 0) {
-            sb.append(nl);
+        if (index >= 0 && pattern != null && index < pattern.length()) {
+            sb.append(System.lineSeparator());
             for (int i = 0; i < index; i++) sb.append(' ');
             sb.append('^');
         }
diff --git a/ojluni/src/main/java/java/util/stream/BaseStream.java b/ojluni/src/main/java/java/util/stream/BaseStream.java
index 35d46e0..0328b25 100644
--- a/ojluni/src/main/java/java/util/stream/BaseStream.java
+++ b/ojluni/src/main/java/java/util/stream/BaseStream.java
@@ -53,7 +53,7 @@
  * parallelism, which governs the behavior of all stream types.
  *
  * @param <T> the type of the stream elements
- * @param <S> the type of of the stream implementing {@code BaseStream}
+ * @param <S> the type of the stream implementing {@code BaseStream}
  * @since 1.8
  * @see Stream
  * @see IntStream
@@ -79,6 +79,14 @@
      * <p>This is a <a href="package-summary.html#StreamOps">terminal
      * operation</a>.
      *
+     * <p>
+     * The returned spliterator should report the set of characteristics derived
+     * from the stream pipeline (namely the characteristics derived from the
+     * stream source spliterator and the intermediate operations).
+     * Implementations may report a sub-set of those characteristics.  For
+     * example, it may be too expensive to compute the entire set for some or
+     * all possible stream pipelines.
+     *
      * @return the element spliterator for this stream
      */
     Spliterator<T> spliterator();
diff --git a/ojluni/src/main/java/java/util/stream/Collectors.java b/ojluni/src/main/java/java/util/stream/Collectors.java
index a338ec2..26d98bf 100644
--- a/ojluni/src/main/java/java/util/stream/Collectors.java
+++ b/ojluni/src/main/java/java/util/stream/Collectors.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 import java.util.AbstractMap;
 import java.util.AbstractSet;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -66,36 +65,37 @@
  * common mutable reduction tasks:
  *
  * <pre>{@code
- *     // Accumulate names into a List
- *     List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
+ * // Accumulate names into a List
+ * List<String> list = people.stream()
+ *   .map(Person::getName)
+ *   .collect(Collectors.toList());
  *
- *     // Accumulate names into a TreeSet
- *     Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
+ * // Accumulate names into a TreeSet
+ * Set<String> set = people.stream()
+ *   .map(Person::getName)
+ *   .collect(Collectors.toCollection(TreeSet::new));
  *
- *     // Convert elements to strings and concatenate them, separated by commas
- *     String joined = things.stream()
- *                           .map(Object::toString)
- *                           .collect(Collectors.joining(", "));
+ * // Convert elements to strings and concatenate them, separated by commas
+ * String joined = things.stream()
+ *   .map(Object::toString)
+ *   .collect(Collectors.joining(", "));
  *
- *     // Compute sum of salaries of employee
- *     int total = employees.stream()
- *                          .collect(Collectors.summingInt(Employee::getSalary)));
+ * // Compute sum of salaries of employee
+ * int total = employees.stream()
+ *   .collect(Collectors.summingInt(Employee::getSalary));
  *
- *     // Group employees by department
- *     Map<Department, List<Employee>> byDept
- *         = employees.stream()
- *                    .collect(Collectors.groupingBy(Employee::getDepartment));
+ * // Group employees by department
+ * Map<Department, List<Employee>> byDept = employees.stream()
+ *   .collect(Collectors.groupingBy(Employee::getDepartment));
  *
- *     // Compute sum of salaries by department
- *     Map<Department, Integer> totalByDept
- *         = employees.stream()
- *                    .collect(Collectors.groupingBy(Employee::getDepartment,
- *                                                   Collectors.summingInt(Employee::getSalary)));
+ * // Compute sum of salaries by department
+ * Map<Department, Integer> totalByDept = employees.stream()
+ *   .collect(Collectors.groupingBy(Employee::getDepartment,
+ *                                  Collectors.summingInt(Employee::getSalary)));
  *
- *     // Partition students into passing and failing
- *     Map<Boolean, List<Student>> passingFailing =
- *         students.stream()
- *                 .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
+ * // Partition students into passing and failing
+ * Map<Boolean, List<Student>> passingFailing = students.stream()
+ *   .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
  *
  * }</pre>
  *
@@ -116,21 +116,69 @@
             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
                                                      Collector.Characteristics.IDENTITY_FINISH));
     static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
+    static final Set<Collector.Characteristics> CH_UNORDERED_NOID
+            = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED));
 
     private Collectors() { }
 
     /**
-     * Returns a merge function, suitable for use in
-     * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
-     * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always
-     * throws {@code IllegalStateException}.  This can be used to enforce the
-     * assumption that the elements being collected are distinct.
+     * Construct an {@code IllegalStateException} with appropriate message.
      *
-     * @param <T> the type of input arguments to the merge function
-     * @return a merge function which always throw {@code IllegalStateException}
+     * @param k the duplicate key
+     * @param u 1st value to be accumulated/merged
+     * @param v 2nd value to be accumulated/merged
      */
-    private static <T> BinaryOperator<T> throwingMerger() {
-        return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
+    private static IllegalStateException duplicateKeyException(
+            Object k, Object u, Object v) {
+        return new IllegalStateException(String.format(
+            "Duplicate key %s (attempted merging values %s and %s)",
+            k, u, v));
+    }
+
+    /**
+     * {@code BinaryOperator<Map>} that merges the contents of its right
+     * argument into its left argument, throwing {@code IllegalStateException}
+     * if duplicate keys are encountered.
+     *
+     * @param <K> type of the map keys
+     * @param <V> type of the map values
+     * @param <M> type of the map
+     * @return a merge function for two maps
+     */
+    private static <K, V, M extends Map<K,V>>
+    BinaryOperator<M> uniqKeysMapMerger() {
+        return (m1, m2) -> {
+            for (Map.Entry<K,V> e : m2.entrySet()) {
+                K k = e.getKey();
+                V v = Objects.requireNonNull(e.getValue());
+                V u = m1.putIfAbsent(k, v);
+                if (u != null) throw duplicateKeyException(k, u, v);
+            }
+            return m1;
+        };
+    }
+
+    /**
+     * {@code BiConsumer<Map, T>} that accumulates (key, value) pairs
+     * extracted from elements into the map, throwing {@code IllegalStateException}
+     * if duplicate keys are encountered.
+     *
+     * @param keyMapper a function that maps an element into a key
+     * @param valueMapper a function that maps an element into a value
+     * @param <T> type of elements
+     * @param <K> type of map keys
+     * @param <V> type of map values
+     * @return an accumulating consumer
+     */
+    private static <T, K, V>
+    BiConsumer<Map<K, V>, T> uniqKeysMapAccumulator(Function<? super T, ? extends K> keyMapper,
+                                                    Function<? super T, ? extends V> valueMapper) {
+        return (map, element) -> {
+            K k = keyMapper.apply(element);
+            V v = Objects.requireNonNull(valueMapper.apply(element));
+            V u = map.putIfAbsent(k, v);
+            if (u != null) throw duplicateKeyException(k, u, v);
+        };
     }
 
     @SuppressWarnings("unchecked")
@@ -203,8 +251,8 @@
      *
      * @param <T> the type of the input elements
      * @param <C> the type of the resulting {@code Collection}
-     * @param collectionFactory a {@code Supplier} which returns a new, empty
-     * {@code Collection} of the appropriate type
+     * @param collectionFactory a supplier providing a new empty {@code Collection}
+     *                          into which the results will be inserted
      * @return a {@code Collector} which collects all the input elements into a
      * {@code Collection}, in encounter order
      */
@@ -233,6 +281,26 @@
     }
 
     /**
+     * Returns a {@code Collector} that accumulates the input elements into an
+     * <a href="../List.html#unmodifiable">unmodifiable List</a> in encounter
+     * order. The returned Collector disallows null values and will throw
+     * {@code NullPointerException} if it is presented with a null value.
+     *
+     * @param <T> the type of the input elements
+     * @return a {@code Collector} that accumulates the input elements into an
+     * <a href="../List.html#unmodifiable">unmodifiable List</a> in encounter order
+     * @since 10
+     */
+    @SuppressWarnings("unchecked")
+    public static <T>
+    Collector<T, ?, List<T>> toUnmodifiableList() {
+        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
+                                   (left, right) -> { left.addAll(right); return left; },
+                                   list -> (List<T>)List.of(list.toArray()),
+                                   CH_NOID);
+    }
+
+    /**
      * Returns a {@code Collector} that accumulates the input elements into a
      * new {@code Set}. There are no guarantees on the type, mutability,
      * serializability, or thread-safety of the {@code Set} returned; if more
@@ -249,11 +317,47 @@
     public static <T>
     Collector<T, ?, Set<T>> toSet() {
         return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
-                                   (left, right) -> { left.addAll(right); return left; },
+                                   (left, right) -> {
+                                       if (left.size() < right.size()) {
+                                           right.addAll(left); return right;
+                                       } else {
+                                           left.addAll(right); return left;
+                                       }
+                                   },
                                    CH_UNORDERED_ID);
     }
 
     /**
+     * Returns a {@code Collector} that accumulates the input elements into an
+     * <a href="../Set.html#unmodifiable">unmodifiable Set</a>. The returned
+     * Collector disallows null values and will throw {@code NullPointerException}
+     * if it is presented with a null value. If the input contains duplicate elements,
+     * an arbitrary element of the duplicates is preserved.
+     *
+     * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
+     * Collector.
+     *
+     * @param <T> the type of the input elements
+     * @return a {@code Collector} that accumulates the input elements into an
+     * <a href="../Set.html#unmodifiable">unmodifiable Set</a>
+     * @since 10
+     */
+    @SuppressWarnings("unchecked")
+    public static <T>
+    Collector<T, ?, Set<T>> toUnmodifiableSet() {
+        return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
+                                   (left, right) -> {
+                                       if (left.size() < right.size()) {
+                                           right.addAll(left); return right;
+                                       } else {
+                                           left.addAll(right); return left;
+                                       }
+                                   },
+                                   set -> (Set<T>)Set.of(set.toArray()),
+                                   CH_UNORDERED_NOID);
+    }
+
+    /**
      * Returns a {@code Collector} that concatenates the input elements into a
      * {@code String}, in encounter order.
      *
@@ -333,9 +437,11 @@
      * {@code partitioningBy}.  For example, given a stream of
      * {@code Person}, to accumulate the set of last names in each city:
      * <pre>{@code
-     *     Map<City, Set<String>> lastNamesByCity
-     *         = people.stream().collect(groupingBy(Person::getCity,
-     *                                              mapping(Person::getLastName, toSet())));
+     * Map<City, Set<String>> lastNamesByCity
+     *   = people.stream().collect(
+     *     groupingBy(Person::getCity,
+     *                mapping(Person::getLastName,
+     *                        toSet())));
      * }</pre>
      *
      * @param <T> the type of the input elements
@@ -358,12 +464,112 @@
     }
 
     /**
+     * Adapts a {@code Collector} accepting elements of type {@code U} to one
+     * accepting elements of type {@code T} by applying a flat mapping function
+     * to each input element before accumulation.  The flat mapping function
+     * maps an input element to a {@link Stream stream} covering zero or more
+     * output elements that are then accumulated downstream.  Each mapped stream
+     * is {@link java.util.stream.BaseStream#close() closed} after its contents
+     * have been placed downstream.  (If a mapped stream is {@code null}
+     * an empty stream is used, instead.)
+     *
+     * @apiNote
+     * The {@code flatMapping()} collectors are most useful when used in a
+     * multi-level reduction, such as downstream of a {@code groupingBy} or
+     * {@code partitioningBy}.  For example, given a stream of
+     * {@code Order}, to accumulate the set of line items for each customer:
+     * <pre>{@code
+     * Map<String, Set<LineItem>> itemsByCustomerName
+     *   = orders.stream().collect(
+     *     groupingBy(Order::getCustomerName,
+     *                flatMapping(order -> order.getLineItems().stream(),
+     *                            toSet())));
+     * }</pre>
+     *
+     * @param <T> the type of the input elements
+     * @param <U> type of elements accepted by downstream collector
+     * @param <A> intermediate accumulation type of the downstream collector
+     * @param <R> result type of collector
+     * @param mapper a function to be applied to the input elements, which
+     * returns a stream of results
+     * @param downstream a collector which will receive the elements of the
+     * stream returned by mapper
+     * @return a collector which applies the mapping function to the input
+     * elements and provides the flat mapped results to the downstream collector
+     * @since 9
+     */
+    public static <T, U, A, R>
+    Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
+                                   Collector<? super U, A, R> downstream) {
+        BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
+        return new CollectorImpl<>(downstream.supplier(),
+                            (r, t) -> {
+                                try (Stream<? extends U> result = mapper.apply(t)) {
+                                    if (result != null)
+                                        result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
+                                }
+                            },
+                            downstream.combiner(), downstream.finisher(),
+                            downstream.characteristics());
+    }
+
+    /**
+     * Adapts a {@code Collector} to one accepting elements of the same type
+     * {@code T} by applying the predicate to each input element and only
+     * accumulating if the predicate returns {@code true}.
+     *
+     * @apiNote
+     * The {@code filtering()} collectors are most useful when used in a
+     * multi-level reduction, such as downstream of a {@code groupingBy} or
+     * {@code partitioningBy}.  For example, given a stream of
+     * {@code Employee}, to accumulate the employees in each department that have a
+     * salary above a certain threshold:
+     * <pre>{@code
+     * Map<Department, Set<Employee>> wellPaidEmployeesByDepartment
+     *   = employees.stream().collect(
+     *     groupingBy(Employee::getDepartment,
+     *                filtering(e -> e.getSalary() > 2000,
+     *                          toSet())));
+     * }</pre>
+     * A filtering collector differs from a stream's {@code filter()} operation.
+     * In this example, suppose there are no employees whose salary is above the
+     * threshold in some department.  Using a filtering collector as shown above
+     * would result in a mapping from that department to an empty {@code Set}.
+     * If a stream {@code filter()} operation were done instead, there would be
+     * no mapping for that department at all.
+     *
+     * @param <T> the type of the input elements
+     * @param <A> intermediate accumulation type of the downstream collector
+     * @param <R> result type of collector
+     * @param predicate a predicate to be applied to the input elements
+     * @param downstream a collector which will accept values that match the
+     * predicate
+     * @return a collector which applies the predicate to the input elements
+     * and provides matching elements to the downstream collector
+     * @since 9
+     */
+    public static <T, A, R>
+    Collector<T, ?, R> filtering(Predicate<? super T> predicate,
+                                 Collector<? super T, A, R> downstream) {
+        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
+        return new CollectorImpl<>(downstream.supplier(),
+                                   (r, t) -> {
+                                       if (predicate.test(t)) {
+                                           downstreamAccumulator.accept(r, t);
+                                       }
+                                   },
+                                   downstream.combiner(), downstream.finisher(),
+                                   downstream.characteristics());
+    }
+
+    /**
      * Adapts a {@code Collector} to perform an additional finishing
      * transformation.  For example, one could adapt the {@link #toList()}
      * collector to always produce an immutable list with:
      * <pre>{@code
-     *     List<String> people
-     *         = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
+     * List<String> list = people.stream().collect(
+     *   collectingAndThen(toList(),
+     *                     Collections::unmodifiableList));
      * }</pre>
      *
      * @param <T> the type of the input elements
@@ -410,7 +616,7 @@
      */
     public static <T> Collector<T, ?, Long>
     counting() {
-        return reducing(0L, e -> 1L, Long::sum);
+        return summingLong(e -> 1L);
     }
 
     /**
@@ -515,8 +721,9 @@
          */
         return new CollectorImpl<>(
                 () -> new double[3],
-                (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t));
-                            a[2] += mapper.applyAsDouble(t);},
+                (a, t) -> { double val = mapper.applyAsDouble(t);
+                            sumWithCompensation(a, val);
+                            a[2] += val;},
                 (a, b) -> { sumWithCompensation(a, b[0]);
                             a[2] += b[2];
                             return sumWithCompensation(a, b[1]); },
@@ -565,8 +772,9 @@
      * the result is 0.
      *
      * @param <T> the type of the input elements
-     * @param mapper a function extracting the property to be summed
-     * @return a {@code Collector} that produces the sum of a derived property
+     * @param mapper a function extracting the property to be averaged
+     * @return a {@code Collector} that produces the arithmetic mean of a
+     * derived property
      */
     public static <T> Collector<T, ?, Double>
     averagingInt(ToIntFunction<? super T> mapper) {
@@ -583,8 +791,9 @@
      * the result is 0.
      *
      * @param <T> the type of the input elements
-     * @param mapper a function extracting the property to be summed
-     * @return a {@code Collector} that produces the sum of a derived property
+     * @param mapper a function extracting the property to be averaged
+     * @return a {@code Collector} that produces the arithmetic mean of a
+     * derived property
      */
     public static <T> Collector<T, ?, Double>
     averagingLong(ToLongFunction<? super T> mapper) {
@@ -614,8 +823,9 @@
      * 2<sup>53</sup>, leading to additional numerical errors.
      *
      * @param <T> the type of the input elements
-     * @param mapper a function extracting the property to be summed
-     * @return a {@code Collector} that produces the sum of a derived property
+     * @param mapper a function extracting the property to be averaged
+     * @return a {@code Collector} that produces the arithmetic mean of a
+     * derived property
      */
     public static <T> Collector<T, ?, Double>
     averagingDouble(ToDoubleFunction<? super T> mapper) {
@@ -627,7 +837,7 @@
          */
         return new CollectorImpl<>(
                 () -> new double[4],
-                (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
+                (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
                 (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
                 a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
                 CH_NOID);
@@ -682,9 +892,11 @@
      * <p>For example, given a stream of {@code Person}, to calculate tallest
      * person in each city:
      * <pre>{@code
-     *     Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
-     *     Map<City, Person> tallestByCity
-     *         = people.stream().collect(groupingBy(Person::getCity, reducing(BinaryOperator.maxBy(byHeight))));
+     * Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
+     * Map<City, Optional<Person>> tallestByCity
+     *   = people.stream().collect(
+     *     groupingBy(Person::getCity,
+     *                reducing(BinaryOperator.maxBy(byHeight))));
      * }</pre>
      *
      * @param <T> element type for the input and output of the reduction
@@ -735,10 +947,13 @@
      * <p>For example, given a stream of {@code Person}, to calculate the longest
      * last name of residents in each city:
      * <pre>{@code
-     *     Comparator<String> byLength = Comparator.comparing(String::length);
-     *     Map<City, String> longestLastNameByCity
-     *         = people.stream().collect(groupingBy(Person::getCity,
-     *                                              reducing(Person::getLastName, BinaryOperator.maxBy(byLength))));
+     * Comparator<String> byLength = Comparator.comparing(String::length);
+     * Map<City, String> longestLastNameByCity
+     *   = people.stream().collect(
+     *     groupingBy(Person::getCity,
+     *                reducing("",
+     *                         Person::getLastName,
+     *                         BinaryOperator.maxBy(byLength))));
      * }</pre>
      *
      * @param <T> the type of the input elements
@@ -822,9 +1037,11 @@
      *
      * <p>For example, to compute the set of last names of people in each city:
      * <pre>{@code
-     *     Map<City, Set<String>> namesByCity
-     *         = people.stream().collect(groupingBy(Person::getCity,
-     *                                              mapping(Person::getLastName, toSet())));
+     * Map<City, Set<String>> namesByCity
+     *   = people.stream().collect(
+     *     groupingBy(Person::getCity,
+     *                mapping(Person::getLastName,
+     *                        toSet())));
      * }</pre>
      *
      * @implNote
@@ -869,9 +1086,12 @@
      * <p>For example, to compute the set of last names of people in each city,
      * where the city names are sorted:
      * <pre>{@code
-     *     Map<City, Set<String>> namesByCity
-     *         = people.stream().collect(groupingBy(Person::getCity, TreeMap::new,
-     *                                              mapping(Person::getLastName, toSet())));
+     * Map<City, Set<String>> namesByCity
+     *   = people.stream().collect(
+     *     groupingBy(Person::getCity,
+     *                TreeMap::new,
+     *                mapping(Person::getLastName,
+     *                        toSet())));
      * }</pre>
      *
      * @implNote
@@ -889,8 +1109,8 @@
      * @param <M> the type of the resulting {@code Map}
      * @param classifier a classifier function mapping input elements to keys
      * @param downstream a {@code Collector} implementing the downstream reduction
-     * @param mapFactory a function which, when called, produces a new empty
-     *                   {@code Map} of the desired type
+     * @param mapFactory a supplier providing a new empty {@code Map}
+     *                   into which the results will be inserted
      * @return a {@code Collector} implementing the cascaded group-by operation
      *
      * @see #groupingBy(Function, Collector)
@@ -944,7 +1164,7 @@
      * function.
      *
      * <p>There are no guarantees on the type, mutability, or serializability
-     * of the {@code Map} or {@code List} objects returned, or of the
+     * of the {@code ConcurrentMap} or {@code List} objects returned, or of the
      * thread-safety of the {@code List} objects returned.
      * @implSpec
      * This produces a result similar to:
@@ -980,14 +1200,19 @@
      * <p>The classification function maps elements to some key type {@code K}.
      * The downstream collector operates on elements of type {@code T} and
      * produces a result of type {@code D}. The resulting collector produces a
-     * {@code Map<K, D>}.
+     * {@code ConcurrentMap<K, D>}.
+     *
+     * <p>There are no guarantees on the type, mutability, or serializability
+     * of the {@code ConcurrentMap} returned.
      *
      * <p>For example, to compute the set of last names of people in each city,
      * where the city names are sorted:
      * <pre>{@code
-     *     ConcurrentMap<City, Set<String>> namesByCity
-     *         = people.stream().collect(groupingByConcurrent(Person::getCity,
-     *                                                        mapping(Person::getLastName, toSet())));
+     * ConcurrentMap<City, Set<String>> namesByCity
+     *   = people.stream().collect(
+     *     groupingByConcurrent(Person::getCity,
+     *                          mapping(Person::getLastName,
+     *                                  toSet())));
      * }</pre>
      *
      * @param <T> the type of the input elements
@@ -1022,17 +1247,19 @@
      * <p>The classification function maps elements to some key type {@code K}.
      * The downstream collector operates on elements of type {@code T} and
      * produces a result of type {@code D}. The resulting collector produces a
-     * {@code Map<K, D>}.
+     * {@code ConcurrentMap<K, D>}.
      *
      * <p>For example, to compute the set of last names of people in each city,
      * where the city names are sorted:
      * <pre>{@code
-     *     ConcurrentMap<City, Set<String>> namesByCity
-     *         = people.stream().collect(groupingBy(Person::getCity, ConcurrentSkipListMap::new,
-     *                                              mapping(Person::getLastName, toSet())));
+     * ConcurrentMap<City, Set<String>> namesByCity
+     *   = people.stream().collect(
+     *     groupingByConcurrent(Person::getCity,
+     *                          ConcurrentSkipListMap::new,
+     *                          mapping(Person::getLastName,
+     *                                  toSet())));
      * }</pre>
      *
-     *
      * @param <T> the type of the input elements
      * @param <K> the type of the keys
      * @param <A> the intermediate accumulation type of the downstream collector
@@ -1040,8 +1267,8 @@
      * @param <M> the type of the resulting {@code ConcurrentMap}
      * @param classifier a classifier function mapping input elements to keys
      * @param downstream a {@code Collector} implementing the downstream reduction
-     * @param mapFactory a function which, when called, produces a new empty
-     *                   {@code ConcurrentMap} of the desired type
+     * @param mapFactory a supplier providing a new empty {@code ConcurrentMap}
+     *                   into which the results will be inserted
      * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
      *
      * @see #groupingByConcurrent(Function)
@@ -1096,8 +1323,15 @@
      * to a {@code Predicate}, and organizes them into a
      * {@code Map<Boolean, List<T>>}.
      *
+     * The returned {@code Map} always contains mappings for both
+     * {@code false} and {@code true} keys.
      * There are no guarantees on the type, mutability,
-     * serializability, or thread-safety of the {@code Map} returned.
+     * serializability, or thread-safety of the {@code Map} or {@code List}
+     * returned.
+     *
+     * @apiNote
+     * If a partition has no elements, its value in the result Map will be
+     * an empty List.
      *
      * @param <T> the type of the input elements
      * @param predicate a predicate used for classifying input elements
@@ -1117,9 +1351,17 @@
      * {@code Map<Boolean, D>} whose values are the result of the downstream
      * reduction.
      *
-     * <p>There are no guarantees on the type, mutability,
+     * <p>
+     * The returned {@code Map} always contains mappings for both
+     * {@code false} and {@code true} keys.
+     * There are no guarantees on the type, mutability,
      * serializability, or thread-safety of the {@code Map} returned.
      *
+     * @apiNote
+     * If a partition has no elements, its value in the result Map will be
+     * obtained by calling the downstream collector's supplier function and then
+     * applying the finisher function.
+     *
      * @param <T> the type of the input elements
      * @param <A> the intermediate accumulation type of the downstream collector
      * @param <D> the result type of the downstream reduction
@@ -1160,12 +1402,15 @@
      * {@code Map} whose keys and values are the result of applying the provided
      * mapping functions to the input elements.
      *
-     * <p>If the mapped keys contains duplicates (according to
+     * <p>If the mapped keys contain duplicates (according to
      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
      * thrown when the collection operation is performed.  If the mapped keys
-     * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
+     * might have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
      * instead.
      *
+     * <p>There are no guarantees on the type, mutability, serializability,
+     * or thread-safety of the {@code Map} returned.
+     *
      * @apiNote
      * It is common for either the key or the value to be the input elements.
      * In this case, the utility method
@@ -1173,16 +1418,18 @@
      * For example, the following produces a {@code Map} mapping
      * students to their grade point average:
      * <pre>{@code
-     *     Map<Student, Double> studentToGPA
-     *         students.stream().collect(toMap(Functions.identity(),
-     *                                         student -> computeGPA(student)));
+     * Map<Student, Double> studentToGPA
+     *   = students.stream().collect(
+     *     toMap(Function.identity(),
+     *           student -> computeGPA(student)));
      * }</pre>
      * And the following produces a {@code Map} mapping a unique identifier to
      * students:
      * <pre>{@code
-     *     Map<String, Student> studentIdToStudent
-     *         students.stream().collect(toMap(Student::getId,
-     *                                         Functions.identity());
+     * Map<String, Student> studentIdToStudent
+     *   = students.stream().collect(
+     *     toMap(Student::getId,
+     *           Function.identity()));
      * }</pre>
      *
      * @implNote
@@ -1209,7 +1456,49 @@
     public static <T, K, U>
     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                     Function<? super T, ? extends U> valueMapper) {
-        return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
+        return new CollectorImpl<>(HashMap::new,
+                                   uniqKeysMapAccumulator(keyMapper, valueMapper),
+                                   uniqKeysMapMerger(),
+                                   CH_ID);
+    }
+
+    /**
+     * Returns a {@code Collector} that accumulates the input elements into an
+     * <a href="../Map.html#unmodifiable">unmodifiable Map</a>,
+     * whose keys and values are the result of applying the provided
+     * mapping functions to the input elements.
+     *
+     * <p>If the mapped keys contain duplicates (according to
+     * {@link Object#equals(Object)}), an {@code IllegalStateException} is
+     * thrown when the collection operation is performed.  If the mapped keys
+     * might have duplicates, use {@link #toUnmodifiableMap(Function, Function, BinaryOperator)}
+     * to handle merging of the values.
+     *
+     * <p>The returned Collector disallows null keys and values. If either mapping function
+     * returns null, {@code NullPointerException} will be thrown.
+     *
+     * @param <T> the type of the input elements
+     * @param <K> the output type of the key mapping function
+     * @param <U> the output type of the value mapping function
+     * @param keyMapper a mapping function to produce keys, must be non-null
+     * @param valueMapper a mapping function to produce values, must be non-null
+     * @return a {@code Collector} that accumulates the input elements into an
+     * <a href="../Map.html#unmodifiable">unmodifiable Map</a>, whose keys and values
+     * are the result of applying the provided mapping functions to the input elements
+     * @throws NullPointerException if either keyMapper or valueMapper is null
+     *
+     * @see #toUnmodifiableMap(Function, Function, BinaryOperator)
+     * @since 10
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static <T, K, U>
+    Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
+                                                Function<? super T, ? extends U> valueMapper) {
+        Objects.requireNonNull(keyMapper, "keyMapper");
+        Objects.requireNonNull(valueMapper, "valueMapper");
+        return collectingAndThen(
+                toMap(keyMapper, valueMapper),
+                map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
     }
 
     /**
@@ -1218,10 +1507,13 @@
      * mapping functions to the input elements.
      *
      * <p>If the mapped
-     * keys contains duplicates (according to {@link Object#equals(Object)}),
+     * keys contain duplicates (according to {@link Object#equals(Object)}),
      * the value mapping function is applied to each equal element, and the
      * results are merged using the provided merging function.
      *
+     * <p>There are no guarantees on the type, mutability, serializability,
+     * or thread-safety of the {@code Map} returned.
+     *
      * @apiNote
      * There are multiple ways to deal with collisions between multiple elements
      * mapping to the same key.  The other forms of {@code toMap} simply use
@@ -1229,13 +1521,14 @@
      * more flexible merge policies.  For example, if you have a stream
      * of {@code Person}, and you want to produce a "phone book" mapping name to
      * address, but it is possible that two persons have the same name, you can
-     * do as follows to gracefully deals with these collisions, and produce a
+     * do as follows to gracefully deal with these collisions, and produce a
      * {@code Map} mapping names to a concatenated list of addresses:
      * <pre>{@code
-     *     Map<String, String> phoneBook
-     *         people.stream().collect(toMap(Person::getName,
-     *                                       Person::getAddress,
-     *                                       (s, a) -> s + ", " + a));
+     * Map<String, String> phoneBook
+     *   = people.stream().collect(
+     *     toMap(Person::getName,
+     *           Person::getAddress,
+     *           (s, a) -> s + ", " + a));
      * }</pre>
      *
      * @implNote
@@ -1271,13 +1564,58 @@
         return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
     }
 
+
+    /**
+     * Returns a {@code Collector} that accumulates the input elements into an
+     * <a href="../Map.html#unmodifiable">unmodifiable Map</a>,
+     * whose keys and values are the result of applying the provided
+     * mapping functions to the input elements.
+     *
+     * <p>If the mapped
+     * keys contain duplicates (according to {@link Object#equals(Object)}),
+     * the value mapping function is applied to each equal element, and the
+     * results are merged using the provided merging function.
+     *
+     * <p>The returned Collector disallows null keys and values. If either mapping function
+     * returns null, {@code NullPointerException} will be thrown.
+     *
+     * @param <T> the type of the input elements
+     * @param <K> the output type of the key mapping function
+     * @param <U> the output type of the value mapping function
+     * @param keyMapper a mapping function to produce keys, must be non-null
+     * @param valueMapper a mapping function to produce values, must be non-null
+     * @param mergeFunction a merge function, used to resolve collisions between
+     *                      values associated with the same key, as supplied
+     *                      to {@link Map#merge(Object, Object, BiFunction)},
+     *                      must be non-null
+     * @return a {@code Collector} that accumulates the input elements into an
+     * <a href="../Map.html#unmodifiable">unmodifiable Map</a>, whose keys and values
+     * are the result of applying the provided mapping functions to the input elements
+     * @throws NullPointerException if the keyMapper, valueMapper, or mergeFunction is null
+     *
+     * @see #toUnmodifiableMap(Function, Function)
+     * @since 10
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static <T, K, U>
+    Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
+                                                Function<? super T, ? extends U> valueMapper,
+                                                BinaryOperator<U> mergeFunction) {
+        Objects.requireNonNull(keyMapper, "keyMapper");
+        Objects.requireNonNull(valueMapper, "valueMapper");
+        Objects.requireNonNull(mergeFunction, "mergeFunction");
+        return collectingAndThen(
+                toMap(keyMapper, valueMapper, mergeFunction, HashMap::new),
+                map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
+    }
+
     /**
      * Returns a {@code Collector} that accumulates elements into a
      * {@code Map} whose keys and values are the result of applying the provided
      * mapping functions to the input elements.
      *
      * <p>If the mapped
-     * keys contains duplicates (according to {@link Object#equals(Object)}),
+     * keys contain duplicates (according to {@link Object#equals(Object)}),
      * the value mapping function is applied to each equal element, and the
      * results are merged using the provided merging function.  The {@code Map}
      * is created by a provided supplier function.
@@ -1299,8 +1637,8 @@
      * @param mergeFunction a merge function, used to resolve collisions between
      *                      values associated with the same key, as supplied
      *                      to {@link Map#merge(Object, Object, BiFunction)}
-     * @param mapSupplier a function which returns a new, empty {@code Map} into
-     *                    which the results will be inserted
+     * @param mapFactory a supplier providing a new empty {@code Map}
+     *                   into which the results will be inserted
      * @return a {@code Collector} which collects elements into a {@code Map}
      * whose keys are the result of applying a key mapping function to the input
      * elements, and whose values are the result of applying a value mapping
@@ -1313,13 +1651,13 @@
      */
     public static <T, K, U, M extends Map<K, U>>
     Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
-                                Function<? super T, ? extends U> valueMapper,
-                                BinaryOperator<U> mergeFunction,
-                                Supplier<M> mapSupplier) {
+                             Function<? super T, ? extends U> valueMapper,
+                             BinaryOperator<U> mergeFunction,
+                             Supplier<M> mapFactory) {
         BiConsumer<M, T> accumulator
                 = (map, element) -> map.merge(keyMapper.apply(element),
                                               valueMapper.apply(element), mergeFunction);
-        return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
+        return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_ID);
     }
 
     /**
@@ -1327,29 +1665,34 @@
      * {@code ConcurrentMap} whose keys and values are the result of applying
      * the provided mapping functions to the input elements.
      *
-     * <p>If the mapped keys contains duplicates (according to
+     * <p>If the mapped keys contain duplicates (according to
      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
      * thrown when the collection operation is performed.  If the mapped keys
      * may have duplicates, use
      * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead.
      *
+     * <p>There are no guarantees on the type, mutability, or serializability
+     * of the {@code ConcurrentMap} returned.
+     *
      * @apiNote
      * It is common for either the key or the value to be the input elements.
      * In this case, the utility method
      * {@link java.util.function.Function#identity()} may be helpful.
-     * For example, the following produces a {@code Map} mapping
+     * For example, the following produces a {@code ConcurrentMap} mapping
      * students to their grade point average:
      * <pre>{@code
-     *     Map<Student, Double> studentToGPA
-     *         students.stream().collect(toMap(Functions.identity(),
-     *                                         student -> computeGPA(student)));
+     * ConcurrentMap<Student, Double> studentToGPA
+     *   = students.stream().collect(
+     *     toConcurrentMap(Function.identity(),
+     *                     student -> computeGPA(student)));
      * }</pre>
-     * And the following produces a {@code Map} mapping a unique identifier to
-     * students:
+     * And the following produces a {@code ConcurrentMap} mapping a
+     * unique identifier to students:
      * <pre>{@code
-     *     Map<String, Student> studentIdToStudent
-     *         students.stream().collect(toConcurrentMap(Student::getId,
-     *                                                   Functions.identity());
+     * ConcurrentMap<String, Student> studentIdToStudent
+     *   = students.stream().collect(
+     *     toConcurrentMap(Student::getId,
+     *                     Function.identity()));
      * }</pre>
      *
      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
@@ -1372,7 +1715,10 @@
     public static <T, K, U>
     Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
                                                         Function<? super T, ? extends U> valueMapper) {
-        return toConcurrentMap(keyMapper, valueMapper, throwingMerger(), ConcurrentHashMap::new);
+        return new CollectorImpl<>(ConcurrentHashMap::new,
+                                   uniqKeysMapAccumulator(keyMapper, valueMapper),
+                                   uniqKeysMapMerger(),
+                                   CH_CONCURRENT_ID);
     }
 
     /**
@@ -1380,10 +1726,13 @@
      * {@code ConcurrentMap} whose keys and values are the result of applying
      * the provided mapping functions to the input elements.
      *
-     * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
+     * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}),
      * the value mapping function is applied to each equal element, and the
      * results are merged using the provided merging function.
      *
+     * <p>There are no guarantees on the type, mutability, or serializability
+     * of the {@code ConcurrentMap} returned.
+     *
      * @apiNote
      * There are multiple ways to deal with collisions between multiple elements
      * mapping to the same key.  The other forms of {@code toConcurrentMap} simply use
@@ -1391,13 +1740,14 @@
      * more flexible merge policies.  For example, if you have a stream
      * of {@code Person}, and you want to produce a "phone book" mapping name to
      * address, but it is possible that two persons have the same name, you can
-     * do as follows to gracefully deals with these collisions, and produce a
-     * {@code Map} mapping names to a concatenated list of addresses:
+     * do as follows to gracefully deal with these collisions, and produce a
+     * {@code ConcurrentMap} mapping names to a concatenated list of addresses:
      * <pre>{@code
-     *     Map<String, String> phoneBook
-     *         people.stream().collect(toConcurrentMap(Person::getName,
-     *                                                 Person::getAddress,
-     *                                                 (s, a) -> s + ", " + a));
+     * ConcurrentMap<String, String> phoneBook
+     *   = people.stream().collect(
+     *     toConcurrentMap(Person::getName,
+     *                     Person::getAddress,
+     *                     (s, a) -> s + ", " + a));
      * }</pre>
      *
      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
@@ -1434,7 +1784,7 @@
      * {@code ConcurrentMap} whose keys and values are the result of applying
      * the provided mapping functions to the input elements.
      *
-     * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
+     * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}),
      * the value mapping function is applied to each equal element, and the
      * results are merged using the provided merging function.  The
      * {@code ConcurrentMap} is created by a provided supplier function.
@@ -1451,8 +1801,8 @@
      * @param mergeFunction a merge function, used to resolve collisions between
      *                      values associated with the same key, as supplied
      *                      to {@link Map#merge(Object, Object, BiFunction)}
-     * @param mapSupplier a function which returns a new, empty {@code Map} into
-     *                    which the results will be inserted
+     * @param mapFactory a supplier providing a new empty {@code ConcurrentMap}
+     *                   into which the results will be inserted
      * @return a concurrent, unordered {@code Collector} which collects elements into a
      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
      * function to the input elements, and whose values are the result of
@@ -1467,11 +1817,11 @@
     Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
                                        Function<? super T, ? extends U> valueMapper,
                                        BinaryOperator<U> mergeFunction,
-                                       Supplier<M> mapSupplier) {
+                                       Supplier<M> mapFactory) {
         BiConsumer<M, T> accumulator
                 = (map, element) -> map.merge(keyMapper.apply(element),
                                               valueMapper.apply(element), mergeFunction);
-        return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID);
+        return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID);
     }
 
     /**
@@ -1550,12 +1900,12 @@
 
         @Override
         public Set<Map.Entry<Boolean, T>> entrySet() {
-            return new AbstractSet<Map.Entry<Boolean, T>>() {
+            return new AbstractSet<>() {
                 @Override
                 public Iterator<Map.Entry<Boolean, T>> iterator() {
                     Map.Entry<Boolean, T> falseEntry = new SimpleImmutableEntry<>(false, forFalse);
                     Map.Entry<Boolean, T> trueEntry = new SimpleImmutableEntry<>(true, forTrue);
-                    return Arrays.asList(falseEntry, trueEntry).iterator();
+                    return List.of(falseEntry, trueEntry).iterator();
                 }
 
                 @Override
diff --git a/ojluni/src/main/java/java/util/stream/MatchOps.java b/ojluni/src/main/java/java/util/stream/MatchOps.java
index cc809e4..dbaab0a 100644
--- a/ojluni/src/main/java/java/util/stream/MatchOps.java
+++ b/ojluni/src/main/java/java/util/stream/MatchOps.java
@@ -249,7 +249,7 @@
      *
      * @param <T> The output type of the stream pipeline
      */
-    private static abstract class BooleanTerminalSink<T> implements Sink<T> {
+    private abstract static class BooleanTerminalSink<T> implements Sink<T> {
         boolean stop;
         boolean value;
 
diff --git a/ojluni/src/main/java/java/util/stream/Sink.java b/ojluni/src/main/java/java/util/stream/Sink.java
index 2c5609c..491701b 100644
--- a/ojluni/src/main/java/java/util/stream/Sink.java
+++ b/ojluni/src/main/java/java/util/stream/Sink.java
@@ -243,7 +243,7 @@
      * implementation of the {@code accept()} method must call the correct
      * {@code accept()} method on the downstream {@code Sink}.
      */
-    static abstract class ChainedReference<T, E_OUT> implements Sink<T> {
+    abstract static class ChainedReference<T, E_OUT> implements Sink<T> {
         protected final Sink<? super E_OUT> downstream;
 
         public ChainedReference(Sink<? super E_OUT> downstream) {
@@ -275,7 +275,7 @@
      * The implementation of the {@code accept()} method must call the correct
      * {@code accept()} method on the downstream {@code Sink}.
      */
-    static abstract class ChainedInt<E_OUT> implements Sink.OfInt {
+    abstract static class ChainedInt<E_OUT> implements Sink.OfInt {
         protected final Sink<? super E_OUT> downstream;
 
         public ChainedInt(Sink<? super E_OUT> downstream) {
@@ -307,7 +307,7 @@
      * The implementation of the {@code accept()} method must call the correct
      * {@code accept()} method on the downstream {@code Sink}.
      */
-    static abstract class ChainedLong<E_OUT> implements Sink.OfLong {
+    abstract static class ChainedLong<E_OUT> implements Sink.OfLong {
         protected final Sink<? super E_OUT> downstream;
 
         public ChainedLong(Sink<? super E_OUT> downstream) {
@@ -339,7 +339,7 @@
      * The implementation of the {@code accept()} method must call the correct
      * {@code accept()} method on the downstream {@code Sink}.
      */
-    static abstract class ChainedDouble<E_OUT> implements Sink.OfDouble {
+    abstract static class ChainedDouble<E_OUT> implements Sink.OfDouble {
         protected final Sink<? super E_OUT> downstream;
 
         public ChainedDouble(Sink<? super E_OUT> downstream) {
diff --git a/ojluni/src/main/java/java/util/stream/StreamOpFlag.java b/ojluni/src/main/java/java/util/stream/StreamOpFlag.java
index 83a3660..38d7db0 100644
--- a/ojluni/src/main/java/java/util/stream/StreamOpFlag.java
+++ b/ojluni/src/main/java/java/util/stream/StreamOpFlag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
  * contexts:
  *
  * <div>
- * <table>
+ * <table class="borderless">
  *   <caption>Type Characteristics</caption>
  *   <thead class="tableSubHeadingColor">
  *     <tr>
@@ -115,7 +115,7 @@
  * characteristics that stream has; when describing a stream operation, one need
  * describe whether the operation preserves, injects, or clears that
  * characteristic.  Accordingly, two bits are used for each flag, so as to allow
- * representing not only the presence of of a characteristic, but how an
+ * representing not only the presence of a characteristic, but how an
  * operation modifies that characteristic.  There are two common forms in which
  * flag bits are combined into an {@code int} bit set.  <em>Stream flags</em>
  * are a unioned bit set constructed by ORing the enum characteristic values of
diff --git a/ojluni/src/main/java/java/util/zip/CheckedInputStream.java b/ojluni/src/main/java/java/util/zip/CheckedInputStream.java
index e1e5249..05c6f89 100644
--- a/ojluni/src/main/java/java/util/zip/CheckedInputStream.java
+++ b/ojluni/src/main/java/java/util/zip/CheckedInputStream.java
@@ -35,6 +35,7 @@
  *
  * @see         Checksum
  * @author      David Connelly
+ * @since 1.1
  */
 public
 class CheckedInputStream extends FilterInputStream {
diff --git a/ojluni/src/main/java/java/util/zip/CheckedOutputStream.java b/ojluni/src/main/java/java/util/zip/CheckedOutputStream.java
index 698b941..9267d8e 100644
--- a/ojluni/src/main/java/java/util/zip/CheckedOutputStream.java
+++ b/ojluni/src/main/java/java/util/zip/CheckedOutputStream.java
@@ -36,6 +36,7 @@
  *
  * @see         Checksum
  * @author      David Connelly
+ * @since 1.1
  */
 public
 class CheckedOutputStream extends FilterOutputStream {
diff --git a/ojluni/src/main/java/java/util/zip/DataFormatException.java b/ojluni/src/main/java/java/util/zip/DataFormatException.java
index 77adbe9..a5639b3 100644
--- a/ojluni/src/main/java/java/util/zip/DataFormatException.java
+++ b/ojluni/src/main/java/java/util/zip/DataFormatException.java
@@ -29,6 +29,7 @@
  * Signals that a data format error has occurred.
  *
  * @author      David Connelly
+ * @since 1.1
  */
 public
 class DataFormatException extends Exception {
diff --git a/ojluni/src/main/java/java/util/zip/DeflaterOutputStream.java b/ojluni/src/main/java/java/util/zip/DeflaterOutputStream.java
index 7821737..8d04949 100644
--- a/ojluni/src/main/java/java/util/zip/DeflaterOutputStream.java
+++ b/ojluni/src/main/java/java/util/zip/DeflaterOutputStream.java
@@ -38,6 +38,7 @@
  *
  * @see         Deflater
  * @author      David Connelly
+ * @since 1.1
  */
 public
 class DeflaterOutputStream extends FilterOutputStream {
@@ -54,7 +55,6 @@
     /**
      * Indicates that the stream has been closed.
      */
-
     private boolean closed = false;
 
     private final boolean syncFlush;
@@ -62,7 +62,7 @@
     /**
      * Creates a new output stream with the specified compressor,
      * buffer size and flush mode.
-
+     *
      * @param out the output stream
      * @param def the compressor ("deflater")
      * @param size the output buffer size
diff --git a/ojluni/src/main/java/java/util/zip/GZIPInputStream.java b/ojluni/src/main/java/java/util/zip/GZIPInputStream.java
index 109454c..b2482f4 100644
--- a/ojluni/src/main/java/java/util/zip/GZIPInputStream.java
+++ b/ojluni/src/main/java/java/util/zip/GZIPInputStream.java
@@ -38,6 +38,7 @@
  *
  * @see         InflaterInputStream
  * @author      David Connelly
+ * @since 1.1
  *
  */
 public
@@ -65,6 +66,14 @@
 
     /**
      * Creates a new input stream with the specified buffer size.
+     *
+     * Android-note: Android limits the number of UnbufferedIO operations that can be performed, so
+     * consider using buffered inputs with this class. More information can be found in the
+     * <a href="https://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder#detectUnbufferedIo()">
+     * UnbufferedIO</a> and
+     * <a href="https://developer.android.com/reference/android/os/StrictMode"> StrictMode</a>
+     * documentation.
+     *
      * @param in the input stream
      * @param size the input buffer size
      *
@@ -151,16 +160,16 @@
     /**
      * GZIP header magic number.
      */
-    public final static int GZIP_MAGIC = 0x8b1f;
+    public static final int GZIP_MAGIC = 0x8b1f;
 
     /*
      * File header flags.
      */
-    private final static int FTEXT      = 1;    // Extra text
-    private final static int FHCRC      = 2;    // Header CRC
-    private final static int FEXTRA     = 4;    // Extra field
-    private final static int FNAME      = 8;    // File name
-    private final static int FCOMMENT   = 16;   // File comment
+    private static final int FTEXT      = 1;    // Extra text
+    private static final int FHCRC      = 2;    // Header CRC
+    private static final int FEXTRA     = 4;    // Extra field
+    private static final int FNAME      = 8;    // File name
+    private static final int FCOMMENT   = 16;   // File comment
 
     /*
      * Reads GZIP member header and returns the total byte number
diff --git a/ojluni/src/main/java/java/util/zip/GZIPOutputStream.java b/ojluni/src/main/java/java/util/zip/GZIPOutputStream.java
index 2c1cd40..cad62dc 100644
--- a/ojluni/src/main/java/java/util/zip/GZIPOutputStream.java
+++ b/ojluni/src/main/java/java/util/zip/GZIPOutputStream.java
@@ -32,6 +32,7 @@
  * This class implements a stream filter for writing compressed data in
  * the GZIP file format.
  * @author      David Connelly
+ * @since 1.1
  *
  */
 public
@@ -44,13 +45,13 @@
     /*
      * GZIP header magic number.
      */
-    private final static int GZIP_MAGIC = 0x8b1f;
+    private static final int GZIP_MAGIC = 0x8b1f;
 
     /*
      * Trailer size in bytes.
      *
      */
-    private final static int TRAILER_SIZE = 8;
+    private static final int TRAILER_SIZE = 8;
 
     /**
      * Creates a new output stream with the specified buffer size.
@@ -58,6 +59,13 @@
      * <p>The new output stream instance is created as if by invoking
      * the 3-argument constructor GZIPOutputStream(out, size, false).
      *
+     * Android-note: Android limits the number of UnbufferedIO operations that can be performed, so
+     * consider using buffered inputs with this class. More information can be found in the
+     * <a href="https://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder#detectUnbufferedIo()">
+     * UnbufferedIO</a> and
+     * <a href="https://developer.android.com/reference/android/os/StrictMode"> StrictMode</a>
+     * documentation.
+     *
      * @param out the output stream
      * @param size the output buffer size
      * @exception IOException If an I/O error has occurred.
diff --git a/ojluni/src/main/java/java/util/zip/InflaterInputStream.java b/ojluni/src/main/java/java/util/zip/InflaterInputStream.java
index b65adbe..1780420 100644
--- a/ojluni/src/main/java/java/util/zip/InflaterInputStream.java
+++ b/ojluni/src/main/java/java/util/zip/InflaterInputStream.java
@@ -38,6 +38,7 @@
  *
  * @see         Inflater
  * @author      David Connelly
+ * @since 1.1
  */
 public
 class InflaterInputStream extends FilterInputStream {
@@ -198,14 +199,10 @@
         ensureOpen();
         if (reachEOF) {
             return 0;
-        // BEGIN Android-added: Return more accurate value from available().
-        // Integrates change http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/dbcf47bfb044 made as part
-        // of https://bugs.openjdk.java.net/browse/JDK-7031075.
         } else if (inf.finished()) {
             // the end of the compressed data stream has been reached
             reachEOF = true;
             return 0;
-        // END Android-added: Return more accurate value from available().
         } else {
             return 1;
         }
diff --git a/ojluni/src/main/java/java/util/zip/ZipConstants.java b/ojluni/src/main/java/java/util/zip/ZipConstants.java
index db7f500..4f54718e 100644
--- a/ojluni/src/main/java/java/util/zip/ZipConstants.java
+++ b/ojluni/src/main/java/java/util/zip/ZipConstants.java
@@ -30,6 +30,7 @@
  * which manipulate ZIP files.
  *
  * @author      David Connelly
+ * @since 1.1
  */
 interface ZipConstants {
     /*
diff --git a/ojluni/src/main/java/java/util/zip/ZipConstants64.java b/ojluni/src/main/java/java/util/zip/ZipConstants64.java
index 5d45f77..d78eaf4 100644
--- a/ojluni/src/main/java/java/util/zip/ZipConstants64.java
+++ b/ojluni/src/main/java/java/util/zip/ZipConstants64.java
@@ -74,11 +74,12 @@
     static final int  ZIP64_EXTLEN = 16;      // uncompressed size, 8-byte
 
     /*
-     * Language encoding flag EFS
+     * Language encoding flag (general purpose flag bit 11)
+     *
+     * If this bit is set the filename and comment fields for this
+     * entry must be encoded using UTF-8.
      */
-    static final int EFS = 0x800;       // If this bit is set the filename and
-                                        // comment fields for this file must be
-                                        // encoded using UTF-8.
+    static final int USE_UTF8 = 0x800;
 
     /*
      * Constants below are defined here (instead of in ZipConstants)
diff --git a/ojluni/src/main/java/java/util/zip/ZipException.java b/ojluni/src/main/java/java/util/zip/ZipException.java
index 4bcfe03..588611f 100644
--- a/ojluni/src/main/java/java/util/zip/ZipException.java
+++ b/ojluni/src/main/java/java/util/zip/ZipException.java
@@ -32,7 +32,7 @@
  *
  * @author  unascribed
  * @see     java.io.IOException
- * @since   JDK1.0
+ * @since   1.1
  */
 
 public
diff --git a/ojluni/src/main/java/java/util/zip/ZipFile.java b/ojluni/src/main/java/java/util/zip/ZipFile.java
index e06fb6d..a2f9e84 100644
--- a/ojluni/src/main/java/java/util/zip/ZipFile.java
+++ b/ojluni/src/main/java/java/util/zip/ZipFile.java
@@ -398,7 +398,7 @@
         ZipFileInputStream in = null;
         synchronized (this) {
             ensureOpen();
-            if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
+            if (!zc.isUTF8() && (entry.flag & USE_UTF8) != 0) {
                 // Android-changed: Find entry by name, falling back to name/ if cannot be found.
                 // Needed for ClassPathURLStreamHandler handling of URLs without trailing slashes.
                 // This was added as part of the work to move StrictJarFile from libcore to
@@ -620,7 +620,7 @@
             e.name = name;
         } else {
             byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME);
-            if (!zc.isUTF8() && (e.flag & EFS) != 0) {
+            if (!zc.isUTF8() && (e.flag & USE_UTF8) != 0) {
                 e.name = zc.toStringUTF8(bname, bname.length);
             } else {
                 e.name = zc.toString(bname, bname.length);
@@ -636,7 +636,7 @@
         if (bcomm == null) {
             e.comment = null;
         } else {
-            if (!zc.isUTF8() && (e.flag & EFS) != 0) {
+            if (!zc.isUTF8() && (e.flag & USE_UTF8) != 0) {
                 e.comment = zc.toStringUTF8(bcomm, bcomm.length);
             } else {
                 e.comment = zc.toString(bcomm, bcomm.length);
diff --git a/ojluni/src/main/java/java/util/zip/ZipInputStream.java b/ojluni/src/main/java/java/util/zip/ZipInputStream.java
index aaebb49..068c277 100644
--- a/ojluni/src/main/java/java/util/zip/ZipInputStream.java
+++ b/ojluni/src/main/java/java/util/zip/ZipInputStream.java
@@ -41,6 +41,7 @@
  * entries.
  *
  * @author      David Connelly
+ * @since 1.1
  */
 public
 class ZipInputStream extends InflaterInputStream implements ZipConstants {
@@ -300,7 +301,7 @@
         if (get32(tmpbuf, 0) != LOCSIG) {
             return null;
         }
-        // get flag first, we need check EFS.
+        // get flag first, we need check USE_UTF8.
         flag = get16(tmpbuf, LOCFLG);
         // get the entry name and create the ZipEntry first
         int len = get16(tmpbuf, LOCNAM);
@@ -312,8 +313,8 @@
             b = new byte[blen];
         }
         readFully(b, 0, len);
-        // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
-        ZipEntry e = createZipEntry(((flag & EFS) != 0)
+        // Force to use UTF-8 if the USE_UTF8 bit is ON
+        ZipEntry e = createZipEntry(((flag & USE_UTF8) != 0)
                                     ? zc.toStringUTF8(b, len)
                                     : zc.toString(b, len));
         // now get the remaining fields for the entry
@@ -323,7 +324,7 @@
         e.method = get16(tmpbuf, LOCHOW);
         e.xdostime = get32(tmpbuf, LOCTIM);
         if ((flag & 8) == 8) {
-            // Android-Changed: Remove the requirement that only DEFLATED entries
+            // Android-changed: Remove the requirement that only DEFLATED entries
             // can have data descriptors. This is not required by the ZIP spec and
             // is inconsistent with the behaviour of ZipFile and versions of Android
             // prior to Android N.
@@ -359,8 +360,21 @@
         return new ZipEntry(name);
     }
 
-    /*
+    /**
      * Reads end of deflated entry as well as EXT descriptor if present.
+     *
+     * Local headers for DEFLATED entries may optionally be followed by a
+     * data descriptor, and that data descriptor may optionally contain a
+     * leading signature (EXTSIG).
+     *
+     * From the zip spec http://www.pkware.com/documents/casestudies/APPNOTE.TXT
+     *
+     * """Although not originally assigned a signature, the value 0x08074b50
+     * has commonly been adopted as a signature value for the data descriptor
+     * record.  Implementers should be aware that ZIP files may be
+     * encountered with or without this signature marking data descriptors
+     * and should account for either case when reading ZIP files to ensure
+     * compatibility."""
      */
     private void readEnd(ZipEntry e) throws IOException {
         int n = inf.getRemaining();
@@ -379,7 +393,7 @@
                     e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
                     e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
                     ((PushbackInputStream)in).unread(
-                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
+                        tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC, ZIP64_EXTCRC);
                 } else {
                     e.crc = get32(tmpbuf, ZIP64_EXTCRC);
                     e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
@@ -393,7 +407,7 @@
                     e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
                     e.size = get32(tmpbuf, EXTLEN - EXTCRC);
                     ((PushbackInputStream)in).unread(
-                                               tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
+                                               tmpbuf, EXTHDR - EXTCRC, EXTCRC);
                 } else {
                     e.crc = get32(tmpbuf, EXTCRC);
                     e.csize = get32(tmpbuf, EXTSIZ);
diff --git a/ojluni/src/main/java/java/util/zip/ZipOutputStream.java b/ojluni/src/main/java/java/util/zip/ZipOutputStream.java
index dd005ec..751db71 100644
--- a/ojluni/src/main/java/java/util/zip/ZipOutputStream.java
+++ b/ojluni/src/main/java/java/util/zip/ZipOutputStream.java
@@ -234,7 +234,7 @@
             throw new ZipException("duplicate entry: " + e.name);
         }
         if (zc.isUTF8())
-            e.flag |= EFS;
+            e.flag |= USE_UTF8;
         current = new XEntry(e, written);
         xentries.add(current);
         writeLOC(current);
diff --git a/ojluni/src/main/java/javax/crypto/Cipher.java b/ojluni/src/main/java/javax/crypto/Cipher.java
index a872317..53e7fb8 100644
--- a/ojluni/src/main/java/javax/crypto/Cipher.java
+++ b/ojluni/src/main/java/javax/crypto/Cipher.java
@@ -46,6 +46,7 @@
 import java.nio.ReadOnlyBufferException;
 import sun.security.jca.*;
 
+/* Android-changed: preformatted example updated to work with Dokka (b/209921086). */
 /**
  * This class provides the functionality of a cryptographic cipher for
  * encryption and decryption. It forms the core of the Java Cryptographic
@@ -74,9 +75,9 @@
  * provider-specific default values for the mode and padding scheme are used).
  * For example, the following is a valid transformation:
  *
- * <pre>
- *     Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
- * </pre>
+ * <pre>{@code
+ *     Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ * }</pre>
  *
  * Using modes such as <code>CFB</code> and <code>OFB</code>, block
  * ciphers can encrypt data in units smaller than the cipher's actual
@@ -242,7 +243,7 @@
  * </table>
  *
  * These transformations are described in the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
+ * <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
  * Cipher section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -597,7 +598,7 @@
      * @param transformation the name of the transformation, e.g.,
      * <i>DES/CBC/PKCS5Padding</i>.
      * See the Cipher section in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard transformation names.
      *
@@ -634,7 +635,7 @@
      * @param transformation the name of the transformation,
      * e.g., <i>DES/CBC/PKCS5Padding</i>.
      * See the Cipher section in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard transformation names.
      *
@@ -686,7 +687,7 @@
      * @param transformation the name of the transformation,
      * e.g., <i>DES/CBC/PKCS5Padding</i>.
      * See the Cipher section in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard transformation names.
      *
@@ -2477,7 +2478,7 @@
      * For more information on default key size in JCE jurisdiction
      * policy files, please see Appendix E in the
      * <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppC">
+     *   "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppC">
      * Java Cryptography Architecture Reference Guide</a>.
      *
      * @param transformation the cipher transformation.
diff --git a/ojluni/src/main/java/javax/crypto/CipherSpi.java b/ojluni/src/main/java/javax/crypto/CipherSpi.java
index ce72581..4b23c38 100644
--- a/ojluni/src/main/java/javax/crypto/CipherSpi.java
+++ b/ojluni/src/main/java/javax/crypto/CipherSpi.java
@@ -40,6 +40,7 @@
 
 import java.nio.ByteBuffer;
 
+/* Android-changed: preformatted example updated to work with Dokka (b/209921086). */
 /**
  * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
  * for the <code>Cipher</code> class.
@@ -74,9 +75,9 @@
  * provider-specific default values for the mode and padding scheme are used).
  * For example, the following is a valid transformation:
  *
- * <pre>
- *     Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
- * </pre>
+ * <pre>{@code
+ *     Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
+ * }</pre>
  *
  * <p>A provider may supply a separate class for each combination
  * of <i>algorithm/mode/padding</i>, or may decide to provide more generic
diff --git a/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java b/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
index b8bf169..5eeb481 100644
--- a/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
+++ b/ojluni/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
@@ -115,7 +115,7 @@
      *
      * @param algName encryption algorithm name. See Appendix A in the
      * <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     *   "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
      * Java Cryptography Architecture Reference Guide</a>
      * for information about standard Cipher algorithm names.
      * @param encryptedData encrypted data. The contents of
@@ -198,7 +198,7 @@
      * in the constructor when such mapping is available.
      * See Appendix A in the
      * <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     *   "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
      * Java Cryptography Architecture Reference Guide</a>
      * for information about standard Cipher algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java b/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java
index f991a66..b90ab43 100644
--- a/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java
+++ b/ojluni/src/main/java/javax/crypto/ExemptionMechanism.java
@@ -116,7 +116,7 @@
      * mechanism.
      * See the ExemptionMechanism section in the
      * <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Exemption">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard exemption mechanism names.
      *
@@ -155,7 +155,7 @@
      * @param algorithm the standard name of the requested exemption mechanism.
      * See the ExemptionMechanism section in the
      * <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Exemption">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard exemption mechanism names.
      *
@@ -199,7 +199,7 @@
      * @param algorithm the standard name of the requested exemption mechanism.
      * See the ExemptionMechanism section in the
      * <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Exemption">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Exemption">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard exemption mechanism names.
      *
diff --git a/ojluni/src/main/java/javax/crypto/KeyAgreement.java b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
index f6decbc..338e682 100644
--- a/ojluni/src/main/java/javax/crypto/KeyAgreement.java
+++ b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,18 +40,18 @@
  * exchange) protocol.
  * <p>
  * The keys involved in establishing a shared secret are created by one of the
- * key generators (<code>KeyPairGenerator</code> or
- * <code>KeyGenerator</code>), a <code>KeyFactory</code>, or as a result from
+ * key generators ({@code KeyPairGenerator} or
+ * {@code KeyGenerator}), a {@code KeyFactory}, or as a result from
  * an intermediate phase of the key agreement protocol.
  *
- * <p> For each of the correspondents in the key exchange, <code>doPhase</code>
+ * <p> For each of the correspondents in the key exchange, {@code doPhase}
  * needs to be called. For example, if this key exchange is with one other
- * party, <code>doPhase</code> needs to be called once, with the
- * <code>lastPhase</code> flag set to <code>true</code>.
+ * party, {@code doPhase} needs to be called once, with the
+ * {@code lastPhase} flag set to {@code true}.
  * If this key exchange is
- * with two other parties, <code>doPhase</code> needs to be called twice,
- * the first time setting the <code>lastPhase</code> flag to
- * <code>false</code>, and the second time setting it to <code>true</code>.
+ * with two other parties, {@code doPhase} needs to be called twice,
+ * the first time setting the {@code lastPhase} flag to
+ * {@code false}, and the second time setting it to {@code true}.
  * There may be any number of parties involved in a key exchange.
  *
  * <p> Android provides the following <code>KeyAgreement</code> algorithms:
@@ -75,7 +75,7 @@
  * </table>
  *
  * This algorithm is described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement">
+ * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
  * KeyAgreement section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -149,20 +149,20 @@
     }
 
     /**
-     * Returns the algorithm name of this <code>KeyAgreement</code> object.
+     * Returns the algorithm name of this {@code KeyAgreement} object.
      *
      * <p>This is the same name that was specified in one of the
-     * <code>getInstance</code> calls that created this
-     * <code>KeyAgreement</code> object.
+     * {@code getInstance} calls that created this
+     * {@code KeyAgreement} object.
      *
-     * @return the algorithm name of this <code>KeyAgreement</code> object.
+     * @return the algorithm name of this {@code KeyAgreement} object.
      */
     public final String getAlgorithm() {
         return this.algorithm;
     }
 
     /**
-     * Returns a <code>KeyAgreement</code> object that implements the
+     * Returns a {@code KeyAgreement} object that implements the
      * specified key agreement algorithm.
      *
      * <p> This method traverses the list of registered security Providers,
@@ -177,11 +177,11 @@
      * @param algorithm the standard name of the requested key agreement
      * algorithm.
      * See the KeyAgreement section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
-     * @return the new <code>KeyAgreement</code> object.
+     * @return the new {@code KeyAgreement} object
      *
      * @exception NullPointerException if the specified algorithm
      *          is null.
@@ -212,7 +212,7 @@
     }
 
     /**
-     * Returns a <code>KeyAgreement</code> object that implements the
+     * Returns a {@code KeyAgreement} object that implements the
      * specified key agreement algorithm.
      *
      * <p> A new KeyAgreement object encapsulating the
@@ -226,13 +226,13 @@
      * @param algorithm the standard name of the requested key agreement
      * algorithm.
      * See the KeyAgreement section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the name of the provider.
      *
-     * @return the new <code>KeyAgreement</code> object.
+     * @return the new {@code KeyAgreement} object
      *
      * @exception NullPointerException if the specified algorithm
      *          is null.
@@ -261,7 +261,7 @@
     }
 
     /**
-     * Returns a <code>KeyAgreement</code> object that implements the
+     * Returns a {@code KeyAgreement} object that implements the
      * specified key agreement algorithm.
      *
      * <p> A new KeyAgreement object encapsulating the
@@ -272,13 +272,13 @@
      * @param algorithm the standard name of the requested key agreement
      * algorithm.
      * See the KeyAgreement section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyAgreement">
-     * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
+     * "{@docRoot}/../specs/security/standard-names.html#keyagreement-algorithms">
+     * Java Security Standard Algorithm Names Specification</a>
      * for information about standard algorithm names.
      *
      * @param provider the provider.
      *
-     * @return the new <code>KeyAgreement</code> object.
+     * @return the new {@code KeyAgreement} object
      *
      * @exception NullPointerException if the specified algorithm
      *          is null.
@@ -366,8 +366,8 @@
         }
     }
 
-    private final static int I_NO_PARAMS = 1;
-    private final static int I_PARAMS    = 2;
+    private static final int I_NO_PARAMS = 1;
+    private static final int I_PARAMS    = 2;
 
     private void implInit(KeyAgreementSpi spi, int type, Key key,
             AlgorithmParameterSpec params, SecureRandom random)
@@ -437,9 +437,9 @@
     }
 
     /**
-     * Returns the provider of this <code>KeyAgreement</code> object.
+     * Returns the provider of this {@code KeyAgreement} object.
      *
-     * @return the provider of this <code>KeyAgreement</code> object
+     * @return the provider of this {@code KeyAgreement} object
      */
     public final Provider getProvider() {
         chooseFirstProvider();
@@ -476,10 +476,10 @@
      * parameters required for this key agreement.
      *
      * <p> If the key agreement algorithm requires random bytes, it gets them
-     * from the given source of randomness, <code>random</code>.
+     * from the given source of randomness, {@code random}.
      * However, if the underlying
      * algorithm implementation does not require any random bytes,
-     * <code>random</code> is ignored.
+     * {@code random} is ignored.
      *
      * @param key the party's private information. For example, in the case
      * of the Diffie-Hellman key agreement, this would be the party's own
@@ -509,7 +509,7 @@
         /*
         if (!skipDebug && pdebug != null) {
             pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
-                this.provider.getName());
+                getProviderName());
         }
         */
     }
@@ -543,6 +543,10 @@
         init(key, params, JceSecurity.RANDOM);
     }
 
+    private String getProviderName() {
+        return (provider == null) ? "(no provider)" : provider.getName();
+    }
+
     /**
      * Initializes this key agreement with the given key, set of
      * algorithm parameters, and source of randomness.
@@ -573,7 +577,7 @@
         /*
         if (!skipDebug && pdebug != null) {
             pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
-                this.provider.getName());
+                getProviderName());
         }
         */
     }
@@ -607,9 +611,9 @@
     /**
      * Generates the shared secret and returns it in a new buffer.
      *
-     * <p>This method resets this <code>KeyAgreement</code> object, so that it
+     * <p>This method resets this {@code KeyAgreement} object, so that it
      * can be reused for further key agreements. Unless this key agreement is
-     * reinitialized with one of the <code>init</code> methods, the same
+     * reinitialized with one of the {@code init} methods, the same
      * private information and algorithm parameters will be used for
      * subsequent key agreements.
      *
@@ -625,23 +629,23 @@
 
     /**
      * Generates the shared secret, and places it into the buffer
-     * <code>sharedSecret</code>, beginning at <code>offset</code> inclusive.
+     * {@code sharedSecret}, beginning at {@code offset} inclusive.
      *
-     * <p>If the <code>sharedSecret</code> buffer is too small to hold the
-     * result, a <code>ShortBufferException</code> is thrown.
+     * <p>If the {@code sharedSecret} buffer is too small to hold the
+     * result, a {@code ShortBufferException} is thrown.
      * In this case, this call should be repeated with a larger output buffer.
      *
-     * <p>This method resets this <code>KeyAgreement</code> object, so that it
+     * <p>This method resets this {@code KeyAgreement} object, so that it
      * can be reused for further key agreements. Unless this key agreement is
-     * reinitialized with one of the <code>init</code> methods, the same
+     * reinitialized with one of the {@code init} methods, the same
      * private information and algorithm parameters will be used for
      * subsequent key agreements.
      *
      * @param sharedSecret the buffer for the shared secret
-     * @param offset the offset in <code>sharedSecret</code> where the
+     * @param offset the offset in {@code sharedSecret} where the
      * shared secret will be stored
      *
-     * @return the number of bytes placed into <code>sharedSecret</code>
+     * @return the number of bytes placed into {@code sharedSecret}
      *
      * @exception IllegalStateException if this key agreement has not been
      * completed yet
@@ -656,12 +660,12 @@
     }
 
     /**
-     * Creates the shared secret and returns it as a <code>SecretKey</code>
+     * Creates the shared secret and returns it as a {@code SecretKey}
      * object of the specified algorithm.
      *
-     * <p>This method resets this <code>KeyAgreement</code> object, so that it
+     * <p>This method resets this {@code KeyAgreement} object, so that it
      * can be reused for further key agreements. Unless this key agreement is
-     * reinitialized with one of the <code>init</code> methods, the same
+     * reinitialized with one of the {@code init} methods, the same
      * private information and algorithm parameters will be used for
      * subsequent key agreements.
      *
diff --git a/ojluni/src/main/java/javax/crypto/KeyGenerator.java b/ojluni/src/main/java/javax/crypto/KeyGenerator.java
index 0b30338..5951eef 100644
--- a/ojluni/src/main/java/javax/crypto/KeyGenerator.java
+++ b/ojluni/src/main/java/javax/crypto/KeyGenerator.java
@@ -156,7 +156,7 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
  * KeyGenerator section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -272,7 +272,7 @@
      *
      * @param algorithm the standard name of the requested key algorithm.
      * See the KeyGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -305,7 +305,7 @@
      *
      * @param algorithm the standard name of the requested key algorithm.
      * See the KeyGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -349,7 +349,7 @@
      *
      * @param algorithm the standard name of the requested key algorithm.
      * See the KeyGenerator section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/crypto/Mac.java b/ojluni/src/main/java/javax/crypto/Mac.java
index 749b627..f70a697 100644
--- a/ojluni/src/main/java/javax/crypto/Mac.java
+++ b/ojluni/src/main/java/javax/crypto/Mac.java
@@ -142,7 +142,7 @@
  * </table>
  *
  * These algorithms are described in the
- * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac">
+ * <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
  * Mac section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -243,7 +243,7 @@
      *
      * @param algorithm the standard name of the requested MAC algorithm.
      * See the Mac section in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -287,7 +287,7 @@
      *
      * @param algorithm the standard name of the requested MAC algorithm.
      * See the Mac section in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -327,7 +327,7 @@
      *
      * @param algorithm the standard name of the requested MAC algorithm.
      * See the Mac section in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Mac">
+     *   "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java b/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java
index 659df8d..bd8b271 100644
--- a/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java
+++ b/ojluni/src/main/java/javax/crypto/SecretKeyFactory.java
@@ -251,7 +251,7 @@
  * </table>
  *
  * These algorithms are described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
  * SecretKeyFactory section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -324,7 +324,7 @@
      * @param algorithm the standard name of the requested secret-key
      * algorithm.
      * See the SecretKeyFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -359,7 +359,7 @@
      * @param algorithm the standard name of the requested secret-key
      * algorithm.
      * See the SecretKeyFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
@@ -405,7 +405,7 @@
      * @param algorithm the standard name of the requested secret-key
      * algorithm.
      * See the SecretKeyFactory section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SecretKeyFactory">
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/crypto/interfaces/package.html b/ojluni/src/main/java/javax/crypto/interfaces/package.html
index 75ef6fe..8b18ce2 100644
--- a/ojluni/src/main/java/javax/crypto/interfaces/package.html
+++ b/ojluni/src/main/java/javax/crypto/interfaces/package.html
@@ -46,7 +46,7 @@
 cryptographic provider developer guide:
 <ul>
   <li><a href=
-    "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html">
+    "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html">
     <b>How to Implement a Provider for the
     Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture
     </b></a></li>
@@ -65,7 +65,7 @@
 <ul>
   <li>
     <a href=
-      "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">
+      "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
       <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
       Cryptography Architecture API Specification and Reference
       </b></a></li>
diff --git a/ojluni/src/main/java/javax/crypto/package.html b/ojluni/src/main/java/javax/crypto/package.html
index bd4c05a..1518573 100644
--- a/ojluni/src/main/java/javax/crypto/package.html
+++ b/ojluni/src/main/java/javax/crypto/package.html
@@ -47,7 +47,7 @@
 <h2>Package Specification</h2>
 
 <ul>
-  <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html"><b>
+  <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"><b>
     <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
     Cryptography Architecture Standard Algorithm Name
     Documentation</b></a></li>
@@ -59,13 +59,13 @@
 <ul>
   <li>
     <a href=
-      "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">
+      "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
       <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
        Cryptography Architecture (JCA) Reference Guide
       </b></a></li>
   <li>
     <a href=
-      "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html">
+      "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html">
       <b>How to Implement a Provider in the
       Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture
       </b></a></li>
diff --git a/ojluni/src/main/java/javax/crypto/spec/GCMParameterSpec.java b/ojluni/src/main/java/javax/crypto/spec/GCMParameterSpec.java
index 403205a..879d729 100644
--- a/ojluni/src/main/java/javax/crypto/spec/GCMParameterSpec.java
+++ b/ojluni/src/main/java/javax/crypto/spec/GCMParameterSpec.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,7 @@
 
         // Input sanity check
         if ((src == null) ||(len < 0) || (offset < 0)
-                || ((len + offset) > src.length)) {
+                || (len > (src.length - offset))) {
             throw new IllegalArgumentException("Invalid buffer arguments");
         }
 
diff --git a/ojluni/src/main/java/javax/crypto/spec/IvParameterSpec.java b/ojluni/src/main/java/javax/crypto/spec/IvParameterSpec.java
index 243c848..6a3d311 100644
--- a/ojluni/src/main/java/javax/crypto/spec/IvParameterSpec.java
+++ b/ojluni/src/main/java/javax/crypto/spec/IvParameterSpec.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,13 +76,16 @@
         if (iv == null) {
             throw new IllegalArgumentException("IV missing");
         }
-        if (iv.length - offset < len) {
-            throw new IllegalArgumentException
-                ("IV buffer too short for given offset/length combination");
+        if (offset < 0) {
+            throw new ArrayIndexOutOfBoundsException("offset is negative");
         }
         if (len < 0) {
             throw new ArrayIndexOutOfBoundsException("len is negative");
         }
+        if (iv.length - offset < len) {
+            throw new IllegalArgumentException
+                ("IV buffer too short for given offset/length combination");
+        }
         this.iv = new byte[len];
         System.arraycopy(iv, offset, this.iv, 0, len);
     }
diff --git a/ojluni/src/main/java/javax/crypto/spec/PBEKeySpec.java b/ojluni/src/main/java/javax/crypto/spec/PBEKeySpec.java
index 239231d..8f8d141 100644
--- a/ojluni/src/main/java/javax/crypto/spec/PBEKeySpec.java
+++ b/ojluni/src/main/java/javax/crypto/spec/PBEKeySpec.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package javax.crypto.spec;
 
 import java.security.spec.KeySpec;
+import java.util.Arrays;
 
 /**
  * A user-chosen password that can be used with password-based encryption
@@ -174,9 +175,7 @@
      */
     public final void clearPassword() {
         if (password != null) {
-            for (int i = 0; i < password.length; i++) {
-                password[i] = ' ';
-            }
+            Arrays.fill(password, ' ');
             password = null;
         }
     }
diff --git a/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java b/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java
index ff1258c..767c0d2 100644
--- a/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java
+++ b/ojluni/src/main/java/javax/crypto/spec/SecretKeySpec.java
@@ -82,7 +82,7 @@
      * @param algorithm the name of the secret-key algorithm to be associated
      * with the given key material.
      * See Appendix A in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     *   "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
      * Java Cryptography Architecture Reference Guide</a>
      * for information about standard algorithm names.
      * @exception IllegalArgumentException if <code>algorithm</code>
@@ -127,7 +127,7 @@
      * @param algorithm the name of the secret-key algorithm to be associated
      * with the given key material.
      * See Appendix A in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     *   "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
      * Java Cryptography Architecture Reference Guide</a>
      * for information about standard algorithm names.
      * @exception IllegalArgumentException if <code>algorithm</code>
diff --git a/ojluni/src/main/java/javax/crypto/spec/package.html b/ojluni/src/main/java/javax/crypto/spec/package.html
index 3e30aa1..b8fd807 100644
--- a/ojluni/src/main/java/javax/crypto/spec/package.html
+++ b/ojluni/src/main/java/javax/crypto/spec/package.html
@@ -61,13 +61,13 @@
 <ul>
   <li>
     <a href=
-      "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html">
+      "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
       <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
       Cryptography Architecture API Specification and Reference
       </b></a></li>
   <li>
     <a href=
-      "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/HowToImplAProvider.html">
+      "{@docRoot}/../technotes/guides/security/crypto/HowToImplAProvider.html">
       <b>How to Implement a Provider for the
       Java<FONT SIZE=-2><SUP>TM</SUP></FONT> Cryptography Architecture
       </b></a></li>
diff --git a/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java b/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java
index 2d832f3..70f98ce 100644
--- a/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java
+++ b/ojluni/src/main/java/javax/net/ssl/ExtendedSSLSession.java
@@ -45,7 +45,7 @@
      * The signature algorithm name must be a standard Java Security
      * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
      * See Appendix A in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
      * Java Cryptography Architecture API Specification &amp; Reference </a>
      * for information about standard algorithm names.
      * <p>
@@ -73,7 +73,7 @@
      * The signature algorithm name must be a standard Java Security
      * name (such as "SHA1withRSA", "SHA256withECDSA", and so on).
      * See Appendix A in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
      * Java Cryptography Architecture API Specification &amp; Reference </a>
      * for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java b/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java
index 04af51a..7ae790c 100644
--- a/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java
+++ b/ojluni/src/main/java/javax/net/ssl/KeyManagerFactory.java
@@ -134,7 +134,7 @@
      *
      * @param algorithm the standard name of the requested algorithm.
      *          See the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">
+     *  "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
@@ -170,7 +170,7 @@
 
      * @param algorithm the standard name of the requested algorithm.
      *          See the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">
+     *  "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
@@ -211,7 +211,7 @@
      *
      * @param algorithm the standard name of the requested algorithm.
      *          See the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">
+     *  "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLContext.java b/ojluni/src/main/java/javax/net/ssl/SSLContext.java
index b580a72..eb7322c 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLContext.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLContext.java
@@ -82,7 +82,7 @@
  * </table>
  *
  * This protocol is described in the <a href=
- * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">
+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext">
  * SSLContext section</a> of the
  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  *
@@ -180,7 +180,7 @@
      *
      * @param protocol the standard name of the requested protocol.
      *          See the SSLContext section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext">
      *          Java Cryptography Architecture Standard Algorithm Name
      *          Documentation</a>
      *          for information about standard protocol names.
@@ -216,7 +216,7 @@
      *
      * @param protocol the standard name of the requested protocol.
      *          See the SSLContext section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext">
      *          Java Cryptography Architecture Standard Algorithm Name
      *          Documentation</a>
      *          for information about standard protocol names.
@@ -256,7 +256,7 @@
      *
      * @param protocol the standard name of the requested protocol.
      *          See the SSLContext section in the <a href=
-     * "https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext">
+     * "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext">
      *          Java Cryptography Architecture Standard Algorithm Name
      *          Documentation</a>
      *          for information about standard protocol names.
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLParameters.java b/ojluni/src/main/java/javax/net/ssl/SSLParameters.java
index 41dcf0f..ecb0fe4 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLParameters.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLParameters.java
@@ -248,16 +248,17 @@
         return identificationAlgorithm;
     }
 
+    // Android-changed: Use "on-path" to comply with Android's inclusive language guidance.
     /**
      * Sets the endpoint identification algorithm.
      * <p>
      * If the <code>algorithm</code> parameter is non-null or non-empty, the
      * endpoint identification/verification procedures must be handled during
-     * SSL/TLS handshaking.  This is to prevent man-in-the-middle attacks.
+     * SSL/TLS handshaking.  This is to prevent on-path attacks.
      *
      * @param algorithm The standard string name of the endpoint
      *     identification algorithm (or null).  See Appendix A in the <a href=
-     *   "https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA">
+     *   "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA">
      *     Java Cryptography Architecture API Specification &amp; Reference </a>
      *     for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLSessionContext.java b/ojluni/src/main/java/javax/net/ssl/SSLSessionContext.java
index b6f6fb6..04a02fb 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLSessionContext.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLSessionContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,10 +87,17 @@
      * A check for sessions exceeding the timeout is made immediately whenever
      * the timeout limit is changed for this <code>SSLSessionContext</code>.
      *
-     * @param seconds the new session timeout limit in seconds; zero means
-     *          there is no limit.
+     * @apiNote Note that the JDK Implementation uses default values for both
+     *          the session cache size and timeout.  See
+     *          {@code getSessionCacheSize} and {@code getSessionTimeout} for
+     *          more information.  Applications should consider their
+     *          performance requirements and override the defaults if necessary.
      *
-     * @exception IllegalArgumentException if the timeout specified is {@code < 0}.
+     * @param seconds the new session timeout limit in seconds; zero means
+     *        there is no limit.
+     *
+     * @throws IllegalArgumentException if the timeout specified is {@code < 0}.
+     *
      * @see #getSessionTimeout
      */
     public void setSessionTimeout(int seconds)
@@ -109,33 +116,51 @@
      * whenever the timeout limit is changed for this
      * <code>SSLSessionContext</code>.
      *
+     * @implNote The JDK implementation returns the session timeout as set by
+     *           the {@code setSessionTimeout} method, or if not set, a default
+     *           value of 86400 seconds (24 hours).
+     *
      * @return the session timeout limit in seconds; zero means there is no
-     * limit.
+     *         limit.
+     *
      * @see #setSessionTimeout
      */
     public int getSessionTimeout();
 
     /**
-     * Sets the size of the cache used for storing
-     * <code>SSLSession</code> objects grouped under this
-     * <code>SSLSessionContext</code>.
+     * Sets the size of the cache used for storing <code>SSLSession</code>
+     * objects grouped under this <code>SSLSessionContext</code>.
+     *
+     * @apiNote Note that the JDK Implementation uses default values for both
+     *          the session cache size and timeout.  See
+     *          {@code getSessionCacheSize} and {@code getSessionTimeout} for
+     *          more information.  Applications should consider their
+     *          performance requirements and override the defaults if necessary.
      *
      * @param size the new session cache size limit; zero means there is no
-     * limit.
-     * @exception IllegalArgumentException if the specified size is {@code < 0}.
+     *        limit.
+     *
+     * @throws IllegalArgumentException if the specified size is {@code < 0}.
+     *
      * @see #getSessionCacheSize
      */
     public void setSessionCacheSize(int size)
                  throws IllegalArgumentException;
 
+    // Android-changed: Modified unsupported @systemProperty javadoc tag.
     /**
-     * Returns the size of the cache used for storing
-     * <code>SSLSession</code> objects grouped under this
-     * <code>SSLSessionContext</code>.
+     * Returns the size of the cache used for storing <code>SSLSession</code>
+     * objects grouped under this <code>SSLSessionContext</code>.
+     *
+     * @implNote The JDK implementation returns the cache size as set by
+     *           the {@code setSessionCacheSize} method, or if not set, the
+     *           value of the {@code javax.net.ssl.sessionCacheSize}
+     *           system property.  If neither is set, it returns a default
+     *           value of 20480.
      *
      * @return size of the session cache; zero means there is no size limit.
+     *
      * @see #setSessionCacheSize
      */
     public int getSessionCacheSize();
-
 }
diff --git a/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java b/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java
index 7322169..d76f5fb 100644
--- a/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java
+++ b/ojluni/src/main/java/javax/net/ssl/TrustManagerFactory.java
@@ -136,7 +136,7 @@
      *
      * @param algorithm the standard name of the requested trust management
      *          algorithm.  See the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">
+     *  "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
@@ -172,7 +172,7 @@
      *
      * @param algorithm the standard name of the requested trust management
      *          algorithm.  See the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">
+     *  "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
@@ -213,7 +213,7 @@
      *
      * @param algorithm the standard name of the requested trust management
      *          algorithm.  See the <a href=
-     *  "https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html">
+     *  "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
diff --git a/ojluni/src/main/java/javax/net/ssl/package.html b/ojluni/src/main/java/javax/net/ssl/package.html
index 0f87f45..5213137 100644
--- a/ojluni/src/main/java/javax/net/ssl/package.html
+++ b/ojluni/src/main/java/javax/net/ssl/package.html
@@ -37,7 +37,7 @@
 <h2>Package Specification</h2>
 
 <ul>
-  <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html">
+  <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
     <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
     Cryptography Architecture Standard Algorithm Name
     Documentation</b></a></li>
diff --git a/ojluni/src/main/java/javax/security/auth/login/package-info.java b/ojluni/src/main/java/javax/security/auth/login/package-info.java
index 6bb5a06..5b43480 100644
--- a/ojluni/src/main/java/javax/security/auth/login/package-info.java
+++ b/ojluni/src/main/java/javax/security/auth/login/package-info.java
@@ -28,7 +28,7 @@
  * <h2>Package Specification</h2>
  *
  * <ul>
- *   <li><a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html">
+ *   <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
  *     <b>Java&trade;
  *     Cryptography Architecture Standard Algorithm Name
  *     Documentation</b></a></li>
diff --git a/ojluni/src/main/java/jdk/internal/HotSpotIntrinsicCandidate.java b/ojluni/src/main/java/jdk/internal/HotSpotIntrinsicCandidate.java
new file mode 100644
index 0000000..cfba310
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/HotSpotIntrinsicCandidate.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal;
+
+import java.lang.annotation.*;
+
+// Android-note: HotSpot-specific implementation notes not relevant for Android.
+/**
+ * The {@code @HotSpotIntrinsicCandidate} annotation is specific to the
+ * HotSpot Virtual Machine. It indicates that an annotated method
+ * may be (but is not guaranteed to be) intrinsified by the HotSpot VM. A method
+ * is intrinsified if the HotSpot VM replaces the annotated method with hand-written
+ * assembly and/or hand-written compiler IR -- a compiler intrinsic -- to improve
+ * performance. The {@code @HotSpotIntrinsicCandidate} annotation is internal to the
+ * Java libraries and is therefore not supposed to have any relevance for application
+ * code.
+ *
+ * Maintainers of the Java libraries must consider the following when
+ * modifying methods annotated with {@code @HotSpotIntrinsicCandidate}.
+ *
+ * <ul>
+ * <li>When modifying a method annotated with {@code @HotSpotIntrinsicCandidate},
+ * the corresponding intrinsic code in the HotSpot VM implementation must be
+ * updated to match the semantics of the annotated method.</li>
+ * <li>For some annotated methods, the corresponding intrinsic may omit some low-level
+ * checks that would be performed as a matter of course if the intrinsic is implemented
+ * using Java bytecodes. This is because individual Java bytecodes implicitly check
+ * for exceptions like {@code NullPointerException} and {@code ArrayStoreException}.
+ * If such a method is replaced by an intrinsic coded in assembly language, any
+ * checks performed as a matter of normal bytecode operation must be performed
+ * before entry into the assembly code. These checks must be performed, as
+ * appropriate, on all arguments to the intrinsic, and on other values (if any) obtained
+ * by the intrinsic through those arguments. The checks may be deduced by inspecting
+ * the non-intrinsic Java code for the method, and determining exactly which exceptions
+ * may be thrown by the code, including undeclared implicit {@code RuntimeException}s.
+ * Therefore, depending on the data accesses performed by the intrinsic,
+ * the checks may include:
+ *
+ *  <ul>
+ *  <li>null checks on references</li>
+ *  <li>range checks on primitive values used as array indexes</li>
+ *  <li>other validity checks on primitive values (e.g., for divide-by-zero conditions)</li>
+ *  <li>store checks on reference values stored into arrays</li>
+ *  <li>array length checks on arrays indexed from within the intrinsic</li>
+ *  <li>reference casts (when formal parameters are {@code Object} or some other weak type)</li>
+ *  </ul>
+ *
+ * </li>
+ *
+ * <li>Note that the receiver value ({@code this}) is passed as a extra argument
+ * to all non-static methods. If a non-static method is an intrinsic, the receiver
+ * value does not need a null check, but (as stated above) any values loaded by the
+ * intrinsic from object fields must also be checked. As a matter of clarity, it is
+ * better to make intrinisics be static methods, to make the dependency on {@code this}
+ * clear. Also, it is better to explicitly load all required values from object
+ * fields before entering the intrinsic code, and pass those values as explicit arguments.
+ * First, this may be necessary for null checks (or other checks). Second, if the
+ * intrinsic reloads the values from fields and operates on those without checks,
+ * race conditions may be able to introduce unchecked invalid values into the intrinsic.
+ * If the intrinsic needs to store a value back to an object field, that value should be
+ * returned explicitly from the intrinsic; if there are multiple return values, coders
+ * should consider buffering them in an array. Removing field access from intrinsics
+ * not only clarifies the interface with between the JVM and JDK; it also helps decouple
+ * the HotSpot and JDK implementations, since if JDK code before and after the intrinsic
+ * manages all field accesses, then intrinsics can be coded to be agnostic of object
+ * layouts.</li>
+ *
+ * Maintainers of the HotSpot VM must consider the following when modifying
+ * intrinsics.
+ *
+ * <ul>
+ * <li>When adding a new intrinsic, make sure that the corresponding method
+ * in the Java libraries is annotated with {@code @HotSpotIntrinsicCandidate}
+ * and that all possible call sequences that result in calling the intrinsic contain
+ * the checks omitted by the intrinsic (if any).</li>
+ * <li>When modifying an existing intrinsic, the Java libraries must be updated
+ * to match the semantics of the intrinsic and to execute all checks omitted
+ * by the intrinsic (if any).</li>
+ * </ul>
+ *
+ * Persons not directly involved with maintaining the Java libraries or the
+ * HotSpot VM can safely ignore the fact that a method is annotated with
+ * {@code @HotSpotIntrinsicCandidate}.
+ *
+ * The HotSpot VM defines (internally) a list of intrinsics. Not all intrinsic
+ * are available on all platforms supported by the HotSpot VM. Furthermore,
+ * the availability of an intrinsic on a given platform depends on the
+ * configuration of the HotSpot VM (e.g., the set of VM flags enabled).
+ * Therefore, annotating a method with {@code @HotSpotIntrinsicCandidate} does
+ * not guarantee that the marked method is intrinsified by the HotSpot VM.
+ *
+ * If the {@code CheckIntrinsics} VM flag is enabled, the HotSpot VM checks
+ * (when loading a class) that (1) all methods of that class that are also on
+ * the VM's list of intrinsics are annotated with {@code @HotSpotIntrinsicCandidate}
+ * and that (2) for all methods of that class annotated with
+ * {@code @HotSpotIntrinsicCandidate} there is an intrinsic in the list.
+ *
+ * @since 9
+ */
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+// Android-changed: RetentionPolicy.SOURCE is sufficient as this is no-op on Android.
+// @Retention(RetentionPolicy.RUNTIME)
+@Retention(RetentionPolicy.SOURCE)
+public @interface HotSpotIntrinsicCandidate {
+}
diff --git a/ojluni/src/main/java/jdk/internal/math/DoubleConsts.java b/ojluni/src/main/java/jdk/internal/math/DoubleConsts.java
new file mode 100644
index 0000000..57e835b
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/math/DoubleConsts.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * {@code double} type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+public class DoubleConsts {
+    /**
+     * Don't let anyone instantiate this class.
+     */
+    private DoubleConsts() {}
+
+    public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
+    public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
+    public static final double NaN = java.lang.Double.NaN;
+    public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
+    public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
+
+    /**
+     * A constant holding the smallest positive normal value of type
+     * <code>double</code>, 2<sup>-1022</sup>.  It is equal to the
+     * value returned by
+     * <code>Double.longBitsToDouble(0x0010000000000000L)</code>.
+     *
+     * @since 1.5
+     */
+    public static final double  MIN_NORMAL      = 2.2250738585072014E-308;
+
+
+    /**
+     * The number of logical bits in the significand of a
+     * {@code double} number, including the implicit bit.
+     */
+    public static final int SIGNIFICAND_WIDTH   = 53;
+
+    /**
+     * Maximum exponent a finite <code>double</code> number may have.
+     * It is equal to the value returned by
+     * <code>Math.ilogb(Double.MAX_VALUE)</code>.
+     */
+    public static final int     MAX_EXPONENT    = 1023;
+
+    /**
+     * Minimum exponent a normalized <code>double</code> number may
+     * have.  It is equal to the value returned by
+     * <code>Math.ilogb(Double.MIN_NORMAL)</code>.
+     */
+    public static final int     MIN_EXPONENT    = -1022;
+
+    /**
+     * The exponent the smallest positive {@code double}
+     * subnormal value would have if it could be normalized..
+     */
+    public static final int     MIN_SUB_EXPONENT = Double.MIN_EXPONENT -
+                                                   (SIGNIFICAND_WIDTH - 1);
+
+    /**
+     * Bias used in representing a {@code double} exponent.
+     */
+    public static final int     EXP_BIAS        = 1023;
+
+    /**
+     * Bit mask to isolate the sign bit of a {@code double}.
+     */
+    public static final long    SIGN_BIT_MASK   = 0x8000000000000000L;
+
+    /**
+     * Bit mask to isolate the exponent field of a
+     * {@code double}.
+     */
+    public static final long    EXP_BIT_MASK    = 0x7FF0000000000000L;
+
+    /**
+     * Bit mask to isolate the significand field of a
+     * {@code double}.
+     */
+    public static final long    SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;
+
+    static {
+        // verify bit masks cover all bit positions and that the bit
+        // masks are non-overlapping
+        assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) &&
+               (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) &&
+                ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) &&
+                ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L)));
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/math/FDBigInteger.java b/ojluni/src/main/java/jdk/internal/math/FDBigInteger.java
new file mode 100644
index 0000000..ba3ce9b
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/math/FDBigInteger.java
@@ -0,0 +1,1508 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.math;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+//@ model import org.jmlspecs.models.JMLMath;
+
+/**
+ * A simple big integer package specifically for floating point base conversion.
+ */
+public /*@ spec_bigint_math @*/ class FDBigInteger {
+
+    //
+    // This class contains many comments that start with "/*@" mark.
+    // They are behavourial specification in
+    // the Java Modelling Language (JML):
+    // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
+    //
+
+    /*@
+    @ public pure model static \bigint UNSIGNED(int v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 32);
+    @ }
+    @
+    @ public pure model static \bigint UNSIGNED(long v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 64);
+    @ }
+    @
+    @ public pure model static \bigint AP(int[] data, int len) {
+    @     return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
+    @ }
+    @
+    @ public pure model static \bigint pow52(int p5, int p2) {
+    @     ghost \bigint v = 1;
+    @     for (int i = 0; i < p5; i++) v *= 5;
+    @     return v << p2;
+    @ }
+    @
+    @ public pure model static \bigint pow10(int p10) {
+    @     return pow52(p10, p10);
+    @ }
+    @*/
+
+    static final int[] SMALL_5_POW = {
+            1,
+            5,
+            5 * 5,
+            5 * 5 * 5,
+            5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+    };
+
+    static final long[] LONG_5_POW = {
+            1L,
+            5L,
+            5L * 5,
+            5L * 5 * 5,
+            5L * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+    };
+
+    // Maximum size of cache of powers of 5 as FDBigIntegers.
+    private static final int MAX_FIVE_POW = 340;
+
+    // Cache of big powers of 5 as FDBigIntegers.
+    private static final FDBigInteger POW_5_CACHE[];
+
+    // Initialize FDBigInteger cache of powers of 5.
+    static {
+        POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
+        int i = 0;
+        while (i < SMALL_5_POW.length) {
+            FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
+            pow5.makeImmutable();
+            POW_5_CACHE[i] = pow5;
+            i++;
+        }
+        FDBigInteger prev = POW_5_CACHE[i - 1];
+        while (i < MAX_FIVE_POW) {
+            POW_5_CACHE[i] = prev = prev.mult(5);
+            prev.makeImmutable();
+            i++;
+        }
+    }
+
+    // Zero as an FDBigInteger.
+    public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
+
+    // Ensure ZERO is immutable.
+    static {
+        ZERO.makeImmutable();
+    }
+
+    // Constant for casting an int to a long via bitwise AND.
+    private static final long LONG_MASK = 0xffffffffL;
+
+    //@ spec_public non_null;
+    private int data[];  // value: data[0] is least significant
+    //@ spec_public;
+    private int offset;  // number of least significant zero padding ints
+    //@ spec_public;
+    private int nWords;  // data[nWords-1]!=0, all values above are zero
+                 // if nWords==0 -> this FDBigInteger is zero
+    //@ spec_public;
+    private boolean isImmutable = false;
+
+    /*@
+     @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ public invariant nWords == 0 ==> offset == 0;
+     @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
+     @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
+     @ public pure model \bigint value() {
+     @     return AP(data, nWords) << (offset*32);
+     @ }
+     @*/
+
+    /**
+     * Constructs an <code>FDBigInteger</code> from data and padding. The
+     * <code>data</code> parameter has the least significant <code>int</code> at
+     * the zeroth index. The <code>offset</code> parameter gives the number of
+     * zero <code>int</code>s to be inferred below the least significant element
+     * of <code>data</code>.
+     *
+     * @param data An array containing all non-zero <code>int</code>s of the value.
+     * @param offset An offset indicating the number of zero <code>int</code>s to pad
+     * below the least significant element of <code>data</code>.
+     */
+    /*@
+     @ requires data != null && offset >= 0;
+     @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
+     @ ensures this.data == \old(data);
+     @*/
+    private FDBigInteger(int[] data, int offset) {
+        this.data = data;
+        this.offset = offset;
+        this.nWords = data.length;
+        trimLeadingZeros();
+    }
+
+    /**
+     * Constructs an <code>FDBigInteger</code> from a starting value and some
+     * decimal digits.
+     *
+     * @param lValue The starting value.
+     * @param digits The decimal digits.
+     * @param kDigits The initial index into <code>digits</code>.
+     * @param nDigits The final index into <code>digits</code>.
+     */
+    /*@
+     @ requires digits != null;
+     @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
+     @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
+     @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
+     @*/
+    public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
+        int n = Math.max((nDigits + 8) / 9, 2);        // estimate size needed.
+        data = new int[n];      // allocate enough space
+        data[0] = (int) lValue;    // starting value
+        data[1] = (int) (lValue >>> 32);
+        offset = 0;
+        nWords = 2;
+        int i = kDigits;
+        int limit = nDigits - 5;       // slurp digits 5 at a time.
+        int v;
+        while (i < limit) {
+            int ilim = i + 5;
+            v = (int) digits[i++] - (int) '0';
+            while (i < ilim) {
+                v = 10 * v + (int) digits[i++] - (int) '0';
+            }
+            multAddMe(100000, v); // ... where 100000 is 10^5.
+        }
+        int factor = 1;
+        v = 0;
+        while (i < nDigits) {
+            v = 10 * v + (int) digits[i++] - (int) '0';
+            factor *= 10;
+        }
+        if (factor != 1) {
+            multAddMe(factor, v);
+        }
+        trimLeadingZeros();
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     *
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfPow52(int p5, int p2) {
+        if (p5 != 0) {
+            if (p2 == 0) {
+                return big5pow(p5);
+            } else if (p5 < SMALL_5_POW.length) {
+                int pow5 = SMALL_5_POW[p5];
+                int wordcount = p2 >> 5;
+                int bitcount = p2 & 0x1f;
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{pow5}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            pow5 << bitcount,
+                            pow5 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                return big5pow(p5).leftShift(p2);
+            }
+        } else {
+            return valueOfPow2(p2);
+        }
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     *
+     * @param value The constant factor.
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
+        assert p5 >= 0 : p5;
+        assert p2 >= 0 : p2;
+        int v0 = (int) value;
+        int v1 = (int) (value >>> 32);
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        if (p5 != 0) {
+            if (p5 < SMALL_5_POW.length) {
+                long pow5 = SMALL_5_POW[p5] & LONG_MASK;
+                long carry = (v0 & LONG_MASK) * pow5;
+                v0 = (int) carry;
+                carry >>>= 32;
+                carry = (v1 & LONG_MASK) * pow5 + carry;
+                v1 = (int) carry;
+                int v2 = (int) (carry >>> 32);
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            v0 << bitcount,
+                            (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                            (v2 << bitcount) | (v1 >>> (32 - bitcount)),
+                            v2 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                FDBigInteger pow5 = big5pow(p5);
+                int[] r;
+                if (v1 == 0) {
+                    r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, r);
+                } else {
+                    r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, v1, r);
+                }
+                return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
+            }
+        } else if (p2 != 0) {
+            if (bitcount == 0) {
+                return new FDBigInteger(new int[]{v0, v1}, wordcount);
+            } else {
+                return new FDBigInteger(new int[]{
+                         v0 << bitcount,
+                        (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                        v1 >>> (32 - bitcount)
+                }, wordcount);
+            }
+        }
+        return new FDBigInteger(new int[]{v0, v1}, 0);
+    }
+
+    /**
+     * Returns an <code>FDBigInteger</code> with the numerical value
+     * <code>2<sup>p2</sup></code>.
+     *
+     * @param p2 The exponent of 2.
+     * @return <code>2<sup>p2</sup></code>
+     */
+    /*@
+     @ requires p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == pow52(0, p2);
+     @*/
+    private static FDBigInteger valueOfPow2(int p2) {
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
+    }
+
+    /**
+     * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
+     * the offset and number of non-zero leading words accordingly.
+     */
+    /*@
+     @ requires data != null;
+     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ requires nWords == 0 ==> offset == 0;
+     @ ensures nWords == 0 ==> offset == 0;
+     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+     @*/
+    private /*@ helper @*/ void trimLeadingZeros() {
+        int i = nWords;
+        if (i > 0 && (data[--i] == 0)) {
+            //for (; i > 0 && data[i - 1] == 0; i--) ;
+            while(i > 0 && data[i - 1] == 0) {
+                i--;
+            }
+            this.nWords = i;
+            if (i == 0) { // all words are zero
+                this.offset = 0;
+            }
+        }
+    }
+
+    /**
+     * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
+     * normalization bias is a left shift such that after it the highest word
+     * of the value will have the 4 highest bits equal to zero:
+     * {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1
+     * {@code (highestWord & 0x08000000) != 0}.
+     *
+     * @return The normalization bias.
+     */
+    /*@
+     @ requires this.value() > 0;
+     @*/
+    public /*@ pure @*/ int getNormalizationBias() {
+        if (nWords == 0) {
+            throw new IllegalArgumentException("Zero value cannot be normalized");
+        }
+        int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
+        return (zeros < 4) ? 28 + zeros : zeros - 4;
+    }
+
+    // TODO: Why is anticount param needed if it is always 32 - bitcount?
+    /**
+     * Left shifts the contents of one int array into another.
+     *
+     * @param src The source array.
+     * @param idx The initial index of the source array.
+     * @param result The destination array.
+     * @param bitcount The left shift.
+     * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
+     * @param prev The prior source value.
+     */
+    /*@
+     @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
+     @ requires src.length >= idx && result.length > idx;
+     @ assignable result[*];
+     @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
+     @*/
+    private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
+        for (; idx > 0; idx--) {
+            int v = (prev << bitcount);
+            prev = src[idx - 1];
+            v |= (prev >>> anticount);
+            result[idx] = v;
+        }
+        int v = prev << bitcount;
+        result[0] = v;
+    }
+
+    /**
+     * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
+     * in-place unless the <code>FDBigInteger</code> is immutable in which case
+     * a new instance of <code>FDBigInteger</code> is returned.
+     *
+     * @param shift The number of bits to shift left.
+     * @return The shifted <code>FDBigInteger</code>.
+     */
+    /*@
+     @ requires this.value() == 0 || shift == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @*/
+    public FDBigInteger leftShift(int shift) {
+        if (shift == 0 || nWords == 0) {
+            return this;
+        }
+        int wordcount = shift >> 5;
+        int bitcount = shift & 0x1f;
+        if (this.isImmutable) {
+            if (bitcount == 0) {
+                return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
+            } else {
+                int anticount = 32 - bitcount;
+                int idx = nWords - 1;
+                int prev = data[idx];
+                int hi = prev >>> anticount;
+                int[] result;
+                if (hi != 0) {
+                    result = new int[nWords + 1];
+                    result[nWords] = hi;
+                } else {
+                    result = new int[nWords];
+                }
+                leftShift(data,idx,result,bitcount,anticount,prev);
+                return new FDBigInteger(result, offset + wordcount);
+            }
+        } else {
+            if (bitcount != 0) {
+                int anticount = 32 - bitcount;
+                if ((data[0] << bitcount) == 0) {
+                    int idx = 0;
+                    int prev = data[idx];
+                    for (; idx < nWords - 1; idx++) {
+                        int v = (prev >>> anticount);
+                        prev = data[idx + 1];
+                        v |= (prev << bitcount);
+                        data[idx] = v;
+                    }
+                    int v = prev >>> anticount;
+                    data[idx] = v;
+                    if(v==0) {
+                        nWords--;
+                    }
+                    offset++;
+                } else {
+                    int idx = nWords - 1;
+                    int prev = data[idx];
+                    int hi = prev >>> anticount;
+                    int[] result = data;
+                    int[] src = data;
+                    if (hi != 0) {
+                        if(nWords == data.length) {
+                            data = result = new int[nWords + 1];
+                        }
+                        result[nWords++] = hi;
+                    }
+                    leftShift(src,idx,result,bitcount,anticount,prev);
+                }
+            }
+            offset += wordcount;
+            return this;
+        }
+    }
+
+    /**
+     * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
+     *
+     * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ ensures \result == 0;
+     @
+     @  also
+     @
+     @ requires this.value() > 0;
+     @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
+     @*/
+    private /*@ pure @*/ int size() {
+        return nWords + offset;
+    }
+
+
+    /**
+     * Computes
+     * <pre>
+     * q = (int)( this / S )
+     * this = 10 * ( this mod S )
+     * Return q.
+     * </pre>
+     * This is the iteration step of digit development for output.
+     * We assume that S has been normalized, as above, and that
+     * "this" has been left-shifted accordingly.
+     * Also assumed, of course, is that the result, q, can be expressed
+     * as an integer, {@code 0 <= q < 10}.
+     *
+     * @param S The divisor of this <code>FDBigInteger</code>.
+     * @return <code>q = (int)(this / S)</code>.
+     */
+    /*@
+     @ requires !this.isImmutable;
+     @ requires this.size() <= S.size();
+     @ requires this.data.length + this.offset >= S.size();
+     @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures \result == \old(this.value() / S.value());
+     @ ensures this.value() == \old(10 * (this.value() % S.value()));
+     @*/
+    public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
+        assert !this.isImmutable : "cannot modify immutable value";
+        // ensure that this and S have the same number of
+        // digits. If S is properly normalized and q < 10 then
+        // this must be so.
+        int thSize = this.size();
+        int sSize = S.size();
+        if (thSize < sSize) {
+            // this value is significantly less than S, result of division is zero.
+            // just mult this by 10.
+            int p = multAndCarryBy10(this.data, this.nWords, this.data);
+            if(p!=0) {
+                this.data[nWords++] = p;
+            } else {
+                trimLeadingZeros();
+            }
+            return 0;
+        } else if (thSize > sSize) {
+            throw new IllegalArgumentException("disparate values");
+        }
+        // estimate q the obvious way. We will usually be
+        // right. If not, then we're only off by a little and
+        // will re-add.
+        long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
+        long diff = multDiffMe(q, S);
+        if (diff != 0L) {
+            //@ assert q != 0;
+            //@ assert this.offset == \old(Math.min(this.offset, S.offset));
+            //@ assert this.offset <= S.offset;
+
+            // q is too big.
+            // add S back in until this turns +. This should
+            // not be very many times!
+            long sum = 0L;
+            int tStart = S.offset - this.offset;
+            //@ assert tStart >= 0;
+            int[] sd = S.data;
+            int[] td = this.data;
+            while (sum == 0L) {
+                for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
+                    sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
+                    td[tIndex] = (int) sum;
+                    sum >>>= 32; // Signed or unsigned, answer is 0 or 1
+                }
+                //
+                // Originally the following line read
+                // "if ( sum !=0 && sum != -1 )"
+                // but that would be wrong, because of the
+                // treatment of the two values as entirely unsigned,
+                // it would be impossible for a carry-out to be interpreted
+                // as -1 -- it would have to be a single-bit carry-out, or +1.
+                //
+                assert sum == 0 || sum == 1 : sum; // carry out of division correction
+                q -= 1;
+            }
+        }
+        // finally, we can multiply this by 10.
+        // it cannot overflow, right, as the high-order word has
+        // at least 4 high-order zeros!
+        int p = multAndCarryBy10(this.data, this.nWords, this.data);
+        assert p == 0 : p; // Carry out of *10
+        trimLeadingZeros();
+        return (int) q;
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
+     * performed in place unless the <code>FDBigInteger</code> is immutable in
+     * which case a new <code>FDBigInteger</code> will be returned.
+     *
+     * @return The <code>FDBigInteger</code> multiplied by 10.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * 10);
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && !this.isImmutable;
+     @ assignable this.nWords, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() * 10);
+     @*/
+    public FDBigInteger multBy10() {
+        if (nWords == 0) {
+            return this;
+        }
+        if (isImmutable) {
+            int[] res = new int[nWords + 1];
+            res[nWords] = multAndCarryBy10(data, nWords, res);
+            return new FDBigInteger(res, offset);
+        } else {
+            int p = multAndCarryBy10(this.data, this.nWords, this.data);
+            if (p != 0) {
+                if (nWords == data.length) {
+                    if (data[0] == 0) {
+                        System.arraycopy(data, 1, data, 0, --nWords);
+                        offset++;
+                    } else {
+                        data = Arrays.copyOf(data, data.length + 1);
+                    }
+                }
+                data[nWords++] = p;
+            } else {
+                trimLeadingZeros();
+            }
+            return this;
+        }
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
+     * performed in place if possible, otherwise a new <code>FDBigInteger</code>
+     * will be returned.
+     *
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return The multiplication result.
+     */
+    /*@
+     @ requires this.value() == 0 || p5 == 0 && p2 == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
+     @ assignable this.nWords, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+     @*/
+    public FDBigInteger multByPow52(int p5, int p2) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        FDBigInteger res = this;
+        if (p5 != 0) {
+            int[] r;
+            int extraSize = (p2 != 0) ? 1 : 0;
+            if (p5 < SMALL_5_POW.length) {
+                r = new int[this.nWords + 1 + extraSize];
+                mult(this.data, this.nWords, SMALL_5_POW[p5], r);
+                res = new FDBigInteger(r, this.offset);
+            } else {
+                FDBigInteger pow5 = big5pow(p5);
+                r = new int[this.nWords + pow5.size() + extraSize];
+                mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
+                res = new FDBigInteger(r, this.offset + pow5.offset);
+            }
+        }
+        return res.leftShift(p2);
+    }
+
+    /**
+     * Multiplies two big integers represented as int arrays.
+     *
+     * @param s1 The first array factor.
+     * @param s1Len The number of elements of <code>s1</code> to use.
+     * @param s2 The second array factor.
+     * @param s2Len The number of elements of <code>s2</code> to use.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires s1 != dst && s2 != dst;
+     @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
+     @ assignable dst[0 .. s1Len + s2Len - 1];
+     @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
+     @*/
+    private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
+        for (int i = 0; i < s1Len; i++) {
+            long v = s1[i] & LONG_MASK;
+            long p = 0L;
+            for (int j = 0; j < s2Len; j++) {
+                p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
+                dst[i + j] = (int) p;
+                p >>>= 32;
+            }
+            dst[i + s2Len] = (int) p;
+        }
+    }
+
+    /**
+     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+     * <code>FDBigInteger</code>. Assert that the result is positive.
+     * If the subtrahend is immutable, store the result in this(minuend).
+     * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
+     *
+     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+     * @return This <code>FDBigInteger</code> less the subtrahend.
+     */
+    /*@
+     @ requires this.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @
+     @  also
+     @
+     @ requires !subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @*/
+    public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
+        assert this.size() >= subtrahend.size() : "result should be positive";
+        FDBigInteger minuend;
+        if (this.isImmutable) {
+            minuend = new FDBigInteger(this.data.clone(), this.offset);
+        } else {
+            minuend = this;
+        }
+        int offsetDiff = subtrahend.offset - minuend.offset;
+        int[] sData = subtrahend.data;
+        int[] mData = minuend.data;
+        int subLen = subtrahend.nWords;
+        int minLen = minuend.nWords;
+        if (offsetDiff < 0) {
+            // need to expand minuend
+            int rLen = minLen - offsetDiff;
+            if (rLen < mData.length) {
+                System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
+                Arrays.fill(mData, 0, -offsetDiff, 0);
+            } else {
+                int[] r = new int[rLen];
+                System.arraycopy(mData, 0, r, -offsetDiff, minLen);
+                minuend.data = mData = r;
+            }
+            minuend.offset = subtrahend.offset;
+            minuend.nWords = minLen = rLen;
+            offsetDiff = 0;
+        }
+        long borrow = 0L;
+        int mIndex = offsetDiff;
+        for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
+            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+            mData[mIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        for (; borrow != 0 && mIndex < minLen; mIndex++) {
+            long diff = (mData[mIndex] & LONG_MASK) + borrow;
+            mData[mIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        assert borrow == 0L : borrow; // borrow out of subtract,
+        // result should be positive
+        minuend.trimLeadingZeros();
+        return minuend;
+    }
+
+    /**
+     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+     * <code>FDBigInteger</code>. Assert that the result is positive.
+     * If the this(minuend) is immutable, store the result in subtrahend.
+     * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
+     *
+     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+     * @return This <code>FDBigInteger</code> less the subtrahend.
+     */
+    /*@
+     @ requires subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @
+     @  also
+     @
+     @ requires !subtrahend.isImmutable;
+     @ requires this.value() >= subtrahend.value();
+     @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
+     @ ensures \result == subtrahend;
+     @ ensures \result.value() == \old(this.value() - subtrahend.value());
+     @*/
+    public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
+        assert this.size() >= subtrahend.size() : "result should be positive";
+        FDBigInteger minuend = this;
+        if (subtrahend.isImmutable) {
+            subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
+        }
+        int offsetDiff = minuend.offset - subtrahend.offset;
+        int[] sData = subtrahend.data;
+        int[] mData = minuend.data;
+        int subLen = subtrahend.nWords;
+        int minLen = minuend.nWords;
+        if (offsetDiff < 0) {
+            int rLen = minLen;
+            if (rLen < sData.length) {
+                System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
+                Arrays.fill(sData, 0, -offsetDiff, 0);
+            } else {
+                int[] r = new int[rLen];
+                System.arraycopy(sData, 0, r, -offsetDiff, subLen);
+                subtrahend.data = sData = r;
+            }
+            subtrahend.offset = minuend.offset;
+            subLen -= offsetDiff;
+            offsetDiff = 0;
+        } else {
+            int rLen = minLen + offsetDiff;
+            if (rLen >= sData.length) {
+                subtrahend.data = sData = Arrays.copyOf(sData, rLen);
+            }
+        }
+        //@ assert minuend == this && minuend.value() == \old(this.value());
+        //@ assert mData == minuend.data && minLen == minuend.nWords;
+        //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
+        //@ assert sData == subtrahend.data;
+        //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
+        //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
+        //@ assert offsetDiff == minuend.offset - subtrahend.offset;
+        //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
+        int sIndex = 0;
+        long borrow = 0L;
+        for (; sIndex < offsetDiff; sIndex++) {
+            long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
+            sData[sIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        //@ assert sIndex == offsetDiff;
+        for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
+            //@ assert sIndex == offsetDiff + mIndex;
+            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+            sData[sIndex] = (int) diff;
+            borrow = diff >> 32; // signed shift
+        }
+        assert borrow == 0L : borrow; // borrow out of subtract,
+        // result should be positive
+        subtrahend.nWords = sIndex;
+        subtrahend.trimLeadingZeros();
+        return subtrahend;
+
+    }
+
+    /**
+     * Determines whether all elements of an array are zero for all indices less
+     * than a given index.
+     *
+     * @param a The array to be examined.
+     * @param from The index strictly below which elements are to be examined.
+     * @return Zero if all elements in range are zero, 1 otherwise.
+     */
+    /*@
+     @ requires 0 <= from && from <= a.length;
+     @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
+     @*/
+    private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
+        while (from > 0) {
+            if (a[--from] != 0) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Compares the parameter with this <code>FDBigInteger</code>. Returns an
+     * integer accordingly as:
+     * <pre>{@code
+     * > 0: this > other
+     *   0: this == other
+     * < 0: this < other
+     * }</pre>
+     *
+     * @param other The <code>FDBigInteger</code> to compare.
+     * @return A negative value, zero, or a positive value according to the
+     * result of the comparison.
+     */
+    /*@
+     @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int cmp(FDBigInteger other) {
+        int aSize = nWords + offset;
+        int bSize = other.nWords + other.offset;
+        if (aSize > bSize) {
+            return 1;
+        } else if (aSize < bSize) {
+            return -1;
+        }
+        int aLen = nWords;
+        int bLen = other.nWords;
+        while (aLen > 0 && bLen > 0) {
+            int a = data[--aLen];
+            int b = other.data[--bLen];
+            if (a != b) {
+                return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+            }
+        }
+        if (aLen > 0) {
+            return checkZeroTail(data, aLen);
+        }
+        if (bLen > 0) {
+            return -checkZeroTail(other.data, bLen);
+        }
+        return 0;
+    }
+
+    /**
+     * Compares this <code>FDBigInteger</code> with
+     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+     * Returns an integer accordingly as:
+     * <pre>{@code
+     * > 0: this > other
+     *   0: this == other
+     * < 0: this < other
+     * }</pre>
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return A negative value, zero, or a positive value according to the
+     * result of the comparison.
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() >  pow52(p5, p2) ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int cmpPow52(int p5, int p2) {
+        if (p5 == 0) {
+            int wordcount = p2 >> 5;
+            int bitcount = p2 & 0x1f;
+            int size = this.nWords + this.offset;
+            if (size > wordcount + 1) {
+                return 1;
+            } else if (size < wordcount + 1) {
+                return -1;
+            }
+            int a = this.data[this.nWords -1];
+            int b = 1 << bitcount;
+            if (a != b) {
+                return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+            }
+            return checkZeroTail(this.data, this.nWords - 1);
+        }
+        return this.cmp(big5pow(p5).leftShift(p2));
+    }
+
+    /**
+     * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
+     * value according to the comparison as:
+     * <pre>{@code
+     * -1: this <  x + y
+     *  0: this == x + y
+     *  1: this >  x + y
+     * }</pre>
+     * @param x The first addend of the sum to compare.
+     * @param y The second addend of the sum to compare.
+     * @return -1, 0, or 1 according to the result of the comparison.
+     */
+    /*@
+     @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
+     @*/
+    public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
+        FDBigInteger big;
+        FDBigInteger small;
+        int xSize = x.size();
+        int ySize = y.size();
+        int bSize;
+        int sSize;
+        if (xSize >= ySize) {
+            big = x;
+            small = y;
+            bSize = xSize;
+            sSize = ySize;
+        } else {
+            big = y;
+            small = x;
+            bSize = ySize;
+            sSize = xSize;
+        }
+        int thSize = this.size();
+        if (bSize == 0) {
+            return thSize == 0 ? 0 : 1;
+        }
+        if (sSize == 0) {
+            return this.cmp(big);
+        }
+        if (bSize > thSize) {
+            return -1;
+        }
+        if (bSize + 1 < thSize) {
+            return 1;
+        }
+        long top = (big.data[big.nWords - 1] & LONG_MASK);
+        if (sSize == bSize) {
+            top += (small.data[small.nWords - 1] & LONG_MASK);
+        }
+        if ((top >>> 32) == 0) {
+            if (((top + 1) >>> 32) == 0) {
+                // good case - no carry extension
+                if (bSize < thSize) {
+                    return 1;
+                }
+                // here sum.nWords == this.nWords
+                long v = (this.data[this.nWords - 1] & LONG_MASK);
+                if (v < top) {
+                    return -1;
+                }
+                if (v > top + 1) {
+                    return 1;
+                }
+            }
+        } else { // (top>>>32)!=0 guaranteed carry extension
+            if (bSize + 1 > thSize) {
+                return -1;
+            }
+            // here sum.nWords == this.nWords
+            top >>>= 32;
+            long v = (this.data[this.nWords - 1] & LONG_MASK);
+            if (v < top) {
+                return -1;
+            }
+            if (v > top + 1) {
+                return 1;
+            }
+        }
+        return this.cmp(big.add(small));
+    }
+
+    /**
+     * Makes this <code>FDBigInteger</code> immutable.
+     */
+    /*@
+     @ assignable this.isImmutable;
+     @ ensures this.isImmutable;
+     @*/
+    public void makeImmutable() {
+        this.isImmutable = true;
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by an integer.
+     *
+     * @param i The factor by which to multiply this <code>FDBigInteger</code>.
+     * @return This <code>FDBigInteger</code> multiplied by an integer.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() != 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
+     @*/
+    private FDBigInteger mult(int i) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        int[] r = new int[nWords + 1];
+        mult(data, nWords, i, r);
+        return new FDBigInteger(r, offset);
+    }
+
+    /**
+     * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
+     *
+     * @param other The <code>FDBigInteger</code> factor by which to multiply.
+     * @return The product of this and the parameter <code>FDBigInteger</code>s.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() != 0 && other.value() == 0;
+     @ assignable \nothing;
+     @ ensures \result == other;
+     @
+     @  also
+     @
+     @ requires this.value() != 0 && other.value() != 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() * other.value());
+     @*/
+    private FDBigInteger mult(FDBigInteger other) {
+        if (this.nWords == 0) {
+            return this;
+        }
+        if (this.size() == 1) {
+            return other.mult(data[0]);
+        }
+        if (other.nWords == 0) {
+            return other;
+        }
+        if (other.size() == 1) {
+            return this.mult(other.data[0]);
+        }
+        int[] r = new int[nWords + other.nWords];
+        mult(this.data, this.nWords, other.data, other.nWords, r);
+        return new FDBigInteger(r, this.offset + other.offset);
+    }
+
+    /**
+     * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
+     *
+     * @param other The <code>FDBigInteger</code> to add.
+     * @return The sum of the <code>FDBigInteger</code>s.
+     */
+    /*@
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() + other.value());
+     @*/
+    private FDBigInteger add(FDBigInteger other) {
+        FDBigInteger big, small;
+        int bigLen, smallLen;
+        int tSize = this.size();
+        int oSize = other.size();
+        if (tSize >= oSize) {
+            big = this;
+            bigLen = tSize;
+            small = other;
+            smallLen = oSize;
+        } else {
+            big = other;
+            bigLen = oSize;
+            small = this;
+            smallLen = tSize;
+        }
+        int[] r = new int[bigLen + 1];
+        int i = 0;
+        long carry = 0L;
+        for (; i < smallLen; i++) {
+            carry += (i < big.offset   ? 0L : (big.data[i - big.offset] & LONG_MASK) )
+                   + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
+            r[i] = (int) carry;
+            carry >>= 32; // signed shift.
+        }
+        for (; i < bigLen; i++) {
+            carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
+            r[i] = (int) carry;
+            carry >>= 32; // signed shift.
+        }
+        r[bigLen] = (int) carry;
+        return new FDBigInteger(r, 0);
+    }
+
+
+    /**
+     * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
+     * result is computed in place. This method is intended only to be invoked
+     * from
+     * <code>
+     * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
+     * </code>.
+     *
+     * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
+     * @param addend The value to add to the product of this
+     * <code>FDBigInteger</code> and <code>iv</code>.
+     */
+    /*@
+     @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
+     @ assignable this.data[*];
+     @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
+     @*/
+    private /*@ helper @*/ void multAddMe(int iv, int addend) {
+        long v = iv & LONG_MASK;
+        // unroll 0th iteration, doing addition.
+        long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
+        data[0] = (int) p;
+        p >>>= 32;
+        for (int i = 1; i < nWords; i++) {
+            p += v * (data[i] & LONG_MASK);
+            data[i] = (int) p;
+            p >>>= 32;
+        }
+        if (p != 0L) {
+            data[nWords++] = (int) p; // will fail noisily if illegal!
+        }
+    }
+
+    //
+    // original doc:
+    //
+    // do this -=q*S
+    // returns borrow
+    //
+    /**
+     * Multiplies the parameters and subtracts them from this
+     * <code>FDBigInteger</code>.
+     *
+     * @param q The integer parameter.
+     * @param S The <code>FDBigInteger</code> parameter.
+     * @return <code>this - q*S</code>.
+     */
+    /*@
+     @ ensures nWords == 0 ==> offset == 0;
+     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+     @*/
+    /*@
+     @ requires 0 < q && q <= (1L << 31);
+     @ requires data != null;
+     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ requires !this.isImmutable;
+     @ requires this.size() == S.size();
+     @ requires this != S;
+     @ assignable this.nWords, this.offset, this.data, this.data[*];
+     @ ensures -q <= \result && \result <= 0;
+     @ ensures this.size() == \old(this.size());
+     @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
+     @ ensures this.offset == \old(Math.min(this.offset, S.offset));
+     @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
+     @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
+     @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
+     @
+     @  also
+     @
+     @ requires q == 0;
+     @ assignable \nothing;
+     @ ensures \result == 0;
+     @*/
+    private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
+        long diff = 0L;
+        if (q != 0) {
+            int deltaSize = S.offset - this.offset;
+            if (deltaSize >= 0) {
+                int[] sd = S.data;
+                int[] td = this.data;
+                for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
+                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+                    td[tIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+            } else {
+                deltaSize = -deltaSize;
+                int[] rd = new int[nWords + deltaSize];
+                int sIndex = 0;
+                int rIndex = 0;
+                int[] sd = S.data;
+                for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
+                    diff -= q * (sd[sIndex] & LONG_MASK);
+                    rd[rIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+                int tIndex = 0;
+                int[] td = this.data;
+                for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
+                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+                    rd[rIndex] = (int) diff;
+                    diff >>= 32; // N.B. SIGNED shift.
+                }
+                this.nWords += deltaSize;
+                this.offset -= deltaSize;
+                this.data = rd;
+            }
+        }
+        return diff;
+    }
+
+
+    /**
+     * Multiplies by 10 a big integer represented as an array. The final carry
+     * is returned.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param dst The product array.
+     * @return The final carry of the multiplication.
+     */
+    /*@
+     @ requires src.length >= srcLen && dst.length >= srcLen;
+     @ assignable dst[0 .. srcLen - 1];
+     @ ensures 0 <= \result && \result < 10;
+     @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
+     @*/
+    private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
+        long carry = 0;
+        for (int i = 0; i < srcLen; i++) {
+            long product = (src[i] & LONG_MASK) * 10L + carry;
+            dst[i] = (int) product;
+            carry = product >>> 32;
+        }
+        return (int) carry;
+    }
+
+    /**
+     * Multiplies by a constant value a big integer represented as an array.
+     * The constant factor is an <code>int</code>.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param value The constant factor by which to multiply.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires src.length >= srcLen && dst.length >= srcLen + 1;
+     @ assignable dst[0 .. srcLen];
+     @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
+     @*/
+    private static void mult(int[] src, int srcLen, int value, int[] dst) {
+        long val = value & LONG_MASK;
+        long carry = 0;
+        for (int i = 0; i < srcLen; i++) {
+            long product = (src[i] & LONG_MASK) * val + carry;
+            dst[i] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen] = (int) carry;
+    }
+
+    /**
+     * Multiplies by a constant value a big integer represented as an array.
+     * The constant factor is a long represent as two <code>int</code>s.
+     *
+     * @param src The array representation of the big integer.
+     * @param srcLen The number of elements of <code>src</code> to use.
+     * @param v0 The lower 32 bits of the long factor.
+     * @param v1 The upper 32 bits of the long factor.
+     * @param dst The product array.
+     */
+    /*@
+     @ requires src != dst;
+     @ requires src.length >= srcLen && dst.length >= srcLen + 2;
+     @ assignable dst[0 .. srcLen + 1];
+     @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
+     @*/
+    private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
+        long v = v0 & LONG_MASK;
+        long carry = 0;
+        for (int j = 0; j < srcLen; j++) {
+            long product = v * (src[j] & LONG_MASK) + carry;
+            dst[j] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen] = (int) carry;
+        v = v1 & LONG_MASK;
+        carry = 0;
+        for (int j = 0; j < srcLen; j++) {
+            long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
+            dst[j + 1] = (int) product;
+            carry = product >>> 32;
+        }
+        dst[srcLen + 1] = (int) carry;
+    }
+
+    // Fails assertion for negative exponent.
+    /**
+     * Computes <code>5</code> raised to a given power.
+     *
+     * @param p The exponent of 5.
+     * @return <code>5<sup>p</sup></code>.
+     */
+    private static FDBigInteger big5pow(int p) {
+        assert p >= 0 : p; // negative power of 5
+        if (p < MAX_FIVE_POW) {
+            return POW_5_CACHE[p];
+        }
+        return big5powRec(p);
+    }
+
+    // slow path
+    /**
+     * Computes <code>5</code> raised to a given power.
+     *
+     * @param p The exponent of 5.
+     * @return <code>5<sup>p</sup></code>.
+     */
+    private static FDBigInteger big5powRec(int p) {
+        if (p < MAX_FIVE_POW) {
+            return POW_5_CACHE[p];
+        }
+        // construct the value.
+        // recursively.
+        int q, r;
+        // in order to compute 5^p,
+        // compute its square root, 5^(p/2) and square.
+        // or, let q = p / 2, r = p -q, then
+        // 5^p = 5^(q+r) = 5^q * 5^r
+        q = p >> 1;
+        r = p - q;
+        FDBigInteger bigq = big5powRec(q);
+        if (r < SMALL_5_POW.length) {
+            return bigq.mult(SMALL_5_POW[r]);
+        } else {
+            return bigq.mult(big5powRec(r));
+        }
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a hexadecimal string.
+     *
+     * @return The hexadecimal string representation.
+     */
+    public String toHexString(){
+        if(nWords ==0) {
+            return "0";
+        }
+        StringBuilder sb = new StringBuilder((nWords +offset)*8);
+        for(int i= nWords -1; i>=0; i--) {
+            String subStr = Integer.toHexString(data[i]);
+            for(int j = subStr.length(); j<8; j++) {
+                sb.append('0');
+            }
+            sb.append(subStr);
+        }
+        for(int i=offset; i>0; i--) {
+            sb.append("00000000");
+        }
+        return sb.toString();
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
+     *
+     * @return The <code>BigInteger</code> representation.
+     */
+    public BigInteger toBigInteger() {
+        byte[] magnitude = new byte[nWords * 4 + 1];
+        for (int i = 0; i < nWords; i++) {
+            int w = data[i];
+            magnitude[magnitude.length - 4 * i - 1] = (byte) w;
+            magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
+            magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
+            magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
+        }
+        return new BigInteger(magnitude).shiftLeft(offset * 32);
+    }
+
+    // for debugging ...
+    /**
+     * Converts this <code>FDBigInteger</code> to a string.
+     *
+     * @return The string representation.
+     */
+    @Override
+    public String toString(){
+        return toBigInteger().toString();
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/math/FloatConsts.java b/ojluni/src/main/java/jdk/internal/math/FloatConsts.java
new file mode 100644
index 0000000..73e0408
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/math/FloatConsts.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * {@code float} type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+public class FloatConsts {
+    /**
+     * Don't let anyone instantiate this class.
+     */
+    private FloatConsts() {}
+
+    public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
+    public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
+    public static final float NaN = java.lang.Float.NaN;
+    public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
+    public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
+
+    /**
+     * A constant holding the smallest positive normal value of type
+     * <code>float</code>, 2<sup>-126</sup>.  It is equal to the value
+     * returned by <code>Float.intBitsToFloat(0x00800000)</code>.
+     */
+    public static final float   MIN_NORMAL      = 1.17549435E-38f;
+
+    /**
+     * The number of logical bits in the significand of a
+     * {@code float} number, including the implicit bit.
+     */
+    public static final int SIGNIFICAND_WIDTH   = 24;
+
+    /**
+     * Maximum exponent a finite <code>float</code> number may have.
+     * It is equal to the value returned by
+     * <code>Math.ilogb(Float.MAX_VALUE)</code>.
+     */
+    public static final int     MAX_EXPONENT    = 127;
+
+    /**
+     * Minimum exponent a normalized <code>float</code> number may
+     * have.  It is equal to the value returned by
+     * <code>Math.ilogb(Float.MIN_NORMAL)</code>.
+     */
+    public static final int     MIN_EXPONENT    = -126;
+
+    /**
+     * The exponent the smallest positive {@code float} subnormal
+     * value would have if it could be normalized.
+     */
+    public static final int     MIN_SUB_EXPONENT = Float.MIN_EXPONENT -
+                                                   (SIGNIFICAND_WIDTH - 1);
+
+    /**
+     * Bias used in representing a {@code float} exponent.
+     */
+    public static final int     EXP_BIAS        = 127;
+
+    /**
+     * Bit mask to isolate the sign bit of a {@code float}.
+     */
+    public static final int     SIGN_BIT_MASK   = 0x80000000;
+
+    /**
+     * Bit mask to isolate the exponent field of a
+     * {@code float}.
+     */
+    public static final int     EXP_BIT_MASK    = 0x7F800000;
+
+    /**
+     * Bit mask to isolate the significand field of a
+     * {@code float}.
+     */
+    public static final int     SIGNIF_BIT_MASK = 0x007FFFFF;
+
+    static {
+        // verify bit masks cover all bit positions and that the bit
+        // masks are non-overlapping
+        assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) &&
+               (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) &&
+                ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) &&
+                ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0)));
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/math/FloatingDecimal.java b/ojluni/src/main/java/jdk/internal/math/FloatingDecimal.java
new file mode 100644
index 0000000..2f4ade0
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/math/FloatingDecimal.java
@@ -0,0 +1,2552 @@
+/*
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+import java.util.Arrays;
+import java.util.regex.*;
+
+/**
+ * A class for converting between ASCII and decimal representations of a single
+ * or double precision floating point number. Most conversions are provided via
+ * static convenience methods, although a <code>BinaryToASCIIConverter</code>
+ * instance may be obtained and reused.
+ */
+public class FloatingDecimal{
+    //
+    // Constants of the implementation;
+    // most are IEEE-754 related.
+    // (There are more really boring constants at the end.)
+    //
+    static final int    EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
+    static final long   FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
+    static final long   EXP_ONE   = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
+    static final int    MAX_SMALL_BIN_EXP = 62;
+    static final int    MIN_SMALL_BIN_EXP = -( 63 / 3 );
+    static final int    MAX_DECIMAL_DIGITS = 15;
+    static final int    MAX_DECIMAL_EXPONENT = 308;
+    static final int    MIN_DECIMAL_EXPONENT = -324;
+    static final int    BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
+    static final int    MAX_NDIGITS = 1100;
+
+    static final int    SINGLE_EXP_SHIFT  =   FloatConsts.SIGNIFICAND_WIDTH - 1;
+    static final int    SINGLE_FRACT_HOB  =   1<<SINGLE_EXP_SHIFT;
+    static final int    SINGLE_MAX_DECIMAL_DIGITS = 7;
+    static final int    SINGLE_MAX_DECIMAL_EXPONENT = 38;
+    static final int    SINGLE_MIN_DECIMAL_EXPONENT = -45;
+    static final int    SINGLE_MAX_NDIGITS = 200;
+
+    static final int    INT_DECIMAL_DIGITS = 9;
+
+    /**
+     * Converts a double precision floating point value to a <code>String</code>.
+     *
+     * @param d The double precision value.
+     * @return The value converted to a <code>String</code>.
+     */
+    public static String toJavaFormatString(double d) {
+        return getBinaryToASCIIConverter(d).toJavaFormatString();
+    }
+
+    /**
+     * Converts a single precision floating point value to a <code>String</code>.
+     *
+     * @param f The single precision value.
+     * @return The value converted to a <code>String</code>.
+     */
+    public static String toJavaFormatString(float f) {
+        return getBinaryToASCIIConverter(f).toJavaFormatString();
+    }
+
+    /**
+     * Appends a double precision floating point value to an <code>Appendable</code>.
+     * @param d The double precision value.
+     * @param buf The <code>Appendable</code> with the value appended.
+     */
+    public static void appendTo(double d, Appendable buf) {
+        getBinaryToASCIIConverter(d).appendTo(buf);
+    }
+
+    /**
+     * Appends a single precision floating point value to an <code>Appendable</code>.
+     * @param f The single precision value.
+     * @param buf The <code>Appendable</code> with the value appended.
+     */
+    public static void appendTo(float f, Appendable buf) {
+        getBinaryToASCIIConverter(f).appendTo(buf);
+    }
+
+    /**
+     * Converts a <code>String</code> to a double precision floating point value.
+     *
+     * @param s The <code>String</code> to convert.
+     * @return The double precision value.
+     * @throws NumberFormatException If the <code>String</code> does not
+     * represent a properly formatted double precision value.
+     */
+    public static double parseDouble(String s) throws NumberFormatException {
+        return readJavaFormatString(s).doubleValue();
+    }
+
+    /**
+     * Converts a <code>String</code> to a single precision floating point value.
+     *
+     * @param s The <code>String</code> to convert.
+     * @return The single precision value.
+     * @throws NumberFormatException If the <code>String</code> does not
+     * represent a properly formatted single precision value.
+     */
+    public static float parseFloat(String s) throws NumberFormatException {
+        return readJavaFormatString(s).floatValue();
+    }
+
+    /**
+     * A converter which can process single or double precision floating point
+     * values into an ASCII <code>String</code> representation.
+     */
+    public interface BinaryToASCIIConverter {
+        /**
+         * Converts a floating point value into an ASCII <code>String</code>.
+         * @return The value converted to a <code>String</code>.
+         */
+        public String toJavaFormatString();
+
+        /**
+         * Appends a floating point value to an <code>Appendable</code>.
+         * @param buf The <code>Appendable</code> to receive the value.
+         */
+        public void appendTo(Appendable buf);
+
+        /**
+         * Retrieves the decimal exponent most closely corresponding to this value.
+         * @return The decimal exponent.
+         */
+        public int getDecimalExponent();
+
+        /**
+         * Retrieves the value as an array of digits.
+         * @param digits The digit array.
+         * @return The number of valid digits copied into the array.
+         */
+        public int getDigits(char[] digits);
+
+        /**
+         * Indicates the sign of the value.
+         * @return {@code value < 0.0}.
+         */
+        public boolean isNegative();
+
+        /**
+         * Indicates whether the value is either infinite or not a number.
+         *
+         * @return <code>true</code> if and only if the value is <code>NaN</code>
+         * or infinite.
+         */
+        public boolean isExceptional();
+
+        /**
+         * Indicates whether the value was rounded up during the binary to ASCII
+         * conversion.
+         *
+         * @return <code>true</code> if and only if the value was rounded up.
+         */
+        public boolean digitsRoundedUp();
+
+        /**
+         * Indicates whether the binary to ASCII conversion was exact.
+         *
+         * @return <code>true</code> if any only if the conversion was exact.
+         */
+        public boolean decimalDigitsExact();
+    }
+
+    /**
+     * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
+     * and infinite values.
+     */
+    private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
+        private final String image;
+        private boolean isNegative;
+
+        public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
+            this.image = image;
+            this.isNegative = isNegative;
+        }
+
+        @Override
+        public String toJavaFormatString() {
+            return image;
+        }
+
+        @Override
+        public void appendTo(Appendable buf) {
+            if (buf instanceof StringBuilder) {
+                ((StringBuilder) buf).append(image);
+            } else if (buf instanceof StringBuffer) {
+                ((StringBuffer) buf).append(image);
+            } else {
+                assert false;
+            }
+        }
+
+        @Override
+        public int getDecimalExponent() {
+            throw new IllegalArgumentException("Exceptional value does not have an exponent");
+        }
+
+        @Override
+        public int getDigits(char[] digits) {
+            throw new IllegalArgumentException("Exceptional value does not have digits");
+        }
+
+        @Override
+        public boolean isNegative() {
+            return isNegative;
+        }
+
+        @Override
+        public boolean isExceptional() {
+            return true;
+        }
+
+        @Override
+        public boolean digitsRoundedUp() {
+            throw new IllegalArgumentException("Exceptional value is not rounded");
+        }
+
+        @Override
+        public boolean decimalDigitsExact() {
+            throw new IllegalArgumentException("Exceptional value is not exact");
+        }
+    }
+
+    private static final String INFINITY_REP = "Infinity";
+    private static final int INFINITY_LENGTH = INFINITY_REP.length();
+    private static final String NAN_REP = "NaN";
+    private static final int NAN_LENGTH = NAN_REP.length();
+
+    private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
+    private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
+    private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
+    private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
+    private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true,  new char[]{'0'});
+
+    /**
+     * A buffered implementation of <code>BinaryToASCIIConverter</code>.
+     */
+    static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
+        private boolean isNegative;
+        private int decExponent;
+        private int firstDigitIndex;
+        private int nDigits;
+        private final char[] digits;
+        private final char[] buffer = new char[26];
+
+        //
+        // The fields below provide additional information about the result of
+        // the binary to decimal digits conversion done in dtoa() and roundup()
+        // methods. They are changed if needed by those two methods.
+        //
+
+        // True if the dtoa() binary to decimal conversion was exact.
+        private boolean exactDecimalConversion = false;
+
+        // True if the result of the binary to decimal conversion was rounded-up
+        // at the end of the conversion process, i.e. roundUp() method was called.
+        private boolean decimalDigitsRoundedUp = false;
+
+        /**
+         * Default constructor; used for non-zero values,
+         * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
+         */
+        BinaryToASCIIBuffer(){
+            this.digits = new char[20];
+        }
+
+        /**
+         * Creates a specialized value (positive and negative zeros).
+         */
+        BinaryToASCIIBuffer(boolean isNegative, char[] digits){
+            this.isNegative = isNegative;
+            this.decExponent  = 0;
+            this.digits = digits;
+            this.firstDigitIndex = 0;
+            this.nDigits = digits.length;
+        }
+
+        @Override
+        public String toJavaFormatString() {
+            int len = getChars(buffer);
+            return new String(buffer, 0, len);
+        }
+
+        @Override
+        public void appendTo(Appendable buf) {
+            int len = getChars(buffer);
+            if (buf instanceof StringBuilder) {
+                ((StringBuilder) buf).append(buffer, 0, len);
+            } else if (buf instanceof StringBuffer) {
+                ((StringBuffer) buf).append(buffer, 0, len);
+            } else {
+                assert false;
+            }
+        }
+
+        @Override
+        public int getDecimalExponent() {
+            return decExponent;
+        }
+
+        @Override
+        public int getDigits(char[] digits) {
+            System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
+            return this.nDigits;
+        }
+
+        @Override
+        public boolean isNegative() {
+            return isNegative;
+        }
+
+        @Override
+        public boolean isExceptional() {
+            return false;
+        }
+
+        @Override
+        public boolean digitsRoundedUp() {
+            return decimalDigitsRoundedUp;
+        }
+
+        @Override
+        public boolean decimalDigitsExact() {
+            return exactDecimalConversion;
+        }
+
+        private void setSign(boolean isNegative) {
+            this.isNegative = isNegative;
+        }
+
+        /**
+         * This is the easy subcase --
+         * all the significant bits, after scaling, are held in lvalue.
+         * negSign and decExponent tell us what processing and scaling
+         * has already been done. Exceptional cases have already been
+         * stripped out.
+         * In particular:
+         * lvalue is a finite number (not Inf, nor NaN)
+         * lvalue > 0L (not zero, nor negative).
+         *
+         * The only reason that we develop the digits here, rather than
+         * calling on Long.toString() is that we can do it a little faster,
+         * and besides want to treat trailing 0s specially. If Long.toString
+         * changes, we should re-evaluate this strategy!
+         */
+        private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){
+            if ( insignificantDigits != 0 ){
+                // Discard non-significant low-order bits, while rounding,
+                // up to insignificant value.
+                long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
+                long residue = lvalue % pow10;
+                lvalue /= pow10;
+                decExponent += insignificantDigits;
+                if ( residue >= (pow10>>1) ){
+                    // round up based on the low-order bits we're discarding
+                    lvalue++;
+                }
+            }
+            int  digitno = digits.length -1;
+            int  c;
+            if ( lvalue <= Integer.MAX_VALUE ){
+                assert lvalue > 0L : lvalue; // lvalue <= 0
+                // even easier subcase!
+                // can do int arithmetic rather than long!
+                int  ivalue = (int)lvalue;
+                c = ivalue%10;
+                ivalue /= 10;
+                while ( c == 0 ){
+                    decExponent++;
+                    c = ivalue%10;
+                    ivalue /= 10;
+                }
+                while ( ivalue != 0){
+                    digits[digitno--] = (char)(c+'0');
+                    decExponent++;
+                    c = ivalue%10;
+                    ivalue /= 10;
+                }
+                digits[digitno] = (char)(c+'0');
+            } else {
+                // same algorithm as above (same bugs, too )
+                // but using long arithmetic.
+                c = (int)(lvalue%10L);
+                lvalue /= 10L;
+                while ( c == 0 ){
+                    decExponent++;
+                    c = (int)(lvalue%10L);
+                    lvalue /= 10L;
+                }
+                while ( lvalue != 0L ){
+                    digits[digitno--] = (char)(c+'0');
+                    decExponent++;
+                    c = (int)(lvalue%10L);
+                    lvalue /= 10;
+                }
+                digits[digitno] = (char)(c+'0');
+            }
+            this.decExponent = decExponent+1;
+            this.firstDigitIndex = digitno;
+            this.nDigits = this.digits.length - digitno;
+        }
+
+        private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
+        {
+            assert fractBits > 0 ; // fractBits here can't be zero or negative
+            assert (fractBits & FRACT_HOB)!=0  ; // Hi-order bit should be set
+            // Examine number. Determine if it is an easy case,
+            // which we can do pretty trivially using float/long conversion,
+            // or whether we must do real work.
+            final int tailZeros = Long.numberOfTrailingZeros(fractBits);
+
+            // number of significant bits of fractBits;
+            final int nFractBits = EXP_SHIFT+1-tailZeros;
+
+            // reset flags to default values as dtoa() does not always set these
+            // flags and a prior call to dtoa() might have set them to incorrect
+            // values with respect to the current state.
+            decimalDigitsRoundedUp = false;
+            exactDecimalConversion = false;
+
+            // number of significant bits to the right of the point.
+            int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+            if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
+                // Look more closely at the number to decide if,
+                // with scaling by 10^nTinyBits, the result will fit in
+                // a long.
+                if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
+                    //
+                    // We can do this:
+                    // take the fraction bits, which are normalized.
+                    // (a) nTinyBits == 0: Shift left or right appropriately
+                    //     to align the binary point at the extreme right, i.e.
+                    //     where a long int point is expected to be. The integer
+                    //     result is easily converted to a string.
+                    // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
+                    //     which effectively converts to long and scales by
+                    //     2^nTinyBits. Then multiply by 5^nTinyBits to
+                    //     complete the scaling. We know this won't overflow
+                    //     because we just counted the number of bits necessary
+                    //     in the result. The integer you get from this can
+                    //     then be converted to a string pretty easily.
+                    //
+                    if ( nTinyBits == 0 ) {
+                        int insignificant;
+                        if ( binExp > nSignificantBits ){
+                            insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
+                        } else {
+                            insignificant = 0;
+                        }
+                        if ( binExp >= EXP_SHIFT ){
+                            fractBits <<= (binExp-EXP_SHIFT);
+                        } else {
+                            fractBits >>>= (EXP_SHIFT-binExp) ;
+                        }
+                        developLongDigits( 0, fractBits, insignificant );
+                        return;
+                    }
+                    //
+                    // The following causes excess digits to be printed
+                    // out in the single-float case. Our manipulation of
+                    // halfULP here is apparently not correct. If we
+                    // better understand how this works, perhaps we can
+                    // use this special case again. But for the time being,
+                    // we do not.
+                    // else {
+                    //     fractBits >>>= EXP_SHIFT+1-nFractBits;
+                    //     fractBits//= long5pow[ nTinyBits ];
+                    //     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+                    //     developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
+                    //     return;
+                    // }
+                    //
+                }
+            }
+            //
+            // This is the hard case. We are going to compute large positive
+            // integers B and S and integer decExp, s.t.
+            //      d = ( B / S )// 10^decExp
+            //      1 <= B / S < 10
+            // Obvious choices are:
+            //      decExp = floor( log10(d) )
+            //      B      = d// 2^nTinyBits// 10^max( 0, -decExp )
+            //      S      = 10^max( 0, decExp)// 2^nTinyBits
+            // (noting that nTinyBits has already been forced to non-negative)
+            // I am also going to compute a large positive integer
+            //      M      = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
+            // i.e. M is (1/2) of the ULP of d, scaled like B.
+            // When we iterate through dividing B/S and picking off the
+            // quotient bits, we will know when to stop when the remainder
+            // is <= M.
+            //
+            // We keep track of powers of 2 and powers of 5.
+            //
+            int decExp = estimateDecExp(fractBits,binExp);
+            int B2, B5; // powers of 2 and powers of 5, respectively, in B
+            int S2, S5; // powers of 2 and powers of 5, respectively, in S
+            int M2, M5; // powers of 2 and powers of 5, respectively, in M
+
+            B5 = Math.max( 0, -decExp );
+            B2 = B5 + nTinyBits + binExp;
+
+            S5 = Math.max( 0, decExp );
+            S2 = S5 + nTinyBits;
+
+            M5 = B5;
+            M2 = B2 - nSignificantBits;
+
+            //
+            // the long integer fractBits contains the (nFractBits) interesting
+            // bits from the mantissa of d ( hidden 1 added if necessary) followed
+            // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
+            // I will shift out those zeros before turning fractBits into a
+            // FDBigInteger. The resulting whole number will be
+            //      d * 2^(nFractBits-1-binExp).
+            //
+            fractBits >>>= tailZeros;
+            B2 -= nFractBits-1;
+            int common2factor = Math.min( B2, S2 );
+            B2 -= common2factor;
+            S2 -= common2factor;
+            M2 -= common2factor;
+
+            //
+            // HACK!! For exact powers of two, the next smallest number
+            // is only half as far away as we think (because the meaning of
+            // ULP changes at power-of-two bounds) for this reason, we
+            // hack M2. Hope this works.
+            //
+            if ( nFractBits == 1 ) {
+                M2 -= 1;
+            }
+
+            if ( M2 < 0 ){
+                // oops.
+                // since we cannot scale M down far enough,
+                // we must scale the other values up.
+                B2 -= M2;
+                S2 -= M2;
+                M2 =  0;
+            }
+            //
+            // Construct, Scale, iterate.
+            // Some day, we'll write a stopping test that takes
+            // account of the asymmetry of the spacing of floating-point
+            // numbers below perfect powers of 2
+            // 26 Sept 96 is not that day.
+            // So we use a symmetric test.
+            //
+            int ndigit = 0;
+            boolean low, high;
+            long lowDigitDifference;
+            int  q;
+
+            //
+            // Detect the special cases where all the numbers we are about
+            // to compute will fit in int or long integers.
+            // In these cases, we will avoid doing FDBigInteger arithmetic.
+            // We use the same algorithms, except that we "normalize"
+            // our FDBigIntegers before iterating. This is to make division easier,
+            // as it makes our fist guess (quotient of high-order words)
+            // more accurate!
+            //
+            // Some day, we'll write a stopping test that takes
+            // account of the asymmetry of the spacing of floating-point
+            // numbers below perfect powers of 2
+            // 26 Sept 96 is not that day.
+            // So we use a symmetric test.
+            //
+            // binary digits needed to represent B, approx.
+            int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
+
+            // binary digits needed to represent 10*S, approx.
+            int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
+            if ( Bbits < 64 && tenSbits < 64){
+                if ( Bbits < 32 && tenSbits < 32){
+                    // wa-hoo! They're all ints!
+                    int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
+                    int s = FDBigInteger.SMALL_5_POW[S5] << S2;
+                    int m = FDBigInteger.SMALL_5_POW[M5] << M2;
+                    int tens = s * 10;
+                    //
+                    // Unroll the first iteration. If our decExp estimate
+                    // was too high, our first quotient will be zero. In this
+                    // case, we discard it and decrement decExp.
+                    //
+                    ndigit = 0;
+                    q = b / s;
+                    b = 10 * ( b % s );
+                    m *= 10;
+                    low  = (b <  m );
+                    high = (b+m > tens );
+                    assert q < 10 : q; // excessively large digit
+                    if ( (q == 0) && ! high ){
+                        // oops. Usually ignore leading zero.
+                        decExp--;
+                    } else {
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    //
+                    // HACK! Java spec sez that we always have at least
+                    // one digit after the . in either F- or E-form output.
+                    // Thus we will need more than one digit if we're using
+                    // E-form
+                    //
+                    if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
+                        high = low = false;
+                    }
+                    while( ! low && ! high ){
+                        q = b / s;
+                        b = 10 * ( b % s );
+                        m *= 10;
+                        assert q < 10 : q; // excessively large digit
+                        if ( m > 0L ){
+                            low  = (b <  m );
+                            high = (b+m > tens );
+                        } else {
+                            // hack -- m might overflow!
+                            // in this case, it is certainly > b,
+                            // which won't
+                            // and b+m > tens, too, since that has overflowed
+                            // either!
+                            low = true;
+                            high = true;
+                        }
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    lowDigitDifference = (b<<1) - tens;
+                    exactDecimalConversion  = (b == 0);
+                } else {
+                    // still good! they're all longs!
+                    long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
+                    long s = FDBigInteger.LONG_5_POW[S5] << S2;
+                    long m = FDBigInteger.LONG_5_POW[M5] << M2;
+                    long tens = s * 10L;
+                    //
+                    // Unroll the first iteration. If our decExp estimate
+                    // was too high, our first quotient will be zero. In this
+                    // case, we discard it and decrement decExp.
+                    //
+                    ndigit = 0;
+                    q = (int) ( b / s );
+                    b = 10L * ( b % s );
+                    m *= 10L;
+                    low  = (b <  m );
+                    high = (b+m > tens );
+                    assert q < 10 : q; // excessively large digit
+                    if ( (q == 0) && ! high ){
+                        // oops. Usually ignore leading zero.
+                        decExp--;
+                    } else {
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    //
+                    // HACK! Java spec sez that we always have at least
+                    // one digit after the . in either F- or E-form output.
+                    // Thus we will need more than one digit if we're using
+                    // E-form
+                    //
+                    if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+                        high = low = false;
+                    }
+                    while( ! low && ! high ){
+                        q = (int) ( b / s );
+                        b = 10 * ( b % s );
+                        m *= 10;
+                        assert q < 10 : q;  // excessively large digit
+                        if ( m > 0L ){
+                            low  = (b <  m );
+                            high = (b+m > tens );
+                        } else {
+                            // hack -- m might overflow!
+                            // in this case, it is certainly > b,
+                            // which won't
+                            // and b+m > tens, too, since that has overflowed
+                            // either!
+                            low = true;
+                            high = true;
+                        }
+                        digits[ndigit++] = (char)('0' + q);
+                    }
+                    lowDigitDifference = (b<<1) - tens;
+                    exactDecimalConversion  = (b == 0);
+                }
+            } else {
+                //
+                // We really must do FDBigInteger arithmetic.
+                // Fist, construct our FDBigInteger initial values.
+                //
+                FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
+                int shiftBias = Sval.getNormalizationBias();
+                Sval = Sval.leftShift(shiftBias); // normalize so that division works better
+
+                FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
+                FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
+
+                FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
+                //
+                // Unroll the first iteration. If our decExp estimate
+                // was too high, our first quotient will be zero. In this
+                // case, we discard it and decrement decExp.
+                //
+                ndigit = 0;
+                q = Bval.quoRemIteration( Sval );
+                low  = (Bval.cmp( Mval ) < 0);
+                high = tenSval.addAndCmp(Bval,Mval)<=0;
+
+                assert q < 10 : q; // excessively large digit
+                if ( (q == 0) && ! high ){
+                    // oops. Usually ignore leading zero.
+                    decExp--;
+                } else {
+                    digits[ndigit++] = (char)('0' + q);
+                }
+                //
+                // HACK! Java spec sez that we always have at least
+                // one digit after the . in either F- or E-form output.
+                // Thus we will need more than one digit if we're using
+                // E-form
+                //
+                if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+                    high = low = false;
+                }
+                while( ! low && ! high ){
+                    q = Bval.quoRemIteration( Sval );
+                    assert q < 10 : q;  // excessively large digit
+                    Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
+                    low  = (Bval.cmp( Mval ) < 0);
+                    high = tenSval.addAndCmp(Bval,Mval)<=0;
+                    digits[ndigit++] = (char)('0' + q);
+                }
+                if ( high && low ){
+                    Bval = Bval.leftShift(1);
+                    lowDigitDifference = Bval.cmp(tenSval);
+                } else {
+                    lowDigitDifference = 0L; // this here only for flow analysis!
+                }
+                exactDecimalConversion  = (Bval.cmp( FDBigInteger.ZERO ) == 0);
+            }
+            this.decExponent = decExp+1;
+            this.firstDigitIndex = 0;
+            this.nDigits = ndigit;
+            //
+            // Last digit gets rounded based on stopping condition.
+            //
+            if ( high ){
+                if ( low ){
+                    if ( lowDigitDifference == 0L ){
+                        // it's a tie!
+                        // choose based on which digits we like.
+                        if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
+                            roundup();
+                        }
+                    } else if ( lowDigitDifference > 0 ){
+                        roundup();
+                    }
+                } else {
+                    roundup();
+                }
+            }
+        }
+
+        // add one to the least significant digit.
+        // in the unlikely event there is a carry out, deal with it.
+        // assert that this will only happen where there
+        // is only one digit, e.g. (float)1e-44 seems to do it.
+        //
+        private void roundup() {
+            int i = (firstDigitIndex + nDigits - 1);
+            int q = digits[i];
+            if (q == '9') {
+                while (q == '9' && i > firstDigitIndex) {
+                    digits[i] = '0';
+                    q = digits[--i];
+                }
+                if (q == '9') {
+                    // carryout! High-order 1, rest 0s, larger exp.
+                    decExponent += 1;
+                    digits[firstDigitIndex] = '1';
+                    return;
+                }
+                // else fall through.
+            }
+            digits[i] = (char) (q + 1);
+            decimalDigitsRoundedUp = true;
+        }
+
+        /**
+         * Estimate decimal exponent. (If it is small-ish,
+         * we could double-check.)
+         *
+         * First, scale the mantissa bits such that 1 <= d2 < 2.
+         * We are then going to estimate
+         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
+         * and so we can estimate
+         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
+         * take the floor and call it decExp.
+         */
+        static int estimateDecExp(long fractBits, int binExp) {
+            double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
+            double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
+            long dBits = Double.doubleToRawLongBits(d);  //can't be NaN here so use raw
+            int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
+            boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+            if(exponent>=0 && exponent<52) { // hot path
+                long mask   = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+                int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
+                return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
+            } else if (exponent < 0) {
+                return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
+                        ( (isNegative) ? -1 : 0) );
+            } else { //if (exponent >= 52)
+                return (int)d;
+            }
+        }
+
+        private static int insignificantDigits(int insignificant) {
+            int i;
+            for ( i = 0; insignificant >= 10L; i++ ) {
+                insignificant /= 10L;
+            }
+            return i;
+        }
+
+        /**
+         * Calculates
+         * <pre>
+         * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
+         * </pre>
+         */
+        private static int insignificantDigitsForPow2(int p2) {
+            if(p2>1 && p2 < insignificantDigitsNumber.length) {
+                return insignificantDigitsNumber[p2];
+            }
+            return 0;
+        }
+
+        /**
+         *  If insignificant==(1L << ixd)
+         *  i = insignificantDigitsNumber[idx] is the same as:
+         *  int i;
+         *  for ( i = 0; insignificant >= 10L; i++ )
+         *         insignificant /= 10L;
+         */
+        private static int[] insignificantDigitsNumber = {
+            0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
+            4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+            8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+            12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
+            15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
+            18, 18, 18, 19
+        };
+
+        // approximately ceil( log2( long5pow[i] ) )
+        private static final int[] N_5_BITS = {
+                0,
+                3,
+                5,
+                7,
+                10,
+                12,
+                14,
+                17,
+                19,
+                21,
+                24,
+                26,
+                28,
+                31,
+                33,
+                35,
+                38,
+                40,
+                42,
+                45,
+                47,
+                49,
+                52,
+                54,
+                56,
+                59,
+                61,
+        };
+
+        private int getChars(char[] result) {
+            assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+            int i = 0;
+            if (isNegative) {
+                result[0] = '-';
+                i = 1;
+            }
+            if (decExponent > 0 && decExponent < 8) {
+                // print digits.digits.
+                int charLength = Math.min(nDigits, decExponent);
+                System.arraycopy(digits, firstDigitIndex, result, i, charLength);
+                i += charLength;
+                if (charLength < decExponent) {
+                    charLength = decExponent - charLength;
+                    Arrays.fill(result,i,i+charLength,'0');
+                    i += charLength;
+                    result[i++] = '.';
+                    result[i++] = '0';
+                } else {
+                    result[i++] = '.';
+                    if (charLength < nDigits) {
+                        int t = nDigits - charLength;
+                        System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
+                        i += t;
+                    } else {
+                        result[i++] = '0';
+                    }
+                }
+            } else if (decExponent <= 0 && decExponent > -3) {
+                result[i++] = '0';
+                result[i++] = '.';
+                if (decExponent != 0) {
+                    Arrays.fill(result, i, i-decExponent, '0');
+                    i -= decExponent;
+                }
+                System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
+                i += nDigits;
+            } else {
+                result[i++] = digits[firstDigitIndex];
+                result[i++] = '.';
+                if (nDigits > 1) {
+                    System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
+                    i += nDigits - 1;
+                } else {
+                    result[i++] = '0';
+                }
+                result[i++] = 'E';
+                int e;
+                if (decExponent <= 0) {
+                    result[i++] = '-';
+                    e = -decExponent + 1;
+                } else {
+                    e = decExponent - 1;
+                }
+                // decExponent has 1, 2, or 3, digits
+                if (e <= 9) {
+                    result[i++] = (char) (e + '0');
+                } else if (e <= 99) {
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
+                } else {
+                    result[i++] = (char) (e / 100 + '0');
+                    e %= 100;
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
+                }
+            }
+            return i;
+        }
+
+    }
+
+    private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
+            new ThreadLocal<BinaryToASCIIBuffer>() {
+                @Override
+                protected BinaryToASCIIBuffer initialValue() {
+                    return new BinaryToASCIIBuffer();
+                }
+            };
+
+    private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
+        return threadLocalBinaryToASCIIBuffer.get();
+    }
+
+    /**
+     * A converter which can process an ASCII <code>String</code> representation
+     * of a single or double precision floating point value into a
+     * <code>float</code> or a <code>double</code>.
+     */
+    interface ASCIIToBinaryConverter {
+
+        double doubleValue();
+
+        float floatValue();
+
+    }
+
+    /**
+     * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
+     */
+    static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        private final double doubleVal;
+        private final float floatVal;
+
+        public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
+            this.doubleVal = doubleVal;
+            this.floatVal = floatVal;
+        }
+
+        @Override
+        public double doubleValue() {
+            return doubleVal;
+        }
+
+        @Override
+        public float floatValue() {
+            return floatVal;
+        }
+    }
+
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER  = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
+
+    /**
+     * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
+     */
+    static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        boolean     isNegative;
+        int         decExponent;
+        char        digits[];
+        int         nDigits;
+
+        ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
+        {
+            this.isNegative = negSign;
+            this.decExponent = decExponent;
+            this.digits = digits;
+            this.nDigits = n;
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a double.
+         *
+         * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+         * ROUNDING DIRECTION in case the result is really destined
+         * for a single-precision float.
+         */
+        @Override
+        public double doubleValue() {
+            int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
+            //
+            // convert the lead kDigits to a long integer.
+            //
+            // (special performance hack: start to do it using int)
+            int iValue = (int) digits[0] - (int) '0';
+            int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
+            for (int i = 1; i < iDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            long lValue = (long) iValue;
+            for (int i = iDigits; i < kDigits; i++) {
+                lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+            }
+            double dValue = (double) lValue;
+            int exp = decExponent - kDigits;
+            //
+            // lValue now contains a long integer with the value of
+            // the first kDigits digits of the number.
+            // dValue contains the (double) of the same.
+            //
+
+            if (nDigits <= MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here
+                //
+                if (exp == 0 || dValue == 0.0) {
+                    return (isNegative) ? -dValue : dValue; // small floating integer
+                }
+                else if (exp >= 0) {
+                    if (exp <= MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        double rValue = dValue * SMALL_10_POW[exp];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    int slop = MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply dValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        dValue *= SMALL_10_POW[slop];
+                        double rValue = dValue * SMALL_10_POW[exp - slop];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        double rValue = dValue / SMALL_10_POW[-exp];
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            }
+
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by approximating the right answer by,
+            // naively, scaling by powers of 10.
+            //
+            if (exp > 0) {
+                if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // Infinity. Cut to the chase.
+                    //
+                    return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                }
+                if ((exp & 15) != 0) {
+                    dValue *= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= BIG_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could overflow.
+                    //
+                    double t = dValue * BIG_10_POW[j];
+                    if (Double.isInfinite(t)) {
+                        //
+                        // It did overflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too large,
+                        // then use the maximum finite as our estimate
+                        // value. Else call the result infinity
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two larger than
+                        // Double.MAX_VALUE ).
+                        //
+                        t = dValue / 2.0;
+                        t *= BIG_10_POW[j];
+                        if (Double.isInfinite(t)) {
+                            return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                        }
+                        t = Double.MAX_VALUE;
+                    }
+                    dValue = t;
+                }
+            } else if (exp < 0) {
+                exp = -exp;
+                if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // zero. Cut to the chase.
+                    //
+                    return (isNegative) ? -0.0 : 0.0;
+                }
+                if ((exp & 15) != 0) {
+                    dValue /= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= TINY_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could underflow.
+                    //
+                    double t = dValue * TINY_10_POW[j];
+                    if (t == 0.0) {
+                        //
+                        // It did underflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too small,
+                        // then use the minimum finite as our estimate
+                        // value. Else call the result 0.0
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two less than
+                        // Double.MIN_VALUE ).
+                        //
+                        t = dValue * 2.0;
+                        t *= TINY_10_POW[j];
+                        if (t == 0.0) {
+                            return (isNegative) ? -0.0 : 0.0;
+                        }
+                        t = Double.MIN_VALUE;
+                    }
+                    dValue = t;
+                }
+            }
+
+            //
+            // dValue is now approximately the result.
+            // The hard part is adjusting it, by comparison
+            // with FDBigInteger arithmetic.
+            // Formulate the EXACT big-number result as
+            // bigD0 * 10^exp
+            //
+            if (nDigits > MAX_NDIGITS) {
+                nDigits = MAX_NDIGITS + 1;
+                digits[MAX_NDIGITS] = '1';
+            }
+            FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
+            exp = decExponent - nDigits;
+
+            long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
+            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+            bigD0 = bigD0.multByPow52(D5, 0);
+            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
+            FDBigInteger bigD = null;
+            int prevD2 = 0;
+
+            correctionLoop:
+            while (true) {
+                // here ieeeBits can't be NaN, Infinity or zero
+                int binexp = (int) (ieeeBits >>> EXP_SHIFT);
+                long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
+                if (binexp > 0) {
+                    bigBbits |= FRACT_HOB;
+                } else { // Normalize denormalized numbers.
+                    assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
+                    int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
+                    int shift = leadingZeros - (63 - EXP_SHIFT);
+                    bigBbits <<= shift;
+                    binexp = 1 - shift;
+                }
+                binexp -= DoubleConsts.EXP_BIAS;
+                int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
+                bigBbits >>>= lowOrderZeros;
+                final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
+                final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
+
+                //
+                // Scale bigD, bigB appropriately for
+                // big-integer operations.
+                // Naively, we multiply by powers of ten
+                // and powers of two. What we actually do
+                // is keep track of the powers of 5 and
+                // powers of 2 we would use, then factor out
+                // common divisors before doing the work.
+                //
+                int B2 = B5; // powers of 2 in bigB
+                int D2 = D5; // powers of 2 in bigD
+                int Ulp2;   // powers of 2 in halfUlp.
+                if (bigIntExp >= 0) {
+                    B2 += bigIntExp;
+                } else {
+                    D2 -= bigIntExp;
+                }
+                Ulp2 = B2;
+                // shift bigB and bigD left by a number s. t.
+                // halfUlp is still an integer.
+                int hulpbias;
+                if (binexp <= -DoubleConsts.EXP_BIAS) {
+                    // This is going to be a denormalized number
+                    // (if not actually zero).
+                    // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
+                    hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
+                } else {
+                    hulpbias = 1 + lowOrderZeros;
+                }
+                B2 += hulpbias;
+                D2 += hulpbias;
+                // if there are common factors of 2, we might just as well
+                // factor them out, as they add nothing useful.
+                int common2 = Math.min(B2, Math.min(D2, Ulp2));
+                B2 -= common2;
+                D2 -= common2;
+                Ulp2 -= common2;
+                // do multiplications by powers of 5 and 2
+                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+                if (bigD == null || prevD2 != D2) {
+                    bigD = bigD0.leftShift(D2);
+                    prevD2 = D2;
+                }
+                //
+                // to recap:
+                // bigB is the scaled-big-int version of our floating-point
+                // candidate.
+                // bigD is the scaled-big-int version of the exact value
+                // as we understand it.
+                // halfUlp is 1/2 an ulp of bigB, except for special cases
+                // of exact powers of 2
+                //
+                // the plan is to compare bigB with bigD, and if the difference
+                // is less than halfUlp, then we're satisfied. Otherwise,
+                // use the ratio of difference to halfUlp to calculate a fudge
+                // factor to add to the floating value, then go 'round again.
+                //
+                FDBigInteger diff;
+                int cmpResult;
+                boolean overvalue;
+                if ((cmpResult = bigB.cmp(bigD)) > 0) {
+                    overvalue = true; // our candidate is too big.
+                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+                    if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
+                        // candidate is a normalized exact power of 2 and
+                        // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
+                        // For our purposes, ulp is the ulp of the
+                        // next smaller range.
+                        Ulp2 -= 1;
+                        if (Ulp2 < 0) {
+                            // rats. Cannot de-scale ulp this far.
+                            // must scale diff in other direction.
+                            Ulp2 = 0;
+                            diff = diff.leftShift(1);
+                        }
+                    }
+                } else if (cmpResult < 0) {
+                    overvalue = false; // our candidate is too small.
+                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+                } else {
+                    // the candidate is exactly right!
+                    // this happens with surprising frequency
+                    break correctionLoop;
+                }
+                cmpResult = diff.cmpPow52(B5, Ulp2);
+                if ((cmpResult) < 0) {
+                    // difference is small.
+                    // this is close enough
+                    break correctionLoop;
+                } else if (cmpResult == 0) {
+                    // difference is exactly half an ULP
+                    // round to some other value maybe, then finish
+                    if ((ieeeBits & 1) != 0) { // half ties to even
+                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    }
+                    break correctionLoop;
+                } else {
+                    // difference is non-trivial.
+                    // could scale addend by ratio of difference to
+                    // halfUlp here, if we bothered to compute that difference.
+                    // Most of the time ( I hope ) it is about 1 anyway.
+                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
+                        break correctionLoop; // oops. Fell off end of range.
+                    }
+                    continue; // try again.
+                }
+
+            }
+            if (isNegative) {
+                ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
+            }
+            return Double.longBitsToDouble(ieeeBits);
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a float.
+         * This is distinct from doubleValue() to avoid the extremely
+         * unlikely case of a double rounding error, wherein the conversion
+         * to double has one rounding error, and the conversion of that double
+         * to a float has another rounding error, IN THE WRONG DIRECTION,
+         * ( because of the preference to a zero low-order bit ).
+         */
+        @Override
+        public float floatValue() {
+            int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
+            //
+            // convert the lead kDigits to an integer.
+            //
+            int iValue = (int) digits[0] - (int) '0';
+            for (int i = 1; i < kDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            float fValue = (float) iValue;
+            int exp = decExponent - kDigits;
+            //
+            // iValue now contains an integer with the value of
+            // the first kDigits digits of the number.
+            // fValue contains the (float) of the same.
+            //
+
+            if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here.
+                //
+                if (exp == 0 || fValue == 0.0f) {
+                    return (isNegative) ? -fValue : fValue; // small floating integer
+                } else if (exp >= 0) {
+                    if (exp <= SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply fValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[slop];
+                        fValue *= SINGLE_SMALL_10_POW[exp - slop];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        fValue /= SINGLE_SMALL_10_POW[-exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
+                //
+                // In double-precision, this is an exact floating integer.
+                // So we can compute to double, then shorten to float
+                // with one round, and get the right answer.
+                //
+                // First, finish accumulating digits.
+                // Then convert that integer to a double, multiply
+                // by the appropriate power of ten, and convert to float.
+                //
+                long lValue = (long) iValue;
+                for (int i = kDigits; i < nDigits; i++) {
+                    lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+                }
+                double dValue = (double) lValue;
+                exp = decExponent - nDigits;
+                dValue *= SMALL_10_POW[exp];
+                fValue = (float) dValue;
+                return (isNegative) ? -fValue : fValue;
+
+            }
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by approximating the right answer by,
+            // naively, scaling by powers of 10.
+            // Scaling uses doubles to avoid overflow/underflow.
+            //
+            double dValue = fValue;
+            if (exp > 0) {
+                if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // Infinity. Cut to the chase.
+                    //
+                    return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+                }
+                if ((exp & 15) != 0) {
+                    dValue *= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 0; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= BIG_10_POW[j];
+                        }
+                    }
+                }
+            } else if (exp < 0) {
+                exp = -exp;
+                if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // zero. Cut to the chase.
+                    //
+                    return (isNegative) ? -0.0f : 0.0f;
+                }
+                if ((exp & 15) != 0) {
+                    dValue /= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 0; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= TINY_10_POW[j];
+                        }
+                    }
+                }
+            }
+            fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
+
+            //
+            // fValue is now approximately the result.
+            // The hard part is adjusting it, by comparison
+            // with FDBigInteger arithmetic.
+            // Formulate the EXACT big-number result as
+            // bigD0 * 10^exp
+            //
+            if (nDigits > SINGLE_MAX_NDIGITS) {
+                nDigits = SINGLE_MAX_NDIGITS + 1;
+                digits[SINGLE_MAX_NDIGITS] = '1';
+            }
+            FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
+            exp = decExponent - nDigits;
+
+            int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
+            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+            bigD0 = bigD0.multByPow52(D5, 0);
+            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
+            FDBigInteger bigD = null;
+            int prevD2 = 0;
+
+            correctionLoop:
+            while (true) {
+                // here ieeeBits can't be NaN, Infinity or zero
+                int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
+                int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
+                if (binexp > 0) {
+                    bigBbits |= SINGLE_FRACT_HOB;
+                } else { // Normalize denormalized numbers.
+                    assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
+                    int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
+                    int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
+                    bigBbits <<= shift;
+                    binexp = 1 - shift;
+                }
+                binexp -= FloatConsts.EXP_BIAS;
+                int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
+                bigBbits >>>= lowOrderZeros;
+                final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
+                final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
+
+                //
+                // Scale bigD, bigB appropriately for
+                // big-integer operations.
+                // Naively, we multiply by powers of ten
+                // and powers of two. What we actually do
+                // is keep track of the powers of 5 and
+                // powers of 2 we would use, then factor out
+                // common divisors before doing the work.
+                //
+                int B2 = B5; // powers of 2 in bigB
+                int D2 = D5; // powers of 2 in bigD
+                int Ulp2;   // powers of 2 in halfUlp.
+                if (bigIntExp >= 0) {
+                    B2 += bigIntExp;
+                } else {
+                    D2 -= bigIntExp;
+                }
+                Ulp2 = B2;
+                // shift bigB and bigD left by a number s. t.
+                // halfUlp is still an integer.
+                int hulpbias;
+                if (binexp <= -FloatConsts.EXP_BIAS) {
+                    // This is going to be a denormalized number
+                    // (if not actually zero).
+                    // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
+                    hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
+                } else {
+                    hulpbias = 1 + lowOrderZeros;
+                }
+                B2 += hulpbias;
+                D2 += hulpbias;
+                // if there are common factors of 2, we might just as well
+                // factor them out, as they add nothing useful.
+                int common2 = Math.min(B2, Math.min(D2, Ulp2));
+                B2 -= common2;
+                D2 -= common2;
+                Ulp2 -= common2;
+                // do multiplications by powers of 5 and 2
+                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+                if (bigD == null || prevD2 != D2) {
+                    bigD = bigD0.leftShift(D2);
+                    prevD2 = D2;
+                }
+                //
+                // to recap:
+                // bigB is the scaled-big-int version of our floating-point
+                // candidate.
+                // bigD is the scaled-big-int version of the exact value
+                // as we understand it.
+                // halfUlp is 1/2 an ulp of bigB, except for special cases
+                // of exact powers of 2
+                //
+                // the plan is to compare bigB with bigD, and if the difference
+                // is less than halfUlp, then we're satisfied. Otherwise,
+                // use the ratio of difference to halfUlp to calculate a fudge
+                // factor to add to the floating value, then go 'round again.
+                //
+                FDBigInteger diff;
+                int cmpResult;
+                boolean overvalue;
+                if ((cmpResult = bigB.cmp(bigD)) > 0) {
+                    overvalue = true; // our candidate is too big.
+                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+                    if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
+                        // candidate is a normalized exact power of 2 and
+                        // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
+                        // For our purposes, ulp is the ulp of the
+                        // next smaller range.
+                        Ulp2 -= 1;
+                        if (Ulp2 < 0) {
+                            // rats. Cannot de-scale ulp this far.
+                            // must scale diff in other direction.
+                            Ulp2 = 0;
+                            diff = diff.leftShift(1);
+                        }
+                    }
+                } else if (cmpResult < 0) {
+                    overvalue = false; // our candidate is too small.
+                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+                } else {
+                    // the candidate is exactly right!
+                    // this happens with surprising frequency
+                    break correctionLoop;
+                }
+                cmpResult = diff.cmpPow52(B5, Ulp2);
+                if ((cmpResult) < 0) {
+                    // difference is small.
+                    // this is close enough
+                    break correctionLoop;
+                } else if (cmpResult == 0) {
+                    // difference is exactly half an ULP
+                    // round to some other value maybe, then finish
+                    if ((ieeeBits & 1) != 0) { // half ties to even
+                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    }
+                    break correctionLoop;
+                } else {
+                    // difference is non-trivial.
+                    // could scale addend by ratio of difference to
+                    // halfUlp here, if we bothered to compute that difference.
+                    // Most of the time ( I hope ) it is about 1 anyway.
+                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+                    if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
+                        break correctionLoop; // oops. Fell off end of range.
+                    }
+                    continue; // try again.
+                }
+
+            }
+            if (isNegative) {
+                ieeeBits |= FloatConsts.SIGN_BIT_MASK;
+            }
+            return Float.intBitsToFloat(ieeeBits);
+        }
+
+
+        /**
+         * All the positive powers of 10 that can be
+         * represented exactly in double/float.
+         */
+        private static final double[] SMALL_10_POW = {
+            1.0e0,
+            1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+            1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+            1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+            1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+            1.0e21, 1.0e22
+        };
+
+        private static final float[] SINGLE_SMALL_10_POW = {
+            1.0e0f,
+            1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+            1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+        };
+
+        private static final double[] BIG_10_POW = {
+            1e16, 1e32, 1e64, 1e128, 1e256 };
+        private static final double[] TINY_10_POW = {
+            1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+        private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
+        private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
+
+    }
+
+    /**
+     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+     * The returned object is a <code>ThreadLocal</code> variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @return The converter.
+     */
+    public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
+        return getBinaryToASCIIConverter(d, true);
+    }
+
+    /**
+     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+     * The returned object is a <code>ThreadLocal</code> variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @param isCompatibleFormat
+     * @return The converter.
+     */
+    static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
+        long dBits = Double.doubleToRawLongBits(d);
+        boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+        long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
+        int  binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
+            }
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0L ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+            }
+            int leadingZeros = Long.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(63-EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  64-leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= FRACT_HOB;
+            nSignificantBits = EXP_SHIFT+1;
+        }
+        binExp -= DoubleConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
+        return buf;
+    }
+
+    private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
+        int fBits = Float.floatToRawIntBits( f );
+        boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
+        int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
+        int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
+            }
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0 ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+            }
+            int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  32 - leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= SINGLE_FRACT_HOB;
+            nSignificantBits = SINGLE_EXP_SHIFT+1;
+        }
+        binExp -= FloatConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
+        return buf;
+    }
+
+    @SuppressWarnings("fallthrough")
+    static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
+        boolean isNegative = false;
+        boolean signSeen   = false;
+        int     decExp;
+        char    c;
+
+    parseNumber:
+        try{
+            in = in.trim(); // don't fool around with white space.
+                            // throws NullPointerException if null
+            int len = in.length();
+            if ( len == 0 ) {
+                throw new NumberFormatException("empty String");
+            }
+            int i = 0;
+            switch (in.charAt(i)){
+            case '-':
+                isNegative = true;
+                //FALLTHROUGH
+            case '+':
+                i++;
+                signSeen = true;
+            }
+            c = in.charAt(i);
+            if(c == 'N') { // Check for NaN
+                if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
+                    return A2BC_NOT_A_NUMBER;
+                }
+                // something went wrong, throw exception
+                break parseNumber;
+            } else if(c == 'I') { // Check for Infinity strings
+                if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
+                    return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+                }
+                // something went wrong, throw exception
+                break parseNumber;
+            } else if (c == '0')  { // check for hexadecimal floating-point number
+                if (len > i+1 ) {
+                    char ch = in.charAt(i+1);
+                    if (ch == 'x' || ch == 'X' ) { // possible hex string
+                        return parseHexString(in);
+                    }
+                }
+            }  // look for and process decimal floating-point string
+
+            char[] digits = new char[ len ];
+            int    nDigits= 0;
+            boolean decSeen = false;
+            int decPt = 0;
+            int nLeadZero = 0;
+            int nTrailZero= 0;
+
+        skipLeadingZerosLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c == '0') {
+                    nLeadZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
+                        // already saw one ., this is the 2nd.
+                        throw new NumberFormatException("multiple points");
+                    }
+                    decPt = i;
+                    if (signSeen) {
+                        decPt -= 1;
+                    }
+                    decSeen = true;
+                } else {
+                    break skipLeadingZerosLoop;
+                }
+                i++;
+            }
+        digitLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c >= '1' && c <= '9') {
+                    digits[nDigits++] = c;
+                    nTrailZero = 0;
+                } else if (c == '0') {
+                    digits[nDigits++] = c;
+                    nTrailZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
+                        // already saw one ., this is the 2nd.
+                        throw new NumberFormatException("multiple points");
+                    }
+                    decPt = i;
+                    if (signSeen) {
+                        decPt -= 1;
+                    }
+                    decSeen = true;
+                } else {
+                    break digitLoop;
+                }
+                i++;
+            }
+            nDigits -=nTrailZero;
+            //
+            // At this point, we've scanned all the digits and decimal
+            // point we're going to see. Trim off leading and trailing
+            // zeros, which will just confuse us later, and adjust
+            // our initial decimal exponent accordingly.
+            // To review:
+            // we have seen i total characters.
+            // nLeadZero of them were zeros before any other digits.
+            // nTrailZero of them were zeros after any other digits.
+            // if ( decSeen ), then a . was seen after decPt characters
+            // ( including leading zeros which have been discarded )
+            // nDigits characters were neither lead nor trailing
+            // zeros, nor point
+            //
+            //
+            // special hack: if we saw no non-zero digits, then the
+            // answer is zero!
+            // Unfortunately, we feel honor-bound to keep parsing!
+            //
+            boolean isZero = (nDigits == 0);
+            if ( isZero &&  nLeadZero == 0 ){
+                // we saw NO DIGITS AT ALL,
+                // not even a crummy 0!
+                // this is not allowed.
+                break parseNumber; // go throw exception
+            }
+            //
+            // Our initial exponent is decPt, adjusted by the number of
+            // discarded zeros. Or, if there was no decPt,
+            // then its just nDigits adjusted by discarded trailing zeros.
+            //
+            if ( decSeen ){
+                decExp = decPt - nLeadZero;
+            } else {
+                decExp = nDigits + nTrailZero;
+            }
+
+            //
+            // Look for 'e' or 'E' and an optionally signed integer.
+            //
+            if ( (i < len) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+                int expSign = 1;
+                int expVal  = 0;
+                int reallyBig = Integer.MAX_VALUE / 10;
+                boolean expOverflow = false;
+                switch( in.charAt(++i) ){
+                case '-':
+                    expSign = -1;
+                    //FALLTHROUGH
+                case '+':
+                    i++;
+                }
+                int expAt = i;
+            expLoop:
+                while ( i < len  ){
+                    if ( expVal >= reallyBig ){
+                        // the next character will cause integer
+                        // overflow.
+                        expOverflow = true;
+                    }
+                    c = in.charAt(i++);
+                    if(c>='0' && c<='9') {
+                        expVal = expVal*10 + ( (int)c - (int)'0' );
+                    } else {
+                        i--;           // back up.
+                        break expLoop; // stop parsing exponent.
+                    }
+                }
+                int expLimit = BIG_DECIMAL_EXPONENT + nDigits + nTrailZero;
+                if (expOverflow || (expVal > expLimit)) {
+                    // There is still a chance that the exponent will be safe to
+                    // use: if it would eventually decrease due to a negative
+                    // decExp, and that number is below the limit.  We check for
+                    // that here.
+                    if (!expOverflow && (expSign == 1 && decExp < 0)
+                            && (expVal + decExp) < expLimit) {
+                        // Cannot overflow: adding a positive and negative number.
+                        decExp += expVal;
+                    } else {
+                        //
+                        // The intent here is to end up with
+                        // infinity or zero, as appropriate.
+                        // The reason for yielding such a small decExponent,
+                        // rather than something intuitive such as
+                        // expSign*Integer.MAX_VALUE, is that this value
+                        // is subject to further manipulation in
+                        // doubleValue() and floatValue(), and I don't want
+                        // it to be able to cause overflow there!
+                        // (The only way we can get into trouble here is for
+                        // really outrageous nDigits+nTrailZero, such as 2
+                        // billion.)
+                        //
+                        decExp = expSign * expLimit;
+                    }
+                } else {
+                    // this should not overflow, since we tested
+                    // for expVal > (MAX+N), where N >= abs(decExp)
+                    decExp = decExp + expSign*expVal;
+                }
+
+                // if we saw something not a digit ( or end of string )
+                // after the [Ee][+-], without seeing any digits at all
+                // this is certainly an error. If we saw some digits,
+                // but then some trailing garbage, that might be ok.
+                // so we just fall through in that case.
+                // HUMBUG
+                if ( i == expAt ) {
+                    break parseNumber; // certainly bad
+                }
+            }
+            //
+            // We parsed everything we could.
+            // If there are leftovers, then this is not good input!
+            //
+            if ( i < len &&
+                ((i != len - 1) ||
+                (in.charAt(i) != 'f' &&
+                 in.charAt(i) != 'F' &&
+                 in.charAt(i) != 'd' &&
+                 in.charAt(i) != 'D'))) {
+                break parseNumber; // go throw exception
+            }
+            if(isZero) {
+                return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+            }
+            return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
+        } catch ( StringIndexOutOfBoundsException e ){ }
+        throw new NumberFormatException("For input string: \"" + in + "\"");
+    }
+
+    private static class HexFloatPattern {
+        /**
+         * Grammar is compatible with hexadecimal floating-point constants
+         * described in section 6.4.4.2 of the C99 specification.
+         */
+        private static final Pattern VALUE = Pattern.compile(
+                   //1           234                   56                7                   8      9
+                    "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+                    );
+    }
+
+    /**
+     * Converts string s to a suitable floating decimal; uses the
+     * double constructor and sets the roundDir variable appropriately
+     * in case the value is later converted to a float.
+     *
+     * @param s The <code>String</code> to parse.
+     */
+   static ASCIIToBinaryConverter parseHexString(String s) {
+            // Verify string is a member of the hexadecimal floating-point
+            // string language.
+            Matcher m = HexFloatPattern.VALUE.matcher(s);
+            boolean validInput = m.matches();
+            if (!validInput) {
+                // Input does not match pattern
+                throw new NumberFormatException("For input string: \"" + s + "\"");
+            } else { // validInput
+                //
+                // We must isolate the sign, significand, and exponent
+                // fields.  The sign value is straightforward.  Since
+                // floating-point numbers are stored with a normalized
+                // representation, the significand and exponent are
+                // interrelated.
+                //
+                // After extracting the sign, we normalized the
+                // significand as a hexadecimal value, calculating an
+                // exponent adjust for any shifts made during
+                // normalization.  If the significand is zero, the
+                // exponent doesn't need to be examined since the output
+                // will be zero.
+                //
+                // Next the exponent in the input string is extracted.
+                // Afterwards, the significand is normalized as a *binary*
+                // value and the input value's normalized exponent can be
+                // computed.  The significand bits are copied into a
+                // double significand; if the string has more logical bits
+                // than can fit in a double, the extra bits affect the
+                // round and sticky bits which are used to round the final
+                // value.
+                //
+                //  Extract significand sign
+                String group1 = m.group(1);
+                boolean isNegative = ((group1 != null) && group1.equals("-"));
+
+                //  Extract Significand magnitude
+                //
+                // Based on the form of the significand, calculate how the
+                // binary exponent needs to be adjusted to create a
+                // normalized//hexadecimal* floating-point number; that
+                // is, a number where there is one nonzero hex digit to
+                // the left of the (hexa)decimal point.  Since we are
+                // adjusting a binary, not hexadecimal exponent, the
+                // exponent is adjusted by a multiple of 4.
+                //
+                // There are a number of significand scenarios to consider;
+                // letters are used in indicate nonzero digits:
+                //
+                // 1. 000xxxx       =>      x.xxx   normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 2. 000xxx.yyyy =>        x.xxyyyy        normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 3. .000yyy  =>   y.yy    normalized
+                //    decrease exponent by (number of zeros + 1)*4
+                //
+                // 4. 000.00000yyy => y.yy normalized
+                //    decrease exponent by (number of zeros to right of point + 1)*4
+                //
+                // If the significand is exactly zero, return a properly
+                // signed zero.
+                //
+
+                String significandString = null;
+                int signifLength = 0;
+                int exponentAdjust = 0;
+                {
+                    int leftDigits = 0; // number of meaningful digits to
+                    // left of "decimal" point
+                    // (leading zeros stripped)
+                    int rightDigits = 0; // number of digits to right of
+                    // "decimal" point; leading zeros
+                    // must always be accounted for
+                    //
+                    // The significand is made up of either
+                    //
+                    // 1. group 4 entirely (integer portion only)
+                    //
+                    // OR
+                    //
+                    // 2. the fractional portion from group 7 plus any
+                    // (optional) integer portions from group 6.
+                    //
+                    String group4;
+                    if ((group4 = m.group(4)) != null) {  // Integer-only significand
+                        // Leading zeros never matter on the integer portion
+                        significandString = stripLeadingZeros(group4);
+                        leftDigits = significandString.length();
+                    } else {
+                        // Group 6 is the optional integer; leading zeros
+                        // never matter on the integer portion
+                        String group6 = stripLeadingZeros(m.group(6));
+                        leftDigits = group6.length();
+
+                        // fraction
+                        String group7 = m.group(7);
+                        rightDigits = group7.length();
+
+                        // Turn "integer.fraction" into "integer"+"fraction"
+                        significandString =
+                                ((group6 == null) ? "" : group6) + // is the null
+                                        // check necessary?
+                                        group7;
+                    }
+
+                    significandString = stripLeadingZeros(significandString);
+                    signifLength = significandString.length();
+
+                    //
+                    // Adjust exponent as described above
+                    //
+                    if (leftDigits >= 1) {  // Cases 1 and 2
+                        exponentAdjust = 4 * (leftDigits - 1);
+                    } else {                // Cases 3 and 4
+                        exponentAdjust = -4 * (rightDigits - signifLength + 1);
+                    }
+
+                    // If the significand is zero, the exponent doesn't
+                    // matter; return a properly signed zero.
+
+                    if (signifLength == 0) { // Only zeros in input
+                        return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+                    }
+                }
+
+                //  Extract Exponent
+                //
+                // Use an int to read in the exponent value; this should
+                // provide more than sufficient range for non-contrived
+                // inputs.  If reading the exponent in as an int does
+                // overflow, examine the sign of the exponent and
+                // significand to determine what to do.
+                //
+                String group8 = m.group(8);
+                boolean positiveExponent = (group8 == null) || group8.equals("+");
+                long unsignedRawExponent;
+                try {
+                    unsignedRawExponent = Integer.parseInt(m.group(9));
+                }
+                catch (NumberFormatException e) {
+                    // At this point, we know the exponent is
+                    // syntactically well-formed as a sequence of
+                    // digits.  Therefore, if an NumberFormatException
+                    // is thrown, it must be due to overflowing int's
+                    // range.  Also, at this point, we have already
+                    // checked for a zero significand.  Thus the signs
+                    // of the exponent and significand determine the
+                    // final result:
+                    //
+                    //                      significand
+                    //                      +               -
+                    // exponent     +       +infinity       -infinity
+                    //              -       +0.0            -0.0
+                    return isNegative ?
+                              (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
+                            : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
+
+                }
+
+                long rawExponent =
+                        (positiveExponent ? 1L : -1L) * // exponent sign
+                                unsignedRawExponent;            // exponent magnitude
+
+                // Calculate partially adjusted exponent
+                long exponent = rawExponent + exponentAdjust;
+
+                // Starting copying non-zero bits into proper position in
+                // a long; copy explicit bit too; this will be masked
+                // later for normal values.
+
+                boolean round = false;
+                boolean sticky = false;
+                int nextShift = 0;
+                long significand = 0L;
+                // First iteration is different, since we only copy
+                // from the leading significand bit; one more exponent
+                // adjust will be needed...
+
+                // IMPORTANT: make leadingDigit a long to avoid
+                // surprising shift semantics!
+                long leadingDigit = getHexDigit(significandString, 0);
+
+                //
+                // Left shift the leading digit (53 - (bit position of
+                // leading 1 in digit)); this sets the top bit of the
+                // significand to 1.  The nextShift value is adjusted
+                // to take into account the number of bit positions of
+                // the leadingDigit actually used.  Finally, the
+                // exponent is adjusted to normalize the significand
+                // as a binary value, not just a hex value.
+                //
+                if (leadingDigit == 1) {
+                    significand |= leadingDigit << 52;
+                    nextShift = 52 - 4;
+                    // exponent += 0
+                } else if (leadingDigit <= 3) { // [2, 3]
+                    significand |= leadingDigit << 51;
+                    nextShift = 52 - 5;
+                    exponent += 1;
+                } else if (leadingDigit <= 7) { // [4, 7]
+                    significand |= leadingDigit << 50;
+                    nextShift = 52 - 6;
+                    exponent += 2;
+                } else if (leadingDigit <= 15) { // [8, f]
+                    significand |= leadingDigit << 49;
+                    nextShift = 52 - 7;
+                    exponent += 3;
+                } else {
+                    throw new AssertionError("Result from digit conversion too large!");
+                }
+                // The preceding if-else could be replaced by a single
+                // code block based on the high-order bit set in
+                // leadingDigit.  Given leadingOnePosition,
+
+                // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+                // nextShift = 52 - (3 + leadingOnePosition);
+                // exponent += (leadingOnePosition-1);
+
+                //
+                // Now the exponent variable is equal to the normalized
+                // binary exponent.  Code below will make representation
+                // adjustments if the exponent is incremented after
+                // rounding (includes overflows to infinity) or if the
+                // result is subnormal.
+                //
+
+                // Copy digit into significand until the significand can't
+                // hold another full hex digit or there are no more input
+                // hex digits.
+                int i = 0;
+                for (i = 1;
+                     i < signifLength && nextShift >= 0;
+                     i++) {
+                    long currentDigit = getHexDigit(significandString, i);
+                    significand |= (currentDigit << nextShift);
+                    nextShift -= 4;
+                }
+
+                // After the above loop, the bulk of the string is copied.
+                // Now, we must copy any partial hex digits into the
+                // significand AND compute the round bit and start computing
+                // sticky bit.
+
+                if (i < signifLength) { // at least one hex input digit exists
+                    long currentDigit = getHexDigit(significandString, i);
+
+                    // from nextShift, figure out how many bits need
+                    // to be copied, if any
+                    switch (nextShift) { // must be negative
+                        case -1:
+                            // three bits need to be copied in; can
+                            // set round bit
+                            significand |= ((currentDigit & 0xEL) >> 1);
+                            round = (currentDigit & 0x1L) != 0L;
+                            break;
+
+                        case -2:
+                            // two bits need to be copied in; can
+                            // set round and start sticky
+                            significand |= ((currentDigit & 0xCL) >> 2);
+                            round = (currentDigit & 0x2L) != 0L;
+                            sticky = (currentDigit & 0x1L) != 0;
+                            break;
+
+                        case -3:
+                            // one bit needs to be copied in
+                            significand |= ((currentDigit & 0x8L) >> 3);
+                            // Now set round and start sticky, if possible
+                            round = (currentDigit & 0x4L) != 0L;
+                            sticky = (currentDigit & 0x3L) != 0;
+                            break;
+
+                        case -4:
+                            // all bits copied into significand; set
+                            // round and start sticky
+                            round = ((currentDigit & 0x8L) != 0);  // is top bit set?
+                            // nonzeros in three low order bits?
+                            sticky = (currentDigit & 0x7L) != 0;
+                            break;
+
+                        default:
+                            throw new AssertionError("Unexpected shift distance remainder.");
+                            // break;
+                    }
+
+                    // Round is set; sticky might be set.
+
+                    // For the sticky bit, it suffices to check the
+                    // current digit and test for any nonzero digits in
+                    // the remaining unprocessed input.
+                    i++;
+                    while (i < signifLength && !sticky) {
+                        currentDigit = getHexDigit(significandString, i);
+                        sticky = sticky || (currentDigit != 0);
+                        i++;
+                    }
+
+                }
+                // else all of string was seen, round and sticky are
+                // correct as false.
+
+                // Float calculations
+                int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
+                if (exponent >= Float.MIN_EXPONENT) {
+                    if (exponent > Float.MAX_EXPONENT) {
+                        // Float.POSITIVE_INFINITY
+                        floatBits |= FloatConsts.EXP_BIT_MASK;
+                    } else {
+                        int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
+                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+                        int iValue = (int) (significand >>> threshShift);
+                        if ((iValue & 3) != 1 || floatSticky) {
+                            iValue++;
+                        }
+                        floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
+                    }
+                } else {
+                    if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
+                        // 0
+                    } else {
+                        // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
+                        int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
+                        assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
+                        assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
+                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+                        int iValue = (int) (significand >>> threshShift);
+                        if ((iValue & 3) != 1 || floatSticky) {
+                            iValue++;
+                        }
+                        floatBits |= iValue >> 1;
+                    }
+                }
+                float fValue = Float.intBitsToFloat(floatBits);
+
+                // Check for overflow and update exponent accordingly.
+                if (exponent > Double.MAX_EXPONENT) {         // Infinite result
+                    // overflow to properly signed infinity
+                    return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+                } else {  // Finite return value
+                    if (exponent <= Double.MAX_EXPONENT && // (Usually) normal result
+                            exponent >= Double.MIN_EXPONENT) {
+
+                        // The result returned in this block cannot be a
+                        // zero or subnormal; however after the
+                        // significand is adjusted from rounding, we could
+                        // still overflow in infinity.
+
+                        // AND exponent bits into significand; if the
+                        // significand is incremented and overflows from
+                        // rounding, this combination will update the
+                        // exponent correctly, even in the case of
+                        // Double.MAX_VALUE overflowing to infinity.
+
+                        significand = ((( exponent +
+                                (long) DoubleConsts.EXP_BIAS) <<
+                                (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                & DoubleConsts.EXP_BIT_MASK) |
+                                (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+                    } else {  // Subnormal or zero
+                        // (exponent < Double.MIN_EXPONENT)
+
+                        if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
+                            // No way to round back to nonzero value
+                            // regardless of significand if the exponent is
+                            // less than -1075.
+                            return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+                        } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+                            //
+                            // Find bit position to round to; recompute
+                            // round and sticky bits, and shift
+                            // significand right appropriately.
+                            //
+
+                            sticky = sticky || round;
+                            round = false;
+
+                            // Number of bits of significand to preserve is
+                            // exponent - abs_min_exp +1
+                            // check:
+                            // -1075 +1074 + 1 = 0
+                            // -1023 +1074 + 1 = 52
+
+                            int bitsDiscarded = 53 -
+                                    ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+                            assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+                            // What to do here:
+                            // First, isolate the new round bit
+                            round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
+                            if (bitsDiscarded > 1) {
+                                // create mask to update sticky bits; low
+                                // order bitsDiscarded bits should be 1
+                                long mask = ~((~0L) << (bitsDiscarded - 1));
+                                sticky = sticky || ((significand & mask) != 0L);
+                            }
+
+                            // Now, discard the bits
+                            significand = significand >> bitsDiscarded;
+
+                            significand = ((((long) (Double.MIN_EXPONENT - 1) + // subnorm exp.
+                                    (long) DoubleConsts.EXP_BIAS) <<
+                                    (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                    & DoubleConsts.EXP_BIT_MASK) |
+                                    (DoubleConsts.SIGNIF_BIT_MASK & significand);
+                        }
+                    }
+
+                    // The significand variable now contains the currently
+                    // appropriate exponent bits too.
+
+                    //
+                    // Determine if significand should be incremented;
+                    // making this determination depends on the least
+                    // significant bit and the round and sticky bits.
+                    //
+                    // Round to nearest even rounding table, adapted from
+                    // table 4.7 in "Computer Arithmetic" by IsraelKoren.
+                    // The digit to the left of the "decimal" point is the
+                    // least significant bit, the digits to the right of
+                    // the point are the round and sticky bits
+                    //
+                    // Number       Round(x)
+                    // x0.00        x0.
+                    // x0.01        x0.
+                    // x0.10        x0.
+                    // x0.11        x1. = x0. +1
+                    // x1.00        x1.
+                    // x1.01        x1.
+                    // x1.10        x1. + 1
+                    // x1.11        x1. + 1
+                    //
+                    boolean leastZero = ((significand & 1L) == 0L);
+                    if ((leastZero && round && sticky) ||
+                            ((!leastZero) && round)) {
+                        significand++;
+                    }
+
+                    double value = isNegative ?
+                            Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
+                            Double.longBitsToDouble(significand );
+
+                    return new PreparedASCIIToBinaryBuffer(value, fValue);
+                }
+            }
+    }
+
+    /**
+     * Returns <code>s</code> with any leading zeros removed.
+     */
+    static String stripLeadingZeros(String s) {
+//        return  s.replaceFirst("^0+", "");
+        if(!s.isEmpty() && s.charAt(0)=='0') {
+            for(int i=1; i<s.length(); i++) {
+                if(s.charAt(i)!='0') {
+                    return s.substring(i);
+                }
+            }
+            return "";
+        }
+        return s;
+    }
+
+    /**
+     * Extracts a hexadecimal digit from position <code>position</code>
+     * of string <code>s</code>.
+     */
+    static int getHexDigit(String s, int position) {
+        int value = Character.digit(s.charAt(position), 16);
+        if (value <= -1 || value >= 16) {
+            throw new AssertionError("Unexpected failure of digit conversion of " +
+                                     s.charAt(position));
+        }
+        return value;
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/math/FormattedFloatingDecimal.java b/ojluni/src/main/java/jdk/internal/math/FormattedFloatingDecimal.java
new file mode 100644
index 0000000..88cd1fe
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/math/FormattedFloatingDecimal.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+import java.util.Arrays;
+
+public class FormattedFloatingDecimal{
+
+    public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
+
+
+    public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
+        FloatingDecimal.BinaryToASCIIConverter fdConverter =
+                FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
+        return new FormattedFloatingDecimal(precision,form, fdConverter);
+    }
+
+    private int decExponentRounded;
+    private char[] mantissa;
+    private char[] exponent;
+
+    private static final ThreadLocal<Object> threadLocalCharBuffer =
+            new ThreadLocal<Object>() {
+                @Override
+                protected Object initialValue() {
+                    return new char[20];
+                }
+            };
+
+    private static char[] getBuffer(){
+        return (char[]) threadLocalCharBuffer.get();
+    }
+
+    private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
+        if (fdConverter.isExceptional()) {
+            this.mantissa = fdConverter.toJavaFormatString().toCharArray();
+            this.exponent = null;
+            return;
+        }
+        char[] digits = getBuffer();
+        int nDigits = fdConverter.getDigits(digits);
+        int decExp = fdConverter.getDecimalExponent();
+        int exp;
+        boolean isNegative = fdConverter.isNegative();
+        switch (form) {
+            case COMPATIBLE:
+                exp = decExp;
+                this.decExponentRounded = exp;
+                fillCompatible(precision, digits, nDigits, exp, isNegative);
+                break;
+            case DECIMAL_FLOAT:
+                exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
+                fillDecimal(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case SCIENTIFIC:
+                exp = applyPrecision(decExp, digits, nDigits, precision + 1);
+                fillScientific(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case GENERAL:
+                exp = applyPrecision(decExp, digits, nDigits, precision);
+                // adjust precision to be the number of digits to right of decimal
+                // the real exponent to be output is actually exp - 1, not exp
+                if (exp - 1 < -4 || exp - 1 >= precision) {
+                    // form = Form.SCIENTIFIC;
+                    precision--;
+                    fillScientific(precision, digits, nDigits, exp, isNegative);
+                } else {
+                    // form = Form.DECIMAL_FLOAT;
+                    precision = precision - exp;
+                    fillDecimal(precision, digits, nDigits, exp, isNegative);
+                }
+                this.decExponentRounded = exp;
+                break;
+            default:
+                assert false;
+        }
+    }
+
+    // returns the exponent after rounding has been done by applyPrecision
+    public int getExponentRounded() {
+        return decExponentRounded - 1;
+    }
+
+    /**
+     * Returns the mantissa as a {@code char[]}.  Note that the returned value
+     * is a reference to the internal {@code char[]} containing the mantissa,
+     * therefore code invoking this method should not pass the return value to
+     * external code but should in that case make a copy.
+     *
+     * @return a reference to the internal {@code char[]} representing the
+     *         mantissa.
+     */
+    public char[] getMantissa(){
+        return mantissa;
+    }
+
+    /**
+     * Returns the exponent as a {@code char[]}.  Note that the returned value
+     * is a reference to the internal {@code char[]} containing the exponent,
+     * therefore code invoking this method should not pass the return value to
+     * external code but should in that case make a copy.
+     *
+     * @return a reference to the internal {@code char[]} representing the
+     *         exponent.
+     */
+    public char[] getExponent(){
+        return exponent;
+    }
+
+    /**
+     * Returns new decExp in case of overflow.
+     */
+    private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
+        if (prec >= nDigits || prec < 0) {
+            // no rounding necessary
+            return decExp;
+        }
+        if (prec == 0) {
+            // only one digit (0 or 1) is returned because the precision
+            // excludes all significant digits
+            if (digits[0] >= '5') {
+                digits[0] = '1';
+                Arrays.fill(digits, 1, nDigits, '0');
+                return decExp + 1;
+            } else {
+                Arrays.fill(digits, 0, nDigits, '0');
+                return decExp;
+            }
+        }
+        int q = digits[prec];
+        if (q >= '5') {
+            int i = prec;
+            q = digits[--i];
+            if ( q == '9' ) {
+                while ( q == '9' && i > 0 ){
+                    q = digits[--i];
+                }
+                if ( q == '9' ){
+                    // carryout! High-order 1, rest 0s, larger exp.
+                    digits[0] = '1';
+                    Arrays.fill(digits, 1, nDigits, '0');
+                    return decExp+1;
+                }
+            }
+            digits[i] = (char)(q + 1);
+            Arrays.fill(digits, i+1, nDigits, '0');
+        } else {
+            Arrays.fill(digits, prec, nDigits, '0');
+        }
+        return decExp;
+    }
+
+    /**
+     * Fills mantissa and exponent char arrays for compatible format.
+     */
+    private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0 && exp < 8) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                int extraZeros = exp - nDigits;
+                mantissa = create(isNegative, nDigits + extraZeros + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
+                mantissa[startIndex + nDigits + extraZeros] = '.';
+                mantissa[startIndex + nDigits + extraZeros+1] = '0';
+            } else if (exp < nDigits) {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + 1 + t);
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                mantissa[startIndex + exp ] = '.';
+                System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
+            } else { // exp == digits.length
+                mantissa = create(isNegative, nDigits + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                mantissa[startIndex + nDigits ] = '.';
+                mantissa[startIndex + nDigits +1] = '0';
+            }
+        } else if (exp <= 0 && exp > -3) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+                if (t > 0) {
+                    // copy only when significant digits are within the precision
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+                }
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+            } else {
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
+            }
+        } else {
+            if (nDigits > 1) {
+                mantissa = create(isNegative, nDigits + 1);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
+            } else {
+                mantissa = create(isNegative, 3);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                mantissa[startIndex + 2] = '0';
+            }
+            int e, expStartIntex;
+            boolean isNegExp = (exp <= 0);
+            if (isNegExp) {
+                e = -exp + 1;
+                expStartIntex = 1;
+            } else {
+                e = exp - 1;
+                expStartIntex = 0;
+            }
+            // decExponent has 1, 2, or 3, digits
+            if (e <= 9) {
+                exponent = create(isNegExp,1);
+                exponent[expStartIntex] = (char) (e + '0');
+            } else if (e <= 99) {
+                exponent = create(isNegExp,2);
+                exponent[expStartIntex] = (char) (e / 10 + '0');
+                exponent[expStartIntex+1] = (char) (e % 10 + '0');
+            } else {
+                exponent = create(isNegExp,3);
+                exponent[expStartIntex] = (char) (e / 100 + '0');
+                e %= 100;
+                exponent[expStartIntex+1] = (char) (e / 10 + '0');
+                exponent[expStartIntex+2] = (char) (e % 10 + '0');
+            }
+        }
+    }
+
+    private static char[] create(boolean isNegative, int size) {
+        if(isNegative) {
+            char[] r = new char[size +1];
+            r[0] = '-';
+            return r;
+        } else {
+            return new char[size];
+        }
+    }
+
+    /*
+     * Fills mantissa char arrays for DECIMAL_FLOAT format.
+     * Exponent should be equal to null.
+     */
+    private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                mantissa = create(isNegative,exp);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+            } else {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+                if (t > 0) {
+                    mantissa[startIndex + exp] = '.';
+                    System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
+                }
+            }
+        } else if (exp <= 0) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+                if (t > 0) {
+                    // copy only when significant digits are within the precision
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+                }
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+            } else {
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
+            }
+        }
+    }
+
+    /**
+     * Fills mantissa and exponent char arrays for SCIENTIFIC format.
+     */
+    private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        int t = Math.max(0, Math.min(nDigits - 1, precision));
+        if (t > 0) {
+            mantissa = create(isNegative, t + 2);
+            mantissa[startIndex] = digits[0];
+            mantissa[startIndex + 1] = '.';
+            System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
+        } else {
+            mantissa = create(isNegative, 1);
+            mantissa[startIndex] = digits[0];
+        }
+        char expSign;
+        int e;
+        if (exp <= 0) {
+            expSign = '-';
+            e = -exp + 1;
+        } else {
+            expSign = '+' ;
+            e = exp - 1;
+        }
+        // decExponent has 1, 2, or 3, digits
+        if (e <= 9) {
+            exponent = new char[] { expSign,
+                    '0', (char) (e + '0') };
+        } else if (e <= 99) {
+            exponent = new char[] { expSign,
+                    (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+        } else {
+            char hiExpChar = (char) (e / 100 + '0');
+            e %= 100;
+            exponent = new char[] { expSign,
+                    hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+        }
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/misc/InnocuousThread.java b/ojluni/src/main/java/jdk/internal/misc/InnocuousThread.java
new file mode 100644
index 0000000..e62a032
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/misc/InnocuousThread.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.ProtectionDomain;
+import java.security.PrivilegedAction;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A thread that has no permissions, is not a member of any user-defined
+ * ThreadGroup and supports the ability to erase ThreadLocals.
+ */
+public final class InnocuousThread extends Thread {
+    private static final jdk.internal.misc.Unsafe UNSAFE;
+    private static final long THREAD_LOCALS;
+    private static final long INHERITABLE_THREAD_LOCALS;
+    private static final ThreadGroup INNOCUOUSTHREADGROUP;
+    private static final AccessControlContext ACC;
+    private static final long INHERITEDACCESSCONTROLCONTEXT;
+    private static final long CONTEXTCLASSLOADER;
+
+    private static final AtomicInteger threadNumber = new AtomicInteger(1);
+    private static String newName() {
+        return "InnocuousThread-" + threadNumber.getAndIncrement();
+    }
+
+    /**
+     * Returns a new InnocuousThread with an auto-generated thread name
+     * and its context class loader is set to the system class loader.
+     */
+    public static Thread newThread(Runnable target) {
+        return newThread(newName(), target);
+    }
+
+    /**
+     * Returns a new InnocuousThread with its context class loader
+     * set to the system class loader.
+     */
+    public static Thread newThread(String name, Runnable target) {
+        return AccessController.doPrivileged(
+                new PrivilegedAction<Thread>() {
+                    @Override
+                    public Thread run() {
+                        return new InnocuousThread(INNOCUOUSTHREADGROUP,
+                                                   target,
+                                                   name,
+                                                   ClassLoader.getSystemClassLoader());
+                    }
+                });
+    }
+
+    /**
+     * Returns a new InnocuousThread with an auto-generated thread name.
+     * Its context class loader is set to null.
+     */
+    public static Thread newSystemThread(Runnable target) {
+        return newSystemThread(newName(), target);
+    }
+
+    /**
+     * Returns a new InnocuousThread with null context class loader.
+     */
+    public static Thread newSystemThread(String name, Runnable target) {
+        return AccessController.doPrivileged(
+                new PrivilegedAction<Thread>() {
+                    @Override
+                    public Thread run() {
+                        return new InnocuousThread(INNOCUOUSTHREADGROUP,
+                                                   target, name, null);
+                    }
+                });
+    }
+
+    private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {
+        super(group, target, name, 0L, false);
+        UNSAFE.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
+        UNSAFE.putObjectRelease(this, CONTEXTCLASSLOADER, tccl);
+    }
+
+    @Override
+    public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) {
+        // silently fail
+    }
+
+    @Override
+    public void setContextClassLoader(ClassLoader cl) {
+        // Allow clearing of the TCCL to remove the reference to the system classloader.
+        if (cl == null)
+            super.setContextClassLoader(null);
+        else
+            throw new SecurityException("setContextClassLoader");
+    }
+
+    /**
+     * Drops all thread locals (and inherited thread locals).
+     */
+    public final void eraseThreadLocals() {
+        UNSAFE.putObject(this, THREAD_LOCALS, null);
+        UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
+    }
+
+    // ensure run method is run only once
+    private volatile boolean hasRun;
+
+    @Override
+    public void run() {
+        if (Thread.currentThread() == this && !hasRun) {
+            hasRun = true;
+            super.run();
+        }
+    }
+
+    // Use Unsafe to access Thread group and ThreadGroup parent fields
+    static {
+        try {
+            ACC = new AccessControlContext(new ProtectionDomain[] {
+                new ProtectionDomain(null, null)
+            });
+
+            // Find and use topmost ThreadGroup as parent of new group
+            UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
+            Class<?> tk = Thread.class;
+            Class<?> gk = ThreadGroup.class;
+
+            THREAD_LOCALS = UNSAFE.objectFieldOffset(tk, "threadLocals");
+            INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
+                    (tk, "inheritableThreadLocals");
+            INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
+                (tk, "inheritedAccessControlContext");
+            CONTEXTCLASSLOADER = UNSAFE.objectFieldOffset
+                (tk, "contextClassLoader");
+
+            long tg = UNSAFE.objectFieldOffset(tk, "group");
+            long gp = UNSAFE.objectFieldOffset(gk, "parent");
+            ThreadGroup group = (ThreadGroup)
+                UNSAFE.getObject(Thread.currentThread(), tg);
+
+            while (group != null) {
+                ThreadGroup parent = (ThreadGroup)UNSAFE.getObject(group, gp);
+                if (parent == null)
+                    break;
+                group = parent;
+            }
+            final ThreadGroup root = group;
+            INNOCUOUSTHREADGROUP = AccessController.doPrivileged(
+                new PrivilegedAction<ThreadGroup>() {
+                    @Override
+                    public ThreadGroup run() {
+                        return new ThreadGroup(root, "InnocuousThreadGroup");
+                    }
+                });
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/misc/JavaIOFileDescriptorAccess.java b/ojluni/src/main/java/jdk/internal/misc/JavaIOFileDescriptorAccess.java
new file mode 100644
index 0000000..3fe3114
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/misc/JavaIOFileDescriptorAccess.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.misc;
+
+import java.io.FileDescriptor;
+
+/*
+ * @author Chris Hegarty
+ */
+
+public interface JavaIOFileDescriptorAccess {
+    public void set(FileDescriptor obj, int fd);
+    public int get(FileDescriptor fd);
+
+    // Only valid on Windows
+    public void setHandle(FileDescriptor obj, long handle);
+    public long getHandle(FileDescriptor obj);
+}
diff --git a/ojluni/src/main/java/jdk/internal/misc/JavaObjectInputStreamAccess.java b/ojluni/src/main/java/jdk/internal/misc/JavaObjectInputStreamAccess.java
new file mode 100644
index 0000000..4c73467
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/misc/JavaObjectInputStreamAccess.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.io.InvalidClassException;
+import java.io.ObjectInputStream;
+
+/**
+ * Interface to specify methods for accessing {@code ObjectInputStream}.
+ */
+@FunctionalInterface
+public interface JavaObjectInputStreamAccess {
+    void checkArray(ObjectInputStream ois, Class<?> arrayType, int arrayLength)
+        throws InvalidClassException;
+}
diff --git a/ojluni/src/main/java/jdk/internal/misc/SharedSecrets.java b/ojluni/src/main/java/jdk/internal/misc/SharedSecrets.java
new file mode 100644
index 0000000..aa2255b
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/misc/SharedSecrets.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.io.ObjectInputStream;
+
+/** A repository of "shared secrets", which are a mechanism for
+    calling implementation-private methods in another package without
+    using reflection. A package-private class implements a public
+    interface and provides the ability to call package-private methods
+    within that package; the object implementing that interface is
+    provided through a third package to which access is restricted.
+    This framework avoids the primary disadvantage of using reflection
+    for this purpose, namely the loss of compile-time checking. */
+
+public class SharedSecrets {
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    // BEGIN Android-removed: Pruned unused access interfaces.
+    /*
+    private static JavaUtilJarAccess javaUtilJarAccess;
+    private static JavaLangAccess javaLangAccess;
+    private static JavaLangRefAccess javaLangRefAccess;
+    private static JavaIOAccess javaIOAccess;
+    private static JavaNetAccess javaNetAccess;
+    private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
+    private static JavaNioAccess javaNioAccess;
+    */
+    // END Android-removed: Pruned unused access interfaces.
+    private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
+    // BEGIN Android-removed: Pruned unused access interfaces.
+    /*
+    private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
+    private static JavaSecurityAccess javaSecurityAccess;
+    private static JavaUtilZipFileAccess javaUtilZipFileAccess;
+    private static JavaAWTAccess javaAWTAccess;
+    private static JavaOISAccess javaOISAccess;
+    private static JavaObjectInputStreamReadString javaObjectInputStreamReadString;
+    */
+    // END Android-removed: Pruned unused access interfaces.
+    private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
+    // BEGIN Android-removed: Pruned unused access interfaces.
+    /*
+    private static JavaSecuritySignatureAccess javaSecuritySignatureAccess;
+
+    public static JavaUtilJarAccess javaUtilJarAccess() {
+        if (javaUtilJarAccess == null) {
+            // Ensure JarFile is initialized; we know that that class
+            // provides the shared secret
+            unsafe.ensureClassInitialized(JarFile.class);
+        }
+        return javaUtilJarAccess;
+    }
+
+    public static void setJavaUtilJarAccess(JavaUtilJarAccess access) {
+        javaUtilJarAccess = access;
+    }
+
+    public static void setJavaLangAccess(JavaLangAccess jla) {
+        javaLangAccess = jla;
+    }
+
+    public static JavaLangAccess getJavaLangAccess() {
+        return javaLangAccess;
+    }
+
+    public static void setJavaLangRefAccess(JavaLangRefAccess jlra) {
+        javaLangRefAccess = jlra;
+    }
+
+    public static JavaLangRefAccess getJavaLangRefAccess() {
+        return javaLangRefAccess;
+    }
+
+    public static void setJavaNetAccess(JavaNetAccess jna) {
+        javaNetAccess = jna;
+    }
+
+    public static JavaNetAccess getJavaNetAccess() {
+        return javaNetAccess;
+    }
+
+    public static void setJavaNetHttpCookieAccess(JavaNetHttpCookieAccess a) {
+        javaNetHttpCookieAccess = a;
+    }
+
+    public static JavaNetHttpCookieAccess getJavaNetHttpCookieAccess() {
+        if (javaNetHttpCookieAccess == null)
+            unsafe.ensureClassInitialized(java.net.HttpCookie.class);
+        return javaNetHttpCookieAccess;
+    }
+
+    public static void setJavaNioAccess(JavaNioAccess jna) {
+        javaNioAccess = jna;
+    }
+
+    public static JavaNioAccess getJavaNioAccess() {
+        if (javaNioAccess == null) {
+            // Ensure java.nio.ByteOrder is initialized; we know that
+            // this class initializes java.nio.Bits that provides the
+            // shared secret.
+            unsafe.ensureClassInitialized(java.nio.ByteOrder.class);
+        }
+        return javaNioAccess;
+    }
+
+    public static void setJavaIOAccess(JavaIOAccess jia) {
+        javaIOAccess = jia;
+    }
+
+    public static JavaIOAccess getJavaIOAccess() {
+        if (javaIOAccess == null) {
+            unsafe.ensureClassInitialized(Console.class);
+        }
+        return javaIOAccess;
+    }
+    */
+    // END Android-removed: Pruned unused access interfaces.
+
+    public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) {
+        javaIOFileDescriptorAccess = jiofda;
+    }
+
+    public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() {
+        // Android-changed: ensureClassInitialized isn't supported in Android. Use Class.forName.
+        // if (javaIOFileDescriptorAccess == null)
+        //     unsafe.ensureClassInitialized(FileDescriptor.class);
+        if (javaIOFileDescriptorAccess == null) {
+            try {
+                Class.forName("java.io.FileDescriptor");
+            } catch (ClassNotFoundException e) {
+                // Throw if FileDescriptor class is not found. Something wrong in runtime / libcore.
+                throw new RuntimeException(e);
+            }
+        }
+        return javaIOFileDescriptorAccess;
+    }
+
+    // BEGIN Android-removed: Pruned unused access interfaces.
+    /*
+    public static void setJavaOISAccess(JavaOISAccess access) {
+        javaOISAccess = access;
+    }
+
+    public static JavaOISAccess getJavaOISAccess() {
+        if (javaOISAccess == null)
+            unsafe.ensureClassInitialized(ObjectInputStream.class);
+
+        return javaOISAccess;
+    }
+
+
+    public static void setJavaSecurityProtectionDomainAccess
+        (JavaSecurityProtectionDomainAccess jspda) {
+            javaSecurityProtectionDomainAccess = jspda;
+    }
+
+    public static JavaSecurityProtectionDomainAccess
+        getJavaSecurityProtectionDomainAccess() {
+            if (javaSecurityProtectionDomainAccess == null)
+                unsafe.ensureClassInitialized(ProtectionDomain.class);
+            return javaSecurityProtectionDomainAccess;
+    }
+
+    public static void setJavaSecurityAccess(JavaSecurityAccess jsa) {
+        javaSecurityAccess = jsa;
+    }
+
+    public static JavaSecurityAccess getJavaSecurityAccess() {
+        if (javaSecurityAccess == null) {
+            unsafe.ensureClassInitialized(AccessController.class);
+        }
+        return javaSecurityAccess;
+    }
+
+    public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
+        if (javaUtilZipFileAccess == null)
+            unsafe.ensureClassInitialized(java.util.zip.ZipFile.class);
+        return javaUtilZipFileAccess;
+    }
+
+    public static void setJavaUtilZipFileAccess(JavaUtilZipFileAccess access) {
+        javaUtilZipFileAccess = access;
+    }
+
+    public static void setJavaAWTAccess(JavaAWTAccess jaa) {
+        javaAWTAccess = jaa;
+    }
+
+    public static JavaAWTAccess getJavaAWTAccess() {
+        // this may return null in which case calling code needs to
+        // provision for.
+        if (javaAWTAccess == null) {
+            return null;
+        }
+        return javaAWTAccess;
+    }
+
+    public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
+        if (javaObjectInputStreamReadString == null) {
+            unsafe.ensureClassInitialized(ObjectInputStream.class);
+        }
+        return javaObjectInputStreamReadString;
+    }
+
+    public static void setJavaObjectInputStreamReadString(JavaObjectInputStreamReadString access) {
+        javaObjectInputStreamReadString = access;
+    }
+    */
+    // END Android-removed: Pruned unused access interfaces.
+
+    public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
+        if (javaObjectInputStreamAccess == null) {
+            unsafe.ensureClassInitialized(ObjectInputStream.class);
+        }
+        return javaObjectInputStreamAccess;
+    }
+
+    public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) {
+        javaObjectInputStreamAccess = access;
+    }
+
+    // BEGIN Android-removed: Pruned unused access interfaces.
+    /*
+    public static void setJavaSecuritySignatureAccess(JavaSecuritySignatureAccess jssa) {
+        javaSecuritySignatureAccess = jssa;
+    }
+
+    public static JavaSecuritySignatureAccess getJavaSecuritySignatureAccess() {
+        if (javaSecuritySignatureAccess == null) {
+            unsafe.ensureClassInitialized(Signature.class);
+        }
+        return javaSecuritySignatureAccess;
+    }
+    */
+    // END Android-removed: Pruned unused access interfaces.
+}
diff --git a/ojluni/src/main/java/jdk/internal/misc/Unsafe.java b/ojluni/src/main/java/jdk/internal/misc/Unsafe.java
new file mode 100644
index 0000000..320cb27
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/misc/Unsafe.java
@@ -0,0 +1,1352 @@
+/*
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import dalvik.annotation.optimization.FastNative;
+import jdk.internal.HotSpotIntrinsicCandidate;
+import sun.reflect.Reflection;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * A collection of methods for performing low-level, unsafe operations.
+ * Although the class and all methods are public, use of this class is
+ * limited because only trusted code can obtain instances of it.
+ *
+ * @author John R. Rose
+ * @see #getUnsafe
+ */
+public final class Unsafe {
+    /** Traditional dalvik name. */
+    private static final Unsafe THE_ONE = new Unsafe();
+
+    private static final Unsafe theUnsafe = THE_ONE;
+    public static final int INVALID_FIELD_OFFSET   = -1;
+
+    /**
+     * This class is only privately instantiable.
+     */
+    private Unsafe() {}
+
+    /**
+     * Gets the unique instance of this class. This is only allowed in
+     * very limited situations.
+     */
+    public static Unsafe getUnsafe() {
+        Class<?> caller = Reflection.getCallerClass();
+        /*
+         * Only code on the bootclasspath is allowed to get at the
+         * Unsafe instance.
+         */
+        ClassLoader calling = (caller == null) ? null : caller.getClassLoader();
+        if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
+            throw new SecurityException("Unsafe access denied");
+        }
+
+        return THE_ONE;
+    }
+
+    /**
+     * Gets the raw byte offset from the start of an object's memory to
+     * the memory used to store the indicated instance field.
+     *
+     * @param field non-{@code null}; the field in question, which must be an
+     * instance field
+     * @return the offset to the field
+     */
+    public long objectFieldOffset(Field field) {
+        if (Modifier.isStatic(field.getModifiers())) {
+            throw new IllegalArgumentException("valid for instance fields only");
+        }
+        return field.getOffset();
+    }
+
+    /**
+     * Reports the location of the field with a given name in the storage
+     * allocation of its class.
+     *
+     * @throws NullPointerException if any parameter is {@code null}.
+     * @throws InternalError if there is no field named {@code name} declared
+     *         in class {@code c}, i.e., if {@code c.getDeclaredField(name)}
+     *         would throw {@code java.lang.NoSuchFieldException}.
+     *
+     * @see #objectFieldOffset(Field)
+     */
+    public long objectFieldOffset(Class<?> c, String name) {
+        if (c == null || name == null) {
+            throw new NullPointerException();
+        }
+
+        Field field = null;
+        Field[] fields = c.getDeclaredFields();
+        for (Field f : fields) {
+            if (f.getName().equals(name)) {
+                field = f;
+                break;
+            }
+        }
+        if (field == null) {
+            throw new InternalError();
+        }
+        return objectFieldOffset(field);
+    }
+
+    /**
+     * Gets the offset from the start of an array object's memory to
+     * the memory used to store its initial (zeroeth) element.
+     *
+     * @param clazz non-{@code null}; class in question; must be an array class
+     * @return the offset to the initial element
+     */
+    public int arrayBaseOffset(Class clazz) {
+        Class<?> component = clazz.getComponentType();
+        if (component == null) {
+            throw new IllegalArgumentException("Valid for array classes only: " + clazz);
+        }
+        return getArrayBaseOffsetForComponentType(component);
+    }
+
+    /** The value of {@code arrayBaseOffset(boolean[].class)} */
+    public static final int ARRAY_BOOLEAN_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(boolean[].class);
+
+    /** The value of {@code arrayBaseOffset(byte[].class)} */
+    public static final int ARRAY_BYTE_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(byte[].class);
+
+    /** The value of {@code arrayBaseOffset(short[].class)} */
+    public static final int ARRAY_SHORT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(short[].class);
+
+    /** The value of {@code arrayBaseOffset(char[].class)} */
+    public static final int ARRAY_CHAR_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(char[].class);
+
+    /** The value of {@code arrayBaseOffset(int[].class)} */
+    public static final int ARRAY_INT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(int[].class);
+
+    /** The value of {@code arrayBaseOffset(long[].class)} */
+    public static final int ARRAY_LONG_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(long[].class);
+
+    /** The value of {@code arrayBaseOffset(float[].class)} */
+    public static final int ARRAY_FLOAT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(float[].class);
+
+    /** The value of {@code arrayBaseOffset(double[].class)} */
+    public static final int ARRAY_DOUBLE_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(double[].class);
+
+    /** The value of {@code arrayBaseOffset(Object[].class)} */
+    public static final int ARRAY_OBJECT_BASE_OFFSET
+            = theUnsafe.arrayBaseOffset(Object[].class);
+
+    /**
+     * Gets the size of each element of the given array class.
+     *
+     * @param clazz non-{@code null}; class in question; must be an array class
+     * @return &gt; 0; the size of each element of the array
+     */
+    public int arrayIndexScale(Class clazz) {
+      Class<?> component = clazz.getComponentType();
+      if (component == null) {
+          throw new IllegalArgumentException("Valid for array classes only: " + clazz);
+      }
+      return getArrayIndexScaleForComponentType(component);
+    }
+
+    /** The value of {@code arrayIndexScale(boolean[].class)} */
+    public static final int ARRAY_BOOLEAN_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(boolean[].class);
+
+    /** The value of {@code arrayIndexScale(byte[].class)} */
+    public static final int ARRAY_BYTE_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(byte[].class);
+
+    /** The value of {@code arrayIndexScale(short[].class)} */
+    public static final int ARRAY_SHORT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(short[].class);
+
+    /** The value of {@code arrayIndexScale(char[].class)} */
+    public static final int ARRAY_CHAR_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(char[].class);
+
+    /** The value of {@code arrayIndexScale(int[].class)} */
+    public static final int ARRAY_INT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(int[].class);
+
+    /** The value of {@code arrayIndexScale(long[].class)} */
+    public static final int ARRAY_LONG_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(long[].class);
+
+    /** The value of {@code arrayIndexScale(float[].class)} */
+    public static final int ARRAY_FLOAT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(float[].class);
+
+    /** The value of {@code arrayIndexScale(double[].class)} */
+    public static final int ARRAY_DOUBLE_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(double[].class);
+
+    /** The value of {@code arrayIndexScale(Object[].class)} */
+    public static final int ARRAY_OBJECT_INDEX_SCALE
+            = theUnsafe.arrayIndexScale(Object[].class);
+
+    /** The value of {@code addressSize()} */
+    public static final int ADDRESS_SIZE = theUnsafe.addressSize();
+
+    @FastNative
+    private static native int getArrayBaseOffsetForComponentType(Class component_class);
+    @FastNative
+    private static native int getArrayIndexScaleForComponentType(Class component_class);
+
+    /**
+     * Fetches a value at some byte offset into a given Java object.
+     * More specifically, fetches a value within the given object
+     * <code>o</code> at the given offset, or (if <code>o</code> is
+     * null) from the memory address whose numerical value is the
+     * given offset.  <p>
+     *
+     * The specification of this method is the same as {@link
+     * #getLong(Object, long)} except that the offset does not need to
+     * have been obtained from {@link #objectFieldOffset} on the
+     * {@link java.lang.reflect.Field} of some Java field.  The value
+     * in memory is raw data, and need not correspond to any Java
+     * variable.  Unless <code>o</code> is null, the value accessed
+     * must be entirely within the allocated object.  The endianness
+     * of the value in memory is the endianness of the native platform.
+     *
+     * <p> The read will be atomic with respect to the largest power
+     * of two that divides the GCD of the offset and the storage size.
+     * For example, getLongUnaligned will make atomic reads of 2-, 4-,
+     * or 8-byte storage units if the offset is zero mod 2, 4, or 8,
+     * respectively.  There are no other guarantees of atomicity.
+     * <p>
+     * 8-byte atomicity is only guaranteed on platforms on which
+     * support atomic accesses to longs.
+     *
+     * @param o Java heap object in which the value resides, if any, else
+     *        null
+     * @param offset The offset in bytes from the start of the object
+     * @return the value fetched from the indicated object
+     * @throws RuntimeException No defined exceptions are thrown, not even
+     *         {@link NullPointerException}
+     * @since 9
+     */
+    public final long getLongUnaligned(Object o, long offset) {
+        if ((offset & 7) == 0) {
+            return getLong(o, offset);
+        } else if ((offset & 3) == 0) {
+            return makeLong(getInt(o, offset),
+                    getInt(o, offset + 4));
+        } else if ((offset & 1) == 0) {
+            return makeLong(getShort(o, offset),
+                    getShort(o, offset + 2),
+                    getShort(o, offset + 4),
+                    getShort(o, offset + 6));
+        } else {
+            return makeLong(getByte(o, offset),
+                    getByte(o, offset + 1),
+                    getByte(o, offset + 2),
+                    getByte(o, offset + 3),
+                    getByte(o, offset + 4),
+                    getByte(o, offset + 5),
+                    getByte(o, offset + 6),
+                    getByte(o, offset + 7));
+        }
+    }
+
+    /** @see #getLongUnaligned(Object, long) */
+    public final int getIntUnaligned(Object o, long offset) {
+        if ((offset & 3) == 0) {
+            return getInt(o, offset);
+        } else if ((offset & 1) == 0) {
+            return makeInt(getShort(o, offset),
+                    getShort(o, offset + 2));
+        } else {
+            return makeInt(getByte(o, offset),
+                    getByte(o, offset + 1),
+                    getByte(o, offset + 2),
+                    getByte(o, offset + 3));
+        }
+    }
+
+    // These methods construct integers from bytes.  The byte ordering
+    // is the native endianness of this platform.
+    private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) {
+        return ((toUnsignedLong(i0))
+                | (toUnsignedLong(i1) << 8)
+                | (toUnsignedLong(i2) << 16)
+                | (toUnsignedLong(i3) << 24)
+                | (toUnsignedLong(i4) << 32)
+                | (toUnsignedLong(i5) << 40)
+                | (toUnsignedLong(i6) << 48)
+                | (toUnsignedLong(i7) << 56));
+    }
+    private static long makeLong(short i0, short i1, short i2, short i3) {
+        return ((toUnsignedLong(i0))
+                | (toUnsignedLong(i1) << 16)
+                | (toUnsignedLong(i2) << 32)
+                | (toUnsignedLong(i3) << 48));
+    }
+    private static long makeLong(int i0, int i1) {
+        return (toUnsignedLong(i0))
+                | (toUnsignedLong(i1) << 32);
+    }
+    private static int makeInt(short i0, short i1) {
+        return (toUnsignedInt(i0))
+                | (toUnsignedInt(i1) << 16);
+    }
+    private static int makeInt(byte i0, byte i1, byte i2, byte i3) {
+        return ((toUnsignedInt(i0))
+                | (toUnsignedInt(i1) << 8)
+                | (toUnsignedInt(i2) << 16)
+                | (toUnsignedInt(i3) << 24));
+    }
+    private static short makeShort(byte i0, byte i1) {
+        return (short)((toUnsignedInt(i0))
+                | (toUnsignedInt(i1) << 8));
+    }
+
+    // Zero-extend an integer
+    private static int toUnsignedInt(byte n)    { return n & 0xff; }
+    private static int toUnsignedInt(short n)   { return n & 0xffff; }
+    private static long toUnsignedLong(byte n)  { return n & 0xffL; }
+    private static long toUnsignedLong(short n) { return n & 0xffffL; }
+    private static long toUnsignedLong(int n)   { return n & 0xffffffffL; }
+
+    /**
+     * Performs a compare-and-set operation on an {@code int}
+     * field within the given object.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param expectedValue expected value of the field
+     * @param newValue new value to store in the field if the contents are
+     * as expected
+     * @return {@code true} if the new value was in fact stored, and
+     * {@code false} if not
+     */
+    @FastNative
+    public native boolean compareAndSwapInt(Object obj, long offset,
+            int expectedValue, int newValue);
+
+    /**
+     * Performs a compare-and-set operation on a {@code long}
+     * field within the given object.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param expectedValue expected value of the field
+     * @param newValue new value to store in the field if the contents are
+     * as expected
+     * @return {@code true} if the new value was in fact stored, and
+     * {@code false} if not
+     */
+    @FastNative
+    public native boolean compareAndSwapLong(Object obj, long offset,
+            long expectedValue, long newValue);
+
+    /**
+     * Performs a compare-and-set operation on an {@code obj}
+     * field (that is, a reference field) within the given object.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param expectedValue expected value of the field
+     * @param newValue new value to store in the field if the contents are
+     * as expected
+     * @return {@code true} if the new value was in fact stored, and
+     * {@code false} if not
+     */
+    @FastNative
+    public native boolean compareAndSwapObject(Object obj, long offset,
+            Object expectedValue, Object newValue);
+
+    /**
+     * Gets an {@code int} field from the given object,
+     * using {@code volatile} semantics.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native int getIntVolatile(Object obj, long offset);
+
+    /**
+     * Stores an {@code int} field into the given object,
+     * using {@code volatile} semantics.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putIntVolatile(Object obj, long offset, int newValue);
+
+    /**
+     * Gets a {@code long} field from the given object,
+     * using {@code volatile} semantics.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native long getLongVolatile(Object obj, long offset);
+
+    /**
+     * Stores a {@code long} field into the given object,
+     * using {@code volatile} semantics.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putLongVolatile(Object obj, long offset, long newValue);
+
+    /**
+     * Gets an {@code obj} field from the given object,
+     * using {@code volatile} semantics.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native Object getObjectVolatile(Object obj, long offset);
+
+    /**
+     * Stores an {@code obj} field into the given object,
+     * using {@code volatile} semantics.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putObjectVolatile(Object obj, long offset,
+            Object newValue);
+
+    /**
+     * Gets an {@code int} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing int field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native int getInt(Object obj, long offset);
+
+    /**
+     * Stores an {@code int} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing int field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putInt(Object obj, long offset, int newValue);
+
+    /**
+     * Lazy set an int field.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putOrderedInt(Object obj, long offset, int newValue);
+
+    /**
+     * Gets a {@code long} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native long getLong(Object obj, long offset);
+
+    /**
+     * Stores a {@code long} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putLong(Object obj, long offset, long newValue);
+
+    /**
+     * Lazy set a long field.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putOrderedLong(Object obj, long offset, long newValue);
+
+    /**
+     * Gets an {@code obj} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native Object getObject(Object obj, long offset);
+
+    /**
+     * Stores an {@code obj} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putObject(Object obj, long offset, Object newValue);
+
+    /**
+     * Lazy set an object field.
+     *
+     * @param obj non-{@code null}; object containing the field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putOrderedObject(Object obj, long offset,
+            Object newValue);
+
+    /**
+     * Gets a {@code boolean} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing boolean field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native boolean getBoolean(Object obj, long offset);
+
+    /**
+     * Stores a {@code boolean} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing boolean field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putBoolean(Object obj, long offset, boolean newValue);
+
+    /**
+     * Gets a {@code byte} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing byte field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native byte getByte(Object obj, long offset);
+
+    /**
+     * Stores a {@code byte} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing byte field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putByte(Object obj, long offset, byte newValue);
+
+    /**
+     * Gets a {@code char} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing char field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native char getChar(Object obj, long offset);
+
+    /**
+     * Stores a {@code char} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing char field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putChar(Object obj, long offset, char newValue);
+
+    /**
+     * Gets a {@code short} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing short field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native short getShort(Object obj, long offset);
+
+    /**
+     * Stores a {@code short} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing short field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putShort(Object obj, long offset, short newValue);
+
+    /**
+     * Gets a {@code float} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing float field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native float getFloat(Object obj, long offset);
+
+    /**
+     * Stores a {@code float} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing float field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putFloat(Object obj, long offset, float newValue);
+
+    /**
+     * Gets a {@code double} field from the given object.
+     *
+     * @param obj non-{@code null}; object containing double field
+     * @param offset offset to the field within {@code obj}
+     * @return the retrieved value
+     */
+    @FastNative
+    public native double getDouble(Object obj, long offset);
+
+    /**
+     * Stores a {@code double} field into the given object.
+     *
+     * @param obj non-{@code null}; object containing double field
+     * @param offset offset to the field within {@code obj}
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putDouble(Object obj, long offset, double newValue);
+
+    /**
+     * Parks the calling thread for the specified amount of time,
+     * unless the "permit" for the thread is already available (due to
+     * a previous call to {@link #unpark}. This method may also return
+     * spuriously (that is, without the thread being told to unpark
+     * and without the indicated amount of time elapsing).
+     *
+     * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+     * in-depth information of the behavior of this method.</p>
+     *
+     * @param absolute whether the given time value is absolute
+     * milliseconds-since-the-epoch ({@code true}) or relative
+     * nanoseconds-from-now ({@code false})
+     * @param time the (absolute millis or relative nanos) time value
+     */
+
+    public native void park(boolean absolute, long time);
+    /**
+     * Unparks the given object, which must be a {@link Thread}.
+     *
+     * <p>See {@link java.util.concurrent.locks.LockSupport} for more
+     * in-depth information of the behavior of this method.</p>
+     *
+     * @param obj non-{@code null}; the object to unpark
+     */
+    @FastNative
+    public native void unpark(Object obj);
+
+    /**
+     * Allocates an instance of the given class without running the constructor.
+     * The class' <clinit> will be run, if necessary.
+     */
+    public native Object allocateInstance(Class<?> c);
+
+    /**
+     * Gets the size of the address value, in bytes.
+     *
+     * @return the size of the address, in bytes
+     */
+    @FastNative
+    public native int addressSize();
+
+    /**
+     * Gets the size of the memory page, in bytes.
+     *
+     * @return the size of the page
+     */
+    @FastNative
+    public native int pageSize();
+
+    /**
+     * Allocates a memory block of size {@code bytes}.
+     *
+     * @param bytes size of the memory block
+     * @return address of the allocated memory
+     */
+    @FastNative
+    public native long allocateMemory(long bytes);
+
+    /**
+     * Frees previously allocated memory at given address.
+     *
+     * @param address address of the freed memory
+     */
+    @FastNative
+    public native void freeMemory(long address);
+
+    /**
+     * Fills given memory block with a given value.
+     *
+     * @param address address of the memoory block
+     * @param bytes length of the memory block, in bytes
+     * @param value fills memory with this value
+     */
+    @FastNative
+    public native void setMemory(long address, long bytes, byte value);
+
+    /**
+     * Gets {@code byte} from given address in memory.
+     *
+     * @param address address in memory
+     * @return {@code byte} value
+     */
+    @FastNative
+    public native byte getByte(long address);
+
+    /**
+     * Stores a {@code byte} into the given memory address.
+     *
+     * @param address address in memory where to store the value
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putByte(long address, byte x);
+
+    /**
+     * Gets {@code short} from given address in memory.
+     *
+     * @param address address in memory
+     * @return {@code short} value
+     */
+    @FastNative
+    public native short getShort(long address);
+
+    /**
+     * Stores a {@code short} into the given memory address.
+     *
+     * @param address address in memory where to store the value
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putShort(long address, short x);
+
+    /**
+     * Gets {@code char} from given address in memory.
+     *
+     * @param address address in memory
+     * @return {@code char} value
+     */
+    @FastNative
+    public native char getChar(long address);
+
+    /**
+     * Stores a {@code char} into the given memory address.
+     *
+     * @param address address in memory where to store the value
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putChar(long address, char x);
+
+    /**
+     * Gets {@code int} from given address in memory.
+     *
+     * @param address address in memory
+     * @return {@code int} value
+     */
+    @FastNative
+    public native int getInt(long address);
+
+    /**
+     * Stores a {@code int} into the given memory address.
+     *
+     * @param address address in memory where to store the value
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putInt(long address, int x);
+
+
+    /**
+     * Gets {@code long} from given address in memory.
+     *
+     * @param address address in memory
+     * @return {@code long} value
+     */
+    @FastNative
+    public native long getLong(long address);
+
+    /**
+     * Stores a {@code long} into the given memory address.
+     *
+     * @param address address in memory where to store the value
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putLong(long address, long x);
+
+    /**
+     * Gets {@code long} from given address in memory.
+     *
+     * @param address address in memory
+     * @return {@code long} value
+     */
+    @FastNative
+    public native float getFloat(long address);
+
+    /**
+     * Stores a {@code float} into the given memory address.
+     *
+     * @param address address in memory where to store the value
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putFloat(long address, float x);
+
+    /**
+     * Gets {@code double} from given address in memory.
+     *
+     * @param address address in memory
+     * @return {@code double} value
+     */
+    @FastNative
+    public native double getDouble(long address);
+
+    /**
+     * Stores a {@code double} into the given memory address.
+     *
+     * @param address address in memory where to store the value
+     * @param newValue the value to store
+     */
+    @FastNative
+    public native void putDouble(long address, double x);
+
+    /**
+     * Sets all bytes in a given block of memory to a copy of another
+     * block.
+     *
+     * This method is to be used to copy memory between array objects. The
+     * offsets used should be relative to the value reported by {@link
+     * #arrayBaseOffset}. For example to copy all elements of an integer
+     * array to another:
+     *
+     * <pre> {@code
+     *   unsafe.copyMemory(srcArray, Unsafe.ARRAY_INT_BASE_OFFSET,
+     *                     destArray, Unsafe.ARRAY_INT_BASE_OFFSET,
+     *                     srcArray.length * 4);
+     * }</pre>
+     *
+     * @param srcBase The source array object from which to copy
+     * @param srcOffset The offset within the object from where to copy
+     * @param destBase The destination array object to which to copy
+     * @param destOffset The offset within the object to where to copy
+     * @param bytes The number of bytes to copy
+     *
+     * @throws RuntimeException if any of the arguments is invalid
+     */
+    public void copyMemory(Object srcBase, long srcOffset,
+                           Object destBase, long destOffset,
+                           long bytes) {
+        copyMemoryChecks(srcBase, srcOffset, destBase, destOffset, bytes);
+
+        if (bytes == 0) {
+            return;
+        }
+
+        copyMemory0(srcBase, srcOffset, destBase, destOffset, bytes);
+    }
+
+    /**
+     * Sets all bytes in a given block of memory to a copy of another block.
+     *
+     * @param srcAddr address of the source memory to be copied from
+     * @param dstAddr address of the destination memory to copy to
+     * @param bytes number of bytes to copy
+     */
+    public void copyMemory(long srcAddr, long dstAddr, long bytes) {
+        copyMemory(null, srcAddr, null, dstAddr, bytes);
+    }
+
+    /**
+     * Validate the arguments to copyMemory
+     *
+     * @throws RuntimeException if any of the arguments is invalid
+     *         (<em>Note:</em> after optimization, invalid inputs may
+     *         go undetected, which will lead to unpredictable
+     *         behavior)
+     */
+    private void copyMemoryChecks(Object srcBase, long srcOffset,
+                                  Object destBase, long destOffset,
+                                  long bytes) {
+        checkSize(bytes);
+        checkPrimitivePointer(srcBase, srcOffset);
+        checkPrimitivePointer(destBase, destOffset);
+    }
+
+    @HotSpotIntrinsicCandidate
+    @FastNative
+    private native void copyMemory0(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @HotSpotIntrinsicCandidate
+    @FastNative
+    public final native boolean compareAndSetInt(Object o, long offset,
+                                                 int expected,
+                                                 int x);
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @HotSpotIntrinsicCandidate
+    @FastNative
+    public final native boolean compareAndSetLong(Object o, long offset,
+                                                  long expected,
+                                                  long x);
+
+    /**
+     * Atomically updates Java variable to {@code x} if it is currently
+     * holding {@code expected}.
+     *
+     * <p>This operation has memory semantics of a {@code volatile} read
+     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
+     *
+     * @return {@code true} if successful
+     */
+    @HotSpotIntrinsicCandidate
+    @FastNative
+    public final native boolean compareAndSetObject(Object o, long offset,
+                                                    Object expected,
+                                                    Object x);
+
+    // The following contain CAS-based Java implementations used on
+    // platforms not supporting native instructions
+
+    /**
+     * Atomically adds the given value to the current value of a field
+     * or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param delta the value to add
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final int getAndAddInt(Object o, long offset, int delta) {
+        int v;
+        do {
+            v = getIntVolatile(o, offset);
+        } while (!compareAndSwapInt(o, offset, v, v + delta));
+        return v;
+    }
+
+    /**
+     * Atomically adds the given value to the current value of a field
+     * or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param delta the value to add
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final long getAndAddLong(Object o, long offset, long delta) {
+        long v;
+        do {
+            v = getLongVolatile(o, offset);
+        } while (!compareAndSwapLong(o, offset, v, v + delta));
+        return v;
+    }
+
+    /**
+     * Atomically exchanges the given value with the current value of
+     * a field or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final int getAndSetInt(Object o, long offset, int newValue) {
+        int v;
+        do {
+            v = getIntVolatile(o, offset);
+        } while (!compareAndSwapInt(o, offset, v, newValue));
+        return v;
+    }
+
+    /**
+     * Atomically exchanges the given value with the current value of
+     * a field or array element within the given object {@code o}
+     * at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final long getAndSetLong(Object o, long offset, long newValue) {
+        long v;
+        do {
+            v = getLongVolatile(o, offset);
+        } while (!compareAndSwapLong(o, offset, v, newValue));
+        return v;
+    }
+
+    /**
+     * Atomically exchanges the given reference value with the current
+     * reference value of a field or array element within the given
+     * object {@code o} at the given {@code offset}.
+     *
+     * @param o object/array to update the field/element in
+     * @param offset field/element offset
+     * @param newValue new value
+     * @return the previous value
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    public final Object getAndSetObject(Object o, long offset, Object newValue) {
+        Object v;
+        do {
+            v = getObjectVolatile(o, offset);
+        } while (!compareAndSwapObject(o, offset, v, newValue));
+        return v;
+    }
+
+    /** Release version of {@link #putIntVolatile(Object, long, int)} */
+    @HotSpotIntrinsicCandidate
+    public final void putIntRelease(Object o, long offset, int x) {
+        putIntVolatile(o, offset, x);
+    }
+
+    /** Acquire version of {@link #getIntVolatile(Object, long)} */
+    @HotSpotIntrinsicCandidate
+    public final int getIntAcquire(Object o, long offset) {
+        return getIntVolatile(o, offset);
+    }
+
+    /** Release version of {@link #putLongVolatile(Object, long, long)} */
+    @HotSpotIntrinsicCandidate
+    public final void putLongRelease(Object o, long offset, long x) {
+        putLongVolatile(o, offset, x);
+    }
+
+    /** Acquire version of {@link #getLongVolatile(Object, long)} */
+    @HotSpotIntrinsicCandidate
+    public final long getLongAcquire(Object o, long offset) {
+        return getLongVolatile(o, offset);
+    }
+
+    /** Release version of {@link #putObjectVolatile(Object, long, Object)} */
+    @HotSpotIntrinsicCandidate
+    public final void putObjectRelease(Object o, long offset, Object x) {
+        putObjectVolatile(o, offset, x);
+    }
+
+    /** Acquire version of {@link #getObjectVolatile(Object, long)} */
+    @HotSpotIntrinsicCandidate
+    public final Object getObjectAcquire(Object o, long offset) {
+        return getObjectVolatile(o, offset);
+    }
+
+    /**
+     * Ensures that loads before the fence will not be reordered with loads and
+     * stores after the fence; a "LoadLoad plus LoadStore barrier".
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_acquire)
+     * (an "acquire fence").
+     *
+     * A pure LoadLoad fence is not provided, since the addition of LoadStore
+     * is almost always desired, and most current hardware instructions that
+     * provide a LoadLoad barrier also provide a LoadStore barrier for free.
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    @FastNative
+    public native void loadFence();
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered with
+     * stores after the fence; a "StoreStore plus LoadStore barrier".
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_release)
+     * (a "release fence").
+     *
+     * A pure StoreStore fence is not provided, since the addition of LoadStore
+     * is almost always desired, and most current hardware instructions that
+     * provide a StoreStore barrier also provide a LoadStore barrier for free.
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    @FastNative
+    public native void storeFence();
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered
+     * with loads and stores after the fence.  Implies the effects of both
+     * loadFence() and storeFence(), and in addition, the effect of a StoreLoad
+     * barrier.
+     *
+     * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
+     * @since 1.8
+     */
+    @HotSpotIntrinsicCandidate
+    @FastNative
+    public native void fullFence();
+
+    /**
+     * Ensures the given class has been initialized. This is often
+     * needed in conjunction with obtaining the static field base of a
+     * class.
+     */
+    public void ensureClassInitialized(Class<?> c) {
+        if (c == null) {
+            throw new NullPointerException();
+        }
+
+        // Android-changed: Implementation not yet available natively (b/202380950)
+        // ensureClassInitialized0(c);
+        try {
+            Class.forName(c.getName(), true, c.getClassLoader());
+        } catch (ClassNotFoundException e) {
+            // The function doesn't specify that it's throwing ClassNotFoundException, so it needs
+            // to be caught here. We could rethrow as NoClassDefFoundError, however that is not
+            // documented for this function and the upstream implementation does not throw an
+            // exception.
+        }
+    }
+
+
+    /// helper methods for validating various types of objects/values
+
+    /**
+     * Create an exception reflecting that some of the input was invalid
+     *
+     * <em>Note:</em> It is the resposibility of the caller to make
+     * sure arguments are checked before the methods are called. While
+     * some rudimentary checks are performed on the input, the checks
+     * are best effort and when performance is an overriding priority,
+     * as when methods of this class are optimized by the runtime
+     * compiler, some or all checks (if any) may be elided. Hence, the
+     * caller must not rely on the checks and corresponding
+     * exceptions!
+     *
+     * @return an exception object
+     */
+    private RuntimeException invalidInput() {
+        return new IllegalArgumentException();
+    }
+
+    /**
+     * Check if a value is 32-bit clean (32 MSB are all zero)
+     *
+     * @param value the 64-bit value to check
+     *
+     * @return true if the value is 32-bit clean
+     */
+    private boolean is32BitClean(long value) {
+        return value >>> 32 == 0;
+    }
+
+    /**
+     * Check the validity of a size (the equivalent of a size_t)
+     *
+     * @throws RuntimeException if the size is invalid
+     *         (<em>Note:</em> after optimization, invalid inputs may
+     *         go undetected, which will lead to unpredictable
+     *         behavior)
+     */
+    private void checkSize(long size) {
+        if (ADDRESS_SIZE == 4) {
+            // Note: this will also check for negative sizes
+            if (!is32BitClean(size)) {
+                throw invalidInput();
+            }
+        } else if (size < 0) {
+            throw invalidInput();
+        }
+    }
+
+    /**
+     * Check the validity of a native address (the equivalent of void*)
+     *
+     * @throws RuntimeException if the address is invalid
+     *         (<em>Note:</em> after optimization, invalid inputs may
+     *         go undetected, which will lead to unpredictable
+     *         behavior)
+     */
+    private void checkNativeAddress(long address) {
+        if (ADDRESS_SIZE == 4) {
+            // Accept both zero and sign extended pointers. A valid
+            // pointer will, after the +1 below, either have produced
+            // the value 0x0 or 0x1. Masking off the low bit allows
+            // for testing against 0.
+            if ((((address >> 32) + 1) & ~1) != 0) {
+                throw invalidInput();
+            }
+        }
+    }
+
+    /**
+     * Check the validity of an offset, relative to a base object
+     *
+     * @param o the base object
+     * @param offset the offset to check
+     *
+     * @throws RuntimeException if the size is invalid
+     *         (<em>Note:</em> after optimization, invalid inputs may
+     *         go undetected, which will lead to unpredictable
+     *         behavior)
+     */
+    private void checkOffset(Object o, long offset) {
+        if (ADDRESS_SIZE == 4) {
+            // Note: this will also check for negative offsets
+            if (!is32BitClean(offset)) {
+                throw invalidInput();
+            }
+        } else if (offset < 0) {
+            throw invalidInput();
+        }
+    }
+
+    /**
+     * Check the validity of a double-register pointer
+     *
+     * Note: This code deliberately does *not* check for NPE for (at
+     * least) three reasons:
+     *
+     * 1) NPE is not just NULL/0 - there is a range of values all
+     * resulting in an NPE, which is not trivial to check for
+     *
+     * 2) It is the responsibility of the callers of Unsafe methods
+     * to verify the input, so throwing an exception here is not really
+     * useful - passing in a NULL pointer is a critical error and the
+     * must not expect an exception to be thrown anyway.
+     *
+     * 3) the actual operations will detect NULL pointers anyway by
+     * means of traps and signals (like SIGSEGV).
+     *
+     * @param o Java heap object, or null
+     * @param offset indication of where the variable resides in a Java heap
+     *        object, if any, else a memory address locating the variable
+     *        statically
+     *
+     * @throws RuntimeException if the pointer is invalid
+     *         (<em>Note:</em> after optimization, invalid inputs may
+     *         go undetected, which will lead to unpredictable
+     *         behavior)
+     */
+    private void checkPointer(Object o, long offset) {
+        if (o == null) {
+            checkNativeAddress(offset);
+        } else {
+            checkOffset(o, offset);
+        }
+    }
+
+    /**
+     * Check if a type is a primitive array type
+     *
+     * @param c the type to check
+     *
+     * @return true if the type is a primitive array type
+     */
+    private void checkPrimitiveArray(Class<?> c) {
+        Class<?> componentType = c.getComponentType();
+        if (componentType == null || !componentType.isPrimitive()) {
+            throw invalidInput();
+        }
+    }
+
+    /**
+     * Check that a pointer is a valid primitive array type pointer
+     *
+     * Note: pointers off-heap are considered to be primitive arrays
+     *
+     * @throws RuntimeException if the pointer is invalid
+     *         (<em>Note:</em> after optimization, invalid inputs may
+     *         go undetected, which will lead to unpredictable
+     *         behavior)
+     */
+    private void checkPrimitivePointer(Object o, long offset) {
+        checkPointer(o, offset);
+
+        if (o != null) {
+            // If on heap, it must be a primitive array
+            checkPrimitiveArray(o.getClass());
+        }
+    }
+
+
+
+}
diff --git a/ojluni/src/main/java/jdk/internal/misc/VM.java b/ojluni/src/main/java/jdk/internal/misc/VM.java
new file mode 100644
index 0000000..3c799bc
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/misc/VM.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import static java.lang.Thread.State.*;
+
+import dalvik.annotation.optimization.CriticalNative;
+import java.util.Properties;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class VM {
+
+    /* The following methods used to be native methods that instruct
+     * the VM to selectively suspend certain threads in low-memory
+     * situations. They are inherently dangerous and not implementable
+     * on native threads. We removed them in JDK 1.2. The skeletons
+     * remain so that existing applications that use these methods
+     * will still work.
+     */
+    private static boolean suspended = false;
+
+    /** @deprecated */
+    @Deprecated
+    public static boolean threadsSuspended() {
+        return suspended;
+    }
+
+    @SuppressWarnings("deprecation")
+    public static boolean allowThreadSuspension(ThreadGroup g, boolean b) {
+        return g.allowThreadSuspension(b);
+    }
+
+    /** @deprecated */
+    @Deprecated
+    public static boolean suspendThreads() {
+        suspended = true;
+        return true;
+    }
+
+    // Causes any suspended threadgroups to be resumed.
+    /** @deprecated */
+    @Deprecated
+    public static void unsuspendThreads() {
+        suspended = false;
+    }
+
+    // Causes threadgroups no longer marked suspendable to be resumed.
+    /** @deprecated */
+    @Deprecated
+    public static void unsuspendSomeThreads() {
+    }
+
+    /* Deprecated fields and methods -- Memory advice not supported in 1.2 */
+
+    /** @deprecated */
+    @Deprecated
+    public static final int STATE_GREEN = 1;
+
+    /** @deprecated */
+    @Deprecated
+    public static final int STATE_YELLOW = 2;
+
+    /** @deprecated */
+    @Deprecated
+    public static final int STATE_RED = 3;
+
+    /** @deprecated */
+    @Deprecated
+    public static final int getState() {
+        return STATE_GREEN;
+    }
+
+    // Android-removed: Not used.
+    /** @deprecated */
+    // @Deprecated
+    // public static void registerVMNotification(VMNotification n) { }
+
+    /** @deprecated */
+    @Deprecated
+    public static void asChange(int as_old, int as_new) { }
+
+    /** @deprecated */
+    @Deprecated
+    public static void asChange_otherthread(int as_old, int as_new) { }
+
+    /*
+     * Not supported in 1.2 because these will have to be exported as
+     * JVM functions, and we are not sure we want do that. Leaving
+     * here so it can be easily resurrected -- just remove the //
+     * comments.
+     */
+
+    /**
+     * Resume Java profiling.  All profiling data is added to any
+     * earlier profiling, unless <code>resetJavaProfiler</code> is
+     * called in between.  If profiling was not started from the
+     * command line, <code>resumeJavaProfiler</code> will start it.
+     * <p>
+     *
+     * NOTE: Profiling must be enabled from the command line for a
+     * java.prof report to be automatically generated on exit; if not,
+     * writeJavaProfilerReport must be invoked to write a report.
+     *
+     * @see     resetJavaProfiler
+     * @see     writeJavaProfilerReport
+     */
+
+    // public native static void resumeJavaProfiler();
+
+    /**
+     * Suspend Java profiling.
+     */
+    // public native static void suspendJavaProfiler();
+
+    /**
+     * Initialize Java profiling.  Any accumulated profiling
+     * information is discarded.
+     */
+    // public native static void resetJavaProfiler();
+
+    /**
+     * Write the current profiling contents to the file "java.prof".
+     * If the file already exists, it will be overwritten.
+     */
+    // public native static void writeJavaProfilerReport();
+
+
+    private static volatile boolean booted = false;
+    private static final Object lock = new Object();
+
+    // Invoked by by System.initializeSystemClass just before returning.
+    // Subsystems that are invoked during initialization can check this
+    // property in order to avoid doing things that should wait until the
+    // application class loader has been set up.
+    //
+    public static void booted() {
+        synchronized (lock) {
+            booted = true;
+            lock.notifyAll();
+        }
+    }
+
+    public static boolean isBooted() {
+        return booted;
+    }
+
+    // Waits until VM completes initialization
+    //
+    // This method is invoked by the Finalizer thread
+    public static void awaitBooted() throws InterruptedException {
+        synchronized (lock) {
+            while (!booted) {
+                lock.wait();
+            }
+        }
+    }
+
+    // A user-settable upper limit on the maximum amount of allocatable direct
+    // buffer memory.  This value may be changed during VM initialization if
+    // "java" is launched with "-XX:MaxDirectMemorySize=<size>".
+    //
+    // The initial value of this field is arbitrary; during JRE initialization
+    // it will be reset to the value specified on the command line, if any,
+    // otherwise to Runtime.getRuntime().maxMemory().
+    //
+    private static long directMemory = 64 * 1024 * 1024;
+
+    // Returns the maximum amount of allocatable direct buffer memory.
+    // The directMemory variable is initialized during system initialization
+    // in the saveAndRemoveProperties method.
+    //
+    public static long maxDirectMemory() {
+        return directMemory;
+    }
+
+    // User-controllable flag that determines if direct buffers should be page
+    // aligned. The "-XX:+PageAlignDirectMemory" option can be used to force
+    // buffers, allocated by ByteBuffer.allocateDirect, to be page aligned.
+    private static boolean pageAlignDirectMemory;
+
+    // Returns {@code true} if the direct buffers should be page aligned. This
+    // variable is initialized by saveAndRemoveProperties.
+    public static boolean isDirectMemoryPageAligned() {
+        return pageAlignDirectMemory;
+    }
+
+    // A user-settable boolean to determine whether ClassLoader.loadClass should
+    // accept array syntax.  This value may be changed during VM initialization
+    // via the system property "sun.lang.ClassLoader.allowArraySyntax".
+    //
+    // The default for 1.5 is "true", array syntax is allowed.  In 1.6, the
+    // default will be "false".  The presence of this system property to
+    // control array syntax allows applications the ability to preview this new
+    // behaviour.
+    //
+    private static boolean defaultAllowArraySyntax = false;
+    private static boolean allowArraySyntax = defaultAllowArraySyntax;
+
+    // The allowArraySyntax boolean is initialized during system initialization
+    // in the saveAndRemoveProperties method.
+    //
+    // It is initialized based on the value of the system property
+    // "sun.lang.ClassLoader.allowArraySyntax".  If the system property is not
+    // provided, the default for 1.5 is "true".  In 1.6, the default will be
+    // "false".  If the system property is provided, then the value of
+    // allowArraySyntax will be equal to "true" if Boolean.parseBoolean()
+    // returns "true".   Otherwise, the field will be set to "false".
+    //
+    public static boolean allowArraySyntax() {
+        return allowArraySyntax;
+    }
+
+    // BEGIN Android-removed: Not used on android.
+    /**
+     * Returns true if the given class loader is in the system domain
+     * in which all permissions are granted.
+     */
+    // public static boolean isSystemDomainLoader(ClassLoader loader) {
+    //     return loader == null;
+    // }
+    // END Android-removed: Not used on android.
+
+    /**
+     * Returns the system property of the specified key saved at
+     * system initialization time.  This method should only be used
+     * for the system properties that are not changed during runtime.
+     * It accesses a private copy of the system properties so
+     * that user's locking of the system properties object will not
+     * cause the library to deadlock.
+     *
+     * Note that the saved system properties do not include
+     * the ones set by sun.misc.Version.init().
+     *
+     */
+    public static String getSavedProperty(String key) {
+        // TODO(narayan): Why is this commented out ?
+        // if (savedProps.isEmpty())
+        //     throw new IllegalStateException("Should be non-empty if initialized");
+
+        return savedProps.getProperty(key);
+    }
+
+    // TODO: the Property Management needs to be refactored and
+    // the appropriate prop keys need to be accessible to the
+    // calling classes to avoid duplication of keys.
+    private static final Properties savedProps = new Properties();
+
+    // Save a private copy of the system properties and remove
+    // the system properties that are not intended for public access.
+    //
+    // This method can only be invoked during system initialization.
+    public static void saveAndRemoveProperties(Properties props) {
+        if (booted)
+            throw new IllegalStateException("System initialization has completed");
+
+        savedProps.putAll(props);
+
+        // Set the maximum amount of direct memory.  This value is controlled
+        // by the vm option -XX:MaxDirectMemorySize=<size>.
+        // The maximum amount of allocatable direct buffer memory (in bytes)
+        // from the system property sun.nio.MaxDirectMemorySize set by the VM.
+        // The system property will be removed.
+        String s = (String)props.remove("sun.nio.MaxDirectMemorySize");
+        if (s != null) {
+            if (s.equals("-1")) {
+                // -XX:MaxDirectMemorySize not given, take default
+                directMemory = Runtime.getRuntime().maxMemory();
+            } else {
+                long l = Long.parseLong(s);
+                if (l > -1)
+                    directMemory = l;
+            }
+        }
+
+        // Check if direct buffers should be page aligned
+        s = (String)props.remove("sun.nio.PageAlignDirectMemory");
+        if ("true".equals(s))
+            pageAlignDirectMemory = true;
+
+        // Set a boolean to determine whether ClassLoader.loadClass accepts
+        // array syntax.  This value is controlled by the system property
+        // "sun.lang.ClassLoader.allowArraySyntax".
+        s = props.getProperty("sun.lang.ClassLoader.allowArraySyntax");
+        allowArraySyntax = (s == null
+                               ? defaultAllowArraySyntax
+                               : Boolean.parseBoolean(s));
+
+        // Remove other private system properties
+        // used by java.lang.Integer.IntegerCache
+        props.remove("java.lang.Integer.IntegerCache.high");
+
+        // used by java.util.zip.ZipFile
+        props.remove("sun.zip.disableMemoryMapping");
+
+        // used by sun.launcher.LauncherHelper
+        props.remove("sun.java.launcher.diag");
+
+        // used by sun.misc.URLClassPath
+        props.remove("sun.cds.enableSharedLookupCache");
+    }
+
+    // Initialize any miscellenous operating system settings that need to be
+    // set for the class libraries.
+    //
+    public static void initializeOSEnvironment() {
+        // Android-removed: OSEnvironment.initialize() not supported
+        //if (!booted) {
+        //    OSEnvironment.initialize();
+        //}
+    }
+
+    /* Current count of objects pending for finalization */
+    private static volatile int finalRefCount = 0;
+
+    /* Peak count of objects pending for finalization */
+    private static volatile int peakFinalRefCount = 0;
+
+    /*
+     * Gets the number of objects pending for finalization.
+     *
+     * @return the number of objects pending for finalization.
+     */
+    public static int getFinalRefCount() {
+        return finalRefCount;
+    }
+
+    /*
+     * Gets the peak number of objects pending for finalization.
+     *
+     * @return the peak number of objects pending for finalization.
+     */
+    public static int getPeakFinalRefCount() {
+        return peakFinalRefCount;
+    }
+
+    /*
+     * Add <tt>n</tt> to the objects pending for finalization count.
+     *
+     * @param n an integer value to be added to the objects pending
+     * for finalization count
+     */
+    public static void addFinalRefCount(int n) {
+        // The caller must hold lock to synchronize the update.
+
+        finalRefCount += n;
+        if (finalRefCount > peakFinalRefCount) {
+            peakFinalRefCount = finalRefCount;
+        }
+    }
+
+    /**
+     * Returns Thread.State for the given threadStatus
+     */
+    public static Thread.State toThreadState(int threadStatus) {
+        if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) {
+            return RUNNABLE;
+        } else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) {
+            return BLOCKED;
+        } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) {
+            return WAITING;
+        } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) {
+            return TIMED_WAITING;
+        } else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) {
+            return TERMINATED;
+        } else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) {
+            return NEW;
+        } else {
+            return RUNNABLE;
+        }
+    }
+
+    /* The threadStatus field is set by the VM at state transition
+     * in the hotspot implementation. Its value is set according to
+     * the JVM TI specification GetThreadState function.
+     */
+    private final static int JVMTI_THREAD_STATE_ALIVE = 0x0001;
+    private final static int JVMTI_THREAD_STATE_TERMINATED = 0x0002;
+    private final static int JVMTI_THREAD_STATE_RUNNABLE = 0x0004;
+    private final static int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400;
+    private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
+    private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
+
+    // Android-changed: Add @CriticalNative for performance to be consistent with System.currentTimeMillis().
+    /**
+     * Get a nanosecond time stamp adjustment in the form of a single long.
+     *
+     * This value can be used to create an instant using
+     * {@link java.time.Instant#ofEpochSecond(long, long)
+     *  java.time.Instant.ofEpochSecond(offsetInSeconds,
+     *  getNanoTimeAdjustment(offsetInSeconds))}.
+     * <p>
+     * The value returned has the best resolution available to the JVM on
+     * the current system.
+     * This is usually down to microseconds - or tenth of microseconds -
+     * depending on the OS/Hardware and the JVM implementation.
+     *
+     * @param offsetInSeconds The offset in seconds from which the nanosecond
+     *        time stamp should be computed.
+     *
+     * @apiNote The offset should be recent enough - so that
+     *         {@code offsetInSeconds} is within {@code +/- 2^32} seconds of the
+     *         current UTC time. If the offset is too far off, {@code -1} will be
+     *         returned. As such, {@code -1} must not be considered as a valid
+     *         nano time adjustment, but as an exception value indicating
+     *         that an offset closer to the current time should be used.
+     *
+     * @return A nanosecond time stamp adjustment in the form of a single long.
+     *     If the offset is too far off the current time, this method returns -1.
+     *     In that case, the caller should call this method again, passing a
+     *     more accurate offset.
+     */
+    @CriticalNative
+    public static native long getNanoTimeAdjustment(long offsetInSeconds);
+
+    // BEGIN Android-removed: latestUserDefinedLoader()/initialize() not supported.
+    // /*
+    //  * Returns the first non-null class loader up the execution stack,
+    //  * or null if only code from the null class loader is on the stack.
+    //  */
+    // public static native ClassLoader latestUserDefinedLoader();
+
+    // static {
+    //     initialize();
+    // }
+    // private native static void initialize();
+    // END Android-removed: latestUserDefinedLoader()/initialize() not supported.
+
+    // BEGIN Android-removed: initializeFromArchive() not supported.
+    /*
+     * Initialize archived static fields in the given Class using archived
+     * values from CDS dump time. Also initialize the classes of objects in
+     * the archived graph referenced by those fields.
+     *
+     * Those static fields remain as uninitialized if there is no mapped CDS
+     * java heap data or there is any error during initialization of the
+     * object class in the archived graph.
+     *
+    public static native void initializeFromArchive(Class<?> c);
+     */
+    // END Android-removed: initializeFromArchive() not supported.
+}
diff --git a/ojluni/src/main/java/jdk/internal/ref/Cleaner.java b/ojluni/src/main/java/jdk/internal/ref/Cleaner.java
new file mode 100644
index 0000000..5522c0c
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/ref/Cleaner.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.ref;
+
+import java.lang.ref.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+
+/**
+ * General-purpose phantom-reference-based cleaners.
+ *
+ * <p> Cleaners are a lightweight and more robust alternative to finalization.
+ * They are lightweight because they are not created by the VM and thus do not
+ * require a JNI upcall to be created, and because their cleanup code is
+ * invoked directly by the reference-handler thread rather than by the
+ * finalizer thread.  They are more robust because they use phantom references,
+ * the weakest type of reference object, thereby avoiding the nasty ordering
+ * problems inherent to finalization.
+ *
+ * <p> A cleaner tracks a referent object and encapsulates a thunk of arbitrary
+ * cleanup code.  Some time after the GC detects that a cleaner's referent has
+ * become phantom-reachable, the reference-handler thread will run the cleaner.
+ * Cleaners may also be invoked directly; they are thread safe and ensure that
+ * they run their thunks at most once.
+ *
+ * <p> Cleaners are not a replacement for finalization.  They should be used
+ * only when the cleanup code is extremely simple and straightforward.
+ * Nontrivial cleaners are inadvisable since they risk blocking the
+ * reference-handler thread and delaying further cleanup and finalization.
+ *
+ *
+ * @author Mark Reinhold
+ */
+
+public class Cleaner
+    extends PhantomReference<Object>
+{
+
+    // Dummy reference queue, needed because the PhantomReference constructor
+    // insists that we pass a queue.  Nothing will ever be placed on this queue
+    // since the reference handler invokes cleaners explicitly.
+    //
+    private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>();
+
+    // Doubly-linked list of live cleaners, which prevents the cleaners
+    // themselves from being GC'd before their referents
+    //
+    private static Cleaner first = null;
+
+    private Cleaner
+        next = null,
+        prev = null;
+
+    private static synchronized Cleaner add(Cleaner cl) {
+        if (first != null) {
+            cl.next = first;
+            first.prev = cl;
+        }
+        first = cl;
+        return cl;
+    }
+
+    private static synchronized boolean remove(Cleaner cl) {
+
+        // If already removed, do nothing
+        if (cl.next == cl)
+            return false;
+
+        // Update list
+        if (first == cl) {
+            if (cl.next != null)
+                first = cl.next;
+            else
+                first = cl.prev;
+        }
+        if (cl.next != null)
+            cl.next.prev = cl.prev;
+        if (cl.prev != null)
+            cl.prev.next = cl.next;
+
+        // Indicate removal by pointing the cleaner to itself
+        cl.next = cl;
+        cl.prev = cl;
+        return true;
+
+    }
+
+    private final Runnable thunk;
+
+    private Cleaner(Object referent, Runnable thunk) {
+        super(referent, dummyQueue);
+        this.thunk = thunk;
+    }
+
+    /**
+     * Creates a new cleaner.
+     *
+     * @param  ob the referent object to be cleaned
+     * @param  thunk
+     *         The cleanup code to be run when the cleaner is invoked.  The
+     *         cleanup code is run directly from the reference-handler thread,
+     *         so it should be as simple and straightforward as possible.
+     *
+     * @return  The new cleaner
+     */
+    public static Cleaner create(Object ob, Runnable thunk) {
+        if (thunk == null)
+            return null;
+        return add(new Cleaner(ob, thunk));
+    }
+
+    /**
+     * Runs this cleaner, if it has not been run before.
+     */
+    public void clean() {
+        if (!remove(this))
+            return;
+        try {
+            thunk.run();
+        } catch (final Throwable x) {
+            AccessController.doPrivileged(new PrivilegedAction<>() {
+                    public Void run() {
+                        if (System.err != null)
+                            new Error("Cleaner terminated abnormally", x)
+                                .printStackTrace();
+                        System.exit(1);
+                        return null;
+                    }});
+        }
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/ref/CleanerFactory.java b/ojluni/src/main/java/jdk/internal/ref/CleanerFactory.java
new file mode 100644
index 0000000..a4d3a0f
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/ref/CleanerFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.ref;
+
+import dalvik.system.ZygoteHooks;
+
+import jdk.internal.misc.InnocuousThread;
+
+import java.lang.ref.Cleaner;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * CleanerFactory provides a Cleaner for use within system modules.
+ * The cleaner is created on the first reference to the CleanerFactory.
+ */
+public final class CleanerFactory {
+
+    /* The common Cleaner. */
+    private final static Cleaner commonCleaner = Cleaner.create(new ThreadFactory() {
+        @Override
+        public Thread newThread(Runnable r) {
+            // Android-added: Fail immediately if we try this in the zygote, where we are
+            // not allowed to create additional threads.
+            if (ZygoteHooks.inZygote()) {
+                throw new AssertionError("Erroneously trying to create Cleaner in zygote");
+            }
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                @Override
+                public Thread run() {
+                    Thread t = InnocuousThread.newSystemThread("Common-Cleaner", r);
+                    t.setPriority(Thread.MAX_PRIORITY - 2);
+                    return t;
+                }
+            });
+        }
+    });
+
+    /**
+     * Cleaner for use within system modules.
+     *
+     * This Cleaner will run on a thread whose context class loader
+     * is {@code null}. The system cleaning action to perform in
+     * this Cleaner should handle a {@code null} context class loader.
+     *
+     * @return a Cleaner for use within system modules
+     */
+    public static Cleaner cleaner() {
+        return commonCleaner;
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/ref/CleanerImpl.java b/ojluni/src/main/java/jdk/internal/ref/CleanerImpl.java
new file mode 100644
index 0000000..16a82fe
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/ref/CleanerImpl.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.ref;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Cleaner.Cleanable;
+import java.lang.ref.ReferenceQueue;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
+
+import jdk.internal.misc.InnocuousThread;
+
+/**
+ * CleanerImpl manages a set of object references and corresponding cleaning actions.
+ * CleanerImpl provides the functionality of {@link java.lang.ref.Cleaner}.
+ */
+public final class CleanerImpl implements Runnable {
+
+    /**
+     * An object to access the CleanerImpl from a Cleaner; set by Cleaner init.
+     */
+    private static Function<Cleaner, CleanerImpl> cleanerImplAccess = null;
+
+    /**
+     * Heads of a CleanableList for each reference type.
+     */
+    final PhantomCleanable<?> phantomCleanableList;
+
+    // Android-removed: WeakCleanable and SoftCleanable. b/198792576
+    // final WeakCleanable<?> weakCleanableList;
+
+    // Android-removed: WeakCleanable and SoftCleanable. b/198792576
+    // final SoftCleanable<?> softCleanableList;
+
+    // The ReferenceQueue of pending cleaning actions
+    final ReferenceQueue<Object> queue;
+
+    /**
+     * Called by Cleaner static initialization to provide the function
+     * to map from Cleaner to CleanerImpl.
+     * @param access a function to map from Cleaner to CleanerImpl
+     */
+    public static void setCleanerImplAccess(Function<Cleaner, CleanerImpl> access) {
+        if (cleanerImplAccess == null) {
+            cleanerImplAccess = access;
+        } else {
+            throw new InternalError("cleanerImplAccess");
+        }
+    }
+
+    /**
+     * Called to get the CleanerImpl for a Cleaner.
+     * @param cleaner the cleaner
+     * @return the corresponding CleanerImpl
+     */
+    static CleanerImpl getCleanerImpl(Cleaner cleaner) {
+        return cleanerImplAccess.apply(cleaner);
+    }
+
+    /**
+     * Constructor for CleanerImpl.
+     */
+    public CleanerImpl() {
+        queue = new ReferenceQueue<>();
+        phantomCleanableList = new PhantomCleanableRef();
+        // Android-removed: WeakCleanable and SoftCleanable. b/198792576
+        // weakCleanableList = new WeakCleanableRef();
+        // softCleanableList = new SoftCleanableRef();
+    }
+
+    /**
+     * Starts the Cleaner implementation.
+     * Ensure this is the CleanerImpl for the Cleaner.
+     * When started waits for Cleanables to be queued.
+     * @param cleaner the cleaner
+     * @param threadFactory the thread factory
+     */
+    public void start(Cleaner cleaner, ThreadFactory threadFactory) {
+        if (getCleanerImpl(cleaner) != this) {
+            throw new AssertionError("wrong cleaner");
+        }
+        // schedule a nop cleaning action for the cleaner, so the associated thread
+        // will continue to run at least until the cleaner is reclaimable.
+        new CleanerCleanable(cleaner);
+
+        if (threadFactory == null) {
+            threadFactory = CleanerImpl.InnocuousThreadFactory.factory();
+        }
+
+        // now that there's at least one cleaning action, for the cleaner,
+        // we can start the associated thread, which runs until
+        // all cleaning actions have been run.
+        Thread thread = threadFactory.newThread(this);
+        thread.setDaemon(true);
+        thread.start();
+    }
+
+    /**
+     * Process queued Cleanables as long as the cleanable lists are not empty.
+     * A Cleanable is in one of the lists for each Object and for the Cleaner
+     * itself.
+     * Terminates when the Cleaner is no longer reachable and
+     * has been cleaned and there are no more Cleanable instances
+     * for which the object is reachable.
+     * <p>
+     * If the thread is a ManagedLocalsThread, the threadlocals
+     * are erased before each cleanup
+     */
+    @Override
+    public void run() {
+        Thread t = Thread.currentThread();
+        InnocuousThread mlThread = (t instanceof InnocuousThread)
+                ? (InnocuousThread) t
+                : null;
+        while (!phantomCleanableList.isListEmpty()) {
+            // Android-removed: WeakCleanable and SoftCleanable. b/198792576
+            //     !weakCleanableList.isListEmpty() ||
+            //     !softCleanableList.isListEmpty()) {
+            if (mlThread != null) {
+                // Clear the thread locals
+                mlThread.eraseThreadLocals();
+            }
+            try {
+                // Wait for a Ref, with a timeout to avoid getting hung
+                // due to a race with clear/clean
+                Cleanable ref = (Cleanable) queue.remove(60 * 1000L);
+                if (ref != null) {
+                    ref.clean();
+                }
+            } catch (Throwable e) {
+                // ignore exceptions from the cleanup action
+                // (including interruption of cleanup thread)
+            }
+        }
+    }
+
+    /**
+     * Perform cleaning on an unreachable PhantomReference.
+     */
+    public static final class PhantomCleanableRef extends PhantomCleanable<Object> {
+        private final Runnable action;
+
+        /**
+         * Constructor for a phantom cleanable reference.
+         * @param obj the object to monitor
+         * @param cleaner the cleaner
+         * @param action the action Runnable
+         */
+        public PhantomCleanableRef(Object obj, Cleaner cleaner, Runnable action) {
+            super(obj, cleaner);
+            this.action = action;
+        }
+
+        /**
+         * Constructor used only for root of phantom cleanable list.
+         */
+        PhantomCleanableRef() {
+            super();
+            this.action = null;
+        }
+
+        @Override
+        protected void performCleanup() {
+            action.run();
+        }
+
+        /**
+         * Prevent access to referent even when it is still alive.
+         *
+         * @throws UnsupportedOperationException always
+         */
+        @Override
+        public Object get() {
+            throw new UnsupportedOperationException("get");
+        }
+
+        /**
+         * Direct clearing of the referent is not supported.
+         *
+         * @throws UnsupportedOperationException always
+         */
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException("clear");
+        }
+    }
+
+    // BEGIN Android-removed: WeakCleanable and SoftCleanable. b/198792576
+    /*
+     * Perform cleaning on an unreachable WeakReference.
+     *
+    public static final class WeakCleanableRef extends WeakCleanable<Object> {
+        private final Runnable action;
+
+        /**
+         * Constructor for a weak cleanable reference.
+         * @param obj the object to monitor
+         * @param cleaner the cleaner
+         * @param action the action Runnable
+         *
+        WeakCleanableRef(Object obj, Cleaner cleaner, Runnable action) {
+            super(obj, cleaner);
+            this.action = action;
+        }
+
+        /**
+         * Constructor used only for root of weak cleanable list.
+         *
+        WeakCleanableRef() {
+            super();
+            this.action = null;
+        }
+
+        @Override
+        protected void performCleanup() {
+            action.run();
+        }
+
+        /**
+         * Prevent access to referent even when it is still alive.
+         *
+         * @throws UnsupportedOperationException always
+         *
+        @Override
+        public Object get() {
+            throw new UnsupportedOperationException("get");
+        }
+
+        /**
+         * Direct clearing of the referent is not supported.
+         *
+         * @throws UnsupportedOperationException always
+         *
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException("clear");
+        }
+    }
+
+    /**
+     * Perform cleaning on an unreachable SoftReference.
+     *
+    public static final class SoftCleanableRef extends SoftCleanable<Object> {
+        private final Runnable action;
+
+        /**
+         * Constructor for a soft cleanable reference.
+         * @param obj the object to monitor
+         * @param cleaner the cleaner
+         * @param action the action Runnable
+         *
+        SoftCleanableRef(Object obj, Cleaner cleaner, Runnable action) {
+            super(obj, cleaner);
+            this.action = action;
+        }
+
+        /**
+         * Constructor used only for root of soft cleanable list.
+         *
+        SoftCleanableRef() {
+            super();
+            this.action = null;
+        }
+
+        @Override
+        protected void performCleanup() {
+            action.run();
+        }
+
+        /**
+         * Prevent access to referent even when it is still alive.
+         *
+         * @throws UnsupportedOperationException always
+         *
+        @Override
+        public Object get() {
+            throw new UnsupportedOperationException("get");
+        }
+
+        /**
+         * Direct clearing of the referent is not supported.
+         *
+         * @throws UnsupportedOperationException always
+         *
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException("clear");
+        }
+
+    }
+    */
+    // END Android-removed: WeakCleanable and SoftCleanable. b/198792576
+
+    /**
+     * A ThreadFactory for InnocuousThreads.
+     * The factory is a singleton.
+     */
+    static final class InnocuousThreadFactory implements ThreadFactory {
+        final static ThreadFactory factory = new InnocuousThreadFactory();
+
+        static ThreadFactory factory() {
+            return factory;
+        }
+
+        final AtomicInteger cleanerThreadNumber = new AtomicInteger();
+
+        public Thread newThread(Runnable r) {
+            return AccessController.doPrivileged(new PrivilegedAction<>() {
+                @Override
+                public Thread run() {
+                    Thread t = InnocuousThread.newThread(r);
+                    t.setPriority(Thread.MAX_PRIORITY - 2);
+                    t.setName("Cleaner-" + cleanerThreadNumber.getAndIncrement());
+                    return t;
+                }
+            });
+        }
+    }
+
+    /**
+     * A PhantomCleanable implementation for tracking the Cleaner itself.
+     */
+    static final class CleanerCleanable extends PhantomCleanable<Cleaner> {
+        CleanerCleanable(Cleaner cleaner) {
+            super(cleaner, cleaner);
+        }
+
+        @Override
+        protected void performCleanup() {
+            // no action
+        }
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/ref/PhantomCleanable.java b/ojluni/src/main/java/jdk/internal/ref/PhantomCleanable.java
new file mode 100644
index 0000000..bbcf994
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/ref/PhantomCleanable.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.ref;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Reference;
+import java.lang.ref.PhantomReference;
+import java.util.Objects;
+
+/**
+ * PhantomCleanable subclasses efficiently encapsulate cleanup state and
+ * the cleaning action.
+ * Subclasses implement the abstract {@link #performCleanup()}  method
+ * to provide the cleaning action.
+ * When constructed, the object reference and the {@link Cleaner.Cleanable Cleanable}
+ * are registered with the {@link Cleaner}.
+ * The Cleaner invokes {@link Cleaner.Cleanable#clean() clean} after the
+ * referent becomes phantom reachable.
+ */
+public abstract class PhantomCleanable<T> extends PhantomReference<T>
+        implements Cleaner.Cleanable {
+
+    /**
+     * Links to previous and next in a doubly-linked list.
+     */
+    PhantomCleanable<?> prev = this, next = this;
+
+    /**
+     * The list of PhantomCleanable; synchronizes insert and remove.
+     */
+    private final PhantomCleanable<?> list;
+
+    /**
+     * Constructs new {@code PhantomCleanable} with
+     * {@code non-null referent} and {@code non-null cleaner}.
+     * The {@code cleaner} is not retained; it is only used to
+     * register the newly constructed {@link Cleaner.Cleanable Cleanable}.
+     *
+     * @param referent the referent to track
+     * @param cleaner  the {@code Cleaner} to register with
+     */
+    public PhantomCleanable(T referent, Cleaner cleaner) {
+        super(Objects.requireNonNull(referent), CleanerImpl.getCleanerImpl(cleaner).queue);
+        this.list = CleanerImpl.getCleanerImpl(cleaner).phantomCleanableList;
+        insert();
+
+        // Ensure referent and cleaner remain accessible
+        Reference.reachabilityFence(referent);
+        Reference.reachabilityFence(cleaner);
+    }
+
+    /**
+     * Construct a new root of the list; not inserted.
+     */
+    PhantomCleanable() {
+        super(null, null);
+        this.list = this;
+    }
+
+    /**
+     * Insert this PhantomCleanable after the list head.
+     */
+    private void insert() {
+        synchronized (list) {
+            prev = list;
+            next = list.next;
+            next.prev = this;
+            list.next = this;
+        }
+    }
+
+    /**
+     * Remove this PhantomCleanable from the list.
+     *
+     * @return true if Cleanable was removed or false if not because
+     * it had already been removed before
+     */
+    private boolean remove() {
+        synchronized (list) {
+            if (next != this) {
+                next.prev = prev;
+                prev.next = next;
+                prev = this;
+                next = this;
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Returns true if the list's next reference refers to itself.
+     *
+     * @return true if the list is empty
+     */
+    boolean isListEmpty() {
+        synchronized (list) {
+            return list == list.next;
+        }
+    }
+
+    /**
+     * Unregister this PhantomCleanable and invoke {@link #performCleanup()},
+     * ensuring at-most-once semantics.
+     */
+    @Override
+    public final void clean() {
+        if (remove()) {
+            super.clear();
+            performCleanup();
+        }
+    }
+
+    /**
+     * Unregister this PhantomCleanable and clear the reference.
+     * Due to inherent concurrency, {@link #performCleanup()} may still be invoked.
+     */
+    @Override
+    public void clear() {
+        if (remove()) {
+            super.clear();
+        }
+    }
+
+    /**
+     * The {@code performCleanup} abstract method is overridden
+     * to implement the cleaning logic.
+     * The {@code performCleanup} method should not be called except
+     * by the {@link #clean} method which ensures at most once semantics.
+     */
+    protected abstract void performCleanup();
+
+    /**
+     * This method always throws {@link UnsupportedOperationException}.
+     * Enqueuing details of {@link Cleaner.Cleanable}
+     * are a private implementation detail.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    @Override
+    public final boolean isEnqueued() {
+        throw new UnsupportedOperationException("isEnqueued");
+    }
+
+    /**
+     * This method always throws {@link UnsupportedOperationException}.
+     * Enqueuing details of {@link Cleaner.Cleanable}
+     * are a private implementation detail.
+     *
+     * @throws UnsupportedOperationException always
+     */
+    @Override
+    public final boolean enqueue() {
+        throw new UnsupportedOperationException("enqueue");
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/reflect/CallerSensitive.java b/ojluni/src/main/java/jdk/internal/reflect/CallerSensitive.java
new file mode 100644
index 0000000..a049926
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/reflect/CallerSensitive.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.reflect;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.ElementType.*;
+
+// Android-added: @hide; CallerSensitive is used in source but not part of the public API
+/**
+ * A method annotated @CallerSensitive is sensitive to its calling class,
+ * via {@link jdk.internal.reflect.Reflection#getCallerClass Reflection.getCallerClass},
+ * or via some equivalent.
+ *
+ * @author John R. Rose
+ *
+ * @hide
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({METHOD})
+public @interface CallerSensitive {
+}
diff --git a/ojluni/src/main/java/jdk/internal/reflect/Reflection.java b/ojluni/src/main/java/jdk/internal/reflect/Reflection.java
new file mode 100644
index 0000000..7091d0d
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/reflect/Reflection.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.reflect;
+
+import java.lang.reflect.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import dalvik.system.VMStack;
+
+/** Common utility routines used by both java.lang and
+    java.lang.reflect */
+
+public class Reflection {
+
+    // Android-removed: Dead code.
+    /*
+    /** Used to filter out fields and methods from certain classes from public
+        view, where they are sensitive or they may contain VM-internal objects.
+        These Maps are updated very rarely. Rather than synchronize on
+        each access, we use copy-on-write *
+    private static volatile Map<Class<?>,String[]> fieldFilterMap;
+    private static volatile Map<Class<?>,String[]> methodFilterMap;
+
+    static {
+        Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>();
+        map.put(Reflection.class,
+            new String[] {"fieldFilterMap", "methodFilterMap"});
+        map.put(System.class, new String[] {"security"});
+        map.put(Class.class, new String[] {"classLoader"});
+        fieldFilterMap = map;
+
+        methodFilterMap = new HashMap<>();
+    }
+   */
+
+    // BEGIN Android-changed: getCallerClass() reimplementation.
+    // As of 2018-07 this implementation does not ignore frames
+    // associated with java.lang.reflect.Method.invoke() but this
+    // may change in future, see http://b/111800372 .
+    // Only code that expects or can handle the RI behavior (eg.
+    // code inherited from the RI) should call this method.
+    /*
+    /** Returns the class of the caller of the method calling this method,
+        ignoring frames associated with java.lang.reflect.Method.invoke()
+        and its implementation. *
+    @CallerSensitive
+    public static native Class<?> getCallerClass();
+    */
+    public static Class<?> getCallerClass() {
+        // This method (getCallerClass()) constitutes another stack frame,
+        // so we need to call getStackClass2() rather than getStackClass1().
+        return VMStack.getStackClass2();
+    }
+    // END Android-changed: getCallerClass() reimplementation.
+
+    // Android-removed: Dead code.
+    /*
+    /**
+     * @deprecated This method will be removed in JDK 9.
+     * This method is a private JDK API and retained temporarily for
+     * existing code to run until a replacement API is defined.
+     *
+    @Deprecated
+    public static native Class<?> getCallerClass(int depth);
+
+    /** Retrieves the access flags written to the class file. For
+        inner classes these flags may differ from those returned by
+        Class.getModifiers(), which searches the InnerClasses
+        attribute to find the source-level access flags. This is used
+        instead of Class.getModifiers() for run-time access checks due
+        to compatibility reasons; see 4471811. Only the values of the
+        low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
+        valid. *
+    public static native int getClassAccessFlags(Class<?> c);
+
+    /** A quick "fast-path" check to try to avoid getCallerClass()
+        calls. *
+    public static boolean quickCheckMemberAccess(Class<?> memberClass,
+                                                 int modifiers)
+    {
+        return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers);
+    }
+    */
+
+    public static void ensureMemberAccess(Class<?> currentClass,
+                                          Class<?> memberClass,
+                                          Object target,
+                                          int modifiers)
+        throws IllegalAccessException
+    {
+        if (currentClass == null || memberClass == null) {
+            throw new InternalError();
+        }
+
+        if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) {
+            throw new IllegalAccessException("Class " + currentClass.getName() +
+                                             " can not access a member of class " +
+                                             memberClass.getName() +
+                                             " with modifiers \"" +
+                                             Modifier.toString(modifiers) +
+                                             "\"");
+        }
+    }
+
+    public static boolean verifyMemberAccess(Class<?> currentClass,
+                                             // Declaring class of field
+                                             // or method
+                                             Class<?> memberClass,
+                                             // May be NULL in case of statics
+                                             Object   target,
+                                             int      modifiers)
+    {
+        // Verify that currentClass can access a field, method, or
+        // constructor of memberClass, where that member's access bits are
+        // "modifiers".
+
+        boolean gotIsSameClassPackage = false;
+        boolean isSameClassPackage = false;
+
+        if (currentClass == memberClass) {
+            // Always succeeds
+            return true;
+        }
+
+        // Android-changed: verifyMemberAccess() consistent with class.getAccessFlags(T).
+        // The RI carries a separate getClassAccessFlags(Class) utility method
+        // with slightly different behavior for backwards compatibility. This
+        // does not apply on Android since the RI code was never adopted.
+        // if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
+        if (!Modifier.isPublic(memberClass.getAccessFlags())) {
+            isSameClassPackage = isSameClassPackage(currentClass, memberClass);
+            gotIsSameClassPackage = true;
+            if (!isSameClassPackage) {
+                return false;
+            }
+        }
+
+        // At this point we know that currentClass can access memberClass.
+
+        if (Modifier.isPublic(modifiers)) {
+            return true;
+        }
+
+        boolean successSoFar = false;
+
+        if (Modifier.isProtected(modifiers)) {
+            // See if currentClass is a subclass of memberClass
+            if (isSubclassOf(currentClass, memberClass)) {
+                successSoFar = true;
+            }
+        }
+
+        if (!successSoFar && !Modifier.isPrivate(modifiers)) {
+            if (!gotIsSameClassPackage) {
+                isSameClassPackage = isSameClassPackage(currentClass,
+                                                        memberClass);
+                gotIsSameClassPackage = true;
+            }
+
+            if (isSameClassPackage) {
+                successSoFar = true;
+            }
+        }
+
+        if (!successSoFar) {
+            return false;
+        }
+
+        if (Modifier.isProtected(modifiers)) {
+            // Additional test for protected members: JLS 6.6.2
+            Class<?> targetClass = (target == null ? memberClass : target.getClass());
+            if (targetClass != currentClass) {
+                if (!gotIsSameClassPackage) {
+                    isSameClassPackage = isSameClassPackage(currentClass, memberClass);
+                    gotIsSameClassPackage = true;
+                }
+                if (!isSameClassPackage) {
+                    if (!isSubclassOf(targetClass, currentClass)) {
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
+    private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
+        return isSameClassPackage(c1.getClassLoader(), c1.getName(),
+                                  c2.getClassLoader(), c2.getName());
+    }
+
+    /** Returns true if two classes are in the same package; classloader
+        and classname information is enough to determine a class's package */
+    private static boolean isSameClassPackage(ClassLoader loader1, String name1,
+                                              ClassLoader loader2, String name2)
+    {
+        if (loader1 != loader2) {
+            return false;
+        } else {
+            int lastDot1 = name1.lastIndexOf('.');
+            int lastDot2 = name2.lastIndexOf('.');
+            if ((lastDot1 == -1) || (lastDot2 == -1)) {
+                // One of the two doesn't have a package.  Only return true
+                // if the other one also doesn't have a package.
+                return (lastDot1 == lastDot2);
+            } else {
+                int idx1 = 0;
+                int idx2 = 0;
+
+                // Skip over '['s
+                if (name1.charAt(idx1) == '[') {
+                    do {
+                        idx1++;
+                    } while (name1.charAt(idx1) == '[');
+                    if (name1.charAt(idx1) != 'L') {
+                        // Something is terribly wrong.  Shouldn't be here.
+                        throw new InternalError("Illegal class name " + name1);
+                    }
+                }
+                if (name2.charAt(idx2) == '[') {
+                    do {
+                        idx2++;
+                    } while (name2.charAt(idx2) == '[');
+                    if (name2.charAt(idx2) != 'L') {
+                        // Something is terribly wrong.  Shouldn't be here.
+                        throw new InternalError("Illegal class name " + name2);
+                    }
+                }
+
+                // Check that package part is identical
+                int length1 = lastDot1 - idx1;
+                int length2 = lastDot2 - idx2;
+
+                if (length1 != length2) {
+                    return false;
+                }
+                return name1.regionMatches(false, idx1, name2, idx2, length1);
+            }
+        }
+    }
+
+    static boolean isSubclassOf(Class<?> queryClass,
+                                Class<?> ofClass)
+    {
+        while (queryClass != null) {
+            if (queryClass == ofClass) {
+                return true;
+            }
+            queryClass = queryClass.getSuperclass();
+        }
+        return false;
+    }
+
+    // Android-removed: Dead code.
+
+}
diff --git a/ojluni/src/main/java/jdk/internal/util/ArraysSupport.java b/ojluni/src/main/java/jdk/internal/util/ArraysSupport.java
new file mode 100644
index 0000000..90cb1a3
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/util/ArraysSupport.java
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.util;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.misc.Unsafe;
+
+/**
+ * Utility methods to find a mismatch between two primitive arrays.
+ *
+ * <p>Array equality and lexicographical comparison can be built on top of
+ * array mismatch functionality.
+ *
+ * <p>The mismatch method implementation, {@link #vectorizedMismatch}, leverages
+ * vector-based techniques to access and compare the contents of two arrays.
+ * The Java implementation uses {@code Unsafe.getLongUnaligned} to access the
+ * content of an array, thus access is supported on platforms that do not
+ * support unaligned access.  For a byte[] array, 8 bytes (64 bits) can be
+ * accessed and compared as a unit rather than individually, which increases
+ * the performance when the method is compiled by the HotSpot VM.  On supported
+ * platforms the mismatch implementation is intrinsified to leverage SIMD
+ * instructions.  So for a byte[] array, 16 bytes (128 bits), 32 bytes
+ * (256 bits), and perhaps in the future even 64 bytes (512 bits), platform
+ * permitting, can be accessed and compared as a unit, which further increases
+ * the performance over the Java implementation.
+ *
+ * <p>None of the mismatch methods perform array bounds checks.  It is the
+ * responsibility of the caller (direct or otherwise) to perform such checks
+ * before calling this method.
+ */
+public class ArraysSupport {
+    static final Unsafe U = Unsafe.getUnsafe();
+
+    // Android-changed: Android is little endian.
+    private static final boolean BIG_ENDIAN = false;
+
+    public static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
+    public static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE);
+    public static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE);
+    public static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE);
+    public static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE);
+    public static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE);
+    public static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE);
+    public static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+
+    private static final int LOG2_BYTE_BIT_SIZE = exactLog2(Byte.SIZE);
+
+    private static int exactLog2(int scale) {
+        if ((scale & (scale - 1)) != 0)
+            throw new Error("data type scale not a power of two");
+        return Integer.numberOfTrailingZeros(scale);
+    }
+
+    private ArraysSupport() {}
+
+    /**
+     * Find the relative index of the first mismatching pair of elements in two
+     * primitive arrays of the same component type.  Pairs of elements will be
+     * tested in order relative to given offsets into both arrays.
+     *
+     * <p>This method does not perform type checks or bounds checks.  It is the
+     * responsibility of the caller to perform such checks before calling this
+     * method.
+     *
+     * <p>The given offsets, in bytes, need not be aligned according to the
+     * given log<sub>2</sub> size the array elements.  More specifically, an
+     * offset modulus the size need not be zero.
+     *
+     * @param a the first array to be tested for mismatch, or {@code null} for
+     * direct memory access
+     * @param aOffset the relative offset, in bytes, from the base address of
+     * the first array to test from, otherwise if the first array is
+     * {@code null}, an absolute address pointing to the first element to test.
+     * @param b the second array to be tested for mismatch, or {@code null} for
+     * direct memory access
+     * @param bOffset the relative offset, in bytes, from the base address of
+     * the second array to test from, otherwise if the second array is
+     * {@code null}, an absolute address pointing to the first element to test.
+     * @param length the number of array elements to test
+     * @param log2ArrayIndexScale log<sub>2</sub> of the array index scale, that
+     * corresponds to the size, in bytes, of an array element.
+     * @return if a mismatch is found a relative index, between 0 (inclusive)
+     * and {@code length} (exclusive), of the first mismatching pair of elements
+     * in the two arrays.  Otherwise, if a mismatch is not found the bitwise
+     * compliment of the number of remaining pairs of elements to be checked in
+     * the tail of the two arrays.
+     */
+    @HotSpotIntrinsicCandidate
+    public static int vectorizedMismatch(Object a, long aOffset,
+                                         Object b, long bOffset,
+                                         int length,
+                                         int log2ArrayIndexScale) {
+        // assert a.getClass().isArray();
+        // assert b.getClass().isArray();
+        // assert 0 <= length <= sizeOf(a)
+        // assert 0 <= length <= sizeOf(b)
+        // assert 0 <= log2ArrayIndexScale <= 3
+
+        int log2ValuesPerWidth = LOG2_ARRAY_LONG_INDEX_SCALE - log2ArrayIndexScale;
+        int wi = 0;
+        for (; wi < length >> log2ValuesPerWidth; wi++) {
+            long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
+            long av = U.getLongUnaligned(a, aOffset + bi);
+            long bv = U.getLongUnaligned(b, bOffset + bi);
+            if (av != bv) {
+                long x = av ^ bv;
+                int o = BIG_ENDIAN
+                        ? Long.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
+                        : Long.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
+                return (wi << log2ValuesPerWidth) + o;
+            }
+        }
+
+        // Calculate the tail of remaining elements to check
+        int tail = length - (wi << log2ValuesPerWidth);
+
+        if (log2ArrayIndexScale < LOG2_ARRAY_INT_INDEX_SCALE) {
+            int wordTail = 1 << (LOG2_ARRAY_INT_INDEX_SCALE - log2ArrayIndexScale);
+            // Handle 4 bytes or 2 chars in the tail using int width
+            if (tail >= wordTail) {
+                long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
+                int av = U.getIntUnaligned(a, aOffset + bi);
+                int bv = U.getIntUnaligned(b, bOffset + bi);
+                if (av != bv) {
+                    int x = av ^ bv;
+                    int o = BIG_ENDIAN
+                            ? Integer.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
+                            : Integer.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
+                    return (wi << log2ValuesPerWidth) + o;
+                }
+                tail -= wordTail;
+            }
+            return ~tail;
+        }
+        else {
+            return ~tail;
+        }
+    }
+
+    // Booleans
+    // Each boolean element takes up one byte
+
+    public static int mismatch(boolean[] a,
+                               boolean[] b,
+                               int length) {
+        int i = 0;
+        if (length > 7) {
+            if (a[0] != b[0])
+                return 0;
+            i = vectorizedMismatch(
+                    a, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
+                    b, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
+                    length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[i] != b[i])
+                return i;
+        }
+        return -1;
+    }
+
+    public static int mismatch(boolean[] a, int aFromIndex,
+                               boolean[] b, int bFromIndex,
+                               int length) {
+        int i = 0;
+        if (length > 7) {
+            if (a[aFromIndex] != b[bFromIndex])
+                return 0;
+            int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex;
+            int bOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + bFromIndex;
+            i = vectorizedMismatch(
+                    a, aOffset,
+                    b, bOffset,
+                    length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[aFromIndex + i] != b[bFromIndex + i])
+                return i;
+        }
+        return -1;
+    }
+
+
+    // Bytes
+
+    /**
+     * Find the index of a mismatch between two arrays.
+     *
+     * <p>This method does not perform bounds checks. It is the responsibility
+     * of the caller to perform such bounds checks before calling this method.
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param b the second array to be tested for a mismatch
+     * @param length the number of bytes from each array to check
+     * @return the index of a mismatch between the two arrays, otherwise -1 if
+     * no mismatch.  The index will be within the range of (inclusive) 0 to
+     * (exclusive) the smaller of the two array lengths.
+     */
+    public static int mismatch(byte[] a,
+                               byte[] b,
+                               int length) {
+        // ISSUE: defer to index receiving methods if performance is good
+        // assert length <= a.length
+        // assert length <= b.length
+
+        int i = 0;
+        if (length > 7) {
+            if (a[0] != b[0])
+                return 0;
+            i = vectorizedMismatch(
+                    a, Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    b, Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    length, LOG2_ARRAY_BYTE_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            // Align to tail
+            i = length - ~i;
+//            assert i >= 0 && i <= 7;
+        }
+        // Tail < 8 bytes
+        for (; i < length; i++) {
+            if (a[i] != b[i])
+                return i;
+        }
+        return -1;
+    }
+
+    /**
+     * Find the relative index of a mismatch between two arrays starting from
+     * given indexes.
+     *
+     * <p>This method does not perform bounds checks. It is the responsibility
+     * of the caller to perform such bounds checks before calling this method.
+     *
+     * @param a the first array to be tested for a mismatch
+     * @param aFromIndex the index of the first element (inclusive) in the first
+     * array to be compared
+     * @param b the second array to be tested for a mismatch
+     * @param bFromIndex the index of the first element (inclusive) in the
+     * second array to be compared
+     * @param length the number of bytes from each array to check
+     * @return the relative index of a mismatch between the two arrays,
+     * otherwise -1 if no mismatch.  The index will be within the range of
+     * (inclusive) 0 to (exclusive) the smaller of the two array bounds.
+     */
+    public static int mismatch(byte[] a, int aFromIndex,
+                               byte[] b, int bFromIndex,
+                               int length) {
+        // assert 0 <= aFromIndex < a.length
+        // assert 0 <= aFromIndex + length <= a.length
+        // assert 0 <= bFromIndex < b.length
+        // assert 0 <= bFromIndex + length <= b.length
+        // assert length >= 0
+
+        int i = 0;
+        if (length > 7) {
+            if (a[aFromIndex] != b[bFromIndex])
+                return 0;
+            int aOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + aFromIndex;
+            int bOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + bFromIndex;
+            i = vectorizedMismatch(
+                    a, aOffset,
+                    b, bOffset,
+                    length, LOG2_ARRAY_BYTE_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[aFromIndex + i] != b[bFromIndex + i])
+                return i;
+        }
+        return -1;
+    }
+
+
+    // Chars
+
+    public static int mismatch(char[] a,
+                               char[] b,
+                               int length) {
+        int i = 0;
+        if (length > 3) {
+            if (a[0] != b[0])
+                return 0;
+            i = vectorizedMismatch(
+                    a, Unsafe.ARRAY_CHAR_BASE_OFFSET,
+                    b, Unsafe.ARRAY_CHAR_BASE_OFFSET,
+                    length, LOG2_ARRAY_CHAR_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[i] != b[i])
+                return i;
+        }
+        return -1;
+    }
+
+    public static int mismatch(char[] a, int aFromIndex,
+                               char[] b, int bFromIndex,
+                               int length) {
+        int i = 0;
+        if (length > 3) {
+            if (a[aFromIndex] != b[bFromIndex])
+                return 0;
+            int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
+            int bOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
+            i = vectorizedMismatch(
+                    a, aOffset,
+                    b, bOffset,
+                    length, LOG2_ARRAY_CHAR_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[aFromIndex + i] != b[bFromIndex + i])
+                return i;
+        }
+        return -1;
+    }
+
+
+    // Shorts
+
+    public static int mismatch(short[] a,
+                               short[] b,
+                               int length) {
+        int i = 0;
+        if (length > 3) {
+            if (a[0] != b[0])
+                return 0;
+            i = vectorizedMismatch(
+                    a, Unsafe.ARRAY_SHORT_BASE_OFFSET,
+                    b, Unsafe.ARRAY_SHORT_BASE_OFFSET,
+                    length, LOG2_ARRAY_SHORT_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[i] != b[i])
+                return i;
+        }
+        return -1;
+    }
+
+    public static int mismatch(short[] a, int aFromIndex,
+                               short[] b, int bFromIndex,
+                               int length) {
+        int i = 0;
+        if (length > 3) {
+            if (a[aFromIndex] != b[bFromIndex])
+                return 0;
+            int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
+            int bOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
+            i = vectorizedMismatch(
+                    a, aOffset,
+                    b, bOffset,
+                    length, LOG2_ARRAY_SHORT_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[aFromIndex + i] != b[bFromIndex + i])
+                return i;
+        }
+        return -1;
+    }
+
+
+    // Ints
+
+    public static int mismatch(int[] a,
+                               int[] b,
+                               int length) {
+        int i = 0;
+        if (length > 1) {
+            if (a[0] != b[0])
+                return 0;
+            i = vectorizedMismatch(
+                    a, Unsafe.ARRAY_INT_BASE_OFFSET,
+                    b, Unsafe.ARRAY_INT_BASE_OFFSET,
+                    length, LOG2_ARRAY_INT_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[i] != b[i])
+                return i;
+        }
+        return -1;
+    }
+
+    public static int mismatch(int[] a, int aFromIndex,
+                               int[] b, int bFromIndex,
+                               int length) {
+        int i = 0;
+        if (length > 1) {
+            if (a[aFromIndex] != b[bFromIndex])
+                return 0;
+            int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
+            int bOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
+            i = vectorizedMismatch(
+                    a, aOffset,
+                    b, bOffset,
+                    length, LOG2_ARRAY_INT_INDEX_SCALE);
+            if (i >= 0)
+                return i;
+            i = length - ~i;
+        }
+        for (; i < length; i++) {
+            if (a[aFromIndex + i] != b[bFromIndex + i])
+                return i;
+        }
+        return -1;
+    }
+
+
+    // Floats
+
+    public static int mismatch(float[] a,
+                               float[] b,
+                               int length) {
+        return mismatch(a, 0, b, 0, length);
+    }
+
+    public static int mismatch(float[] a, int aFromIndex,
+                               float[] b, int bFromIndex,
+                               int length) {
+        int i = 0;
+        if (length > 1) {
+            if (Float.floatToRawIntBits(a[aFromIndex]) == Float.floatToRawIntBits(b[bFromIndex])) {
+                int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
+                int bOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
+                i = vectorizedMismatch(
+                        a, aOffset,
+                        b, bOffset,
+                        length, LOG2_ARRAY_FLOAT_INDEX_SCALE);
+            }
+            // Mismatched
+            if (i >= 0) {
+                // Check if mismatch is not associated with two NaN values
+                if (!Float.isNaN(a[aFromIndex + i]) || !Float.isNaN(b[bFromIndex + i]))
+                    return i;
+
+                // Mismatch on two different NaN values that are normalized to match
+                // Fall back to slow mechanism
+                // ISSUE: Consider looping over vectorizedMismatch adjusting ranges
+                // However, requires that returned value be relative to input ranges
+                i++;
+            }
+            // Matched
+            else {
+                i = length - ~i;
+            }
+        }
+        for (; i < length; i++) {
+            if (Float.floatToIntBits(a[aFromIndex + i]) != Float.floatToIntBits(b[bFromIndex + i]))
+                return i;
+        }
+        return -1;
+    }
+
+    // 64 bit sizes
+
+    // Long
+
+    public static int mismatch(long[] a,
+                               long[] b,
+                               int length) {
+        if (length == 0) {
+            return -1;
+        }
+        if (a[0] != b[0])
+            return 0;
+        int i = vectorizedMismatch(
+                a, Unsafe.ARRAY_LONG_BASE_OFFSET,
+                b, Unsafe.ARRAY_LONG_BASE_OFFSET,
+                length, LOG2_ARRAY_LONG_INDEX_SCALE);
+        return i >= 0 ? i : -1;
+    }
+
+    public static int mismatch(long[] a, int aFromIndex,
+                               long[] b, int bFromIndex,
+                               int length) {
+        if (length == 0) {
+            return -1;
+        }
+        if (a[aFromIndex] != b[bFromIndex])
+            return 0;
+        int aOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
+        int bOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
+        int i = vectorizedMismatch(
+                a, aOffset,
+                b, bOffset,
+                length, LOG2_ARRAY_LONG_INDEX_SCALE);
+        return i >= 0 ? i : -1;
+    }
+
+
+    // Double
+
+    public static int mismatch(double[] a,
+                               double[] b,
+                               int length) {
+        return mismatch(a, 0, b, 0, length);
+    }
+
+    public static int mismatch(double[] a, int aFromIndex,
+                               double[] b, int bFromIndex,
+                               int length) {
+        if (length == 0) {
+            return -1;
+        }
+        int i = 0;
+        if (Double.doubleToRawLongBits(a[aFromIndex]) == Double.doubleToRawLongBits(b[bFromIndex])) {
+            int aOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+            int bOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+            i = vectorizedMismatch(
+                    a, aOffset,
+                    b, bOffset,
+                    length, LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+        }
+        if (i >= 0) {
+            // Check if mismatch is not associated with two NaN values
+            if (!Double.isNaN(a[aFromIndex + i]) || !Double.isNaN(b[bFromIndex + i]))
+                return i;
+
+            // Mismatch on two different NaN values that are normalized to match
+            // Fall back to slow mechanism
+            // ISSUE: Consider looping over vectorizedMismatch adjusting ranges
+            // However, requires that returned value be relative to input ranges
+            i++;
+            for (; i < length; i++) {
+                if (Double.doubleToLongBits(a[aFromIndex + i]) != Double.doubleToLongBits(b[bFromIndex + i]))
+                    return i;
+            }
+        }
+
+        return -1;
+    }
+}
diff --git a/ojluni/src/main/java/jdk/internal/util/Preconditions.java b/ojluni/src/main/java/jdk/internal/util/Preconditions.java
index 0e91afd..d275b15 100644
--- a/ojluni/src/main/java/jdk/internal/util/Preconditions.java
+++ b/ojluni/src/main/java/jdk/internal/util/Preconditions.java
@@ -24,6 +24,8 @@
  */
 package jdk.internal.util;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+
 import java.util.List;
 import java.util.function.BiFunction;
 import java.util.function.Function;
@@ -183,13 +185,13 @@
         // Switch to default if fewer or more arguments than required are supplied
         switch ((args.size() != argSize) ? "" : checkKind) {
             case "checkIndex":
-                return String.format("Index %d out-of-bounds for length %d",
+                return String.format("Index %s out of bounds for length %s",
                                      args.get(0), args.get(1));
             case "checkFromToIndex":
-                return String.format("Range [%d, %d) out-of-bounds for length %d",
+                return String.format("Range [%s, %s) out of bounds for length %s",
                                      args.get(0), args.get(1), args.get(2));
             case "checkFromIndexSize":
-                return String.format("Range [%d, %<d + %d) out-of-bounds for length %d",
+                return String.format("Range [%s, %<s + %s) out of bounds for length %s",
                                      args.get(0), args.get(1), args.get(2));
             default:
                 return String.format("Range check failed: %s %s", checkKind, args);
@@ -238,8 +240,7 @@
      * length is a non-negative value (such as that of an array length or from
      * the upper bound of a loop)
     */
-    // Android-removed: @HotSpotIntrinsicCandidate not present on Android yet (could reconsider).
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public static <X extends RuntimeException>
     int checkIndex(int index, int length,
                    BiFunction<String, List<Integer>, X> oobef) {
diff --git a/ojluni/src/main/java/jdk/internal/vm/annotation/Contended.java b/ojluni/src/main/java/jdk/internal/vm/annotation/Contended.java
new file mode 100644
index 0000000..fd616cc
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/vm/annotation/Contended.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.vm.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// Android-note: Contended-specific implementation notes not relevant for Android.
+/**
+ * <p>An annotation expressing that objects and/or their fields are
+ * expected to encounter memory contention, generally in the form of
+ * "false sharing". This annotation serves as a hint that such objects
+ * and fields should reside in locations isolated from those of other
+ * objects or fields. Susceptibility to memory contention is a
+ * property of the intended usages of objects and fields, not their
+ * types or qualifiers. The effects of this annotation will nearly
+ * always add significant space overhead to objects. The use of
+ * {@code @Contended} is warranted only when the performance impact of
+ * this time/space tradeoff is intrinsically worthwhile; for example,
+ * in concurrent contexts in which each instance of the annotated
+ * class is often accessed by a different thread.
+ *
+ * <p>A {@code @Contended} field annotation may optionally include a
+ * <i>contention group</i> tag. A contention group defines a set of one
+ * or more fields that collectively must be isolated from all other
+ * contention groups. The fields in the same contention group may not be
+ * pairwise isolated. With no contention group tag (or with the default
+ * empty tag: "") each {@code @Contended} field resides in its own
+ * <i>distinct</i> and <i>anonymous</i> contention group.
+ *
+ * <p>When the annotation is used at the class level, the effect is
+ * equivalent to grouping all the declared fields not already having the
+ * {@code @Contended} annotation into the same anonymous group.
+ * With the class level annotation, implementations may choose different
+ * isolation techniques, such as isolating the entire object, rather than
+ * isolating distinct fields. A contention group tag has no meaning
+ * in a class level {@code @Contended} annotation, and is ignored.
+ *
+ * <p>The class level {@code @Contended} annotation is not inherited and has
+ * no effect on the fields declared in any sub-classes. The effects of all
+ * {@code @Contended} annotations, however, remain in force for all
+ * subclass instances, providing isolation of all the defined contention
+ * groups. Contention group tags are not inherited, and the same tag used
+ * in a superclass and subclass, represent distinct contention groups.
+ *
+ * @since 1.8
+ */
+// Android-changed: RetentionPolicy.SOURCE is sufficient as this is no-op on Android.
+// @Retention(RetentionPolicy.RUNTIME)
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.FIELD, ElementType.TYPE})
+public @interface Contended {
+
+    /**
+     * The (optional) contention group tag.
+     * This tag is only meaningful for field level annotations.
+     *
+     * @return contention group tag.
+     */
+    String value() default "";
+}
diff --git a/ojluni/src/main/java/jdk/internal/vm/annotation/ReservedStackAccess.java b/ojluni/src/main/java/jdk/internal/vm/annotation/ReservedStackAccess.java
new file mode 100644
index 0000000..91ea865
--- /dev/null
+++ b/ojluni/src/main/java/jdk/internal/vm/annotation/ReservedStackAccess.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.vm.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+// Android-note: ReservedStackAccess-specific implementation not available on Android.
+/**
+ * <p>An annotation expressing that a method is especially sensitive
+ * to stack overflows. This is a hint the JVM can use to grant access to
+ * extra stack space when executing this code if such feature is supported
+ * by the JVM. The JVM is free to ignore this annotation.
+ *
+ * A possible way for the JVM to improve the execution context for methods
+ * with this annotation is to reserve part of the thread's execution stack
+ * for them. Access to this section of the stack would be denied by default
+ * but could be granted if the JVM detects a possible stack overflow and
+ * the thread's call stack includes at least one annotated method. Even if
+ * access to this reserved area has been granted, the JVM might decide to
+ * throw a delayed StackOverflowError when the thread exits the annotated
+ * method.
+ *
+ * @since 9
+ */
+// Android-changed: RetentionPolicy.SOURCE is sufficient as this is no-op on Android.
+// @Retention(RetentionPolicy.RUNTIME)
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+public @interface ReservedStackAccess { }
+
diff --git a/ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java b/ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java
index 644fc4d..74a7bc8 100644
--- a/ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java
+++ b/ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,23 @@
 
 package jdk.net;
 
+import java.io.FileDescriptor;
+import java.net.SocketException;
 import java.net.SocketOption;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import jdk.internal.misc.JavaIOFileDescriptorAccess;
+import jdk.internal.misc.SharedSecrets;
 
 /**
  * Defines extended socket options, beyond those defined in
  * {@link java.net.StandardSocketOptions}. These options may be platform
  * specific.
+ *
+ * @since 1.8
  */
 // Android-removed: @jdk.Exported, not present on Android.
 // @jdk.Exported
@@ -48,7 +59,7 @@
         @Override public String toString() { return name; }
     }
 
-    private ExtendedSocketOptions() {}
+    private ExtendedSocketOptions() { }
 
     /**
      * Service level properties. When a security manager is installed,
@@ -58,4 +69,347 @@
      */
     public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
         ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
+
+    /**
+     * Disable Delayed Acknowledgements.
+     *
+     * <p>
+     * This socket option can be used to reduce or disable delayed
+     * acknowledgments (ACKs). When {@code TCP_QUICKACK} is enabled, ACKs are
+     * sent immediately, rather than delayed if needed in accordance to normal
+     * TCP operation. This option is not permanent, it only enables a switch to
+     * or from {@code TCP_QUICKACK} mode. Subsequent operations of the TCP
+     * protocol will once again disable/enable {@code TCP_QUICKACK} mode
+     * depending on internal protocol processing and factors such as delayed ACK
+     * timeouts occurring and data transfer, therefore this option needs to be
+     * set with {@code setOption} after each operation of TCP on a given socket.
+     *
+     * <p>
+     * The value of this socket option is a {@code Boolean} that represents
+     * whether the option is enabled or disabled. The socket option is specific
+     * to stream-oriented sockets using the TCP/IP protocol. The exact semantics
+     * of this socket option are socket type and system dependent.
+     *
+     * @since 10
+     */
+    public static final SocketOption<Boolean> TCP_QUICKACK =
+            new ExtSocketOption<Boolean>("TCP_QUICKACK", Boolean.class);
+
+    /**
+     * Keep-Alive idle time.
+     *
+     * <p>
+     * The value of this socket option is an {@code Integer} that is the number
+     * of seconds of idle time before keep-alive initiates a probe. The socket
+     * option is specific to stream-oriented sockets using the TCP/IP protocol.
+     * The exact semantics of this socket option are system dependent.
+     *
+     * <p>
+     * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE
+     * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been
+     * idle for some amount of time. The default value for this idle period is
+     * system dependent, but is typically 2 hours. The {@code TCP_KEEPIDLE}
+     * option can be used to affect this value for a given socket.
+     *
+     * @since 11
+     */
+    public static final SocketOption<Integer> TCP_KEEPIDLE
+            = new ExtSocketOption<Integer>("TCP_KEEPIDLE", Integer.class);
+
+    /**
+     * Keep-Alive retransmission interval time.
+     *
+     * <p>
+     * The value of this socket option is an {@code Integer} that is the number
+     * of seconds to wait before retransmitting a keep-alive probe. The socket
+     * option is specific to stream-oriented sockets using the TCP/IP protocol.
+     * The exact semantics of this socket option are system dependent.
+     *
+     * <p>
+     * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE
+     * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been
+     * idle for some amount of time. If the remote system does not respond to a
+     * keep-alive probe, TCP retransmits the probe after some amount of time.
+     * The default value for this retransmission interval is system dependent,
+     * but is typically 75 seconds. The {@code TCP_KEEPINTERVAL} option can be
+     * used to affect this value for a given socket.
+     *
+     * @since 11
+     */
+    public static final SocketOption<Integer> TCP_KEEPINTERVAL
+            = new ExtSocketOption<Integer>("TCP_KEEPINTERVAL", Integer.class);
+
+    /**
+     * Keep-Alive retransmission maximum limit.
+     *
+     * <p>
+     * The value of this socket option is an {@code Integer} that is the maximum
+     * number of keep-alive probes to be sent. The socket option is specific to
+     * stream-oriented sockets using the TCP/IP protocol. The exact semantics of
+     * this socket option are system dependent.
+     *
+     * <p>
+     * When the {@link java.net.StandardSocketOptions#SO_KEEPALIVE
+     * SO_KEEPALIVE} option is enabled, TCP probes a connection that has been
+     * idle for some amount of time. If the remote system does not respond to a
+     * keep-alive probe, TCP retransmits the probe a certain number of times
+     * before a connection is considered to be broken. The default value for
+     * this keep-alive probe retransmit limit is system dependent, but is
+     * typically 8. The {@code TCP_KEEPCOUNT} option can be used to affect this
+     * value for a given socket.
+     *
+     * @since 11
+     */
+    public static final SocketOption<Integer> TCP_KEEPCOUNT
+            = new ExtSocketOption<Integer>("TCP_KEEPCOUNT", Integer.class);
+
+    private static final PlatformSocketOptions platformSocketOptions =
+            PlatformSocketOptions.get();
+
+    private static final boolean flowSupported =
+            platformSocketOptions.flowSupported();
+    private static final boolean quickAckSupported =
+            platformSocketOptions.quickAckSupported();
+    private static final boolean keepAliveOptSupported =
+            platformSocketOptions.keepAliveOptionsSupported();
+    private static final Set<SocketOption<?>> extendedOptions = options();
+
+    static Set<SocketOption<?>> options() {
+        Set<SocketOption<?>> options = new HashSet<>();
+        if (flowSupported) {
+            options.add(SO_FLOW_SLA);
+        }
+        if (quickAckSupported) {
+            options.add(TCP_QUICKACK);
+        }
+        if (keepAliveOptSupported) {
+            options.addAll(Set.of(TCP_KEEPCOUNT, TCP_KEEPIDLE, TCP_KEEPINTERVAL));
+        }
+        return Collections.unmodifiableSet(options);
+    }
+
+    static {
+        // Registers the extended socket options with the base module.
+        sun.net.ext.ExtendedSocketOptions.register(
+                new sun.net.ext.ExtendedSocketOptions(extendedOptions) {
+
+            @Override
+            public void setOption(FileDescriptor fd,
+                                  SocketOption<?> option,
+                                  Object value)
+                throws SocketException
+            {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkPermission(new NetworkPermission("setOption." + option.name()));
+
+                if (fd == null || !fd.valid())
+                    throw new SocketException("socket closed");
+
+                if (option == SO_FLOW_SLA) {
+                    assert flowSupported;
+                    SocketFlow flow = checkValueType(value, option.type());
+                    setFlowOption(fd, flow);
+                } else if (option == TCP_QUICKACK) {
+                    setQuickAckOption(fd, (boolean) value);
+                } else if (option == TCP_KEEPCOUNT) {
+                    setTcpkeepAliveProbes(fd, (Integer) value);
+                } else if (option == TCP_KEEPIDLE) {
+                    setTcpKeepAliveTime(fd, (Integer) value);
+                } else if (option == TCP_KEEPINTERVAL) {
+                    setTcpKeepAliveIntvl(fd, (Integer) value);
+                } else {
+                    throw new InternalError("Unexpected option " + option);
+                }
+            }
+
+            @Override
+            public Object getOption(FileDescriptor fd,
+                                    SocketOption<?> option)
+                throws SocketException
+            {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkPermission(new NetworkPermission("getOption." + option.name()));
+
+                if (fd == null || !fd.valid())
+                    throw new SocketException("socket closed");
+
+                if (option == SO_FLOW_SLA) {
+                    assert flowSupported;
+                    SocketFlow flow = SocketFlow.create();
+                    getFlowOption(fd, flow);
+                    return flow;
+                } else if (option == TCP_QUICKACK) {
+                    return getQuickAckOption(fd);
+                } else if (option == TCP_KEEPCOUNT) {
+                    return getTcpkeepAliveProbes(fd);
+                } else if (option == TCP_KEEPIDLE) {
+                    return getTcpKeepAliveTime(fd);
+                } else if (option == TCP_KEEPINTERVAL) {
+                    return getTcpKeepAliveIntvl(fd);
+                } else {
+                    throw new InternalError("Unexpected option " + option);
+                }
+            }
+        });
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T checkValueType(Object value, Class<?> type) {
+        if (!type.isAssignableFrom(value.getClass())) {
+            String s = "Found: " + value.getClass() + ", Expected: " + type;
+            throw new IllegalArgumentException(s);
+        }
+        return (T) value;
+    }
+
+    private static final JavaIOFileDescriptorAccess fdAccess =
+            SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    private static void setFlowOption(FileDescriptor fd, SocketFlow f)
+        throws SocketException
+    {
+        int status = platformSocketOptions.setFlowOption(fdAccess.get(fd),
+                                                         f.priority(),
+                                                         f.bandwidth());
+        f.status(status);  // augment the given flow with the status
+    }
+
+    private static void getFlowOption(FileDescriptor fd, SocketFlow f)
+            throws SocketException {
+        int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f);
+        f.status(status);  // augment the given flow with the status
+    }
+
+    private static void setQuickAckOption(FileDescriptor fd, boolean enable)
+            throws SocketException {
+        platformSocketOptions.setQuickAck(fdAccess.get(fd), enable);
+    }
+
+    private static Object getQuickAckOption(FileDescriptor fd)
+            throws SocketException {
+        return platformSocketOptions.getQuickAck(fdAccess.get(fd));
+    }
+
+    private static void setTcpkeepAliveProbes(FileDescriptor fd, int value)
+            throws SocketException {
+        platformSocketOptions.setTcpkeepAliveProbes(fdAccess.get(fd), value);
+    }
+
+    private static void setTcpKeepAliveTime(FileDescriptor fd, int value)
+            throws SocketException {
+        platformSocketOptions.setTcpKeepAliveTime(fdAccess.get(fd), value);
+    }
+
+    private static void setTcpKeepAliveIntvl(FileDescriptor fd, int value)
+            throws SocketException {
+        platformSocketOptions.setTcpKeepAliveIntvl(fdAccess.get(fd), value);
+    }
+
+    private static int getTcpkeepAliveProbes(FileDescriptor fd) throws SocketException {
+        return platformSocketOptions.getTcpkeepAliveProbes(fdAccess.get(fd));
+    }
+
+    private static int getTcpKeepAliveTime(FileDescriptor fd) throws SocketException {
+        return platformSocketOptions.getTcpKeepAliveTime(fdAccess.get(fd));
+    }
+
+    private static int getTcpKeepAliveIntvl(FileDescriptor fd) throws SocketException {
+        return platformSocketOptions.getTcpKeepAliveIntvl(fdAccess.get(fd));
+    }
+
+    static class PlatformSocketOptions {
+
+        protected PlatformSocketOptions() {}
+
+        @SuppressWarnings("unchecked")
+        private static PlatformSocketOptions newInstance(String cn) {
+            Class<PlatformSocketOptions> c;
+            try {
+                c = (Class<PlatformSocketOptions>)Class.forName(cn);
+                return c.getConstructor(new Class<?>[] { }).newInstance();
+            } catch (ReflectiveOperationException x) {
+                throw new AssertionError(x);
+            }
+        }
+
+        private static PlatformSocketOptions create() {
+            // Android-removed: other platforms are unsupported.
+//            String osname = AccessController.doPrivileged(
+//                    new PrivilegedAction<String>() {
+//                        public String run() {
+//                            return System.getProperty("os.name");
+//                        }
+//                    });
+//            if ("SunOS".equals(osname)) {
+//                return newInstance("jdk.net.SolarisSocketOptions");
+//            } else if ("Linux".equals(osname)) {
+//                return newInstance("jdk.net.LinuxSocketOptions");
+//            } else if (osname.startsWith("Mac")) {
+//                return newInstance("jdk.net.MacOSXSocketOptions");
+//            }
+            return new PlatformSocketOptions();
+        }
+
+        private static final PlatformSocketOptions instance = create();
+
+        static PlatformSocketOptions get() {
+            return instance;
+        }
+
+        int setFlowOption(int fd, int priority, long bandwidth)
+            throws SocketException
+        {
+            throw new UnsupportedOperationException("unsupported socket option");
+        }
+
+        int getFlowOption(int fd, SocketFlow f) throws SocketException {
+            throw new UnsupportedOperationException("unsupported socket option");
+        }
+
+        boolean flowSupported() {
+            return false;
+        }
+
+        void setQuickAck(int fd, boolean on) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_QUICKACK option");
+        }
+
+        boolean getQuickAck(int fd) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_QUICKACK option");
+        }
+
+        boolean quickAckSupported() {
+            return false;
+        }
+
+        boolean keepAliveOptionsSupported() {
+            return false;
+        }
+
+        void setTcpkeepAliveProbes(int fd, final int value) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
+        }
+
+        void setTcpKeepAliveTime(int fd, final int value) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option");
+        }
+
+        void setTcpKeepAliveIntvl(int fd, final int value) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
+        }
+
+        int getTcpkeepAliveProbes(int fd) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_KEEPCNT option");
+        }
+
+        int getTcpKeepAliveTime(int fd) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_KEEPIDLE option");
+        }
+
+        int getTcpKeepAliveIntvl(int fd) throws SocketException {
+            throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
+        }
+    }
 }
diff --git a/ojluni/src/main/java/jdk/net/SocketFlow.java b/ojluni/src/main/java/jdk/net/SocketFlow.java
index 59875a8..8777722 100644
--- a/ojluni/src/main/java/jdk/net/SocketFlow.java
+++ b/ojluni/src/main/java/jdk/net/SocketFlow.java
@@ -42,28 +42,33 @@
  * <p>
  * When a security manager is installed, a {@link NetworkPermission}
  * is required to set or get this option.
+ *
+ * @since 1.8
  */
 // Android-removed: @jdk.Exported, not present on Android.
 // @jdk.Exported
 public class SocketFlow {
 
-    private static final int UNSET = -1;
+    @Native public static final int UNSET = -1;
     @Native public static final int NORMAL_PRIORITY = 1;
     @Native public static final int HIGH_PRIORITY = 2;
 
-    private int priority = NORMAL_PRIORITY;
-
-    private long bandwidth = UNSET;
-
-    private Status status = Status.NO_STATUS;
-
-    private SocketFlow() {}
+    @Native private static final int NO_STATUS_VALUE = 0;
+    @Native private static final int OK_VALUE = 1;
+    @Native private static final int NO_PERMISSION_VALUE = 2;
+    @Native private static final int NOT_CONNECTED_VALUE = 3;
+    @Native private static final int NOT_SUPPORTED_VALUE = 4;
+    @Native private static final int ALREADY_CREATED_VALUE = 5;
+    @Native private static final int IN_PROGRESS_VALUE = 6;
+    @Native private static final int OTHER_VALUE = 7;
 
     /**
      * Enumeration of the return values from the SO_FLOW_SLA
      * socket option. Both setting and getting the option return
      * one of these statuses, which reflect the state of socket's
      * flow.
+     *
+     * @since 1.8
      */
     // Android-removed: @jdk.Exported, not present on Android.
     // @jdk.Exported
@@ -72,37 +77,56 @@
          * Set or get socket option has not been called yet. Status
          * values can only be retrieved after calling set or get.
          */
-        NO_STATUS,
+        NO_STATUS(NO_STATUS_VALUE),
         /**
          * Flow successfully created.
          */
-        OK,
+        OK(OK_VALUE),
         /**
          * Caller has no permission to create flow.
          */
-        NO_PERMISSION,
+        NO_PERMISSION(NO_PERMISSION_VALUE),
         /**
          * Flow can not be created because socket is not connected.
          */
-        NOT_CONNECTED,
+        NOT_CONNECTED(NOT_CONNECTED_VALUE),
         /**
          * Flow creation not supported for this socket.
          */
-        NOT_SUPPORTED,
+        NOT_SUPPORTED(NOT_SUPPORTED_VALUE),
         /**
          * A flow already exists with identical attributes.
          */
-        ALREADY_CREATED,
+        ALREADY_CREATED(ALREADY_CREATED_VALUE),
         /**
          * A flow is being created.
          */
-        IN_PROGRESS,
+        IN_PROGRESS(IN_PROGRESS_VALUE),
         /**
          * Some other unspecified error.
          */
-        OTHER
+        OTHER(OTHER_VALUE);
+
+        private final int value;
+        Status(int value) { this.value = value; }
+
+        static Status from(int value) {
+            if      (value == NO_STATUS.value)       return NO_STATUS;
+            else if (value == OK.value)              return OK;
+            else if (value == NO_PERMISSION.value)   return NO_PERMISSION;
+            else if (value == NOT_CONNECTED.value)   return NOT_CONNECTED;
+            else if (value == NOT_SUPPORTED.value)   return NOT_SUPPORTED;
+            else if (value == ALREADY_CREATED.value) return ALREADY_CREATED;
+            else if (value == IN_PROGRESS.value)     return IN_PROGRESS;
+            else if (value == OTHER.value)           return OTHER;
+            else     throw new InternalError("Unknown value: " + value);
+        }
     }
 
+    private int priority = NORMAL_PRIORITY;
+    private long bandwidth = UNSET;
+    private Status status = Status.NO_STATUS;
+
     /**
      * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA
      * socket option and create a socket flow.
@@ -111,6 +135,8 @@
         return new SocketFlow();
     }
 
+    private SocketFlow() { }
+
     /**
      * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY
      * HIGH_PRIORITY. If not set, a flow's priority is normal.
@@ -119,9 +145,8 @@
      *         HIGH_PRIORITY.
      */
     public SocketFlow priority(int priority) {
-        if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) {
-            throw new IllegalArgumentException("invalid priority");
-        }
+        if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY)
+            throw new IllegalArgumentException("invalid priority :" + priority);
         this.priority = priority;
         return this;
     }
@@ -133,11 +158,9 @@
      * @throws IllegalArgumentException if bandwidth is less than zero.
      */
     public SocketFlow bandwidth(long bandwidth) {
-        if (bandwidth < 0) {
-            throw new IllegalArgumentException("invalid bandwidth");
-        } else {
-            this.bandwidth = bandwidth;
-        }
+        if (bandwidth < 0)
+            throw new IllegalArgumentException("invalid bandwidth: " + bandwidth);
+        this.bandwidth = bandwidth;
         return this;
     }
 
@@ -164,4 +187,18 @@
     public Status status() {
         return status;
     }
+
+    void status(int status) {
+        this.status = Status.from(status);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(super.toString());
+        sb.append(" [ priority=").append(priority())
+          .append(", bandwidth=").append(bandwidth())
+          .append(", status=").append(status())
+          .append(" ]");
+        return sb.toString();
+    }
 }
diff --git a/ojluni/src/main/java/sun/invoke/util/Wrapper.java b/ojluni/src/main/java/sun/invoke/util/Wrapper.java
index 0a0d04b..a9005ed 100644
--- a/ojluni/src/main/java/sun/invoke/util/Wrapper.java
+++ b/ojluni/src/main/java/sun/invoke/util/Wrapper.java
@@ -26,50 +26,51 @@
 package sun.invoke.util;
 
 public enum Wrapper {
-    //        wrapperType    primitiveType  char            zero         emptyArray          format
-    BOOLEAN(  Boolean.class, boolean.class, 'Z',      (Boolean)false, new boolean[0], Format.unsigned( 1)),
+    //        wrapperType      simple     primitiveType  simple     char  emptyArray     format
+    BOOLEAN(  Boolean.class,   "Boolean", boolean.class, "boolean", 'Z', new boolean[0], Format.unsigned( 1)),
     // These must be in the order defined for widening primitive conversions in JLS 5.1.2
-    BYTE   (     Byte.class,    byte.class, 'B',       (Byte)(byte)0, new    byte[0], Format.signed(   8)),
-    SHORT  (    Short.class,   short.class, 'S',     (Short)(short)0, new   short[0], Format.signed(  16)),
-    CHAR   (Character.class,    char.class, 'C',  (Character)(char)0, new    char[0], Format.unsigned(16)),
-    INT    (  Integer.class,     int.class, 'I', (Integer)/*(int)*/0, new     int[0], Format.signed(  32)),
-    LONG   (     Long.class,    long.class, 'J',       (Long)(long)0, new    long[0], Format.signed(  64)),
-    FLOAT  (    Float.class,   float.class, 'F',     (Float)(float)0, new   float[0], Format.floating(32)),
-    DOUBLE (   Double.class,  double.class, 'D',   (Double)(double)0, new  double[0], Format.floating(64)),
-    OBJECT (   Object.class,  Object.class, 'L',                null, new  Object[0], Format.other(    1)),
+    // Avoid boxing integral types here to defer initialization of internal caches
+    BYTE   (     Byte.class,      "Byte",    byte.class,    "byte", 'B', new    byte[0], Format.signed(   8)),
+    SHORT  (    Short.class,     "Short",   short.class,   "short", 'S', new   short[0], Format.signed(  16)),
+    CHAR   (Character.class, "Character",    char.class,    "char", 'C', new    char[0], Format.unsigned(16)),
+    INT    (  Integer.class,   "Integer",     int.class,     "int", 'I', new     int[0], Format.signed(  32)),
+    LONG   (     Long.class,      "Long",    long.class,    "long", 'J', new    long[0], Format.signed(  64)),
+    FLOAT  (    Float.class,     "Float",   float.class,   "float", 'F', new   float[0], Format.floating(32)),
+    DOUBLE (   Double.class,    "Double",  double.class,  "double", 'D', new  double[0], Format.floating(64)),
+    OBJECT (   Object.class,    "Object",  Object.class,  "Object", 'L', new  Object[0], Format.other(    1)),
     // VOID must be the last type, since it is "assignable" from any other type:
-    VOID   (     Void.class,    void.class, 'V',                null,           null, Format.other(    0)),
+    VOID   (     Void.class,      "Void",    void.class,    "void", 'V',           null, Format.other(    0)),
     ;
 
+    public static final int COUNT = 10;
+
     private final Class<?> wrapperType;
     private final Class<?> primitiveType;
     private final char     basicTypeChar;
-    private final Object   zero;
     private final Object   emptyArray;
     private final int      format;
     private final String   wrapperSimpleName;
     private final String   primitiveSimpleName;
 
-    private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) {
+    private Wrapper(Class<?> wtype, String wtypeName, Class<?> ptype, String ptypeName, char tchar, Object emptyArray, int format) {
         this.wrapperType = wtype;
         this.primitiveType = ptype;
         this.basicTypeChar = tchar;
-        this.zero = zero;
         this.emptyArray = emptyArray;
         this.format = format;
-        this.wrapperSimpleName = wtype.getSimpleName();
-        this.primitiveSimpleName = ptype.getSimpleName();
+        this.wrapperSimpleName = wtypeName;
+        this.primitiveSimpleName = ptypeName;
     }
 
     /** For debugging, give the details of this wrapper. */
     public String detailString() {
         return wrapperSimpleName+
                 java.util.Arrays.asList(wrapperType, primitiveType,
-                basicTypeChar, zero,
+                basicTypeChar, zero(),
                 "0x"+Integer.toHexString(format));
     }
 
-    private static abstract class Format {
+    private abstract static class Format {
         static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
         static final int
                 SIGNED   = (-1) << KIND_SHIFT,
@@ -161,7 +162,10 @@
         return true;
     }
 
-    static { assert(checkConvertibleFrom()); }
+    static {
+        assert(checkConvertibleFrom());
+        assert(COUNT == Wrapper.values().length);
+    }
     private static boolean checkConvertibleFrom() {
         // Check the matrix for correct classification of widening conversions.
         for (Wrapper w : values()) {
@@ -222,13 +226,39 @@
      *  type.  (For void, it is what a reflective method returns
      *  instead of no value at all.)
      */
-    public Object zero() { return zero; }
+    public Object zero() {
+        switch (this) {
+            case BOOLEAN:
+                return Boolean.FALSE;
+            case INT:
+                return (Integer)0;
+            case BYTE:
+                return (Byte)(byte)0;
+            case CHAR:
+                return (Character)(char)0;
+            case SHORT:
+                return (Short)(short)0;
+            case LONG:
+                return (Long)(long)0;
+            case FLOAT:
+                return FLOAT_ZERO;
+            case DOUBLE:
+                return DOUBLE_ZERO;
+            case VOID:
+            case OBJECT:
+            default:
+                return null;
+        }
+    }
+
+    private static final Object DOUBLE_ZERO = (Double)(double)0;
+    private static final Object FLOAT_ZERO = (Float)(float)0;
 
     /** Produce a zero value for the given wrapper type T.
      *  The optional argument must a type compatible with this wrapper.
      *  Equivalent to {@code this.cast(this.zero(), type)}.
      */
-    public <T> T zero(Class<T> type) { return convert(zero, type); }
+    public <T> T zero(Class<T> type) { return convert(zero(), type); }
 
     /** Return the wrapper that wraps values of the given type.
      *  The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
@@ -243,6 +273,25 @@
         throw newIllegalArgumentException("not primitive: "+type);
     }
 
+    /** Return the wrapper that corresponds to the provided basic type char.
+     *  The basic type char must be for one of the eight primitive types, or void.
+     *  @throws IllegalArgumentException for unexpected types
+     */
+    public static Wrapper forPrimitiveType(char basicTypeChar) {
+        switch (basicTypeChar) {
+            case 'I': return INT;
+            case 'J': return LONG;
+            case 'S': return SHORT;
+            case 'B': return BYTE;
+            case 'C': return CHAR;
+            case 'F': return FLOAT;
+            case 'D': return DOUBLE;
+            case 'Z': return BOOLEAN;
+            case 'V': return VOID;
+            default: throw newIllegalArgumentException("not primitive: " + basicTypeChar);
+        }
+    }
+
     static Wrapper findPrimitiveType(Class<?> type) {
         Wrapper w = FROM_PRIM[hashPrim(type)];
         if (w != null && w.primitiveType == type) {
@@ -473,7 +522,7 @@
             }
         } else if (x == null) {
             @SuppressWarnings("unchecked")
-            T z = (T) zero;
+            T z = (T) zero();
             return z;
         }
         @SuppressWarnings("unchecked")
@@ -488,12 +537,6 @@
      * If the target type is a primitive, change it to a wrapper.
      */
     static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
-        boolean z = (type == exampleType ||
-               type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
-               exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
-               type == Object.class && !exampleType.isPrimitive());
-        if (!z)
-            System.out.println(type+" <= "+exampleType);
         assert(type == exampleType ||
                type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
                exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
diff --git a/ojluni/src/main/java/sun/misc/DoubleConsts.java b/ojluni/src/main/java/sun/misc/DoubleConsts.java
deleted file mode 100644
index 2c5964b..0000000
--- a/ojluni/src/main/java/sun/misc/DoubleConsts.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * This class contains additional constants documenting limits of the
- * <code>double</code> type.
- *
- * @author Joseph D. Darcy
- */
-
-public class DoubleConsts {
-    /**
-     * Don't let anyone instantiate this class.
-     */
-    private DoubleConsts() {}
-
-    public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
-    public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
-    public static final double NaN = java.lang.Double.NaN;
-    public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
-    public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
-
-    /**
-     * A constant holding the smallest positive normal value of type
-     * <code>double</code>, 2<sup>-1022</sup>.  It is equal to the
-     * value returned by
-     * <code>Double.longBitsToDouble(0x0010000000000000L)</code>.
-     *
-     * @since 1.5
-     */
-    public static final double  MIN_NORMAL      = 2.2250738585072014E-308;
-
-
-    /**
-     * The number of logical bits in the significand of a
-     * <code>double</code> number, including the implicit bit.
-     */
-    public static final int SIGNIFICAND_WIDTH   = 53;
-
-    /**
-     * Maximum exponent a finite <code>double</code> number may have.
-     * It is equal to the value returned by
-     * <code>Math.ilogb(Double.MAX_VALUE)</code>.
-     */
-    public static final int     MAX_EXPONENT    = 1023;
-
-    /**
-     * Minimum exponent a normalized <code>double</code> number may
-     * have.  It is equal to the value returned by
-     * <code>Math.ilogb(Double.MIN_NORMAL)</code>.
-     */
-    public static final int     MIN_EXPONENT    = -1022;
-
-    /**
-     * The exponent the smallest positive <code>double</code>
-     * subnormal value would have if it could be normalized.  It is
-     * equal to the value returned by
-     * <code>FpUtils.ilogb(Double.MIN_VALUE)</code>.
-     */
-    public static final int     MIN_SUB_EXPONENT = MIN_EXPONENT -
-                                                   (SIGNIFICAND_WIDTH - 1);
-
-    /**
-     * Bias used in representing a <code>double</code> exponent.
-     */
-    public static final int     EXP_BIAS        = 1023;
-
-    /**
-     * Bit mask to isolate the sign bit of a <code>double</code>.
-     */
-    public static final long    SIGN_BIT_MASK   = 0x8000000000000000L;
-
-    /**
-     * Bit mask to isolate the exponent field of a
-     * <code>double</code>.
-     */
-    public static final long    EXP_BIT_MASK    = 0x7FF0000000000000L;
-
-    /**
-     * Bit mask to isolate the significand field of a
-     * <code>double</code>.
-     */
-    public static final long    SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;
-
-    static {
-        // verify bit masks cover all bit positions and that the bit
-        // masks are non-overlapping
-        assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) &&
-               (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) &&
-                ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) &&
-                ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L)));
-    }
-}
diff --git a/ojluni/src/main/java/sun/misc/FDBigInteger.java b/ojluni/src/main/java/sun/misc/FDBigInteger.java
deleted file mode 100644
index 77d6fbc..0000000
--- a/ojluni/src/main/java/sun/misc/FDBigInteger.java
+++ /dev/null
@@ -1,1508 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-//@ model import org.jmlspecs.models.JMLMath;
-
-/**
- * A simple big integer package specifically for floating point base conversion.
- */
-public /*@ spec_bigint_math @*/ class FDBigInteger {
-
-    //
-    // This class contains many comments that start with "/*@" mark.
-    // They are behavourial specification in
-    // the Java Modelling Language (JML):
-    // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
-    //
-
-    /*@
-    @ public pure model static \bigint UNSIGNED(int v) {
-    @     return v >= 0 ? v : v + (((\bigint)1) << 32);
-    @ }
-    @
-    @ public pure model static \bigint UNSIGNED(long v) {
-    @     return v >= 0 ? v : v + (((\bigint)1) << 64);
-    @ }
-    @
-    @ public pure model static \bigint AP(int[] data, int len) {
-    @     return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
-    @ }
-    @
-    @ public pure model static \bigint pow52(int p5, int p2) {
-    @     ghost \bigint v = 1;
-    @     for (int i = 0; i < p5; i++) v *= 5;
-    @     return v << p2;
-    @ }
-    @
-    @ public pure model static \bigint pow10(int p10) {
-    @     return pow52(p10, p10);
-    @ }
-    @*/
-
-    static final int[] SMALL_5_POW = {
-            1,
-            5,
-            5 * 5,
-            5 * 5 * 5,
-            5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
-    };
-
-    static final long[] LONG_5_POW = {
-            1L,
-            5L,
-            5L * 5,
-            5L * 5 * 5,
-            5L * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
-    };
-
-    // Maximum size of cache of powers of 5 as FDBigIntegers.
-    private static final int MAX_FIVE_POW = 340;
-
-    // Cache of big powers of 5 as FDBigIntegers.
-    private static final FDBigInteger POW_5_CACHE[];
-
-    // Initialize FDBigInteger cache of powers of 5.
-    static {
-        POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
-        int i = 0;
-        while (i < SMALL_5_POW.length) {
-            FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
-            pow5.makeImmutable();
-            POW_5_CACHE[i] = pow5;
-            i++;
-        }
-        FDBigInteger prev = POW_5_CACHE[i - 1];
-        while (i < MAX_FIVE_POW) {
-            POW_5_CACHE[i] = prev = prev.mult(5);
-            prev.makeImmutable();
-            i++;
-        }
-    }
-
-    // Zero as an FDBigInteger.
-    public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
-
-    // Ensure ZERO is immutable.
-    static {
-        ZERO.makeImmutable();
-    }
-
-    // Constant for casting an int to a long via bitwise AND.
-    private final static long LONG_MASK = 0xffffffffL;
-
-    //@ spec_public non_null;
-    private int data[];  // value: data[0] is least significant
-    //@ spec_public;
-    private int offset;  // number of least significant zero padding ints
-    //@ spec_public;
-    private int nWords;  // data[nWords-1]!=0, all values above are zero
-                 // if nWords==0 -> this FDBigInteger is zero
-    //@ spec_public;
-    private boolean isImmutable = false;
-
-    /*@
-     @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
-     @ public invariant nWords == 0 ==> offset == 0;
-     @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
-     @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
-     @ public pure model \bigint value() {
-     @     return AP(data, nWords) << (offset*32);
-     @ }
-     @*/
-
-    /**
-     * Constructs an <code>FDBigInteger</code> from data and padding. The
-     * <code>data</code> parameter has the least significant <code>int</code> at
-     * the zeroth index. The <code>offset</code> parameter gives the number of
-     * zero <code>int</code>s to be inferred below the least significant element
-     * of <code>data</code>.
-     *
-     * @param data An array containing all non-zero <code>int</code>s of the value.
-     * @param offset An offset indicating the number of zero <code>int</code>s to pad
-     * below the least significant element of <code>data</code>.
-     */
-    /*@
-     @ requires data != null && offset >= 0;
-     @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
-     @ ensures this.data == \old(data);
-     @*/
-    private FDBigInteger(int[] data, int offset) {
-        this.data = data;
-        this.offset = offset;
-        this.nWords = data.length;
-        trimLeadingZeros();
-    }
-
-    /**
-     * Constructs an <code>FDBigInteger</code> from a starting value and some
-     * decimal digits.
-     *
-     * @param lValue The starting value.
-     * @param digits The decimal digits.
-     * @param kDigits The initial index into <code>digits</code>.
-     * @param nDigits The final index into <code>digits</code>.
-     */
-    /*@
-     @ requires digits != null;
-     @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
-     @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
-     @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
-     @*/
-    public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
-        int n = Math.max((nDigits + 8) / 9, 2);        // estimate size needed.
-        data = new int[n];      // allocate enough space
-        data[0] = (int) lValue;    // starting value
-        data[1] = (int) (lValue >>> 32);
-        offset = 0;
-        nWords = 2;
-        int i = kDigits;
-        int limit = nDigits - 5;       // slurp digits 5 at a time.
-        int v;
-        while (i < limit) {
-            int ilim = i + 5;
-            v = (int) digits[i++] - (int) '0';
-            while (i < ilim) {
-                v = 10 * v + (int) digits[i++] - (int) '0';
-            }
-            multAddMe(100000, v); // ... where 100000 is 10^5.
-        }
-        int factor = 1;
-        v = 0;
-        while (i < nDigits) {
-            v = 10 * v + (int) digits[i++] - (int) '0';
-            factor *= 10;
-        }
-        if (factor != 1) {
-            multAddMe(factor, v);
-        }
-        trimLeadingZeros();
-    }
-
-    /**
-     * Returns an <code>FDBigInteger</code> with the numerical value
-     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
-     *
-     * @param p5 The exponent of the power-of-five factor.
-     * @param p2 The exponent of the power-of-two factor.
-     * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
-     */
-    /*@
-     @ requires p5 >= 0 && p2 >= 0;
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(pow52(p5, p2));
-     @*/
-    public static FDBigInteger valueOfPow52(int p5, int p2) {
-        if (p5 != 0) {
-            if (p2 == 0) {
-                return big5pow(p5);
-            } else if (p5 < SMALL_5_POW.length) {
-                int pow5 = SMALL_5_POW[p5];
-                int wordcount = p2 >> 5;
-                int bitcount = p2 & 0x1f;
-                if (bitcount == 0) {
-                    return new FDBigInteger(new int[]{pow5}, wordcount);
-                } else {
-                    return new FDBigInteger(new int[]{
-                            pow5 << bitcount,
-                            pow5 >>> (32 - bitcount)
-                    }, wordcount);
-                }
-            } else {
-                return big5pow(p5).leftShift(p2);
-            }
-        } else {
-            return valueOfPow2(p2);
-        }
-    }
-
-    /**
-     * Returns an <code>FDBigInteger</code> with the numerical value
-     * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
-     *
-     * @param value The constant factor.
-     * @param p5 The exponent of the power-of-five factor.
-     * @param p2 The exponent of the power-of-two factor.
-     * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
-     */
-    /*@
-     @ requires p5 >= 0 && p2 >= 0;
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
-     @*/
-    public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
-        assert p5 >= 0 : p5;
-        assert p2 >= 0 : p2;
-        int v0 = (int) value;
-        int v1 = (int) (value >>> 32);
-        int wordcount = p2 >> 5;
-        int bitcount = p2 & 0x1f;
-        if (p5 != 0) {
-            if (p5 < SMALL_5_POW.length) {
-                long pow5 = SMALL_5_POW[p5] & LONG_MASK;
-                long carry = (v0 & LONG_MASK) * pow5;
-                v0 = (int) carry;
-                carry >>>= 32;
-                carry = (v1 & LONG_MASK) * pow5 + carry;
-                v1 = (int) carry;
-                int v2 = (int) (carry >>> 32);
-                if (bitcount == 0) {
-                    return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
-                } else {
-                    return new FDBigInteger(new int[]{
-                            v0 << bitcount,
-                            (v1 << bitcount) | (v0 >>> (32 - bitcount)),
-                            (v2 << bitcount) | (v1 >>> (32 - bitcount)),
-                            v2 >>> (32 - bitcount)
-                    }, wordcount);
-                }
-            } else {
-                FDBigInteger pow5 = big5pow(p5);
-                int[] r;
-                if (v1 == 0) {
-                    r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
-                    mult(pow5.data, pow5.nWords, v0, r);
-                } else {
-                    r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
-                    mult(pow5.data, pow5.nWords, v0, v1, r);
-                }
-                return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
-            }
-        } else if (p2 != 0) {
-            if (bitcount == 0) {
-                return new FDBigInteger(new int[]{v0, v1}, wordcount);
-            } else {
-                return new FDBigInteger(new int[]{
-                         v0 << bitcount,
-                        (v1 << bitcount) | (v0 >>> (32 - bitcount)),
-                        v1 >>> (32 - bitcount)
-                }, wordcount);
-            }
-        }
-        return new FDBigInteger(new int[]{v0, v1}, 0);
-    }
-
-    /**
-     * Returns an <code>FDBigInteger</code> with the numerical value
-     * <code>2<sup>p2</sup></code>.
-     *
-     * @param p2 The exponent of 2.
-     * @return <code>2<sup>p2</sup></code>
-     */
-    /*@
-     @ requires p2 >= 0;
-     @ assignable \nothing;
-     @ ensures \result.value() == pow52(0, p2);
-     @*/
-    private static FDBigInteger valueOfPow2(int p2) {
-        int wordcount = p2 >> 5;
-        int bitcount = p2 & 0x1f;
-        return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
-    }
-
-    /**
-     * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
-     * the offset and number of non-zero leading words accordingly.
-     */
-    /*@
-     @ requires data != null;
-     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
-     @ requires nWords == 0 ==> offset == 0;
-     @ ensures nWords == 0 ==> offset == 0;
-     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
-     @*/
-    private /*@ helper @*/ void trimLeadingZeros() {
-        int i = nWords;
-        if (i > 0 && (data[--i] == 0)) {
-            //for (; i > 0 && data[i - 1] == 0; i--) ;
-            while(i > 0 && data[i - 1] == 0) {
-                i--;
-            }
-            this.nWords = i;
-            if (i == 0) { // all words are zero
-                this.offset = 0;
-            }
-        }
-    }
-
-    /**
-     * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
-     * normalization bias is a left shift such that after it the highest word
-     * of the value will have the 4 highest bits equal to zero:
-     * <code>(highestWord & 0xf0000000) == 0</code>, but the next bit should be 1
-     * <code>(highestWord & 0x08000000) != 0</code>.
-     *
-     * @return The normalization bias.
-     */
-    /*@
-     @ requires this.value() > 0;
-     @*/
-    public /*@ pure @*/ int getNormalizationBias() {
-        if (nWords == 0) {
-            throw new IllegalArgumentException("Zero value cannot be normalized");
-        }
-        int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
-        return (zeros < 4) ? 28 + zeros : zeros - 4;
-    }
-
-    // TODO: Why is anticount param needed if it is always 32 - bitcount?
-    /**
-     * Left shifts the contents of one int array into another.
-     *
-     * @param src The source array.
-     * @param idx The initial index of the source array.
-     * @param result The destination array.
-     * @param bitcount The left shift.
-     * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
-     * @param prev The prior source value.
-     */
-    /*@
-     @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
-     @ requires src.length >= idx && result.length > idx;
-     @ assignable result[*];
-     @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
-     @*/
-    private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
-        for (; idx > 0; idx--) {
-            int v = (prev << bitcount);
-            prev = src[idx - 1];
-            v |= (prev >>> anticount);
-            result[idx] = v;
-        }
-        int v = prev << bitcount;
-        result[0] = v;
-    }
-
-    /**
-     * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
-     * in-place unless the <code>FDBigInteger</code> is immutable in which case
-     * a new instance of <code>FDBigInteger</code> is returned.
-     *
-     * @param shift The number of bits to shift left.
-     * @return The shifted <code>FDBigInteger</code>.
-     */
-    /*@
-     @ requires this.value() == 0 || shift == 0;
-     @ assignable \nothing;
-     @ ensures \result == this;
-     @
-     @  also
-     @
-     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() << shift);
-     @
-     @  also
-     @
-     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
-     @ assignable \nothing;
-     @ ensures \result == this;
-     @ ensures \result.value() == \old(this.value() << shift);
-     @*/
-    public FDBigInteger leftShift(int shift) {
-        if (shift == 0 || nWords == 0) {
-            return this;
-        }
-        int wordcount = shift >> 5;
-        int bitcount = shift & 0x1f;
-        if (this.isImmutable) {
-            if (bitcount == 0) {
-                return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
-            } else {
-                int anticount = 32 - bitcount;
-                int idx = nWords - 1;
-                int prev = data[idx];
-                int hi = prev >>> anticount;
-                int[] result;
-                if (hi != 0) {
-                    result = new int[nWords + 1];
-                    result[nWords] = hi;
-                } else {
-                    result = new int[nWords];
-                }
-                leftShift(data,idx,result,bitcount,anticount,prev);
-                return new FDBigInteger(result, offset + wordcount);
-            }
-        } else {
-            if (bitcount != 0) {
-                int anticount = 32 - bitcount;
-                if ((data[0] << bitcount) == 0) {
-                    int idx = 0;
-                    int prev = data[idx];
-                    for (; idx < nWords - 1; idx++) {
-                        int v = (prev >>> anticount);
-                        prev = data[idx + 1];
-                        v |= (prev << bitcount);
-                        data[idx] = v;
-                    }
-                    int v = prev >>> anticount;
-                    data[idx] = v;
-                    if(v==0) {
-                        nWords--;
-                    }
-                    offset++;
-                } else {
-                    int idx = nWords - 1;
-                    int prev = data[idx];
-                    int hi = prev >>> anticount;
-                    int[] result = data;
-                    int[] src = data;
-                    if (hi != 0) {
-                        if(nWords == data.length) {
-                            data = result = new int[nWords + 1];
-                        }
-                        result[nWords++] = hi;
-                    }
-                    leftShift(src,idx,result,bitcount,anticount,prev);
-                }
-            }
-            offset += wordcount;
-            return this;
-        }
-    }
-
-    /**
-     * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
-     *
-     * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
-     */
-    /*@
-     @ requires this.value() == 0;
-     @ ensures \result == 0;
-     @
-     @  also
-     @
-     @ requires this.value() > 0;
-     @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
-     @*/
-    private /*@ pure @*/ int size() {
-        return nWords + offset;
-    }
-
-
-    /**
-     * Computes
-     * <pre>
-     * q = (int)( this / S )
-     * this = 10 * ( this mod S )
-     * Return q.
-     * </pre>
-     * This is the iteration step of digit development for output.
-     * We assume that S has been normalized, as above, and that
-     * "this" has been left-shifted accordingly.
-     * Also assumed, of course, is that the result, q, can be expressed
-     * as an integer, 0 <= q < 10.
-     *
-     * @param The divisor of this <code>FDBigInteger</code>.
-     * @return <code>q = (int)(this / S)</code>.
-     */
-    /*@
-     @ requires !this.isImmutable;
-     @ requires this.size() <= S.size();
-     @ requires this.data.length + this.offset >= S.size();
-     @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
-     @ assignable this.nWords, this.offset, this.data, this.data[*];
-     @ ensures \result == \old(this.value() / S.value());
-     @ ensures this.value() == \old(10 * (this.value() % S.value()));
-     @*/
-    public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
-        assert !this.isImmutable : "cannot modify immutable value";
-        // ensure that this and S have the same number of
-        // digits. If S is properly normalized and q < 10 then
-        // this must be so.
-        int thSize = this.size();
-        int sSize = S.size();
-        if (thSize < sSize) {
-            // this value is significantly less than S, result of division is zero.
-            // just mult this by 10.
-            int p = multAndCarryBy10(this.data, this.nWords, this.data);
-            if(p!=0) {
-                this.data[nWords++] = p;
-            } else {
-                trimLeadingZeros();
-            }
-            return 0;
-        } else if (thSize > sSize) {
-            throw new IllegalArgumentException("disparate values");
-        }
-        // estimate q the obvious way. We will usually be
-        // right. If not, then we're only off by a little and
-        // will re-add.
-        long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
-        long diff = multDiffMe(q, S);
-        if (diff != 0L) {
-            //@ assert q != 0;
-            //@ assert this.offset == \old(Math.min(this.offset, S.offset));
-            //@ assert this.offset <= S.offset;
-
-            // q is too big.
-            // add S back in until this turns +. This should
-            // not be very many times!
-            long sum = 0L;
-            int tStart = S.offset - this.offset;
-            //@ assert tStart >= 0;
-            int[] sd = S.data;
-            int[] td = this.data;
-            while (sum == 0L) {
-                for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
-                    sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
-                    td[tIndex] = (int) sum;
-                    sum >>>= 32; // Signed or unsigned, answer is 0 or 1
-                }
-                //
-                // Originally the following line read
-                // "if ( sum !=0 && sum != -1 )"
-                // but that would be wrong, because of the
-                // treatment of the two values as entirely unsigned,
-                // it would be impossible for a carry-out to be interpreted
-                // as -1 -- it would have to be a single-bit carry-out, or +1.
-                //
-                assert sum == 0 || sum == 1 : sum; // carry out of division correction
-                q -= 1;
-            }
-        }
-        // finally, we can multiply this by 10.
-        // it cannot overflow, right, as the high-order word has
-        // at least 4 high-order zeros!
-        int p = multAndCarryBy10(this.data, this.nWords, this.data);
-        assert p == 0 : p; // Carry out of *10
-        trimLeadingZeros();
-        return (int) q;
-    }
-
-    /**
-     * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
-     * performed in place unless the <code>FDBigInteger</code> is immutable in
-     * which case a new <code>FDBigInteger</code> will be returned.
-     *
-     * @return The <code>FDBigInteger</code> multiplied by 10.
-     */
-    /*@
-     @ requires this.value() == 0;
-     @ assignable \nothing;
-     @ ensures \result == this;
-     @
-     @  also
-     @
-     @ requires this.value() > 0 && this.isImmutable;
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() * 10);
-     @
-     @  also
-     @
-     @ requires this.value() > 0 && !this.isImmutable;
-     @ assignable this.nWords, this.data, this.data[*];
-     @ ensures \result == this;
-     @ ensures \result.value() == \old(this.value() * 10);
-     @*/
-    public FDBigInteger multBy10() {
-        if (nWords == 0) {
-            return this;
-        }
-        if (isImmutable) {
-            int[] res = new int[nWords + 1];
-            res[nWords] = multAndCarryBy10(data, nWords, res);
-            return new FDBigInteger(res, offset);
-        } else {
-            int p = multAndCarryBy10(this.data, this.nWords, this.data);
-            if (p != 0) {
-                if (nWords == data.length) {
-                    if (data[0] == 0) {
-                        System.arraycopy(data, 1, data, 0, --nWords);
-                        offset++;
-                    } else {
-                        data = Arrays.copyOf(data, data.length + 1);
-                    }
-                }
-                data[nWords++] = p;
-            } else {
-                trimLeadingZeros();
-            }
-            return this;
-        }
-    }
-
-    /**
-     * Multiplies this <code>FDBigInteger</code> by
-     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
-     * performed in place if possible, otherwise a new <code>FDBigInteger</code>
-     * will be returned.
-     *
-     * @param p5 The exponent of the power-of-five factor.
-     * @param p2 The exponent of the power-of-two factor.
-     * @return
-     */
-    /*@
-     @ requires this.value() == 0 || p5 == 0 && p2 == 0;
-     @ assignable \nothing;
-     @ ensures \result == this;
-     @
-     @  also
-     @
-     @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
-     @
-     @  also
-     @
-     @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
-     @ assignable this.nWords, this.data, this.data[*];
-     @ ensures \result == this;
-     @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
-     @*/
-    public FDBigInteger multByPow52(int p5, int p2) {
-        if (this.nWords == 0) {
-            return this;
-        }
-        FDBigInteger res = this;
-        if (p5 != 0) {
-            int[] r;
-            int extraSize = (p2 != 0) ? 1 : 0;
-            if (p5 < SMALL_5_POW.length) {
-                r = new int[this.nWords + 1 + extraSize];
-                mult(this.data, this.nWords, SMALL_5_POW[p5], r);
-                res = new FDBigInteger(r, this.offset);
-            } else {
-                FDBigInteger pow5 = big5pow(p5);
-                r = new int[this.nWords + pow5.size() + extraSize];
-                mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
-                res = new FDBigInteger(r, this.offset + pow5.offset);
-            }
-        }
-        return res.leftShift(p2);
-    }
-
-    /**
-     * Multiplies two big integers represented as int arrays.
-     *
-     * @param s1 The first array factor.
-     * @param s1Len The number of elements of <code>s1</code> to use.
-     * @param s2 The second array factor.
-     * @param s2Len The number of elements of <code>s2</code> to use.
-     * @param dst The product array.
-     */
-    /*@
-     @ requires s1 != dst && s2 != dst;
-     @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
-     @ assignable dst[0 .. s1Len + s2Len - 1];
-     @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
-     @*/
-    private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
-        for (int i = 0; i < s1Len; i++) {
-            long v = s1[i] & LONG_MASK;
-            long p = 0L;
-            for (int j = 0; j < s2Len; j++) {
-                p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
-                dst[i + j] = (int) p;
-                p >>>= 32;
-            }
-            dst[i + s2Len] = (int) p;
-        }
-    }
-
-    /**
-     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
-     * <code>FDBigInteger</code>. Assert that the result is positive.
-     * If the subtrahend is immutable, store the result in this(minuend).
-     * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
-     *
-     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
-     * @return This <code>FDBigInteger</code> less the subtrahend.
-     */
-    /*@
-     @ requires this.isImmutable;
-     @ requires this.value() >= subtrahend.value();
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() - subtrahend.value());
-     @
-     @  also
-     @
-     @ requires !subtrahend.isImmutable;
-     @ requires this.value() >= subtrahend.value();
-     @ assignable this.nWords, this.offset, this.data, this.data[*];
-     @ ensures \result == this;
-     @ ensures \result.value() == \old(this.value() - subtrahend.value());
-     @*/
-    public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
-        assert this.size() >= subtrahend.size() : "result should be positive";
-        FDBigInteger minuend;
-        if (this.isImmutable) {
-            minuend = new FDBigInteger(this.data.clone(), this.offset);
-        } else {
-            minuend = this;
-        }
-        int offsetDiff = subtrahend.offset - minuend.offset;
-        int[] sData = subtrahend.data;
-        int[] mData = minuend.data;
-        int subLen = subtrahend.nWords;
-        int minLen = minuend.nWords;
-        if (offsetDiff < 0) {
-            // need to expand minuend
-            int rLen = minLen - offsetDiff;
-            if (rLen < mData.length) {
-                System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
-                Arrays.fill(mData, 0, -offsetDiff, 0);
-            } else {
-                int[] r = new int[rLen];
-                System.arraycopy(mData, 0, r, -offsetDiff, minLen);
-                minuend.data = mData = r;
-            }
-            minuend.offset = subtrahend.offset;
-            minuend.nWords = minLen = rLen;
-            offsetDiff = 0;
-        }
-        long borrow = 0L;
-        int mIndex = offsetDiff;
-        for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
-            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
-            mData[mIndex] = (int) diff;
-            borrow = diff >> 32; // signed shift
-        }
-        for (; borrow != 0 && mIndex < minLen; mIndex++) {
-            long diff = (mData[mIndex] & LONG_MASK) + borrow;
-            mData[mIndex] = (int) diff;
-            borrow = diff >> 32; // signed shift
-        }
-        assert borrow == 0L : borrow; // borrow out of subtract,
-        // result should be positive
-        minuend.trimLeadingZeros();
-        return minuend;
-    }
-
-    /**
-     * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
-     * <code>FDBigInteger</code>. Assert that the result is positive.
-     * If the this(minuend) is immutable, store the result in subtrahend.
-     * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
-     *
-     * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
-     * @return This <code>FDBigInteger</code> less the subtrahend.
-     */
-    /*@
-     @ requires subtrahend.isImmutable;
-     @ requires this.value() >= subtrahend.value();
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() - subtrahend.value());
-     @
-     @  also
-     @
-     @ requires !subtrahend.isImmutable;
-     @ requires this.value() >= subtrahend.value();
-     @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
-     @ ensures \result == subtrahend;
-     @ ensures \result.value() == \old(this.value() - subtrahend.value());
-     @*/
-    public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
-        assert this.size() >= subtrahend.size() : "result should be positive";
-        FDBigInteger minuend = this;
-        if (subtrahend.isImmutable) {
-            subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
-        }
-        int offsetDiff = minuend.offset - subtrahend.offset;
-        int[] sData = subtrahend.data;
-        int[] mData = minuend.data;
-        int subLen = subtrahend.nWords;
-        int minLen = minuend.nWords;
-        if (offsetDiff < 0) {
-            int rLen = minLen;
-            if (rLen < sData.length) {
-                System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
-                Arrays.fill(sData, 0, -offsetDiff, 0);
-            } else {
-                int[] r = new int[rLen];
-                System.arraycopy(sData, 0, r, -offsetDiff, subLen);
-                subtrahend.data = sData = r;
-            }
-            subtrahend.offset = minuend.offset;
-            subLen -= offsetDiff;
-            offsetDiff = 0;
-        } else {
-            int rLen = minLen + offsetDiff;
-            if (rLen >= sData.length) {
-                subtrahend.data = sData = Arrays.copyOf(sData, rLen);
-            }
-        }
-        //@ assert minuend == this && minuend.value() == \old(this.value());
-        //@ assert mData == minuend.data && minLen == minuend.nWords;
-        //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
-        //@ assert sData == subtrahend.data;
-        //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
-        //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
-        //@ assert offsetDiff == minuend.offset - subtrahend.offset;
-        //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
-        int sIndex = 0;
-        long borrow = 0L;
-        for (; sIndex < offsetDiff; sIndex++) {
-            long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
-            sData[sIndex] = (int) diff;
-            borrow = diff >> 32; // signed shift
-        }
-        //@ assert sIndex == offsetDiff;
-        for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
-            //@ assert sIndex == offsetDiff + mIndex;
-            long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
-            sData[sIndex] = (int) diff;
-            borrow = diff >> 32; // signed shift
-        }
-        assert borrow == 0L : borrow; // borrow out of subtract,
-        // result should be positive
-        subtrahend.nWords = sIndex;
-        subtrahend.trimLeadingZeros();
-        return subtrahend;
-
-    }
-
-    /**
-     * Determines whether all elements of an array are zero for all indices less
-     * than a given index.
-     *
-     * @param a The array to be examined.
-     * @param from The index strictly below which elements are to be examined.
-     * @return Zero if all elements in range are zero, 1 otherwise.
-     */
-    /*@
-     @ requires 0 <= from && from <= a.length;
-     @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
-     @*/
-    private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
-        while (from > 0) {
-            if (a[--from] != 0) {
-                return 1;
-            }
-        }
-        return 0;
-    }
-
-    /**
-     * Compares the parameter with this <code>FDBigInteger</code>. Returns an
-     * integer accordingly as:
-     * <pre>
-     * >0: this > other
-     *  0: this == other
-     * <0: this < other
-     * </pre>
-     *
-     * @param other The <code>FDBigInteger</code> to compare.
-     * @return A negative value, zero, or a positive value according to the
-     * result of the comparison.
-     */
-    /*@
-     @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
-     @*/
-    public /*@ pure @*/ int cmp(FDBigInteger other) {
-        int aSize = nWords + offset;
-        int bSize = other.nWords + other.offset;
-        if (aSize > bSize) {
-            return 1;
-        } else if (aSize < bSize) {
-            return -1;
-        }
-        int aLen = nWords;
-        int bLen = other.nWords;
-        while (aLen > 0 && bLen > 0) {
-            int a = data[--aLen];
-            int b = other.data[--bLen];
-            if (a != b) {
-                return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
-            }
-        }
-        if (aLen > 0) {
-            return checkZeroTail(data, aLen);
-        }
-        if (bLen > 0) {
-            return -checkZeroTail(other.data, bLen);
-        }
-        return 0;
-    }
-
-    /**
-     * Compares this <code>FDBigInteger</code> with
-     * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
-     * Returns an integer accordingly as:
-     * <pre>
-     * >0: this > other
-     *  0: this == other
-     * <0: this < other
-     * </pre>
-     * @param p5 The exponent of the power-of-five factor.
-     * @param p2 The exponent of the power-of-two factor.
-     * @return A negative value, zero, or a positive value according to the
-     * result of the comparison.
-     */
-    /*@
-     @ requires p5 >= 0 && p2 >= 0;
-     @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() >  pow52(p5, p2) ? +1 : 0);
-     @*/
-    public /*@ pure @*/ int cmpPow52(int p5, int p2) {
-        if (p5 == 0) {
-            int wordcount = p2 >> 5;
-            int bitcount = p2 & 0x1f;
-            int size = this.nWords + this.offset;
-            if (size > wordcount + 1) {
-                return 1;
-            } else if (size < wordcount + 1) {
-                return -1;
-            }
-            int a = this.data[this.nWords -1];
-            int b = 1 << bitcount;
-            if (a != b) {
-                return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
-            }
-            return checkZeroTail(this.data, this.nWords - 1);
-        }
-        return this.cmp(big5pow(p5).leftShift(p2));
-    }
-
-    /**
-     * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
-     * value according to the comparison as:
-     * <pre>
-     * -1: this <  x + y
-     *  0: this == x + y
-     *  1: this >  x + y
-     * </pre>
-     * @param x The first addend of the sum to compare.
-     * @param y The second addend of the sum to compare.
-     * @return -1, 0, or 1 according to the result of the comparison.
-     */
-    /*@
-     @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
-     @*/
-    public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
-        FDBigInteger big;
-        FDBigInteger small;
-        int xSize = x.size();
-        int ySize = y.size();
-        int bSize;
-        int sSize;
-        if (xSize >= ySize) {
-            big = x;
-            small = y;
-            bSize = xSize;
-            sSize = ySize;
-        } else {
-            big = y;
-            small = x;
-            bSize = ySize;
-            sSize = xSize;
-        }
-        int thSize = this.size();
-        if (bSize == 0) {
-            return thSize == 0 ? 0 : 1;
-        }
-        if (sSize == 0) {
-            return this.cmp(big);
-        }
-        if (bSize > thSize) {
-            return -1;
-        }
-        if (bSize + 1 < thSize) {
-            return 1;
-        }
-        long top = (big.data[big.nWords - 1] & LONG_MASK);
-        if (sSize == bSize) {
-            top += (small.data[small.nWords - 1] & LONG_MASK);
-        }
-        if ((top >>> 32) == 0) {
-            if (((top + 1) >>> 32) == 0) {
-                // good case - no carry extension
-                if (bSize < thSize) {
-                    return 1;
-                }
-                // here sum.nWords == this.nWords
-                long v = (this.data[this.nWords - 1] & LONG_MASK);
-                if (v < top) {
-                    return -1;
-                }
-                if (v > top + 1) {
-                    return 1;
-                }
-            }
-        } else { // (top>>>32)!=0 guaranteed carry extension
-            if (bSize + 1 > thSize) {
-                return -1;
-            }
-            // here sum.nWords == this.nWords
-            top >>>= 32;
-            long v = (this.data[this.nWords - 1] & LONG_MASK);
-            if (v < top) {
-                return -1;
-            }
-            if (v > top + 1) {
-                return 1;
-            }
-        }
-        return this.cmp(big.add(small));
-    }
-
-    /**
-     * Makes this <code>FDBigInteger</code> immutable.
-     */
-    /*@
-     @ assignable this.isImmutable;
-     @ ensures this.isImmutable;
-     @*/
-    public void makeImmutable() {
-        this.isImmutable = true;
-    }
-
-    /**
-     * Multiplies this <code>FDBigInteger</code> by an integer.
-     *
-     * @param i The factor by which to multiply this <code>FDBigInteger</code>.
-     * @return This <code>FDBigInteger</code> multiplied by an integer.
-     */
-    /*@
-     @ requires this.value() == 0;
-     @ assignable \nothing;
-     @ ensures \result == this;
-     @
-     @  also
-     @
-     @ requires this.value() != 0;
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
-     @*/
-    private FDBigInteger mult(int i) {
-        if (this.nWords == 0) {
-            return this;
-        }
-        int[] r = new int[nWords + 1];
-        mult(data, nWords, i, r);
-        return new FDBigInteger(r, offset);
-    }
-
-    /**
-     * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
-     *
-     * @param other The <code>FDBigInteger</code> factor by which to multiply.
-     * @return The product of this and the parameter <code>FDBigInteger</code>s.
-     */
-    /*@
-     @ requires this.value() == 0;
-     @ assignable \nothing;
-     @ ensures \result == this;
-     @
-     @  also
-     @
-     @ requires this.value() != 0 && other.value() == 0;
-     @ assignable \nothing;
-     @ ensures \result == other;
-     @
-     @  also
-     @
-     @ requires this.value() != 0 && other.value() != 0;
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() * other.value());
-     @*/
-    private FDBigInteger mult(FDBigInteger other) {
-        if (this.nWords == 0) {
-            return this;
-        }
-        if (this.size() == 1) {
-            return other.mult(data[0]);
-        }
-        if (other.nWords == 0) {
-            return other;
-        }
-        if (other.size() == 1) {
-            return this.mult(other.data[0]);
-        }
-        int[] r = new int[nWords + other.nWords];
-        mult(this.data, this.nWords, other.data, other.nWords, r);
-        return new FDBigInteger(r, this.offset + other.offset);
-    }
-
-    /**
-     * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
-     *
-     * @param other The <code>FDBigInteger</code> to add.
-     * @return The sum of the <code>FDBigInteger</code>s.
-     */
-    /*@
-     @ assignable \nothing;
-     @ ensures \result.value() == \old(this.value() + other.value());
-     @*/
-    private FDBigInteger add(FDBigInteger other) {
-        FDBigInteger big, small;
-        int bigLen, smallLen;
-        int tSize = this.size();
-        int oSize = other.size();
-        if (tSize >= oSize) {
-            big = this;
-            bigLen = tSize;
-            small = other;
-            smallLen = oSize;
-        } else {
-            big = other;
-            bigLen = oSize;
-            small = this;
-            smallLen = tSize;
-        }
-        int[] r = new int[bigLen + 1];
-        int i = 0;
-        long carry = 0L;
-        for (; i < smallLen; i++) {
-            carry += (i < big.offset   ? 0L : (big.data[i - big.offset] & LONG_MASK) )
-                   + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
-            r[i] = (int) carry;
-            carry >>= 32; // signed shift.
-        }
-        for (; i < bigLen; i++) {
-            carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
-            r[i] = (int) carry;
-            carry >>= 32; // signed shift.
-        }
-        r[bigLen] = (int) carry;
-        return new FDBigInteger(r, 0);
-    }
-
-
-    /**
-     * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
-     * result is computed in place. This method is intended only to be invoked
-     * from
-     * <code>
-     * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
-     * </code>.
-     *
-     * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
-     * @param addend The value to add to the product of this
-     * <code>FDBigInteger</code> and <code>iv</code>.
-     */
-    /*@
-     @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
-     @ assignable this.data[*];
-     @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
-     @*/
-    private /*@ helper @*/ void multAddMe(int iv, int addend) {
-        long v = iv & LONG_MASK;
-        // unroll 0th iteration, doing addition.
-        long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
-        data[0] = (int) p;
-        p >>>= 32;
-        for (int i = 1; i < nWords; i++) {
-            p += v * (data[i] & LONG_MASK);
-            data[i] = (int) p;
-            p >>>= 32;
-        }
-        if (p != 0L) {
-            data[nWords++] = (int) p; // will fail noisily if illegal!
-        }
-    }
-
-    //
-    // original doc:
-    //
-    // do this -=q*S
-    // returns borrow
-    //
-    /**
-     * Multiplies the parameters and subtracts them from this
-     * <code>FDBigInteger</code>.
-     *
-     * @param q The integer parameter.
-     * @param S The <code>FDBigInteger</code> parameter.
-     * @return <code>this - q*S</code>.
-     */
-    /*@
-     @ ensures nWords == 0 ==> offset == 0;
-     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
-     @*/
-    /*@
-     @ requires 0 < q && q <= (1L << 31);
-     @ requires data != null;
-     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
-     @ requires !this.isImmutable;
-     @ requires this.size() == S.size();
-     @ requires this != S;
-     @ assignable this.nWords, this.offset, this.data, this.data[*];
-     @ ensures -q <= \result && \result <= 0;
-     @ ensures this.size() == \old(this.size());
-     @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
-     @ ensures this.offset == \old(Math.min(this.offset, S.offset));
-     @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
-     @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
-     @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
-     @
-     @  also
-     @
-     @ requires q == 0;
-     @ assignable \nothing;
-     @ ensures \result == 0;
-     @*/
-    private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
-        long diff = 0L;
-        if (q != 0) {
-            int deltaSize = S.offset - this.offset;
-            if (deltaSize >= 0) {
-                int[] sd = S.data;
-                int[] td = this.data;
-                for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
-                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
-                    td[tIndex] = (int) diff;
-                    diff >>= 32; // N.B. SIGNED shift.
-                }
-            } else {
-                deltaSize = -deltaSize;
-                int[] rd = new int[nWords + deltaSize];
-                int sIndex = 0;
-                int rIndex = 0;
-                int[] sd = S.data;
-                for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
-                    diff -= q * (sd[sIndex] & LONG_MASK);
-                    rd[rIndex] = (int) diff;
-                    diff >>= 32; // N.B. SIGNED shift.
-                }
-                int tIndex = 0;
-                int[] td = this.data;
-                for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
-                    diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
-                    rd[rIndex] = (int) diff;
-                    diff >>= 32; // N.B. SIGNED shift.
-                }
-                this.nWords += deltaSize;
-                this.offset -= deltaSize;
-                this.data = rd;
-            }
-        }
-        return diff;
-    }
-
-
-    /**
-     * Multiplies by 10 a big integer represented as an array. The final carry
-     * is returned.
-     *
-     * @param src The array representation of the big integer.
-     * @param srcLen The number of elements of <code>src</code> to use.
-     * @param dst The product array.
-     * @return The final carry of the multiplication.
-     */
-    /*@
-     @ requires src.length >= srcLen && dst.length >= srcLen;
-     @ assignable dst[0 .. srcLen - 1];
-     @ ensures 0 <= \result && \result < 10;
-     @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
-     @*/
-    private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
-        long carry = 0;
-        for (int i = 0; i < srcLen; i++) {
-            long product = (src[i] & LONG_MASK) * 10L + carry;
-            dst[i] = (int) product;
-            carry = product >>> 32;
-        }
-        return (int) carry;
-    }
-
-    /**
-     * Multiplies by a constant value a big integer represented as an array.
-     * The constant factor is an <code>int</code>.
-     *
-     * @param src The array representation of the big integer.
-     * @param srcLen The number of elements of <code>src</code> to use.
-     * @param value The constant factor by which to multiply.
-     * @param dst The product array.
-     */
-    /*@
-     @ requires src.length >= srcLen && dst.length >= srcLen + 1;
-     @ assignable dst[0 .. srcLen];
-     @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
-     @*/
-    private static void mult(int[] src, int srcLen, int value, int[] dst) {
-        long val = value & LONG_MASK;
-        long carry = 0;
-        for (int i = 0; i < srcLen; i++) {
-            long product = (src[i] & LONG_MASK) * val + carry;
-            dst[i] = (int) product;
-            carry = product >>> 32;
-        }
-        dst[srcLen] = (int) carry;
-    }
-
-    /**
-     * Multiplies by a constant value a big integer represented as an array.
-     * The constant factor is a long represent as two <code>int</code>s.
-     *
-     * @param src The array representation of the big integer.
-     * @param srcLen The number of elements of <code>src</code> to use.
-     * @param v0 The lower 32 bits of the long factor.
-     * @param v1 The upper 32 bits of the long factor.
-     * @param dst The product array.
-     */
-    /*@
-     @ requires src != dst;
-     @ requires src.length >= srcLen && dst.length >= srcLen + 2;
-     @ assignable dst[0 .. srcLen + 1];
-     @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
-     @*/
-    private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
-        long v = v0 & LONG_MASK;
-        long carry = 0;
-        for (int j = 0; j < srcLen; j++) {
-            long product = v * (src[j] & LONG_MASK) + carry;
-            dst[j] = (int) product;
-            carry = product >>> 32;
-        }
-        dst[srcLen] = (int) carry;
-        v = v1 & LONG_MASK;
-        carry = 0;
-        for (int j = 0; j < srcLen; j++) {
-            long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
-            dst[j + 1] = (int) product;
-            carry = product >>> 32;
-        }
-        dst[srcLen + 1] = (int) carry;
-    }
-
-    // Fails assertion for negative exponent.
-    /**
-     * Computes <code>5</code> raised to a given power.
-     *
-     * @param p The exponent of 5.
-     * @return <code>5<sup>p</sup></code>.
-     */
-    private static FDBigInteger big5pow(int p) {
-        assert p >= 0 : p; // negative power of 5
-        if (p < MAX_FIVE_POW) {
-            return POW_5_CACHE[p];
-        }
-        return big5powRec(p);
-    }
-
-    // slow path
-    /**
-     * Computes <code>5</code> raised to a given power.
-     *
-     * @param p The exponent of 5.
-     * @return <code>5<sup>p</sup></code>.
-     */
-    private static FDBigInteger big5powRec(int p) {
-        if (p < MAX_FIVE_POW) {
-            return POW_5_CACHE[p];
-        }
-        // construct the value.
-        // recursively.
-        int q, r;
-        // in order to compute 5^p,
-        // compute its square root, 5^(p/2) and square.
-        // or, let q = p / 2, r = p -q, then
-        // 5^p = 5^(q+r) = 5^q * 5^r
-        q = p >> 1;
-        r = p - q;
-        FDBigInteger bigq = big5powRec(q);
-        if (r < SMALL_5_POW.length) {
-            return bigq.mult(SMALL_5_POW[r]);
-        } else {
-            return bigq.mult(big5powRec(r));
-        }
-    }
-
-    // for debugging ...
-    /**
-     * Converts this <code>FDBigInteger</code> to a hexadecimal string.
-     *
-     * @return The hexadecimal string representation.
-     */
-    public String toHexString(){
-        if(nWords ==0) {
-            return "0";
-        }
-        StringBuilder sb = new StringBuilder((nWords +offset)*8);
-        for(int i= nWords -1; i>=0; i--) {
-            String subStr = Integer.toHexString(data[i]);
-            for(int j = subStr.length(); j<8; j++) {
-                sb.append('0');
-            }
-            sb.append(subStr);
-        }
-        for(int i=offset; i>0; i--) {
-            sb.append("00000000");
-        }
-        return sb.toString();
-    }
-
-    // for debugging ...
-    /**
-     * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
-     *
-     * @return The <code>BigInteger</code> representation.
-     */
-    public BigInteger toBigInteger() {
-        byte[] magnitude = new byte[nWords * 4 + 1];
-        for (int i = 0; i < nWords; i++) {
-            int w = data[i];
-            magnitude[magnitude.length - 4 * i - 1] = (byte) w;
-            magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
-            magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
-            magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
-        }
-        return new BigInteger(magnitude).shiftLeft(offset * 32);
-    }
-
-    // for debugging ...
-    /**
-     * Converts this <code>FDBigInteger</code> to a string.
-     *
-     * @return The string representation.
-     */
-    @Override
-    public String toString(){
-        return toBigInteger().toString();
-    }
-}
diff --git a/ojluni/src/main/java/sun/misc/FloatConsts.java b/ojluni/src/main/java/sun/misc/FloatConsts.java
deleted file mode 100644
index 4345c19..0000000
--- a/ojluni/src/main/java/sun/misc/FloatConsts.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/**
- * This class contains additional constants documenting limits of the
- * <code>float</code> type.
- *
- * @author Joseph D. Darcy
- */
-
-public class FloatConsts {
-    /**
-     * Don't let anyone instantiate this class.
-     */
-    private FloatConsts() {}
-
-    public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
-    public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
-    public static final float NaN = java.lang.Float.NaN;
-    public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
-    public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
-
-    /**
-     * A constant holding the smallest positive normal value of type
-     * <code>float</code>, 2<sup>-126</sup>.  It is equal to the value
-     * returned by <code>Float.intBitsToFloat(0x00800000)</code>.
-     */
-    public static final float   MIN_NORMAL      = 1.17549435E-38f;
-
-    /**
-     * The number of logical bits in the significand of a
-     * <code>float</code> number, including the implicit bit.
-     */
-    public static final int SIGNIFICAND_WIDTH   = 24;
-
-    /**
-     * Maximum exponent a finite <code>float</code> number may have.
-     * It is equal to the value returned by
-     * <code>Math.ilogb(Float.MAX_VALUE)</code>.
-     */
-    public static final int     MAX_EXPONENT    = 127;
-
-    /**
-     * Minimum exponent a normalized <code>float</code> number may
-     * have.  It is equal to the value returned by
-     * <code>Math.ilogb(Float.MIN_NORMAL)</code>.
-     */
-    public static final int     MIN_EXPONENT    = -126;
-
-    /**
-     * The exponent the smallest positive <code>float</code> subnormal
-     * value would have if it could be normalized.  It is equal to the
-     * value returned by <code>FpUtils.ilogb(Float.MIN_VALUE)</code>.
-     */
-    public static final int     MIN_SUB_EXPONENT = MIN_EXPONENT -
-                                                   (SIGNIFICAND_WIDTH - 1);
-
-    /**
-     * Bias used in representing a <code>float</code> exponent.
-     */
-    public static final int     EXP_BIAS        = 127;
-
-    /**
-     * Bit mask to isolate the sign bit of a <code>float</code>.
-     */
-    public static final int     SIGN_BIT_MASK   = 0x80000000;
-
-    /**
-     * Bit mask to isolate the exponent field of a
-     * <code>float</code>.
-     */
-    public static final int     EXP_BIT_MASK    = 0x7F800000;
-
-    /**
-     * Bit mask to isolate the significand field of a
-     * <code>float</code>.
-     */
-    public static final int     SIGNIF_BIT_MASK = 0x007FFFFF;
-
-    static {
-        // verify bit masks cover all bit positions and that the bit
-        // masks are non-overlapping
-        assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) &&
-               (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) &&
-                ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) &&
-                ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0)));
-    }
-}
diff --git a/ojluni/src/main/java/sun/misc/FloatingDecimal.java b/ojluni/src/main/java/sun/misc/FloatingDecimal.java
deleted file mode 100644
index ddd8790..0000000
--- a/ojluni/src/main/java/sun/misc/FloatingDecimal.java
+++ /dev/null
@@ -1,2541 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.util.Arrays;
-import java.util.regex.*;
-
-/**
- * A class for converting between ASCII and decimal representations of a single
- * or double precision floating point number. Most conversions are provided via
- * static convenience methods, although a <code>BinaryToASCIIConverter</code>
- * instance may be obtained and reused.
- */
-public class FloatingDecimal{
-    //
-    // Constants of the implementation;
-    // most are IEEE-754 related.
-    // (There are more really boring constants at the end.)
-    //
-    static final int    EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
-    static final long   FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
-    static final long   EXP_ONE   = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
-    static final int    MAX_SMALL_BIN_EXP = 62;
-    static final int    MIN_SMALL_BIN_EXP = -( 63 / 3 );
-    static final int    MAX_DECIMAL_DIGITS = 15;
-    static final int    MAX_DECIMAL_EXPONENT = 308;
-    static final int    MIN_DECIMAL_EXPONENT = -324;
-    static final int    BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
-    static final int    MAX_NDIGITS = 1100;
-
-    static final int    SINGLE_EXP_SHIFT  =   FloatConsts.SIGNIFICAND_WIDTH - 1;
-    static final int    SINGLE_FRACT_HOB  =   1<<SINGLE_EXP_SHIFT;
-    static final int    SINGLE_MAX_DECIMAL_DIGITS = 7;
-    static final int    SINGLE_MAX_DECIMAL_EXPONENT = 38;
-    static final int    SINGLE_MIN_DECIMAL_EXPONENT = -45;
-    static final int    SINGLE_MAX_NDIGITS = 200;
-
-    static final int    INT_DECIMAL_DIGITS = 9;
-
-    /**
-     * Converts a double precision floating point value to a <code>String</code>.
-     *
-     * @param d The double precision value.
-     * @return The value converted to a <code>String</code>.
-     */
-    public static String toJavaFormatString(double d) {
-        return getBinaryToASCIIConverter(d).toJavaFormatString();
-    }
-
-    /**
-     * Converts a single precision floating point value to a <code>String</code>.
-     *
-     * @param f The single precision value.
-     * @return The value converted to a <code>String</code>.
-     */
-    public static String toJavaFormatString(float f) {
-        return getBinaryToASCIIConverter(f).toJavaFormatString();
-    }
-
-    /**
-     * Appends a double precision floating point value to an <code>Appendable</code>.
-     * @param d The double precision value.
-     * @param buf The <code>Appendable</code> with the value appended.
-     */
-    public static void appendTo(double d, Appendable buf) {
-        getBinaryToASCIIConverter(d).appendTo(buf);
-    }
-
-    /**
-     * Appends a single precision floating point value to an <code>Appendable</code>.
-     * @param f The single precision value.
-     * @param buf The <code>Appendable</code> with the value appended.
-     */
-    public static void appendTo(float f, Appendable buf) {
-        getBinaryToASCIIConverter(f).appendTo(buf);
-    }
-
-    /**
-     * Converts a <code>String</code> to a double precision floating point value.
-     *
-     * @param s The <code>String</code> to convert.
-     * @return The double precision value.
-     * @throws NumberFormatException If the <code>String</code> does not
-     * represent a properly formatted double precision value.
-     */
-    public static double parseDouble(String s) throws NumberFormatException {
-        return readJavaFormatString(s).doubleValue();
-    }
-
-    /**
-     * Converts a <code>String</code> to a single precision floating point value.
-     *
-     * @param s The <code>String</code> to convert.
-     * @return The single precision value.
-     * @throws NumberFormatException If the <code>String</code> does not
-     * represent a properly formatted single precision value.
-     */
-    public static float parseFloat(String s) throws NumberFormatException {
-        return readJavaFormatString(s).floatValue();
-    }
-
-    /**
-     * A converter which can process single or double precision floating point
-     * values into an ASCII <code>String</code> representation.
-     */
-    public interface BinaryToASCIIConverter {
-        /**
-         * Converts a floating point value into an ASCII <code>String</code>.
-         * @return The value converted to a <code>String</code>.
-         */
-        public String toJavaFormatString();
-
-        /**
-         * Appends a floating point value to an <code>Appendable</code>.
-         * @param buf The <code>Appendable</code> to receive the value.
-         */
-        public void appendTo(Appendable buf);
-
-        /**
-         * Retrieves the decimal exponent most closely corresponding to this value.
-         * @return The decimal exponent.
-         */
-        public int getDecimalExponent();
-
-        /**
-         * Retrieves the value as an array of digits.
-         * @param digits The digit array.
-         * @return The number of valid digits copied into the array.
-         */
-        public int getDigits(char[] digits);
-
-        /**
-         * Indicates the sign of the value.
-         * @return <code>value < 0.0</code>.
-         */
-        public boolean isNegative();
-
-        /**
-         * Indicates whether the value is either infinite or not a number.
-         *
-         * @return <code>true</code> if and only if the value is <code>NaN</code>
-         * or infinite.
-         */
-        public boolean isExceptional();
-
-        /**
-         * Indicates whether the value was rounded up during the binary to ASCII
-         * conversion.
-         *
-         * @return <code>true</code> if and only if the value was rounded up.
-         */
-        public boolean digitsRoundedUp();
-
-        /**
-         * Indicates whether the binary to ASCII conversion was exact.
-         *
-         * @return <code>true</code> if any only if the conversion was exact.
-         */
-        public boolean decimalDigitsExact();
-    }
-
-    /**
-     * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
-     * and infinite values.
-     */
-    private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
-        final private String image;
-        private boolean isNegative;
-
-        public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
-            this.image = image;
-            this.isNegative = isNegative;
-        }
-
-        @Override
-        public String toJavaFormatString() {
-            return image;
-        }
-
-        @Override
-        public void appendTo(Appendable buf) {
-            if (buf instanceof StringBuilder) {
-                ((StringBuilder) buf).append(image);
-            } else if (buf instanceof StringBuffer) {
-                ((StringBuffer) buf).append(image);
-            } else {
-                assert false;
-            }
-        }
-
-        @Override
-        public int getDecimalExponent() {
-            throw new IllegalArgumentException("Exceptional value does not have an exponent");
-        }
-
-        @Override
-        public int getDigits(char[] digits) {
-            throw new IllegalArgumentException("Exceptional value does not have digits");
-        }
-
-        @Override
-        public boolean isNegative() {
-            return isNegative;
-        }
-
-        @Override
-        public boolean isExceptional() {
-            return true;
-        }
-
-        @Override
-        public boolean digitsRoundedUp() {
-            throw new IllegalArgumentException("Exceptional value is not rounded");
-        }
-
-        @Override
-        public boolean decimalDigitsExact() {
-            throw new IllegalArgumentException("Exceptional value is not exact");
-        }
-    }
-
-    private static final String INFINITY_REP = "Infinity";
-    private static final int INFINITY_LENGTH = INFINITY_REP.length();
-    private static final String NAN_REP = "NaN";
-    private static final int NAN_LENGTH = NAN_REP.length();
-
-    private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
-    private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
-    private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
-    private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
-    private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true,  new char[]{'0'});
-
-    /**
-     * A buffered implementation of <code>BinaryToASCIIConverter</code>.
-     */
-    static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
-        private boolean isNegative;
-        private int decExponent;
-        private int firstDigitIndex;
-        private int nDigits;
-        private final char[] digits;
-        private final char[] buffer = new char[26];
-
-        //
-        // The fields below provide additional information about the result of
-        // the binary to decimal digits conversion done in dtoa() and roundup()
-        // methods. They are changed if needed by those two methods.
-        //
-
-        // True if the dtoa() binary to decimal conversion was exact.
-        private boolean exactDecimalConversion = false;
-
-        // True if the result of the binary to decimal conversion was rounded-up
-        // at the end of the conversion process, i.e. roundUp() method was called.
-        private boolean decimalDigitsRoundedUp = false;
-
-        /**
-         * Default constructor; used for non-zero values,
-         * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
-         */
-        BinaryToASCIIBuffer(){
-            this.digits = new char[20];
-        }
-
-        /**
-         * Creates a specialized value (positive and negative zeros).
-         */
-        BinaryToASCIIBuffer(boolean isNegative, char[] digits){
-            this.isNegative = isNegative;
-            this.decExponent  = 0;
-            this.digits = digits;
-            this.firstDigitIndex = 0;
-            this.nDigits = digits.length;
-        }
-
-        @Override
-        public String toJavaFormatString() {
-            int len = getChars(buffer);
-            return new String(buffer, 0, len);
-        }
-
-        @Override
-        public void appendTo(Appendable buf) {
-            int len = getChars(buffer);
-            if (buf instanceof StringBuilder) {
-                ((StringBuilder) buf).append(buffer, 0, len);
-            } else if (buf instanceof StringBuffer) {
-                ((StringBuffer) buf).append(buffer, 0, len);
-            } else {
-                assert false;
-            }
-        }
-
-        @Override
-        public int getDecimalExponent() {
-            return decExponent;
-        }
-
-        @Override
-        public int getDigits(char[] digits) {
-            System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
-            return this.nDigits;
-        }
-
-        @Override
-        public boolean isNegative() {
-            return isNegative;
-        }
-
-        @Override
-        public boolean isExceptional() {
-            return false;
-        }
-
-        @Override
-        public boolean digitsRoundedUp() {
-            return decimalDigitsRoundedUp;
-        }
-
-        @Override
-        public boolean decimalDigitsExact() {
-            return exactDecimalConversion;
-        }
-
-        private void setSign(boolean isNegative) {
-            this.isNegative = isNegative;
-        }
-
-        /**
-         * This is the easy subcase --
-         * all the significant bits, after scaling, are held in lvalue.
-         * negSign and decExponent tell us what processing and scaling
-         * has already been done. Exceptional cases have already been
-         * stripped out.
-         * In particular:
-         * lvalue is a finite number (not Inf, nor NaN)
-         * lvalue > 0L (not zero, nor negative).
-         *
-         * The only reason that we develop the digits here, rather than
-         * calling on Long.toString() is that we can do it a little faster,
-         * and besides want to treat trailing 0s specially. If Long.toString
-         * changes, we should re-evaluate this strategy!
-         */
-        private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){
-            if ( insignificantDigits != 0 ){
-                // Discard non-significant low-order bits, while rounding,
-                // up to insignificant value.
-                long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
-                long residue = lvalue % pow10;
-                lvalue /= pow10;
-                decExponent += insignificantDigits;
-                if ( residue >= (pow10>>1) ){
-                    // round up based on the low-order bits we're discarding
-                    lvalue++;
-                }
-            }
-            int  digitno = digits.length -1;
-            int  c;
-            if ( lvalue <= Integer.MAX_VALUE ){
-                assert lvalue > 0L : lvalue; // lvalue <= 0
-                // even easier subcase!
-                // can do int arithmetic rather than long!
-                int  ivalue = (int)lvalue;
-                c = ivalue%10;
-                ivalue /= 10;
-                while ( c == 0 ){
-                    decExponent++;
-                    c = ivalue%10;
-                    ivalue /= 10;
-                }
-                while ( ivalue != 0){
-                    digits[digitno--] = (char)(c+'0');
-                    decExponent++;
-                    c = ivalue%10;
-                    ivalue /= 10;
-                }
-                digits[digitno] = (char)(c+'0');
-            } else {
-                // same algorithm as above (same bugs, too )
-                // but using long arithmetic.
-                c = (int)(lvalue%10L);
-                lvalue /= 10L;
-                while ( c == 0 ){
-                    decExponent++;
-                    c = (int)(lvalue%10L);
-                    lvalue /= 10L;
-                }
-                while ( lvalue != 0L ){
-                    digits[digitno--] = (char)(c+'0');
-                    decExponent++;
-                    c = (int)(lvalue%10L);
-                    lvalue /= 10;
-                }
-                digits[digitno] = (char)(c+'0');
-            }
-            this.decExponent = decExponent+1;
-            this.firstDigitIndex = digitno;
-            this.nDigits = this.digits.length - digitno;
-        }
-
-        private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
-        {
-            assert fractBits > 0 ; // fractBits here can't be zero or negative
-            assert (fractBits & FRACT_HOB)!=0  ; // Hi-order bit should be set
-            // Examine number. Determine if it is an easy case,
-            // which we can do pretty trivially using float/long conversion,
-            // or whether we must do real work.
-            final int tailZeros = Long.numberOfTrailingZeros(fractBits);
-
-            // number of significant bits of fractBits;
-            final int nFractBits = EXP_SHIFT+1-tailZeros;
-
-            // reset flags to default values as dtoa() does not always set these
-            // flags and a prior call to dtoa() might have set them to incorrect
-            // values with respect to the current state.
-            decimalDigitsRoundedUp = false;
-            exactDecimalConversion = false;
-
-            // number of significant bits to the right of the point.
-            int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
-            if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
-                // Look more closely at the number to decide if,
-                // with scaling by 10^nTinyBits, the result will fit in
-                // a long.
-                if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
-                    //
-                    // We can do this:
-                    // take the fraction bits, which are normalized.
-                    // (a) nTinyBits == 0: Shift left or right appropriately
-                    //     to align the binary point at the extreme right, i.e.
-                    //     where a long int point is expected to be. The integer
-                    //     result is easily converted to a string.
-                    // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
-                    //     which effectively converts to long and scales by
-                    //     2^nTinyBits. Then multiply by 5^nTinyBits to
-                    //     complete the scaling. We know this won't overflow
-                    //     because we just counted the number of bits necessary
-                    //     in the result. The integer you get from this can
-                    //     then be converted to a string pretty easily.
-                    //
-                    if ( nTinyBits == 0 ) {
-                        int insignificant;
-                        if ( binExp > nSignificantBits ){
-                            insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
-                        } else {
-                            insignificant = 0;
-                        }
-                        if ( binExp >= EXP_SHIFT ){
-                            fractBits <<= (binExp-EXP_SHIFT);
-                        } else {
-                            fractBits >>>= (EXP_SHIFT-binExp) ;
-                        }
-                        developLongDigits( 0, fractBits, insignificant );
-                        return;
-                    }
-                    //
-                    // The following causes excess digits to be printed
-                    // out in the single-float case. Our manipulation of
-                    // halfULP here is apparently not correct. If we
-                    // better understand how this works, perhaps we can
-                    // use this special case again. But for the time being,
-                    // we do not.
-                    // else {
-                    //     fractBits >>>= EXP_SHIFT+1-nFractBits;
-                    //     fractBits//= long5pow[ nTinyBits ];
-                    //     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
-                    //     developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
-                    //     return;
-                    // }
-                    //
-                }
-            }
-            //
-            // This is the hard case. We are going to compute large positive
-            // integers B and S and integer decExp, s.t.
-            //      d = ( B / S )// 10^decExp
-            //      1 <= B / S < 10
-            // Obvious choices are:
-            //      decExp = floor( log10(d) )
-            //      B      = d// 2^nTinyBits// 10^max( 0, -decExp )
-            //      S      = 10^max( 0, decExp)// 2^nTinyBits
-            // (noting that nTinyBits has already been forced to non-negative)
-            // I am also going to compute a large positive integer
-            //      M      = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
-            // i.e. M is (1/2) of the ULP of d, scaled like B.
-            // When we iterate through dividing B/S and picking off the
-            // quotient bits, we will know when to stop when the remainder
-            // is <= M.
-            //
-            // We keep track of powers of 2 and powers of 5.
-            //
-            int decExp = estimateDecExp(fractBits,binExp);
-            int B2, B5; // powers of 2 and powers of 5, respectively, in B
-            int S2, S5; // powers of 2 and powers of 5, respectively, in S
-            int M2, M5; // powers of 2 and powers of 5, respectively, in M
-
-            B5 = Math.max( 0, -decExp );
-            B2 = B5 + nTinyBits + binExp;
-
-            S5 = Math.max( 0, decExp );
-            S2 = S5 + nTinyBits;
-
-            M5 = B5;
-            M2 = B2 - nSignificantBits;
-
-            //
-            // the long integer fractBits contains the (nFractBits) interesting
-            // bits from the mantissa of d ( hidden 1 added if necessary) followed
-            // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
-            // I will shift out those zeros before turning fractBits into a
-            // FDBigInteger. The resulting whole number will be
-            //      d * 2^(nFractBits-1-binExp).
-            //
-            fractBits >>>= tailZeros;
-            B2 -= nFractBits-1;
-            int common2factor = Math.min( B2, S2 );
-            B2 -= common2factor;
-            S2 -= common2factor;
-            M2 -= common2factor;
-
-            //
-            // HACK!! For exact powers of two, the next smallest number
-            // is only half as far away as we think (because the meaning of
-            // ULP changes at power-of-two bounds) for this reason, we
-            // hack M2. Hope this works.
-            //
-            if ( nFractBits == 1 ) {
-                M2 -= 1;
-            }
-
-            if ( M2 < 0 ){
-                // oops.
-                // since we cannot scale M down far enough,
-                // we must scale the other values up.
-                B2 -= M2;
-                S2 -= M2;
-                M2 =  0;
-            }
-            //
-            // Construct, Scale, iterate.
-            // Some day, we'll write a stopping test that takes
-            // account of the asymmetry of the spacing of floating-point
-            // numbers below perfect powers of 2
-            // 26 Sept 96 is not that day.
-            // So we use a symmetric test.
-            //
-            int ndigit = 0;
-            boolean low, high;
-            long lowDigitDifference;
-            int  q;
-
-            //
-            // Detect the special cases where all the numbers we are about
-            // to compute will fit in int or long integers.
-            // In these cases, we will avoid doing FDBigInteger arithmetic.
-            // We use the same algorithms, except that we "normalize"
-            // our FDBigIntegers before iterating. This is to make division easier,
-            // as it makes our fist guess (quotient of high-order words)
-            // more accurate!
-            //
-            // Some day, we'll write a stopping test that takes
-            // account of the asymmetry of the spacing of floating-point
-            // numbers below perfect powers of 2
-            // 26 Sept 96 is not that day.
-            // So we use a symmetric test.
-            //
-            // binary digits needed to represent B, approx.
-            int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
-
-            // binary digits needed to represent 10*S, approx.
-            int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
-            if ( Bbits < 64 && tenSbits < 64){
-                if ( Bbits < 32 && tenSbits < 32){
-                    // wa-hoo! They're all ints!
-                    int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
-                    int s = FDBigInteger.SMALL_5_POW[S5] << S2;
-                    int m = FDBigInteger.SMALL_5_POW[M5] << M2;
-                    int tens = s * 10;
-                    //
-                    // Unroll the first iteration. If our decExp estimate
-                    // was too high, our first quotient will be zero. In this
-                    // case, we discard it and decrement decExp.
-                    //
-                    ndigit = 0;
-                    q = b / s;
-                    b = 10 * ( b % s );
-                    m *= 10;
-                    low  = (b <  m );
-                    high = (b+m > tens );
-                    assert q < 10 : q; // excessively large digit
-                    if ( (q == 0) && ! high ){
-                        // oops. Usually ignore leading zero.
-                        decExp--;
-                    } else {
-                        digits[ndigit++] = (char)('0' + q);
-                    }
-                    //
-                    // HACK! Java spec sez that we always have at least
-                    // one digit after the . in either F- or E-form output.
-                    // Thus we will need more than one digit if we're using
-                    // E-form
-                    //
-                    if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
-                        high = low = false;
-                    }
-                    while( ! low && ! high ){
-                        q = b / s;
-                        b = 10 * ( b % s );
-                        m *= 10;
-                        assert q < 10 : q; // excessively large digit
-                        if ( m > 0L ){
-                            low  = (b <  m );
-                            high = (b+m > tens );
-                        } else {
-                            // hack -- m might overflow!
-                            // in this case, it is certainly > b,
-                            // which won't
-                            // and b+m > tens, too, since that has overflowed
-                            // either!
-                            low = true;
-                            high = true;
-                        }
-                        digits[ndigit++] = (char)('0' + q);
-                    }
-                    lowDigitDifference = (b<<1) - tens;
-                    exactDecimalConversion  = (b == 0);
-                } else {
-                    // still good! they're all longs!
-                    long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
-                    long s = FDBigInteger.LONG_5_POW[S5] << S2;
-                    long m = FDBigInteger.LONG_5_POW[M5] << M2;
-                    long tens = s * 10L;
-                    //
-                    // Unroll the first iteration. If our decExp estimate
-                    // was too high, our first quotient will be zero. In this
-                    // case, we discard it and decrement decExp.
-                    //
-                    ndigit = 0;
-                    q = (int) ( b / s );
-                    b = 10L * ( b % s );
-                    m *= 10L;
-                    low  = (b <  m );
-                    high = (b+m > tens );
-                    assert q < 10 : q; // excessively large digit
-                    if ( (q == 0) && ! high ){
-                        // oops. Usually ignore leading zero.
-                        decExp--;
-                    } else {
-                        digits[ndigit++] = (char)('0' + q);
-                    }
-                    //
-                    // HACK! Java spec sez that we always have at least
-                    // one digit after the . in either F- or E-form output.
-                    // Thus we will need more than one digit if we're using
-                    // E-form
-                    //
-                    if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
-                        high = low = false;
-                    }
-                    while( ! low && ! high ){
-                        q = (int) ( b / s );
-                        b = 10 * ( b % s );
-                        m *= 10;
-                        assert q < 10 : q;  // excessively large digit
-                        if ( m > 0L ){
-                            low  = (b <  m );
-                            high = (b+m > tens );
-                        } else {
-                            // hack -- m might overflow!
-                            // in this case, it is certainly > b,
-                            // which won't
-                            // and b+m > tens, too, since that has overflowed
-                            // either!
-                            low = true;
-                            high = true;
-                        }
-                        digits[ndigit++] = (char)('0' + q);
-                    }
-                    lowDigitDifference = (b<<1) - tens;
-                    exactDecimalConversion  = (b == 0);
-                }
-            } else {
-                //
-                // We really must do FDBigInteger arithmetic.
-                // Fist, construct our FDBigInteger initial values.
-                //
-                FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
-                int shiftBias = Sval.getNormalizationBias();
-                Sval = Sval.leftShift(shiftBias); // normalize so that division works better
-
-                FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
-                FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
-
-                FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
-                //
-                // Unroll the first iteration. If our decExp estimate
-                // was too high, our first quotient will be zero. In this
-                // case, we discard it and decrement decExp.
-                //
-                ndigit = 0;
-                q = Bval.quoRemIteration( Sval );
-                low  = (Bval.cmp( Mval ) < 0);
-                high = tenSval.addAndCmp(Bval,Mval)<=0;
-
-                assert q < 10 : q; // excessively large digit
-                if ( (q == 0) && ! high ){
-                    // oops. Usually ignore leading zero.
-                    decExp--;
-                } else {
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                //
-                // HACK! Java spec sez that we always have at least
-                // one digit after the . in either F- or E-form output.
-                // Thus we will need more than one digit if we're using
-                // E-form
-                //
-                if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
-                    high = low = false;
-                }
-                while( ! low && ! high ){
-                    q = Bval.quoRemIteration( Sval );
-                    assert q < 10 : q;  // excessively large digit
-                    Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
-                    low  = (Bval.cmp( Mval ) < 0);
-                    high = tenSval.addAndCmp(Bval,Mval)<=0;
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                if ( high && low ){
-                    Bval = Bval.leftShift(1);
-                    lowDigitDifference = Bval.cmp(tenSval);
-                } else {
-                    lowDigitDifference = 0L; // this here only for flow analysis!
-                }
-                exactDecimalConversion  = (Bval.cmp( FDBigInteger.ZERO ) == 0);
-            }
-            this.decExponent = decExp+1;
-            this.firstDigitIndex = 0;
-            this.nDigits = ndigit;
-            //
-            // Last digit gets rounded based on stopping condition.
-            //
-            if ( high ){
-                if ( low ){
-                    if ( lowDigitDifference == 0L ){
-                        // it's a tie!
-                        // choose based on which digits we like.
-                        if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
-                            roundup();
-                        }
-                    } else if ( lowDigitDifference > 0 ){
-                        roundup();
-                    }
-                } else {
-                    roundup();
-                }
-            }
-        }
-
-        // add one to the least significant digit.
-        // in the unlikely event there is a carry out, deal with it.
-        // assert that this will only happen where there
-        // is only one digit, e.g. (float)1e-44 seems to do it.
-        //
-        private void roundup() {
-            int i = (firstDigitIndex + nDigits - 1);
-            int q = digits[i];
-            if (q == '9') {
-                while (q == '9' && i > firstDigitIndex) {
-                    digits[i] = '0';
-                    q = digits[--i];
-                }
-                if (q == '9') {
-                    // carryout! High-order 1, rest 0s, larger exp.
-                    decExponent += 1;
-                    digits[firstDigitIndex] = '1';
-                    return;
-                }
-                // else fall through.
-            }
-            digits[i] = (char) (q + 1);
-            decimalDigitsRoundedUp = true;
-        }
-
-        /**
-         * Estimate decimal exponent. (If it is small-ish,
-         * we could double-check.)
-         *
-         * First, scale the mantissa bits such that 1 <= d2 < 2.
-         * We are then going to estimate
-         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
-         * and so we can estimate
-         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
-         * take the floor and call it decExp.
-         */
-        static int estimateDecExp(long fractBits, int binExp) {
-            double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
-            double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
-            long dBits = Double.doubleToRawLongBits(d);  //can't be NaN here so use raw
-            int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
-            boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
-            if(exponent>=0 && exponent<52) { // hot path
-                long mask   = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
-                int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
-                return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
-            } else if (exponent < 0) {
-                return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
-                        ( (isNegative) ? -1 : 0) );
-            } else { //if (exponent >= 52)
-                return (int)d;
-            }
-        }
-
-        private static int insignificantDigits(int insignificant) {
-            int i;
-            for ( i = 0; insignificant >= 10L; i++ ) {
-                insignificant /= 10L;
-            }
-            return i;
-        }
-
-        /**
-         * Calculates
-         * <pre>
-         * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
-         * </pre>
-         */
-        private static int insignificantDigitsForPow2(int p2) {
-            if(p2>1 && p2 < insignificantDigitsNumber.length) {
-                return insignificantDigitsNumber[p2];
-            }
-            return 0;
-        }
-
-        /**
-         *  If insignificant==(1L << ixd)
-         *  i = insignificantDigitsNumber[idx] is the same as:
-         *  int i;
-         *  for ( i = 0; insignificant >= 10L; i++ )
-         *         insignificant /= 10L;
-         */
-        private static int[] insignificantDigitsNumber = {
-            0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
-            4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
-            8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
-            12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
-            15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
-            18, 18, 18, 19
-        };
-
-        // approximately ceil( log2( long5pow[i] ) )
-        private static final int[] N_5_BITS = {
-                0,
-                3,
-                5,
-                7,
-                10,
-                12,
-                14,
-                17,
-                19,
-                21,
-                24,
-                26,
-                28,
-                31,
-                33,
-                35,
-                38,
-                40,
-                42,
-                45,
-                47,
-                49,
-                52,
-                54,
-                56,
-                59,
-                61,
-        };
-
-        private int getChars(char[] result) {
-            assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
-            int i = 0;
-            if (isNegative) {
-                result[0] = '-';
-                i = 1;
-            }
-            if (decExponent > 0 && decExponent < 8) {
-                // print digits.digits.
-                int charLength = Math.min(nDigits, decExponent);
-                System.arraycopy(digits, firstDigitIndex, result, i, charLength);
-                i += charLength;
-                if (charLength < decExponent) {
-                    charLength = decExponent - charLength;
-                    Arrays.fill(result,i,i+charLength,'0');
-                    i += charLength;
-                    result[i++] = '.';
-                    result[i++] = '0';
-                } else {
-                    result[i++] = '.';
-                    if (charLength < nDigits) {
-                        int t = nDigits - charLength;
-                        System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
-                        i += t;
-                    } else {
-                        result[i++] = '0';
-                    }
-                }
-            } else if (decExponent <= 0 && decExponent > -3) {
-                result[i++] = '0';
-                result[i++] = '.';
-                if (decExponent != 0) {
-                    Arrays.fill(result, i, i-decExponent, '0');
-                    i -= decExponent;
-                }
-                System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
-                i += nDigits;
-            } else {
-                result[i++] = digits[firstDigitIndex];
-                result[i++] = '.';
-                if (nDigits > 1) {
-                    System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
-                    i += nDigits - 1;
-                } else {
-                    result[i++] = '0';
-                }
-                result[i++] = 'E';
-                int e;
-                if (decExponent <= 0) {
-                    result[i++] = '-';
-                    e = -decExponent + 1;
-                } else {
-                    e = decExponent - 1;
-                }
-                // decExponent has 1, 2, or 3, digits
-                if (e <= 9) {
-                    result[i++] = (char) (e + '0');
-                } else if (e <= 99) {
-                    result[i++] = (char) (e / 10 + '0');
-                    result[i++] = (char) (e % 10 + '0');
-                } else {
-                    result[i++] = (char) (e / 100 + '0');
-                    e %= 100;
-                    result[i++] = (char) (e / 10 + '0');
-                    result[i++] = (char) (e % 10 + '0');
-                }
-            }
-            return i;
-        }
-
-    }
-
-    private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
-            new ThreadLocal<BinaryToASCIIBuffer>() {
-                @Override
-                protected BinaryToASCIIBuffer initialValue() {
-                    return new BinaryToASCIIBuffer();
-                }
-            };
-
-    private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
-        return threadLocalBinaryToASCIIBuffer.get();
-    }
-
-    /**
-     * A converter which can process an ASCII <code>String</code> representation
-     * of a single or double precision floating point value into a
-     * <code>float</code> or a <code>double</code>.
-     */
-    interface ASCIIToBinaryConverter {
-
-        double doubleValue();
-
-        float floatValue();
-
-    }
-
-    /**
-     * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
-     */
-    static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
-        final private double doubleVal;
-        final private float floatVal;
-
-        public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
-            this.doubleVal = doubleVal;
-            this.floatVal = floatVal;
-        }
-
-        @Override
-        public double doubleValue() {
-            return doubleVal;
-        }
-
-        @Override
-        public float floatValue() {
-            return floatVal;
-        }
-    }
-
-    static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
-    static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
-    static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER  = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
-    static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
-    static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
-
-    /**
-     * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
-     */
-    static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
-        boolean     isNegative;
-        int         decExponent;
-        char        digits[];
-        int         nDigits;
-
-        ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
-        {
-            this.isNegative = negSign;
-            this.decExponent = decExponent;
-            this.digits = digits;
-            this.nDigits = n;
-        }
-
-        /**
-         * Takes a FloatingDecimal, which we presumably just scanned in,
-         * and finds out what its value is, as a double.
-         *
-         * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
-         * ROUNDING DIRECTION in case the result is really destined
-         * for a single-precision float.
-         */
-        @Override
-        public double doubleValue() {
-            int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
-            //
-            // convert the lead kDigits to a long integer.
-            //
-            // (special performance hack: start to do it using int)
-            int iValue = (int) digits[0] - (int) '0';
-            int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
-            for (int i = 1; i < iDigits; i++) {
-                iValue = iValue * 10 + (int) digits[i] - (int) '0';
-            }
-            long lValue = (long) iValue;
-            for (int i = iDigits; i < kDigits; i++) {
-                lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
-            }
-            double dValue = (double) lValue;
-            int exp = decExponent - kDigits;
-            //
-            // lValue now contains a long integer with the value of
-            // the first kDigits digits of the number.
-            // dValue contains the (double) of the same.
-            //
-
-            if (nDigits <= MAX_DECIMAL_DIGITS) {
-                //
-                // possibly an easy case.
-                // We know that the digits can be represented
-                // exactly. And if the exponent isn't too outrageous,
-                // the whole thing can be done with one operation,
-                // thus one rounding error.
-                // Note that all our constructors trim all leading and
-                // trailing zeros, so simple values (including zero)
-                // will always end up here
-                //
-                if (exp == 0 || dValue == 0.0) {
-                    return (isNegative) ? -dValue : dValue; // small floating integer
-                }
-                else if (exp >= 0) {
-                    if (exp <= MAX_SMALL_TEN) {
-                        //
-                        // Can get the answer with one operation,
-                        // thus one roundoff.
-                        //
-                        double rValue = dValue * SMALL_10_POW[exp];
-                        return (isNegative) ? -rValue : rValue;
-                    }
-                    int slop = MAX_DECIMAL_DIGITS - kDigits;
-                    if (exp <= MAX_SMALL_TEN + slop) {
-                        //
-                        // We can multiply dValue by 10^(slop)
-                        // and it is still "small" and exact.
-                        // Then we can multiply by 10^(exp-slop)
-                        // with one rounding.
-                        //
-                        dValue *= SMALL_10_POW[slop];
-                        double rValue = dValue * SMALL_10_POW[exp - slop];
-                        return (isNegative) ? -rValue : rValue;
-                    }
-                    //
-                    // Else we have a hard case with a positive exp.
-                    //
-                } else {
-                    if (exp >= -MAX_SMALL_TEN) {
-                        //
-                        // Can get the answer in one division.
-                        //
-                        double rValue = dValue / SMALL_10_POW[-exp];
-                        return (isNegative) ? -rValue : rValue;
-                    }
-                    //
-                    // Else we have a hard case with a negative exp.
-                    //
-                }
-            }
-
-            //
-            // Harder cases:
-            // The sum of digits plus exponent is greater than
-            // what we think we can do with one error.
-            //
-            // Start by approximating the right answer by,
-            // naively, scaling by powers of 10.
-            //
-            if (exp > 0) {
-                if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
-                    //
-                    // Lets face it. This is going to be
-                    // Infinity. Cut to the chase.
-                    //
-                    return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                }
-                if ((exp & 15) != 0) {
-                    dValue *= SMALL_10_POW[exp & 15];
-                }
-                if ((exp >>= 4) != 0) {
-                    int j;
-                    for (j = 0; exp > 1; j++, exp >>= 1) {
-                        if ((exp & 1) != 0) {
-                            dValue *= BIG_10_POW[j];
-                        }
-                    }
-                    //
-                    // The reason for the weird exp > 1 condition
-                    // in the above loop was so that the last multiply
-                    // would get unrolled. We handle it here.
-                    // It could overflow.
-                    //
-                    double t = dValue * BIG_10_POW[j];
-                    if (Double.isInfinite(t)) {
-                        //
-                        // It did overflow.
-                        // Look more closely at the result.
-                        // If the exponent is just one too large,
-                        // then use the maximum finite as our estimate
-                        // value. Else call the result infinity
-                        // and punt it.
-                        // ( I presume this could happen because
-                        // rounding forces the result here to be
-                        // an ULP or two larger than
-                        // Double.MAX_VALUE ).
-                        //
-                        t = dValue / 2.0;
-                        t *= BIG_10_POW[j];
-                        if (Double.isInfinite(t)) {
-                            return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                        }
-                        t = Double.MAX_VALUE;
-                    }
-                    dValue = t;
-                }
-            } else if (exp < 0) {
-                exp = -exp;
-                if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
-                    //
-                    // Lets face it. This is going to be
-                    // zero. Cut to the chase.
-                    //
-                    return (isNegative) ? -0.0 : 0.0;
-                }
-                if ((exp & 15) != 0) {
-                    dValue /= SMALL_10_POW[exp & 15];
-                }
-                if ((exp >>= 4) != 0) {
-                    int j;
-                    for (j = 0; exp > 1; j++, exp >>= 1) {
-                        if ((exp & 1) != 0) {
-                            dValue *= TINY_10_POW[j];
-                        }
-                    }
-                    //
-                    // The reason for the weird exp > 1 condition
-                    // in the above loop was so that the last multiply
-                    // would get unrolled. We handle it here.
-                    // It could underflow.
-                    //
-                    double t = dValue * TINY_10_POW[j];
-                    if (t == 0.0) {
-                        //
-                        // It did underflow.
-                        // Look more closely at the result.
-                        // If the exponent is just one too small,
-                        // then use the minimum finite as our estimate
-                        // value. Else call the result 0.0
-                        // and punt it.
-                        // ( I presume this could happen because
-                        // rounding forces the result here to be
-                        // an ULP or two less than
-                        // Double.MIN_VALUE ).
-                        //
-                        t = dValue * 2.0;
-                        t *= TINY_10_POW[j];
-                        if (t == 0.0) {
-                            return (isNegative) ? -0.0 : 0.0;
-                        }
-                        t = Double.MIN_VALUE;
-                    }
-                    dValue = t;
-                }
-            }
-
-            //
-            // dValue is now approximately the result.
-            // The hard part is adjusting it, by comparison
-            // with FDBigInteger arithmetic.
-            // Formulate the EXACT big-number result as
-            // bigD0 * 10^exp
-            //
-            if (nDigits > MAX_NDIGITS) {
-                nDigits = MAX_NDIGITS + 1;
-                digits[MAX_NDIGITS] = '1';
-            }
-            FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
-            exp = decExponent - nDigits;
-
-            long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
-            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
-            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
-            bigD0 = bigD0.multByPow52(D5, 0);
-            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
-            FDBigInteger bigD = null;
-            int prevD2 = 0;
-
-            correctionLoop:
-            while (true) {
-                // here ieeeBits can't be NaN, Infinity or zero
-                int binexp = (int) (ieeeBits >>> EXP_SHIFT);
-                long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
-                if (binexp > 0) {
-                    bigBbits |= FRACT_HOB;
-                } else { // Normalize denormalized numbers.
-                    assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
-                    int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
-                    int shift = leadingZeros - (63 - EXP_SHIFT);
-                    bigBbits <<= shift;
-                    binexp = 1 - shift;
-                }
-                binexp -= DoubleConsts.EXP_BIAS;
-                int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
-                bigBbits >>>= lowOrderZeros;
-                final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
-                final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
-
-                //
-                // Scale bigD, bigB appropriately for
-                // big-integer operations.
-                // Naively, we multiply by powers of ten
-                // and powers of two. What we actually do
-                // is keep track of the powers of 5 and
-                // powers of 2 we would use, then factor out
-                // common divisors before doing the work.
-                //
-                int B2 = B5; // powers of 2 in bigB
-                int D2 = D5; // powers of 2 in bigD
-                int Ulp2;   // powers of 2 in halfUlp.
-                if (bigIntExp >= 0) {
-                    B2 += bigIntExp;
-                } else {
-                    D2 -= bigIntExp;
-                }
-                Ulp2 = B2;
-                // shift bigB and bigD left by a number s. t.
-                // halfUlp is still an integer.
-                int hulpbias;
-                if (binexp <= -DoubleConsts.EXP_BIAS) {
-                    // This is going to be a denormalized number
-                    // (if not actually zero).
-                    // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
-                    hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
-                } else {
-                    hulpbias = 1 + lowOrderZeros;
-                }
-                B2 += hulpbias;
-                D2 += hulpbias;
-                // if there are common factors of 2, we might just as well
-                // factor them out, as they add nothing useful.
-                int common2 = Math.min(B2, Math.min(D2, Ulp2));
-                B2 -= common2;
-                D2 -= common2;
-                Ulp2 -= common2;
-                // do multiplications by powers of 5 and 2
-                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
-                if (bigD == null || prevD2 != D2) {
-                    bigD = bigD0.leftShift(D2);
-                    prevD2 = D2;
-                }
-                //
-                // to recap:
-                // bigB is the scaled-big-int version of our floating-point
-                // candidate.
-                // bigD is the scaled-big-int version of the exact value
-                // as we understand it.
-                // halfUlp is 1/2 an ulp of bigB, except for special cases
-                // of exact powers of 2
-                //
-                // the plan is to compare bigB with bigD, and if the difference
-                // is less than halfUlp, then we're satisfied. Otherwise,
-                // use the ratio of difference to halfUlp to calculate a fudge
-                // factor to add to the floating value, then go 'round again.
-                //
-                FDBigInteger diff;
-                int cmpResult;
-                boolean overvalue;
-                if ((cmpResult = bigB.cmp(bigD)) > 0) {
-                    overvalue = true; // our candidate is too big.
-                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
-                    if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
-                        // candidate is a normalized exact power of 2 and
-                        // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
-                        // For our purposes, ulp is the ulp of the
-                        // next smaller range.
-                        Ulp2 -= 1;
-                        if (Ulp2 < 0) {
-                            // rats. Cannot de-scale ulp this far.
-                            // must scale diff in other direction.
-                            Ulp2 = 0;
-                            diff = diff.leftShift(1);
-                        }
-                    }
-                } else if (cmpResult < 0) {
-                    overvalue = false; // our candidate is too small.
-                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
-                } else {
-                    // the candidate is exactly right!
-                    // this happens with surprising frequency
-                    break correctionLoop;
-                }
-                cmpResult = diff.cmpPow52(B5, Ulp2);
-                if ((cmpResult) < 0) {
-                    // difference is small.
-                    // this is close enough
-                    break correctionLoop;
-                } else if (cmpResult == 0) {
-                    // difference is exactly half an ULP
-                    // round to some other value maybe, then finish
-                    if ((ieeeBits & 1) != 0) { // half ties to even
-                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
-                    }
-                    break correctionLoop;
-                } else {
-                    // difference is non-trivial.
-                    // could scale addend by ratio of difference to
-                    // halfUlp here, if we bothered to compute that difference.
-                    // Most of the time ( I hope ) it is about 1 anyway.
-                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
-                    if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
-                        break correctionLoop; // oops. Fell off end of range.
-                    }
-                    continue; // try again.
-                }
-
-            }
-            if (isNegative) {
-                ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
-            }
-            return Double.longBitsToDouble(ieeeBits);
-        }
-
-        /**
-         * Takes a FloatingDecimal, which we presumably just scanned in,
-         * and finds out what its value is, as a float.
-         * This is distinct from doubleValue() to avoid the extremely
-         * unlikely case of a double rounding error, wherein the conversion
-         * to double has one rounding error, and the conversion of that double
-         * to a float has another rounding error, IN THE WRONG DIRECTION,
-         * ( because of the preference to a zero low-order bit ).
-         */
-        @Override
-        public float floatValue() {
-            int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
-            //
-            // convert the lead kDigits to an integer.
-            //
-            int iValue = (int) digits[0] - (int) '0';
-            for (int i = 1; i < kDigits; i++) {
-                iValue = iValue * 10 + (int) digits[i] - (int) '0';
-            }
-            float fValue = (float) iValue;
-            int exp = decExponent - kDigits;
-            //
-            // iValue now contains an integer with the value of
-            // the first kDigits digits of the number.
-            // fValue contains the (float) of the same.
-            //
-
-            if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
-                //
-                // possibly an easy case.
-                // We know that the digits can be represented
-                // exactly. And if the exponent isn't too outrageous,
-                // the whole thing can be done with one operation,
-                // thus one rounding error.
-                // Note that all our constructors trim all leading and
-                // trailing zeros, so simple values (including zero)
-                // will always end up here.
-                //
-                if (exp == 0 || fValue == 0.0f) {
-                    return (isNegative) ? -fValue : fValue; // small floating integer
-                } else if (exp >= 0) {
-                    if (exp <= SINGLE_MAX_SMALL_TEN) {
-                        //
-                        // Can get the answer with one operation,
-                        // thus one roundoff.
-                        //
-                        fValue *= SINGLE_SMALL_10_POW[exp];
-                        return (isNegative) ? -fValue : fValue;
-                    }
-                    int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
-                    if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
-                        //
-                        // We can multiply fValue by 10^(slop)
-                        // and it is still "small" and exact.
-                        // Then we can multiply by 10^(exp-slop)
-                        // with one rounding.
-                        //
-                        fValue *= SINGLE_SMALL_10_POW[slop];
-                        fValue *= SINGLE_SMALL_10_POW[exp - slop];
-                        return (isNegative) ? -fValue : fValue;
-                    }
-                    //
-                    // Else we have a hard case with a positive exp.
-                    //
-                } else {
-                    if (exp >= -SINGLE_MAX_SMALL_TEN) {
-                        //
-                        // Can get the answer in one division.
-                        //
-                        fValue /= SINGLE_SMALL_10_POW[-exp];
-                        return (isNegative) ? -fValue : fValue;
-                    }
-                    //
-                    // Else we have a hard case with a negative exp.
-                    //
-                }
-            } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
-                //
-                // In double-precision, this is an exact floating integer.
-                // So we can compute to double, then shorten to float
-                // with one round, and get the right answer.
-                //
-                // First, finish accumulating digits.
-                // Then convert that integer to a double, multiply
-                // by the appropriate power of ten, and convert to float.
-                //
-                long lValue = (long) iValue;
-                for (int i = kDigits; i < nDigits; i++) {
-                    lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
-                }
-                double dValue = (double) lValue;
-                exp = decExponent - nDigits;
-                dValue *= SMALL_10_POW[exp];
-                fValue = (float) dValue;
-                return (isNegative) ? -fValue : fValue;
-
-            }
-            //
-            // Harder cases:
-            // The sum of digits plus exponent is greater than
-            // what we think we can do with one error.
-            //
-            // Start by approximating the right answer by,
-            // naively, scaling by powers of 10.
-            // Scaling uses doubles to avoid overflow/underflow.
-            //
-            double dValue = fValue;
-            if (exp > 0) {
-                if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
-                    //
-                    // Lets face it. This is going to be
-                    // Infinity. Cut to the chase.
-                    //
-                    return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
-                }
-                if ((exp & 15) != 0) {
-                    dValue *= SMALL_10_POW[exp & 15];
-                }
-                if ((exp >>= 4) != 0) {
-                    int j;
-                    for (j = 0; exp > 0; j++, exp >>= 1) {
-                        if ((exp & 1) != 0) {
-                            dValue *= BIG_10_POW[j];
-                        }
-                    }
-                }
-            } else if (exp < 0) {
-                exp = -exp;
-                if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
-                    //
-                    // Lets face it. This is going to be
-                    // zero. Cut to the chase.
-                    //
-                    return (isNegative) ? -0.0f : 0.0f;
-                }
-                if ((exp & 15) != 0) {
-                    dValue /= SMALL_10_POW[exp & 15];
-                }
-                if ((exp >>= 4) != 0) {
-                    int j;
-                    for (j = 0; exp > 0; j++, exp >>= 1) {
-                        if ((exp & 1) != 0) {
-                            dValue *= TINY_10_POW[j];
-                        }
-                    }
-                }
-            }
-            fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
-
-            //
-            // fValue is now approximately the result.
-            // The hard part is adjusting it, by comparison
-            // with FDBigInteger arithmetic.
-            // Formulate the EXACT big-number result as
-            // bigD0 * 10^exp
-            //
-            if (nDigits > SINGLE_MAX_NDIGITS) {
-                nDigits = SINGLE_MAX_NDIGITS + 1;
-                digits[SINGLE_MAX_NDIGITS] = '1';
-            }
-            FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
-            exp = decExponent - nDigits;
-
-            int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
-            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
-            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
-            bigD0 = bigD0.multByPow52(D5, 0);
-            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
-            FDBigInteger bigD = null;
-            int prevD2 = 0;
-
-            correctionLoop:
-            while (true) {
-                // here ieeeBits can't be NaN, Infinity or zero
-                int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
-                int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
-                if (binexp > 0) {
-                    bigBbits |= SINGLE_FRACT_HOB;
-                } else { // Normalize denormalized numbers.
-                    assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
-                    int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
-                    int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
-                    bigBbits <<= shift;
-                    binexp = 1 - shift;
-                }
-                binexp -= FloatConsts.EXP_BIAS;
-                int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
-                bigBbits >>>= lowOrderZeros;
-                final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
-                final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
-
-                //
-                // Scale bigD, bigB appropriately for
-                // big-integer operations.
-                // Naively, we multiply by powers of ten
-                // and powers of two. What we actually do
-                // is keep track of the powers of 5 and
-                // powers of 2 we would use, then factor out
-                // common divisors before doing the work.
-                //
-                int B2 = B5; // powers of 2 in bigB
-                int D2 = D5; // powers of 2 in bigD
-                int Ulp2;   // powers of 2 in halfUlp.
-                if (bigIntExp >= 0) {
-                    B2 += bigIntExp;
-                } else {
-                    D2 -= bigIntExp;
-                }
-                Ulp2 = B2;
-                // shift bigB and bigD left by a number s. t.
-                // halfUlp is still an integer.
-                int hulpbias;
-                if (binexp <= -FloatConsts.EXP_BIAS) {
-                    // This is going to be a denormalized number
-                    // (if not actually zero).
-                    // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
-                    hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
-                } else {
-                    hulpbias = 1 + lowOrderZeros;
-                }
-                B2 += hulpbias;
-                D2 += hulpbias;
-                // if there are common factors of 2, we might just as well
-                // factor them out, as they add nothing useful.
-                int common2 = Math.min(B2, Math.min(D2, Ulp2));
-                B2 -= common2;
-                D2 -= common2;
-                Ulp2 -= common2;
-                // do multiplications by powers of 5 and 2
-                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
-                if (bigD == null || prevD2 != D2) {
-                    bigD = bigD0.leftShift(D2);
-                    prevD2 = D2;
-                }
-                //
-                // to recap:
-                // bigB is the scaled-big-int version of our floating-point
-                // candidate.
-                // bigD is the scaled-big-int version of the exact value
-                // as we understand it.
-                // halfUlp is 1/2 an ulp of bigB, except for special cases
-                // of exact powers of 2
-                //
-                // the plan is to compare bigB with bigD, and if the difference
-                // is less than halfUlp, then we're satisfied. Otherwise,
-                // use the ratio of difference to halfUlp to calculate a fudge
-                // factor to add to the floating value, then go 'round again.
-                //
-                FDBigInteger diff;
-                int cmpResult;
-                boolean overvalue;
-                if ((cmpResult = bigB.cmp(bigD)) > 0) {
-                    overvalue = true; // our candidate is too big.
-                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
-                    if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
-                        // candidate is a normalized exact power of 2 and
-                        // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
-                        // For our purposes, ulp is the ulp of the
-                        // next smaller range.
-                        Ulp2 -= 1;
-                        if (Ulp2 < 0) {
-                            // rats. Cannot de-scale ulp this far.
-                            // must scale diff in other direction.
-                            Ulp2 = 0;
-                            diff = diff.leftShift(1);
-                        }
-                    }
-                } else if (cmpResult < 0) {
-                    overvalue = false; // our candidate is too small.
-                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
-                } else {
-                    // the candidate is exactly right!
-                    // this happens with surprising frequency
-                    break correctionLoop;
-                }
-                cmpResult = diff.cmpPow52(B5, Ulp2);
-                if ((cmpResult) < 0) {
-                    // difference is small.
-                    // this is close enough
-                    break correctionLoop;
-                } else if (cmpResult == 0) {
-                    // difference is exactly half an ULP
-                    // round to some other value maybe, then finish
-                    if ((ieeeBits & 1) != 0) { // half ties to even
-                        ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
-                    }
-                    break correctionLoop;
-                } else {
-                    // difference is non-trivial.
-                    // could scale addend by ratio of difference to
-                    // halfUlp here, if we bothered to compute that difference.
-                    // Most of the time ( I hope ) it is about 1 anyway.
-                    ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
-                    if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
-                        break correctionLoop; // oops. Fell off end of range.
-                    }
-                    continue; // try again.
-                }
-
-            }
-            if (isNegative) {
-                ieeeBits |= FloatConsts.SIGN_BIT_MASK;
-            }
-            return Float.intBitsToFloat(ieeeBits);
-        }
-
-
-        /**
-         * All the positive powers of 10 that can be
-         * represented exactly in double/float.
-         */
-        private static final double[] SMALL_10_POW = {
-            1.0e0,
-            1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
-            1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
-            1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
-            1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
-            1.0e21, 1.0e22
-        };
-
-        private static final float[] SINGLE_SMALL_10_POW = {
-            1.0e0f,
-            1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
-            1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
-        };
-
-        private static final double[] BIG_10_POW = {
-            1e16, 1e32, 1e64, 1e128, 1e256 };
-        private static final double[] TINY_10_POW = {
-            1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
-        private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
-        private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
-
-    }
-
-    /**
-     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
-     * The returned object is a <code>ThreadLocal</code> variable of this class.
-     *
-     * @param d The double precision value to convert.
-     * @return The converter.
-     */
-    public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
-        return getBinaryToASCIIConverter(d, true);
-    }
-
-    /**
-     * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
-     * The returned object is a <code>ThreadLocal</code> variable of this class.
-     *
-     * @param d The double precision value to convert.
-     * @param isCompatibleFormat
-     * @return The converter.
-     */
-    static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
-        long dBits = Double.doubleToRawLongBits(d);
-        boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
-        long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
-        int  binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
-        // Discover obvious special cases of NaN and Infinity.
-        if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
-            if ( fractBits == 0L ){
-                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
-            } else {
-                return B2AC_NOT_A_NUMBER;
-            }
-        }
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        int  nSignificantBits;
-        if ( binExp == 0 ){
-            if ( fractBits == 0L ){
-                // not a denorm, just a 0!
-                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
-            }
-            int leadingZeros = Long.numberOfLeadingZeros(fractBits);
-            int shift = leadingZeros-(63-EXP_SHIFT);
-            fractBits <<= shift;
-            binExp = 1 - shift;
-            nSignificantBits =  64-leadingZeros; // recall binExp is  - shift count.
-        } else {
-            fractBits |= FRACT_HOB;
-            nSignificantBits = EXP_SHIFT+1;
-        }
-        binExp -= DoubleConsts.EXP_BIAS;
-        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
-        buf.setSign(isNegative);
-        // call the routine that actually does all the hard work.
-        buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
-        return buf;
-    }
-
-    private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
-        int fBits = Float.floatToRawIntBits( f );
-        boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
-        int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
-        int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
-        // Discover obvious special cases of NaN and Infinity.
-        if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
-            if ( fractBits == 0L ){
-                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
-            } else {
-                return B2AC_NOT_A_NUMBER;
-            }
-        }
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        int  nSignificantBits;
-        if ( binExp == 0 ){
-            if ( fractBits == 0 ){
-                // not a denorm, just a 0!
-                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
-            }
-            int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
-            int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
-            fractBits <<= shift;
-            binExp = 1 - shift;
-            nSignificantBits =  32 - leadingZeros; // recall binExp is  - shift count.
-        } else {
-            fractBits |= SINGLE_FRACT_HOB;
-            nSignificantBits = SINGLE_EXP_SHIFT+1;
-        }
-        binExp -= FloatConsts.EXP_BIAS;
-        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
-        buf.setSign(isNegative);
-        // call the routine that actually does all the hard work.
-        buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
-        return buf;
-    }
-
-    @SuppressWarnings("fallthrough")
-    static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
-        boolean isNegative = false;
-        boolean signSeen   = false;
-        int     decExp;
-        char    c;
-
-    parseNumber:
-        try{
-            in = in.trim(); // don't fool around with white space.
-                            // throws NullPointerException if null
-            int len = in.length();
-            if ( len == 0 ) {
-                throw new NumberFormatException("empty String");
-            }
-            int i = 0;
-            switch (in.charAt(i)){
-            case '-':
-                isNegative = true;
-                //FALLTHROUGH
-            case '+':
-                i++;
-                signSeen = true;
-            }
-            c = in.charAt(i);
-            if(c == 'N') { // Check for NaN
-                if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
-                    return A2BC_NOT_A_NUMBER;
-                }
-                // something went wrong, throw exception
-                break parseNumber;
-            } else if(c == 'I') { // Check for Infinity strings
-                if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
-                    return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
-                }
-                // something went wrong, throw exception
-                break parseNumber;
-            } else if (c == '0')  { // check for hexadecimal floating-point number
-                if (len > i+1 ) {
-                    char ch = in.charAt(i+1);
-                    if (ch == 'x' || ch == 'X' ) { // possible hex string
-                        return parseHexString(in);
-                    }
-                }
-            }  // look for and process decimal floating-point string
-
-            char[] digits = new char[ len ];
-            int    nDigits= 0;
-            boolean decSeen = false;
-            int decPt = 0;
-            int nLeadZero = 0;
-            int nTrailZero= 0;
-
-        skipLeadingZerosLoop:
-            while (i < len) {
-                c = in.charAt(i);
-                if (c == '0') {
-                    nLeadZero++;
-                } else if (c == '.') {
-                    if (decSeen) {
-                        // already saw one ., this is the 2nd.
-                        throw new NumberFormatException("multiple points");
-                    }
-                    decPt = i;
-                    if (signSeen) {
-                        decPt -= 1;
-                    }
-                    decSeen = true;
-                } else {
-                    break skipLeadingZerosLoop;
-                }
-                i++;
-            }
-        digitLoop:
-            while (i < len) {
-                c = in.charAt(i);
-                if (c >= '1' && c <= '9') {
-                    digits[nDigits++] = c;
-                    nTrailZero = 0;
-                } else if (c == '0') {
-                    digits[nDigits++] = c;
-                    nTrailZero++;
-                } else if (c == '.') {
-                    if (decSeen) {
-                        // already saw one ., this is the 2nd.
-                        throw new NumberFormatException("multiple points");
-                    }
-                    decPt = i;
-                    if (signSeen) {
-                        decPt -= 1;
-                    }
-                    decSeen = true;
-                } else {
-                    break digitLoop;
-                }
-                i++;
-            }
-            nDigits -=nTrailZero;
-            //
-            // At this point, we've scanned all the digits and decimal
-            // point we're going to see. Trim off leading and trailing
-            // zeros, which will just confuse us later, and adjust
-            // our initial decimal exponent accordingly.
-            // To review:
-            // we have seen i total characters.
-            // nLeadZero of them were zeros before any other digits.
-            // nTrailZero of them were zeros after any other digits.
-            // if ( decSeen ), then a . was seen after decPt characters
-            // ( including leading zeros which have been discarded )
-            // nDigits characters were neither lead nor trailing
-            // zeros, nor point
-            //
-            //
-            // special hack: if we saw no non-zero digits, then the
-            // answer is zero!
-            // Unfortunately, we feel honor-bound to keep parsing!
-            //
-            boolean isZero = (nDigits == 0);
-            if ( isZero &&  nLeadZero == 0 ){
-                // we saw NO DIGITS AT ALL,
-                // not even a crummy 0!
-                // this is not allowed.
-                break parseNumber; // go throw exception
-            }
-            //
-            // Our initial exponent is decPt, adjusted by the number of
-            // discarded zeros. Or, if there was no decPt,
-            // then its just nDigits adjusted by discarded trailing zeros.
-            //
-            if ( decSeen ){
-                decExp = decPt - nLeadZero;
-            } else {
-                decExp = nDigits + nTrailZero;
-            }
-
-            //
-            // Look for 'e' or 'E' and an optionally signed integer.
-            //
-            if ( (i < len) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
-                int expSign = 1;
-                int expVal  = 0;
-                int reallyBig = Integer.MAX_VALUE / 10;
-                boolean expOverflow = false;
-                switch( in.charAt(++i) ){
-                case '-':
-                    expSign = -1;
-                    //FALLTHROUGH
-                case '+':
-                    i++;
-                }
-                int expAt = i;
-            expLoop:
-                while ( i < len  ){
-                    if ( expVal >= reallyBig ){
-                        // the next character will cause integer
-                        // overflow.
-                        expOverflow = true;
-                    }
-                    c = in.charAt(i++);
-                    if(c>='0' && c<='9') {
-                        expVal = expVal*10 + ( (int)c - (int)'0' );
-                    } else {
-                        i--;           // back up.
-                        break expLoop; // stop parsing exponent.
-                    }
-                }
-                int expLimit = BIG_DECIMAL_EXPONENT+nDigits+nTrailZero;
-                if ( expOverflow || ( expVal > expLimit ) ){
-                    //
-                    // The intent here is to end up with
-                    // infinity or zero, as appropriate.
-                    // The reason for yielding such a small decExponent,
-                    // rather than something intuitive such as
-                    // expSign*Integer.MAX_VALUE, is that this value
-                    // is subject to further manipulation in
-                    // doubleValue() and floatValue(), and I don't want
-                    // it to be able to cause overflow there!
-                    // (The only way we can get into trouble here is for
-                    // really outrageous nDigits+nTrailZero, such as 2 billion. )
-                    //
-                    decExp = expSign*expLimit;
-                } else {
-                    // this should not overflow, since we tested
-                    // for expVal > (MAX+N), where N >= abs(decExp)
-                    decExp = decExp + expSign*expVal;
-                }
-
-                // if we saw something not a digit ( or end of string )
-                // after the [Ee][+-], without seeing any digits at all
-                // this is certainly an error. If we saw some digits,
-                // but then some trailing garbage, that might be ok.
-                // so we just fall through in that case.
-                // HUMBUG
-                if ( i == expAt ) {
-                    break parseNumber; // certainly bad
-                }
-            }
-            //
-            // We parsed everything we could.
-            // If there are leftovers, then this is not good input!
-            //
-            if ( i < len &&
-                ((i != len - 1) ||
-                (in.charAt(i) != 'f' &&
-                 in.charAt(i) != 'F' &&
-                 in.charAt(i) != 'd' &&
-                 in.charAt(i) != 'D'))) {
-                break parseNumber; // go throw exception
-            }
-            if(isZero) {
-                return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
-            }
-            return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
-        } catch ( StringIndexOutOfBoundsException e ){ }
-        throw new NumberFormatException("For input string: \"" + in + "\"");
-    }
-
-    private static class HexFloatPattern {
-        /**
-         * Grammar is compatible with hexadecimal floating-point constants
-         * described in section 6.4.4.2 of the C99 specification.
-         */
-        private static final Pattern VALUE = Pattern.compile(
-                   //1           234                   56                7                   8      9
-                    "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
-                    );
-    }
-
-    /**
-     * Converts string s to a suitable floating decimal; uses the
-     * double constructor and sets the roundDir variable appropriately
-     * in case the value is later converted to a float.
-     *
-     * @param s The <code>String</code> to parse.
-     */
-   static ASCIIToBinaryConverter parseHexString(String s) {
-            // Verify string is a member of the hexadecimal floating-point
-            // string language.
-            Matcher m = HexFloatPattern.VALUE.matcher(s);
-            boolean validInput = m.matches();
-            if (!validInput) {
-                // Input does not match pattern
-                throw new NumberFormatException("For input string: \"" + s + "\"");
-            } else { // validInput
-                //
-                // We must isolate the sign, significand, and exponent
-                // fields.  The sign value is straightforward.  Since
-                // floating-point numbers are stored with a normalized
-                // representation, the significand and exponent are
-                // interrelated.
-                //
-                // After extracting the sign, we normalized the
-                // significand as a hexadecimal value, calculating an
-                // exponent adjust for any shifts made during
-                // normalization.  If the significand is zero, the
-                // exponent doesn't need to be examined since the output
-                // will be zero.
-                //
-                // Next the exponent in the input string is extracted.
-                // Afterwards, the significand is normalized as a *binary*
-                // value and the input value's normalized exponent can be
-                // computed.  The significand bits are copied into a
-                // double significand; if the string has more logical bits
-                // than can fit in a double, the extra bits affect the
-                // round and sticky bits which are used to round the final
-                // value.
-                //
-                //  Extract significand sign
-                String group1 = m.group(1);
-                boolean isNegative = ((group1 != null) && group1.equals("-"));
-
-                //  Extract Significand magnitude
-                //
-                // Based on the form of the significand, calculate how the
-                // binary exponent needs to be adjusted to create a
-                // normalized//hexadecimal* floating-point number; that
-                // is, a number where there is one nonzero hex digit to
-                // the left of the (hexa)decimal point.  Since we are
-                // adjusting a binary, not hexadecimal exponent, the
-                // exponent is adjusted by a multiple of 4.
-                //
-                // There are a number of significand scenarios to consider;
-                // letters are used in indicate nonzero digits:
-                //
-                // 1. 000xxxx       =>      x.xxx   normalized
-                //    increase exponent by (number of x's - 1)*4
-                //
-                // 2. 000xxx.yyyy =>        x.xxyyyy        normalized
-                //    increase exponent by (number of x's - 1)*4
-                //
-                // 3. .000yyy  =>   y.yy    normalized
-                //    decrease exponent by (number of zeros + 1)*4
-                //
-                // 4. 000.00000yyy => y.yy normalized
-                //    decrease exponent by (number of zeros to right of point + 1)*4
-                //
-                // If the significand is exactly zero, return a properly
-                // signed zero.
-                //
-
-                String significandString = null;
-                int signifLength = 0;
-                int exponentAdjust = 0;
-                {
-                    int leftDigits = 0; // number of meaningful digits to
-                    // left of "decimal" point
-                    // (leading zeros stripped)
-                    int rightDigits = 0; // number of digits to right of
-                    // "decimal" point; leading zeros
-                    // must always be accounted for
-                    //
-                    // The significand is made up of either
-                    //
-                    // 1. group 4 entirely (integer portion only)
-                    //
-                    // OR
-                    //
-                    // 2. the fractional portion from group 7 plus any
-                    // (optional) integer portions from group 6.
-                    //
-                    String group4;
-                    if ((group4 = m.group(4)) != null) {  // Integer-only significand
-                        // Leading zeros never matter on the integer portion
-                        significandString = stripLeadingZeros(group4);
-                        leftDigits = significandString.length();
-                    } else {
-                        // Group 6 is the optional integer; leading zeros
-                        // never matter on the integer portion
-                        String group6 = stripLeadingZeros(m.group(6));
-                        leftDigits = group6.length();
-
-                        // fraction
-                        String group7 = m.group(7);
-                        rightDigits = group7.length();
-
-                        // Turn "integer.fraction" into "integer"+"fraction"
-                        significandString =
-                                ((group6 == null) ? "" : group6) + // is the null
-                                        // check necessary?
-                                        group7;
-                    }
-
-                    significandString = stripLeadingZeros(significandString);
-                    signifLength = significandString.length();
-
-                    //
-                    // Adjust exponent as described above
-                    //
-                    if (leftDigits >= 1) {  // Cases 1 and 2
-                        exponentAdjust = 4 * (leftDigits - 1);
-                    } else {                // Cases 3 and 4
-                        exponentAdjust = -4 * (rightDigits - signifLength + 1);
-                    }
-
-                    // If the significand is zero, the exponent doesn't
-                    // matter; return a properly signed zero.
-
-                    if (signifLength == 0) { // Only zeros in input
-                        return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
-                    }
-                }
-
-                //  Extract Exponent
-                //
-                // Use an int to read in the exponent value; this should
-                // provide more than sufficient range for non-contrived
-                // inputs.  If reading the exponent in as an int does
-                // overflow, examine the sign of the exponent and
-                // significand to determine what to do.
-                //
-                String group8 = m.group(8);
-                boolean positiveExponent = (group8 == null) || group8.equals("+");
-                long unsignedRawExponent;
-                try {
-                    unsignedRawExponent = Integer.parseInt(m.group(9));
-                }
-                catch (NumberFormatException e) {
-                    // At this point, we know the exponent is
-                    // syntactically well-formed as a sequence of
-                    // digits.  Therefore, if an NumberFormatException
-                    // is thrown, it must be due to overflowing int's
-                    // range.  Also, at this point, we have already
-                    // checked for a zero significand.  Thus the signs
-                    // of the exponent and significand determine the
-                    // final result:
-                    //
-                    //                      significand
-                    //                      +               -
-                    // exponent     +       +infinity       -infinity
-                    //              -       +0.0            -0.0
-                    return isNegative ?
-                              (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
-                            : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
-
-                }
-
-                long rawExponent =
-                        (positiveExponent ? 1L : -1L) * // exponent sign
-                                unsignedRawExponent;            // exponent magnitude
-
-                // Calculate partially adjusted exponent
-                long exponent = rawExponent + exponentAdjust;
-
-                // Starting copying non-zero bits into proper position in
-                // a long; copy explicit bit too; this will be masked
-                // later for normal values.
-
-                boolean round = false;
-                boolean sticky = false;
-                int nextShift = 0;
-                long significand = 0L;
-                // First iteration is different, since we only copy
-                // from the leading significand bit; one more exponent
-                // adjust will be needed...
-
-                // IMPORTANT: make leadingDigit a long to avoid
-                // surprising shift semantics!
-                long leadingDigit = getHexDigit(significandString, 0);
-
-                //
-                // Left shift the leading digit (53 - (bit position of
-                // leading 1 in digit)); this sets the top bit of the
-                // significand to 1.  The nextShift value is adjusted
-                // to take into account the number of bit positions of
-                // the leadingDigit actually used.  Finally, the
-                // exponent is adjusted to normalize the significand
-                // as a binary value, not just a hex value.
-                //
-                if (leadingDigit == 1) {
-                    significand |= leadingDigit << 52;
-                    nextShift = 52 - 4;
-                    // exponent += 0
-                } else if (leadingDigit <= 3) { // [2, 3]
-                    significand |= leadingDigit << 51;
-                    nextShift = 52 - 5;
-                    exponent += 1;
-                } else if (leadingDigit <= 7) { // [4, 7]
-                    significand |= leadingDigit << 50;
-                    nextShift = 52 - 6;
-                    exponent += 2;
-                } else if (leadingDigit <= 15) { // [8, f]
-                    significand |= leadingDigit << 49;
-                    nextShift = 52 - 7;
-                    exponent += 3;
-                } else {
-                    throw new AssertionError("Result from digit conversion too large!");
-                }
-                // The preceding if-else could be replaced by a single
-                // code block based on the high-order bit set in
-                // leadingDigit.  Given leadingOnePosition,
-
-                // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
-                // nextShift = 52 - (3 + leadingOnePosition);
-                // exponent += (leadingOnePosition-1);
-
-                //
-                // Now the exponent variable is equal to the normalized
-                // binary exponent.  Code below will make representation
-                // adjustments if the exponent is incremented after
-                // rounding (includes overflows to infinity) or if the
-                // result is subnormal.
-                //
-
-                // Copy digit into significand until the significand can't
-                // hold another full hex digit or there are no more input
-                // hex digits.
-                int i = 0;
-                for (i = 1;
-                     i < signifLength && nextShift >= 0;
-                     i++) {
-                    long currentDigit = getHexDigit(significandString, i);
-                    significand |= (currentDigit << nextShift);
-                    nextShift -= 4;
-                }
-
-                // After the above loop, the bulk of the string is copied.
-                // Now, we must copy any partial hex digits into the
-                // significand AND compute the round bit and start computing
-                // sticky bit.
-
-                if (i < signifLength) { // at least one hex input digit exists
-                    long currentDigit = getHexDigit(significandString, i);
-
-                    // from nextShift, figure out how many bits need
-                    // to be copied, if any
-                    switch (nextShift) { // must be negative
-                        case -1:
-                            // three bits need to be copied in; can
-                            // set round bit
-                            significand |= ((currentDigit & 0xEL) >> 1);
-                            round = (currentDigit & 0x1L) != 0L;
-                            break;
-
-                        case -2:
-                            // two bits need to be copied in; can
-                            // set round and start sticky
-                            significand |= ((currentDigit & 0xCL) >> 2);
-                            round = (currentDigit & 0x2L) != 0L;
-                            sticky = (currentDigit & 0x1L) != 0;
-                            break;
-
-                        case -3:
-                            // one bit needs to be copied in
-                            significand |= ((currentDigit & 0x8L) >> 3);
-                            // Now set round and start sticky, if possible
-                            round = (currentDigit & 0x4L) != 0L;
-                            sticky = (currentDigit & 0x3L) != 0;
-                            break;
-
-                        case -4:
-                            // all bits copied into significand; set
-                            // round and start sticky
-                            round = ((currentDigit & 0x8L) != 0);  // is top bit set?
-                            // nonzeros in three low order bits?
-                            sticky = (currentDigit & 0x7L) != 0;
-                            break;
-
-                        default:
-                            throw new AssertionError("Unexpected shift distance remainder.");
-                            // break;
-                    }
-
-                    // Round is set; sticky might be set.
-
-                    // For the sticky bit, it suffices to check the
-                    // current digit and test for any nonzero digits in
-                    // the remaining unprocessed input.
-                    i++;
-                    while (i < signifLength && !sticky) {
-                        currentDigit = getHexDigit(significandString, i);
-                        sticky = sticky || (currentDigit != 0);
-                        i++;
-                    }
-
-                }
-                // else all of string was seen, round and sticky are
-                // correct as false.
-
-                // Float calculations
-                int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
-                if (exponent >= FloatConsts.MIN_EXPONENT) {
-                    if (exponent > FloatConsts.MAX_EXPONENT) {
-                        // Float.POSITIVE_INFINITY
-                        floatBits |= FloatConsts.EXP_BIT_MASK;
-                    } else {
-                        int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
-                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
-                        int iValue = (int) (significand >>> threshShift);
-                        if ((iValue & 3) != 1 || floatSticky) {
-                            iValue++;
-                        }
-                        floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
-                    }
-                } else {
-                    if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
-                        // 0
-                    } else {
-                        // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
-                        int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
-                        assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
-                        assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
-                        boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
-                        int iValue = (int) (significand >>> threshShift);
-                        if ((iValue & 3) != 1 || floatSticky) {
-                            iValue++;
-                        }
-                        floatBits |= iValue >> 1;
-                    }
-                }
-                float fValue = Float.intBitsToFloat(floatBits);
-
-                // Check for overflow and update exponent accordingly.
-                if (exponent > DoubleConsts.MAX_EXPONENT) {         // Infinite result
-                    // overflow to properly signed infinity
-                    return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
-                } else {  // Finite return value
-                    if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
-                            exponent >= DoubleConsts.MIN_EXPONENT) {
-
-                        // The result returned in this block cannot be a
-                        // zero or subnormal; however after the
-                        // significand is adjusted from rounding, we could
-                        // still overflow in infinity.
-
-                        // AND exponent bits into significand; if the
-                        // significand is incremented and overflows from
-                        // rounding, this combination will update the
-                        // exponent correctly, even in the case of
-                        // Double.MAX_VALUE overflowing to infinity.
-
-                        significand = ((( exponent +
-                                (long) DoubleConsts.EXP_BIAS) <<
-                                (DoubleConsts.SIGNIFICAND_WIDTH - 1))
-                                & DoubleConsts.EXP_BIT_MASK) |
-                                (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
-                    } else {  // Subnormal or zero
-                        // (exponent < DoubleConsts.MIN_EXPONENT)
-
-                        if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
-                            // No way to round back to nonzero value
-                            // regardless of significand if the exponent is
-                            // less than -1075.
-                            return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
-                        } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023
-                            //
-                            // Find bit position to round to; recompute
-                            // round and sticky bits, and shift
-                            // significand right appropriately.
-                            //
-
-                            sticky = sticky || round;
-                            round = false;
-
-                            // Number of bits of significand to preserve is
-                            // exponent - abs_min_exp +1
-                            // check:
-                            // -1075 +1074 + 1 = 0
-                            // -1023 +1074 + 1 = 52
-
-                            int bitsDiscarded = 53 -
-                                    ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
-                            assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
-                            // What to do here:
-                            // First, isolate the new round bit
-                            round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
-                            if (bitsDiscarded > 1) {
-                                // create mask to update sticky bits; low
-                                // order bitsDiscarded bits should be 1
-                                long mask = ~((~0L) << (bitsDiscarded - 1));
-                                sticky = sticky || ((significand & mask) != 0L);
-                            }
-
-                            // Now, discard the bits
-                            significand = significand >> bitsDiscarded;
-
-                            significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
-                                    (long) DoubleConsts.EXP_BIAS) <<
-                                    (DoubleConsts.SIGNIFICAND_WIDTH - 1))
-                                    & DoubleConsts.EXP_BIT_MASK) |
-                                    (DoubleConsts.SIGNIF_BIT_MASK & significand);
-                        }
-                    }
-
-                    // The significand variable now contains the currently
-                    // appropriate exponent bits too.
-
-                    //
-                    // Determine if significand should be incremented;
-                    // making this determination depends on the least
-                    // significant bit and the round and sticky bits.
-                    //
-                    // Round to nearest even rounding table, adapted from
-                    // table 4.7 in "Computer Arithmetic" by IsraelKoren.
-                    // The digit to the left of the "decimal" point is the
-                    // least significant bit, the digits to the right of
-                    // the point are the round and sticky bits
-                    //
-                    // Number       Round(x)
-                    // x0.00        x0.
-                    // x0.01        x0.
-                    // x0.10        x0.
-                    // x0.11        x1. = x0. +1
-                    // x1.00        x1.
-                    // x1.01        x1.
-                    // x1.10        x1. + 1
-                    // x1.11        x1. + 1
-                    //
-                    boolean leastZero = ((significand & 1L) == 0L);
-                    if ((leastZero && round && sticky) ||
-                            ((!leastZero) && round)) {
-                        significand++;
-                    }
-
-                    double value = isNegative ?
-                            Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
-                            Double.longBitsToDouble(significand );
-
-                    return new PreparedASCIIToBinaryBuffer(value, fValue);
-                }
-            }
-    }
-
-    /**
-     * Returns <code>s</code> with any leading zeros removed.
-     */
-    static String stripLeadingZeros(String s) {
-//        return  s.replaceFirst("^0+", "");
-        if(!s.isEmpty() && s.charAt(0)=='0') {
-            for(int i=1; i<s.length(); i++) {
-                if(s.charAt(i)!='0') {
-                    return s.substring(i);
-                }
-            }
-            return "";
-        }
-        return s;
-    }
-
-    /**
-     * Extracts a hexadecimal digit from position <code>position</code>
-     * of string <code>s</code>.
-     */
-    static int getHexDigit(String s, int position) {
-        int value = Character.digit(s.charAt(position), 16);
-        if (value <= -1 || value >= 16) {
-            throw new AssertionError("Unexpected failure of digit conversion of " +
-                                     s.charAt(position));
-        }
-        return value;
-    }
-}
diff --git a/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java b/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
deleted file mode 100644
index fc53920..0000000
--- a/ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.util.Arrays;
-
-public class FormattedFloatingDecimal{
-
-    public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
-
-
-    public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
-        FloatingDecimal.BinaryToASCIIConverter fdConverter =
-                FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
-        return new FormattedFloatingDecimal(precision,form, fdConverter);
-    }
-
-    private int decExponentRounded;
-    private char[] mantissa;
-    private char[] exponent;
-
-    private static final ThreadLocal<Object> threadLocalCharBuffer =
-            new ThreadLocal<Object>() {
-                @Override
-                protected Object initialValue() {
-                    return new char[20];
-                }
-            };
-
-    private static char[] getBuffer(){
-        return (char[]) threadLocalCharBuffer.get();
-    }
-
-    private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
-        if (fdConverter.isExceptional()) {
-            this.mantissa = fdConverter.toJavaFormatString().toCharArray();
-            this.exponent = null;
-            return;
-        }
-        char[] digits = getBuffer();
-        int nDigits = fdConverter.getDigits(digits);
-        int decExp = fdConverter.getDecimalExponent();
-        int exp;
-        boolean isNegative = fdConverter.isNegative();
-        switch (form) {
-            case COMPATIBLE:
-                exp = decExp;
-                this.decExponentRounded = exp;
-                fillCompatible(precision, digits, nDigits, exp, isNegative);
-                break;
-            case DECIMAL_FLOAT:
-                exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
-                fillDecimal(precision, digits, nDigits, exp, isNegative);
-                this.decExponentRounded = exp;
-                break;
-            case SCIENTIFIC:
-                exp = applyPrecision(decExp, digits, nDigits, precision + 1);
-                fillScientific(precision, digits, nDigits, exp, isNegative);
-                this.decExponentRounded = exp;
-                break;
-            case GENERAL:
-                exp = applyPrecision(decExp, digits, nDigits, precision);
-                // adjust precision to be the number of digits to right of decimal
-                // the real exponent to be output is actually exp - 1, not exp
-                if (exp - 1 < -4 || exp - 1 >= precision) {
-                    // form = Form.SCIENTIFIC;
-                    precision--;
-                    fillScientific(precision, digits, nDigits, exp, isNegative);
-                } else {
-                    // form = Form.DECIMAL_FLOAT;
-                    precision = precision - exp;
-                    fillDecimal(precision, digits, nDigits, exp, isNegative);
-                }
-                this.decExponentRounded = exp;
-                break;
-            default:
-                assert false;
-        }
-    }
-
-    // returns the exponent after rounding has been done by applyPrecision
-    public int getExponentRounded() {
-        return decExponentRounded - 1;
-    }
-
-    public char[] getMantissa(){
-        return mantissa;
-    }
-
-    public char[] getExponent(){
-        return exponent;
-    }
-
-    /**
-     * Returns new decExp in case of overflow.
-     */
-    private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
-        if (prec >= nDigits || prec < 0) {
-            // no rounding necessary
-            return decExp;
-        }
-        if (prec == 0) {
-            // only one digit (0 or 1) is returned because the precision
-            // excludes all significant digits
-            if (digits[0] >= '5') {
-                digits[0] = '1';
-                Arrays.fill(digits, 1, nDigits, '0');
-                return decExp + 1;
-            } else {
-                Arrays.fill(digits, 0, nDigits, '0');
-                return decExp;
-            }
-        }
-        int q = digits[prec];
-        if (q >= '5') {
-            int i = prec;
-            q = digits[--i];
-            if ( q == '9' ) {
-                while ( q == '9' && i > 0 ){
-                    q = digits[--i];
-                }
-                if ( q == '9' ){
-                    // carryout! High-order 1, rest 0s, larger exp.
-                    digits[0] = '1';
-                    Arrays.fill(digits, 1, nDigits, '0');
-                    return decExp+1;
-                }
-            }
-            digits[i] = (char)(q + 1);
-            Arrays.fill(digits, i+1, nDigits, '0');
-        } else {
-            Arrays.fill(digits, prec, nDigits, '0');
-        }
-        return decExp;
-    }
-
-    /**
-     * Fills mantissa and exponent char arrays for compatible format.
-     */
-    private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
-        int startIndex = isNegative ? 1 : 0;
-        if (exp > 0 && exp < 8) {
-            // print digits.digits.
-            if (nDigits < exp) {
-                int extraZeros = exp - nDigits;
-                mantissa = create(isNegative, nDigits + extraZeros + 2);
-                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
-                Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
-                mantissa[startIndex + nDigits + extraZeros] = '.';
-                mantissa[startIndex + nDigits + extraZeros+1] = '0';
-            } else if (exp < nDigits) {
-                int t = Math.min(nDigits - exp, precision);
-                mantissa = create(isNegative, exp + 1 + t);
-                System.arraycopy(digits, 0, mantissa, startIndex, exp);
-                mantissa[startIndex + exp ] = '.';
-                System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
-            } else { // exp == digits.length
-                mantissa = create(isNegative, nDigits + 2);
-                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
-                mantissa[startIndex + nDigits ] = '.';
-                mantissa[startIndex + nDigits +1] = '0';
-            }
-        } else if (exp <= 0 && exp > -3) {
-            int zeros = Math.max(0, Math.min(-exp, precision));
-            int t = Math.max(0, Math.min(nDigits, precision + exp));
-            // write '0' s before the significant digits
-            if (zeros > 0) {
-                mantissa = create(isNegative, zeros + 2 + t);
-                mantissa[startIndex] = '0';
-                mantissa[startIndex+1] = '.';
-                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
-                if (t > 0) {
-                    // copy only when significant digits are within the precision
-                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
-                }
-            } else if (t > 0) {
-                mantissa = create(isNegative, zeros + 2 + t);
-                mantissa[startIndex] = '0';
-                mantissa[startIndex + 1] = '.';
-                // copy only when significant digits are within the precision
-                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
-            } else {
-                this.mantissa = create(isNegative, 1);
-                this.mantissa[startIndex] = '0';
-            }
-        } else {
-            if (nDigits > 1) {
-                mantissa = create(isNegative, nDigits + 1);
-                mantissa[startIndex] = digits[0];
-                mantissa[startIndex + 1] = '.';
-                System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
-            } else {
-                mantissa = create(isNegative, 3);
-                mantissa[startIndex] = digits[0];
-                mantissa[startIndex + 1] = '.';
-                mantissa[startIndex + 2] = '0';
-            }
-            int e, expStartIntex;
-            boolean isNegExp = (exp <= 0);
-            if (isNegExp) {
-                e = -exp + 1;
-                expStartIntex = 1;
-            } else {
-                e = exp - 1;
-                expStartIntex = 0;
-            }
-            // decExponent has 1, 2, or 3, digits
-            if (e <= 9) {
-                exponent = create(isNegExp,1);
-                exponent[expStartIntex] = (char) (e + '0');
-            } else if (e <= 99) {
-                exponent = create(isNegExp,2);
-                exponent[expStartIntex] = (char) (e / 10 + '0');
-                exponent[expStartIntex+1] = (char) (e % 10 + '0');
-            } else {
-                exponent = create(isNegExp,3);
-                exponent[expStartIntex] = (char) (e / 100 + '0');
-                e %= 100;
-                exponent[expStartIntex+1] = (char) (e / 10 + '0');
-                exponent[expStartIntex+2] = (char) (e % 10 + '0');
-            }
-        }
-    }
-
-    private static char[] create(boolean isNegative, int size) {
-        if(isNegative) {
-            char[] r = new char[size +1];
-            r[0] = '-';
-            return r;
-        } else {
-            return new char[size];
-        }
-    }
-
-    /*
-     * Fills mantissa char arrays for DECIMAL_FLOAT format.
-     * Exponent should be equal to null.
-     */
-    private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
-        int startIndex = isNegative ? 1 : 0;
-        if (exp > 0) {
-            // print digits.digits.
-            if (nDigits < exp) {
-                mantissa = create(isNegative,exp);
-                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
-                Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
-                // Do not append ".0" for formatted floats since the user
-                // may request that it be omitted. It is added as necessary
-                // by the Formatter.
-            } else {
-                int t = Math.min(nDigits - exp, precision);
-                mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
-                System.arraycopy(digits, 0, mantissa, startIndex, exp);
-                // Do not append ".0" for formatted floats since the user
-                // may request that it be omitted. It is added as necessary
-                // by the Formatter.
-                if (t > 0) {
-                    mantissa[startIndex + exp] = '.';
-                    System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
-                }
-            }
-        } else if (exp <= 0) {
-            int zeros = Math.max(0, Math.min(-exp, precision));
-            int t = Math.max(0, Math.min(nDigits, precision + exp));
-            // write '0' s before the significant digits
-            if (zeros > 0) {
-                mantissa = create(isNegative, zeros + 2 + t);
-                mantissa[startIndex] = '0';
-                mantissa[startIndex+1] = '.';
-                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
-                if (t > 0) {
-                    // copy only when significant digits are within the precision
-                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
-                }
-            } else if (t > 0) {
-                mantissa = create(isNegative, zeros + 2 + t);
-                mantissa[startIndex] = '0';
-                mantissa[startIndex + 1] = '.';
-                // copy only when significant digits are within the precision
-                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
-            } else {
-                this.mantissa = create(isNegative, 1);
-                this.mantissa[startIndex] = '0';
-            }
-        }
-    }
-
-    /**
-     * Fills mantissa and exponent char arrays for SCIENTIFIC format.
-     */
-    private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
-        int startIndex = isNegative ? 1 : 0;
-        int t = Math.max(0, Math.min(nDigits - 1, precision));
-        if (t > 0) {
-            mantissa = create(isNegative, t + 2);
-            mantissa[startIndex] = digits[0];
-            mantissa[startIndex + 1] = '.';
-            System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
-        } else {
-            mantissa = create(isNegative, 1);
-            mantissa[startIndex] = digits[0];
-        }
-        char expSign;
-        int e;
-        if (exp <= 0) {
-            expSign = '-';
-            e = -exp + 1;
-        } else {
-            expSign = '+' ;
-            e = exp - 1;
-        }
-        // decExponent has 1, 2, or 3, digits
-        if (e <= 9) {
-            exponent = new char[] { expSign,
-                    '0', (char) (e + '0') };
-        } else if (e <= 99) {
-            exponent = new char[] { expSign,
-                    (char) (e / 10 + '0'), (char) (e % 10 + '0') };
-        } else {
-            char hiExpChar = (char) (e / 100 + '0');
-            e %= 100;
-            exponent = new char[] { expSign,
-                    hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
-        }
-    }
-}
diff --git a/ojluni/src/main/java/sun/misc/FpUtils.java b/ojluni/src/main/java/sun/misc/FpUtils.java
index a874c80..9711894 100644
--- a/ojluni/src/main/java/sun/misc/FpUtils.java
+++ b/ojluni/src/main/java/sun/misc/FpUtils.java
@@ -25,8 +25,8 @@
 
 package sun.misc;
 
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FloatConsts;
 
 /**
  * The class {@code FpUtils} contains static utility methods for
diff --git a/ojluni/src/main/java/sun/misc/Unsafe.java b/ojluni/src/main/java/sun/misc/Unsafe.java
index e538b73..59d8df5 100644
--- a/ojluni/src/main/java/sun/misc/Unsafe.java
+++ b/ojluni/src/main/java/sun/misc/Unsafe.java
@@ -26,6 +26,7 @@
 package sun.misc;
 
 import dalvik.annotation.optimization.FastNative;
+import jdk.internal.HotSpotIntrinsicCandidate;
 import sun.reflect.Reflection;
 
 import java.lang.reflect.Field;
@@ -698,7 +699,7 @@
      * @return the previous value
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public final int getAndAddInt(Object o, long offset, int delta) {
         int v;
         do {
@@ -718,7 +719,7 @@
      * @return the previous value
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public final long getAndAddLong(Object o, long offset, long delta) {
         long v;
         do {
@@ -738,7 +739,7 @@
      * @return the previous value
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public final int getAndSetInt(Object o, long offset, int newValue) {
         int v;
         do {
@@ -758,7 +759,7 @@
      * @return the previous value
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public final long getAndSetLong(Object o, long offset, long newValue) {
         long v;
         do {
@@ -778,7 +779,7 @@
      * @return the previous value
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     public final Object getAndSetObject(Object o, long offset, Object newValue) {
         Object v;
         do {
@@ -800,7 +801,7 @@
      * provide a LoadLoad barrier also provide a LoadStore barrier for free.
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     @FastNative
     public native void loadFence();
 
@@ -816,7 +817,7 @@
      * provide a StoreStore barrier also provide a LoadStore barrier for free.
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     @FastNative
     public native void storeFence();
 
@@ -829,7 +830,7 @@
      * Corresponds to C11 atomic_thread_fence(memory_order_seq_cst).
      * @since 1.8
      */
-    // @HotSpotIntrinsicCandidate
+    @HotSpotIntrinsicCandidate
     @FastNative
     public native void fullFence();
 }
diff --git a/ojluni/src/main/java/sun/net/ext/ExtendedSocketOptions.java b/ojluni/src/main/java/sun/net/ext/ExtendedSocketOptions.java
new file mode 100644
index 0000000..4036e11
--- /dev/null
+++ b/ojluni/src/main/java/sun/net/ext/ExtendedSocketOptions.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.ext;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.util.Collections;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Defines the infrastructure to support extended socket options, beyond those
+ * defined in {@link java.net.StandardSocketOptions}.
+ *
+ * Extended socket options are accessed through the jdk.net API, which is in
+ * the jdk.net module.
+ */
+public abstract class ExtendedSocketOptions {
+
+    public static final short SOCK_STREAM = 1;
+    public static final short SOCK_DGRAM = 2;
+
+    private final Set<SocketOption<?>> options;
+
+    /** Tells whether or not the option is supported. */
+    public final boolean isOptionSupported(SocketOption<?> option) {
+        return options().contains(option);
+    }
+
+    /** Return the, possibly empty, set of extended socket options available. */
+    public final Set<SocketOption<?>> options() { return options; }
+
+    public static final Set<SocketOption<?>> options(short type) {
+        return getInstance().options0(type);
+    }
+
+    private Set<SocketOption<?>> options0(short type) {
+        Set<SocketOption<?>> extOptions = null;
+        switch (type) {
+            case SOCK_DGRAM:
+                extOptions = options.stream()
+                        .filter((option) -> !option.name().startsWith("TCP_"))
+                        .collect(Collectors.toUnmodifiableSet());
+                break;
+            case SOCK_STREAM:
+                extOptions = options.stream()
+                        .filter((option) -> !option.name().startsWith("UDP_"))
+                        .collect(Collectors.toUnmodifiableSet());
+                break;
+            default:
+                //this will never happen
+                throw new IllegalArgumentException("Invalid socket option type");
+        }
+        return extOptions;
+    }
+
+    /** Sets the value of a socket option, for the given socket. */
+    public abstract void setOption(FileDescriptor fd, SocketOption<?> option, Object value)
+            throws SocketException;
+
+    /** Returns the value of a socket option, for the given socket. */
+    public abstract Object getOption(FileDescriptor fd, SocketOption<?> option)
+            throws SocketException;
+
+    protected ExtendedSocketOptions(Set<SocketOption<?>> options) {
+        this.options = options;
+    }
+
+    private static volatile ExtendedSocketOptions instance;
+
+    public static final ExtendedSocketOptions getInstance() { return instance; }
+
+    /** Registers support for extended socket options. Invoked by the jdk.net module. */
+    public static final void register(ExtendedSocketOptions extOptions) {
+        if (instance != null)
+            throw new InternalError("Attempting to reregister extended options");
+
+        instance = extOptions;
+    }
+
+    static {
+        try {
+            // If the class is present, it will be initialized which
+            // triggers registration of the extended socket options.
+            Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");
+        } catch (ClassNotFoundException e) {
+            // the jdk.net module is not present => no extended socket options
+            instance = new NoExtendedSocketOptions();
+        }
+    }
+
+    static final class NoExtendedSocketOptions extends ExtendedSocketOptions {
+
+        NoExtendedSocketOptions() {
+            super(Collections.<SocketOption<?>>emptySet());
+        }
+
+        @Override
+        public void setOption(FileDescriptor fd, SocketOption<?> option, Object value)
+            throws SocketException
+        {
+            throw new UnsupportedOperationException(
+                    "no extended options: " + option.name());
+        }
+
+        @Override
+        public Object getOption(FileDescriptor fd, SocketOption<?> option)
+            throws SocketException
+        {
+            throw new UnsupportedOperationException(
+                    "no extended options: " + option.name());
+        }
+    }
+}
diff --git a/ojluni/src/main/java/sun/nio/ch/AllocatedNativeObject.java b/ojluni/src/main/java/sun/nio/ch/AllocatedNativeObject.java
index 2406cb8..6709ce1 100644
--- a/ojluni/src/main/java/sun/nio/ch/AllocatedNativeObject.java
+++ b/ojluni/src/main/java/sun/nio/ch/AllocatedNativeObject.java
@@ -36,14 +36,14 @@
 {
 
     /**
-     * Allocates a memory area of at least <tt>size</tt> bytes outside of the
+     * Allocates a memory area of at least {@code size} bytes outside of the
      * Java heap and creates a native object for that area.
      *
      * @param  size
      *         Number of bytes to allocate
      *
      * @param  pageAligned
-     *         If <tt>true</tt> then the area will be aligned on a hardware
+     *         If {@code true} then the area will be aligned on a hardware
      *         page boundary
      *
      * @throws OutOfMemoryError
diff --git a/ojluni/src/main/java/sun/nio/ch/ChannelInputStream.java b/ojluni/src/main/java/sun/nio/ch/ChannelInputStream.java
index e2f8092..4237365 100644
--- a/ojluni/src/main/java/sun/nio/ch/ChannelInputStream.java
+++ b/ojluni/src/main/java/sun/nio/ch/ChannelInputStream.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
 import java.nio.*;
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
-
+import java.util.Objects;
 
 /**
  * This class is defined here rather than in java.nio.channels.Channels
@@ -88,10 +88,8 @@
     public synchronized int read(byte[] bs, int off, int len)
         throws IOException
     {
-        if ((off < 0) || (off > bs.length) || (len < 0) ||
-            ((off + len) > bs.length) || ((off + len) < 0)) {
-            throw new IndexOutOfBoundsException();
-        } else if (len == 0)
+        Objects.checkFromIndexSize(off, len, bs.length);
+        if (len == 0)
             return 0;
 
         ByteBuffer bb = ((this.bs == bs)
@@ -120,6 +118,27 @@
         return 0;
     }
 
+    public synchronized long skip(long n) throws IOException {
+        // special case where the channel is to a file
+        if (ch instanceof SeekableByteChannel) {
+            SeekableByteChannel sbc = (SeekableByteChannel)ch;
+            long pos = sbc.position();
+            long newPos;
+            if (n > 0) {
+                newPos = pos + n;
+                long size = sbc.size();
+                if (newPos < 0 || newPos > size) {
+                    newPos = size;
+                }
+            } else {
+                newPos = Long.max(pos + n, 0);
+            }
+            sbc.position(newPos);
+            return newPos - pos;
+        }
+        return super.skip(n);
+    }
+
     public void close() throws IOException {
         ch.close();
     }
diff --git a/ojluni/src/main/java/sun/nio/ch/FileKey.java b/ojluni/src/main/java/sun/nio/ch/FileKey.java
index cb2ce53..bde23b4 100644
--- a/ojluni/src/main/java/sun/nio/ch/FileKey.java
+++ b/ojluni/src/main/java/sun/nio/ch/FileKey.java
@@ -38,13 +38,9 @@
 
     private FileKey() { }
 
-    public static FileKey create(FileDescriptor fd) {
+    public static FileKey create(FileDescriptor fd) throws IOException {
         FileKey fk = new FileKey();
-        try {
-            fk.init(fd);
-        } catch (IOException ioe) {
-            throw new Error(ioe);
-        }
+        fk.init(fd);
         return fk;
     }
 
diff --git a/ojluni/src/main/java/sun/nio/ch/FileLockImpl.java b/ojluni/src/main/java/sun/nio/ch/FileLockImpl.java
index 05bc576..1b00761 100644
--- a/ojluni/src/main/java/sun/nio/ch/FileLockImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/FileLockImpl.java
@@ -31,7 +31,7 @@
 public class FileLockImpl
     extends FileLock
 {
-    private volatile boolean valid = true;
+    private volatile boolean invalid;
 
     FileLockImpl(FileChannel channel, long position, long size, boolean shared)
     {
@@ -44,25 +44,25 @@
     }
 
     public boolean isValid() {
-        return valid;
+        return !invalid;
     }
 
     void invalidate() {
         assert Thread.holdsLock(this);
-        valid = false;
+        invalid = true;
     }
 
     public synchronized void release() throws IOException {
         Channel ch = acquiredBy();
         if (!ch.isOpen())
             throw new ClosedChannelException();
-        if (valid) {
+        if (isValid()) {
             if (ch instanceof FileChannelImpl)
                 ((FileChannelImpl)ch).release(this);
             else if (ch instanceof AsynchronousFileChannelImpl)
                 ((AsynchronousFileChannelImpl)ch).release(this);
             else throw new AssertionError();
-            valid = false;
+            invalidate();
         }
     }
 }
diff --git a/ojluni/src/main/java/sun/nio/ch/Invoker.java b/ojluni/src/main/java/sun/nio/ch/Invoker.java
index 386f736..1d3e793 100644
--- a/ojluni/src/main/java/sun/nio/ch/Invoker.java
+++ b/ojluni/src/main/java/sun/nio/ch/Invoker.java
@@ -136,9 +136,9 @@
         /*
         if (System.getSecurityManager() != null) {
             Thread me = Thread.currentThread();
-            if (me instanceof sun.misc.InnocuousThread) {
+            if (me instanceof InnocuousThread) {
                 GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
-                ((sun.misc.InnocuousThread)me).eraseThreadLocals();
+                ((InnocuousThread)me).eraseThreadLocals();
                 if (thisGroupAndInvokeCount != null) {
                     myGroupAndInvokeCount.set(thisGroupAndInvokeCount);
                 }
diff --git a/ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java b/ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java
index 5ecc396..46d6536 100644
--- a/ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/MembershipKeyImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,11 @@
 
 package sun.nio.ch;
 
-import java.nio.channels.*;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
 import java.io.IOException;
+import java.nio.channels.MembershipKey;
+import java.nio.channels.MulticastChannel;
 import java.util.HashSet;
 
 /**
@@ -43,11 +44,10 @@
     private final NetworkInterface interf;
     private final InetAddress source;
 
-    // true when key is valid
-    private volatile boolean valid = true;
+    private volatile boolean invalid;
 
     // lock used when creating or accessing blockedSet
-    private Object stateLock = new Object();
+    private final Object stateLock = new Object();
 
     // set of source addresses that are blocked
     private HashSet<InetAddress> blockedSet;
@@ -134,12 +134,12 @@
     }
 
     public boolean isValid() {
-        return valid;
+        return !invalid;
     }
 
     // package-private
     void invalidate() {
-        valid = false;
+        invalid = true;
     }
 
     public void drop() {
@@ -184,7 +184,7 @@
 
             // created blocked set if required and add source address
             if (blockedSet == null)
-                blockedSet = new HashSet<InetAddress>();
+                blockedSet = new HashSet<>();
             blockedSet.add(toBlock);
         }
         return this;
diff --git a/ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java b/ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java
index 6607fc8..9f01c51 100644
--- a/ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java
+++ b/ojluni/src/main/java/sun/nio/ch/MembershipRegistry.java
@@ -84,13 +84,13 @@
         InetAddress group = key.group();
         List<MembershipKeyImpl> keys;
         if (groups == null) {
-            groups = new HashMap<InetAddress,List<MembershipKeyImpl>>();
+            groups = new HashMap<>();
             keys = null;
         } else {
             keys = groups.get(group);
         }
         if (keys == null) {
-            keys = new LinkedList<MembershipKeyImpl>();
+            keys = new LinkedList<>();
             groups.put(group, keys);
         }
         keys.add(key);
diff --git a/ojluni/src/main/java/sun/nio/ch/PipeImpl.java b/ojluni/src/main/java/sun/nio/ch/PipeImpl.java
index 0e8a549..f4ef6ce 100644
--- a/ojluni/src/main/java/sun/nio/ch/PipeImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/PipeImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
     private final SourceChannel source;
     private final SinkChannel sink;
 
-    PipeImpl(SelectorProvider sp) {
+    PipeImpl(SelectorProvider sp) throws IOException {
         long pipeFds = IOUtil.makePipe(true);
         int readFd = (int) (pipeFds >>> 32);
         int writeFd = (int) pipeFds;
diff --git a/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java b/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java
index d4ce6a1..644aeff 100644
--- a/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java
+++ b/ojluni/src/main/java/sun/nio/ch/PollSelectorProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,8 @@
 package sun.nio.ch;
 
 import java.io.IOException;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
+import java.nio.channels.Channel;
+import java.nio.channels.spi.AbstractSelector;
 
 public class PollSelectorProvider
     extends SelectorProviderImpl
diff --git a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
index cb5a33b..df44ebe 100644
--- a/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java
@@ -46,7 +46,7 @@
     extends AsynchronousServerSocketChannelImpl
     implements Port.PollableChannel
 {
-    private final static NativeDispatcher nd = new SocketDispatcher();
+    private static final NativeDispatcher nd = new SocketDispatcher();
 
     private final Port port;
     private final int fdVal;
@@ -239,7 +239,7 @@
         // permission check must always be in initiator's context
         try {
             if (acc != null) {
-                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                AccessController.doPrivileged(new PrivilegedAction<>() {
                     public Void run() {
                         SecurityManager sm = System.getSecurityManager();
                         if (sm != null) {
@@ -310,7 +310,7 @@
                 synchronized (updateLock) {
                     if (handler == null) {
                         this.acceptHandler = null;
-                        result = new PendingFuture<AsynchronousSocketChannel,Object>(this);
+                        result = new PendingFuture<>(this);
                         this.acceptFuture = result;
                     } else {
                         this.acceptHandler = handler;
diff --git a/ojluni/src/main/java/sun/nio/fs/AbstractUserDefinedFileAttributeView.java b/ojluni/src/main/java/sun/nio/fs/AbstractUserDefinedFileAttributeView.java
index 3886aa1..a349b08 100644
--- a/ojluni/src/main/java/sun/nio/fs/AbstractUserDefinedFileAttributeView.java
+++ b/ojluni/src/main/java/sun/nio/fs/AbstractUserDefinedFileAttributeView.java
@@ -83,7 +83,7 @@
                 names = list();
                 break;
             } else {
-                if (name.length() == 0)
+                if (name.isEmpty())
                     throw new IllegalArgumentException();
                 names.add(name);
             }
diff --git a/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java b/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java
index 0532e4d..8c7031b 100644
--- a/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java
+++ b/ojluni/src/main/java/sun/nio/fs/UnixFileStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,11 +27,8 @@
 
 import java.nio.file.*;
 import java.nio.file.attribute.*;
-import java.nio.channels.*;
 import java.util.*;
 import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 
 /**
  * Base implementation of FileStore for Unix/like implementations.
@@ -126,6 +123,12 @@
     }
 
     @Override
+    public long getBlockSize() throws IOException {
+       UnixFileStoreAttributes attrs = readAttributes();
+       return attrs.blockSize();
+    }
+
+    @Override
     public long getUnallocatedSpace() throws IOException {
         UnixFileStoreAttributes attrs = readAttributes();
         return attrs.blockSize() * attrs.freeBlocks();
@@ -218,12 +221,17 @@
     /**
      * Returns status to indicate if file system supports a given feature
      */
+    // BEGIN Android-changed: fstypes properties file is not used on Android.
+    FeatureStatus checkIfFeaturePresent(String feature) {
+        return FeatureStatus.UNKNOWN;
+    }
+    /*
     FeatureStatus checkIfFeaturePresent(String feature) {
         if (props == null) {
             synchronized (loadLock) {
                 if (props == null) {
                     props = AccessController.doPrivileged(
-                        new PrivilegedAction<Properties>() {
+                        new PrivilegedAction<>() {
                             @Override
                             public Properties run() {
                                 return loadProperties();
@@ -253,14 +261,16 @@
 
     private static Properties loadProperties() {
         Properties result = new Properties();
-        String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
-        Path file = Paths.get(fstypes);
+        String fstypes = StaticProperty.javaHome() + "/lib/fstypes.properties";
+        Path file = Path.of(fstypes);
         try {
             try (ReadableByteChannel rbc = Files.newByteChannel(file)) {
-                result.load(Channels.newReader(rbc, "UTF-8"));
+                result.load(Channels.newReader(rbc, UTF_8.INSTANCE));
             }
         } catch (IOException x) {
         }
         return result;
     }
+    */
+    // END Android-changed: fstypes properties file is not used on Android.
 }
diff --git a/ojluni/src/main/java/sun/security/action/GetPropertyAction.java b/ojluni/src/main/java/sun/security/action/GetPropertyAction.java
index 4ed9bde..44ec16f 100644
--- a/ojluni/src/main/java/sun/security/action/GetPropertyAction.java
+++ b/ojluni/src/main/java/sun/security/action/GetPropertyAction.java
@@ -25,6 +25,10 @@
 
 package sun.security.action;
 
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Properties;
+
 /**
  * A convenience class for retrieving the string value of a system
  * property as a privileged action.
@@ -33,7 +37,7 @@
  * <code>AccessController.doPrivileged</code>.
  *
  * <p>The following code retrieves the value of the system
- * property named <code>"prop"</code> as a privileged action: <p>
+ * property named <code>"prop"</code> as a privileged action:
  *
  * <pre>
  * String s = java.security.AccessController.doPrivileged
@@ -46,8 +50,7 @@
  * @since 1.2
  */
 
-public class GetPropertyAction
-        implements java.security.PrivilegedAction<String> {
+public class GetPropertyAction implements PrivilegedAction<String> {
     private String theProp;
     private String defaultVal;
 
@@ -66,7 +69,7 @@
      * value of that property.
      *
      * @param theProp the name of the system property.
-     * @param defaulVal the default value.
+     * @param defaultVal the default value.
      */
     public GetPropertyAction(String theProp, String defaultVal) {
         this.theProp = theProp;
@@ -84,4 +87,73 @@
         String value = System.getProperty(theProp);
         return (value == null) ? defaultVal : value;
     }
+
+    /**
+     * Convenience method to get a property without going through doPrivileged
+     * if no security manager is present. This is unsafe for inclusion in a
+     * public API but allowable here since this class is now encapsulated.
+     *
+     * Note that this method performs a privileged action using caller-provided
+     * inputs. The caller of this method should take care to ensure that the
+     * inputs are not tainted and the returned property is not made accessible
+     * to untrusted code if it contains sensitive information.
+     *
+     * @param theProp the name of the system property.
+     */
+    public static String privilegedGetProperty(String theProp) {
+        if (System.getSecurityManager() == null) {
+            return System.getProperty(theProp);
+        } else {
+            return AccessController.doPrivileged(
+                    new GetPropertyAction(theProp));
+        }
+    }
+
+    /**
+     * Convenience method to get a property without going through doPrivileged
+     * if no security manager is present. This is unsafe for inclusion in a
+     * public API but allowable here since this class is now encapsulated.
+     *
+     * Note that this method performs a privileged action using caller-provided
+     * inputs. The caller of this method should take care to ensure that the
+     * inputs are not tainted and the returned property is not made accessible
+     * to untrusted code if it contains sensitive information.
+     *
+     * @param theProp the name of the system property.
+     * @param defaultVal the default value.
+     */
+    public static String privilegedGetProperty(String theProp,
+            String defaultVal) {
+        if (System.getSecurityManager() == null) {
+            return System.getProperty(theProp, defaultVal);
+        } else {
+            return AccessController.doPrivileged(
+                    new GetPropertyAction(theProp, defaultVal));
+        }
+    }
+
+    /**
+     * Convenience method to call <code>System.getProperties</code> without
+     * having to go through doPrivileged if no security manager is present.
+     * This is unsafe for inclusion in a public API but allowable here since
+     * this class is now encapsulated.
+     *
+     * Note that this method performs a privileged action, and callers of
+     * this method should take care to ensure that the returned properties
+     * are not made accessible to untrusted code since it may contain
+     * sensitive information.
+     */
+    public static Properties privilegedGetProperties() {
+        if (System.getSecurityManager() == null) {
+            return System.getProperties();
+        } else {
+            return AccessController.doPrivileged(
+                    new PrivilegedAction<Properties>() {
+                        public Properties run() {
+                            return System.getProperties();
+                        }
+                    }
+            );
+        }
+    }
 }
diff --git a/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java b/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
index ea12395..73d3ab5 100644
--- a/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
+++ b/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
@@ -96,7 +96,7 @@
     PKCS9Attributes authenticatedAttributes;
     PKCS9Attributes unauthenticatedAttributes;
 
-    // Android-added: No-arg constructor to use in @libcore.api.CorePlatformApi
+    // Android-added: No-arg constructor to use in @SystemApi(client = MODULE_LIBRARIES)
     public SignerInfo() {}
 
     public SignerInfo(X500Name  issuerName,
diff --git a/ojluni/src/main/java/sun/security/util/HexDumpEncoder.java b/ojluni/src/main/java/sun/security/util/HexDumpEncoder.java
new file mode 100644
index 0000000..9726a4f
--- /dev/null
+++ b/ojluni/src/main/java/sun/security/util/HexDumpEncoder.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package sun.security.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * This class encodes a buffer into the classic: "Hexadecimal Dump" format of
+ * the past. It is useful for analyzing the contents of binary buffers.
+ * The format produced is as follows:
+ * <pre>
+ * xxxx: 00 11 22 33 44 55 66 77   88 99 aa bb cc dd ee ff ................
+ * </pre>
+ * Where xxxx is the offset into the buffer in 16 byte chunks, followed
+ * by ascii coded hexadecimal bytes followed by the ASCII representation of
+ * the bytes or '.' if they are not valid bytes.
+ *
+ * @author      Chuck McManis
+ */
+
+public class HexDumpEncoder {
+
+    private int offset;
+    private int thisLineLength;
+    private int currentByte;
+    private byte thisLine[] = new byte[16];
+
+    static void hexDigit(PrintStream p, byte x) {
+        char c;
+
+        c = (char) ((x >> 4) & 0xf);
+        if (c > 9)
+            c = (char) ((c-10) + 'A');
+        else
+            c = (char)(c + '0');
+        p.write(c);
+        c = (char) (x & 0xf);
+        if (c > 9)
+            c = (char)((c-10) + 'A');
+        else
+            c = (char)(c + '0');
+        p.write(c);
+    }
+
+    protected int bytesPerAtom() {
+        return (1);
+    }
+
+    protected int bytesPerLine() {
+        return (16);
+    }
+
+    protected void encodeBufferPrefix(OutputStream o) throws IOException {
+        offset = 0;
+        pStream = new PrintStream(o);
+    }
+
+    protected void encodeLinePrefix(OutputStream o, int len) throws IOException {
+        hexDigit(pStream, (byte)((offset >>> 8) & 0xff));
+        hexDigit(pStream, (byte)(offset & 0xff));
+        pStream.print(": ");
+        currentByte = 0;
+        thisLineLength = len;
+    }
+
+    protected void encodeAtom(OutputStream o, byte buf[], int off, int len) throws IOException {
+        thisLine[currentByte] = buf[off];
+        hexDigit(pStream, buf[off]);
+        pStream.print(" ");
+        currentByte++;
+        if (currentByte == 8)
+            pStream.print("  ");
+    }
+
+    protected void encodeLineSuffix(OutputStream o) throws IOException {
+        if (thisLineLength < 16) {
+            for (int i = thisLineLength; i < 16; i++) {
+                pStream.print("   ");
+                if (i == 7)
+                    pStream.print("  ");
+            }
+        }
+        pStream.print(" ");
+        for (int i = 0; i < thisLineLength; i++) {
+            if ((thisLine[i] < ' ') || (thisLine[i] > 'z')) {
+                pStream.print(".");
+            } else {
+                pStream.write(thisLine[i]);
+            }
+        }
+        pStream.println();
+        offset += thisLineLength;
+    }
+
+    /** Stream that understands "printing" */
+    protected PrintStream pStream;
+
+    /**
+     * This method works around the bizarre semantics of BufferedInputStream's
+     * read method.
+     */
+    protected int readFully(InputStream in, byte buffer[])
+            throws java.io.IOException {
+        for (int i = 0; i < buffer.length; i++) {
+            int q = in.read();
+            if (q == -1)
+                return i;
+            buffer[i] = (byte)q;
+        }
+        return buffer.length;
+    }
+
+    /**
+     * Encode bytes from the input stream, and write them as text characters
+     * to the output stream. This method will run until it exhausts the
+     * input stream, but does not print the line suffix for a final
+     * line that is shorter than bytesPerLine().
+     */
+    public void encode(InputStream inStream, OutputStream outStream)
+        throws IOException
+    {
+        int     j;
+        int     numBytes;
+        byte    tmpbuffer[] = new byte[bytesPerLine()];
+
+        encodeBufferPrefix(outStream);
+
+        while (true) {
+            numBytes = readFully(inStream, tmpbuffer);
+            if (numBytes == 0) {
+                break;
+            }
+            encodeLinePrefix(outStream, numBytes);
+            for (j = 0; j < numBytes; j += bytesPerAtom()) {
+
+                if ((j + bytesPerAtom()) <= numBytes) {
+                    encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
+                } else {
+                    encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
+                }
+            }
+            if (numBytes < bytesPerLine()) {
+                break;
+            } else {
+                encodeLineSuffix(outStream);
+            }
+        }
+    }
+
+    /**
+     * A 'streamless' version of encode that simply takes a buffer of
+     * bytes and returns a string containing the encoded buffer.
+     */
+    public String encode(byte aBuffer[]) {
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        ByteArrayInputStream    inStream = new ByteArrayInputStream(aBuffer);
+        String retVal = null;
+        try {
+            encode(inStream, outStream);
+            // explicit ascii->unicode conversion
+            retVal = outStream.toString("ISO-8859-1");
+        } catch (Exception IOException) {
+            // This should never happen.
+            throw new Error("CharacterEncoder.encode internal error");
+        }
+        return (retVal);
+    }
+
+    /**
+     * Return a byte array from the remaining bytes in this ByteBuffer.
+     * <P>
+     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
+     * <P>
+     * To avoid an extra copy, the implementation will attempt to return the
+     * byte array backing the ByteBuffer.  If this is not possible, a
+     * new byte array will be created.
+     */
+    private byte [] getBytes(ByteBuffer bb) {
+        /*
+         * This should never return a BufferOverflowException, as we're
+         * careful to allocate just the right amount.
+         */
+        byte [] buf = null;
+
+        /*
+         * If it has a usable backing byte buffer, use it.  Use only
+         * if the array exactly represents the current ByteBuffer.
+         */
+        if (bb.hasArray()) {
+            byte [] tmp = bb.array();
+            if ((tmp.length == bb.capacity()) &&
+                    (tmp.length == bb.remaining())) {
+                buf = tmp;
+                bb.position(bb.limit());
+            }
+        }
+
+        if (buf == null) {
+            /*
+             * This class doesn't have a concept of encode(buf, len, off),
+             * so if we have a partial buffer, we must reallocate
+             * space.
+             */
+            buf = new byte[bb.remaining()];
+
+            /*
+             * position() automatically updated
+             */
+            bb.get(buf);
+        }
+
+        return buf;
+    }
+
+    /**
+     * A 'streamless' version of encode that simply takes a ByteBuffer
+     * and returns a string containing the encoded buffer.
+     * <P>
+     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
+     */
+    public String encode(ByteBuffer aBuffer) {
+        byte [] buf = getBytes(aBuffer);
+        return encode(buf);
+    }
+
+    /**
+     * Encode bytes from the input stream, and write them as text characters
+     * to the output stream. This method will run until it exhausts the
+     * input stream. It differs from encode in that it will add the
+     * line at the end of a final line that is shorter than bytesPerLine().
+     */
+    public void encodeBuffer(InputStream inStream, OutputStream outStream)
+        throws IOException
+    {
+        int     j;
+        int     numBytes;
+        byte    tmpbuffer[] = new byte[bytesPerLine()];
+
+        encodeBufferPrefix(outStream);
+
+        while (true) {
+            numBytes = readFully(inStream, tmpbuffer);
+            if (numBytes == 0) {
+                break;
+            }
+            encodeLinePrefix(outStream, numBytes);
+            for (j = 0; j < numBytes; j += bytesPerAtom()) {
+                if ((j + bytesPerAtom()) <= numBytes) {
+                    encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
+                } else {
+                    encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
+                }
+            }
+            encodeLineSuffix(outStream);
+            if (numBytes < bytesPerLine()) {
+                break;
+            }
+        }
+    }
+
+    /**
+     * Encode the buffer in <i>aBuffer</i> and write the encoded
+     * result to the OutputStream <i>aStream</i>.
+     */
+    public void encodeBuffer(byte aBuffer[], OutputStream aStream)
+        throws IOException
+    {
+        ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
+        encodeBuffer(inStream, aStream);
+    }
+
+    /**
+     * A 'streamless' version of encode that simply takes a buffer of
+     * bytes and returns a string containing the encoded buffer.
+     */
+    public String encodeBuffer(byte aBuffer[]) {
+        ByteArrayOutputStream   outStream = new ByteArrayOutputStream();
+        ByteArrayInputStream    inStream = new ByteArrayInputStream(aBuffer);
+        try {
+            encodeBuffer(inStream, outStream);
+        } catch (Exception IOException) {
+            // This should never happen.
+            throw new Error("CharacterEncoder.encodeBuffer internal error");
+        }
+        return (outStream.toString());
+    }
+
+    /**
+     * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
+     * result to the OutputStream <i>aStream</i>.
+     * <P>
+     * The ByteBuffer's position will be advanced to ByteBuffer's limit.
+     */
+    public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)
+        throws IOException
+    {
+        byte [] buf = getBytes(aBuffer);
+        encodeBuffer(buf, aStream);
+    }
+
+}
diff --git a/ojluni/src/main/java/sun/security/util/SecurityConstants.java b/ojluni/src/main/java/sun/security/util/SecurityConstants.java
index 41e80e5..a13181b 100644
--- a/ojluni/src/main/java/sun/security/util/SecurityConstants.java
+++ b/ojluni/src/main/java/sun/security/util/SecurityConstants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,14 +25,13 @@
 
 package sun.security.util;
 
+import java.lang.reflect.ReflectPermission;
 import java.net.SocketPermission;
 import java.net.NetPermission;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.security.Permission;
-import java.security.BasicPermission;
 import java.security.SecurityPermission;
 import java.security.AllPermission;
+import sun.security.action.GetPropertyAction;
 
 /**
  * Permission constants and string constants used to create permissions
@@ -70,84 +69,6 @@
     // sun.security.provider.PolicyFile
     public static final AllPermission ALL_PERMISSION = new AllPermission();
 
-    /**
-     * AWT Permissions used in the JDK.
-     */
-    // BEGIN Android-removed
-    /*
-    public static class AWT {
-        private AWT() { }
-
-        // The class name of the factory to create java.awt.AWTPermission objects.
-        private static final String AWTFactory = "sun.awt.AWTPermissionFactory";
-
-        // The PermissionFactory to create AWT permissions (or null if AWT is
-        // not present)
-        private static final PermissionFactory<?> factory = permissionFactory();
-
-        private static PermissionFactory<?> permissionFactory() {
-            Class<?> c;
-            try {
-                c = Class.forName(AWTFactory, false, AWT.class.getClassLoader());
-            } catch (ClassNotFoundException e) {
-                // not available
-                return null;
-            }
-            // AWT present
-            try {
-                return (PermissionFactory<?>)c.newInstance();
-            } catch (ReflectiveOperationException x) {
-                throw new InternalError(x);
-            }
-        }
-
-        private static Permission newAWTPermission(String name) {
-            return (factory == null) ? null : factory.newPermission(name);
-        }
-
-        // java.lang.SecurityManager
-        public static final Permission TOPLEVEL_WINDOW_PERMISSION =
-            newAWTPermission("showWindowWithoutWarningBanner");
-
-        // java.lang.SecurityManager
-        public static final Permission ACCESS_CLIPBOARD_PERMISSION =
-            newAWTPermission("accessClipboard");
-
-        // java.lang.SecurityManager
-        public static final Permission CHECK_AWT_EVENTQUEUE_PERMISSION =
-            newAWTPermission("accessEventQueue");
-
-        // java.awt.Dialog
-        public static final Permission TOOLKIT_MODALITY_PERMISSION =
-            newAWTPermission("toolkitModality");
-
-        // java.awt.Robot
-        public static final Permission READ_DISPLAY_PIXELS_PERMISSION =
-            newAWTPermission("readDisplayPixels");
-
-        // java.awt.Robot
-        public static final Permission CREATE_ROBOT_PERMISSION =
-            newAWTPermission("createRobot");
-
-        // java.awt.MouseInfo
-        public static final Permission WATCH_MOUSE_PERMISSION =
-            newAWTPermission("watchMousePointer");
-
-        // java.awt.Window
-        public static final Permission SET_WINDOW_ALWAYS_ON_TOP_PERMISSION =
-            newAWTPermission("setWindowAlwaysOnTop");
-
-        // java.awt.Toolkit
-        public static final Permission ALL_AWT_EVENTS_PERMISSION =
-            newAWTPermission("listenToAllAWTEvents");
-
-        // java.awt.SystemTray
-        public static final Permission ACCESS_SYSTEM_TRAY_PERMISSION =
-            newAWTPermission("accessSystemTray");
-    }
-    */
-    // END Android-removed
-
     // java.net.URL
     public static final NetPermission SPECIFY_HANDLER_PERMISSION =
        new NetPermission("specifyStreamHandler");
@@ -176,7 +97,11 @@
     public static final NetPermission GET_RESPONSECACHE_PERMISSION =
        new NetPermission("getResponseCache");
 
-    // java.lang.SecurityManager, sun.applet.AppletPanel, sun.misc.Launcher
+    // java.net.ServerSocket, java.net.Socket
+    public static final NetPermission SET_SOCKETIMPL_PERMISSION =
+        new NetPermission("setSocketImpl");
+
+    // java.lang.SecurityManager, sun.applet.AppletPanel
     public static final RuntimePermission CREATE_CLASSLOADER_PERMISSION =
         new RuntimePermission("createClassLoader");
 
@@ -208,6 +133,10 @@
     public static final RuntimePermission GET_STACK_TRACE_PERMISSION =
        new RuntimePermission("getStackTrace");
 
+    // java.lang.Thread
+    public static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
+        new RuntimePermission("enableContextClassLoaderOverride");
+
     // java.security.AccessControlContext
     public static final SecurityPermission CREATE_ACC_PERMISSION =
        new SecurityPermission("createAccessControlContext");
@@ -223,4 +152,16 @@
     // java.lang.SecurityManager
     public static final SocketPermission LOCAL_LISTEN_PERMISSION =
         new SocketPermission("localhost:0", SOCKET_LISTEN_ACTION);
+
+    public static final String PROVIDER_VER =
+        GetPropertyAction.privilegedGetProperty("java.specification.version");
+
+    // java.lang.reflect.AccessibleObject
+    public static final ReflectPermission ACCESS_PERMISSION =
+        new ReflectPermission("suppressAccessChecks");
+
+    // sun.reflect.ReflectionFactory
+    public static final RuntimePermission REFLECTION_FACTORY_ACCESS_PERMISSION =
+        new RuntimePermission("reflectionFactoryAccess");
+
 }
diff --git a/ojluni/src/main/java/sun/security/x509/AlgorithmId.java b/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
index 71501d9..09a438b 100644
--- a/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
+++ b/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
@@ -56,7 +56,6 @@
  * @author Amit Kapoor
  * @author Hemma Prafullchandra
  */
-@libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
 public class AlgorithmId implements Serializable, DerEncoder {
 
     /** use serialVersionUID from JDK 1.1. for interoperability */
@@ -232,7 +231,6 @@
      *
      * @return name of the algorithm
      */
-    @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE)
     public String getName() {
         String algName = nameTable.get(algid);
         if (algName != null) {
diff --git a/ojluni/src/main/java/sun/security/x509/OCSPNoCheckExtension.java b/ojluni/src/main/java/sun/security/x509/OCSPNoCheckExtension.java
index 35e4cc5..9afa740 100644
--- a/ojluni/src/main/java/sun/security/x509/OCSPNoCheckExtension.java
+++ b/ojluni/src/main/java/sun/security/x509/OCSPNoCheckExtension.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,8 @@
  * lifetime of the responder's certificate. The CA does so by including
  * the extension id-pkix-ocsp-nocheck. This SHOULD be a non-critical
  * extension. The value of the extension should be NULL. CAs issuing
- * such a certificate should realized that a compromise of the
- * responder's key, is as serious as the compromise of a CA key used to
+ * such a certificate should realize that a compromise of the
+ * responder's key is as serious as the compromise of a CA key used to
  * sign CRLs, at least for the validity period of this certificate. CA's
  * may choose to issue this type of certificate with a very short
  * lifetime and renew it frequently.
diff --git a/ojluni/src/main/java/sun/util/locale/BaseLocale.java b/ojluni/src/main/java/sun/util/locale/BaseLocale.java
index e0e9ed0..c037d67 100644
--- a/ojluni/src/main/java/sun/util/locale/BaseLocale.java
+++ b/ojluni/src/main/java/sun/util/locale/BaseLocale.java
@@ -164,6 +164,19 @@
         return h;
     }
 
+    // BEGIN Android-added: Add a static method to clear the stale entries in Zygote
+    /**
+     * This method cleans the stale entries in BaseLocale.CACHE.  This would
+     * be called in Zygote after GC but before fork, and so to avoid the
+     * cleaning of the cache to happen in child processes.
+     *
+     * @hide
+     */
+    public static void cleanCache() {
+        CACHE.cleanStaleEntries();
+    }
+    // END Android-added: Add a static method to clear the stale entries in Zygote
+
     private static final class Key {
         private final SoftReference<String> lang;
         private final SoftReference<String> scrt;
diff --git a/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java b/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
index 81fa86e..cd42ca0 100644
--- a/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
+++ b/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
@@ -331,7 +331,7 @@
                 done.add(key);
             }
         }
-        if (privateuse != null && privateuse.length() > 0) {
+        if (privateuse != null && !privateuse.isEmpty()) {
             // privateuse string contains prefix, e.g. "x-abc-def"
             if (extensions == null) {
                 extensions = new HashMap<>(1);
@@ -406,19 +406,19 @@
         // Validate base locale fields before updating internal state.
         // LocaleExtensions always store validated/canonicalized values,
         // so no checks are necessary.
-        if (language.length() > 0 && !LanguageTag.isLanguage(language)) {
+        if (!language.isEmpty() && !LanguageTag.isLanguage(language)) {
             throw new LocaleSyntaxException("Ill-formed language: " + language);
         }
 
-        if (script.length() > 0 && !LanguageTag.isScript(script)) {
+        if (!script.isEmpty() && !LanguageTag.isScript(script)) {
             throw new LocaleSyntaxException("Ill-formed script: " + script);
         }
 
-        if (region.length() > 0 && !LanguageTag.isRegion(region)) {
+        if (!region.isEmpty() && !LanguageTag.isRegion(region)) {
             throw new LocaleSyntaxException("Ill-formed region: " + region);
         }
 
-        if (variant.length() > 0) {
+        if (!variant.isEmpty()) {
             // BEGIN Android-added: normalize separators to "_"
             variant = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
             // END Android-added: normalize separators to "_"
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java b/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
index eae1480..f859966 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
@@ -88,8 +88,9 @@
         return (oldEntry == null) ? null : oldEntry.get();
     }
 
+    // Android-changed: Make it public / protected to clean stale entries before Zygote forks
     @SuppressWarnings("unchecked")
-    private void cleanStaleEntries() {
+    public void cleanStaleEntries() {
         CacheEntry<K, V> entry;
         while ((entry = (CacheEntry<K, V>)queue.poll()) != null) {
             map.remove(entry.getKey());
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
index ead48fc..264c500 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
@@ -207,7 +207,7 @@
     }
 
     static boolean isEmpty(String str) {
-        return str == null || str.length() == 0;
+        return str == null || str.isEmpty();
     }
 
     static boolean isEmpty(Set<?> set) {
diff --git a/ojluni/src/main/native/Android.bp b/ojluni/src/main/native/Android.bp
index 162a73c..5edf48a 100644
--- a/ojluni/src/main/native/Android.bp
+++ b/ojluni/src/main/native/Android.bp
@@ -85,5 +85,6 @@
         "socket_tagger_util.cpp",
         "OnLoad.cpp",
         "JniConstants.cpp",
+        "jdk_internal_misc_VM.cpp",
     ],
 }
diff --git a/ojluni/src/main/native/JniConstants.cpp b/ojluni/src/main/native/JniConstants.cpp
index 0eb499d..287bc54 100644
--- a/ojluni/src/main/native/JniConstants.cpp
+++ b/ojluni/src/main/native/JniConstants.cpp
@@ -55,10 +55,6 @@
 // initialized. This pattern is only necessary because if a process finishes one
 // runtime and starts another then JNI_OnLoad may not be called.
 void EnsureJniConstantsInitialized(JNIEnv* env) {
-    if (g_constants_valid) {
-        return;
-    }
-
     std::lock_guard guard(g_constants_mutex);
     if (g_constants_valid) {
         return;
diff --git a/ojluni/src/main/native/LinuxWatchService.c b/ojluni/src/main/native/LinuxWatchService.c
index 1f531d0..2e688e7 100644
--- a/ojluni/src/main/native/LinuxWatchService.c
+++ b/ojluni/src/main/native/LinuxWatchService.c
@@ -32,12 +32,10 @@
 #include <dlfcn.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-// Android-changed: Fuchsia: Point to correct location of header. http://b/119426171
+// Android-changed: Point to correct location of header. http://b/119426171
 // #include <sys/poll.h>
-#if defined(__Fuchsia__)
 #include <poll.h>
-#else
-#include <sys/poll.h>
+#if !defined(__Fuchsia__)
 #include <sys/inotify.h>
 #endif
 
diff --git a/ojluni/src/main/native/MappedByteBuffer.c b/ojluni/src/main/native/MappedByteBuffer.c
index 72e840a..1d46218 100644
--- a/ojluni/src/main/native/MappedByteBuffer.c
+++ b/ojluni/src/main/native/MappedByteBuffer.c
@@ -50,9 +50,10 @@
     int i = 0;
     void *a = (void *) jlong_to_ptr(address);
 #ifdef __linux__
-    unsigned char *vec = (unsigned char *)malloc(numPages * sizeof(char));
+    // Android-changed: fix mismatched type in sizeof.
+    unsigned char *vec = (unsigned char *)malloc(numPages * sizeof(*vec));
 #else
-    char *vec = (char *)malloc(numPages * sizeof(char));
+    char *vec = (char *)malloc(numPages * sizeof(*vec));
 #endif
 
     if (vec == NULL) {
diff --git a/ojluni/src/main/native/NativeThread.c b/ojluni/src/main/native/NativeThread.c
index dc21e5d..6093b98 100644
--- a/ojluni/src/main/native/NativeThread.c
+++ b/ojluni/src/main/native/NativeThread.c
@@ -34,7 +34,9 @@
 
 #ifdef __linux__
   #include <pthread.h>
-  #include <sys/signal.h>
+  // Android-changed: Use correct include for signal.h
+  // #include <sys/signal.h>
+  #include <signal.h>
   // Android-changed: Bionic (and AsynchronousCloseMonitor) expects libcore to use
   // __SIGRTMIN + 2, not __SIGRTMAX - 2
   /* Also defined in net/linux_close.c */
diff --git a/ojluni/src/main/native/Net.c b/ojluni/src/main/native/Net.c
index bcf984e..e1da723 100644
--- a/ojluni/src/main/native/Net.c
+++ b/ojluni/src/main/native/Net.c
@@ -23,13 +23,9 @@
  * questions.
  */
 
-// Android-changed: Fuchsia: Point to correct location of header. http://b/119426171
+// Android-changed: Point to correct location of header. http://b/119426171
 // #include <sys/poll.h>
-#if defined(__Fuchsia__)
 #include <poll.h>
-#else
-#include <sys/poll.h>
-#endif
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <string.h>
diff --git a/ojluni/src/main/native/OnLoad.cpp b/ojluni/src/main/native/OnLoad.cpp
index f0b8566..3424402 100644
--- a/ojluni/src/main/native/OnLoad.cpp
+++ b/ojluni/src/main/native/OnLoad.cpp
@@ -61,6 +61,7 @@
 extern "C" void register_java_lang_Runtime(JNIEnv* env);
 extern "C" void register_java_lang_UNIXProcess(JNIEnv* env);
 void register_java_lang_Character(JNIEnv* env);
+void register_jdk_internal_misc_VM(JNIEnv* env);
 
 extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
   jint version = JNI_VERSION_1_6;
@@ -131,6 +132,7 @@
   register_java_lang_Runtime(env);
   register_java_lang_UNIXProcess(env);
   register_java_lang_Character(env);
+  register_jdk_internal_misc_VM(env);
 
   env->PopLocalFrame(/* result */ nullptr);  // Pop the local frame.
   return version;
diff --git a/ojluni/src/main/native/UNIXProcess_md.c b/ojluni/src/main/native/UNIXProcess_md.c
index a3790e8..8fdb6a0 100644
--- a/ojluni/src/main/native/UNIXProcess_md.c
+++ b/ojluni/src/main/native/UNIXProcess_md.c
@@ -58,6 +58,10 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <limits.h>
+// Android-added: Use raw syscalls instead of libc functions in the child.
+#ifdef __linux__
+#include <sys/syscall.h>
+#endif
 
 #ifdef __APPLE__
 #include <crt_externs.h>
@@ -400,16 +404,29 @@
     return err;
 }
 
+// Android-added: in the child process, we want to avoid using the libc
+// close() function because it is sometimes intercepted by other libraries and
+// could cause a deadlock.
+static int closeInChild(int fd)
+{
+#ifdef __linux__
+    return syscall(__NR_close, fd);
+#else
+    return close(fd);
+#endif
+}
+
 static int
 closeSafely(int fd)
 {
     return (fd == -1) ? 0 : restartableClose(fd);
 }
 
+// Android-added: See closeInChild.
 static int
-isAsciiDigit(char c)
+closeSafelyInChild(int fd)
 {
-  return c >= '0' && c <= '9';
+    return (fd == -1) ? 0 : closeInChild(fd);
 }
 
 // Android-changed: Fuchsia: Alias *64 on Fuchsia builds. http://b/119496969
@@ -422,6 +439,56 @@
 #define FD_DIR "/proc/self/fd"
 #endif
 
+// Android-changed: opendir is not async-signal-safe and should not be called
+// after forking. This can cause a deadlock if both of these conditions are met:
+// - The program is running under a binary translation tool such as Valgrind
+//   which emulates the vfork syscall using fork.
+// - The malloc mutex was locked at the time of the fork, which remains
+//   permanently locked in the child process.
+//
+// As a workaround, we access the directory directly with the getdents syscall
+// using a stack-allocated buffer.
+#ifdef __linux__
+static int
+closeDescriptors(void)
+{
+    int dir_fd;
+    char buffer[4096];
+    long available_bytes;
+    int from_fd = FAIL_FILENO + 1;
+
+    // Close one file descriptor to guarantee that we have enough free FDs to
+    // open FD_DIR.
+    closeInChild(from_fd);
+
+    if ((dir_fd = syscall(__NR_openat, AT_FDCWD, FD_DIR, O_CLOEXEC | O_DIRECTORY | O_RDONLY)) == -1)
+        return 0;
+
+    // See closeInChild for why we are using a raw syscall here.
+    while ((available_bytes = syscall(__NR_getdents64, dir_fd, buffer, sizeof(buffer))) > 0) {
+        char *p = buffer;
+        while (available_bytes > 0) {
+            struct dirent64 *dirp = (struct dirent64 *)p;
+            p += dirp->d_reclen;
+            available_bytes -= dirp->d_reclen;
+
+            int fd = atoi(dirp->d_name);
+            if (fd >= from_fd && fd != dir_fd)
+                closeInChild(fd);
+        }
+    }
+
+    closeInChild(dir_fd);
+
+    return 1;
+}
+#else
+static int
+isAsciiDigit(char c)
+{
+  return c >= '0' && c <= '9';
+}
+
 static int
 closeDescriptors(void)
 {
@@ -436,8 +503,8 @@
      * the lowest numbered file descriptor, just like open().  So we
      * close a couple explicitly.  */
 
-    restartableClose(from_fd);          /* for possible use by opendir() */
-    restartableClose(from_fd + 1);      /* another one for good luck */
+    closeInChild(from_fd);          /* for possible use by opendir() */
+    closeInChild(from_fd + 1);      /* another one for good luck */
 
     if ((dp = opendir(FD_DIR)) == NULL)
         return 0;
@@ -449,20 +516,21 @@
         int fd;
         if (isAsciiDigit(dirp->d_name[0]) &&
             (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2)
-            restartableClose(fd);
+            closeInChild(fd);
     }
 
     closedir(dp);
 
     return 1;
 }
+#endif
 
 static int
 moveDescriptor(int fd_from, int fd_to)
 {
     if (fd_from != fd_to) {
         if ((restartableDup2(fd_from, fd_to) == -1) ||
-            (restartableClose(fd_from) == -1))
+            (closeInChild(fd_from) == -1))
             return -1;
     }
     return 0;
@@ -736,10 +804,10 @@
     /* Close the parent sides of the pipes.
        Closing pipe fds here is redundant, since closeDescriptors()
        would do it anyways, but a little paranoia is a good thing. */
-    if ((closeSafely(p->in[1])   == -1) ||
-        (closeSafely(p->out[0])  == -1) ||
-        (closeSafely(p->err[0])  == -1) ||
-        (closeSafely(p->fail[0]) == -1))
+    if ((closeSafelyInChild(p->in[1])   == -1) ||
+        (closeSafelyInChild(p->out[0])  == -1) ||
+        (closeSafelyInChild(p->err[0])  == -1) ||
+        (closeSafelyInChild(p->fail[0]) == -1))
         goto WhyCantJohnnyExec;
 
     /* Give the child sides of the pipes the right fileno's. */
@@ -751,7 +819,7 @@
         goto WhyCantJohnnyExec;
 
     if (p->redirectErrorStream) {
-        if ((closeSafely(p->err[1]) == -1) ||
+        if ((closeSafelyInChild(p->err[1]) == -1) ||
             (restartableDup2(STDOUT_FILENO, STDERR_FILENO) == -1))
             goto WhyCantJohnnyExec;
     } else {
@@ -768,7 +836,7 @@
         int max_fd = (int)sysconf(_SC_OPEN_MAX);
         int fd;
         for (fd = FAIL_FILENO + 1; fd < max_fd; fd++)
-            if (restartableClose(fd) == -1 && errno != EBADF)
+            if (closeInChild(fd) == -1 && errno != EBADF)
                 goto WhyCantJohnnyExec;
     }
 
@@ -796,7 +864,7 @@
         int errnum = errno;
         restartableWrite(FAIL_FILENO, &errnum, sizeof(errnum));
     }
-    restartableClose(FAIL_FILENO);
+    closeInChild(FAIL_FILENO);
     _exit(-1);
     return 0;  /* Suppress warning "no return value from function" */
 }
diff --git a/ojluni/src/main/native/jdk_internal_misc_VM.cpp b/ojluni/src/main/native/jdk_internal_misc_VM.cpp
new file mode 100644
index 0000000..8e41328
--- /dev/null
+++ b/ojluni/src/main/native/jdk_internal_misc_VM.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  The Android Open Source
+ * Project designates this particular file as subject to the "Classpath"
+ * exception as provided by The Android Open Source Project in the LICENSE
+ * file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "jni.h"
+#include "jvm.h"
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/jni_macros.h>
+
+JNIEXPORT jlong JNICALL VM_getNanoTimeAdjustment(jlong offsetInSeconds) {
+    return JVM_GetNanoTimeAdjustment(nullptr, nullptr, offsetInSeconds);
+}
+
+static JNINativeMethod gMethods[] = {
+  CRITICAL_NATIVE_METHOD(VM, getNanoTimeAdjustment, "(J)J"),
+};
+
+void register_jdk_internal_misc_VM(JNIEnv* env) {
+    jniRegisterNativeMethods(env, "jdk/internal/misc/VM", gMethods, NELEM(gMethods));
+}
\ No newline at end of file
diff --git a/ojluni/src/main/native/jvm.h b/ojluni/src/main/native/jvm.h
index fd15abf..5421419 100644
--- a/ojluni/src/main/native/jvm.h
+++ b/ojluni/src/main/native/jvm.h
@@ -105,6 +105,9 @@
 JNIEXPORT jlong JNICALL
 JVM_NanoTime(JNIEnv *env, jclass ignored);
 
+JNIEXPORT jlong JNICALL
+JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs);
+
 JNIEXPORT void JNICALL
 JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
               jobject dst, jint dst_pos, jint length);
diff --git a/ojluni/src/main/native/jvm_md.h b/ojluni/src/main/native/jvm_md.h
index 54743c6..20baad9 100644
--- a/ojluni/src/main/native/jvm_md.h
+++ b/ojluni/src/main/native/jvm_md.h
@@ -65,13 +65,9 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
-// Android-changed: Fuchsia: Point to correct header location. http://b/119426171
+// Android-changed: Point to correct header location. http://b/119426171
 // #include <sys/signal.h>
-#if !defined(__Fuchsia__)
-#include <sys/signal.h>
-#else
 #include <signal.h>
-#endif
 
 /* O Flags */
 
diff --git a/ojluni/src/main/native/linux_close.cpp b/ojluni/src/main/native/linux_close.cpp
index a4d1457..c2d660b 100644
--- a/ojluni/src/main/native/linux_close.cpp
+++ b/ojluni/src/main/native/linux_close.cpp
@@ -35,13 +35,9 @@
 #include <unistd.h>
 #include <errno.h>
 
-// Android-changed: Fuchsia: Fix poll.h include location
+// Android-changed: Fix poll.h include location
 // #include <sys/poll.h>
-#if !defined(__Fuchsia__)
-#include <sys/poll.h>
-#else
 #include <poll.h>
-#endif
 
 #include <AsynchronousCloseMonitor.h>
 
diff --git a/ojluni/src/main/native/net_util_md.c b/ojluni/src/main/native/net_util_md.c
index 3fb3eb6..23c4d24 100644
--- a/ojluni/src/main/native/net_util_md.c
+++ b/ojluni/src/main/native/net_util_md.c
@@ -1097,6 +1097,7 @@
         // Android-changed: This is out-dated RFC 1349 scheme. Modern Linux uses
         // Diffsev/ECN, and this mask is no longer relavant.
         // *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
+        (void) iptos;
     }
 
     /*
diff --git a/ojluni/src/main/native/net_util_md.h b/ojluni/src/main/native/net_util_md.h
index 0bef5b9..67a6c97 100644
--- a/ojluni/src/main/native/net_util_md.h
+++ b/ojluni/src/main/native/net_util_md.h
@@ -33,14 +33,10 @@
 #include <unistd.h>
 
 #ifndef USE_SELECT
-// Android-changed: Fuchsia: Point to correct location of header. http://b/119426171
+// Android-changed: Point to correct location of header. http://b/119426171
 // #include <sys/poll.h>
-#if !defined(__Fuchsia__)
-#include <sys/poll.h>
-#else
 #include <poll.h>
 #endif
-#endif
 
 // Android-changed: Fuchsia: Use the non-JVM NET_* on Fuchsia also.
 // #if defined(__linux__) || defined(MACOSX)
diff --git a/ojluni/src/main/native/zip_util.c b/ojluni/src/main/native/zip_util.c
index aa9c5ce..01dcce7 100644
--- a/ojluni/src/main/native/zip_util.c
+++ b/ojluni/src/main/native/zip_util.c
@@ -775,6 +775,8 @@
     jzfile *zip = NULL;
 
     /* Clear zip error message */
+    // BEGIN Android-changed: Don't crash crash if `pmsg` is NULL and getting from the cache fails.
+    /*
     if (pmsg != 0) {
         *pmsg = NULL;
     }
@@ -785,6 +787,26 @@
         ZFILE zfd = ZFILE_Open(name, mode);
         zip = ZIP_Put_In_Cache(name, zfd, pmsg, lastModified);
     }
+    */
+    /*
+     * We want to know if ZIP_Get_From_Cache fails, which isn't possible to
+     * distinguish without passing a non-null message value. Hence, if the user
+     * didn't supply a `pmsg`, we make and manage our own.
+     */
+    char *localPmsg = NULL;
+    zip = ZIP_Get_From_Cache(name, &localPmsg, lastModified);
+
+    if (zip == NULL && localPmsg == NULL) {
+        ZFILE zfd = ZFILE_Open(name, mode);
+        zip = ZIP_Put_In_Cache(name, zfd, &localPmsg, lastModified);
+    }
+
+    if (pmsg == NULL) {
+      free(localPmsg);
+    } else {
+      *pmsg = localPmsg;
+    }
+    // END Android-changed: Don't crash crash if `pmsg` is NULL and getting from the cache fails.
     return zip;
 }
 
diff --git a/ojluni/src/main/resources/hijrah-config-umalqura.properties b/ojluni/src/main/resources/java/time/chrono/hijrah-config-islamic-umalqura.properties
similarity index 100%
rename from ojluni/src/main/resources/hijrah-config-umalqura.properties
rename to ojluni/src/main/resources/java/time/chrono/hijrah-config-islamic-umalqura.properties
diff --git a/ojluni/src/test/java/io/ByteArrayInputStream/ReadAllReadNTransferTo.java b/ojluni/src/test/java/io/ByteArrayInputStream/ReadAllReadNTransferTo.java
new file mode 100644
index 0000000..c3e6e6c
--- /dev/null
+++ b/ojluni/src/test/java/io/ByteArrayInputStream/ReadAllReadNTransferTo.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.ByteArrayInputStream;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+/* @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main ReadAllReadNTransferTo
+ * @bug 8180451
+ * @summary Verify ByteArrayInputStream readAllBytes, readNBytes, and transferTo
+ * @key randomness
+ */
+public class ReadAllReadNTransferTo {
+    private static final int SIZE = 0x4d4d;
+
+    private static Random random = new Random();
+
+    @Test
+    public void testRead() throws IOException {
+        byte[] buf = new byte[SIZE];
+        random.nextBytes(buf);
+        int position = random.nextInt(SIZE/2);
+        int size = random.nextInt(SIZE - position);
+
+        ByteArrayInputStream bais =
+                new ByteArrayInputStream(buf, position, size);
+        int off = size < 2 ? 0 : random.nextInt(size / 2);
+        int len = size - off < 1 ? 0 : random.nextInt(size - off);
+
+        byte[] bN = new byte[off + len];
+        if (bais.readNBytes(bN, off, len) != len) {
+            throw new RuntimeException("readNBytes return value");
+        }
+
+        if (!Arrays.equals(Arrays.copyOfRange(bN, off, off+len),
+                Arrays.copyOfRange(buf, position, position+len))) {
+            throw new RuntimeException("readNBytes content");
+        }
+
+        byte[] bAll = bais.readAllBytes();
+        Objects.requireNonNull(bAll, "readAllBytes return value");
+        if (bAll.length != size - len) {
+            throw new RuntimeException("readAllBytes return value length");
+        }
+        if (!Arrays.equals(bAll,
+               Arrays.copyOfRange( buf, position + len, position + len + bAll.length))) {
+            throw new RuntimeException("readAllBytes content");
+        }
+
+        // XXX transferTo()
+        bais = new ByteArrayInputStream(buf);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(buf.length);
+        if (bais.transferTo(baos) != buf.length) {
+            throw new RuntimeException("transferTo return value length");
+        }
+        if (!Arrays.equals(buf, baos.toByteArray())) {
+            throw new RuntimeException("transferTo content");
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/ByteArrayOutputStream/EncodingTest.java b/ojluni/src/test/java/io/ByteArrayOutputStream/EncodingTest.java
new file mode 100644
index 0000000..34a6b73
--- /dev/null
+++ b/ojluni/src/test/java/io/ByteArrayOutputStream/EncodingTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.ByteArrayOutputStream;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183743
+ * @summary Test to verify the new overload method with Charset functions the same
+ * as the existing method that takes a charset name.
+ * @run testng EncodingTest
+ */
+public class EncodingTest {
+    /*
+     * DataProvider for the toString method test. Provides the following fields:
+     * byte array, charset name string, charset object
+     */
+    @DataProvider(name = "parameters")
+    public Object[][] getParameters() throws IOException {
+        byte[] data = getData();
+        return new Object[][]{
+                {data, StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8},
+                {data, StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1},
+        };
+    }
+
+    /**
+     * Verifies that the new overload method that takes a Charset is equivalent to
+     * the existing one that takes a charset name.
+     * @param data a byte array
+     * @param csn the charset name
+     * @param charset the charset
+     * @throws Exception if the test fails
+     */
+    @Test(dataProvider = "parameters")
+    public void test(byte[] data, String csn, Charset charset) throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        baos.write(data);
+        String str1 = baos.toString(csn);
+        String str2 = baos.toString(charset);
+        Assert.assertEquals(str1, str2);
+    }
+
+    /*
+     * Returns an array containing a character that's invalid for UTF-8
+     * but valid for ISO-8859-1
+     */
+    byte[] getData() throws IOException {
+        String str1 = "A string that contains ";
+        String str2 = " , an invalid character for UTF-8.";
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        baos.write(str1.getBytes());
+        baos.write(0xFA);
+        baos.write(str2.getBytes());
+        return baos.toByteArray();
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/ByteArrayOutputStream/ToString.java b/ojluni/src/test/java/io/ByteArrayOutputStream/ToString.java
new file mode 100644
index 0000000..cbd8781
--- /dev/null
+++ b/ojluni/src/test/java/io/ByteArrayOutputStream/ToString.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 1226190
+   @summary Heartbeat test of ByteArrayOutputStream's toString methods
+ */
+package test.java.io.ByteArrayOutputStream;
+
+import java.io.*;
+
+import org.testng.annotations.Test;
+
+public class ToString {
+
+    @Test
+    public void testToString() throws IOException {
+        String test = "This is a test.";
+        ByteArrayOutputStream b = new ByteArrayOutputStream();
+        PrintStream p = new PrintStream(b);
+        p.print(test);
+        p.close();
+
+        if (! b.toString().equals(test))
+            throw new RuntimeException("Default encoding failed");
+        if (! b.toString("UTF8").equals(test))
+            throw new RuntimeException("UTF8 encoding failed");
+        if (! b.toString(0).equals(test))
+            throw new RuntimeException("Hibyte0 encoding failed");
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/ByteArrayOutputStream/Write.java b/ojluni/src/test/java/io/ByteArrayOutputStream/Write.java
new file mode 100644
index 0000000..2424263
--- /dev/null
+++ b/ojluni/src/test/java/io/ByteArrayOutputStream/Write.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4017158 8180410
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run testng Write
+ * @summary Check for correct implementation of ByteArrayInputStream.write
+ * @key randomness
+ */
+package test.java.io.ByteArrayOutputStream;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.Random;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class Write {
+
+    private static void doBoundsTest(byte[] b, int off, int len,
+            ByteArrayOutputStream baos)
+            throws Exception {
+        if (b != null) {
+            System.out.println("ByteArrayOutStream.write: b.length = " +
+                    b.length + " off = " + off + " len = " + len);
+        } else{
+            System.out.println("ByteArrayOutStream.write: b is null off = " +
+                    off + " len = " + len);
+        }
+
+        try {
+            baos.write(b, off, len);
+        } catch (IndexOutOfBoundsException e) {
+            System.out.println("IndexOutOfBoundsException is thrown: OKAY");
+        } catch (NullPointerException e) {
+            System.out.println("NullPointerException is thrown: OKAY");
+        } catch (Throwable e){
+            throw new RuntimeException("Unexpected Exception is thrown", e);
+        }
+
+        if (b != null) {
+            System.out.println("ByteArrayOutStream.writeBytes: b.length = " +
+                    b.length);
+        } else{
+            System.out.println("ByteArrayOutStream.writeBytes: b is null");
+        }
+
+        try {
+            baos.writeBytes(b);
+        } catch (NullPointerException e) {
+            System.out.println("NullPointerException is thrown: OKAY");
+        } catch (Throwable e){
+            throw new RuntimeException("Unexpected Exception is thrown", e);
+        }
+    }
+
+    @Test
+    public void boundsTest() throws Exception {
+        byte array1[] = {1 , 2 , 3 , 4 , 5};     // Simple array
+
+        //Create new ByteArrayOutputStream object
+        ByteArrayOutputStream y1 = new ByteArrayOutputStream(5);
+
+        doBoundsTest(array1, 0, Integer.MAX_VALUE , y1);
+        doBoundsTest(array1, 0, array1.length+100, y1);
+        doBoundsTest(array1, -1, 2, y1);
+        doBoundsTest(array1, 0, -1, y1);
+        doBoundsTest(null, 0, 2, y1);
+    }
+
+    @Test
+    public void writeTest() throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Random rnd = new Random();
+        final int size = 17 + rnd.nextInt(128);
+
+        byte[] b = new byte[size];
+        rnd.nextBytes(b);
+
+        int off1 = rnd.nextInt(size / 4) + 1;
+        int len1 = Math.min(rnd.nextInt(size / 4) + 1, size - off1);
+        int off2 = rnd.nextInt(size / 2) + 1;
+        int len2 = Math.min(rnd.nextInt(size / 2) + 1, size - off2);
+
+        System.out.format("size: %d, off1: %d, len1: %d, off2: %d, len2: %d%n",
+                size, off1, len1, off2, len2);
+
+        baos.write(b, off1, len1);
+        byte[] b1 = baos.toByteArray();
+        assertEquals(b1.length, len1, "Array length test 1 failed.");
+        assertEquals(b1, Arrays.copyOfRange(b, off1, off1 + len1),
+                "Array equality test 1 failed.");
+
+        baos.write(b, off2, len2);
+        byte[] b2 = baos.toByteArray();
+        assertEquals(b2.length, len1 + len2, "Array length test 2 failed.");
+        assertEquals(Arrays.copyOfRange(b2, 0, len1),
+                Arrays.copyOfRange(b, off1, off1 + len1),
+                "Array equality test 2A failed.");
+        assertEquals(Arrays.copyOfRange(b2, len1, len1 + len2),
+                Arrays.copyOfRange(b, off2, off2 + len2),
+                "Array equality test 2B failed.");
+
+        baos.writeBytes(b);
+        byte[] b3 = baos.toByteArray();
+        int len3 = len1 + len2 + b.length;
+        if (b3.length != len1 + len2 + b.length) {
+            throw new RuntimeException("Array length test 3 failed.");
+        }
+        assertEquals(b3.length, len3, "Array length test 3 failed.");
+        assertEquals(Arrays.copyOfRange(b3, 0, len1),
+                Arrays.copyOfRange(b, off1, off1 + len1),
+                "Array equality test 3A failed.");
+        assertEquals(Arrays.copyOfRange(b3, len1, len1 + len2),
+                Arrays.copyOfRange(b, off2, off2 + len2),
+                "Array equality test 3B failed.");
+        assertEquals(Arrays.copyOfRange(b3, len1 + len2, len3), b,
+                "Array equality test 3C failed.");
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/FileReader/ConstructorTest.java b/ojluni/src/test/java/io/FileReader/ConstructorTest.java
new file mode 100644
index 0000000..30b5504
--- /dev/null
+++ b/ojluni/src/test/java/io/FileReader/ConstructorTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.FileReader;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183554
+ * @summary Test to verify the new Constructors that take a Charset.
+ * @run testng ConstructorTest
+ */
+public class ConstructorTest {
+    static String USER_DIR = System.getProperty("user.dir", ".");
+
+    public static enum ConstructorType {
+        STRING,
+        FILE
+    }
+
+    static final String TEST_STRING = "abc \u0100 \u0101 \u0555 \u07FD \u07FF";
+    static final int BUFFER_SIZE = 8192;
+
+    @DataProvider(name = "parameters")
+    public Object[][] getParameters() throws IOException {
+        File file1 = new File(USER_DIR, "FileReaderTest1.txt");
+        File file2 = new File(USER_DIR, "FileReaderTest2.txt");
+
+        return new Object[][]{
+                {ConstructorType.STRING, file1, file2, StandardCharsets.UTF_8},
+                {ConstructorType.FILE, file1, file2, StandardCharsets.UTF_8},
+                {ConstructorType.STRING, file1, file2, StandardCharsets.ISO_8859_1},
+                {ConstructorType.FILE, file1, file2, StandardCharsets.ISO_8859_1},
+        };
+    }
+
+    /**
+     * Verifies that the new constructors that take a Charset function the same
+     * as an InputStreamReader on a FileInputStream as was recommended before
+     * this change.
+     *
+     * @param type the type of the constructor
+     * @param file1 file1 to be read with a FileReader
+     * @param file2 file2 to be read with an InputStreamReader
+     * @param charset the charset
+     * @throws IOException
+     */
+    @Test(dataProvider = "parameters")
+    void test(ConstructorType type, File file1, File file2, Charset charset)
+            throws Exception {
+        prepareFile(file1, TEST_STRING, charset);
+        prepareFile(file2, TEST_STRING, charset);
+
+        try (FileReader fr = getFileReader(type, file1, charset);
+             FileInputStream is = new FileInputStream(file2);
+             InputStreamReader isr = new InputStreamReader(is, charset);) {
+            String result1 = readAll(fr, BUFFER_SIZE);
+            String result2 = readAll(isr, BUFFER_SIZE);
+            Assert.assertEquals(result1, result2);
+        }
+    }
+
+    public String readAll(Reader reader, int bufferSize) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        char[] buf = new char[bufferSize];
+        int numRead;
+        while ((numRead = reader.read(buf)) != -1) {
+            if (numRead == buf.length) {
+                sb.append(buf);
+            } else {
+                sb.append(String.valueOf(buf, 0, numRead));
+            }
+        }
+        return sb.toString();
+    }
+
+    /*
+     * Creates a FileReader over the given input file.
+     */
+    FileReader getFileReader(ConstructorType type, File file, Charset charset)
+            throws IOException {
+        switch (type) {
+            case STRING:
+                return new FileReader(file.getPath(), charset);
+            case FILE:
+                return new FileReader(file, charset);
+        }
+
+        return null;
+    }
+
+    void prepareFile(File file, String content, Charset charset) throws IOException {
+        try (FileWriter writer = new FileWriter(file, charset);) {
+            writer.write(content);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/FileWriter/ConstructorTest.java b/ojluni/src/test/java/io/FileWriter/ConstructorTest.java
new file mode 100644
index 0000000..c95ba89
--- /dev/null
+++ b/ojluni/src/test/java/io/FileWriter/ConstructorTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.FileWriter;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183554
+ * @summary Test to verify the new Constructors that take a Charset.
+ * @run testng ConstructorTest
+ */
+public class ConstructorTest {
+
+    public static enum ConstructorType {
+        STRING,
+        FILE,
+        STRING_APPEND,
+        FILE_APPEND
+    }
+
+    static final String TEST_STRING = "abc \u0100 \u0101 \u0555 \u07FD \u07FF";
+    static final int BUFFER_SIZE = 8192;
+
+    @DataProvider(name = "parameters")
+    public Object[][] getParameters() throws IOException {
+        File file1 = File.createTempFile("FileWriterTest1", "txt");
+        File file2 = File.createTempFile("FileWriterTest2", "txt");
+
+        return new Object[][]{
+                {ConstructorType.STRING, file1, file2, StandardCharsets.UTF_8},
+                {ConstructorType.FILE, file1, file2, StandardCharsets.UTF_8},
+                {ConstructorType.STRING_APPEND, file1, file2, StandardCharsets.UTF_8},
+                {ConstructorType.FILE_APPEND, file1, file2, StandardCharsets.UTF_8},
+                {ConstructorType.STRING, file1, file2, StandardCharsets.ISO_8859_1},
+                {ConstructorType.FILE, file1, file2, StandardCharsets.ISO_8859_1},
+                {ConstructorType.STRING_APPEND, file1, file2, StandardCharsets.ISO_8859_1},
+                {ConstructorType.FILE_APPEND, file1, file2, StandardCharsets.ISO_8859_1},
+        };
+    }
+
+    /**
+     * Verifies that the new constructors that take a Charset function the same
+     * as an OutputStreamWriter on a FileOutputStream as was recommended before
+     * this change.
+     *
+     * @param type the type of the constructor
+     * @param file1 file1 to be written with a FileWriter
+     * @param file2 file2 to be written  with an OutputStreamWriter
+     * @param charset the charset
+     * @throws IOException
+     */
+    @Test(dataProvider = "parameters")
+    void test(ConstructorType type, File file1, File file2, Charset charset)
+            throws Exception {
+        writeWithFileWriter(type, file1, TEST_STRING, charset);
+        writeWithOutputStreamWriter(type, file2, TEST_STRING, charset);
+
+        try (
+                FileReader r1 = getFileReader(type, file1, charset);
+                FileReader r2 = getFileReader(type, file2, charset);
+        ) {
+            String result1 = readAll(r1, BUFFER_SIZE);
+            String result2 = readAll(r2, BUFFER_SIZE);
+            Assert.assertEquals(result1, result2);
+        }
+    }
+
+    public String readAll(Reader reader, int bufferSize) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        char[] buf = new char[bufferSize];
+        int numRead;
+        while ((numRead = reader.read(buf)) != -1) {
+            if (numRead == buf.length) {
+                sb.append(buf);
+            } else {
+                sb.append(String.valueOf(buf, 0, numRead));
+            }
+        }
+        return sb.toString();
+    }
+
+    /*
+     * Creates a FileReader over the given input file.
+     */
+    FileReader getFileReader(ConstructorType type, File file, Charset charset)
+            throws IOException {
+        switch (type) {
+            case STRING:
+            case STRING_APPEND:
+                return new FileReader(file.getPath(), charset);
+            case FILE:
+            case FILE_APPEND:
+                return new FileReader(file, charset);
+        }
+
+        return null;
+    }
+
+    /*
+     * Creates a FileWriter using the constructor as specified.
+     */
+    FileWriter getFileWriter(ConstructorType type, File file, Charset charset)
+            throws IOException {
+        switch (type) {
+            case STRING:
+                return new FileWriter(file.getPath(), charset);
+            case FILE:
+                return new FileWriter(file, charset);
+            case STRING_APPEND:
+                return new FileWriter(file.getPath(), charset, true);
+            case FILE_APPEND:
+                return new FileWriter(file, charset, true);
+        }
+
+        return null;
+    }
+
+    void writeWithFileWriter(ConstructorType type, File file, String content, Charset charset)
+            throws IOException {
+        if (type == ConstructorType.STRING_APPEND || type == ConstructorType.FILE_APPEND) {
+            try (FileWriter writer = getFileWriter(ConstructorType.FILE, file, charset);) {
+                writer.write(content);
+            }
+        }
+        try (FileWriter writer = getFileWriter(type, file, charset);) {
+            writer.write(content);
+        }
+    }
+
+    void writeWithOutputStreamWriter(ConstructorType type, File file, String content, Charset charset)
+            throws IOException {
+        try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), charset)) {
+            writer.write(content);
+            if (type == ConstructorType.STRING_APPEND || type == ConstructorType.FILE_APPEND) {
+                writer.write(content);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/InputStream/NullInputStream.java b/ojluni/src/test/java/io/InputStream/NullInputStream.java
new file mode 100644
index 0000000..ad281b7
--- /dev/null
+++ b/ojluni/src/test/java/io/InputStream/NullInputStream.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.InputStream;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import org.testng.annotations.AfterGroups;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 4358774 8139206
+ * @run testng NullInputStream
+ * @summary Check for expected behavior of InputStream.nullInputStream().
+ */
+public class NullInputStream {
+    private static InputStream openStream;
+    private static InputStream closedStream;
+
+    @BeforeGroups(groups="open")
+    public static void openStream() {
+        openStream = InputStream.nullInputStream();
+    }
+
+    @BeforeGroups(groups="closed")
+    public static void openAndCloseStream() {
+        closedStream = InputStream.nullInputStream();
+        try {
+            closedStream.close();
+        } catch (IOException e) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @AfterGroups(groups="open")
+    public static void closeStream() {
+        try {
+            openStream.close();
+        } catch (IOException e) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testOpen() {
+        assertNotNull(openStream, "InputStream.nullInputStream() returned null");
+    }
+
+    @Test(groups = "open")
+    public static void testAvailable() {
+        try {
+            assertEquals(0, openStream.available(), "available() != 0");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testRead() {
+        try {
+            assertEquals(-1, openStream.read(), "read() != -1");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testReadBII() {
+        try {
+            assertEquals(-1, openStream.read(new byte[1], 0, 1),
+                    "read(byte[],int,int) != -1");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testReadAllBytes() {
+        try {
+            assertEquals(0, openStream.readAllBytes().length,
+                    "readAllBytes().length != 0");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testReadNBytes() {
+        try {
+            assertEquals(0, openStream.readNBytes(new byte[1], 0, 1),
+                    "readNBytes(byte[],int,int) != 0");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testReadNBytesWithLength() {
+        try {
+            assertEquals(0, openStream.readNBytes(-1).length,
+                    "readNBytes(-1) != 0");
+            fail("Expected IllegalArgumentException not thrown");
+        } catch (IllegalArgumentException iae) {
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+        try {
+            assertEquals(0, openStream.readNBytes(0).length,
+                    "readNBytes(0, false) != 0");
+            assertEquals(0, openStream.readNBytes(1).length,
+                    "readNBytes(1, false) != 0");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testSkip() {
+        try {
+            assertEquals(0, openStream.skip(1), "skip() != 0");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "open")
+    public static void testTransferTo() {
+        try {
+            assertEquals(0, openStream.transferTo(new ByteArrayOutputStream(7)),
+                    "transferTo() != 0");
+        } catch (IOException ioe) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testAvailableClosed() {
+        try {
+            closedStream.available();
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testReadClosed() {
+        try {
+            closedStream.read();
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testReadBIIClosed() {
+        try {
+            closedStream.read(new byte[1], 0, 1);
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testReadAllBytesClosed() {
+        try {
+            closedStream.readAllBytes();
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testReadNBytesClosed() {
+        try {
+            closedStream.readNBytes(new byte[1], 0, 1);
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testReadNBytesWithLengthClosed() {
+        try {
+            closedStream.readNBytes(1);
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testSkipClosed() {
+        try {
+            closedStream.skip(1);
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups = "closed")
+    public static void testTransferToClosed() {
+        try {
+            closedStream.transferTo(new ByteArrayOutputStream(7));
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/InputStream/ReadAllBytes.java b/ojluni/src/test/java/io/InputStream/ReadAllBytes.java
new file mode 100644
index 0000000..2851a1f
--- /dev/null
+++ b/ojluni/src/test/java/io/InputStream/ReadAllBytes.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.InputStream;
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Random;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8080835 8193832
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main ReadAllBytes
+ * @summary Basic test for InputStream.readAllBytes
+ * @key randomness
+ */
+
+public class ReadAllBytes {
+
+    private static Random generator = new Random();
+
+    @Test
+    public void testReadAllBytes() throws IOException {
+        test(new byte[]{});
+        test(new byte[]{1, 2, 3});
+        test(createRandomBytes(1024));
+        for (int shift : new int[] {13, 14, 15, 17}) {
+            for (int offset : new int[] {-1, 0, 1}) {
+                test(createRandomBytes((1 << shift) + offset));
+            }
+        }
+    }
+
+    static void test(byte[] expectedBytes) throws IOException {
+        int expectedLength = expectedBytes.length;
+        WrapperInputStream in = new WrapperInputStream(new ByteArrayInputStream(expectedBytes));
+        byte[] readBytes = in.readAllBytes();
+
+        int x;
+        byte[] tmp = new byte[10];
+        check((x = in.read()) == -1,
+                "Expected end of stream from read(), got " + x);
+        check((x = in.read(tmp)) == -1,
+                "Expected end of stream from read(byte[]), got " + x);
+        check((x = in.read(tmp, 0, tmp.length)) == -1,
+                "Expected end of stream from read(byte[], int, int), got " + x);
+        check(in.readAllBytes().length == 0,
+                "Expected readAllBytes to return empty byte array");
+        check(expectedLength == readBytes.length,
+                "Expected length " + expectedLength + ", got " + readBytes.length);
+        check(Arrays.equals(expectedBytes, readBytes),
+                "Expected[" + expectedBytes + "], got:[" + readBytes + "]");
+        check(!in.isClosed(), "Stream unexpectedly closed");
+    }
+
+    static byte[] createRandomBytes(int size) {
+        byte[] bytes = new byte[size];
+        generator.nextBytes(bytes);
+        return bytes;
+    }
+
+    static void check(boolean cond, Object ... failedArgs) {
+        if (cond)
+            return;
+        StringBuilder sb = new StringBuilder();
+        for (Object o : failedArgs)
+            sb.append(o);
+        throw new RuntimeException(sb.toString());
+    }
+
+    static class WrapperInputStream extends FilterInputStream {
+        private boolean closed;
+        WrapperInputStream(InputStream in) { super(in); }
+        @Override public void close() throws IOException { closed = true; in.close(); }
+        boolean isClosed() { return closed; }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/InputStream/ReadNBytes.java b/ojluni/src/test/java/io/InputStream/ReadNBytes.java
new file mode 100644
index 0000000..68644ba
--- /dev/null
+++ b/ojluni/src/test/java/io/InputStream/ReadNBytes.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.InputStream;
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Random;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8080835 8139206
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main ReadNBytes
+ * @summary Basic test for InputStream.readNBytes
+ * @key randomness
+ */
+
+public class ReadNBytes {
+
+    private static Random generator = new Random();
+
+    @Test
+    public void testReadNBytes() throws IOException {
+        test(new byte[]{1, 2, 3});
+        test(createRandomBytes(1024));
+        for (int shift : new int[] {13, 15, 17}) {
+            for (int offset : new int[] {-1, 0, 1}) {
+                test(createRandomBytes((1 << shift) + offset));
+            }
+        }
+
+        test(-1);
+        test(0);
+        for (int shift : new int[] {13, 15, 17}) {
+            for (int offset : new int[] {-1, 0, 1}) {
+                test((1 << shift) + offset);
+            }
+        }
+    }
+
+    static void test(byte[] inputBytes) throws IOException {
+        int length = inputBytes.length;
+        WrapperInputStream in = new WrapperInputStream(new ByteArrayInputStream(inputBytes));
+        byte[] readBytes = new byte[(length / 2) + 1];
+        int nread = in.readNBytes(readBytes, 0, readBytes.length);
+
+        int x;
+        byte[] tmp;
+        check(nread == readBytes.length,
+                "Expected number of bytes read: " + readBytes.length + ", got: " + nread);
+        check(Arrays.equals((tmp = Arrays.copyOf(inputBytes, nread)), readBytes),
+                "Expected[" + tmp + "], got:[" + readBytes + "]");
+        check(!in.isClosed(), "Stream unexpectedly closed");
+
+        // Read again
+        nread = in.readNBytes(readBytes, 0, readBytes.length);
+
+        check(nread == length - readBytes.length,
+                "Expected number of bytes read: " + (length - readBytes.length) + ", got: " + nread);
+        check(Arrays.equals((tmp = Arrays.copyOfRange(inputBytes, readBytes.length, length)),
+                Arrays.copyOf(readBytes, nread)),
+                "Expected[" + tmp + "], got:[" + readBytes + "]");
+        // Expect end of stream
+        check((x = in.read()) == -1,
+                "Expected end of stream from read(), got " + x);
+        check((x = in.read(tmp)) == -1,
+                "Expected end of stream from read(byte[]), got " + x);
+        check((x = in.read(tmp, 0, tmp.length)) == -1,
+                "Expected end of stream from read(byte[], int, int), got " + x);
+        check((x = in.readNBytes(tmp, 0, tmp.length)) == 0,
+                "Expected end of stream, 0, from readNBytes(byte[], int, int), got " + x);
+        check(!in.isClosed(), "Stream unexpectedly closed");
+    }
+
+    static void test(int max) throws IOException {
+        byte[] inputBytes = max <= 0 ? new byte[0] : createRandomBytes(max);
+        WrapperInputStream in =
+                new WrapperInputStream(new ByteArrayInputStream(inputBytes));
+
+        if (max < 0) {
+            try {
+                in.readNBytes(max);
+                check(false, "Expected IllegalArgumentException not thrown");
+            } catch (IllegalArgumentException iae) {
+                return;
+            }
+        } else if (max == 0) {
+            int x;
+            check((x = in.readNBytes(max).length) == 0,
+                    "Expected zero bytes, got " + x);
+            return;
+        }
+
+        int off = Math.toIntExact(in.skip(generator.nextInt(max/2)));
+        int len = generator.nextInt(max - 1 - off);
+        byte[] readBytes = in.readNBytes(len);
+        check(readBytes.length == len,
+                "Expected " + len + " bytes, got " + readBytes.length);
+        check(Arrays.equals(Arrays.copyOfRange(inputBytes, off, off + len), readBytes),
+                "Expected[" + Arrays.copyOfRange(inputBytes, off, off + len) +
+                        "], got:[" + readBytes + "]");
+
+        int remaining = max - (off + len);
+        readBytes = in.readNBytes(remaining);
+        check(readBytes.length == remaining,
+                "Expected " + remaining + "bytes, got " + readBytes.length);
+        check(Arrays.equals(Arrays.copyOfRange(inputBytes, off + len, max),
+                readBytes),
+                "Expected[" + Arrays.copyOfRange(inputBytes, off + len, max) +
+                        "], got:[" + readBytes + "]");
+
+        check(!in.isClosed(), "Stream unexpectedly closed");
+    }
+
+    static byte[] createRandomBytes(int size) {
+        byte[] bytes = new byte[size];
+        generator.nextBytes(bytes);
+        return bytes;
+    }
+
+    static void check(boolean cond, Object ... failedArgs) {
+        if (cond)
+            return;
+        StringBuilder sb = new StringBuilder();
+        for (Object o : failedArgs)
+            sb.append(o);
+        throw new RuntimeException(sb.toString());
+    }
+
+
+    static class WrapperInputStream extends FilterInputStream {
+        private boolean closed;
+        WrapperInputStream(InputStream in) { super(in); }
+        @Override public void close() throws IOException { closed = true; in.close(); }
+        boolean isClosed() { return closed; }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/InputStream/Skip.java b/ojluni/src/test/java/io/InputStream/Skip.java
new file mode 100644
index 0000000..47814d1
--- /dev/null
+++ b/ojluni/src/test/java/io/InputStream/Skip.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.InputStream;
+
+import org.testng.annotations.Test;
+
+/* @test
+   @bug 4016710
+   @summary check for correct implementation of InputStream.skip
+   */
+
+import java.io.*;
+
+
+public class Skip {
+
+    private static void dotest(InputStream in , int curpos ,
+            long total , long toskip , long expected)
+            throws Exception
+    {
+
+        try {
+
+            System.err.println("\n\nCurrently at pos = " + curpos +
+                    "\nTotal bytes in the Stream = " + total +
+                    "\nNumber of bytes to skip = " + toskip +
+                    "\nNumber of bytes that should be skipped = " +
+                    expected);
+
+            long skipped = in.skip(toskip);
+
+            System.err.println("actual number skipped: "+ skipped);
+
+            if ((skipped < 0) || (skipped > expected)) {
+                throw new RuntimeException("Unexpected number of bytes skipped");
+            }
+
+        } catch (IOException e) {
+            System.err.println("IOException is thrown - possible result");
+        } catch (Throwable e) {
+            throw new RuntimeException("Unexpected "+e+" is thrown!");
+        }
+
+    }
+
+    @Test
+    public void testSkip() throws Exception {
+
+        MyInputStream in = new MyInputStream(11);
+
+        /* test for negative skip */
+        dotest(in,  0, 11, -23,  0);
+
+        /* check for skip beyond EOF starting from before EOF */
+        dotest(in,  0, 11,  20, 11);
+
+        /* check for skip after EOF */
+        dotest(in, -1, 11,  20,  0);
+
+        in = new MyInputStream(9000);
+        /* check for skip equal to the read chunk size in InputStream.java */
+        dotest(in,  0, 9000, 2048, 2048);
+
+        /* check for skip greater than the read chunk size in InputStream.java */
+        dotest(in, 2048, 9000, 5000, 5000);
+
+        /* check for skip beyond EOF starting from before EOF */
+        dotest(in, 7048, 9000, 5000, 1952);
+
+        in = new MyInputStream(5000);
+
+        /* check for multiple chunk reads */
+        dotest(in, 0, 5000, 6000, 5000);
+
+        /*
+         * check for skip larger than Integer.MAX_VALUE
+         * (Takes about 2 hrs on a sparc ultra-1)
+         * long total = (long)Integer.MAX_VALUE + (long)10;
+         * long toskip = total - (long)6;
+         * in = new MyInputStream(total);
+         * dotest(in, 0, total, toskip, toskip);
+         */
+
+    }
+
+}
+
+class MyInputStream extends InputStream {
+
+    private int readctr = 0;
+    private long endoffile;
+
+    public MyInputStream(long endoffile) {
+        this.endoffile = endoffile;
+    }
+
+    public int read() {
+
+        if (readctr == endoffile) {
+            return -1;
+        }
+        else {
+            readctr++;
+            return 0;
+        }
+    }
+
+    public int available() { return 0; }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/InputStream/TransferTo.java b/ojluni/src/test/java/io/InputStream/TransferTo.java
new file mode 100644
index 0000000..b35bc1b
--- /dev/null
+++ b/ojluni/src/test/java/io/InputStream/TransferTo.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.InputStream;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Random;
+import org.testng.annotations.Test;
+
+import static java.lang.String.format;
+
+/*
+ * @test
+ * @bug 8066867
+ * @summary tests whether java.io.InputStream.transferTo conforms to its
+ *          contract defined in the javadoc
+ * @key randomness
+ */
+public class TransferTo {
+
+    @Test
+    public void ifOutIsNullThenNpeIsThrown() throws IOException {
+        try (InputStream in = input()) {
+            assertThrowsNPE(() -> in.transferTo(null), "out");
+        }
+
+        try (InputStream in = input((byte) 1)) {
+            assertThrowsNPE(() -> in.transferTo(null), "out");
+        }
+
+        try (InputStream in = input((byte) 1, (byte) 2)) {
+            assertThrowsNPE(() -> in.transferTo(null), "out");
+        }
+
+        InputStream in = null;
+        try {
+            InputStream fin = in = new ThrowingInputStream();
+            // null check should precede everything else:
+            // InputStream shouldn't be touched if OutputStream is null
+            assertThrowsNPE(() -> fin.transferTo(null), "out");
+        } finally {
+            if (in != null)
+                try {
+                    in.close();
+                } catch (IOException ignored) { }
+        }
+    }
+
+    @Test
+    public void ifExceptionInInputNeitherStreamIsClosed()
+            throws IOException {
+        transferToThenCheckIfAnyClosed(input(0, new byte[]{1, 2, 3}), output());
+        transferToThenCheckIfAnyClosed(input(1, new byte[]{1, 2, 3}), output());
+        transferToThenCheckIfAnyClosed(input(2, new byte[]{1, 2, 3}), output());
+    }
+
+    @Test
+    public void ifExceptionInOutputNeitherStreamIsClosed()
+            throws IOException {
+        transferToThenCheckIfAnyClosed(input(new byte[]{1, 2, 3}), output(0));
+        transferToThenCheckIfAnyClosed(input(new byte[]{1, 2, 3}), output(1));
+        transferToThenCheckIfAnyClosed(input(new byte[]{1, 2, 3}), output(2));
+    }
+
+    private static void transferToThenCheckIfAnyClosed(InputStream input,
+            OutputStream output)
+            throws IOException {
+        try (CloseLoggingInputStream in = new CloseLoggingInputStream(input);
+             CloseLoggingOutputStream out =
+                     new CloseLoggingOutputStream(output)) {
+            boolean thrown = false;
+            try {
+                in.transferTo(out);
+            } catch (IOException ignored) {
+                thrown = true;
+            }
+            if (!thrown)
+                throw new AssertionError();
+
+            if (in.wasClosed() || out.wasClosed()) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void onReturnNeitherStreamIsClosed()
+            throws IOException {
+        try (CloseLoggingInputStream in =
+                     new CloseLoggingInputStream(input(new byte[]{1, 2, 3}));
+             CloseLoggingOutputStream out =
+                     new CloseLoggingOutputStream(output())) {
+
+            in.transferTo(out);
+
+            if (in.wasClosed() || out.wasClosed()) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void onReturnInputIsAtEnd() throws IOException {
+        try (InputStream in = input(new byte[]{1, 2, 3});
+             OutputStream out = output()) {
+
+            in.transferTo(out);
+
+            if (in.read() != -1) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void contents() throws IOException {
+        checkTransferredContents(new byte[0]);
+        checkTransferredContents(createRandomBytes(1024, 4096));
+        // to span through several batches
+        checkTransferredContents(createRandomBytes(16384, 16384));
+    }
+
+    private static void checkTransferredContents(byte[] bytes)
+            throws IOException {
+        try (InputStream in = input(bytes);
+             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+            in.transferTo(out);
+
+            byte[] outBytes = out.toByteArray();
+            if (!Arrays.equals(bytes, outBytes)) {
+                throw new AssertionError(
+                        format("bytes.length=%s, outBytes.length=%s",
+                                bytes.length, outBytes.length));
+            }
+        }
+    }
+
+    private static byte[] createRandomBytes(int min, int maxRandomAdditive) {
+        Random rnd = new Random();
+        byte[] bytes = new byte[min + rnd.nextInt(maxRandomAdditive)];
+        rnd.nextBytes(bytes);
+        return bytes;
+    }
+
+    private static OutputStream output() {
+        return output(-1);
+    }
+
+    private static OutputStream output(int exceptionPosition) {
+        return new OutputStream() {
+
+            int pos;
+
+            @Override
+            public void write(int b) throws IOException {
+                if (pos++ == exceptionPosition)
+                    throw new IOException();
+            }
+        };
+    }
+
+    private static InputStream input(byte... bytes) {
+        return input(-1, bytes);
+    }
+
+    private static InputStream input(int exceptionPosition, byte... bytes) {
+        return new InputStream() {
+
+            int pos;
+
+            @Override
+            public int read() throws IOException {
+                if (pos == exceptionPosition) {
+                    // because of the pesky IOException swallowing in
+                    // java.io.InputStream.read(byte[], int, int)
+                    // pos++;
+                    throw new IOException();
+                }
+
+                if (pos >= bytes.length)
+                    return -1;
+                return bytes[pos++] & 0xff;
+            }
+        };
+    }
+
+    private static class ThrowingInputStream extends InputStream {
+
+        boolean closed;
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public long skip(long n) throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public int available() throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public void close() throws IOException {
+            if (!closed) {
+                closed = true;
+                throw new IOException();
+            }
+        }
+
+        @Override
+        public void reset() throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public int read() throws IOException {
+            throw new IOException();
+        }
+    }
+
+    private static class CloseLoggingInputStream extends FilterInputStream {
+
+        boolean closed;
+
+        CloseLoggingInputStream(InputStream in) {
+            super(in);
+        }
+
+        @Override
+        public void close() throws IOException {
+            closed = true;
+            super.close();
+        }
+
+        boolean wasClosed() {
+            return closed;
+        }
+    }
+
+    private static class CloseLoggingOutputStream extends FilterOutputStream {
+
+        boolean closed;
+
+        CloseLoggingOutputStream(OutputStream out) {
+            super(out);
+        }
+
+        @Override
+        public void close() throws IOException {
+            closed = true;
+            super.close();
+        }
+
+        boolean wasClosed() {
+            return closed;
+        }
+    }
+
+    public interface Thrower {
+        public void run() throws Throwable;
+    }
+
+    public static void assertThrowsNPE(Thrower thrower, String message) {
+        assertThrows(thrower, NullPointerException.class, message);
+    }
+
+    public static <T extends Throwable> void assertThrows(Thrower thrower,
+            Class<T> throwable,
+            String message) {
+        Throwable thrown;
+        try {
+            thrower.run();
+            thrown = null;
+        } catch (Throwable caught) {
+            thrown = caught;
+        }
+
+        if (!throwable.isInstance(thrown)) {
+            String caught = thrown == null ?
+                    "nothing" : thrown.getClass().getCanonicalName();
+            throw new AssertionError(
+                    format("Expected to catch %s, but caught %s",
+                            throwable, caught), thrown);
+        }
+
+        if (thrown != null && !message.equals(thrown.getMessage())) {
+            throw new AssertionError(
+                    format("Expected exception message to be '%s', but it's '%s'",
+                            message, thrown.getMessage()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/OutputStream/NullOutputStream.java b/ojluni/src/test/java/io/OutputStream/NullOutputStream.java
new file mode 100644
index 0000000..982313d
--- /dev/null
+++ b/ojluni/src/test/java/io/OutputStream/NullOutputStream.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.OutputStream;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import org.testng.annotations.AfterGroups;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 4358774
+ * @run testng NullOutputStream
+ * @summary Check for expected behavior of OutputStream.nullOutputStream().
+ */
+public class NullOutputStream {
+    private static OutputStream openStream;
+    private static OutputStream closedStream;
+
+    @BeforeGroups(groups="open")
+    public static void openStream() {
+        openStream = OutputStream.nullOutputStream();
+    }
+
+    @BeforeGroups(groups="closed")
+    public static void openAndCloseStream() {
+        closedStream = OutputStream.nullOutputStream();
+        try {
+            closedStream.close();
+        } catch (IOException e) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @AfterGroups(groups="open")
+    public static void closeStream() {
+        try {
+            openStream.close();
+        } catch (IOException e) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups="open")
+    public static void testOpen() {
+        assertNotNull(openStream,
+                "OutputStream.nullOutputStream() returned null");
+    }
+
+    @Test(groups="open")
+    public static void testWrite() {
+        try {
+            openStream.write(62832);
+        } catch (IOException e) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups="open")
+    public static void testWriteBII() {
+        try {
+            openStream.write(new byte[] {(byte)6}, 0, 1);
+        } catch (Exception e) {
+            fail("Unexpected IOException");
+        }
+    }
+
+    @Test(groups="closed")
+    public static void testWriteClosed() {
+        try {
+            closedStream.write(62832);
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+
+    @Test(groups="closed")
+    public static void testWriteBIIClosed() {
+        try {
+            closedStream.write(new byte[] {(byte)6}, 0, 1);
+            fail("Expected IOException not thrown");
+        } catch (IOException e) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/PrintStream/EncodingTest.java b/ojluni/src/test/java/io/PrintStream/EncodingTest.java
new file mode 100644
index 0000000..41caec7
--- /dev/null
+++ b/ojluni/src/test/java/io/PrintStream/EncodingTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.PrintStream;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183743
+ * @summary Test to verify the new overload method with Charset functions the same
+ * as the existing method that takes a charset name.
+ * @run testng EncodingTest
+ */
+public class EncodingTest {
+    static boolean AUTOFLUSH = true;
+    public static enum ConstructorType {
+        STRING,
+        FILE,
+        OUTPUTSTREAM
+    }
+
+    /*
+     * DataProvider fields:
+     * Type of the constructor, a file to be written with a charset name,
+     * a file to be written with a charset, charset name, charset.
+     */
+    @DataProvider(name = "parameters")
+    public Object[][] getParameters() throws IOException {
+        String csn = StandardCharsets.UTF_8.name();
+        Charset charset = StandardCharsets.UTF_8;
+        File file1 = File.createTempFile("PSCharsetTest1", "txt");
+        File file2 = File.createTempFile("PSCharsetTest2", "txt");
+
+        return new Object[][]{
+                {ConstructorType.STRING, file1, file2, csn, charset},
+                {ConstructorType.FILE, file1, file2, csn, charset},
+                {ConstructorType.OUTPUTSTREAM, file1, file2, csn, charset}
+        };
+    }
+
+    /**
+     * Verifies that the overloading constructor behaves the same as the existing
+     * one.
+     * @param type the type of the constructor
+     * @param file1 file1 written with the name of a charset
+     * @param file2 file2 written with a charset
+     * @param csn the charset name
+     * @param charset the charset
+     * @throws IOException
+     */
+    @Test(dataProvider = "parameters")
+    public void test(ConstructorType type, File file1, File file2, String csn, Charset charset)
+            throws Exception {
+        createFile(getPrintStream(type, file1.getPath(), csn, null));
+        createFile(getPrintStream(type, file2.getPath(), null, charset));
+
+        Assert.assertEquals(Files.readAllLines(Paths.get(file1.getPath()), charset),
+                Files.readAllLines(Paths.get(file2.getPath()), charset));
+    }
+
+    public void createFile(PrintStream out) throws IOException {
+        out.println("high surrogate");
+        out.println(Character.MIN_HIGH_SURROGATE);
+        out.println("low surrogate");
+        out.println(Character.MIN_LOW_SURROGATE);
+        out.flush();
+        out.close();
+    }
+
+    PrintStream getPrintStream(ConstructorType type, String path, String csn, Charset charset)
+            throws IOException {
+        PrintStream out = null;
+        if (csn != null) {
+            switch (type) {
+                case STRING:
+                    out = new PrintStream(path, csn);
+                    break;
+                case FILE:
+                    out = new PrintStream(new File(path), csn);
+                    break;
+                case OUTPUTSTREAM:
+                    FileOutputStream fout = new FileOutputStream(path);
+                    out = new PrintStream(fout, AUTOFLUSH, csn);
+                    break;
+            }
+        } else {
+            switch (type) {
+                case STRING:
+                    out = new PrintStream(path, charset);
+                    break;
+                case FILE:
+                    out = new PrintStream(new File(path), charset);
+                    break;
+                case OUTPUTSTREAM:
+                    FileOutputStream fout = new FileOutputStream(path);
+                    out = new PrintStream(fout, AUTOFLUSH, charset);
+                    break;
+            }
+        }
+
+        return out;
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/PrintWriter/EncodingTest.java b/ojluni/src/test/java/io/PrintWriter/EncodingTest.java
new file mode 100644
index 0000000..7f2608b
--- /dev/null
+++ b/ojluni/src/test/java/io/PrintWriter/EncodingTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.PrintWriter;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183743
+ * @bug 8183743
+ * @summary Test to verify the new overload method with Charset functions the same
+ * as the existing method that takes a charset name.
+ * @run testng EncodingTest
+ */
+public class EncodingTest {
+    static boolean AUTOFLUSH = true;
+    public static enum ConstructorType {
+        STRING,
+        FILE,
+        OUTPUTSTREAM
+    }
+
+    /*
+     * DataProvider fields:
+     * Type of the constructor, a file to be written with a charset name,
+     * a file to be written with a charset, charset name, charset.
+     */
+    @DataProvider(name = "parameters")
+    public Object[][] getParameters() throws IOException {
+        String csn = StandardCharsets.UTF_8.name();
+        Charset charset = StandardCharsets.UTF_8;
+        File file1 = File.createTempFile("PSCharsetTest1", "txt");
+        File file2 = File.createTempFile("PSCharsetTest2", "txt");
+
+        return new Object[][]{
+                {ConstructorType.STRING, file1, file2, csn, charset},
+                {ConstructorType.FILE, file1, file2, csn, charset},
+                {ConstructorType.OUTPUTSTREAM, file1, file2, csn, charset}
+        };
+    }
+
+    /**
+     * Verifies that the overloading constructor behaves the same as the existing
+     * one.
+     *
+     * @param type the type of the constructor
+     * @param file1 file1 written with the name of a charset
+     * @param file2 file2 written with a charset
+     * @param csn the charset name
+     * @param charset the charset
+     * @throws IOException
+     */
+    @Test(dataProvider = "parameters")
+    public void test(ConstructorType type, File file1, File file2, String csn, Charset charset)
+            throws Exception {
+        createFile(getWriter(type, file1.getPath(), csn, null));
+        createFile(getWriter(type, file2.getPath(), null, charset));
+
+        Assert.assertEquals(Files.readAllLines(Paths.get(file1.getPath()), charset),
+                Files.readAllLines(Paths.get(file2.getPath()), charset));
+    }
+
+    void createFile(PrintWriter out) throws IOException {
+        out.println("high surrogate");
+        out.println(Character.MIN_HIGH_SURROGATE);
+        out.println("low surrogate");
+        out.println(Character.MIN_LOW_SURROGATE);
+        out.flush();
+        out.close();
+    }
+
+    PrintWriter getWriter(ConstructorType type, String path, String csn, Charset charset)
+            throws IOException {
+        PrintWriter out = null;
+        if (csn != null) {
+            switch (type) {
+                case STRING:
+                    out = new PrintWriter(path, csn);
+                    break;
+                case FILE:
+                    out = new PrintWriter(new File(path), csn);
+                    break;
+                case OUTPUTSTREAM:
+                    // No corresponding method with charset name
+                    // compare with PrintWriter(path, csn) instead
+                    out = new PrintWriter(path, csn);
+                    break;
+            }
+        } else {
+            switch (type) {
+                case STRING:
+                    out = new PrintWriter(path, charset);
+                    break;
+                case FILE:
+                    out = new PrintWriter(new File(path), charset);
+                    break;
+                case OUTPUTSTREAM:
+                    FileOutputStream fout = new FileOutputStream(path);
+                    out = new PrintWriter(fout, AUTOFLUSH, charset);
+                    break;
+            }
+        }
+
+        return out;
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/Reader/NullReader.java b/ojluni/src/test/java/io/Reader/NullReader.java
new file mode 100644
index 0000000..67083f1
--- /dev/null
+++ b/ojluni/src/test/java/io/Reader/NullReader.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.Reader;
+
+import java.io.Reader;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+
+import org.testng.annotations.AfterGroups;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 8196298 8204930
+ * @run testng NullReader
+ * @summary Check for expected behavior of Reader.nullReader().
+ */
+public class NullReader {
+    private static Reader openReader;
+    private static Reader closedReader;
+
+    @BeforeGroups(groups = "open")
+    public static void openStream() {
+        openReader = Reader.nullReader();
+    }
+
+    @BeforeGroups(groups = "closed")
+    public static void openAndCloseStream() throws IOException {
+        closedReader = Reader.nullReader();
+        closedReader.close();
+    }
+
+    @AfterGroups(groups = "open")
+    public static void closeStream() throws IOException {
+        openReader.close();
+    }
+
+    @Test(groups = "open")
+    public static void testOpen() {
+        assertNotNull(openReader, "Reader.nullReader() returned null");
+    }
+
+    @Test(groups = "open")
+    public static void testRead() throws IOException {
+        assertEquals(-1, openReader.read(), "read() != -1");
+    }
+
+    @Test(groups = "open")
+    public static void testReadBII() throws IOException {
+        assertEquals(-1, openReader.read(new char[1], 0, 1),
+                "read(char[],int,int) != -1");
+    }
+
+    @Test(groups = "open")
+    public static void testReadBIILenZero() throws IOException {
+        assertEquals(0, openReader.read(new char[1], 0, 0),
+                "read(char[],int,int) != 0");
+    }
+
+    @Test(groups = "open")
+    public static void testReadCharBuffer() throws IOException {
+        CharBuffer charBuffer = CharBuffer.allocate(1);
+        assertEquals(-1, openReader.read(charBuffer),
+                "read(CharBuffer) != -1");
+    }
+
+    @Test(groups = "open")
+    public static void testReadCharBufferZeroRemaining() throws IOException {
+        CharBuffer charBuffer = CharBuffer.allocate(0);
+        assertEquals(0, openReader.read(charBuffer),
+                "read(CharBuffer) != 0");
+    }
+
+    @Test(groups = "open")
+    public static void testReady() throws IOException {
+        assertFalse(openReader.ready());
+    }
+
+    @Test(groups = "open")
+    public static void testSkip() throws IOException {
+        assertEquals(0, openReader.skip(1), "skip() != 0");
+    }
+
+    @Test(groups = "open")
+    public static void testTransferTo() throws IOException {
+        assertEquals(0, openReader.transferTo(new StringWriter(7)),
+                "transferTo() != 0");
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testReadClosed() throws IOException {
+        closedReader.read();
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testReadBIIClosed() throws IOException {
+        closedReader.read(new char[1], 0, 1);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testReadCharBufferClosed() throws IOException {
+        CharBuffer charBuffer = CharBuffer.allocate(0);
+        closedReader.read(charBuffer);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testReadCharBufferZeroRemainingClosed() throws IOException {
+        CharBuffer charBuffer = CharBuffer.allocate(0);
+        closedReader.read(charBuffer);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testReadyClosed() throws IOException {
+        closedReader.ready();
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testSkipClosed() throws IOException {
+        closedReader.skip(1);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testTransferToClosed() throws IOException {
+        closedReader.transferTo(new StringWriter(7));
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/Reader/TransferTo.java b/ojluni/src/test/java/io/Reader/TransferTo.java
new file mode 100644
index 0000000..f3dd40a
--- /dev/null
+++ b/ojluni/src/test/java/io/Reader/TransferTo.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.io.Reader;
+
+import java.io.*;
+import java.util.Arrays;
+import java.util.Random;
+import org.testng.annotations.Test;
+
+import static java.lang.String.format;
+
+/*
+ * @test
+ * @bug 8191706
+ * @summary tests whether java.io.Reader.transferTo conforms to its
+ *          contract defined source the javadoc
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main TransferTo
+ * @key randomness
+ * @author Patrick Reinhart
+ */
+public class TransferTo {
+
+    private static Random generator = new Random();
+
+    @Test
+    public void ifOutIsNullThenNpeIsThrown() throws IOException {
+        try (Reader in = input()) {
+            assertThrowsNPE(() -> in.transferTo(null), "out");
+        }
+
+        try (Reader in = input((char) 1)) {
+            assertThrowsNPE(() -> in.transferTo(null), "out");
+        }
+
+        try (Reader in = input((char) 1, (char) 2)) {
+            assertThrowsNPE(() -> in.transferTo(null), "out");
+        }
+
+        Reader in = null;
+        try {
+            Reader fin = in = new ThrowingReader();
+            // null check should precede everything else:
+            // Reader shouldn't be touched if Writer is null
+            assertThrowsNPE(() -> fin.transferTo(null), "out");
+        } finally {
+            if (in != null)
+                try {
+                    in.close();
+                } catch (IOException ignored) { }
+        }
+    }
+
+    @Test
+    public void ifExceptionInInputNeitherStreamIsClosed()
+            throws IOException {
+        transferToThenCheckIfAnyClosed(input(0, new char[]{1, 2, 3}), output());
+        transferToThenCheckIfAnyClosed(input(1, new char[]{1, 2, 3}), output());
+        transferToThenCheckIfAnyClosed(input(2, new char[]{1, 2, 3}), output());
+    }
+
+    @Test
+    public void ifExceptionInOutputNeitherStreamIsClosed()
+            throws IOException {
+        transferToThenCheckIfAnyClosed(input(new char[]{1, 2, 3}), output(0));
+        transferToThenCheckIfAnyClosed(input(new char[]{1, 2, 3}), output(1));
+        transferToThenCheckIfAnyClosed(input(new char[]{1, 2, 3}), output(2));
+    }
+
+    private static void transferToThenCheckIfAnyClosed(Reader input,
+            Writer output)
+            throws IOException {
+        try (CloseLoggingReader in = new CloseLoggingReader(input);
+             CloseLoggingWriter out =
+                     new CloseLoggingWriter(output)) {
+            boolean thrown = false;
+            try {
+                in.transferTo(out);
+            } catch (IOException ignored) {
+                thrown = true;
+            }
+            if (!thrown)
+                throw new AssertionError();
+
+            if (in.wasClosed() || out.wasClosed()) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void onReturnNeitherStreamIsClosed()
+            throws IOException {
+        try (CloseLoggingReader in =
+                     new CloseLoggingReader(input(new char[]{1, 2, 3}));
+             CloseLoggingWriter out =
+                     new CloseLoggingWriter(output())) {
+
+            in.transferTo(out);
+
+            if (in.wasClosed() || out.wasClosed()) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void onReturnInputIsAtEnd() throws IOException {
+        try (Reader in = input(new char[]{1, 2, 3});
+             Writer out = output()) {
+
+            in.transferTo(out);
+
+            if (in.read() != -1) {
+                throw new AssertionError();
+            }
+        }
+    }
+
+    @Test
+    public void contents() throws IOException {
+        checkTransferredContents(new char[0]);
+        checkTransferredContents(createRandomChars(1024, 4096));
+        // to span through several batches
+        checkTransferredContents(createRandomChars(16384, 16384));
+    }
+
+    private static void checkTransferredContents(char[] chars)
+            throws IOException {
+        try (Reader in = input(chars);
+             StringWriter out = new StringWriter()) {
+            in.transferTo(out);
+
+            char[] outChars = out.toString().toCharArray();
+            if (!Arrays.equals(chars, outChars)) {
+                throw new AssertionError(
+                        format("chars.length=%s, outChars.length=%s",
+                                chars.length, outChars.length));
+            }
+        }
+    }
+
+    private static char[] createRandomChars(int min, int maxRandomAdditive) {
+        char[] chars = new char[min + generator.nextInt(maxRandomAdditive)];
+        for (int index=0; index<chars.length; index++) {
+            chars[index] = (char)generator.nextInt();
+        }
+        return chars;
+    }
+
+    private static Writer output() {
+        return output(-1);
+    }
+
+    private static Writer output(int exceptionPosition) {
+        return new Writer() {
+
+            int pos;
+
+            @Override
+            public void write(int b) throws IOException {
+                if (pos++ == exceptionPosition)
+                    throw new IOException();
+            }
+
+            @Override
+            public void write(char[] chars, int off, int len) throws IOException {
+                for (int i=0; i<len; i++) {
+                    write(chars[off + i]);
+                }
+            }
+
+            @Override
+            public Writer append(CharSequence csq, int start, int end) throws IOException {
+                for (int i = start; i < end; i++) {
+                    write(csq.charAt(i));
+                }
+                return this;
+            }
+
+            @Override
+            public void flush() throws IOException {
+            }
+
+            @Override
+            public void close() throws IOException {
+            }
+        };
+    }
+
+    private static Reader input(char... chars) {
+        return input(-1, chars);
+    }
+
+    private static Reader input(int exceptionPosition, char... chars) {
+        return new Reader() {
+
+            int pos;
+
+            @Override
+            public int read() throws IOException {
+                if (pos == exceptionPosition) {
+                    throw new IOException();
+                }
+
+                if (pos >= chars.length)
+                    return -1;
+                return chars[pos++];
+            }
+
+            @Override
+            public int read(char[] cbuf, int off, int len) throws IOException {
+                int c = read();
+                if (c == -1) {
+                    return -1;
+                }
+                cbuf[off] = (char)c;
+
+                int i = 1;
+                for (; i < len ; i++) {
+                    c = read();
+                    if (c == -1) {
+                        break;
+                    }
+                    cbuf[off + i] = (char)c;
+                }
+                return i;
+            }
+
+            @Override
+            public void close() throws IOException {
+            }
+        };
+    }
+
+    private static class ThrowingReader extends Reader {
+
+        boolean closed;
+
+        @Override
+        public int read(char[] b, int off, int len) throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public void close() throws IOException {
+            if (!closed) {
+                closed = true;
+                throw new IOException();
+            }
+        }
+        @Override
+        public int read() throws IOException {
+            throw new IOException();
+        }
+    }
+
+    private static class CloseLoggingReader extends FilterReader {
+
+        boolean closed;
+
+        CloseLoggingReader(Reader in) {
+            super(in);
+        }
+
+        @Override
+        public void close() throws IOException {
+            closed = true;
+            super.close();
+        }
+
+        boolean wasClosed() {
+            return closed;
+        }
+    }
+
+    private static class CloseLoggingWriter extends FilterWriter {
+
+        boolean closed;
+
+        CloseLoggingWriter(Writer out) {
+            super(out);
+        }
+
+        @Override
+        public void close() throws IOException {
+            closed = true;
+            super.close();
+        }
+
+        boolean wasClosed() {
+            return closed;
+        }
+    }
+
+    public interface Thrower {
+        public void run() throws Throwable;
+    }
+
+    public static void assertThrowsNPE(Thrower thrower, String message) {
+        assertThrows(thrower, NullPointerException.class, message);
+    }
+
+    public static <T extends Throwable> void assertThrows(Thrower thrower,
+            Class<T> throwable,
+            String message) {
+        Throwable thrown;
+        try {
+            thrower.run();
+            thrown = null;
+        } catch (Throwable caught) {
+            thrown = caught;
+        }
+
+        if (!throwable.isInstance(thrown)) {
+            String caught = thrown == null ?
+                    "nothing" : thrown.getClass().getCanonicalName();
+            throw new AssertionError(
+                    format("Expected to catch %s, but caught %s",
+                            throwable, caught), thrown);
+        }
+
+        if (thrown != null && !message.equals(thrown.getMessage())) {
+            throw new AssertionError(
+                    format("Expected exception message to be '%s', but it's '%s'",
+                            message, thrown.getMessage()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/io/Writer/NullWriter.java b/ojluni/src/test/java/io/Writer/NullWriter.java
new file mode 100644
index 0000000..f33ecaa
--- /dev/null
+++ b/ojluni/src/test/java/io/Writer/NullWriter.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+// Android-added: Test package.
+package test.java.io.Writer;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.testng.annotations.AfterGroups;
+import org.testng.annotations.BeforeGroups;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+/*
+ * @test
+ * @bug 8196298
+ * @run testng NullWriter
+ * @summary Check for expected behavior of Writer.nullWriter().
+ */
+public class NullWriter {
+    private static Writer openWriter;
+    private static Writer closedWriter;
+
+    @BeforeGroups(groups = "open")
+    public static void openStream() {
+        openWriter = Writer.nullWriter();
+    }
+
+    @BeforeGroups(groups = "closed")
+    public static void openAndCloseStream() throws IOException {
+        closedWriter = Writer.nullWriter();
+        closedWriter.close();
+    }
+
+    @AfterGroups(groups = "open")
+    public static void closeStream() throws IOException {
+        openWriter.close();
+    }
+
+    @Test(groups = "open")
+    public static void testOpen() {
+        assertNotNull(openWriter, "Writer.nullWriter() returned null");
+    }
+
+    @Test(groups = "open")
+    public static void testAppendChar() throws IOException {
+        assertSame(openWriter, openWriter.append('x'));
+    }
+
+    @Test(groups = "open")
+    public static void testAppendCharSequence() throws IOException {
+        CharSequence cs = "abc";
+        assertSame(openWriter, openWriter.append(cs));
+    }
+
+    @Test(groups = "open")
+    public static void testAppendCharSequenceNull() throws IOException {
+        assertSame(openWriter, openWriter.append(null));
+    }
+
+    @Test(groups = "open")
+    public static void testAppendCharSequenceII() throws IOException {
+        CharSequence cs = "abc";
+        assertSame(openWriter, openWriter.append(cs, 0, 1));
+    }
+
+    @Test(groups = "open")
+    public static void testAppendCharSequenceIINull() throws IOException {
+        assertSame(openWriter, openWriter.append(null, 2, 1));
+    }
+
+    @Test(groups = "open")
+    public static void testFlush() throws IOException {
+        openWriter.flush();
+    }
+
+    @Test(groups = "open")
+    public static void testWrite() throws IOException {
+        openWriter.write(62832);
+    }
+
+    @Test(groups = "open")
+    public static void testWriteString() throws IOException {
+        openWriter.write("");
+    }
+
+    @Test(groups = "open")
+    public static void testWriteStringII() throws IOException {
+        openWriter.write("", 0, 0);
+    }
+
+    @Test(groups = "open")
+    public static void testWriteBII() throws IOException, Exception {
+        openWriter.write(new char[]{(char) 6}, 0, 1);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testAppendCharClosed() throws IOException {
+        closedWriter.append('x');
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testAppendCharSequenceClosed() throws IOException {
+        CharSequence cs = "abc";
+        closedWriter.append(cs);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testAppendCharSequenceNullClosed() throws IOException {
+        closedWriter.append(null);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testAppendCharSequenceIIClosed() throws IOException {
+        CharSequence cs = "abc";
+        closedWriter.append(cs, 0, 1);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testAppendCharSequenceIINullClosed() throws IOException {
+        closedWriter.append(null, 2, 1);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testFlushClosed() throws IOException {
+        closedWriter.flush();
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testWriteClosed() throws IOException {
+        closedWriter.write(62832);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testWriteStringClosed() throws IOException {
+        closedWriter.write("");
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testWriteStringIIClosed() throws IOException {
+        closedWriter.write("", 0, 0);
+    }
+
+    @Test(groups = "closed", expectedExceptions = IOException.class)
+    public static void testWriteBIIClosed() throws IOException {
+        closedWriter.write(new char[]{(char) 6}, 0, 1);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Boolean/Factory.java b/ojluni/src/test/java/lang/Boolean/Factory.java
new file mode 100644
index 0000000..55238f0
--- /dev/null
+++ b/ojluni/src/test/java/lang/Boolean/Factory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4262398
+ * @summary Basic test for Boolean.valueOf(boolean b).
+ */
+package test.java.lang.Boolean;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class Factory {
+
+    @Test
+    public void testFactoryValueOf()  {
+        Assert.assertEquals(Boolean.valueOf(true), Boolean.TRUE);
+        Assert.assertEquals(Boolean.valueOf(false), Boolean.FALSE);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Boolean/GetBoolean.java b/ojluni/src/test/java/lang/Boolean/GetBoolean.java
new file mode 100644
index 0000000..519be80
--- /dev/null
+++ b/ojluni/src/test/java/lang/Boolean/GetBoolean.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4252308
+ * @summary test Boolean.getBoolean method with empty key
+ */
+package test.java.lang.Boolean;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class GetBoolean {
+
+    @Test
+    public void testFactoryGetBoolean() {
+        Assert.assertFalse(Boolean.getBoolean(""));
+        Assert.assertFalse(Boolean.getBoolean(null));
+    }
+}
diff --git a/ojluni/src/test/java/lang/Boolean/MakeBooleanComparable.java b/ojluni/src/test/java/lang/Boolean/MakeBooleanComparable.java
new file mode 100644
index 0000000..9c181a2
--- /dev/null
+++ b/ojluni/src/test/java/lang/Boolean/MakeBooleanComparable.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     4329937
+ * @summary Basic test for making Boolean implement Comparable
+ * @author  Josh Bloch
+ * @key randomness
+ */
+package test.java.lang.Boolean;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class MakeBooleanComparable {
+
+    @Test
+    public void testComparable() {
+        Random rnd = new Random();
+        List<Boolean> list = new ArrayList<>();
+        int numFalse = 0;
+        for (int i = 0; i < 1000; i++) {
+            boolean element = rnd.nextBoolean();
+            if (!element) {
+                numFalse++;
+            }
+            list.add(element); // Autoboxing!
+        }
+
+        Collections.sort(list);
+
+        for (int i = 0; i < numFalse; i++) {
+            Assert.assertFalse(list.get(i).booleanValue()); // Autounboxing doesn't work yet!
+        }
+        for (int i = numFalse; i < 1000; i++) {
+            Assert.assertTrue(list.get(i).booleanValue()); // Autounboxing doesn't work yet!
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Boolean/ParseBoolean.java b/ojluni/src/test/java/lang/Boolean/ParseBoolean.java
new file mode 100644
index 0000000..b768444
--- /dev/null
+++ b/ojluni/src/test/java/lang/Boolean/ParseBoolean.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4253773
+ * @summary test Boolean.parseBoolean
+ */
+package test.java.lang.Boolean;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ParseBoolean {
+
+    @Test
+    public void testParseBoolean() {
+        Assert.assertTrue(Boolean.parseBoolean("TRUE"));
+        Assert.assertTrue(Boolean.parseBoolean("true"));
+        Assert.assertTrue(Boolean.parseBoolean("TrUe"));
+
+        Assert.assertFalse(Boolean.parseBoolean("false"));
+        Assert.assertFalse(Boolean.parseBoolean("FALSE"));
+        Assert.assertFalse(Boolean.parseBoolean("FaLse"));
+        Assert.assertFalse(Boolean.parseBoolean(null));
+        Assert.assertFalse(Boolean.parseBoolean("garbage"));
+        Assert.assertFalse(Boolean.parseBoolean("TRUEE"));
+    }
+}
diff --git a/ojluni/src/test/java/lang/ClassLoader/AssertTest.java b/ojluni/src/test/java/lang/ClassLoader/AssertTest.java
new file mode 100644
index 0000000..83483fe
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/AssertTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4290640 4785473
+ * @build package1.Class1 package2.Class2 package1.package3.Class3 Assert
+ * @run main/othervm Assert
+ * @summary Test the assertion facility
+ * @author Mike McCloskey
+ * @key randomness
+ */
+
+// Android-changed: Adapt structure and expectations to Android.
+// Android does not use AssertionStatuses, so this test changes expectations to reflect that.
+// Furthermore, the test structure is simplified to avoid relying on args[] and use the
+// org.testng.annotations.Test package instead of a main() method.
+package test.java.lang.ClassLoader;
+
+import test.java.lang.ClassLoader.package1.*;
+import test.java.lang.ClassLoader.package2.*;
+import test.java.lang.ClassLoader.package1.package3.*;
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+public class AssertTest {
+
+    private static Class1 testClass1;
+    private static Class2 testClass2;
+    private static Class3 testClass3;
+    private static Random generator = new Random();
+
+    /**
+     * AssertionStatuses don't actually do anything on Android, this test proves as much.
+     */
+    @Test
+    public void testAssert() {
+        // Switch values: 0=don't touch, 1=off, 2 = on
+        int[] switches = new int[7];
+        for(int x=0; x<10; x++) {
+            int temp = generator.nextInt(2187);
+            for (int i = 0; i < 7; i++) {
+                switches[i] = temp % 3;
+                temp = temp / 3;
+            }
+            SetAssertionSwitches(switches);
+            ConstructClassTree();
+            TestClassTree();
+        }
+
+
+        // Android-added: Add testing of clearAssertionStatus().
+        for(int x=0; x<7; x++) {
+            switches[x]=2;
+        }
+        ClassLoader loader = SetAssertionSwitches(switches);
+        loader.clearAssertionStatus(); // Clearing also does nothing
+        ConstructClassTree();
+        TestClassTree();
+    }
+
+    /*
+     * Activate/Deactivate the assertions in the tree according to the
+     * specified switches.
+     */
+    private static ClassLoader SetAssertionSwitches(int[] switches) {
+        ClassLoader loader = ClassLoader.getSystemClassLoader();
+
+        if (switches[0] != 0)
+            loader.setDefaultAssertionStatus(switches[0]==2);
+        if (switches[1] != 0)
+            loader.setPackageAssertionStatus("package1", switches[1]==2);
+        if (switches[2] != 0)
+            loader.setPackageAssertionStatus("package2", switches[2]==2);
+        if (switches[3] != 0)
+            loader.setPackageAssertionStatus("package1.package3", switches[3]==2);
+        if (switches[4] != 0)
+            loader.setClassAssertionStatus("package1.Class1", switches[4]==2);
+        if (switches[5] != 0)
+            loader.setClassAssertionStatus("package2.Class2", switches[5]==2);
+        if (switches[6] != 0)
+            loader.setClassAssertionStatus("package1.package3.Class3", switches[6]==2);
+        return loader;
+    }
+
+    /*
+     * Verify that the assertions are activated or deactivated as specified
+     * by the switches.
+     */
+    private static void TestClassTree() {
+        testClass1.testAssert(false);
+        Class1.Class11.testAssert(false);
+        testClass2.testAssert(false);
+        testClass3.testAssert(false);
+        Class3.Class31.testAssert(false);
+
+    }
+
+    /*
+     * Create the class tree to be tested. Each test run must reload the classes
+     * of the tree since assertion status is determined at class load time.
+     */
+    private static void ConstructClassTree() {
+        testClass1 = new Class1();
+        testClass2 = new Class2();
+        testClass3 = new Class3();
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/ClassLoader/package1/Class1.java b/ojluni/src/test/java/lang/ClassLoader/package1/Class1.java
new file mode 100644
index 0000000..0c5e7cc
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/package1/Class1.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.ClassLoader.package1;
+
+public class Class1 {
+    public void testAssert(boolean assertsShouldBeOn) {
+        boolean assertsEnabled = false;
+        assert(assertsEnabled = true);
+        if (assertsEnabled != assertsShouldBeOn)
+            throw new RuntimeException(assertsEnabled ? "TRUE" : "FALSE");
+
+        Class1 anonTest =  new Class1() {
+            public void testAssert(boolean assertsShouldBeOn) {
+                boolean assertsEnabled2 = false;
+                assert(assertsEnabled2 = true);
+                if (assertsEnabled2 != assertsShouldBeOn)
+                    throw new RuntimeException("Failure of Asserts Facility.");
+            }
+        };
+        anonTest.testAssert(assertsShouldBeOn);
+    }
+
+    // Named inner class
+    public static class Class11 {
+        public static void testAssert(boolean assertsShouldBeOn) {
+            boolean assertsEnabled3 = false;
+            assert(assertsEnabled3 = true);
+            if (assertsEnabled3 != assertsShouldBeOn)
+                throw new RuntimeException("Failure of Asserts Facility.");
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/ClassLoader/package1/package3/Class3.java b/ojluni/src/test/java/lang/ClassLoader/package1/package3/Class3.java
new file mode 100644
index 0000000..b133e2a
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/package1/package3/Class3.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.ClassLoader.package1.package3;
+
+import org.testng.Assert;
+
+public class Class3 {
+    public void testAssert(boolean assertsShouldBeOn) {
+        boolean assertsEnabled = false;
+        assert(assertsEnabled = true);
+        if (assertsEnabled != assertsShouldBeOn)
+            Assert.fail("Failure of Asserts Facility.");
+
+        Class3 anonTest =  new Class3() {
+            public void testAssert(boolean assertsShouldBeOn) {
+                boolean assertsEnabled = false;
+                assert(assertsEnabled = true);
+                if (assertsEnabled != assertsShouldBeOn)
+                    Assert.fail("Failure of Asserts Facility.");
+            }
+        };
+        anonTest.testAssert(assertsShouldBeOn);
+    }
+
+    // Named inner class
+    public static class Class31 {
+        public static void testAssert(boolean assertsShouldBeOn) {
+            boolean assertsEnabled = false;
+            assert(assertsEnabled = true);
+            if (assertsEnabled != assertsShouldBeOn)
+                Assert.fail("Failure of Asserts Facility.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/ClassLoader/package2/Class2.java b/ojluni/src/test/java/lang/ClassLoader/package2/Class2.java
new file mode 100644
index 0000000..d7d92bc
--- /dev/null
+++ b/ojluni/src/test/java/lang/ClassLoader/package2/Class2.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.ClassLoader.package2;
+
+
+public class Class2 {
+    public void testAssert(boolean assertsShouldBeOn) {
+        boolean assertsEnabled = false;
+        assert(assertsEnabled = true);
+        if (assertsEnabled != assertsShouldBeOn)
+            throw new RuntimeException("Failure of Asserts Facility.");
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/lang/Double/BitwiseConversionTest.java b/ojluni/src/test/java/lang/Double/BitwiseConversionTest.java
new file mode 100644
index 0000000..6c871a6
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/BitwiseConversionTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5037596
+ * @summary Verify bitwise conversion works for non-canonical NaN values
+ * @library ../Math
+ * @build DoubleConsts
+ * @run main BitwiseConversion
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Double;
+
+import static java.lang.Double.*;
+
+import jdk.internal.math.DoubleConsts;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class BitwiseConversionTest {
+    static void testNanCase(long x) {
+        // Strip out sign and exponent bits
+        long y = x & DoubleConsts.SIGNIF_BIT_MASK;
+
+        double[] values = {
+            longBitsToDouble(DoubleConsts.EXP_BIT_MASK | y),
+            longBitsToDouble(DoubleConsts.SIGN_BIT_MASK | DoubleConsts.EXP_BIT_MASK | y)
+        };
+
+        for(double value : values) {
+            Assert.assertTrue(isNaN(value), "Invalid input " + y + "yielded non-NaN" + value);
+
+            long converted = doubleToLongBits(value);
+            Assert.assertEquals(converted, 0x7ff8000000000000L,
+                String.format("Non-canonical NaN bits returned: %x%n", converted));
+        }
+    }
+
+    @Test
+    public void testNanCases() {
+        for (int i = 0; i < DoubleConsts.SIGNIFICAND_WIDTH - 1; i++) {
+            testNanCase(1L << i);
+        }
+    }
+
+    @Test
+    public void testDoubleToLongBits() {
+        Assert.assertEquals(doubleToLongBits(Double.POSITIVE_INFINITY), 0x7ff0000000000000L,
+            "Bad conversion for +infinity.");
+
+        Assert.assertEquals(doubleToLongBits(Double.NEGATIVE_INFINITY), 0xfff0000000000000L,
+            "Bad conversion for -infinity.");
+    }
+}
diff --git a/ojluni/src/test/java/lang/Double/ConstantsTest.java b/ojluni/src/test/java/lang/Double/ConstantsTest.java
new file mode 100644
index 0000000..816b42f
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/ConstantsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @compile Constants.java
+ * @bug 4397405 4826652
+ * @summary Testing constant-ness of Double.{MIN_VALUE, MAX_VALUE}, etc.
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Double;
+
+public class ConstantsTest {
+    /*
+     * This compile-only test is to make sure that the primitive
+     * public static final fields in java.lang.Double are "constant
+     * expressions" as defined by "The Java Language Specification,
+     * 2nd edition" section 15.28; a different test checks the values
+     * of those fields.
+     */
+    public void testPublicStaticFinalFields_areConstantExpressions() throws Exception {
+        int i = 0;
+        switch (i) {
+        case (int)Double.NaN:                   // 0
+            System.out.println("Double.NaN is a constant!");
+            break;
+        case (int)Double.MIN_VALUE + 1:         // 0 + 1
+            System.out.println("Double.MIN_VALUE is a constant!");
+            break;
+        case (int)Double.MIN_NORMAL + 2:        // 0 + 2
+            System.out.println("Double.MIN_NORMAL is a constant!");
+            break;
+        case Double.MIN_EXPONENT:               // -1022
+            System.out.println("Double.MIN_EXPONENT is a constant!");
+            break;
+        case Double.MAX_EXPONENT:               // 1023
+            System.out.println("Double.MAX_EXPONENT is a constant!");
+            break;
+        case (int)Double.MAX_VALUE - 1:         // Integer.MAX_VALUE - 1
+            System.out.println("Double.MAX_VALUE is a constant!");
+            break;
+        case (int)Double.POSITIVE_INFINITY:     // Integer.MAX_VALUE
+            System.out.println("Double.POSITIVE_INFINITY is a constant!");
+            break;
+        case (int)Double.NEGATIVE_INFINITY:     // Integer.MIN_VALUE
+            System.out.println("Double.NEGATIVE_INFINITY is a constant!");
+            break;
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Double/ExtremaTest.java b/ojluni/src/test/java/lang/Double/ExtremaTest.java
new file mode 100644
index 0000000..7591262
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/ExtremaTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4408489 4826652
+ * @summary Testing values of Double.{MIN_VALUE, MIN_NORMAL, MAX_VALUE}
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Double;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ExtremaTest {
+    @Test
+    public void testExtremalValues() throws Exception {
+        Assert.assertEquals(Double.longBitsToDouble(0x1L), Double.MIN_VALUE,
+            "Double.MIN_VALUE is not equal to longBitsToDouble(0x1L).");
+
+        Assert.assertEquals(Double.longBitsToDouble(0x0010000000000000L), Double.MIN_NORMAL,
+            "Double.MIN_NORMAL is not equal to longBitsToDouble(0x0010000000000000L).");
+
+        Assert.assertEquals (Double.longBitsToDouble(0x7fefffffffffffffL), Double.MAX_VALUE,
+            "Double.MAX_VALUE is not equal to longBitsToDouble(0x7fefffffffffffffL).");
+    }
+}
diff --git a/ojluni/src/test/java/lang/Double/NaNInfinityParsingTest.java b/ojluni/src/test/java/lang/Double/NaNInfinityParsingTest.java
new file mode 100644
index 0000000..3464b9a
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/NaNInfinityParsingTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4428772
+ * @summary Testing recognition of "NaN" and "Infinity" strings
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Double;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class NaNInfinityParsingTest {
+    /*
+     * Regression tests for:
+     * 4428772 -- Establish invariant for Float & Double classes and
+     * their string representations
+     *
+     * Added capability for parse{Float, Double} and related methods
+     * to recognize "NaN" and "Infinity" strings so that
+     * parseDouble(toString(d)) will always return the original
+     * floating-point value.
+     */
+
+    static String[] NaNStrings = {
+        "NaN",
+        "+NaN",
+        "-NaN"
+    };
+
+    static String[] infinityStrings = {
+        "Infinity",
+        "+Infinity",
+        "-Infinity",
+    };
+
+    static String[] invalidStrings = {
+        "+",
+        "-",
+        "@",
+        "N",
+        "Na",
+        "Nan",
+        "NaNf",
+        "NaNd",
+        "NaNF",
+        "NaND",
+        "+N",
+        "+Na",
+        "+Nan",
+        "+NaNf",
+        "+NaNd",
+        "+NaNF",
+        "+NaND",
+        "-N",
+        "-Na",
+        "-Nan",
+        "-NaNf",
+        "-NaNd",
+        "-NaNF",
+        "-NaND",
+        "I",
+        "In",
+        "Inf",
+        "Infi",
+        "Infin",
+        "Infini",
+        "Infinit",
+        "InfinitY",
+        "Infinityf",
+        "InfinityF",
+        "Infinityd",
+        "InfinityD",
+        "+I",
+        "+In",
+        "+Inf",
+        "+Infi",
+        "+Infin",
+        "+Infini",
+        "+Infinit",
+        "+InfinitY",
+        "+Infinityf",
+        "+InfinityF",
+        "+Infinityd",
+        "+InfinityD",
+        "-I",
+        "-In",
+        "-Inf",
+        "-Infi",
+        "-Infin",
+        "-Infini",
+        "-Infinit",
+        "-InfinitY",
+        "-Infinityf",
+        "-InfinityF",
+        "-Infinityd",
+        "-InfinityD",
+        "NaNInfinity",
+        "InfinityNaN",
+        "nan",
+        "infinity"
+    };
+
+    @Test
+    public void testValidNaNStrings() {
+        for (String naNString : NaNStrings) {
+            double d = Double.parseDouble(naNString);
+            Assert.assertTrue(Double.isNaN(d), "NaN string ``" + naNString
+                    + "'' did not parse as a NaN; returned " +
+                    d + " instead.");
+        }
+    }
+
+    @Test
+    public void testValidInfinityStrings() {
+        for (String infinityString : infinityStrings) {
+            double d = Double.parseDouble(infinityString);
+            Assert.assertTrue(Double.isInfinite(d), "Infinity string ``" +
+                    infinityString +
+                    "'' did not parse as infinity; returned " +
+                    d + "instead.");
+            // check sign of result
+
+            boolean negative = (infinityString.charAt(0) == '-');
+            Assert.assertEquals(d, (negative ? Double.NEGATIVE_INFINITY :
+                Double.POSITIVE_INFINITY), "Infinity has wrong sign;" +
+                    (negative ? "positive instead of negative." :
+                        "negative instead of positive."));
+        }
+    }
+
+    @Test
+    public void testAlmostValidStrings() {
+        for (String invalidString : invalidStrings) {
+            try {
+                double d = Double.parseDouble(invalidString);
+                Assert.fail("Invalid string ``" + invalidString + "'' parsed as " + d + ".");
+            } catch (NumberFormatException e) {
+               // expected
+            }
+        }
+
+    }
+}
diff --git a/ojluni/src/test/java/lang/Double/ParseDoubleTest.java b/ojluni/src/test/java/lang/Double/ParseDoubleTest.java
new file mode 100644
index 0000000..563f787
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/ParseDoubleTest.java
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4160406 4705734 4707389 4826774 4895911 4421494 6358355 7021568 7039369 4396272
+ * @summary Test for Double.parseDouble method and acceptance regex
+ */
+package test.java.lang.Double;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.regex.*;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+// Android-changed: remove pass/fail counting; migrate to org.testng assertions instead of throws
+public class ParseDoubleTest {
+
+    private static final BigDecimal HALF = BigDecimal.valueOf(0.5);
+
+    private static void fail(String val, double n) {
+        Assert.fail("Double.parseDouble failed. String:" + val + " Result:" + n);
+    }
+
+    private static void check(String val) {
+        double n = Double.parseDouble(val);
+        boolean isNegativeN = n < 0 || n == 0 && 1/n < 0;
+        double na = Math.abs(n);
+        String s = val.trim().toLowerCase();
+        switch (s.charAt(s.length() - 1)) {
+            case 'd':
+            case 'f':
+                s = s.substring(0, s.length() - 1);
+                break;
+        }
+        boolean isNegative = false;
+        if (s.charAt(0) == '+') {
+            s = s.substring(1);
+        } else if (s.charAt(0) == '-') {
+            s = s.substring(1);
+            isNegative = true;
+        }
+        if (s.equals("nan")) {
+            if (!Double.isNaN(n)) {
+                fail(val, n);
+            }
+            return;
+        }
+        if (Double.isNaN(n)) {
+            fail(val, n);
+        }
+        if (isNegativeN != isNegative)
+            fail(val, n);
+        if (s.equals("infinity")) {
+            if (na != Double.POSITIVE_INFINITY) {
+                fail(val, n);
+            }
+            return;
+        }
+        BigDecimal bd;
+        if (s.startsWith("0x")) {
+            s = s.substring(2);
+            int indP = s.indexOf('p');
+            long exp = Long.parseLong(s.substring(indP + 1));
+            int indD = s.indexOf('.');
+            String significand;
+            if (indD >= 0) {
+                significand = s.substring(0, indD) + s.substring(indD + 1, indP);
+                exp -= 4*(indP - indD - 1);
+            } else {
+                significand = s.substring(0, indP);
+            }
+            bd = new BigDecimal(new BigInteger(significand, 16));
+            if (exp >= 0) {
+                bd = bd.multiply(BigDecimal.valueOf(2).pow((int)exp));
+            } else {
+                bd = bd.divide(BigDecimal.valueOf(2).pow((int)-exp));
+            }
+        } else {
+            bd = new BigDecimal(s);
+        }
+        BigDecimal l, u;
+        if (Double.isInfinite(na)) {
+            l = new BigDecimal(Double.MAX_VALUE).add(new BigDecimal(Math.ulp(Double.MAX_VALUE)).multiply(HALF));
+            u = null;
+        } else {
+            l = new BigDecimal(na).subtract(new BigDecimal(Math.ulp(Math.nextUp(-na))).multiply(HALF));
+            u = new BigDecimal(na).add(new BigDecimal(Math.ulp(n)).multiply(HALF));
+        }
+        int cmpL = bd.compareTo(l);
+        int cmpU = u != null ? bd.compareTo(u) : -1;
+        if ((Double.doubleToLongBits(n) & 1) != 0) {
+            if (cmpL <= 0 || cmpU >= 0) {
+                fail(val, n);
+            }
+        } else {
+            if (cmpL < 0 || cmpU > 0) {
+                fail(val, n);
+            }
+        }
+    }
+
+    private static void check(String val, double expected) {
+        double n = Double.parseDouble(val);
+        if (n != expected)
+            fail(val, n);
+        check(val);
+    }
+
+    @Test
+    public void rudimentaryTest() {
+        check(new String(""+Double.MIN_VALUE), Double.MIN_VALUE);
+        check(new String(""+Double.MAX_VALUE), Double.MAX_VALUE);
+
+        check("10",     (double)  10.0);
+        check("10.0",   (double)  10.0);
+        check("10.01",  (double)  10.01);
+
+        check("-10",    (double) -10.0);
+        check("-10.00", (double) -10.0);
+        check("-10.01", (double) -10.01);
+    }
+
+
+    static String[] badStrings = {
+        "",
+        "+",
+        "-",
+        "+e",
+        "-e",
+        "+e170",
+        "-e170",
+
+        // Make sure intermediate white space is not deleted.
+        "1234   e10",
+        "-1234   e10",
+
+        // Control characters in the interior of a string are not legal
+        "1\u0007e1",
+        "1e\u00071",
+
+        // NaN and infinity can't have trailing type suffices or exponents
+        "NaNf",
+        "NaNF",
+        "NaNd",
+        "NaND",
+        "-NaNf",
+        "-NaNF",
+        "-NaNd",
+        "-NaND",
+        "+NaNf",
+        "+NaNF",
+        "+NaNd",
+        "+NaND",
+        "Infinityf",
+        "InfinityF",
+        "Infinityd",
+        "InfinityD",
+        "-Infinityf",
+        "-InfinityF",
+        "-Infinityd",
+        "-InfinityD",
+        "+Infinityf",
+        "+InfinityF",
+        "+Infinityd",
+        "+InfinityD",
+
+        "NaNe10",
+        "-NaNe10",
+        "+NaNe10",
+        "Infinitye10",
+        "-Infinitye10",
+        "+Infinitye10",
+
+        // Non-ASCII digits are not recognized
+        // Android-removed: non-ASCII digits tests
+        // "\u0661e\u0661", // 1e1 in Arabic-Indic digits
+        // "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits
+        // "\u0967e\u0967", // 1e1 in Devanagari digits
+
+        // JCK test lex03592m3
+        ".",
+
+        // JCK test lex03592m4
+        "e42",
+
+        // JCK test lex03592m5
+        ".e42",
+
+        // JCK test lex03592m6
+        "d",
+
+        // JCK test lex03592m7
+        ".d",
+
+        // JCK test lex03592m8
+        "e42d",
+
+        // JCK test lex03592m9
+        ".e42d",
+
+        // JCK test lex03593m10
+        "1A01.01125e-10d",
+
+        // JCK test lex03593m11
+        "2;3.01125e-10d",
+
+        // JCK test lex03593m12
+        "1_34.01125e-10d",
+
+        // JCK test lex03593m14
+        "202..01125e-10d",
+
+        // JCK test lex03593m15
+        "202,01125e-10d",
+
+        // JCK test lex03593m16
+        "202.03b4e-10d",
+
+        // JCK test lex03593m18
+        "202.06_3e-10d",
+
+        // JCK test lex03593m20
+        "202.01125e-f0d",
+
+        // JCK test lex03593m21
+        "202.01125e_3d",
+
+        // JCK test lex03593m22
+        "202.01125e -5d",
+
+        // JCK test lex03593m24
+        "202.01125e-10r",
+
+        // JCK test lex03593m25
+        "202.01125e-10ff",
+
+        // JCK test lex03593m26
+        "1234L.01",
+
+        // JCK test lex03593m27
+        "12ee-2",
+
+        // JCK test lex03593m28
+        "12e-2.2.2",
+
+        // JCK test lex03593m29
+        "12.01e+",
+
+        // JCK test lex03593m30
+        "12.01E",
+
+        // Bad hexadecimal-style strings
+
+        // Two leading zeros
+        "00x1.0p1",
+
+        // Must have hex specifier
+        "1.0p1",
+        "00010p1",
+        "deadbeefp1",
+
+        // Need an explicit fully-formed exponent
+        "0x1.0p",
+        "0x1.0",
+
+        // Exponent must be in decimal
+        "0x1.0pa",
+        "0x1.0pf",
+
+        // Exponent separated by "p"
+        "0x1.0e22",
+        "0x1.0e22",
+
+        // Need a signifcand
+        "0xp22"
+    };
+
+    static String[] goodStrings = {
+        "NaN",
+        "+NaN",
+        "-NaN",
+        "Infinity",
+        "+Infinity",
+        "-Infinity",
+        "1.1e-23f",
+        ".1e-23f",
+        "1e-23",
+        "1f",
+        "0",
+        "-0",
+        "+0",
+        "00",
+        "00",
+        "-00",
+        "+00",
+        "0000000000",
+        "-0000000000",
+        "+0000000000",
+        "1",
+        "2",
+        "1234",
+        "-1234",
+        "+1234",
+        "2147483647",   // Integer.MAX_VALUE
+        "2147483648",
+        "-2147483648",  // Integer.MIN_VALUE
+        "-2147483649",
+
+        "16777215",
+        "16777216",     // 2^24
+        "16777217",
+
+        "-16777215",
+        "-16777216",    // -2^24
+        "-16777217",
+
+        "9007199254740991",
+        "9007199254740992",     // 2^53
+        "9007199254740993",
+
+        "-9007199254740991",
+        "-9007199254740992",    // -2^53
+        "-9007199254740993",
+
+        "9223372036854775807",
+        "9223372036854775808",  // Long.MAX_VALUE
+        "9223372036854775809",
+
+        "-9223372036854775808",
+        "-9223372036854775809", // Long.MIN_VALUE
+        "-9223372036854775810",
+
+        // Culled from JCK test lex03591m1
+        "54.07140d",
+        "7.01e-324d",
+        "2147483647.01d",
+        "1.2147483647f",
+        "000000000000000000000000001.F",
+        "1.00000000000000000000000000e-2F",
+
+        // Culled from JCK test lex03592m2
+        "2.",
+        ".0909",
+        "122112217090.0",
+        "7090e-5",
+        "2.E-20",
+        ".0909e42",
+        "122112217090.0E+100",
+        "7090f",
+        "2.F",
+        ".0909d",
+        "122112217090.0D",
+        "7090e-5f",
+        "2.E-20F",
+        ".0909e42d",
+        "122112217090.0E+100D",
+
+        // Culled from JCK test lex03594m31 -- unicode escapes
+        "\u0035\u0031\u0034\u0039\u0032\u0033\u0036\u0037\u0038\u0030.1102E-209D",
+        "1290873\u002E12301e100",
+        "1.1E-10\u0066",
+
+        // Culled from JCK test lex03595m1
+        "0.0E-10",
+        "1E10",
+
+        // Culled from JCK test lex03691m1
+        "0.f",
+        "1f",
+        "0.F",
+        "1F",
+        "0.12d",
+        "1e-0d",
+        "12.e+1D",
+        "0e-0D",
+        "12.e+01",
+        "1e-01",
+
+        // Good hex strings
+        // Vary capitalization of separators.
+
+        "0x1p1",
+        "0X1p1",
+        "0x1P1",
+        "0X1P1",
+        "0x1p1f",
+        "0X1p1f",
+        "0x1P1f",
+        "0X1P1f",
+        "0x1p1F",
+        "0X1p1F",
+        "0x1P1F",
+        "0X1P1F",
+        "0x1p1d",
+        "0X1p1d",
+        "0x1P1d",
+        "0X1P1d",
+        "0x1p1D",
+        "0X1p1D",
+        "0x1P1D",
+        "0X1P1D",
+
+        "-0x1p1",
+        "-0X1p1",
+        "-0x1P1",
+        "-0X1P1",
+        "-0x1p1f",
+        "-0X1p1f",
+        "-0x1P1f",
+        "-0X1P1f",
+        "-0x1p1F",
+        "-0X1p1F",
+        "-0x1P1F",
+        "-0X1P1F",
+        "-0x1p1d",
+        "-0X1p1d",
+        "-0x1P1d",
+        "-0X1P1d",
+        "-0x1p1D",
+        "-0X1p1D",
+        "-0x1P1D",
+        "-0X1P1D",
+
+        "0x1p-1",
+        "0X1p-1",
+        "0x1P-1",
+        "0X1P-1",
+        "0x1p-1f",
+        "0X1p-1f",
+        "0x1P-1f",
+        "0X1P-1f",
+        "0x1p-1F",
+        "0X1p-1F",
+        "0x1P-1F",
+        "0X1P-1F",
+        "0x1p-1d",
+        "0X1p-1d",
+        "0x1P-1d",
+        "0X1P-1d",
+        "0x1p-1D",
+        "0X1p-1D",
+        "0x1P-1D",
+        "0X1P-1D",
+
+        "-0x1p-1",
+        "-0X1p-1",
+        "-0x1P-1",
+        "-0X1P-1",
+        "-0x1p-1f",
+        "-0X1p-1f",
+        "-0x1P-1f",
+        "-0X1P-1f",
+        "-0x1p-1F",
+        "-0X1p-1F",
+        "-0x1P-1F",
+        "-0X1P-1F",
+        "-0x1p-1d",
+        "-0X1p-1d",
+        "-0x1P-1d",
+        "-0X1P-1d",
+        "-0x1p-1D",
+        "-0X1p-1D",
+        "-0x1P-1D",
+        "-0X1P-1D",
+
+
+        // Try different significand combinations
+        "0xap1",
+        "0xbp1",
+        "0xcp1",
+        "0xdp1",
+        "0xep1",
+        "0xfp1",
+
+        "0x1p1",
+        "0x.1p1",
+        "0x1.1p1",
+
+        "0x001p23",
+        "0x00.1p1",
+        "0x001.1p1",
+
+        "0x100p1",
+        "0x.100p1",
+        "0x1.100p1",
+
+        "0x00100p1",
+        "0x00.100p1",
+        "0x001.100p1",
+
+        // Limits
+
+        "1.7976931348623157E308",     // Double.MAX_VALUE
+        "4.9e-324",                   // Double.MIN_VALUE
+        "2.2250738585072014e-308",    // Double.MIN_NORMAL
+
+        "2.2250738585072012e-308",    // near Double.MIN_NORMAL
+
+        "1.7976931348623158e+308",    // near MAX_VALUE + ulp(MAX_VALUE)/2
+        "1.7976931348623159e+308",    // near MAX_VALUE + ulp(MAX_VALUE)
+
+        "2.4703282292062329e-324",    // above MIN_VALUE/2
+        "2.4703282292062327e-324",    // MIN_VALUE/2
+        "2.4703282292062325e-324",    // below MIN_VALUE/2
+
+        // 1e308 with leading zeros
+
+        "0.0000000000001e321",
+        "00.000000000000000001e326",
+        "00000.000000000000000001e326",
+        "000.0000000000000000001e327",
+        "0.00000000000000000001e328",
+    };
+
+    static String[] paddedBadStrings;
+    static String[] paddedGoodStrings;
+    static {
+        String pad = " \t\n\r\f\u0001\u000b\u001f";
+        paddedBadStrings = new String[badStrings.length];
+        for(int i = 0 ; i <  badStrings.length; i++)
+            paddedBadStrings[i] = pad + badStrings[i] + pad;
+
+        paddedGoodStrings = new String[goodStrings.length];
+        for(int i = 0 ; i <  goodStrings.length; i++)
+            paddedGoodStrings[i] = pad + goodStrings[i] + pad;
+
+    }
+
+
+    /*
+     * Throws an exception if <code>Input</code> is
+     * <code>exceptionalInput</code> and {@link Double.parseDouble
+     * parseDouble} does <em>not</em> throw an exception or if
+     * <code>Input</code> is not <code>exceptionalInput</code> and
+     * <code>parseDouble</code> throws an exception.  This method does
+     * not attempt to test whether the string is converted to the
+     * proper value; just whether the input is accepted appropriately
+     * or not.
+     */
+    private static void testParsing(String [] input, boolean exceptionalInput) {
+        for(int i = 0; i < input.length; i++) {
+            double d;
+
+            try {
+                d = Double.parseDouble(input[i]);
+                check(input[i]);
+            }
+            catch (NumberFormatException e) {
+                if (! exceptionalInput) {
+                    Assert.fail("Double.parseDouble rejected good string `" + input[i] + "'.");
+                }
+                break;
+            }
+            if (exceptionalInput) {
+                Assert.fail("Double.parseDouble accepted bad string `" + input[i] + "'.");
+            }
+        }
+    }
+
+    /*
+     * Throws an exception if <code>Input</code> is
+     * <code>exceptionalInput</code> and the regular expression
+     * matches one of the strings or if <code>Input</code> is not
+     * <code>exceptionalInput</code> and the regular expression fails
+     * to match an input string.
+     */
+    private static void testRegex(String [] input, boolean exceptionalInput) {
+        /*
+         * The regex below is taken from the JavaDoc for
+         * Double.valueOf.
+         */
+
+        final String Digits     = "(\\p{Digit}+)";
+        final String HexDigits  = "(\\p{XDigit}+)";
+        // an exponent is 'e' or 'E' followed by an optionally
+        // signed decimal integer.
+        final String Exp        = "[eE][+-]?"+Digits;
+        final String fpRegex    =
+            ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
+             "[+-]?(" + // Optional sign character
+             "NaN|" +           // "NaN" string
+             "Infinity|" +      // "Infinity" string
+
+             // A floating-point string representing a finite positive
+             // number without a leading sign has at most five basic pieces:
+             // Digits . Digits ExponentPart FloatTypeSuffix
+             //
+             // Since this method allows integer-only strings as input
+             // in addition to strings of floating-point literals, the
+             // two sub-patterns below are simplifications of the grammar
+             // productions from the Java Language Specification, 2nd
+             // edition, section 3.10.2.
+
+
+             // A decimal floating-point string representing a finite positive
+             // number without a leading sign has at most five basic pieces:
+             // Digits . Digits ExponentPart FloatTypeSuffix
+             //
+             // Since this method allows integer-only strings as input
+             // in addition to strings of floating-point literals, the
+             // two sub-patterns below are simplifications of the grammar
+             // productions from the Java Language Specification, 2nd
+             // edition, section 3.10.2.
+
+             // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
+             "(((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
+
+             // . Digits ExponentPart_opt FloatTypeSuffix_opt
+             "(\\.("+Digits+")("+Exp+")?))|"+
+
+            // Hexadecimal strings
+            "((" +
+             // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
+             "(0[xX]" + HexDigits + "(\\.)?)|" +
+
+             // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
+             "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
+
+             ")[pP][+-]?" + Digits + "))" +
+             "[fFdD]?))" +
+             "[\\x00-\\x20]*");// Optional trailing "whitespace"
+        Pattern fpPattern = Pattern.compile(fpRegex);
+
+        for(int i = 0; i < input.length; i++) {
+             Matcher m = fpPattern.matcher(input[i]);
+             Assert.assertEquals(m.matches(), ! exceptionalInput, "Regular expression " +
+                                            (exceptionalInput?
+                                             "accepted bad":
+                                             "rejected good") +
+                                            " string `" +
+                                            input[i] + "'.");
+             }
+
+    }
+
+    /**
+     * For each subnormal power of two, test at boundaries of
+     * region that should convert to that value.
+     */
+    @Test
+    public void testSubnormalPowers() {
+        BigDecimal TWO = BigDecimal.valueOf(2);
+        // An ulp is the same for all subnormal values
+        BigDecimal ulp_BD = new BigDecimal(Double.MIN_VALUE);
+
+        // Test subnormal powers of two (except Double.MIN_VALUE)
+        for(int i = -1073; i <= -1022; i++) {
+            double d = Math.scalb(1.0, i);
+
+            /*
+             * The region [d - ulp/2, d + ulp/2] should round to d.
+             */
+            BigDecimal d_BD = new BigDecimal(d);
+
+            BigDecimal lowerBound = d_BD.subtract(ulp_BD.divide(TWO));
+            BigDecimal upperBound = d_BD.add(ulp_BD.divide(TWO));
+
+            double convertedLowerBound = Double.parseDouble(lowerBound.toString());
+            double convertedUpperBound = Double.parseDouble(upperBound.toString());
+            Assert.assertEquals(convertedLowerBound, d,
+                    String.format("2^%d lowerBound converts as %a %s%n", i,
+                            convertedLowerBound, lowerBound));
+            Assert.assertEquals(convertedUpperBound, d,
+                    String.format("2^%d upperBound converts as %a %s%n",
+                                  i, convertedUpperBound, upperBound));
+        }
+        /*
+         * Double.MIN_VALUE
+         * The region ]0.5*Double.MIN_VALUE, 1.5*Double.MIN_VALUE[ should round to Double.MIN_VALUE .
+         */
+        BigDecimal minValue = new BigDecimal(Double.MIN_VALUE);
+        Assert.assertEquals(Double.parseDouble(minValue.multiply(new BigDecimal(0.5)).toString()), 0.0,
+                "0.5*MIN_VALUE doesn't convert 0");
+        Assert.assertEquals(Double.parseDouble(minValue.multiply(new BigDecimal(0.50000000001)).toString()), Double.MIN_VALUE,
+                "0.50000000001*MIN_VALUE doesn't convert to MIN_VALUE");
+        Assert.assertEquals(Double.parseDouble(minValue.multiply(new BigDecimal(1.49999999999)).toString()), Double.MIN_VALUE,
+                "1.49999999999*MIN_VALUE doesn't convert to MIN_VALUE");
+        Assert.assertEquals(Double.parseDouble(minValue.multiply(new BigDecimal(1.5)).toString()), 2*Double.MIN_VALUE,
+                "1.5*MIN_VALUE doesn't convert to 2*MIN_VALUE");
+    }
+
+    /**
+     * For each power of two, test at boundaries of
+     * region that should convert to that value.
+     */
+    @Test
+    public void testPowers() {
+        for(int i = -1074; i <= +1023; i++) {
+            double d = Math.scalb(1.0, i);
+            BigDecimal d_BD = new BigDecimal(d);
+
+            BigDecimal lowerBound = d_BD.subtract(new BigDecimal(Math.ulp(Math.nextUp(-d))).multiply(HALF));
+            BigDecimal upperBound = d_BD.add(new BigDecimal(Math.ulp(d)).multiply(HALF));
+
+            check(lowerBound.toString());
+            check(upperBound.toString());
+        }
+        check(new BigDecimal(Double.MAX_VALUE).add(new BigDecimal(Math.ulp(Double.MAX_VALUE)).multiply(HALF)).toString());
+    }
+
+    @Test
+    public void testStrictness() {
+        final double expected = 0x0.0000008000000p-1022;
+//        final double expected = 0x0.0000008000001p-1022;
+        double conversion = 0.0;
+        double sum = 0.0; // Prevent conversion from being optimized away
+
+        //2^-1047 + 2^-1075 rounds to 2^-1047
+        String decimal = "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316";
+
+        for(int i = 0; i <= 12_000; i++) {
+            conversion = Double.parseDouble(decimal);
+            sum += conversion;
+        // BEGIN Android-changed: replace printf with assert
+        /*
+            if (conversion != expected) {
+                failed = true;
+                System.out.printf("Iteration %d converts as %a%n",
+                                  i, conversion);
+            }
+         */
+            Assert.assertEquals(conversion, expected,
+                    String.format("Iteration %d converts as %a%n", i, conversion));
+        }
+        /*
+        System.out.println("Sum = "  + sum);
+        if (failed)
+            throw new RuntimeException("Inconsistent conversion");
+         */
+        // END Android-changed: replace printf with assert
+    }
+
+    @Test
+    public void testParsing() {
+        testParsing(goodStrings, false);
+        testParsing(paddedGoodStrings, false);
+        testParsing(badStrings, true);
+        testParsing(paddedBadStrings, true);
+    }
+
+    @Test
+    public void testRegex() {
+        testRegex(goodStrings, false);
+        testRegex(paddedGoodStrings, false);
+        testRegex(badStrings, true);
+        testRegex(paddedBadStrings, true);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Double/ParseHexFloatingPointTest.java b/ojluni/src/test/java/lang/Double/ParseHexFloatingPointTest.java
new file mode 100644
index 0000000..0676ae7
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/ParseHexFloatingPointTest.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main ParseHexFloatingPoint
+ * @bug 4826774 8078672
+ * @summary Numerical tests for hexadecimal inputs to parse{Double, Float} (use -Dseed=X to set PRNG seed)
+ * @author Joseph D. Darcy
+ * @key randomness
+ */
+package test.java.lang.Double;
+
+import java.util.Random;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ParseHexFloatingPointTest {
+    private ParseHexFloatingPointTest(){}
+
+    public static final double infinityD = Double.POSITIVE_INFINITY;
+    public static final double NaND = Double.NaN;
+
+    static void test(String testName, String input,
+                    double result, double expected) {
+        Assert.assertEquals(Double.compare(result, expected), 0,
+            "Failure for " + testName +
+                               ": For input " + input +
+                               " expected " + expected +
+                               " got " + result + ".");
+
+    }
+
+    static void testCase(String input, double expected) {
+        // Try different combination of letter components
+        input = input.toLowerCase(java.util.Locale.US);
+
+        String [] suffices = {"", "f", "F", "d", "D"};
+        String [] signs = {"", "-", "+"};
+
+        for(int i = 0; i < 2; i++) {
+            String s1 = input;
+            if(i == 1)
+                s1 = s1.replace('x', 'X');
+
+            for(int j = 0; j < 2; j++) {
+                String s2 = s1;
+                if(j == 1)
+                    s2 = s2.replace('p', 'P');
+
+                for(int k = 0; k < 2; k++) {
+                    String s3 = s2;
+                    if(k == 1)
+                        s3 = upperCaseHex(s3);
+
+
+                    for(int m = 0; m < suffices.length; m++) {
+                        String s4 = s3 + suffices[m];
+
+                        for(int n = 0; n < signs.length; n++) {
+                            String s5 = signs[n] + s4;
+
+                            double result = Double.parseDouble(s5);
+                            test("Double.parseDouble",
+                                             s5, result, (signs[n].equals("-") ?
+                                                          -expected:
+                                                          expected));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    static String upperCaseHex(String s) {
+        return s.replace('a', 'A').replace('b', 'B').replace('c', 'C').
+                 replace('d', 'D').replace('e','E').replace('f', 'F');
+    }
+
+    /*
+     * Test easy and tricky double rounding cases.
+     */
+    @Test
+    public void testDouble() {
+
+        /*
+         * A String, double pair
+         */
+        class PairSD {
+            public String s;
+            public double d;
+            PairSD(String s, double d) {
+                this.s = s;
+                this.d = d;
+            }
+        }
+
+        // Hex strings that convert to three; test basic functionality
+        // of significand and exponent shift adjusts along with the
+        // no-op of adding leading zeros.  These cases don't exercise
+        // the rounding code.
+        String leadingZeros = "0x0000000000000000000";
+        String [] threeTests = {
+            "0x.003p12",
+            "0x.006p11",
+            "0x.00cp10",
+            "0x.018p9",
+
+            "0x.3p4",
+            "0x.6p3",
+            "0x.cp2",
+            "0x1.8p1",
+
+            "0x3p0",
+            "0x6.0p-1",
+            "0xc.0p-2",
+            "0x18.0p-3",
+
+            "0x3000000p-24",
+            "0x3.0p0",
+            "0x3.000000p0",
+        };
+        for(int i=0; i < threeTests.length; i++) {
+            String input = threeTests[i];
+            testCase(input, 3.0);
+
+            input.replaceFirst("^0x", leadingZeros);
+            testCase(input, 3.0);
+        }
+
+        long bigExponents [] = {
+            2*Double.MAX_EXPONENT,
+            2*Double.MIN_EXPONENT,
+
+            (long)Integer.MAX_VALUE-1,
+            (long)Integer.MAX_VALUE,
+            (long)Integer.MAX_VALUE+1,
+
+            (long)Integer.MIN_VALUE-1,
+            (long)Integer.MIN_VALUE,
+            (long)Integer.MIN_VALUE+1,
+
+            Long.MAX_VALUE-1,
+            Long.MAX_VALUE,
+
+            Long.MIN_VALUE+1,
+            Long.MIN_VALUE,
+        };
+
+        // Test zero significand with large exponents.
+        for(int i = 0; i < bigExponents.length; i++) {
+            testCase("0x0.0p"+Long.toString(bigExponents[i]) , 0.0);
+        }
+
+        // Test nonzero significand with large exponents.
+        for(int i = 0; i < bigExponents.length; i++) {
+            long exponent = bigExponents[i];
+            testCase("0x10000.0p"+Long.toString(exponent) ,
+                                 (exponent <0?0.0:infinityD));
+        }
+
+        // Test significands with different lengths and bit patterns.
+        {
+            long signif = 0;
+                for(int i = 1; i <= 0xe; i++) {
+                    signif = (signif <<4) | (long)i;
+                    testCase("0x"+Long.toHexString(signif)+"p0", signif);
+                }
+        }
+
+        PairSD [] testCases = {
+            new PairSD("0x0.0p0",               0.0/16.0),
+            new PairSD("0x0.1p0",               1.0/16.0),
+            new PairSD("0x0.2p0",               2.0/16.0),
+            new PairSD("0x0.3p0",               3.0/16.0),
+            new PairSD("0x0.4p0",               4.0/16.0),
+            new PairSD("0x0.5p0",               5.0/16.0),
+            new PairSD("0x0.6p0",               6.0/16.0),
+            new PairSD("0x0.7p0",               7.0/16.0),
+            new PairSD("0x0.8p0",               8.0/16.0),
+            new PairSD("0x0.9p0",               9.0/16.0),
+            new PairSD("0x0.ap0",               10.0/16.0),
+            new PairSD("0x0.bp0",               11.0/16.0),
+            new PairSD("0x0.cp0",               12.0/16.0),
+            new PairSD("0x0.dp0",               13.0/16.0),
+            new PairSD("0x0.ep0",               14.0/16.0),
+            new PairSD("0x0.fp0",               15.0/16.0),
+
+            // Half-way case between zero and MIN_VALUE rounds down to
+            // zero
+            new PairSD("0x1.0p-1075",           0.0),
+
+            // Slighly more than half-way case between zero and
+            // MIN_VALUES rounds up to zero.
+            new PairSD("0x1.1p-1075",                   Double.MIN_VALUE),
+            new PairSD("0x1.000000000001p-1075",        Double.MIN_VALUE),
+            new PairSD("0x1.000000000000001p-1075",     Double.MIN_VALUE),
+
+            // More subnormal rounding tests
+            new PairSD("0x0.fffffffffffff7fffffp-1022", Math.nextDown(Double.MIN_NORMAL)),
+            new PairSD("0x0.fffffffffffff8p-1022",      Double.MIN_NORMAL),
+            new PairSD("0x0.fffffffffffff800000001p-1022",Double.MIN_NORMAL),
+            new PairSD("0x0.fffffffffffff80000000000000001p-1022",Double.MIN_NORMAL),
+            new PairSD("0x1.0p-1022",                   Double.MIN_NORMAL),
+
+
+            // Large value and overflow rounding tests
+            new PairSD("0x1.fffffffffffffp1023",        Double.MAX_VALUE),
+            new PairSD("0x1.fffffffffffff0000000p1023", Double.MAX_VALUE),
+            new PairSD("0x1.fffffffffffff4p1023",       Double.MAX_VALUE),
+            new PairSD("0x1.fffffffffffff7fffffp1023",  Double.MAX_VALUE),
+            new PairSD("0x1.fffffffffffff8p1023",       infinityD),
+            new PairSD("0x1.fffffffffffff8000001p1023", infinityD),
+
+            new PairSD("0x1.ffffffffffffep1023",        Math.nextDown(Double.MAX_VALUE)),
+            new PairSD("0x1.ffffffffffffe0000p1023",    Math.nextDown(Double.MAX_VALUE)),
+            new PairSD("0x1.ffffffffffffe8p1023",       Math.nextDown(Double.MAX_VALUE)),
+            new PairSD("0x1.ffffffffffffe7p1023",       Math.nextDown(Double.MAX_VALUE)),
+            new PairSD("0x1.ffffffffffffeffffffp1023",  Double.MAX_VALUE),
+            new PairSD("0x1.ffffffffffffe8000001p1023", Double.MAX_VALUE),
+        };
+
+        for (int i = 0; i < testCases.length; i++) {
+            testCase(testCases[i].s,testCases[i].d);
+        }
+    }
+
+    @Test
+    public void testRandomDoubles() {
+        java.util.Random rand = new Random();
+        // Consistency check; double => hexadecimal => double
+        // preserves the original value.
+        for(int i = 0; i < 1000; i++) {
+            double d = rand.nextDouble();
+            testCase(Double.toHexString(d), d);
+        }
+    }
+
+    /*
+     * Verify rounding works the same regardless of how the
+     * significand is aligned on input.  A useful extension could be
+     * to have this sort of test for strings near the overflow
+     * threshold.
+     */
+    @Test
+    public static void significandAlignmentTests() {
+        // baseSignif * 2^baseExp = nextDown(2.0)
+        long [] baseSignifs = {
+            0x1ffffffffffffe00L,
+            0x1fffffffffffff00L
+        };
+
+        double [] answers = {
+            Math.nextDown(Math.nextDown(2.0)),
+            Math.nextDown(2.0),
+            2.0
+        };
+
+        int baseExp = -60;
+        int count = 0;
+        for(int i = 0; i < 2; i++) {
+            for(long j = 0; j <= 0xfL; j++) {
+                for(long k = 0; k <= 8; k+= 4) { // k = {0, 4, 8}
+                    long base = baseSignifs[i];
+                    long testValue = base | (j<<4) | k;
+
+                    int offset = 0;
+                    // Calculate when significand should be incremented
+                    // see table 4.7 in Koren book
+
+                    if ((base & 0x100L) == 0L ) { // lsb is 0
+                        if ( (j >= 8L) &&         // round is 1
+                             ((j & 0x7L) != 0 || k != 0 ) ) // sticky is 1
+                            offset = 1;
+                    }
+                    else {                        // lsb is 1
+                        if (j >= 8L)              // round is 1
+                            offset = 1;
+                    }
+
+                    double expected = answers[i+offset];
+
+                    for(int m = -2; m <= 3; m++) {
+                        count ++;
+
+                        // Form equal value string and evaluate it
+                        String s = "0x" +
+                            Long.toHexString((m >=0) ?(testValue<<m):(testValue>>(-m))) +
+                            "p" + (baseExp - m);
+
+                        testCase(s, expected);
+                    }
+                }
+            }
+        }
+    }
+
+
+    /*
+     * Test tricky float rounding cases.  The code which
+     * reads in a hex string converts the string to a double value.
+     * If a float value is needed, the double value is cast to float.
+     * However, the cast be itself not always guaranteed to return the
+     * right result since:
+     *
+     * 1. hex string => double can discard a sticky bit which would
+     * influence a direct hex string => float conversion.
+     *
+     * 2. hex string => double => float can have a rounding to double
+     * precision which results in a larger float value while a direct
+     * hex string => float conversion would not round up.
+     *
+     * This method includes tests of the latter two possibilities.
+     */
+    @Test
+    public void testFloat() {
+        /*
+         * A String, float pair
+         */
+        class PairSD {
+            public String s;
+            public float f;
+            PairSD(String s, float f) {
+                this.s = s;
+                this.f = f;
+            }
+        }
+
+        String [][] roundingTestCases = {
+            // Target float value       hard rounding version
+
+            {"0x1.000000p0",    "0x1.0000000000001p0"},
+
+            // Try some values that should round up to nextUp(1.0f)
+            {"0x1.000002p0",    "0x1.0000010000001p0"},
+            {"0x1.000002p0",    "0x1.00000100000008p0"},
+            {"0x1.000002p0",    "0x1.0000010000000fp0"},
+            {"0x1.000002p0",    "0x1.00000100000001p0"},
+            {"0x1.000002p0",    "0x1.00000100000000000000000000000000000000001p0"},
+            {"0x1.000002p0",    "0x1.0000010000000fp0"},
+
+            // Potential double rounding cases
+            {"0x1.000002p0",    "0x1.000002fffffffp0"},
+            {"0x1.000002p0",    "0x1.000002fffffff8p0"},
+            {"0x1.000002p0",    "0x1.000002ffffffffp0"},
+
+            {"0x1.000002p0",    "0x1.000002ffff0ffp0"},
+            {"0x1.000002p0",    "0x1.000002ffff0ff8p0"},
+            {"0x1.000002p0",    "0x1.000002ffff0fffp0"},
+
+
+            {"0x1.000000p0",    "0x1.000000fffffffp0"},
+            {"0x1.000000p0",    "0x1.000000fffffff8p0"},
+            {"0x1.000000p0",    "0x1.000000ffffffffp0"},
+
+            {"0x1.000000p0",    "0x1.000000ffffffep0"},
+            {"0x1.000000p0",    "0x1.000000ffffffe8p0"},
+            {"0x1.000000p0",    "0x1.000000ffffffefp0"},
+
+            // Float subnormal cases
+            {"0x0.000002p-126", "0x0.0000010000001p-126"},
+            {"0x0.000002p-126", "0x0.00000100000000000001p-126"},
+
+            {"0x0.000006p-126", "0x0.0000050000001p-126"},
+            {"0x0.000006p-126", "0x0.00000500000000000001p-126"},
+
+            {"0x0.0p-149",      "0x0.7ffffffffffffffp-149"},
+            {"0x1.0p-148",      "0x1.3ffffffffffffffp-148"},
+            {"0x1.cp-147",      "0x1.bffffffffffffffp-147"},
+
+            {"0x1.fffffcp-127", "0x1.fffffdffffffffp-127"},
+        };
+
+        String [] signs = {"", "-"};
+
+        for(int i = 0; i < roundingTestCases.length; i++) {
+            for(int j = 0; j < signs.length; j++) {
+                String expectedIn = signs[j]+roundingTestCases[i][0];
+                String resultIn   = signs[j]+roundingTestCases[i][1];
+
+                float expected =  Float.parseFloat(expectedIn);
+                float result   =  Float.parseFloat(resultIn);
+
+                Assert.assertEquals(Float.compare(expected, result), 0,
+                    "Expected = " + Float.toHexString(expected) +
+                    "Rounded  = " + Float.toHexString(result) +
+                     "Double   = " + Double.toHexString(Double.parseDouble(resultIn)) +
+                    "Input    = " + resultIn);
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Double/ToHexStringTest.java b/ojluni/src/test/java/lang/Double/ToHexStringTest.java
new file mode 100644
index 0000000..9893f1f
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/ToHexStringTest.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4826774 4926547
+ * @summary Tests for {Float, Double}.toHexString methods
+ * @library ../Math
+ * @build DoubleConsts
+ * @run main ToHexString
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Double;
+
+import java.util.regex.*;
+
+import jdk.internal.math.DoubleConsts;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ToHexStringTest {
+    private ToHexStringTest() {}
+
+    /*
+     * Given a double value, create a hexadecimal floating-point
+     * string via an intermediate long hex string.
+     */
+    static String doubleToHexString(double d) {
+        return hexLongStringtoHexDoubleString(Long.toHexString(Double.doubleToLongBits(d)));
+    }
+
+    /*
+     * Transform the hexadecimal long output into the equivalent
+     * hexadecimal double value.
+     */
+    static String hexLongStringtoHexDoubleString(String transString) {
+        transString = transString.toLowerCase();
+
+        String zeros = "";
+        StringBuffer result = new StringBuffer(24);
+
+        for(int i = 0; i < (16 - transString.length()); i++, zeros += "0");
+        transString = zeros + transString;
+
+        // assert transString.length == 16;
+
+            char topChar;
+            // Extract sign
+            if((topChar=transString.charAt(0)) >= '8' ) {// 8, 9, a, A, b, B, ...
+                result.append("-");
+                // clear sign bit
+                transString =
+                    Character.toString(Character.forDigit(Character.digit(topChar, 16) - 8, 16)) +
+                    transString.substring(1,16);
+            }
+
+            // check for NaN and infinity
+            String signifString = transString.substring(3,16);
+
+            if( transString.substring(0,3).equals("7ff") ) {
+                if(signifString.equals("0000000000000")) {
+                    result.append("Infinity");
+                }
+                else
+                    result.append("NaN");
+            }
+            else { // finite value
+                // Extract exponent
+                int exponent = Integer.parseInt(transString.substring(0,3), 16) -
+                    DoubleConsts.EXP_BIAS;
+                result.append("0x");
+
+                if (exponent == Double.MIN_EXPONENT - 1) { // zero or subnormal
+                    if(signifString.equals("0000000000000")) {
+                        result.append("0.0p0");
+                    }
+                    else {
+                        result.append("0." + signifString.replaceFirst("0+$", "").replaceFirst("^$", "0") +
+                                      "p-1022");
+                    }
+                }
+                else {  // normal value
+                    result.append("1." + signifString.replaceFirst("0+$", "").replaceFirst("^$", "0") +
+                                  "p" + exponent);
+                }
+            }
+            return result.toString();
+    }
+
+    @Test
+    public void testToHexString() {
+        String [][] testCases1 = {
+            {"Infinity",                "Infinity"},
+            {"-Infinity",               "-Infinity"},
+            {"NaN",                     "NaN"},
+            {"-NaN",                    "NaN"},
+            {"0.0",                     "0x0.0p0"},
+            {"-0.0",                    "-0x0.0p0"},
+            {"1.0",                     "0x1.0p0"},
+            {"-1.0",                    "-0x1.0p0"},
+            {"2.0",                     "0x1.0p1"},
+            {"3.0",                     "0x1.8p1"},
+            {"0.5",                     "0x1.0p-1"},
+            {"0.25",                    "0x1.0p-2"},
+            {"1.7976931348623157e+308", "0x1.fffffffffffffp1023"},      // MAX_VALUE
+            {"2.2250738585072014E-308", "0x1.0p-1022"},                 // MIN_NORMAL
+            {"2.225073858507201E-308",  "0x0.fffffffffffffp-1022"},     // MAX_SUBNORMAL
+            {"4.9e-324",                "0x0.0000000000001p-1022"}      // MIN_VALUE
+        };
+
+        // Compare decimal string -> double -> hex string to hex string
+        for (int i = 0; i < testCases1.length; i++) {
+            String result = Double.toHexString(Double.parseDouble(testCases1[i][0]));
+            Assert.assertEquals(result, testCases1[i][1],
+                "For floating-point string " + testCases1[i][0] +
+                                   ", expected hex output " + testCases1[i][1] + ", got " + result +".");
+        }
+
+
+        // Except for float subnormals, the output for numerically
+        // equal float and double values should be the same.
+        // Therefore, we will explicitly test float subnormal values.
+        String [][] floatTestCases = {
+            {"Infinity",                "Infinity"},
+            {"-Infinity",               "-Infinity"},
+            {"NaN",                     "NaN"},
+            {"-NaN",                    "NaN"},
+            {"0.0",                     "0x0.0p0"},
+            {"-0.0",                    "-0x0.0p0"},
+            {"1.0",                     "0x1.0p0"},
+            {"-1.0",                    "-0x1.0p0"},
+            {"2.0",                     "0x1.0p1"},
+            {"3.0",                     "0x1.8p1"},
+            {"0.5",                     "0x1.0p-1"},
+            {"0.25",                    "0x1.0p-2"},
+            {"3.4028235e+38f",          "0x1.fffffep127"},      // MAX_VALUE
+            {"1.17549435E-38f",         "0x1.0p-126"},          // MIN_NORMAL
+            {"1.1754942E-38",           "0x0.fffffep-126"},     // MAX_SUBNORMAL
+            {"1.4e-45f",                "0x0.000002p-126"}      // MIN_VALUE
+        };
+        // Compare decimal string -> double -> hex string to hex string
+        for (int i = 0; i < floatTestCases.length; i++) {
+            String result = Float.toHexString(Float.parseFloat(floatTestCases[i][0]));
+            Assert.assertEquals(result, floatTestCases[i][1],
+                "For floating-point string " + floatTestCases[i][0] +
+                          ", expected hex output\n" + floatTestCases[i][1] + ", got\n" + result +".");
+        }
+
+        // Particular floating-point values and hex equivalents, mostly
+        // taken from fdlibm source.
+        String [][] testCases2 = {
+            {"+0.0",                                    "0000000000000000"},
+            {"-0.0",                                    "8000000000000000"},
+            {"+4.9e-324",                               "0000000000000001"},
+            {"-4.9e-324",                               "8000000000000001"},
+
+            // fdlibm k_sin.c
+            {"+5.00000000000000000000e-01",             "3FE0000000000000"},
+            {"-1.66666666666666324348e-01",             "BFC5555555555549"},
+            {"+8.33333333332248946124e-03",             "3F8111111110F8A6"},
+            {"-1.98412698298579493134e-04",             "BF2A01A019C161D5"},
+            {"+2.75573137070700676789e-06",             "3EC71DE357B1FE7D"},
+            {"-2.50507602534068634195e-08",             "BE5AE5E68A2B9CEB"},
+            {"+1.58969099521155010221e-10",             "3DE5D93A5ACFD57C"},
+
+            // fdlibm k_cos.c
+            {"+4.16666666666666019037e-02",             "3FA555555555554C"},
+            {"-1.38888888888741095749e-03",             "BF56C16C16C15177"},
+            {"+2.48015872894767294178e-05",             "3EFA01A019CB1590"},
+            {"-2.75573143513906633035e-07",             "BE927E4F809C52AD"},
+            {"+2.08757232129817482790e-09",             "3E21EE9EBDB4B1C4"},
+            {"-1.13596475577881948265e-11",             "BDA8FAE9BE8838D4"},
+
+            // fdlibm e_rempio.c
+            {"1.67772160000000000000e+07",              "4170000000000000"},
+            {"6.36619772367581382433e-01",              "3FE45F306DC9C883"},
+            {"1.57079632673412561417e+00",              "3FF921FB54400000"},
+            {"6.07710050650619224932e-11",              "3DD0B4611A626331"},
+            {"6.07710050630396597660e-11",              "3DD0B4611A600000"},
+            {"2.02226624879595063154e-21",              "3BA3198A2E037073"},
+            {"2.02226624871116645580e-21",              "3BA3198A2E000000"},
+            {"8.47842766036889956997e-32",              "397B839A252049C1"},
+
+
+            // fdlibm s_cbrt.c
+            {"+5.42857142857142815906e-01",             "3FE15F15F15F15F1"},
+            {"-7.05306122448979611050e-01",             "BFE691DE2532C834"},
+            {"+1.41428571428571436819e+00",             "3FF6A0EA0EA0EA0F"},
+            {"+1.60714285714285720630e+00",             "3FF9B6DB6DB6DB6E"},
+            {"+3.57142857142857150787e-01",             "3FD6DB6DB6DB6DB7"},
+        };
+
+        // Compare decimal string -> double -> hex string to
+        // long hex string -> double hex string
+        for (int i = 0; i < testCases2.length; i++) {
+            String result = Double.toHexString(Double.parseDouble(testCases2[i][0]));
+            String expected = hexLongStringtoHexDoubleString(testCases2[i][1]);
+            Assert.assertEquals(result, expected,
+                "For floating-point string " + testCases2[i][0] +
+                          ", expected hex output " + expected + ", got " + result +".");
+        }
+    }
+
+    @Test
+    public void testRandomDoubles() {
+        // Test random double values;
+        // compare double -> Double.toHexString with local doubleToHexString
+        java.util.Random rand = new java.util.Random(0);
+        for (int i = 0; i < 1000; i++) {
+            double d = rand.nextDouble();
+            String result = Double.toHexString(d);
+            String expected = doubleToHexString(d);
+            Assert.assertEquals(result, expected, "For floating-point value " + d +
+                    ", expected hex output " + expected + ", got " + result +".");
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Double/ToStringTest.java b/ojluni/src/test/java/lang/Double/ToStringTest.java
new file mode 100644
index 0000000..773255b
--- /dev/null
+++ b/ojluni/src/test/java/lang/Double/ToStringTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4428022
+ * @summary Tests for Double.toString
+ * @author Andrew Haley <aph@redhat.com>
+ */
+package test.java.lang.Double;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ToStringTest {
+
+    @Test
+    public void testToString() {
+        Assert.assertEquals(Double.toString(0.001), "0.001");
+        Assert.assertEquals(Double.toString(0.002), "0.002");
+    }
+}
diff --git a/ojluni/src/test/java/lang/Float/BitwiseConversionTest.java b/ojluni/src/test/java/lang/Float/BitwiseConversionTest.java
new file mode 100644
index 0000000..bba9de4
--- /dev/null
+++ b/ojluni/src/test/java/lang/Float/BitwiseConversionTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5037596
+ * @summary Verify bitwise conversion works for non-canonical NaN values
+ * @library ../Math
+ * @build FloatConsts
+ * @run main BitwiseConversion
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Float;
+
+import static java.lang.Float.*;
+
+import jdk.internal.math.FloatConsts;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class BitwiseConversionTest {
+    static void testNanCase(int x) {
+        // Strip out sign and exponent bits
+        int y = x & FloatConsts.SIGNIF_BIT_MASK;
+
+        float[] values = {
+            intBitsToFloat(FloatConsts.EXP_BIT_MASK | y),
+            intBitsToFloat(FloatConsts.SIGN_BIT_MASK | FloatConsts.EXP_BIT_MASK | y)
+        };
+
+        for(float value: values) {
+            Assert.assertTrue(isNaN(value), "Invalid input " + y + "yielded non-NaN" + value);
+
+            int converted = floatToIntBits(value);
+            Assert.assertEquals(converted, 0x7fc00000,
+                String.format("Non-canonical NaN bits returned: %x%n", converted));
+        }
+    }
+
+    @Test
+    public void testNanCases() {
+        for (int i = 0; i < FloatConsts.SIGNIFICAND_WIDTH - 1; i++) {
+            testNanCase(1 << i);
+        }
+    }
+
+    @Test
+    public void testFloatToIntBits() {
+        Assert.assertEquals (floatToIntBits(Float.POSITIVE_INFINITY), 0x7F800000,
+            "Bad conversion for +infinity.");
+
+        Assert.assertEquals(floatToIntBits(Float.NEGATIVE_INFINITY), 0xFF800000,
+            "Bad conversion for -infinity.");
+    }
+}
diff --git a/ojluni/src/test/java/lang/Float/ConstantsTest.java b/ojluni/src/test/java/lang/Float/ConstantsTest.java
new file mode 100644
index 0000000..033cfdd
--- /dev/null
+++ b/ojluni/src/test/java/lang/Float/ConstantsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @compile Constants.java
+ * @bug 4397405 4826652
+ * @summary Testing constant-ness of Float.{MIN_VALUE, MAX_VALUE}, etc.
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Float;
+
+public class ConstantsTest {
+    /*
+     * This compile-only test is to make sure that the primitive
+     * public static final fields in java.lang.Float are "constant
+     * expressions" as defined by "The Java Language Specification,
+     * 2nd edition" section 15.28; a different test checks the values
+     * of those fields.
+     */
+    public void testPublicStaticFinalFields_areConstantExpressions() throws Exception {
+        int i = 0;
+        switch (i) {
+        case (int)Float.NaN:                    // 0
+            System.out.println("Float.NaN is a constant!");
+            break;
+        case (int)Float.MIN_VALUE + 1:          // 0 + 1
+            System.out.println("Float.MIN_VALUE is a constant!");
+            break;
+        case (int)Float.MIN_NORMAL + 2:         // 0 + 2
+            System.out.println("Float.MIN_NORMAL is a constant!");
+            break;
+        case Float.MIN_EXPONENT:                // -126
+            System.out.println("Float.MIN_EXPONENT is a constant!");
+            break;
+        case Float.MAX_EXPONENT:                // 127
+            System.out.println("Float.MAX_EXPONENT is a constant!");
+            break;
+        case (int)Float.MAX_VALUE - 1:          // Integer.MAX_VALUE - 1
+            System.out.println("Float.MAX_VALUE is a constant!");
+            break;
+        case (int)Float.POSITIVE_INFINITY:      // Integer.MAX_VALUE
+            System.out.println("Float.POSITIVE_INFINITY is a constant!");
+            break;
+        case (int)Float.NEGATIVE_INFINITY:      // Integer.MIN_VALUE
+            System.out.println("Float.NEGATIVE_INFINITY is a constant!");
+            break;
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Float/ExtremaTest.java b/ojluni/src/test/java/lang/Float/ExtremaTest.java
new file mode 100644
index 0000000..a216384
--- /dev/null
+++ b/ojluni/src/test/java/lang/Float/ExtremaTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4408489 4826652
+ * @summary Testing values of Float.{MIN_VALUE, MIN_NORMAL, MAX_VALUE}
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Float;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ExtremaTest {
+    @Test
+    public void testExtremalValues() throws Exception {
+        Assert.assertEquals(Float.intBitsToFloat(0x1), Float.MIN_VALUE,
+            "Float.MIN_VALUE is not equal to intBitsToFloat(0x1).");
+
+        Assert.assertEquals(Float.intBitsToFloat(0x00800000), Float.MIN_NORMAL,
+            "Float.MIN_NORMAL is not equal to intBitsToFloat(0x00800000).");
+
+        Assert.assertEquals(Float.intBitsToFloat(0x7f7fffff), Float.MAX_VALUE,
+            "Float.MAX_VALUE is not equal to intBitsToFloat(0x7f7fffff).");
+    }
+}
diff --git a/ojluni/src/test/java/lang/Float/NaNInfinityParsingTest.java b/ojluni/src/test/java/lang/Float/NaNInfinityParsingTest.java
new file mode 100644
index 0000000..de1a5fe
--- /dev/null
+++ b/ojluni/src/test/java/lang/Float/NaNInfinityParsingTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4428772
+ * @summary Testing recognition of "NaN" and "Infinity" strings
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Float;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class NaNInfinityParsingTest {
+    /*
+     * Regression tests for:
+     * 4428772 -- Establish invariant for Float & Double classes and
+     * their string representations
+     *
+     * Added capability for parse{Float, Double} and related methods
+     * to recognize "NaN" and "Infinity" strings so that
+     * parseFloat(toString(d)) will always return the original
+     * floating-point value.
+     */
+
+    static String NaNStrings[] = {
+        "NaN",
+        "+NaN",
+        "-NaN"
+    };
+
+    static String infinityStrings[] = {
+        "Infinity",
+        "+Infinity",
+        "-Infinity",
+    };
+
+    static String invalidStrings[] = {
+        "+",
+        "-",
+        "@",
+        "N",
+        "Na",
+        "Nan",
+        "NaNf",
+        "NaNd",
+        "NaNF",
+        "NaND",
+        "+N",
+        "+Na",
+        "+Nan",
+        "+NaNf",
+        "+NaNd",
+        "+NaNF",
+        "+NaND",
+        "-N",
+        "-Na",
+        "-Nan",
+        "-NaNf",
+        "-NaNd",
+        "-NaNF",
+        "-NaND",
+        "I",
+        "In",
+        "Inf",
+        "Infi",
+        "Infin",
+        "Infini",
+        "Infinit",
+        "InfinitY",
+        "Infinityf",
+        "InfinityF",
+        "Infinityd",
+        "InfinityD",
+        "+I",
+        "+In",
+        "+Inf",
+        "+Infi",
+        "+Infin",
+        "+Infini",
+        "+Infinit",
+        "+InfinitY",
+        "+Infinityf",
+        "+InfinityF",
+        "+Infinityd",
+        "+InfinityD",
+        "-I",
+        "-In",
+        "-Inf",
+        "-Infi",
+        "-Infin",
+        "-Infini",
+        "-Infinit",
+        "-InfinitY",
+        "-Infinityf",
+        "-InfinityF",
+        "-Infinityd",
+        "-InfinityD",
+        "NaNInfinity",
+        "InfinityNaN",
+        "nan",
+        "infinity"
+    };
+
+    public static void main(String [] argv) throws Exception {
+        int i;
+        float d;
+    }
+
+    @Test
+    public void testValidNaNStrings() {
+        for (String naNString : NaNStrings) {
+            float d = Float.parseFloat(naNString);
+            Assert.assertTrue(Float.isNaN(d), "NaN string ``" + naNString
+                    + "'' did not parse as a NaN; returned " +
+                    d + " instead.");
+        }
+    }
+
+    @Test
+    public void testValidInfinityStrings() {
+        for (String infinityString : infinityStrings) {
+            float d = Float.parseFloat(infinityString);
+            Assert.assertTrue(Float.isInfinite(d), "Infinity string ``" +
+                infinityString +
+                "'' did not parse as infinity; returned " +
+                d + "instead.");
+            // check sign of result
+
+            boolean negative = (infinityString.charAt(0) == '-');
+            Assert.assertEquals(d, (negative ? Float.NEGATIVE_INFINITY :
+                Float.POSITIVE_INFINITY), "Infinity has wrong sign;" +
+                    (negative ? "positive instead of negative." :
+                        "negative instead of positive."));
+        }
+    }
+
+    @Test
+    public void testAlmostValidStrings() {
+        for (String invalidString : invalidStrings) {
+            try {
+                float d = Float.parseFloat(invalidString);
+                Assert.fail("Invalid string ``" + invalidString + "'' parsed as " + d + ".");
+            } catch (NumberFormatException e) {
+                // expected
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Float/ParseFloatTest.java b/ojluni/src/test/java/lang/Float/ParseFloatTest.java
new file mode 100644
index 0000000..24f2448
--- /dev/null
+++ b/ojluni/src/test/java/lang/Float/ParseFloatTest.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4160406 4705734 4707389 6358355 7032154
+ * @summary Tests for Float.parseFloat method
+ */
+package test.java.lang.Float;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ParseFloatTest {
+
+    private static final BigDecimal HALF = BigDecimal.valueOf(0.5);
+
+    private static void fail(String val, float n) {
+        Assert.fail("Float.parseFloat failed. String:" + val + " Result:" + n);
+    }
+
+    private static void check(String val) {
+        float n = Float.parseFloat(val);
+        boolean isNegativeN = n < 0 || n == 0 && 1/n < 0;
+        float na = Math.abs(n);
+        String s = val.trim().toLowerCase();
+        switch (s.charAt(s.length() - 1)) {
+            case 'd':
+            case 'f':
+                s = s.substring(0, s.length() - 1);
+                break;
+        }
+        boolean isNegative = false;
+        if (s.charAt(0) == '+') {
+            s = s.substring(1);
+        } else if (s.charAt(0) == '-') {
+            s = s.substring(1);
+            isNegative = true;
+        }
+        if (s.equals("nan")) {
+            if (!Float.isNaN(n)) {
+                fail(val, n);
+            }
+            return;
+        }
+        if (Float.isNaN(n)) {
+            fail(val, n);
+        }
+        if (isNegativeN != isNegative)
+            fail(val, n);
+        if (s.equals("infinity")) {
+            if (na != Float.POSITIVE_INFINITY) {
+                fail(val, n);
+            }
+            return;
+        }
+        BigDecimal bd;
+        if (s.startsWith("0x")) {
+            s = s.substring(2);
+            int indP = s.indexOf('p');
+            long exp = Long.parseLong(s.substring(indP + 1));
+            int indD = s.indexOf('.');
+            String significand;
+            if (indD >= 0) {
+                significand = s.substring(0, indD) + s.substring(indD + 1, indP);
+                exp -= 4*(indP - indD - 1);
+            } else {
+                significand = s.substring(0, indP);
+            }
+            bd = new BigDecimal(new BigInteger(significand, 16));
+            if (exp >= 0) {
+                bd = bd.multiply(BigDecimal.valueOf(2).pow((int)exp));
+            } else {
+                bd = bd.divide(BigDecimal.valueOf(2).pow((int)-exp));
+            }
+        } else {
+            bd = new BigDecimal(s);
+        }
+        BigDecimal l, u;
+        if (Float.isInfinite(na)) {
+            l = new BigDecimal(Float.MAX_VALUE).add(new BigDecimal(Math.ulp(Float.MAX_VALUE)).multiply(HALF));
+            u = null;
+        } else {
+            l = new BigDecimal(na).subtract(new BigDecimal(Math.ulp(-Math.nextUp(-na))).multiply(HALF));
+            u = new BigDecimal(na).add(new BigDecimal(Math.ulp(n)).multiply(HALF));
+        }
+        int cmpL = bd.compareTo(l);
+        int cmpU = u != null ? bd.compareTo(u) : -1;
+        if ((Float.floatToIntBits(n) & 1) != 0) {
+            if (cmpL <= 0 || cmpU >= 0) {
+                fail(val, n);
+            }
+        } else {
+            if (cmpL < 0 || cmpU > 0) {
+                fail(val, n);
+            }
+        }
+    }
+
+    private static void check(String val, float expected) {
+        float n = Float.parseFloat(val);
+        if (n != expected)
+            fail(val, n);
+        check(val);
+    }
+
+    @Test
+    public void rudimentaryTest() {
+        check(new String(""+Float.MIN_VALUE), Float.MIN_VALUE);
+        check(new String(""+Float.MAX_VALUE), Float.MAX_VALUE);
+
+        check("10",     (float)  10.0);
+        check("10.0",   (float)  10.0);
+        check("10.01",  (float)  10.01);
+
+        check("-10",    (float) -10.0);
+        check("-10.00", (float) -10.0);
+        check("-10.01", (float) -10.01);
+
+        // bug 6358355
+        check("144115196665790480", 0x1.000002p57f);
+        check("144115196665790481", 0x1.000002p57f);
+        check("0.050000002607703203", 0.05f);
+        check("0.050000002607703204", 0.05f);
+        check("0.050000002607703205", 0.05f);
+        check("0.050000002607703206", 0.05f);
+        check("0.050000002607703207", 0.05f);
+        check("0.050000002607703208", 0.05f);
+        check("0.050000002607703209", 0.050000004f);
+    }
+
+    static String[] badStrings = {
+        "",
+        "+",
+        "-",
+        "+e",
+        "-e",
+        "+e170",
+        "-e170",
+
+        // Make sure intermediate white space is not deleted.
+        "1234   e10",
+        "-1234   e10",
+
+        // Control characters in the interior of a string are not legal
+        "1\u0007e1",
+        "1e\u00071",
+
+        // NaN and infinity can't have trailing type suffices or exponents
+        "NaNf",
+        "NaNF",
+        "NaNd",
+        "NaND",
+        "-NaNf",
+        "-NaNF",
+        "-NaNd",
+        "-NaND",
+        "+NaNf",
+        "+NaNF",
+        "+NaNd",
+        "+NaND",
+        "Infinityf",
+        "InfinityF",
+        "Infinityd",
+        "InfinityD",
+        "-Infinityf",
+        "-InfinityF",
+        "-Infinityd",
+        "-InfinityD",
+        "+Infinityf",
+        "+InfinityF",
+        "+Infinityd",
+        "+InfinityD",
+
+        "NaNe10",
+        "-NaNe10",
+        "+NaNe10",
+        "Infinitye10",
+        "-Infinitye10",
+        "+Infinitye10",
+
+        // Non-ASCII digits are not recognized
+        "\u0661e\u0661", // 1e1 in Arabic-Indic digits
+        "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits
+        "\u0967e\u0967" // 1e1 in Devanagari digits
+    };
+
+    static String[] goodStrings = {
+        "NaN",
+        "+NaN",
+        "-NaN",
+        "Infinity",
+        "+Infinity",
+        "-Infinity",
+        "1.1e-23f",
+        ".1e-23f",
+        "1e-23",
+        "1f",
+        "1",
+        "2",
+        "1234",
+        "-1234",
+        "+1234",
+        "2147483647",   // Integer.MAX_VALUE
+        "2147483648",
+        "-2147483648",  // Integer.MIN_VALUE
+        "-2147483649",
+
+        "16777215",
+        "16777216",     // 2^24
+        "16777217",
+
+        "-16777215",
+        "-16777216",    // -2^24
+        "-16777217",
+
+        "9007199254740991",
+        "9007199254740992",     // 2^53
+        "9007199254740993",
+
+        "-9007199254740991",
+        "-9007199254740992",    // -2^53
+        "-9007199254740993",
+
+        "9223372036854775807",
+        "9223372036854775808",  // Long.MAX_VALUE
+        "9223372036854775809",
+
+        "-9223372036854775808",
+        "-9223372036854775809", // Long.MIN_VALUE
+        "-9223372036854775810"
+    };
+
+    static String[] paddedBadStrings;
+    static String[] paddedGoodStrings;
+    static {
+        String pad = " \t\n\r\f\u0001\u000b\u001f";
+        paddedBadStrings = new String[badStrings.length];
+        for(int i = 0 ; i <  badStrings.length; i++)
+            paddedBadStrings[i] = pad + badStrings[i] + pad;
+
+        paddedGoodStrings = new String[goodStrings.length];
+        for(int i = 0 ; i <  goodStrings.length; i++)
+            paddedGoodStrings[i] = pad + goodStrings[i] + pad;
+
+    }
+
+    /*
+     * Throws an exception if <code>Input</code> is
+     * <code>exceptionalInput</code> and {@link Float.parseFloat
+     * parseFloat} does <em>not</em> throw an exception or if
+     * <code>Input</code> is not <code>exceptionalInput</code> and
+     * <code>parseFloat</code> throws an exception.  This method does
+     * not attempt to test whether the string is converted to the
+     * proper value; just whether the input is accepted appropriately
+     * or not.
+     */
+    private static void testParsing(String [] input,
+                                    boolean exceptionalInput) {
+        for(int i = 0; i < input.length; i++) {
+            double d;
+
+            try {
+                d = Float.parseFloat(input[i]);
+                check(input[i]);
+            }
+            catch (NumberFormatException e) {
+                if (! exceptionalInput) {
+                    throw new RuntimeException("Float.parseFloat rejected " +
+                                               "good string `" + input[i] +
+                                               "'.");
+                }
+                break;
+            }
+            if (exceptionalInput) {
+                throw new RuntimeException("Float.parseFloat accepted " +
+                                           "bad string `" + input[i] +
+                                           "'.");
+            }
+        }
+    }
+
+    /**
+     * For each power of two, test at boundaries of
+     * region that should convert to that value.
+     */
+    @Test
+    public void testPowers() {
+        for(int i = -149; i <= +127; i++) {
+            float f = Math.scalb(1.0f, i);
+            BigDecimal f_BD = new BigDecimal(f);
+
+            BigDecimal lowerBound = f_BD.subtract(new BigDecimal(Math.ulp(-Math.nextUp(-f))).multiply(HALF));
+            BigDecimal upperBound = f_BD.add(new BigDecimal(Math.ulp(f)).multiply(HALF));
+
+            check(lowerBound.toString());
+            check(upperBound.toString());
+        }
+        check(new BigDecimal(Float.MAX_VALUE).add(new BigDecimal(Math.ulp(Float.MAX_VALUE)).multiply(HALF)).toString());
+    }
+
+    @Test
+    public void testParsing() {
+        testParsing(goodStrings, false);
+        testParsing(paddedGoodStrings, false);
+        testParsing(badStrings, true);
+        testParsing(paddedBadStrings, true);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Integer/ParsingTest.java b/ojluni/src/test/java/lang/Integer/ParsingTest.java
new file mode 100644
index 0000000..b1ff08b
--- /dev/null
+++ b/ojluni/src/test/java/lang/Integer/ParsingTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5017980 6576055 8041972 8055251
+ * @summary Test parsing methods
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Integer;
+
+import java.lang.IndexOutOfBoundsException;
+import java.lang.NullPointerException;
+import java.lang.RuntimeException;
+
+// Android-added: support for wrapper to avoid d8 backporting of Integer.parseInt (b/215435866).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * There are seven methods in java.lang.Integer which transform strings
+ * into an int or Integer value:
+ *
+ * public Integer(String s)
+ * public static Integer decode(String nm)
+ * public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix)
+ * public static int parseInt(String s, int radix)
+ * public static int parseInt(String s)
+ * public static Integer valueOf(String s, int radix)
+ * public static Integer valueOf(String s)
+ *
+ * Besides decode, all the methods and constructor call down into
+ * parseInt(CharSequence, int, int, int) to do the actual work.  Therefore, the
+ * behavior of parseInt(CharSequence, int, int, int) will be tested here.
+ *
+ */
+
+public class ParsingTest {
+
+    @Test
+    public void main() {
+        check(+100, "+100");
+        check(-100, "-100");
+
+        check(0, "+0");
+        check(0, "-0");
+        check(0, "+00000");
+        check(0, "-00000");
+
+        check(0, "0");
+        check(1, "1");
+        check(9, "9");
+
+        checkFailure("");
+        checkFailure("\u0000");
+        checkFailure("\u002f");
+        checkFailure("+");
+        checkFailure("-");
+        checkFailure("++");
+        checkFailure("+-");
+        checkFailure("-+");
+        checkFailure("--");
+        checkFailure("++100");
+        checkFailure("--100");
+        checkFailure("+-6");
+        checkFailure("-+6");
+        checkFailure("*100");
+
+        // check offset based methods
+        check(0, "+00000", 0, 6, 10);
+        check(0, "-00000", 0, 6, 10);
+        check(0, "test-00000", 4, 10, 10);
+        check(-12345, "test-12345", 4, 10, 10);
+        check(12345, "xx12345yy", 2, 7, 10);
+        check(15, "xxFyy", 2, 3, 16);
+
+        checkNumberFormatException("", 0, 0, 10);
+        checkNumberFormatException("+-6", 0, 3, 10);
+        checkNumberFormatException("1000000", 7, 7, 10);
+        checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1);
+        checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1);
+
+        checkIndexOutOfBoundsException("1000000", 10, 4, 10);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("-1", 0, 3, 10);
+        checkIndexOutOfBoundsException("-1", 2, 3, 10);
+        checkIndexOutOfBoundsException("-1", -1, 2, 10);
+
+        checkNull(0, 1, 10);
+        checkNull(-1, 0, 10);
+        checkNull(0, 0, 10);
+        checkNull(0, -1, 10);
+        checkNull(-1, -1, -1);
+    }
+
+    private static void check(int expected, String val) {
+        int n = Integer.parseInt(val);
+        if (n != expected)
+            throw new RuntimeException("Integer.parseInt failed. String:" +
+                                                val + " Result:" + n);
+    }
+
+    private static void checkFailure(String val) {
+        int n = 0;
+        try {
+            n = Integer.parseInt(val);
+            System.err.println("parseInt(" + val + ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (NumberFormatException nfe) {
+            ; // Expected
+        }
+    }
+
+    private static void checkNumberFormatException(String val, int start, int end, int radix) {
+        int n = 0;
+        try {
+            // Android-changed: call wrapper to avoid d8 backports (b/215435866).
+            // n = Integer.parseInt(val, start, end, radix);
+            n = Integer_parseInt(val, start, end, radix);
+            System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix +
+                    ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (NumberFormatException nfe) {
+            ; // Expected
+        }
+    }
+
+    private static void checkIndexOutOfBoundsException(String val, int start, int end, int radix) {
+        int n = 0;
+        try {
+            // Android-changed: call wrapper to avoid d8 backports (b/215435866).
+            // n = Integer.parseInt(val, start, end, radix);
+            n = Integer_parseInt(val, start, end, radix);
+            System.err.println("parseInt(" + val + ", " + start + ", " + end + ", " + radix  +
+                    ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (IndexOutOfBoundsException ioob) {
+            ; // Expected
+        }
+    }
+
+    private static void checkNull(int start, int end, int radix) {
+        int n = 0;
+        try {
+            // Android-changed: call wrapper to avoid d8 backports (b/215435866).
+            // n = Integer.parseInt(null, start, end, radix);
+            n = Integer_parseInt(null, start, end, radix);
+            System.err.println("parseInt(null, " + start + ", " + end + ", " + radix +
+                    ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (NullPointerException npe) {
+            ; // Expected
+        }
+    }
+
+    private static void check(int expected, String val, int start, int end, int radix) {
+        // Android-changed: call wrapper to avoid d8 backports (b/215435866).
+        // int n = Integer.parseInt(val, start, end, radix);
+        int n = Integer_parseInt(val, start, end, radix);
+        if (n != expected)
+            throw new RuntimeException("Integer.parsedInt failed. Expected: " + expected + " String: \"" +
+                    val + "\", start: " + start + ", end: " + end + ", radix: " + radix + " Result:" + n);
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of Integer.parseInt (b/215435866).
+    private static int Integer_parseInt(String val, int start, int end, int radix) {
+        try {
+            MethodType parseIntType = MethodType.methodType(int.class,
+                                                            CharSequence.class,
+                                                            int.class,
+                                                            int.class,
+                                                            int.class);
+            MethodHandle parseInt =
+                    MethodHandles.lookup().findStatic(Integer.class, "parseInt", parseIntType);
+            return (int) parseInt.invokeExact((CharSequence) val, start, end, radix);
+        } catch (IndexOutOfBoundsException | NullPointerException | NumberFormatException e) {
+            // Expected exceptions from the target method during the tests here.
+            throw e;
+        } catch (Throwable t) {
+            // Everything else.
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Integer/Unsigned.java b/ojluni/src/test/java/lang/Integer/Unsigned.java
new file mode 100644
index 0000000..36cce16
--- /dev/null
+++ b/ojluni/src/test/java/lang/Integer/Unsigned.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.Integer;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/*
+ * @test
+ * @bug 4504839 4215269 6322074
+ * @summary Basic tests for unsigned operations.
+ * @author Joseph D. Darcy
+ */
+public class Unsigned {
+
+    @Test
+    public void testRoundtrip() {
+        int[] data = {-1, 0, 1};
+
+        for(int datum : data) {
+            Assert.assertEquals(
+                Integer.parseUnsignedInt(Integer.toBinaryString(datum), 2),
+                datum,
+                "Bad binary roundtrip conversion of " + datum);
+
+            Assert.assertEquals(Integer.parseUnsignedInt(Integer.toOctalString(datum), 8),
+                datum,
+                "Bad octal roundtrip conversion of " + datum);
+
+            Assert.assertEquals(Integer.parseUnsignedInt(Integer.toHexString(datum), 16),
+                datum,
+                "Bad hex roundtrip conversion of " + datum);
+        }
+    }
+
+    @Test
+    public void testByteToUnsignedInt() {
+        for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+            byte datum = (byte) i;
+            int ui = Byte.toUnsignedInt(datum);
+
+            if ( (ui & (~0xff)) != 0 || ((byte)ui != datum )) {
+                Assert.fail(
+                    String.format("Bad conversion of byte %d to unsigned int %d%n", datum, ui));
+            }
+        }
+    }
+
+    @Test
+    public void testShortToUnsignedInt() {
+        for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) {
+            short datum = (short) i;
+            int ui = Short.toUnsignedInt(datum);
+
+            if ( (ui & (~0xffff)) != 0 || ((short)ui != datum )) {
+                Assert.fail(
+                    String.format("Bad conversion of short %d to unsigned int %d%n", datum, ui));
+            }
+        }
+    }
+
+    @Test
+    public void testUnsignedCompare() {
+        int[] data = {
+            0,
+            1,
+            2,
+            3,
+            0x8000_0000,
+            0x8000_0001,
+            0x8000_0002,
+            0x8000_0003,
+            0xFFFF_FFFE,
+            0xFFFF_FFFF,
+        };
+
+        for(int i : data) {
+            for(int j : data) {
+                int libraryResult    = Integer.compareUnsigned(i, j);
+                int libraryResultRev = Integer.compareUnsigned(j, i);
+                int localResult      = compUnsigned(i, j);
+
+                if (i == j) {
+                    Assert.assertEquals(libraryResult, 0,
+                        String.format("Value 0x%x did not compare as " +
+                                          "an unsigned value equal to itself; got %d%n",
+                                          i, libraryResult));
+                }
+
+                Assert.assertEquals(Integer.signum(libraryResult),
+                    Integer.signum(localResult),
+                    String.format("Unsigned compare of 0x%x to 0x%x%n:" +
+                                      "\texpected sign of %d, got %d%n",
+                                      i, j, localResult, libraryResult));
+
+                Assert.assertEquals(Integer.signum(libraryResult),
+                    -Integer.signum(libraryResultRev),
+                    String.format("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" +
+                                      " for \t0x%x and 0x%x, computed %d and %d%n",
+                                      i, j, libraryResult, libraryResultRev));
+            }
+        }
+    }
+
+    /**
+     * Straightforward compare unsigned algorithm.
+     */
+    private static int compUnsigned(int x, int y) {
+        int sign_x = x & Integer.MIN_VALUE;
+        int sign_y = y & Integer.MIN_VALUE;
+
+        int mant_x  = x & (~Integer.MIN_VALUE);
+        int mant_y  = y & (~Integer.MIN_VALUE);
+
+        if (sign_x == sign_y)
+            return Integer.compare(mant_x, mant_y);
+        else {
+            if (sign_x == 0)
+                return -1; // sign x is 0, sign y is 1 => (x < y)
+            else
+                return 1; //  sign x is 1, sign y is 0 => (x > y)
+        }
+    }
+
+    @Test
+    public void testToUnsignedLong() {
+        int[] data = {
+            0,
+            1,
+            2,
+            3,
+            0x1234_5678,
+            0x8000_0000,
+            0x8000_0001,
+            0x8000_0002,
+            0x8000_0003,
+            0x8765_4321,
+            0xFFFF_FFFE,
+            0xFFFF_FFFF,
+        };
+
+        for(int datum : data) {
+            long result = Integer.toUnsignedLong(datum);
+
+            // High-order bits should be zero
+            Assert.assertEquals(
+                (result & 0xffff_ffff_0000_0000L),
+                0L,
+                String.format("High bits set converting 0x%x to 0x%x%n", datum, result));
+
+            // Lower-order bits should be equal to datum.
+            int lowOrder = (int)(result & 0x0000_0000_ffff_ffffL);
+            Assert.assertEquals(lowOrder, datum,
+                String.format("Low bits not preserved converting 0x%x to 0x%x%n", datum, result));
+        }
+    }
+
+    @Test
+    public void testToStringUnsigned() {
+        int[] data = {
+            0,
+            1,
+            2,
+            3,
+            99999,
+            100000,
+            999999,
+            100000,
+            999999999,
+            1000000000,
+            0x1234_5678,
+            0x8000_0000,
+            0x8000_0001,
+            0x8000_0002,
+            0x8000_0003,
+            0x8765_4321,
+            0xFFFF_FFFE,
+            0xFFFF_FFFF,
+        };
+
+        for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+            for(int datum : data) {
+                String result1 = Integer.toUnsignedString(datum, radix);
+                String result2 = Long.toString(Integer.toUnsignedLong(datum), radix);
+
+                if (!result1.equals(result2)) {
+                    Assert.fail(String.format("Unexpected string difference converting 0x%x:" +
+                                      "\t%s %s%n",
+                                      datum, result1, result2));
+                }
+
+                if (radix == 10) {
+                    String result3 = Integer.toUnsignedString(datum);
+                    if (!result2.equals(result3)) {
+                        Assert.fail(String.format("Unexpected string difference converting 0x%x:" +
+                                          "\t%s %s%n",
+                                          datum, result3, result2));
+                    }
+                }
+
+                int parseResult = Integer.parseUnsignedInt(result1, radix);
+
+                if (parseResult != datum) {
+                    Assert.fail(String.format("Bad roundtrip conversion of %d in base %d" +
+                                          "\tconverting back ''%s'' resulted in %d%n",
+                                          datum, radix, result1,  parseResult));
+                }
+            }
+        }
+    }
+
+    private static final long MAX_UNSIGNED_INT = Integer.toUnsignedLong(0xffff_ffff);
+
+    @Test
+    public void testParseUnsignedInt() {
+        // Values include those between signed Integer.MAX_VALUE and
+        // unsignted int MAX_VALUE.
+        long[] inRange = {
+            0L,
+            1L,
+            10L,
+            2147483646L,   // MAX_VALUE - 1
+            2147483647L,   // MAX_VALUE
+            2147483648L,   // MAX_VALUE + 1
+
+            MAX_UNSIGNED_INT - 1L,
+            MAX_UNSIGNED_INT,
+        };
+
+        for(long value : inRange) {
+            for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+                String longString = Long.toString(value, radix);
+                int intResult = Integer.parseUnsignedInt(longString, radix);
+
+                if (Integer.toUnsignedLong(intResult) != value) {
+                    Assert.fail(String.format("Bad roundtrip conversion of %d in base %d" +
+                                      "\tconverting back ''%s'' resulted in %d%n",
+                                      value, radix, longString,  intResult));
+                }
+
+                // test offset based parse method
+                intResult = Integer.parseUnsignedInt("prefix" + longString + "suffix",
+                        "prefix".length(), "prefix".length() + longString.length(), radix);
+
+                if (Integer.toUnsignedLong(intResult) != value) {
+                    Assert.fail(String.format("Bad roundtrip conversion of %d in base %d" +
+                            "\tconverting back ''%s'' resulted in %d%n",
+                            value, radix, longString,  intResult));
+                }
+            }
+        }
+
+        String[] outOfRange = {
+            null,
+            "",
+            "-1",
+            Long.toString(MAX_UNSIGNED_INT + 1L),
+            Long.toString(Long.MAX_VALUE)
+        };
+
+        for(String s : outOfRange) {
+            try {
+                int result = Integer.parseUnsignedInt(s);
+                Assert.fail(
+                    String.format("Unexpected got %d from an unsigned conversion of %s", result, s));
+            } catch(NumberFormatException nfe) {
+                ; // Correct result
+            }
+        }
+    }
+
+    @Test
+    public void testDivideAndRemainder() {
+        long[] inRange = {
+            0L,
+            1L,
+            2L,
+            2147483646L,   // MAX_VALUE - 1
+            2147483647L,   // MAX_VALUE
+            2147483648L,   // MAX_VALUE + 1
+
+            MAX_UNSIGNED_INT - 1L,
+            MAX_UNSIGNED_INT,
+        };
+
+        for(long dividend : inRange) {
+            for(long divisor : inRange) {
+                int quotient;
+                long longQuotient;
+
+                int remainder;
+                long longRemainder;
+
+                if (divisor == 0) {
+                    try {
+                        quotient = Integer.divideUnsigned((int) dividend, (int) divisor);
+                        Assert.fail("Unexpectedly did not throw");
+                    } catch(ArithmeticException ea) {
+                        ; // Expected
+                    }
+
+                    try {
+                        remainder = Integer.remainderUnsigned((int) dividend, (int) divisor);
+                        Assert.fail("Unexpectedly did not throw");
+                    } catch(ArithmeticException ea) {
+                        ; // Expected
+                    }
+                } else {
+                    quotient = Integer.divideUnsigned((int) dividend, (int) divisor);
+                    longQuotient = dividend / divisor;
+
+                    if (quotient != (int)longQuotient) {
+                        Assert.fail(String.format("Unexpected unsigned divide result %s on %s/%s%n",
+                                          Integer.toUnsignedString(quotient),
+                                          Integer.toUnsignedString((int) dividend),
+                                          Integer.toUnsignedString((int) divisor)));
+                    }
+
+                    remainder = Integer.remainderUnsigned((int) dividend, (int) divisor);
+                    longRemainder = dividend % divisor;
+
+                    if (remainder != (int)longRemainder) {
+                        Assert.fail(String.format("Unexpected unsigned remainder result %s on %s%%%s%n",
+                                          Integer.toUnsignedString(remainder),
+                                          Integer.toUnsignedString((int) dividend),
+                                          Integer.toUnsignedString((int) divisor)));
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Long/ParsingTest.java b/ojluni/src/test/java/lang/Long/ParsingTest.java
new file mode 100644
index 0000000..7706fe0
--- /dev/null
+++ b/ojluni/src/test/java/lang/Long/ParsingTest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5017980 6576055 8041972 8055251
+ * @summary Test parsing methods
+ * @author Joseph D. Darcy
+ */
+
+/**
+ * There are seven methods in java.lang.Long which transform strings
+ * into a long or Long value:
+ *
+ * public Long(String s)
+ * public static Long decode(String nm)
+ * public static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex)
+ * public static long parseLong(String s, int radix)
+ * public static long parseLong(String s)
+ * public static Long valueOf(String s, int radix)
+ * public static Long valueOf(String s)
+ *
+ * Besides decode, all the methods and constructor call down into
+ * parseLong(CharSequence, int, int, int) to do the actual work.  Therefore, the
+ * behavior of parseLong(CharSequence, int, int, int) will be tested here.
+ */
+package test.java.lang.Long;
+
+// Android-added: support for wrapper to avoid d8 backporting of Integer.parseInt (b/215435867).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import org.testng.annotations.Test;
+
+public class ParsingTest {
+
+    @Test
+    public void testParsing() {
+        check(+100L, "+100");
+        check(-100L, "-100");
+
+        check(0L, "+0");
+        check(0L, "-0");
+        check(0L, "+00000");
+        check(0L, "-00000");
+
+        check(0L, "0");
+        check(1L, "1");
+        check(9L, "9");
+
+        checkFailure("");
+        checkFailure("\u0000");
+        checkFailure("\u002f");
+        checkFailure("+");
+        checkFailure("-");
+        checkFailure("++");
+        checkFailure("+-");
+        checkFailure("-+");
+        checkFailure("--");
+        checkFailure("++100");
+        checkFailure("--100");
+        checkFailure("+-6");
+        checkFailure("-+6");
+        checkFailure("*100");
+
+        check(0L, "test-00000", 4, 10, 10);
+        check(-12345L, "test-12345", 4, 10, 10);
+        check(12345L, "xx12345yy", 2, 7, 10);
+        check(123456789012345L, "xx123456789012345yy", 2, 17, 10);
+        check(15L, "xxFyy", 2, 3, 16);
+
+        checkNumberFormatException("", 0, 0, 10);
+        checkNumberFormatException("+-6", 0, 3, 10);
+        checkNumberFormatException("1000000", 7, 7, 10);
+        checkNumberFormatException("1000000", 0, 2, Character.MAX_RADIX + 1);
+        checkNumberFormatException("1000000", 0, 2, Character.MIN_RADIX - 1);
+
+        checkIndexOutOfBoundsException("", 1, 1, 10);
+        checkIndexOutOfBoundsException("1000000", 10, 4, 10);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", 10, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MAX_RADIX + 1);
+        checkIndexOutOfBoundsException("1000000", -1, 2, Character.MIN_RADIX - 1);
+        checkIndexOutOfBoundsException("-1", 0, 3, 10);
+        checkIndexOutOfBoundsException("-1", 2, 3, 10);
+        checkIndexOutOfBoundsException("-1", -1, 2, 10);
+
+        checkNull(0, 1, 10);
+        checkNull(-1, 0, 10);
+        checkNull(0, 0, 10);
+        checkNull(0, -1, 10);
+        checkNull(-1, -1, -1);
+    }
+
+    private static void check(long expected, String val) {
+        long n = Long.parseLong(val);
+        if (n != expected)
+            throw new RuntimeException("Long.parseLong failed. String:" +
+                                       val + " Result:" + n);
+    }
+
+    private static void checkFailure(String val) {
+        long n = 0L;
+        try {
+            n = Long.parseLong(val);
+            System.err.println("parseLong(" + val + ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (NumberFormatException nfe) {
+            ; // Expected
+        }
+    }
+
+    private static void checkNumberFormatException(String val, int start, int end, int radix) {
+        long n = 0;
+        try {
+            // Android-changed: call wrapper to avoid d8 backporting Long.parseLong (b/215435867).
+            // n = Long.parseLong(val, start, end, radix);
+            n = Long_parseLong(val, start, end, radix);
+            System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix +
+                    ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (NumberFormatException nfe) {
+            ; // Expected
+        }
+    }
+
+    private static void checkIndexOutOfBoundsException(String val, int start, int end, int radix) {
+        long n = 0;
+        try {
+            // Android-changed: call wrapper to avoid d8 backporting Long.parseLong (b/215435867).
+            // n = Long.parseLong(val, start, end, radix);
+            n = Long_parseLong(val, start, end, radix);
+            System.err.println("parseLong(" + val + ", " + start + ", " + end + ", " + radix +
+                    ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (IndexOutOfBoundsException ioob) {
+            ; // Expected
+        }
+    }
+
+    private static void checkNull(int start, int end, int radix) {
+        long n = 0;
+        try {
+            // Android-changed: call wrapper to avoid d8 backporting Long.parseLong (b/215435867).
+            // n = Long.parseLong(null, start, end, radix);
+            n = Long_parseLong(null, start, end, radix);
+            System.err.println("parseLong(null, " + start + ", " + end + ", " + radix +
+                    ") incorrectly returned " + n);
+            throw new RuntimeException();
+        } catch (NullPointerException npe) {
+            ; // Expected
+        }
+    }
+
+    private static void check(long expected, String val, int start, int end, int radix) {
+        // Android-changed: call wrapper to avoid d8 backporting Long.parseLong (b/215435867).
+        // long n = Long.parseLong(val, start, end, radix);
+        long n = Long_parseLong(val, start, end, radix);
+        if (n != expected)
+            throw new RuntimeException("Long.parseLong failed. Expexted: " + expected + " String: \"" +
+                    val + "\", start: " + start + ", end: " + end + " radix: " + radix + " Result: " + n);
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of Long.parseLong (b/215435867).
+    private static long Long_parseLong(String val, int start, int end, int radix) {
+        try {
+            MethodType parseType = MethodType.methodType(long.class,
+                                                         CharSequence.class,
+                                                         int.class,
+                                                         int.class,
+                                                         int.class);
+            MethodHandle parse =
+                    MethodHandles.lookup().findStatic(Long.class, "parseLong", parseType);
+            return (long) parse.invokeExact((CharSequence) val, start, end, radix);
+        } catch (IndexOutOfBoundsException | NullPointerException | NumberFormatException e) {
+            // Expected exceptions from the target method during the tests here.
+            throw e;
+        } catch (Throwable t) {
+            // Everything else.
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Long/Unsigned.java b/ojluni/src/test/java/lang/Long/Unsigned.java
new file mode 100644
index 0000000..d724b34
--- /dev/null
+++ b/ojluni/src/test/java/lang/Long/Unsigned.java
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4504839 4215269 6322074 8030814
+ * @summary Basic tests for unsigned operations
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Long;
+
+// Android-added: support for wrapper to avoid d8 backporting of Integer.parseInt (b/215435867).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import java.math.*;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class Unsigned {
+    private static final BigInteger TWO = BigInteger.valueOf(2L);
+
+    @Test
+    public void testRoundtrip() {
+        long[] data = {-1L, 0L, 1L};
+
+        for(long datum : data) {
+            Assert.assertEquals(
+                Long.parseUnsignedLong(Long.toBinaryString(datum), 2),
+                datum,
+                "Bad binary roundtrip conversion of " + datum);
+
+            Assert.assertEquals(
+                Long.parseUnsignedLong(Long.toOctalString(datum), 8),
+                datum,
+                "Bad octal roundtrip conversion of " + datum);
+
+            Assert.assertEquals(
+                Long.parseUnsignedLong(Long.toHexString(datum), 16),
+                datum,
+                "Bad hex roundtrip conversion of " + datum);
+        }
+    }
+
+    @Test
+    public void testByteToUnsignedLong() {
+        for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+            byte datum = (byte) i;
+            long ui = Byte.toUnsignedLong(datum);
+
+            if ( (ui & (~0xffL)) != 0L || ((byte)ui != datum )) {
+                Assert.fail(
+                    String.format("Bad conversion of byte %d to unsigned long %d%n", datum, ui));
+            }
+        }
+    }
+
+    @Test
+    public void testShortToUnsignedLong() {
+        for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) {
+            short datum = (short) i;
+            long ui = Short.toUnsignedLong(datum);
+
+            if ( (ui & (~0xffffL)) != 0L || ((short)ui != datum )) {
+                Assert.fail(
+                    String.format("Bad conversion of short %d to unsigned long %d%n", datum, ui));
+            }
+        }
+    }
+
+    @Test
+    public void testUnsignedCompare() {
+        long[] data = {
+            0L,
+            1L,
+            2L,
+            3L,
+            0x00000000_80000000L,
+            0x00000000_FFFFFFFFL,
+            0x00000001_00000000L,
+            0x80000000_00000000L,
+            0x80000000_00000001L,
+            0x80000000_00000002L,
+            0x80000000_00000003L,
+            0x80000000_80000000L,
+            0xFFFFFFFF_FFFFFFFEL,
+            0xFFFFFFFF_FFFFFFFFL,
+        };
+
+        for(long i : data) {
+            for(long j : data) {
+                long libraryResult    = Long.compareUnsigned(i, j);
+                long libraryResultRev = Long.compareUnsigned(j, i);
+                long localResult      = compUnsigned(i, j);
+
+                if (i == j) {
+                    Assert.assertEquals(
+                        libraryResult,
+                        0,
+                        String.format("Value 0x%x did not compare as " +
+                                          "an unsigned equal to itself; got %d%n",
+                                          i, libraryResult));
+                }
+
+                Assert.assertEquals(
+                    Long.signum(libraryResult),
+                    Long.signum(localResult),
+                    String.format("Unsigned compare of 0x%x to 0x%x%n:" +
+                                     "\texpected sign of %d, got %d%n",
+                                     i, j, localResult, libraryResult));
+
+                Assert.assertEquals(
+                    Long.signum(libraryResult),
+                    -Long.signum(libraryResultRev),
+                    String.format("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" +
+                                          " for \t0x%x and 0x%x, computed %d and %d%n",
+                                          i, j, libraryResult, libraryResultRev));
+            }
+        }
+    }
+
+    private static int compUnsigned(long x, long y) {
+        BigInteger big_x = toUnsignedBigInt(x);
+        BigInteger big_y = toUnsignedBigInt(y);
+
+        return big_x.compareTo(big_y);
+    }
+
+    private static BigInteger toUnsignedBigInt(long x) {
+        if (x >= 0)
+            return BigInteger.valueOf(x);
+        else {
+            int upper = (int)(((long)x) >> 32);
+            int lower = (int) x;
+
+            BigInteger bi = // (upper << 32) + lower
+                (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
+                add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
+
+            // System.out.printf("%n\t%d%n\t%s%n", x, bi.toString());
+            return bi;
+        }
+    }
+
+    @Test
+    public void testToStringUnsigned() {
+        long[] data = {
+            0L,
+            1L,
+            2L,
+            3L,
+            99999L,
+            100000L,
+            999999L,
+            100000L,
+            999999999L,
+            1000000000L,
+            0x1234_5678L,
+            0x8000_0000L,
+            0x8000_0001L,
+            0x8000_0002L,
+            0x8000_0003L,
+            0x8765_4321L,
+            0xFFFF_FFFEL,
+            0xFFFF_FFFFL,
+
+            // Long-range values
+              999_999_999_999L,
+            1_000_000_000_000L,
+
+              999_999_999_999_999_999L,
+            1_000_000_000_000_000_000L,
+
+            0xFFFF_FFFF_FFFF_FFFEL,
+            0xFFFF_FFFF_FFFF_FFFFL,
+        };
+
+        for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+            for(long datum : data) {
+                String result1 = Long.toUnsignedString(datum, radix);
+                String result2 = toUnsignedBigInt(datum).toString(radix);
+
+                Assert.assertEquals(
+                    result1,
+                    result2,
+                    String.format("Unexpected string difference converting 0x%x:" +
+                                      "\t%s %s%n", datum, result1, result2));
+
+                if (radix == 10) {
+                    String result3 = Long.toUnsignedString(datum);
+                    Assert.assertEquals(
+                        result2,
+                        result3,
+                        String.format("Unexpected string difference converting 0x%x:" +
+                                          "\t%s %s%n", datum, result3, result2));
+                }
+
+                long parseResult = Long.parseUnsignedLong(result1, radix);
+
+                Assert.assertEquals(
+                    parseResult,
+                    datum,
+                    String.format("Bad roundtrip conversion of %d in base %d" +
+                                          "\tconverting back ''%s'' resulted in %d%n",
+                                          datum, radix, result1,  parseResult));
+            }
+        }
+    }
+
+    @Test
+    public void testParseUnsignedLong() {
+        long maxUnsignedInt = Integer.toUnsignedLong(0xffff_ffff);
+
+        // Values include those between signed Long.MAX_VALUE and
+        // unsignted Long MAX_VALUE.
+        BigInteger[] inRange = {
+            BigInteger.valueOf(0L),
+            BigInteger.valueOf(1L),
+            BigInteger.valueOf(10L),
+            BigInteger.valueOf(2147483646L),   // Integer.MAX_VALUE - 1
+            BigInteger.valueOf(2147483647L),   // Integer.MAX_VALUE
+            BigInteger.valueOf(2147483648L),   // Integer.MAX_VALUE + 1
+
+            BigInteger.valueOf(maxUnsignedInt - 1L),
+            BigInteger.valueOf(maxUnsignedInt),
+
+            BigInteger.valueOf(Long.MAX_VALUE - 1L),
+            BigInteger.valueOf(Long.MAX_VALUE),
+            BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE),
+
+            TWO.pow(64).subtract(BigInteger.ONE)
+        };
+
+        for(BigInteger value : inRange) {
+            for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+                String bigString = value.toString(radix);
+                long longResult = Long.parseUnsignedLong(bigString, radix);
+
+                Assert.assertEquals(
+                    toUnsignedBigInt(longResult),
+                    value,
+                    String.format("Bad roundtrip conversion of %d in base %d" +
+                                      "\tconverting back ''%s'' resulted in %d%n",
+                                      value, radix, bigString,  longResult));
+
+                // test offset based parse method
+                // Android-changed: avoid d8 backporting Long.parseUnsignedLong (b/215435867).
+                // longResult = Long.parseUnsignedLong("prefix" + bigString + "suffix", "prefix".length(),
+                //        "prefix".length() + bigString.length(), radix);
+                longResult = Long_parseUnsignedLong("prefix" + bigString + "suffix", "prefix".length(),
+                        "prefix".length() + bigString.length(), radix);
+
+                Assert.assertEquals(
+                    toUnsignedBigInt(longResult),
+                    value,
+                    String.format("Bad roundtrip conversion of %d in base %d" +
+                            "\tconverting back ''%s'' resulted in %d%n",
+                            value, radix, bigString,  longResult));
+            }
+        }
+
+        String[] outOfRange = {
+            null,
+            "",
+            "-1",
+            TWO.pow(64).toString(),
+        };
+
+        for(String s : outOfRange) {
+            try {
+                long result = Long.parseUnsignedLong(s);
+                Assert.fail(String.format("Unexpected got %d from an unsigned conversion of %s",
+                                  result, s));
+            } catch(NumberFormatException nfe) {
+                ; // Correct result
+            }
+        }
+
+        // test case known at one time to fail
+        testUnsignedOverflow("1234567890abcdef1", 16, true);
+
+        // largest value with guard = 91 = 13*7; radix = 13
+        testUnsignedOverflow("196a78a44c3bba320c", 13, false);
+
+        // smallest value with guard = 92 = 23*2*2; radix = 23
+        testUnsignedOverflow("137060c6g1c1dg0", 23, false);
+
+        // guard in [92,98]: no overflow
+
+        // one less than smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33
+        testUnsignedOverflow("b1w8p7j5q9r6f", 33, false);
+
+        // smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33
+        testUnsignedOverflow("b1w8p7j5q9r6g", 33, true);
+
+        // test overflow of overflow
+        BigInteger maxUnsignedLong =
+                BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE);
+        for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+            BigInteger quotient = maxUnsignedLong.divide(BigInteger.valueOf(radix));
+            for (int addend = 2; addend <= radix; addend++) {
+                BigInteger b = quotient.multiply(BigInteger.valueOf(radix + addend));
+                testUnsignedOverflow(b.toString(radix), radix, b.compareTo(maxUnsignedLong) > 0);
+            }
+        }
+    }
+
+    // test for missing or unexpected unsigned overflow exception
+    private static void testUnsignedOverflow(String s, int radix, boolean exception) {
+        long result;
+        try {
+            result = Long.parseUnsignedLong(s, radix);
+            if (exception) {
+                Assert.fail(String.format("Unexpected result %d for Long.parseUnsignedLong(%s,%d)\n",
+                        result, s, radix));
+            }
+        } catch (NumberFormatException nfe) {
+            if (!exception) {
+                Assert.fail(
+                    String.format("Unexpected exception %s for Long.parseUnsignedLong(%s,%d)\n",
+                    nfe.toString(), s, radix));
+            }
+        }
+    }
+
+    @Test
+    public void testDivideAndRemainder() {
+        long MAX_UNSIGNED_INT = Integer.toUnsignedLong(0xffff_ffff);
+
+        BigInteger[] inRange = {
+            BigInteger.valueOf(0L),
+            BigInteger.valueOf(1L),
+            BigInteger.valueOf(10L),
+            BigInteger.valueOf(2147483646L),   // Integer.MAX_VALUE - 1
+            BigInteger.valueOf(2147483647L),   // Integer.MAX_VALUE
+            BigInteger.valueOf(2147483648L),   // Integer.MAX_VALUE + 1
+
+            BigInteger.valueOf(MAX_UNSIGNED_INT - 1L),
+            BigInteger.valueOf(MAX_UNSIGNED_INT),
+
+            BigInteger.valueOf(Long.MAX_VALUE - 1L),
+            BigInteger.valueOf(Long.MAX_VALUE),
+            BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE),
+
+            TWO.pow(64).subtract(BigInteger.ONE)
+        };
+
+        for(BigInteger dividend : inRange) {
+            for(BigInteger divisor : inRange) {
+                long quotient;
+                BigInteger longQuotient;
+
+                long remainder;
+                BigInteger longRemainder;
+
+                if (divisor.equals(BigInteger.ZERO)) {
+                    try {
+                        quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue());
+                        Assert.fail("Unexpectedly did not throw while dividing by zero");
+                    } catch(ArithmeticException ea) {
+                        ; // Expected
+                    }
+
+                    try {
+                        remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue());
+                        Assert.fail("Unexpectedly did not throw while dividing by zero");
+                    } catch(ArithmeticException ea) {
+                        ; // Expected
+                    }
+                } else {
+                    quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue());
+                    longQuotient = dividend.divide(divisor);
+
+                    Assert.assertEquals(
+                        quotient,
+                        longQuotient.longValue(),
+                        String.format("Unexpected unsigned divide result %s on %s/%s%n",
+                                          Long.toUnsignedString(quotient),
+                                          Long.toUnsignedString(dividend.longValue()),
+                                          Long.toUnsignedString(divisor.longValue())));
+
+                    remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue());
+                    longRemainder = dividend.remainder(divisor);
+
+                    Assert.assertEquals(
+                        remainder,
+                        longRemainder.longValue(),
+                        String.format("Unexpected unsigned remainder result %s on %s%%%s%n",
+                                          Long.toUnsignedString(remainder),
+                                          Long.toUnsignedString(dividend.longValue()),
+                                          Long.toUnsignedString(divisor.longValue())));
+                }
+            }
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of Long.parseUnsignedLong(JIII) (b/215435867).
+    private static long Long_parseUnsignedLong(String val, int start, int end, int radix) {
+        try {
+            MethodType parseType = MethodType.methodType(long.class,
+                                                         CharSequence.class,
+                                                         int.class,
+                                                         int.class,
+                                                         int.class);
+            MethodHandle parse =
+                    MethodHandles.lookup().findStatic(Long.class, "parseUnsignedLong", parseType);
+            return (long) parse.invokeExact((CharSequence) val, start, end, radix);
+        } catch (IndexOutOfBoundsException | NullPointerException | NumberFormatException e) {
+            // Expected exceptions from the target method during the tests here.
+            throw e;
+        } catch (Throwable t) {
+            // Everything else.
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/AbsPositiveZero.java b/ojluni/src/test/java/lang/Math/AbsPositiveZero.java
new file mode 100644
index 0000000..5531aab
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/AbsPositiveZero.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/* @test
+   @bug 4096278
+   @summary Math.abs(+0.0) wrong
+   @author Anand Palaniswamy
+ */
+public class AbsPositiveZero {
+
+    private static boolean isPositiveZero(float f) {
+        return Float.floatToIntBits(f) == Float.floatToIntBits(0.0f);
+    }
+
+    private static boolean isPositiveZero(double d) {
+        return Double.doubleToLongBits(d) == Double.doubleToLongBits(0.0d);
+    }
+
+    @Test
+    public void testAbsPositiveZero() throws Exception {
+        Assert.assertTrue(isPositiveZero(Math.abs(-0.0d)));
+        Assert.assertTrue(isPositiveZero(Math.abs(+0.0d)));
+
+        Assert.assertEquals(Math.abs(Double.POSITIVE_INFINITY), Double.POSITIVE_INFINITY);
+        Assert.assertEquals(Math.abs(Double.NEGATIVE_INFINITY), Double.POSITIVE_INFINITY);
+
+        double dnanval = Math.abs(Double.NaN);
+        Assert.assertFalse(dnanval == dnanval);
+
+        Assert.assertTrue(isPositiveZero(Math.abs(-0.0f)));
+        Assert.assertTrue(isPositiveZero(Math.abs(+0.0f)));
+
+        Assert.assertEquals(Math.abs(Float.POSITIVE_INFINITY), Float.POSITIVE_INFINITY);
+        Assert.assertEquals(Math.abs(Float.NEGATIVE_INFINITY), Float.POSITIVE_INFINITY);
+
+        float fnanval = Math.abs(Float.NaN);
+        Assert.assertFalse(fnanval == fnanval);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/Atan2Tests.java b/ojluni/src/test/java/lang/Math/Atan2Tests.java
new file mode 100644
index 0000000..c52ce9f
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/Atan2Tests.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 4984407
+ * @summary Tests for {Math, StrictMath}.atan2
+ * @author Joseph D. Darcy
+ */
+
+public class Atan2Tests {
+
+    private Atan2Tests() {
+    }
+
+    static void testAtan2Case(double input1, double input2, double expected) {
+        Tests.test("StrictMath.atan2(double, double)", input1, input2,
+                StrictMath.atan2(input1, input2), expected);
+        Tests.test("Math.atan2(double, double)", input1, input2,
+                Math.atan2(input1, input2), expected);
+    }
+
+    @Test
+    public void testAtan2() {
+        double[][] testCases = {
+                {-3.0, Double.POSITIVE_INFINITY, -0.0},
+        };
+
+        for (double[] testCase : testCases) {
+            testAtan2Case(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/Math/CeilAndFloorTests.java b/ojluni/src/test/java/lang/Math/CeilAndFloorTests.java
new file mode 100644
index 0000000..c1ce114
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/CeilAndFloorTests.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6908131
+ * @summary Check for correct implementation of Math.ceil and Math.floor
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+
+public class CeilAndFloorTests {
+
+    private static void testCeilCase(double input, double expected) {
+        Tests.test("Math.ceil", input, Math.ceil(input), expected);
+        Tests.test("StrictMath.ceil", input, StrictMath.ceil(input), expected);
+    }
+
+    private static void testFloorCase(double input, double expected) {
+        Tests.test("Math.floor", input, Math.floor(input), expected);
+        Tests.test("StrictMath.floor", input, StrictMath.floor(input), expected);
+    }
+
+    @Test
+    private void nearIntegerTests() {
+        double[] fixedPoints = {
+                -0.0,
+                0.0,
+                -1.0,
+                1.0,
+                -0x1.0p52,
+                0x1.0p52,
+                -Double.MAX_VALUE,
+                Double.MAX_VALUE,
+                Double.NEGATIVE_INFINITY,
+                Double.POSITIVE_INFINITY,
+                Double.NaN,
+        };
+
+        for (double fixedPoint : fixedPoints) {
+            testCeilCase(fixedPoint, fixedPoint);
+            testFloorCase(fixedPoint, fixedPoint);
+        }
+
+        for (int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
+            double powerOfTwo = Math.scalb(1.0, i);
+            double neighborDown = Math.nextDown(powerOfTwo);
+            double neighborUp = Math.nextUp(powerOfTwo);
+
+            if (i < 0) {
+                testCeilCase(powerOfTwo, 1.0);
+                testCeilCase(-powerOfTwo, -0.0);
+
+                testFloorCase(powerOfTwo, 0.0);
+                testFloorCase(-powerOfTwo, -1.0);
+
+                testCeilCase(neighborDown, 1.0);
+                testCeilCase(-neighborDown, -0.0);
+
+                testFloorCase(neighborUp, 0.0);
+                testFloorCase(-neighborUp, -1.0);
+            } else {
+                testCeilCase(powerOfTwo, powerOfTwo);
+                testFloorCase(powerOfTwo, powerOfTwo);
+
+                if (neighborDown == Math.rint(neighborDown)) {
+                    testCeilCase(neighborDown, neighborDown);
+                    testCeilCase(-neighborDown, -neighborDown);
+
+                    testFloorCase(neighborDown, neighborDown);
+                    testFloorCase(-neighborDown, -neighborDown);
+                } else {
+                    testCeilCase(neighborDown, powerOfTwo);
+                    testFloorCase(-neighborDown, -powerOfTwo);
+                }
+
+                if (neighborUp == Math.rint(neighborUp)) {
+                    testCeilCase(neighborUp, neighborUp);
+                    testCeilCase(-neighborUp, -neighborUp);
+
+                    testFloorCase(neighborUp, neighborUp);
+                    testFloorCase(-neighborUp, -neighborUp);
+                } else {
+                    testFloorCase(neighborUp, powerOfTwo);
+                    testCeilCase(-neighborUp, -powerOfTwo);
+                }
+            }
+        }
+
+        for (int i = -(0x10000); i <= 0x10000; i++) {
+            double d = (double) i;
+            double neighborDown = Math.nextDown(d);
+            double neighborUp = Math.nextUp(d);
+
+            testCeilCase(d, d);
+            testCeilCase(-d, -d);
+
+            testFloorCase(d, d);
+            testFloorCase(-d, -d);
+
+            if (Math.abs(d) > 1.0) {
+                testCeilCase(neighborDown, d);
+                testCeilCase(-neighborDown, -d + 1);
+
+                testFloorCase(neighborUp, d);
+                testFloorCase(-neighborUp, -d - 1);
+            }
+        }
+    }
+
+    @Test
+    public void roundingTests() {
+        double[][] testCases = {
+                {Double.MIN_VALUE, 1.0},
+                {-Double.MIN_VALUE, -0.0},
+                {Math.nextDown(Double.MIN_NORMAL), 1.0},
+                {-Math.nextDown(Double.MIN_NORMAL), -0.0},
+                {Double.MIN_NORMAL, 1.0},
+                {-Double.MIN_NORMAL, -0.0},
+
+                {0.1, 1.0},
+                {-0.1, -0.0},
+
+                {0.5, 1.0},
+                {-0.5, -0.0},
+
+                {1.5, 2.0},
+                {-1.5, -1.0},
+
+                {2.5, 3.0},
+                {-2.5, -2.0},
+
+                {Math.nextDown(1.0), 1.0},
+                {Math.nextDown(-1.0), -1.0},
+
+                {Math.nextUp(1.0), 2.0},
+                {Math.nextUp(-1.0), -0.0},
+
+                {0x1.0p51, 0x1.0p51},
+                {-0x1.0p51, -0x1.0p51},
+
+                {Math.nextDown(0x1.0p51), 0x1.0p51},
+                {-Math.nextUp(0x1.0p51), -0x1.0p51},
+
+                {Math.nextUp(0x1.0p51), 0x1.0p51 + 1},
+                {-Math.nextDown(0x1.0p51), -0x1.0p51 + 1},
+
+                {Math.nextDown(0x1.0p52), 0x1.0p52},
+                {-Math.nextUp(0x1.0p52), -0x1.0p52 - 1.0},
+
+                {Math.nextUp(0x1.0p52), 0x1.0p52 + 1.0},
+                {-Math.nextDown(0x1.0p52), -0x1.0p52 + 1.0},
+        };
+
+        for (double[] testCase : testCases) {
+            testCeilCase(testCase[0], testCase[1]);
+            testFloorCase(-testCase[0], -testCase[1]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/CubeRootTests.java b/ojluni/src/test/java/lang/Math/CubeRootTests.java
new file mode 100644
index 0000000..9f2f92b
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/CubeRootTests.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main CubeRootTests
+ * @bug 4347132 4939441 8078672
+ * @summary Tests for {Math, StrictMath}.cbrt (use -Dseed=X to set PRNG seed)
+ * @author Joseph D. Darcy
+ * @key randomness
+ */
+package test.java.lang.Math;
+
+import java.util.Random;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class CubeRootTests {
+
+    private CubeRootTests() {
+    }
+
+    static final double infinityD = Double.POSITIVE_INFINITY;
+    static final double NaNd = Double.NaN;
+
+    // Initialize shared random number generator
+    static java.util.Random rand = new Random();
+
+    static void testCubeRootCase(double input, double expected) {
+        double minus_input = -input;
+        double minus_expected = -expected;
+
+        Tests.test("Math.cbrt(double)", input,
+                Math.cbrt(input), expected);
+        Tests.test("Math.cbrt(double)", minus_input,
+                Math.cbrt(minus_input), minus_expected);
+        Tests.test("StrictMath.cbrt(double)", input,
+                StrictMath.cbrt(input), expected);
+        Tests.test("StrictMath.cbrt(double)", minus_input,
+                StrictMath.cbrt(minus_input), minus_expected);
+    }
+
+    @Test
+    public void testCubeRoot() {
+        double[][] testCases = {
+                {NaNd, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
+                {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY},
+                {Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY},
+                {+0.0, +0.0},
+                {-0.0, -0.0},
+                {+1.0, +1.0},
+                {-1.0, -1.0},
+                {+8.0, +2.0},
+                {-8.0, -2.0}
+        };
+
+        for (double[] testCase : testCases) {
+            testCubeRootCase(testCase[0], testCase[1]);
+        }
+
+        // Test integer perfect cubes less than 2^53.
+        // Android-changed: reduce test run time testing every 100th of original
+        // for (int i = 0; i <= 208063; i++) {
+        for (int i = 0; i <= 208063; i += 100) {
+            double d = i;
+            testCubeRootCase(d * d * d, (double) i);
+        }
+
+        // Test cbrt(2^(3n)) = 2^n.
+        for (int i = 18; i <= Double.MAX_EXPONENT / 3; i++) {
+            testCubeRootCase(Math.scalb(1.0, 3 * i), Math.scalb(1.0, i));
+        }
+
+        // Test cbrt(2^(-3n)) = 2^-n.
+        for (int i = -1; i >= DoubleConsts.MIN_SUB_EXPONENT / 3; i--) {
+            testCubeRootCase(Math.scalb(1.0, 3 * i), Math.scalb(1.0, i));
+        }
+
+        // Test random perfect cubes.  Create double values with
+        // modest exponents but only have at most the 17 most
+        // significant bits in the significand set; 17*3 = 51, which
+        // is less than the number of bits in a double's significand.
+        long exponentBits1 =
+                Double.doubleToLongBits(Math.scalb(1.0, 55)) &
+                        DoubleConsts.EXP_BIT_MASK;
+        long exponentBits2 =
+                Double.doubleToLongBits(Math.scalb(1.0, -55)) &
+                        DoubleConsts.EXP_BIT_MASK;
+        for (int i = 0; i < 100; i++) {
+            // Take 16 bits since the 17th bit is implicit in the
+            // exponent
+            double input1 =
+                    Double.longBitsToDouble(exponentBits1 |
+                            // Significand bits
+                            ((long) (rand.nextInt() & 0xFFFF)) <<
+                                    (DoubleConsts.SIGNIFICAND_WIDTH - 1 - 16));
+            testCubeRootCase(input1 * input1 * input1, input1);
+
+            double input2 =
+                    Double.longBitsToDouble(exponentBits2 |
+                            // Significand bits
+                            ((long) (rand.nextInt() & 0xFFFF)) <<
+                                    (DoubleConsts.SIGNIFICAND_WIDTH - 1 - 16));
+            testCubeRootCase(input2 * input2 * input2, input2);
+        }
+
+        // Directly test quality of implementation properties of cbrt
+        // for values that aren't perfect cubes.  Verify returned
+        // result meets the 1 ulp test.  That is, we want to verify
+        // that for positive x > 1,
+        // y = cbrt(x),
+        //
+        // if (err1=x - y^3 ) < 0, abs((y_pp^3 -x )) < err1
+        // if (err1=x - y^3 ) > 0, abs((y_mm^3 -x )) < err1
+        //
+        // where y_mm and y_pp are the next smaller and next larger
+        // floating-point value to y.  In other words, if y^3 is too
+        // big, making y larger does not improve the result; likewise,
+        // if y^3 is too small, making y smaller does not improve the
+        // result.
+        //
+        // ...-----|--?--|--?--|-----... Where is the true result?
+        //         y_mm  y     y_pp
+        //
+        // The returned value y should be one of the floating-point
+        // values braketing the true result.  However, given y, a
+        // priori we don't know if the true result falls in [y_mm, y]
+        // or [y, y_pp].  The above test looks at the error in x-y^3
+        // to determine which region the true result is in; e.g. if
+        // y^3 is smaller than x, the true result should be in [y,
+        // y_pp].  Therefore, it would be an error for y_mm to be a
+        // closer approximation to x^(1/3).  In this case, it is
+        // permissible, although not ideal, for y_pp^3 to be a closer
+        // approximation to x^(1/3) than y^3.
+        //
+        // We will use pow(y,3) to compute y^3.  Although pow is not
+        // correctly rounded, StrictMath.pow should have at most 1 ulp
+        // error.  For y > 1, pow(y_mm,3) and pow(y_pp,3) will differ
+        // from pow(y,3) by more than one ulp so the comparison of
+        // errors should still be valid.
+
+        for (int i = 0; i < 1000; i++) {
+            double d = 1.0 + rand.nextDouble();
+            double err, err_adjacent;
+
+            double y1 = Math.cbrt(d);
+            double y2 = StrictMath.cbrt(d);
+
+            err = d - StrictMath.pow(y1, 3);
+            if (err != 0.0) {
+                if (Double.isNaN(err)) {
+                    Assert.fail("Encountered unexpected NaN value: d = " + d +
+                            "\tcbrt(d) = " + y1);
+                } else {
+                    if (err < 0.0) {
+                        err_adjacent = StrictMath.pow(Math.nextUp(y1), 3) - d;
+                    } else { // (err > 0.0)
+                        err_adjacent = StrictMath.pow(Math.nextAfter(y1, 0.0), 3) - d;
+                    }
+
+                    if (Math.abs(err) > Math.abs(err_adjacent)) {
+                        Assert.fail("For Math.cbrt(" + d + "), returned result " +
+                                y1 + "is not as good as adjacent value.");
+                    }
+                }
+            }
+
+            err = d - StrictMath.pow(y2, 3);
+            if (err != 0.0) {
+                if (Double.isNaN(err)) {
+                    Assert.fail("Encountered unexpected NaN value: d = " + d +
+                            "\tcbrt(d) = " + y2);
+                } else {
+                    if (err < 0.0) {
+                        err_adjacent = StrictMath.pow(Math.nextUp(y2), 3) - d;
+                    } else { // (err > 0.0)
+                        err_adjacent = StrictMath.pow(Math.nextAfter(y2, 0.0), 3) - d;
+                    }
+
+                    if (Math.abs(err) > Math.abs(err_adjacent)) {
+                        Assert.fail("For StrictMath.cbrt(" + d + "), returned result " +
+                                y2 + "is not as good as adjacent value.");
+                    }
+                }
+            }
+
+
+        }
+
+        // Test monotonicity properties near perfect cubes; test two
+        // numbers before and two numbers after; i.e. for
+        //
+        // pcNeighbors[] =
+        // {nextDown(nextDown(pc)),
+        // nextDown(pc),
+        // pc,
+        // nextUp(pc),
+        // nextUp(nextUp(pc))}
+        //
+        // test that cbrt(pcNeighbors[i]) <= cbrt(pcNeighbors[i+1])
+        {
+
+            double[] pcNeighbors = new double[5];
+            double[] pcNeighborsCbrt = new double[5];
+            double[] pcNeighborsStrictCbrt = new double[5];
+
+            // Test near cbrt(2^(3n)) = 2^n.
+            for (int i = 18; i <= Double.MAX_EXPONENT / 3; i++) {
+                double pc = Math.scalb(1.0, 3 * i);
+
+                pcNeighbors[2] = pc;
+                pcNeighbors[1] = Math.nextDown(pc);
+                pcNeighbors[0] = Math.nextDown(pcNeighbors[1]);
+                pcNeighbors[3] = Math.nextUp(pc);
+                pcNeighbors[4] = Math.nextUp(pcNeighbors[3]);
+
+                for (int j = 0; j < pcNeighbors.length; j++) {
+                    pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]);
+                    pcNeighborsStrictCbrt[j] = StrictMath.cbrt(pcNeighbors[j]);
+                }
+
+                for (int j = 0; j < pcNeighborsCbrt.length - 1; j++) {
+                    if (pcNeighborsCbrt[j] > pcNeighborsCbrt[j + 1]) {
+                        Assert.fail("Monotonicity failure for Math.cbrt on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsCbrt[j] + " and " +
+                                pcNeighborsCbrt[j + 1]);
+                    }
+
+                    if (pcNeighborsStrictCbrt[j] > pcNeighborsStrictCbrt[j + 1]) {
+                        Assert.fail("Monotonicity failure for StrictMath.cbrt on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsStrictCbrt[j] + " and " +
+                                pcNeighborsStrictCbrt[j + 1]);
+                    }
+
+
+                }
+
+            }
+
+            // Test near cbrt(2^(-3n)) = 2^-n.
+            for (int i = -1; i >= DoubleConsts.MIN_SUB_EXPONENT / 3; i--) {
+                double pc = Math.scalb(1.0, 3 * i);
+
+                pcNeighbors[2] = pc;
+                pcNeighbors[1] = Math.nextDown(pc);
+                pcNeighbors[0] = Math.nextDown(pcNeighbors[1]);
+                pcNeighbors[3] = Math.nextUp(pc);
+                pcNeighbors[4] = Math.nextUp(pcNeighbors[3]);
+
+                for (int j = 0; j < pcNeighbors.length; j++) {
+                    pcNeighborsCbrt[j] = Math.cbrt(pcNeighbors[j]);
+                    pcNeighborsStrictCbrt[j] = StrictMath.cbrt(pcNeighbors[j]);
+                }
+
+                for (int j = 0; j < pcNeighborsCbrt.length - 1; j++) {
+                    if (pcNeighborsCbrt[j] > pcNeighborsCbrt[j + 1]) {
+                        Assert.fail("Monotonicity failure for Math.cbrt on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsCbrt[j] + " and " +
+                                pcNeighborsCbrt[j + 1]);
+                    }
+
+                    if (pcNeighborsStrictCbrt[j] > pcNeighborsStrictCbrt[j + 1]) {
+                        Assert.fail("Monotonicity failure for StrictMath.cbrt on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsStrictCbrt[j] + " and " +
+                                pcNeighborsStrictCbrt[j + 1]);
+                    }
+
+
+                }
+            }
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/Math/DivModTests.java b/ojluni/src/test/java/lang/Math/DivModTests.java
index 7e9fb61..20aa421 100644
--- a/ojluni/src/test/java/lang/Math/DivModTests.java
+++ b/ojluni/src/test/java/lang/Math/DivModTests.java
@@ -31,13 +31,14 @@
 /**
  * @test Test Math and StrictMath Floor Div / Modulo operations.
  * @bug 6282196
- * @summary Basic tests for Floor division and modulo methods for both Math
- * and StrictMath for int and long datatypes.
+ * @summary Basic tests for Floor division and modulo methods for both Math and StrictMath for int
+ * and long datatypes.
  */
 public class DivModTests {
 
     /**
      * Report a test failure and increment the error count.
+     *
      * @param message the formatting string
      * @param args the variable number of arguments for the message.
      */
@@ -47,12 +48,13 @@
     }
 
     /**
-     * Test the integer floorDiv and floorMod methods.
-     * Math and StrictMath tested and the same results are expected for both.
+     * Test the integer floorDiv and floorMod methods. Math and StrictMath tested and the same
+     * results are expected for both.
      */
     @Test
     public void testIntFloorDivMod() {
-        testIntFloorDivMod(4, 0, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException
+        testIntFloorDivMod(4, 0, new ArithmeticException(),
+                new ArithmeticException()); // Should throw ArithmeticException
         testIntFloorDivMod(4, 3, 1, 1);
         testIntFloorDivMod(3, 3, 1, 0);
         testIntFloorDivMod(2, 3, 0, 2);
@@ -101,7 +103,8 @@
 
         Object strict_result = doStrictFloorDiv(x, y);
         if (!resultEquals(strict_result, expected)) {
-            fail("FAIL: StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+            fail("FAIL: StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result,
+                    expected);
         }
     }
 
@@ -116,17 +119,19 @@
 
         Object strict_result = doStrictFloorMod(x, y);
         if (!resultEquals(strict_result, expected)) {
-            fail("FAIL: StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+            fail("FAIL: StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result,
+                    expected);
         }
 
         try {
             // Verify result against double precision floor function
             int tmp = x / y;     // Force ArithmeticException for divide by zero
-            double ff = x - Math.floor((double)x / (double)y) * y;
-            int fr = (int)ff;
-            boolean t = (fr == ((Integer)result));
+            double ff = x - Math.floor((double) x / (double) y) * y;
+            int fr = (int) ff;
+            boolean t = (fr == ((Integer) result));
             if (!result.equals(fr)) {
-                fail("FAIL: Math.floorMod(%d, %d) = %s differs from Math.floor(x, y): %d%n", x, y, result, fr);
+                fail("FAIL: Math.floorMod(%d, %d) = %s differs from Math.floor(x, y): %d%n", x, y,
+                        result, fr);
             }
         } catch (ArithmeticException ae) {
             if (y != 0) {
@@ -140,7 +145,8 @@
      */
     @Test
     public void testLongFloorDivMod() {
-        testLongFloorDivMod(4L, 0L, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException
+        testLongFloorDivMod(4L, 0L, new ArithmeticException(),
+                new ArithmeticException()); // Should throw ArithmeticException
         testLongFloorDivMod(4L, 3L, 1L, 1L);
         testLongFloorDivMod(3L, 3L, 1L, 0L);
         testLongFloorDivMod(2L, 3L, 0L, 2L);
@@ -172,8 +178,8 @@
     }
 
     /**
-     * Test the long floorDiv and floorMod methods.
-     * Math and StrictMath are tested and the same results are expected for both.
+     * Test the long floorDiv and floorMod methods. Math and StrictMath are tested and the same
+     * results are expected for both.
      */
     static void testLongFloorDivMod(long x, long y, Object divExpected, Object modExpected) {
         testLongFloorDiv(x, y, divExpected);
@@ -181,9 +187,8 @@
     }
 
     /**
-     * Test FloorDiv with long arguments against expected value.
-     * The expected value is usually a Long but in some cases  is
-     * an ArithmeticException.
+     * Test FloorDiv with long arguments against expected value. The expected value is usually a
+     * Long but in some cases  is an ArithmeticException.
      *
      * @param x dividend
      * @param y modulus
@@ -197,14 +202,14 @@
 
         Object strict_result = doStrictFloorDiv(x, y);
         if (!resultEquals(strict_result, expected)) {
-            fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+            fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result,
+                    expected);
         }
     }
 
     /**
-     * Test FloorMod of long arguments against expected value.
-     * The expected value is usually a Long but in some cases  is
-     * an ArithmeticException.
+     * Test FloorMod of long arguments against expected value. The expected value is usually a Long
+     * but in some cases  is an ArithmeticException.
      *
      * @param x dividend
      * @param y modulus
@@ -218,7 +223,8 @@
 
         Object strict_result = doStrictFloorMod(x, y);
         if (!resultEquals(strict_result, expected)) {
-            fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+            fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result,
+                    expected);
         }
 
         try {
@@ -230,7 +236,8 @@
             resultD = xD.subtract(resultD);
             long fr = resultD.longValue();
             if (!result.equals(fr)) {
-                fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n", x, y, result, fr);
+                fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n",
+                        x, y, result, fr);
 
             }
         } catch (ArithmeticException ae) {
@@ -245,7 +252,8 @@
      */
     @Test
     public void testLongIntFloorDivMod() {
-        testLongIntFloorDivMod(4L, 0, new ArithmeticException(), new ArithmeticException()); // Should throw ArithmeticException
+        testLongIntFloorDivMod(4L, 0, new ArithmeticException(),
+                new ArithmeticException()); // Should throw ArithmeticException
         testLongIntFloorDivMod(4L, 3, 1L, 1);
         testLongIntFloorDivMod(3L, 3, 1L, 0);
         testLongIntFloorDivMod(2L, 3, 0L, 2);
@@ -277,8 +285,8 @@
     }
 
     /**
-     * Test the integer floorDiv and floorMod methods.
-     * Math and StrictMath are tested and the same results are expected for both.
+     * Test the integer floorDiv and floorMod methods. Math and StrictMath are tested and the same
+     * results are expected for both.
      */
     static void testLongIntFloorDivMod(long x, int y, Object divExpected, Object modExpected) {
         testLongIntFloorDiv(x, y, divExpected);
@@ -286,9 +294,8 @@
     }
 
     /**
-     * Test FloorDiv with long arguments against expected value.
-     * The expected value is usually a Long but in some cases  is
-     * an ArithmeticException.
+     * Test FloorDiv with long arguments against expected value. The expected value is usually a
+     * Long but in some cases  is an ArithmeticException.
      *
      * @param x dividend
      * @param y modulus
@@ -302,14 +309,14 @@
 
         Object strict_result = doStrictFloorDiv(x, y);
         if (!resultEquals(strict_result, expected)) {
-            fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+            fail("FAIL: long StrictMath.floorDiv(%d, %d) = %s; expected %s%n", x, y, strict_result,
+                    expected);
         }
     }
 
     /**
-     * Test FloorMod of long arguments against expected value.
-     * The expected value is usually a Long but in some cases  is
-     * an ArithmeticException.
+     * Test FloorMod of long arguments against expected value. The expected value is usually a Long
+     * but in some cases  is an ArithmeticException.
      *
      * @param x dividend
      * @param y modulus
@@ -323,7 +330,8 @@
 
         Object strict_result = doStrictFloorMod(x, y);
         if (!resultEquals(strict_result, expected)) {
-            fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result, expected);
+            fail("FAIL: long StrictMath.floorMod(%d, %d) = %s; expected %s%n", x, y, strict_result,
+                    expected);
         }
 
         try {
@@ -337,7 +345,8 @@
             // long fr = resultD.longValue();
             int fr = resultD.intValue();
             if (!result.equals(fr)) {
-                fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n", x, y, result, fr);
+                fail("FAIL: Long.floorMod(%d, %d) = %d is different than BigDecimal result: %d%n",
+                        x, y, result, fr);
             }
         } catch (ArithmeticException ae) {
             if (y != 0) {
@@ -348,6 +357,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -362,6 +372,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -376,6 +387,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -390,6 +402,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -404,6 +417,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -418,6 +432,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -432,6 +447,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -446,6 +462,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -460,6 +477,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -474,6 +492,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -488,6 +507,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -502,6 +522,7 @@
 
     /**
      * Invoke floorDiv and return the result or any exception.
+     *
      * @param x the x value
      * @param y the y value
      * @return the result Integer or an exception.
@@ -515,10 +536,9 @@
     }
 
     /**
-     * Returns a boolean by comparing the result and the expected value.
-     * The equals method is not defined for ArithmeticException but it is
-     * desirable to have equals return true if the expected and the result
-     * both threw the same exception (class and message.)
+     * Returns a boolean by comparing the result and the expected value. The equals method is not
+     * defined for ArithmeticException but it is desirable to have equals return true if the
+     * expected and the result both threw the same exception (class and message.)
      *
      * @param result the result from testing the method
      * @param expected the expected value
diff --git a/ojluni/src/test/java/lang/Math/DoubleConsts.java b/ojluni/src/test/java/lang/Math/DoubleConsts.java
new file mode 100644
index 0000000..98afdc2
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/DoubleConsts.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * Common library for additional constants of the {@code double} type.
+ */
+public final class DoubleConsts {
+
+    /**
+     * Don't let anyone instantiate this class.
+     */
+    private DoubleConsts() {
+    }
+
+    /**
+     * Bias used in representing a {@code double} exponent.
+     */
+    public static final int EXP_BIAS = jdk.internal.math.DoubleConsts.EXP_BIAS;
+
+    /**
+     * Bit mask to isolate the exponent field of a {@code double}.
+     */
+    public static final long EXP_BIT_MASK = jdk.internal.math.DoubleConsts.EXP_BIT_MASK;
+
+    /**
+     * Bit mask to isolate the sign bit of a {@code double}.
+     */
+    public static final long SIGN_BIT_MASK = jdk.internal.math.DoubleConsts.SIGN_BIT_MASK;
+
+    /**
+     * Bit mask to isolate the significand field of a {@code double}.
+     */
+    public static final long SIGNIF_BIT_MASK = jdk.internal.math.DoubleConsts.SIGNIF_BIT_MASK;
+
+    /**
+     * The number of logical bits in the significand of a {@code double} number, including the
+     * implicit bit.
+     */
+    public static final int SIGNIFICAND_WIDTH = jdk.internal.math.DoubleConsts.SIGNIFICAND_WIDTH;
+
+    /**
+     * The exponent the smallest positive {@code double} subnormal value would have if it could be
+     * normalized.
+     */
+    public static final int MIN_SUB_EXPONENT = jdk.internal.math.DoubleConsts.MIN_SUB_EXPONENT;
+
+    @Test
+    public void testDoubleConstants() {
+        Assert.assertEquals((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK), ~0L);
+        Assert.assertEquals((SIGN_BIT_MASK & EXP_BIT_MASK), 0L);
+        Assert.assertEquals((SIGN_BIT_MASK & SIGNIF_BIT_MASK), 0L);
+        Assert.assertEquals((EXP_BIT_MASK & SIGNIF_BIT_MASK), 0L);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/ExactArithTests.java b/ojluni/src/test/java/lang/Math/ExactArithTests.java
index 3109d41..3b7adbb 100644
--- a/ojluni/src/test/java/lang/Math/ExactArithTests.java
+++ b/ojluni/src/test/java/lang/Math/ExactArithTests.java
@@ -30,18 +30,18 @@
 import static org.testng.Assert.fail;
 
 // Android-changed: Added test annotations, remove main() method.
+
 /**
+ * @author Roger Riggs
  * @test Test for Math.*Exact integer and long methods.
  * @bug 6708398
  * @summary Basic tests for Math exact arithmetic operations.
- *
- * @author Roger Riggs
  */
 public class ExactArithTests {
 
     /**
-     * Test Math.addExact, multiplyExact, subtractExact, toIntValue methods
-     * with {@code int} arguments.
+     * Test Math.addExact, multiplyExact, subtractExact, toIntValue methods with {@code int}
+     * arguments.
      */
     @Test
     public void testIntegerExact() {
@@ -65,9 +65,8 @@
     }
 
     /**
-     * Test exact arithmetic by comparing with the same operations using long
-     * and checking that the result is the same as the integer truncation.
-     * Errors are reported with {@link fail}.
+     * Test exact arithmetic by comparing with the same operations using long and checking that the
+     * result is the same as the integer truncation. Errors are reported with {@link fail}.
      *
      * @param x first parameter
      * @param y second parameter
@@ -78,14 +77,17 @@
             int sum = Math.addExact(x, y);
             long sum2 = (long) x + (long) y;
             if ((int) sum2 != sum2) {
-                fail("FAIL: int Math.addExact(" + x + " + " + y + ") = " + sum + "; expected Arithmetic exception");
+                fail("FAIL: int Math.addExact(" + x + " + " + y + ") = " + sum
+                        + "; expected Arithmetic exception");
             } else if (sum != sum2) {
-                fail("FAIL: long Math.addExact(" + x + " + " + y + ") = " + sum + "; expected: " + sum2);
+                fail("FAIL: long Math.addExact(" + x + " + " + y + ") = " + sum + "; expected: "
+                        + sum2);
             }
         } catch (ArithmeticException ex) {
             long sum2 = (long) x + (long) y;
             if ((int) sum2 == sum2) {
-                fail("FAIL: int Math.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: int Math.addExact(" + x + " + " + y + ")" + "; Unexpected exception: "
+                        + ex);
 
             }
         }
@@ -95,13 +97,15 @@
             int diff = Math.subtractExact(x, y);
             long diff2 = (long) x - (long) y;
             if ((int) diff2 != diff2) {
-                fail("FAIL: int Math.subtractExact(" + x + " - " + y + ") = " + diff + "; expected: " + diff2);
+                fail("FAIL: int Math.subtractExact(" + x + " - " + y + ") = " + diff
+                        + "; expected: " + diff2);
             }
 
         } catch (ArithmeticException ex) {
             long diff2 = (long) x - (long) y;
             if ((int) diff2 == diff2) {
-                fail("FAIL: int Math.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: int Math.subtractExact(" + x + " - " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
@@ -110,12 +114,14 @@
             int product = Math.multiplyExact(x, y);
             long m2 = (long) x * (long) y;
             if ((int) m2 != m2) {
-                fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ") = " + product + "; expected: " + m2);
+                fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ") = " + product
+                        + "; expected: " + m2);
             }
         } catch (ArithmeticException ex) {
             long m2 = (long) x * (long) y;
             if ((int) m2 == m2) {
-                fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
@@ -124,7 +130,8 @@
             int inc = Math.incrementExact(x);
             long inc2 = (long) x + 1L;
             if ((int) inc2 != inc2) {
-                fail("FAIL: int Math.incrementExact(" + x + ") = " + inc + "; expected Arithmetic exception");
+                fail("FAIL: int Math.incrementExact(" + x + ") = " + inc
+                        + "; expected Arithmetic exception");
             } else if (inc != inc2) {
                 fail("FAIL: long Math.incrementExact(" + x + ") = " + inc + "; expected: " + inc2);
             }
@@ -141,7 +148,8 @@
             int dec = Math.decrementExact(x);
             long dec2 = (long) x - 1L;
             if ((int) dec2 != dec2) {
-                fail("FAIL: int Math.decrementExact(" + x + ") = " + dec + "; expected Arithmetic exception");
+                fail("FAIL: int Math.decrementExact(" + x + ") = " + dec
+                        + "; expected Arithmetic exception");
             } else if (dec != dec2) {
                 fail("FAIL: long Math.decrementExact(" + x + ") = " + dec + "; expected: " + dec2);
             }
@@ -156,9 +164,10 @@
         try {
             // Test negateExact
             int neg = Math.negateExact(x);
-            long neg2 = -((long)x) ;
+            long neg2 = -((long) x);
             if ((int) neg2 != neg2) {
-                fail("FAIL: int Math.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception");
+                fail("FAIL: int Math.negateExact(" + x + ") = " + neg
+                        + "; expected Arithmetic exception");
             } else if (neg != neg2) {
                 fail("FAIL: long Math.negateExact(" + x + ") = " + neg + "; expected: " + neg2);
             }
@@ -172,8 +181,8 @@
     }
 
     /**
-     * Test Math.addExact, multiplyExact, subtractExact, toIntExact methods
-     * with {@code long} arguments.
+     * Test Math.addExact, multiplyExact, subtractExact, toIntExact methods with {@code long}
+     * arguments.
      */
     @Test
     static void testLongExact() {
@@ -192,23 +201,20 @@
         testLongExactTwice(Long.MAX_VALUE, -1);
         testLongExactTwice(Long.MIN_VALUE, -2);
         testLongExactTwice(Long.MAX_VALUE, -2);
-        testLongExactTwice(Long.MIN_VALUE/2, 2);
+        testLongExactTwice(Long.MIN_VALUE / 2, 2);
         testLongExactTwice(Long.MAX_VALUE, 2);
         testLongExactTwice(Integer.MAX_VALUE, Integer.MAX_VALUE);
         testLongExactTwice(Integer.MAX_VALUE, -Integer.MAX_VALUE);
-        testLongExactTwice(Integer.MAX_VALUE+1, Integer.MAX_VALUE+1);
-        testLongExactTwice(Integer.MAX_VALUE+1, -Integer.MAX_VALUE+1);
-        testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
-        testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
-        testLongExactTwice(Integer.MIN_VALUE/2, 2);
+        testLongExactTwice(Integer.MAX_VALUE + 1, Integer.MAX_VALUE + 1);
+        testLongExactTwice(Integer.MAX_VALUE + 1, -Integer.MAX_VALUE + 1);
+        testLongExactTwice(Integer.MIN_VALUE - 1, Integer.MIN_VALUE - 1);
+        testLongExactTwice(Integer.MIN_VALUE - 1, -Integer.MIN_VALUE - 1);
+        testLongExactTwice(Integer.MIN_VALUE / 2, 2);
 
     }
 
     /**
-     * Test each of the exact operations with the arguments and
-     * with the arguments reversed.
-     * @param x
-     * @param y
+     * Test each of the exact operations with the arguments and with the arguments reversed.
      */
     static void testLongExactTwice(long x, long y) {
         testLongExact(x, y);
@@ -217,9 +223,9 @@
 
 
     /**
-     * Test long exact arithmetic by comparing with the same operations using BigInteger
-     * and checking that the result is the same as the long truncation.
-     * Errors are reported with {@link fail}.
+     * Test long exact arithmetic by comparing with the same operations using BigInteger and
+     * checking that the result is the same as the long truncation. Errors are reported with {@link
+     * fail}.
      *
      * @param x first parameter
      * @param y second parameter
@@ -235,7 +241,8 @@
             checkResult("long Math.addExact", x, y, sum, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long Math.addExact(" + x + " + " + y + "); Unexpected exception: " + ex);
+                fail("FAIL: long Math.addExact(" + x + " + " + y + "); Unexpected exception: "
+                        + ex);
             }
         }
 
@@ -246,7 +253,8 @@
             checkResult("long Math.subtractExact", x, y, diff, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long Math.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: long Math.subtractExact(" + x + " - " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
@@ -257,7 +265,8 @@
             checkResult("long Math.multiplyExact", x, y, product, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
@@ -297,8 +306,9 @@
         try {
             // Test toIntExact
             int value = Math.toIntExact(x);
-            if ((long)value != x) {
-                fail("FAIL: " + "long Math.toIntExact" + "(" + x + ") = " + value + "; expected an arithmetic exception: ");
+            if ((long) value != x) {
+                fail("FAIL: " + "long Math.toIntExact" + "(" + x + ") = " + value
+                        + "; expected an arithmetic exception: ");
             }
         } catch (ArithmeticException ex) {
             if (resultBig.bitLength() <= 32) {
@@ -310,6 +320,7 @@
 
     /**
      * Compare the expected and actual results.
+     *
      * @param message message for the error
      * @param x first argument
      * @param y second argument
@@ -319,15 +330,17 @@
     static void checkResult(String message, long x, long y, long result, BigInteger expected) {
         BigInteger resultBig = BigInteger.valueOf(result);
         if (!inLongRange(expected)) {
-            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected an arithmetic exception: ");
+            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result
+                    + "; expected an arithmetic exception: ");
         } else if (!resultBig.equals(expected)) {
-            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected " + expected);
+            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected "
+                    + expected);
         }
     }
 
     /**
      * Check if the value fits in 64 bits (a long).
-     * @param value
+     *
      * @return true if the value fits in 64 bits (including the sign).
      */
     static boolean inLongRange(BigInteger value) {
@@ -335,8 +348,7 @@
     }
 
     /**
-     * Test Math.multiplyExact method with {@code long} and {@code int}
-     * arguments.
+     * Test Math.multiplyExact method with {@code long} and {@code int} arguments.
      */
     @Test
     static void testLongIntExact() {
@@ -355,21 +367,21 @@
         testLongIntExact(Long.MAX_VALUE, -1);
         testLongIntExact(Long.MIN_VALUE, -2);
         testLongIntExact(Long.MAX_VALUE, -2);
-        testLongIntExact(Long.MIN_VALUE/2, 2);
+        testLongIntExact(Long.MIN_VALUE / 2, 2);
         testLongIntExact(Long.MAX_VALUE, 2);
         testLongIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
         testLongIntExact(Integer.MAX_VALUE, -Integer.MAX_VALUE);
-        testLongIntExact((long)Integer.MAX_VALUE+1L, Integer.MAX_VALUE);
-        testLongIntExact((long)Integer.MAX_VALUE+1L, -Integer.MAX_VALUE+1);
-        testLongIntExact((long)Integer.MIN_VALUE-1L, Integer.MIN_VALUE);
-        testLongIntExact((long)Integer.MIN_VALUE-1, Integer.MAX_VALUE);
-        testLongIntExact(Integer.MIN_VALUE/2, 2);
+        testLongIntExact((long) Integer.MAX_VALUE + 1L, Integer.MAX_VALUE);
+        testLongIntExact((long) Integer.MAX_VALUE + 1L, -Integer.MAX_VALUE + 1);
+        testLongIntExact((long) Integer.MIN_VALUE - 1L, Integer.MIN_VALUE);
+        testLongIntExact((long) Integer.MIN_VALUE - 1, Integer.MAX_VALUE);
+        testLongIntExact(Integer.MIN_VALUE / 2, 2);
     }
 
     /**
-     * Test long-int exact arithmetic by comparing with the same operations using BigInteger
-     * and checking that the result is the same as the long truncation.
-     * Errors are reported with {@link fail}.
+     * Test long-int exact arithmetic by comparing with the same operations using BigInteger and
+     * checking that the result is the same as the long truncation. Errors are reported with {@link
+     * fail}.
      *
      * @param x first parameter
      * @param y second parameter
@@ -386,7 +398,8 @@
             checkResult("long Math.multiplyExact", x, y, product, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: long Math.multiplyExact(" + x + " * " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
     }
diff --git a/ojluni/src/test/java/lang/Math/ExpCornerCaseTests.java b/ojluni/src/test/java/lang/Math/ExpCornerCaseTests.java
new file mode 100644
index 0000000..d9a8fbd
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/ExpCornerCaseTests.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011,2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8255368
+ * @summary Tests corner cases of Math.exp
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ExpCornerCaseTests {
+
+    private ExpCornerCaseTests() {
+    }
+
+    @Test
+    public void testExpCornerCases() {
+        double[][] testCases = {
+                {+0x4.0p8, Double.POSITIVE_INFINITY},
+                {+0x2.71p12, Double.POSITIVE_INFINITY},
+        };
+
+        for (double[] testCase : testCases) {
+            testExp(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testExp(double input, double expected) {
+        Tests.test("StrictMath.exp", input, StrictMath.exp(input), expected);
+        Tests.test("Math.exp", input, Math.exp(input), expected);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/Expm1Tests.java b/ojluni/src/test/java/lang/Math/Expm1Tests.java
new file mode 100644
index 0000000..9c9248d
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/Expm1Tests.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4851638 4900189 4939441
+ * @summary Tests for {Math, StrictMath}.expm1
+ * @author Joseph D. Darcy
+ */
+
+/*
+ * The Taylor expansion of expxm1(x) = exp(x) -1 is
+ *
+ * 1 + x/1! + x^2/2! + x^3/3| + ... -1 =
+ *
+ * x + x^2/2! + x^3/3 + ...
+ *
+ * Therefore, for small values of x, expxm1 ~= x.
+ *
+ * For large values of x, expxm1(x) ~= exp(x)
+ *
+ * For large negative x, expxm1(x) ~= -1.
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class Expm1Tests {
+
+    private Expm1Tests() {
+    }
+
+    static final double infinityD = Double.POSITIVE_INFINITY;
+    static final double NaNd = Double.NaN;
+
+    @Test
+    public void testExpm1() {
+        double[][] testCases = {
+                {Double.NaN, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
+                {infinityD, infinityD},
+                {-infinityD, -1.0},
+                {-0.0, -0.0},
+                {+0.0, +0.0},
+        };
+
+        // Test special cases
+        for (double[] testCase : testCases) {
+            testExpm1CaseWithUlpDiff(testCase[0], testCase[1], 0, null);
+        }
+
+        // For |x| < 2^-54 expm1(x) ~= x
+        for (int i = DoubleConsts.MIN_SUB_EXPONENT; i <= -54; i++) {
+            double d = Math.scalb(2, i);
+            testExpm1Case(d, d);
+            testExpm1Case(-d, -d);
+        }
+
+        // For values of y where exp(y) > 2^54, expm1(x) ~= exp(x).
+        // The least such y is ln(2^54) ~= 37.42994775023705; exp(x)
+        // overflows for x > ~= 709.8
+
+        // Use a 2-ulp error threshold to account for errors in the
+        // exp implementation; the increments of d in the loop will be
+        // exact.
+        for (double d = 37.5; d <= 709.5; d += 1.0) {
+            testExpm1CaseWithUlpDiff(d, StrictMath.exp(d), 2, null);
+        }
+
+        // For x > 710, expm1(x) should be infinity
+        for (int i = 10; i <= Double.MAX_EXPONENT; i++) {
+            double d = Math.scalb(2, i);
+            testExpm1Case(d, infinityD);
+        }
+
+        // By monotonicity, once the limit is reached, the
+        // implementation should return the limit for all smaller
+        // values.
+        boolean[] reachedLimit = {false, false};
+
+        // Once exp(y) < 0.5 * ulp(1), expm1(y) ~= -1.0;
+        // The greatest such y is ln(2^-53) ~= -36.7368005696771.
+        for (double d = -36.75; d >= -127.75; d -= 1.0) {
+            testExpm1CaseWithUlpDiff(d, -1.0, 1, reachedLimit);
+        }
+
+        for (int i = 7; i <= Double.MAX_EXPONENT; i++) {
+            double d = -Math.scalb(2, i);
+            testExpm1CaseWithUlpDiff(d, -1.0, 1, reachedLimit);
+        }
+
+        // Test for monotonicity failures near multiples of log(2).
+        // Test two numbers before and two numbers after each chosen
+        // value; i.e.
+        //
+        // pcNeighbors[] =
+        // {nextDown(nextDown(pc)),
+        // nextDown(pc),
+        // pc,
+        // nextUp(pc),
+        // nextUp(nextUp(pc))}
+        //
+        // and we test that expm1(pcNeighbors[i]) <= expm1(pcNeighbors[i+1])
+        {
+            double[] pcNeighbors = new double[5];
+            double[] pcNeighborsExpm1 = new double[5];
+            double[] pcNeighborsStrictExpm1 = new double[5];
+
+            for (int i = -50; i <= 50; i++) {
+                double pc = StrictMath.log(2) * i;
+
+                pcNeighbors[2] = pc;
+                pcNeighbors[1] = Math.nextDown(pc);
+                pcNeighbors[0] = Math.nextDown(pcNeighbors[1]);
+                pcNeighbors[3] = Math.nextUp(pc);
+                pcNeighbors[4] = Math.nextUp(pcNeighbors[3]);
+
+                for (int j = 0; j < pcNeighbors.length; j++) {
+                    pcNeighborsExpm1[j] = Math.expm1(pcNeighbors[j]);
+                    pcNeighborsStrictExpm1[j] = StrictMath.expm1(pcNeighbors[j]);
+                }
+
+                for (int j = 0; j < pcNeighborsExpm1.length - 1; j++) {
+                    if (pcNeighborsExpm1[j] > pcNeighborsExpm1[j + 1]) {
+                        Assert.fail("Monotonicity failure for Math.expm1 on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsExpm1[j] + " and " +
+                                pcNeighborsExpm1[j + 1]);
+                    }
+
+                    if (pcNeighborsStrictExpm1[j] > pcNeighborsStrictExpm1[j + 1]) {
+                        Assert.fail("Monotonicity failure for StrictMath.expm1 on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsStrictExpm1[j] + " and " +
+                                pcNeighborsStrictExpm1[j + 1]);
+                    }
+
+
+                }
+
+            }
+        }
+    }
+
+    public static int testExpm1Case(double input,
+            double expected) {
+        return testExpm1CaseWithUlpDiff(input, expected, 1, null);
+    }
+
+    public static int testExpm1CaseWithUlpDiff(double input,
+            double expected,
+            double ulps,
+            boolean[] reachedLimit) {
+        int failures = 0;
+        double mathUlps = ulps, strictUlps = ulps;
+        double mathOutput;
+        double strictOutput;
+
+        if (reachedLimit != null) {
+            if (reachedLimit[0]) {
+                mathUlps = 0;
+            }
+
+            if (reachedLimit[1]) {
+                strictUlps = 0;
+            }
+        }
+
+        Tests.testUlpDiffWithLowerBound("Math.expm1(double)",
+                input, mathOutput = Math.expm1(input),
+                expected, mathUlps, -1.0);
+        Tests.testUlpDiffWithLowerBound("StrictMath.expm1(double)",
+                input, strictOutput = StrictMath.expm1(input),
+                expected, strictUlps, -1.0);
+        if (reachedLimit != null) {
+            reachedLimit[0] |= (mathOutput == -1.0);
+            reachedLimit[1] |= (strictOutput == -1.0);
+        }
+
+        return failures;
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/FloatConsts.java b/ojluni/src/test/java/lang/Math/FloatConsts.java
new file mode 100644
index 0000000..0502b65
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/FloatConsts.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * Common library for additional constants of the {@code float} type.
+ */
+public final class FloatConsts {
+
+    /**
+     * Don't let anyone instantiate this class.
+     */
+    private FloatConsts() {
+    }
+
+    /**
+     * Bias used in representing a {@code float} exponent.
+     */
+    public static final int EXP_BIAS = jdk.internal.math.FloatConsts.EXP_BIAS;
+
+    /**
+     * Bit mask to isolate the exponent field of a {@code float}.
+     */
+    public static final int EXP_BIT_MASK = jdk.internal.math.FloatConsts.EXP_BIT_MASK;
+
+    /**
+     * Bit mask to isolate the sign bit of a {@code float}.
+     */
+    public static final int SIGN_BIT_MASK = jdk.internal.math.FloatConsts.SIGN_BIT_MASK;
+
+    /**
+     * Bit mask to isolate the significand field of a {@code float}.
+     */
+    public static final int SIGNIF_BIT_MASK = jdk.internal.math.FloatConsts.SIGNIF_BIT_MASK;
+
+    /**
+     * The number of logical bits in the significand of a {@code float} number, including the
+     * implicit bit.
+     */
+    public static final int SIGNIFICAND_WIDTH = jdk.internal.math.FloatConsts.SIGNIFICAND_WIDTH;
+
+    /**
+     * The exponent the smallest positive {@code float} subnormal value would have if it could be
+     * normalized.
+     */
+    public static final int MIN_SUB_EXPONENT = jdk.internal.math.FloatConsts.MIN_SUB_EXPONENT;
+
+    @Test
+    public void testFloatConstants() {
+        Assert.assertEquals((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK), ~0);
+        Assert.assertEquals((SIGN_BIT_MASK & EXP_BIT_MASK), 0);
+        Assert.assertEquals((SIGN_BIT_MASK & SIGNIF_BIT_MASK), 0);
+        Assert.assertEquals((EXP_BIT_MASK & SIGNIF_BIT_MASK), 0);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/FusedMultiplyAddTests.java b/ojluni/src/test/java/lang/Math/FusedMultiplyAddTests.java
new file mode 100644
index 0000000..30d6889
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/FusedMultiplyAddTests.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4851642 8253409
+ * @summary Tests for Math.fusedMac and StrictMath.fusedMac.
+ * @build Tests
+ * @build FusedMultiplyAddTests
+ * @run main FusedMultiplyAddTests
+ * @run main/othervm -XX:-UseFMA FusedMultiplyAddTests
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * The specifications for both Math.fusedMac and StrictMath.fusedMac are the same and both are
+ * exactly specified. Therefore, both methods are tested in this file.
+ */
+
+public class FusedMultiplyAddTests {
+
+    private FusedMultiplyAddTests() {
+    }
+
+    private static final double Infinity = Double.POSITIVE_INFINITY;
+    private static final float InfinityF = Float.POSITIVE_INFINITY;
+    private static final double NaN = Double.NaN;
+    private static final float NaNf = Float.NaN;
+
+    @Test
+    public void testNonFiniteD() {
+        double[][] testCases = {
+                {Infinity, Infinity, Infinity,
+                        Infinity,
+                },
+
+                {-Infinity, Infinity, -Infinity,
+                        -Infinity,
+                },
+
+                {-Infinity, Infinity, Infinity,
+                        NaN,
+                },
+
+                {Infinity, Infinity, -Infinity,
+                        NaN,
+                },
+
+                {1.0, Infinity, 2.0,
+                        Infinity,
+                },
+
+                {1.0, 2.0, Infinity,
+                        Infinity,
+                },
+
+                {Infinity, 1.0, Infinity,
+                        Infinity,
+                },
+
+                {Double.MAX_VALUE, 2.0, -Infinity,
+                        -Infinity},
+
+                {Infinity, 1.0, -Infinity,
+                        NaN,
+                },
+
+                {-Infinity, 1.0, Infinity,
+                        NaN,
+                },
+
+                {1.0, NaN, 2.0,
+                        NaN,
+                },
+
+                {1.0, 2.0, NaN,
+                        NaN,
+                },
+
+                {Infinity, 2.0, NaN,
+                        NaN,
+                },
+
+                {NaN, 2.0, Infinity,
+                        NaN,
+                },
+        };
+
+        for (double[] testCase : testCases) {
+            testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]);
+        }
+    }
+
+    @Test
+    public void testZeroesD() {
+        double[][] testCases = {
+                {+0.0, +0.0, +0.0,
+                        +0.0,
+                },
+
+                {-0.0, +0.0, +0.0,
+                        +0.0,
+                },
+
+                {+0.0, +0.0, -0.0,
+                        +0.0,
+                },
+
+                {+0.0, +0.0, -0.0,
+                        +0.0,
+                },
+
+                {-0.0, +0.0, -0.0,
+                        -0.0,
+                },
+
+                {-0.0, -0.0, -0.0,
+                        +0.0,
+                },
+
+                {-1.0, +0.0, -0.0,
+                        -0.0,
+                },
+
+                {-1.0, +0.0, +0.0,
+                        +0.0,
+                },
+
+                {-2.0, +0.0, -0.0,
+                        -0.0,
+                },
+
+                {-2.0, +0.0, +0.0,
+                        +0.0,
+                },
+        };
+
+        for (double[] testCase : testCases) {
+            testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]);
+        }
+    }
+
+    @Test
+    public void testSimpleD() {
+        double[][] testCases = {
+                {1.0, 2.0, 3.0,
+                        5.0,},
+
+                {1.0, 2.0, -2.0,
+                        0.0,},
+
+                {5.0, 5.0, -25.0,
+                        0.0,},
+
+                {Double.MAX_VALUE, 2.0, -Double.MAX_VALUE,
+                        Double.MAX_VALUE},
+
+                {Double.MAX_VALUE, 2.0, 1.0,
+                        Infinity},
+
+                {Double.MIN_VALUE, -Double.MIN_VALUE, +0.0,
+                        -0.0},
+
+                {Double.MIN_VALUE, -Double.MIN_VALUE, -0.0,
+                        -0.0},
+
+                {Double.MIN_VALUE, Double.MIN_VALUE, +0.0,
+                        +0.0},
+
+                {Double.MIN_VALUE, Double.MIN_VALUE, -0.0,
+                        +0.0},
+
+                {Double.MIN_VALUE, +0.0, -0.0,
+                        +0.0},
+
+                {Double.MIN_VALUE, -0.0, -0.0,
+                        -0.0},
+
+                {Double.MIN_VALUE, +0.0, +0.0,
+                        +0.0},
+
+                {Double.MIN_VALUE, -0.0, +0.0,
+                        +0.0},
+
+                {1.0 + Math.ulp(1.0), 1.0 + Math.ulp(1.0), -1.0 - 2.0 * Math.ulp(1.0),
+                        Math.ulp(1.0) * Math.ulp(1.0)},
+        };
+
+        for (double[] testCase : testCases) {
+            testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]);
+        }
+    }
+
+    @Test
+    public void testNonFiniteF() {
+        float[][] testCases = {
+                {1.0f, InfinityF, 2.0f,
+                        InfinityF,
+                },
+
+                {1.0f, 2.0f, InfinityF,
+                        InfinityF,
+                },
+
+                {InfinityF, 1.0f, InfinityF,
+                        InfinityF,
+                },
+
+                {Float.MAX_VALUE, 2.0f, -InfinityF,
+                        -InfinityF},
+
+                {InfinityF, 1.0f, -InfinityF,
+                        NaNf,
+                },
+
+                {-InfinityF, 1.0f, InfinityF,
+                        NaNf,
+                },
+
+                {1.0f, NaNf, 2.0f,
+                        NaNf,
+                },
+
+                {1.0f, 2.0f, NaNf,
+                        NaNf,
+                },
+
+                {InfinityF, 2.0f, NaNf,
+                        NaNf,
+                },
+
+                {NaNf, 2.0f, InfinityF,
+                        NaNf,
+                },
+        };
+
+        for (float[] testCase : testCases) {
+            testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]);
+        }
+    }
+
+    @Test
+    public void testZeroesF() {
+        float[][] testCases = {
+                {+0.0f, +0.0f, +0.0f,
+                        +0.0f,
+                },
+
+                {-0.0f, +0.0f, +0.0f,
+                        +0.0f,
+                },
+
+                {+0.0f, +0.0f, -0.0f,
+                        +0.0f,
+                },
+
+                {+0.0f, +0.0f, -0.0f,
+                        +0.0f,
+                },
+
+                {-0.0f, +0.0f, -0.0f,
+                        -0.0f,
+                },
+
+                {-0.0f, -0.0f, -0.0f,
+                        +0.0f,
+                },
+
+                {-1.0f, +0.0f, -0.0f,
+                        -0.0f,
+                },
+
+                {-1.0f, +0.0f, +0.0f,
+                        +0.0f,
+                },
+
+                {-2.0f, +0.0f, -0.0f,
+                        -0.0f,
+                },
+        };
+
+        for (float[] testCase : testCases) {
+            testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]);
+        }
+    }
+
+    @Test
+    public void testSimpleF() {
+        float[][] testCases = {
+                {1.0f, 2.0f, 3.0f,
+                        5.0f,},
+
+                {1.0f, 2.0f, -2.0f,
+                        0.0f,},
+
+                {5.0f, 5.0f, -25.0f,
+                        0.0f,},
+
+                {Float.MAX_VALUE, 2.0f, -Float.MAX_VALUE,
+                        Float.MAX_VALUE},
+
+                {Float.MAX_VALUE, 2.0f, 1.0f,
+                        InfinityF},
+
+                {1.0f + Math.ulp(1.0f), 1.0f + Math.ulp(1.0f), -1.0f - 2.0f * Math.ulp(1.0f),
+                        Math.ulp(1.0f) * Math.ulp(1.0f)},
+
+                // Double-rounding if done in double precision
+                {0x1.fffffep23f, 0x1.000004p28f, 0x1.fep5f, 0x1.000002p52f}
+        };
+
+        for (float[] testCase : testCases) {
+            testFusedMacCase(testCase[0], testCase[1], testCase[2], testCase[3]);
+        }
+    }
+
+
+    private static void testFusedMacCase(double input1, double input2, double input3,
+            double expected) {
+        Tests.test("Math.fma(double)", input1, input2, input3,
+                Math.fma(input1, input2, input3), expected);
+        Tests.test("StrictMath.fma(double)", input1, input2, input3,
+                               StrictMath.fma(input1, input2, input3), expected);
+
+        // Permute first two inputs
+        Tests.test("Math.fma(double)", input2, input1, input3,
+                Math.fma(input2, input1, input3), expected);
+        Tests.test("StrictMath.fma(double)", input2, input1, input3,
+                               StrictMath.fma(input2, input1, input3), expected);
+    }
+
+    private static void testFusedMacCase(float input1, float input2, float input3, float expected) {
+        Tests.test("Math.fma(float)", input1, input2, input3,
+                Math.fma(input1, input2, input3), expected);
+        Tests.test("StrictMath.fma(float)", input1, input2, input3,
+                               StrictMath.fma(input1, input2, input3), expected);
+
+        // Permute first two inputs
+        Tests.test("Math.fma(float)", input2, input1, input3,
+                Math.fma(input2, input1, input3), expected);
+        Tests.test("StrictMath.fma(float)", input2, input1, input3,
+                               StrictMath.fma(input2, input1, input3), expected);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/HyperbolicTests.java b/ojluni/src/test/java/lang/Math/HyperbolicTests.java
new file mode 100644
index 0000000..f59138f
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/HyperbolicTests.java
@@ -0,0 +1,1017 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4851625 4900189 4939441
+ * @summary Tests for {Math, StrictMath}.{sinh, cosh, tanh}
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class HyperbolicTests {
+
+    private HyperbolicTests() {
+    }
+
+    static final double NaNd = Double.NaN;
+
+    /**
+     * Test accuracy of {Math, StrictMath}.sinh.  The specified accuracy is 2.5 ulps.
+     *
+     * The definition of sinh(x) is
+     *
+     * (e^x - e^(-x))/2
+     *
+     * The series expansion of sinh(x) =
+     *
+     * x + x^3/3! + x^5/5! + x^7/7! +...
+     *
+     * Therefore,
+     *
+     * 1. For large values of x sinh(x) ~= signum(x)*exp(|x|)/2
+     *
+     * 2. For small values of x, sinh(x) ~= x.
+     *
+     * Additionally, sinh is an odd function; sinh(-x) = -sinh(x).
+     */
+    @Test
+    public void testSinh() {
+        /*
+         * Array elements below generated using a quad sinh
+         * implementation.  Rounded to a double, the quad result
+         * *should* be correctly rounded, unless we are quite unlucky.
+         * Assuming the quad value is a correctly rounded double, the
+         * allowed error is 3.0 ulps instead of 2.5 since the quad
+         * value rounded to double can have its own 1/2 ulp error.
+         */
+        double[][] testCases = {
+                // x                sinh(x)
+                {0.0625, 0.06254069805219182172183988501029229},
+                {0.1250, 0.12532577524111545698205754229137154},
+                {0.1875, 0.18860056562029018382047025055167585},
+                {0.2500, 0.25261231680816830791412515054205787},
+                {0.3125, 0.31761115611357728583959867611490292},
+                {0.3750, 0.38385106791361456875429567642050245},
+                {0.4375, 0.45159088610312053032509815226723017},
+                {0.5000, 0.52109530549374736162242562641149155},
+                {0.5625, 0.59263591611468777373870867338492247},
+                {0.6250, 0.66649226445661608227260655608302908},
+                {0.6875, 0.74295294580567543571442036910465007},
+                {0.7500, 0.82231673193582998070366163444691386},
+                {0.8125, 0.90489373856606433650504536421491368},
+                {0.8750, 0.99100663714429475605317427568995231},
+                {0.9375, 1.08099191569306394011007867453992548},
+                {1.0000, 1.17520119364380145688238185059560082},
+                {1.0625, 1.27400259579739321279181130344911907},
+                {1.1250, 1.37778219077984075760379987065228373},
+                {1.1875, 1.48694549961380717221109202361777593},
+                {1.2500, 1.60191908030082563790283030151221415},
+                {1.3125, 1.72315219460596010219069206464391528},
+                {1.3750, 1.85111856355791532419998548438506416},
+                {1.4375, 1.98631821852425112898943304217629457},
+                {1.5000, 2.12927945509481749683438749467763195},
+                {1.5625, 2.28056089740825247058075476705718764},
+                {1.6250, 2.44075368098794353221372986997161132},
+                {1.6875, 2.61048376261693140366028569794027603},
+                {1.7500, 2.79041436627764265509289122308816092},
+                {1.8125, 2.98124857471401377943765253243875520},
+                {1.8750, 3.18373207674259205101326780071803724},
+                {1.9375, 3.39865608104779099764440244167531810},
+                {2.0000, 3.62686040784701876766821398280126192},
+                {2.0625, 3.86923677050642806693938384073620450},
+                {2.1250, 4.12673225993027252260441410537905269},
+                {2.1875, 4.40035304533919660406976249684469164},
+                {2.2500, 4.69116830589833069188357567763552003},
+                {2.3125, 5.00031440855811351554075363240262157},
+                {2.3750, 5.32899934843284576394645856548481489},
+                {2.4375, 5.67850746906785056212578751630266858},
+                {2.5000, 6.05020448103978732145032363835040319},
+                {2.5625, 6.44554279850040875063706020260185553},
+                {2.6250, 6.86606721451642172826145238779845813},
+                {2.6875, 7.31342093738196587585692115636603571},
+                {2.7500, 7.78935201149073201875513401029935330},
+                {2.8125, 8.29572014785741787167717932988491961},
+                {2.8750, 8.83450399097893197351853322827892144},
+                {2.9375, 9.40780885043076394429977972921690859},
+                {3.0000, 10.01787492740990189897459361946582867},
+                {3.0625, 10.66708606836969224165124519209968368},
+                {3.1250, 11.35797907995166028304704128775698426},
+                {3.1875, 12.09325364161259019614431093344260209},
+                {3.2500, 12.87578285468067003959660391705481220},
+                {3.3125, 13.70862446906136798063935858393686525},
+                {3.3750, 14.59503283146163690015482636921657975},
+                {3.4375, 15.53847160182039311025096666980558478},
+                {3.5000, 16.54262728763499762495673152901249743},
+                {3.5625, 17.61142364906941482858466494889121694},
+                {3.6250, 18.74903703113232171399165788088277979},
+                {3.6875, 19.95991268283598684128844120984214675},
+                {3.7500, 21.24878212710338697364101071825171163},
+                {3.8125, 22.62068164929685091969259499078125023},
+                {3.8750, 24.08097197661255803883403419733891573},
+                {3.9375, 25.63535922523855307175060244757748997},
+                {4.0000, 27.28991719712775244890827159079382096},
+                {4.0625, 29.05111111351106713777825462100160185},
+                {4.1250, 30.92582287788986031725487699744107092},
+                {4.1875, 32.92137796722343190618721270937061472},
+                {4.2500, 35.04557405638942942322929652461901154},
+                {4.3125, 37.30671148776788628118833357170042385},
+                {4.3750, 39.71362570500944929025069048612806024},
+                {4.4375, 42.27572177772344954814418332587050658},
+                {4.5000, 45.00301115199178562180965680564371424},
+                {4.5625, 47.90615077031205065685078058248081891},
+                {4.6250, 50.99648471383193131253995134526177467},
+                {4.6875, 54.28608852959281437757368957713936555},
+                {4.7500, 57.78781641599226874961859781628591635},
+                {4.8125, 61.51535145084362283008545918273109379},
+                {4.8750, 65.48325905829987165560146562921543361},
+                {4.9375, 69.70704392356508084094318094283346381},
+                {5.0000, 74.20321057778875897700947199606456364},
+                {5.0625, 78.98932788987998983462810080907521151},
+                {5.1250, 84.08409771724448958901392613147384951},
+                {5.1875, 89.50742798369883598816307922895346849},
+                {5.2500, 95.28051047011540739630959111303975956},
+                {5.3125, 101.42590362176666730633859252034238987},
+                {5.3750, 107.96762069594029162704530843962700133},
+                {5.4375, 114.93122359426386042048760580590182604},
+                {5.5000, 122.34392274639096192409774240457730721},
+                {5.5625, 130.23468343534638291488502321709913206},
+                {5.6250, 138.63433897999898233879574111119546728},
+                {5.6875, 147.57571121692522056519568264304815790},
+                {5.7500, 157.09373875244884423880085377625986165},
+                {5.8125, 167.22561348600435888568183143777868662},
+                {5.8750, 178.01092593829229887752609866133883987},
+                {5.9375, 189.49181995209921964640216682906501778},
+                {6.0000, 201.71315737027922812498206768797872263},
+                {6.0625, 214.72269333437984291483666459592578915},
+                {6.1250, 228.57126288889537420461281285729970085},
+                {6.1875, 243.31297962030799867970551767086092471},
+                {6.2500, 259.00544710710289911522315435345489966},
+                {6.3125, 275.70998400700299790136562219920451185},
+                {6.3750, 293.49186366095654566861661249898332253},
+                {6.4375, 312.42056915013535342987623229485223434},
+                {6.5000, 332.57006480258443156075705566965111346},
+                {6.5625, 354.01908521044116928437570109827956007},
+                {6.6250, 376.85144288706511933454985188849781703},
+                {6.6875, 401.15635576625530823119100750634165252},
+                {6.7500, 427.02879582326538080306830640235938517},
+                {6.8125, 454.56986017986077163530945733572724452},
+                {6.8750, 483.88716614351897894746751705315210621},
+                {6.9375, 515.09527172439720070161654727225752288},
+                {7.0000, 548.31612327324652237375611757601851598},
+                {7.0625, 583.67953198942753384680988096024373270},
+                {7.1250, 621.32368116099280160364794462812762880},
+                {7.1875, 661.39566611888784148449430491465857519},
+                {7.2500, 704.05206901515336623551137120663358760},
+                {7.3125, 749.45957067108712382864538206200700256},
+                {7.3750, 797.79560188617531521347351754559776282},
+                {7.4375, 849.24903675279739482863565789325699416},
+                {7.5000, 904.02093068584652953510919038935849651},
+                {7.5625, 962.32530605113249628368993221570636328},
+                {7.6250, 1024.38998846242707559349318193113614698},
+                {7.6875, 1090.45749701500081956792547346904792325},
+                {7.7500, 1160.78599193425808533255719118417856088},
+                {7.8125, 1235.65028334242796895820912936318532502},
+                {7.8750, 1315.34290508508890654067255740428824014},
+                {7.9375, 1400.17525781352742299995139486063802583},
+                {8.0000, 1490.47882578955018611587663903188144796},
+                {8.0625, 1586.60647216744061169450001100145859236},
+                {8.1250, 1688.93381781440241350635231605477507900},
+                {8.1875, 1797.86070905726094477721128358866360644},
+                {8.2500, 1913.81278009067446281883262689250118009},
+                {8.3125, 2037.24311615199935553277163192983440062},
+                {8.3750, 2168.63402396170125867037749369723761636},
+                {8.4375, 2308.49891634734644432370720900969004306},
+                {8.5000, 2457.38431841538268239359965370719928775},
+                {8.5625, 2615.87200310986940554256648824234335262},
+                {8.6250, 2784.58126450289932429469130598902487336},
+                {8.6875, 2964.17133769964321637973459949999057146},
+                {8.7500, 3155.34397481384944060352507473513108710},
+                {8.8125, 3358.84618707947841898217318996045550438},
+                {8.8750, 3575.47316381333288862617411467285480067},
+                {8.9375, 3806.07137963459383403903729660349293583},
+                {9.0000, 4051.54190208278996051522359589803425598},
+                {9.0625, 4312.84391255878980330955246931164633615},
+                {9.1250, 4590.99845434696991399363282718106006883},
+                {9.1875, 4887.09242236403719571363798584676797558},
+                {9.2500, 5202.28281022453561319352901552085348309},
+                {9.3125, 5537.80123121853803935727335892054791265},
+                {9.3750, 5894.95873086734181634245918412592155656},
+                {9.4375, 6275.15090986233399457103055108344546942},
+                {9.5000, 6679.86337740502119410058225086262108741},
+                {9.5625, 7110.67755625726876329967852256934334025},
+                {9.6250, 7569.27686218510919585241049433331592115},
+                {9.6875, 8057.45328194243077504648484392156371121},
+                {9.7500, 8577.11437549816065709098061006273039092},
+                {9.8125, 9130.29072986829727910801024120918114778},
+                {9.8750, 9719.14389367880274015504995181862860062},
+                {9.9375, 10345.97482346383208590278839409938269134},
+                {10.0000, 11013.23287470339337723652455484636420303},
+        };
+
+        for (double[] testCase : testCases) {
+            testSinhCaseWithUlpDiff(testCase[0], testCase[1], 3.0);
+        }
+
+        double[][] specialTestCases = {
+                {0.0, 0.0},
+                {NaNd, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
+                {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}
+        };
+
+        for (double[] specialTestCase : specialTestCases) {
+            testSinhCaseWithUlpDiff(specialTestCase[0], specialTestCase[1], 0.0);
+        }
+
+        // For powers of 2 less than 2^(-27), the second and
+        // subsequent terms of the Taylor series expansion will get
+        // rounded away since |n-n^3| > 53, the binary precision of a
+        // double significand.
+
+        for (int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) {
+            double d = Math.scalb(2.0, i);
+
+            // Result and expected are the same.
+            testSinhCaseWithUlpDiff(d, d, 2.5);
+        }
+
+        // For values of x larger than 22, the e^(-x) term is
+        // insignificant to the floating-point result.  Util exp(x)
+        // overflows around 709.8, sinh(x) ~= exp(x)/2; will will test
+        // 10000 values in this range.
+
+        long trans22 = Double.doubleToLongBits(22.0);
+        // (approximately) largest value such that exp shouldn't
+        // overflow
+        long transExpOvfl = Double.doubleToLongBits(Math.nextDown(709.7827128933841));
+
+        for (long i = trans22;
+                i < transExpOvfl;
+                i += (transExpOvfl - trans22) / 10000) {
+
+            double d = Double.longBitsToDouble(i);
+
+            // Allow 3.5 ulps of error to deal with error in exp.
+            testSinhCaseWithUlpDiff(d, StrictMath.exp(d) * 0.5, 3.5);
+        }
+
+        // (approximately) largest value such that sinh shouldn't
+        // overflow.
+        long transSinhOvfl = Double.doubleToLongBits(710.4758600739439);
+
+        // Make sure sinh(x) doesn't overflow as soon as exp(x)
+        // overflows.
+
+        /*
+         * For large values of x, sinh(x) ~= 0.5*(e^x).  Therefore,
+         *
+         * sinh(x) ~= e^(ln 0.5) * e^x = e^(x + ln 0.5)
+         *
+         * So, we can calculate the approximate expected result as
+         * exp(x + -0.693147186).  However, this sum suffers from
+         * roundoff, limiting the accuracy of the approximation.  The
+         * accuracy can be improved by recovering the rounded-off
+         * information.  Since x is larger than ln(0.5), the trailing
+         * bits of ln(0.5) get rounded away when the two values are
+         * added.  However, high-order bits of ln(0.5) that
+         * contribute to the sum can be found:
+         *
+         * offset = log(0.5);
+         * effective_offset = (x + offset) - x; // exact subtraction
+         * rounded_away_offset = offset - effective_offset; // exact subtraction
+         *
+         * Therefore, the product
+         *
+         * exp(x + offset)*exp(rounded_away_offset)
+         *
+         * will be a better approximation to the exact value of
+         *
+         * e^(x + offset)
+         *
+         * than exp(x+offset) alone.  (The expected result cannot be
+         * computed as exp(x)*exp(offset) since exp(x) by itself would
+         * overflow to infinity.)
+         */
+        double offset = StrictMath.log(0.5);
+        for (long i = transExpOvfl + 1; i < transSinhOvfl;
+                i += (transSinhOvfl - transExpOvfl) / 1000) {
+            double input = Double.longBitsToDouble(i);
+
+            double expected =
+                    StrictMath.exp(input + offset) *
+                            StrictMath.exp(offset - ((input + offset) - input));
+
+            testSinhCaseWithUlpDiff(input, expected, 4.0);
+        }
+
+        // sinh(x) overflows for values greater than 710; in
+        // particular, it overflows for all 2^i, i > 10.
+        for (int i = 10; i <= Double.MAX_EXPONENT; i++) {
+            double d = Math.scalb(2.0, i);
+
+            // Result and expected are the same.
+            testSinhCaseWithUlpDiff(d, Double.POSITIVE_INFINITY, 0.0);
+        }
+    }
+
+    public static int testSinhCaseWithTolerance(double input,
+            double expected,
+            double tolerance) {
+        int failures = 0;
+        Tests.testTolerance("Math.sinh(double)",
+                input, Math.sinh(input),
+                expected, tolerance);
+        Tests.testTolerance("Math.sinh(double)",
+                -input, Math.sinh(-input),
+                -expected, tolerance);
+
+        Tests.testTolerance("StrictMath.sinh(double)",
+                input, StrictMath.sinh(input),
+                expected, tolerance);
+        Tests.testTolerance("StrictMath.sinh(double)",
+                -input, StrictMath.sinh(-input),
+                -expected, tolerance);
+        return failures;
+    }
+
+    public static void testSinhCaseWithUlpDiff(double input,
+            double expected,
+            double ulps) {
+        int failures = 0;
+        Tests.testUlpDiff("Math.sinh(double)",
+                input, Math.sinh(input),
+                expected, ulps);
+        Tests.testUlpDiff("Math.sinh(double)",
+                -input, Math.sinh(-input),
+                -expected, ulps);
+
+        Tests.testUlpDiff("StrictMath.sinh(double)",
+                input, StrictMath.sinh(input),
+                expected, ulps);
+        Tests.testUlpDiff("StrictMath.sinh(double)",
+                -input, StrictMath.sinh(-input),
+                -expected, ulps);
+    }
+
+
+    /**
+     * Test accuracy of {Math, StrictMath}.cosh.  The specified accuracy is 2.5 ulps.
+     *
+     * The definition of cosh(x) is
+     *
+     * (e^x + e^(-x))/2
+     *
+     * The series expansion of cosh(x) =
+     *
+     * 1 + x^2/2! + x^4/4! + x^6/6! +...
+     *
+     * Therefore,
+     *
+     * 1. For large values of x cosh(x) ~= exp(|x|)/2
+     *
+     * 2. For small values of x, cosh(x) ~= 1.
+     *
+     * Additionally, cosh is an even function; cosh(-x) = cosh(x).
+     */
+    @Test
+    public void testCosh() {
+        /*
+         * Array elements below generated using a quad cosh
+         * implementation.  Rounded to a double, the quad result
+         * *should* be correctly rounded, unless we are quite unlucky.
+         * Assuming the quad value is a correctly rounded double, the
+         * allowed error is 3.0 ulps instead of 2.5 since the quad
+         * value rounded to double can have its own 1/2 ulp error.
+         */
+        double[][] testCases = {
+                // x                cosh(x)
+                {0.0625, 1.001953760865667607841550709632597376},
+                {0.1250, 1.007822677825710859846949685520422223},
+                {0.1875, 1.017629683800690526835115759894757615},
+                {0.2500, 1.031413099879573176159295417520378622},
+                {0.3125, 1.049226785060219076999158096606305793},
+                {0.3750, 1.071140346704586767299498015567016002},
+                {0.4375, 1.097239412531012567673453832328262160},
+                {0.5000, 1.127625965206380785226225161402672030},
+                {0.5625, 1.162418740845610783505338363214045218},
+                {0.6250, 1.201753692975606324229229064105075301},
+                {0.6875, 1.245784523776616395403056980542275175},
+                {0.7500, 1.294683284676844687841708185390181730},
+                {0.8125, 1.348641048647144208352285714214372703},
+                {0.8750, 1.407868656822803158638471458026344506},
+                {0.9375, 1.472597542369862933336886403008640891},
+                {1.0000, 1.543080634815243778477905620757061497},
+                {1.0625, 1.619593348374367728682469968448090763},
+                {1.1250, 1.702434658138190487400868008124755757},
+                {1.1875, 1.791928268324866464246665745956119612},
+                {1.2500, 1.888423877161015738227715728160051696},
+                {1.3125, 1.992298543335143985091891077551921106},
+                {1.3750, 2.103958159362661802010972984204389619},
+                {1.4375, 2.223839037619709260803023946704272699},
+                {1.5000, 2.352409615243247325767667965441644201},
+                {1.5625, 2.490172284559350293104864895029231913},
+                {1.6250, 2.637665356192137582275019088061812951},
+                {1.6875, 2.795465162524235691253423614360562624},
+                {1.7500, 2.964188309728087781773608481754531801},
+                {1.8125, 3.144494087167972176411236052303565201},
+                {1.8750, 3.337087043587520514308832278928116525},
+                {1.9375, 3.542719740149244276729383650503145346},
+                {2.0000, 3.762195691083631459562213477773746099},
+                {2.0625, 3.996372503438463642260225717607554880},
+                {2.1250, 4.246165228196992140600291052990934410},
+                {2.1875, 4.512549935859540340856119781585096760},
+                {2.2500, 4.796567530460195028666793366876218854},
+                {2.3125, 5.099327816921939817643745917141739051},
+                {2.3750, 5.422013837643509250646323138888569746},
+                {2.4375, 5.765886495263270945949271410819116399},
+                {2.5000, 6.132289479663686116619852312817562517},
+                {2.5625, 6.522654518468725462969589397439224177},
+                {2.6250, 6.938506971550673190999796241172117288},
+                {2.6875, 7.381471791406976069645686221095397137},
+                {2.7500, 7.853279872697439591457564035857305647},
+                {2.8125, 8.355774815752725814638234943192709129},
+                {2.8750, 8.890920130482709321824793617157134961},
+                {2.9375, 9.460806908834119747071078865866737196},
+                {3.0000, 10.067661995777765841953936035115890343},
+                {3.0625, 10.713856690753651225304006562698007312},
+                {3.1250, 11.401916013575067700373788969458446177},
+                {3.1875, 12.134528570998387744547733730974713055},
+                {3.2500, 12.914557062512392049483503752322408761},
+                {3.3125, 13.745049466398732213877084541992751273},
+                {3.3750, 14.629250949773302934853381428660210721},
+                {3.4375, 15.570616549147269180921654324879141947},
+                {3.5000, 16.572824671057316125696517821376119469},
+                {3.5625, 17.639791465519127930722105721028711044},
+                {3.6250, 18.775686128468677200079039891415789429},
+                {3.6875, 19.984947192985946987799359614758598457},
+                {3.7500, 21.272299872959396081877161903352144126},
+                {3.8125, 22.642774526961913363958587775566619798},
+                {3.8750, 24.101726314486257781049388094955970560},
+                {3.9375, 25.654856121347151067170940701379544221},
+                {4.0000, 27.308232836016486629201989612067059978},
+                {4.0625, 29.068317063936918520135334110824828950},
+                {4.1250, 30.941986372478026192360480044849306606},
+                {4.1875, 32.936562165180269851350626768308756303},
+                {4.2500, 35.059838290298428678502583470475012235},
+                {4.3125, 37.320111495433027109832850313172338419},
+                {4.3750, 39.726213847251883288518263854094284091},
+                {4.4375, 42.287547242982546165696077854963452084},
+                {4.5000, 45.014120148530027928305799939930642658},
+                {4.5625, 47.916586706774825161786212701923307169},
+                {4.6250, 51.006288368867753140854830589583165950},
+                {4.6875, 54.295298211196782516984520211780624960},
+                {4.7500, 57.796468111195389383795669320243166117},
+                {4.8125, 61.523478966332915041549750463563672435},
+                {4.8750, 65.490894152518731617237739112888213645},
+                {4.9375, 69.714216430810089539924900313140922323},
+                {5.0000, 74.209948524787844444106108044487704798},
+                {5.0625, 78.995657605307475581204965926043112946},
+                {5.1250, 84.090043934600961683400343038519519678},
+                {5.1875, 89.513013937957834087706670952561002466},
+                {5.2500, 95.285757988514588780586084642381131013},
+                {5.3125, 101.430833209098212357990123684449846912},
+                {5.3750, 107.972251614673824873137995865940755392},
+                {5.4375, 114.935573939814969189535554289886848550},
+                {5.5000, 122.348009517829425991091207107262038316},
+                {5.5625, 130.238522601820409078244923165746295574},
+                {5.6250, 138.637945543134998069351279801575968875},
+                {5.6875, 147.579099269447055276899288971207106581},
+                {5.7500, 157.096921533245353905868840194264636395},
+                {5.8125, 167.228603431860671946045256541679445836},
+                {5.8750, 178.013734732486824390148614309727161925},
+                {5.9375, 189.494458570056311567917444025807275896},
+                {6.0000, 201.715636122455894483405112855409538488},
+                {6.0625, 214.725021906554080628430756558271312513},
+                {6.1250, 228.573450380013557089736092321068279231},
+                {6.1875, 243.315034578039208138752165587134488645},
+                {6.2500, 259.007377561239126824465367865430519592},
+                {6.3125, 275.711797500835732516530131577254654076},
+                {6.3750, 293.493567280752348242602902925987643443},
+                {6.4375, 312.422169552825597994104814531010579387},
+                {6.5000, 332.571568241777409133204438572983297292},
+                {6.5625, 354.020497560858198165985214519757890505},
+                {6.6250, 376.852769667496146326030849450983914197},
+                {6.6875, 401.157602161123700280816957271992998156},
+                {6.7500, 427.029966702886171977469256622451185850},
+                {6.8125, 454.570960119471524953536004647195906721},
+                {6.8750, 483.888199441157626584508920036981010995},
+                {6.9375, 515.096242417696720610477570797503766179},
+                {7.0000, 548.317035155212076889964120712102928484},
+                {7.0625, 583.680388623257719787307547662358502345},
+                {7.1250, 621.324485894002926216918634755431456031},
+                {7.1875, 661.396422095589629755266517362992812037},
+                {7.2500, 704.052779189542208784574955807004218856},
+                {7.3125, 749.460237818184878095966335081928645934},
+                {7.3750, 797.796228612873763671070863694973560629},
+                {7.4375, 849.249625508044731271830060572510241864},
+                {7.5000, 904.021483770216677368692292389446994987},
+                {7.5625, 962.325825625814651122171697031114091993},
+                {7.6250, 1024.390476557670599008492465853663578558},
+                {7.6875, 1090.457955538048482588540574008226583335},
+                {7.7500, 1160.786422676798661020094043586456606003},
+                {7.8125, 1235.650687987597295222707689125107720568},
+                {7.8750, 1315.343285214046776004329388551335841550},
+                {7.9375, 1400.175614911635999247504386054087931958},
+                {8.0000, 1490.479161252178088627715460421007179728},
+                {8.0625, 1586.606787305415349050508956232945539108},
+                {8.1250, 1688.934113859132470361718199038326340668},
+                {8.1875, 1797.860987165547537276364148450577336075},
+                {8.2500, 1913.813041349231764486365114317586148767},
+                {8.3125, 2037.243361581700856522236313401822532385},
+                {8.3750, 2168.634254521568851112005905503069409349},
+                {8.4375, 2308.499132938297821208734949028296170563},
+                {8.5000, 2457.384521883751693037774022640629666294},
+                {8.5625, 2615.872194250713123494312356053193077854},
+                {8.6250, 2784.581444063104750127653362960649823247},
+                {8.6875, 2964.171506380845754878370650565756538203},
+                {8.7500, 3155.344133275174556354775488913749659006},
+                {8.8125, 3358.846335940117183452010789979584950102},
+                {8.8750, 3575.473303654961482727206202358956274888},
+                {8.9375, 3806.071511003646460448021740303914939059},
+                {9.0000, 4051.542025492594047194773093534725371440},
+                {9.0625, 4312.844028491571841588188869958240355518},
+                {9.1250, 4590.998563255739769060078863130940205710},
+                {9.1875, 4887.092524674358252509551443117048351290},
+                {9.2500, 5202.282906336187674588222835339193136030},
+                {9.3125, 5537.801321507079474415176386655744387251},
+                {9.3750, 5894.958815685577062811620236195525504885},
+                {9.4375, 6275.150989541692149890530417987358096221},
+                {9.5000, 6679.863452256851081801173722051940058824},
+                {9.5625, 7110.677626574055535297758456126491707647},
+                {9.6250, 7569.276928241617224537226019600213961572},
+                {9.6875, 8057.453343996777301036241026375049070162},
+                {9.7500, 8577.114433792824387959788368429252257664},
+                {9.8125, 9130.290784631065880205118262838330689429},
+                {9.8750, 9719.143945123662919857326995631317996715},
+                {9.9375, 10345.974871791805753327922796701684092861},
+                {10.0000, 11013.232920103323139721376090437880844591},
+        };
+
+        for (double[] testCase : testCases) {
+            testCoshCaseWithUlpDiff(testCase[0], testCase[1], 3.0);
+        }
+
+        double[][] specialTestCases = {
+                {0.0, 1.0},
+                {NaNd, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
+                {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY}
+        };
+
+        for (double[] specialTestCase : specialTestCases) {
+            testCoshCaseWithUlpDiff(specialTestCase[0], specialTestCase[1], 0.0);
+        }
+
+        // For powers of 2 less than 2^(-27), the second and
+        // subsequent terms of the Taylor series expansion will get
+        // rounded.
+
+        for (int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) {
+            double d = Math.scalb(2.0, i);
+
+            // Result and expected are the same.
+            testCoshCaseWithUlpDiff(d, 1.0, 2.5);
+        }
+
+        // For values of x larger than 22, the e^(-x) term is
+        // insignificant to the floating-point result.  Util exp(x)
+        // overflows around 709.8, cosh(x) ~= exp(x)/2; will will test
+        // 10000 values in this range.
+
+        long trans22 = Double.doubleToLongBits(22.0);
+        // (approximately) largest value such that exp shouldn't
+        // overflow
+        long transExpOvfl = Double.doubleToLongBits(Math.nextDown(709.7827128933841));
+
+        for (long i = trans22;
+                i < transExpOvfl;
+                i += (transExpOvfl - trans22) / 10000) {
+
+            double d = Double.longBitsToDouble(i);
+
+            // Allow 3.5 ulps of error to deal with error in exp.
+            testCoshCaseWithUlpDiff(d, StrictMath.exp(d) * 0.5, 3.5);
+        }
+
+        // (approximately) largest value such that cosh shouldn't
+        // overflow.
+        long transCoshOvfl = Double.doubleToLongBits(710.4758600739439);
+
+        // Make sure sinh(x) doesn't overflow as soon as exp(x)
+        // overflows.
+
+        /*
+         * For large values of x, cosh(x) ~= 0.5*(e^x).  Therefore,
+         *
+         * cosh(x) ~= e^(ln 0.5) * e^x = e^(x + ln 0.5)
+         *
+         * So, we can calculate the approximate expected result as
+         * exp(x + -0.693147186).  However, this sum suffers from
+         * roundoff, limiting the accuracy of the approximation.  The
+         * accuracy can be improved by recovering the rounded-off
+         * information.  Since x is larger than ln(0.5), the trailing
+         * bits of ln(0.5) get rounded away when the two values are
+         * added.  However, high-order bits of ln(0.5) that
+         * contribute to the sum can be found:
+         *
+         * offset = log(0.5);
+         * effective_offset = (x + offset) - x; // exact subtraction
+         * rounded_away_offset = offset - effective_offset; // exact subtraction
+         *
+         * Therefore, the product
+         *
+         * exp(x + offset)*exp(rounded_away_offset)
+         *
+         * will be a better approximation to the exact value of
+         *
+         * e^(x + offset)
+         *
+         * than exp(x+offset) alone.  (The expected result cannot be
+         * computed as exp(x)*exp(offset) since exp(x) by itself would
+         * overflow to infinity.)
+         */
+        double offset = StrictMath.log(0.5);
+        for (long i = transExpOvfl + 1; i < transCoshOvfl;
+                i += (transCoshOvfl - transExpOvfl) / 1000) {
+            double input = Double.longBitsToDouble(i);
+
+            double expected =
+                    StrictMath.exp(input + offset) *
+                            StrictMath.exp(offset - ((input + offset) - input));
+
+            testCoshCaseWithUlpDiff(input, expected, 4.0);
+        }
+
+        // cosh(x) overflows for values greater than 710; in
+        // particular, it overflows for all 2^i, i > 10.
+        for (int i = 10; i <= Double.MAX_EXPONENT; i++) {
+            double d = Math.scalb(2.0, i);
+
+            // Result and expected are the same.
+            testCoshCaseWithUlpDiff(d, Double.POSITIVE_INFINITY, 0.0);
+        }
+    }
+
+    public static int testCoshCaseWithTolerance(double input,
+            double expected,
+            double tolerance) {
+        int failures = 0;
+        Tests.testTolerance("Math.cosh(double)",
+                input, Math.cosh(input),
+                expected, tolerance);
+        Tests.testTolerance("Math.cosh(double)",
+                -input, Math.cosh(-input),
+                expected, tolerance);
+
+        Tests.testTolerance("StrictMath.cosh(double)",
+                input, StrictMath.cosh(input),
+                expected, tolerance);
+        Tests.testTolerance("StrictMath.cosh(double)",
+                -input, StrictMath.cosh(-input),
+                expected, tolerance);
+        return failures;
+    }
+
+    public static void testCoshCaseWithUlpDiff(double input,
+            double expected,
+            double ulps) {
+        int failures = 0;
+        Tests.testUlpDiff("Math.cosh(double)",
+                input, Math.cosh(input),
+                expected, ulps);
+        Tests.testUlpDiff("Math.cosh(double)",
+                -input, Math.cosh(-input),
+                expected, ulps);
+
+        Tests.testUlpDiff("StrictMath.cosh(double)",
+                input, StrictMath.cosh(input),
+                expected, ulps);
+        Tests.testUlpDiff("StrictMath.cosh(double)",
+                -input, StrictMath.cosh(-input),
+                expected, ulps);
+    }
+
+
+    /**
+     * Test accuracy of {Math, StrictMath}.tanh.  The specified accuracy is 2.5 ulps.
+     *
+     * The definition of tanh(x) is
+     *
+     * (e^x - e^(-x))/(e^x + e^(-x))
+     *
+     * The series expansion of tanh(x) =
+     *
+     * x - x^3/3 + 2x^5/15 - 17x^7/315 + ...
+     *
+     * Therefore,
+     *
+     * 1. For large values of x tanh(x) ~= signum(x)
+     *
+     * 2. For small values of x, tanh(x) ~= x.
+     *
+     * Additionally, tanh is an odd function; tanh(-x) = -tanh(x).
+     */
+    @Test
+    public void testTanh() {
+        /*
+         * Array elements below generated using a quad sinh
+         * implementation.  Rounded to a double, the quad result
+         * *should* be correctly rounded, unless we are quite unlucky.
+         * Assuming the quad value is a correctly rounded double, the
+         * allowed error is 3.0 ulps instead of 2.5 since the quad
+         * value rounded to double can have its own 1/2 ulp error.
+         */
+        double[][] testCases = {
+                // x                tanh(x)
+                {0.0625, 0.06241874674751251449014289119421133},
+                {0.1250, 0.12435300177159620805464727580589271},
+                {0.1875, 0.18533319990813951753211997502482787},
+                {0.2500, 0.24491866240370912927780113149101697},
+                {0.3125, 0.30270972933210848724239738970991712},
+                {0.3750, 0.35835739835078594631936023155315807},
+                {0.4375, 0.41157005567402245143207555859415687},
+                {0.5000, 0.46211715726000975850231848364367256},
+                {0.5625, 0.50982997373525658248931213507053130},
+                {0.6250, 0.55459972234938229399903909532308371},
+                {0.6875, 0.59637355547924233984437303950726939},
+                {0.7500, 0.63514895238728731921443435731249638},
+                {0.8125, 0.67096707420687367394810954721913358},
+                {0.8750, 0.70390560393662106058763026963135371},
+                {0.9375, 0.73407151960434149263991588052503660},
+                {1.0000, 0.76159415595576488811945828260479366},
+                {1.0625, 0.78661881210869761781941794647736081},
+                {1.1250, 0.80930107020178101206077047354332696},
+                {1.1875, 0.82980190998595952708572559629034476},
+                {1.2500, 0.84828363995751289761338764670750445},
+                {1.3125, 0.86490661772074179125443141102709751},
+                {1.3750, 0.87982669965198475596055310881018259},
+                {1.4375, 0.89319334040035153149249598745889365},
+                {1.5000, 0.90514825364486643824230369645649557},
+                {1.5625, 0.91582454416876231820084311814416443},
+                {1.6250, 0.92534622531174107960457166792300374},
+                {1.6875, 0.93382804322259173763570528576138652},
+                {1.7500, 0.94137553849728736226942088377163687},
+                {1.8125, 0.94808528560440629971240651310180052},
+                {1.8750, 0.95404526017994877009219222661968285},
+                {1.9375, 0.95933529331468249183399461756952555},
+                {2.0000, 0.96402758007581688394641372410092317},
+                {2.0625, 0.96818721657637057702714316097855370},
+                {2.1250, 0.97187274591350905151254495374870401},
+                {2.1875, 0.97513669829362836159665586901156483},
+                {2.2500, 0.97802611473881363992272924300618321},
+                {2.3125, 0.98058304703705186541999427134482061},
+                {2.3750, 0.98284502917257603002353801620158861},
+                {2.4375, 0.98484551746427837912703608465407824},
+                {2.5000, 0.98661429815143028888127603923734964},
+                {2.5625, 0.98817786228751240824802592958012269},
+                {2.6250, 0.98955974861288320579361709496051109},
+                {2.6875, 0.99078085564125158320311117560719312},
+                {2.7500, 0.99185972456820774534967078914285035},
+                {2.8125, 0.99281279483715982021711715899682324},
+                {2.8750, 0.99365463431502962099607366282699651},
+                {2.9375, 0.99439814606575805343721743822723671},
+                {3.0000, 0.99505475368673045133188018525548849},
+                {3.0625, 0.99563456710930963835715538507891736},
+                {3.1250, 0.99614653067334504917102591131792951},
+                {3.1875, 0.99659855517712942451966113109487039},
+                {3.2500, 0.99699763548652601693227592643957226},
+                {3.3125, 0.99734995516557367804571991063376923},
+                {3.3750, 0.99766097946988897037219469409451602},
+                {3.4375, 0.99793553792649036103161966894686844},
+                {3.5000, 0.99817789761119870928427335245061171},
+                {3.5625, 0.99839182812874152902001617480606320},
+                {3.6250, 0.99858065920179882368897879066418294},
+                {3.6875, 0.99874733168378115962760304582965538},
+                {3.7500, 0.99889444272615280096784208280487888},
+                {3.8125, 0.99902428575443546808677966295308778},
+                {3.8750, 0.99913888583735077016137617231569011},
+                {3.9375, 0.99924003097049627100651907919688313},
+                {4.0000, 0.99932929973906704379224334434172499},
+                {4.0625, 0.99940808577297384603818654530731215},
+                {4.1250, 0.99947761936180856115470576756499454},
+                {4.1875, 0.99953898655601372055527046497863955},
+                {4.2500, 0.99959314604388958696521068958989891},
+                {4.3125, 0.99964094406130644525586201091350343},
+                {4.3750, 0.99968312756179494813069349082306235},
+                {4.4375, 0.99972035584870534179601447812936151},
+                {4.5000, 0.99975321084802753654050617379050162},
+                {4.5625, 0.99978220617994689112771768489030236},
+                {4.6250, 0.99980779516900105210240981251048167},
+                {4.6875, 0.99983037791655283849546303868853396},
+                {4.7500, 0.99985030754497877753787358852000255},
+                {4.8125, 0.99986789571029070417475400133989992},
+                {4.8750, 0.99988341746867772271011794614780441},
+                {4.9375, 0.99989711557251558205051185882773206},
+                {5.0000, 0.99990920426259513121099044753447306},
+                {5.0625, 0.99991987261554158551063867262784721},
+                {5.1250, 0.99992928749851651137225712249720606},
+                {5.1875, 0.99993759617721206697530526661105307},
+                {5.2500, 0.99994492861777083305830639416802036},
+                {5.3125, 0.99995139951851344080105352145538345},
+                {5.3750, 0.99995711010315817210152906092289064},
+                {5.4375, 0.99996214970350792531554669737676253},
+                {5.5000, 0.99996659715630380963848952941756868},
+                {5.5625, 0.99997052203605101013786592945475432},
+                {5.6250, 0.99997398574306704793434088941484766},
+                {5.6875, 0.99997704246374583929961850444364696},
+                {5.7500, 0.99997974001803825215761760428815437},
+                {5.8125, 0.99998212060739040166557477723121777},
+                {5.8750, 0.99998422147482750993344503195672517},
+                {5.9375, 0.99998607548749972326220227464612338},
+                {6.0000, 0.99998771165079557056434885235523206},
+                {6.0625, 0.99998915556205996764518917496149338},
+                {6.1250, 0.99999042981101021976277974520745310},
+                {6.1875, 0.99999155433311068015449574811497719},
+                {6.2500, 0.99999254672143162687722782398104276},
+                {6.3125, 0.99999342250186907900400800240980139},
+                {6.3750, 0.99999419537602957780612639767025158},
+                {6.4375, 0.99999487743557848265406225515388994},
+                {6.5000, 0.99999547935140419285107893831698753},
+                {6.5625, 0.99999601054055694588617385671796346},
+                {6.6250, 0.99999647931357331502887600387959900},
+                {6.6875, 0.99999689300449080997594368612277442},
+                {6.7500, 0.99999725808558628431084200832778748},
+                {6.8125, 0.99999758026863294516387464046135924},
+                {6.8750, 0.99999786459425991170635407313276785},
+                {6.9375, 0.99999811551081218572759991597586905},
+                {7.0000, 0.99999833694394467173571641595066708},
+                {7.0625, 0.99999853235803894918375164252059190},
+                {7.1250, 0.99999870481040359014665019356422927},
+                {7.1875, 0.99999885699910593255108365463415411},
+                {7.2500, 0.99999899130518359709674536482047025},
+                {7.3125, 0.99999910982989611769943303422227663},
+                {7.3750, 0.99999921442759946591163427422888252},
+                {7.4375, 0.99999930673475777603853435094943258},
+                {7.5000, 0.99999938819554614875054970643513124},
+                {7.5625, 0.99999946008444508183970109263856958},
+                {7.6250, 0.99999952352618001331402589096040117},
+                {7.6875, 0.99999957951331792817413683491979752},
+                {7.7500, 0.99999962892179632633374697389145081},
+                {7.8125, 0.99999967252462750190604116210421169},
+                {7.8750, 0.99999971100399253750324718031574484},
+                {7.9375, 0.99999974496191422474977283863588658},
+                {8.0000, 0.99999977492967588981001883295636840},
+                {8.0625, 0.99999980137613348259726597081723424},
+                {8.1250, 0.99999982471505097353529823063673263},
+                {8.1875, 0.99999984531157382142423402736529911},
+                {8.2500, 0.99999986348794179107425910499030547},
+                {8.3125, 0.99999987952853049895833839645847571},
+                {8.3750, 0.99999989368430056302584289932834041},
+                {8.4375, 0.99999990617672396471542088609051728},
+                {8.5000, 0.99999991720124905211338798152800748},
+                {8.5625, 0.99999992693035839516545287745322387},
+                {8.6250, 0.99999993551626733394129009365703767},
+                {8.6875, 0.99999994309330543951799157347876934},
+                {8.7500, 0.99999994978001814614368429416607424},
+                {8.8125, 0.99999995568102143535399207289008504},
+                {8.8750, 0.99999996088863858914831986187674522},
+                {8.9375, 0.99999996548434461974481685677429908},
+                {9.0000, 0.99999996954004097447930211118358244},
+                {9.0625, 0.99999997311918045901919121395899372},
+                {9.1250, 0.99999997627775997868467948564005257},
+                {9.1875, 0.99999997906519662964368381583648379},
+                {9.2500, 0.99999998152510084671976114264303159},
+                {9.3125, 0.99999998369595870397054673668361266},
+                {9.3750, 0.99999998561173404286033236040150950},
+                {9.4375, 0.99999998730239984852716512979473289},
+                {9.5000, 0.99999998879440718770812040917618843},
+                {9.5625, 0.99999999011109904501789298212541698},
+                {9.6250, 0.99999999127307553219220251303121960},
+                {9.6875, 0.99999999229851618412119275358396363},
+                {9.7500, 0.99999999320346438410630581726217930},
+                {9.8125, 0.99999999400207836827291739324060736},
+                {9.8750, 0.99999999470685273619047001387577653},
+                {9.9375, 0.99999999532881393331131526966058758},
+                {10.0000, 0.99999999587769276361959283713827574},
+        };
+
+        for (double[] testCase : testCases) {
+            testTanhCaseWithUlpDiff(testCase[0], testCase[1], 3.0);
+        }
+
+        double[][] specialTestCases = {
+                {0.0, 0.0},
+                {NaNd, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
+                {Double.POSITIVE_INFINITY, 1.0}
+        };
+
+        for (double[] specialTestCase : specialTestCases) {
+            testTanhCaseWithUlpDiff(specialTestCase[0], specialTestCase[1], 0.0);
+        }
+
+        // For powers of 2 less than 2^(-27), the second and
+        // subsequent terms of the Taylor series expansion will get
+        // rounded away since |n-n^3| > 53, the binary precision of a
+        // double significand.
+
+        for (int i = DoubleConsts.MIN_SUB_EXPONENT; i < -27; i++) {
+            double d = Math.scalb(2.0, i);
+
+            // Result and expected are the same.
+            testTanhCaseWithUlpDiff(d, d, 2.5);
+        }
+
+        // For values of x larger than 22, tanh(x) is 1.0 in double
+        // floating-point arithmetic.
+
+        for (int i = 22; i < 32; i++) {
+            testTanhCaseWithUlpDiff(i, 1.0, 2.5);
+        }
+
+        for (int i = 5; i <= Double.MAX_EXPONENT; i++) {
+            double d = Math.scalb(2.0, i);
+
+            testTanhCaseWithUlpDiff(d, 1.0, 2.5);
+        }
+    }
+
+    public static int testTanhCaseWithTolerance(double input,
+            double expected,
+            double tolerance) {
+        int failures = 0;
+        Tests.testTolerance("Math.tanh(double",
+                input, Math.tanh(input),
+                expected, tolerance);
+        Tests.testTolerance("Math.tanh(double",
+                -input, Math.tanh(-input),
+                -expected, tolerance);
+
+        Tests.testTolerance("StrictMath.tanh(double",
+                input, StrictMath.tanh(input),
+                expected, tolerance);
+        Tests.testTolerance("StrictMath.tanh(double",
+                -input, StrictMath.tanh(-input),
+                -expected, tolerance);
+        return failures;
+    }
+
+    public static void testTanhCaseWithUlpDiff(double input,
+            double expected,
+            double ulps) {
+        Tests.testUlpDiffWithAbsBound("Math.tanh(double)",
+                input, Math.tanh(input),
+                expected, ulps, 1.0);
+        Tests.testUlpDiffWithAbsBound("Math.tanh(double)",
+                -input, Math.tanh(-input),
+                -expected, ulps, 1.0);
+
+        Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)",
+                input, StrictMath.tanh(input),
+                expected, ulps, 1.0);
+        Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)",
+                -input, StrictMath.tanh(-input),
+                -expected, ulps, 1.0);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/HypotTests.java b/ojluni/src/test/java/lang/Math/HypotTests.java
new file mode 100644
index 0000000..5623891
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/HypotTests.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main HypotTests
+ * @bug 4851638 4939441 8078672
+ * @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed)
+ * @author Joseph D. Darcy
+ * @key randomness
+ */
+package test.java.lang.Math;
+
+import java.util.Random;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class HypotTests {
+
+    private HypotTests() {
+    }
+
+    static final double infinityD = Double.POSITIVE_INFINITY;
+    static final double NaNd = Double.NaN;
+
+    /**
+     * Given integers m and n, assuming m < n, the triple (n^2 - m^2, 2mn, and n^2 + m^2) is a
+     * Pythagorean triple with a^2 + b^2 = c^2.  This methods returns a long array holding the
+     * Pythagorean triple corresponding to the inputs.
+     */
+    static long[] pythagoreanTriple(int m, int n) {
+        long M = m;
+        long N = n;
+        long result[] = new long[3];
+
+        result[0] = Math.abs(M * M - N * N);
+        result[1] = Math.abs(2 * M * N);
+        result[2] = Math.abs(M * M + N * N);
+
+        return result;
+    }
+
+    @Test
+    public void testHypot() {
+        double[][] testCases = {
+                // Special cases
+                {infinityD, infinityD, infinityD},
+                {infinityD, 0.0, infinityD},
+                {infinityD, 1.0, infinityD},
+                {infinityD, NaNd, infinityD},
+                {NaNd, NaNd, NaNd},
+                {0.0, NaNd, NaNd},
+                {1.0, NaNd, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), 1.0, NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), 1.0, NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), 1.0, NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), 1.0, NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), 1.0, NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), 1.0, NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), 1.0, NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), 1.0, NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), 1.0, NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), 1.0, NaNd},
+        };
+
+        for (double[] testCase : testCases) {
+            testHypotCase(testCase[0], testCase[1], testCase[2]);
+        }
+
+        // Verify hypot(x, 0.0) is close to x over the entire exponent
+        // range.
+        for (int i = DoubleConsts.MIN_SUB_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
+            double input = Math.scalb(2, i);
+            testHypotCase(input, 0.0, input);
+        }
+
+        // Test Pythagorean triples
+
+        // Small ones
+        for (int m = 1; m < 10; m++) {
+            for (int n = m + 1; n < 11; n++) {
+                long[] result = pythagoreanTriple(m, n);
+                testHypotCase(result[0], result[1], result[2]);
+            }
+        }
+
+        // Big ones
+        // Android-changed: reduce test run time testing every 5th of original
+        // for (int m = 100000; m < 100100; m++) {
+        for (int m = 100000; m < 100100; m += 5) {
+            // Android-changed: reduce test run time testing every 1000th of original
+            // for (int n = m + 100000; n < 200200; n++) {
+            for (int n = m + 100000; n < 200200; n += 1000) {
+                long[] result = pythagoreanTriple(m, n);
+                testHypotCase(result[0], result[1], result[2]);
+            }
+        }
+
+        // Approaching overflow tests
+
+        /*
+         * Create a random value r with an large-ish exponent.  The
+         * result of hypot(3*r, 4*r) should be approximately 5*r. (The
+         * computation of 4*r is exact since it just changes the
+         * exponent).  While the exponent of r is less than or equal
+         * to (MAX_EXPONENT - 3), the computation should not overflow.
+         */
+        java.util.Random rand = new Random();
+        // Android-changed: reduce test run time testing every 10th of original
+        // for (int i = 0; i < 1000; i++) {
+        for (int i = 0; i < 1000; i += 10) {
+            double d = rand.nextDouble();
+            // Scale d to have an exponent equal to MAX_EXPONENT -15
+            d = Math.scalb(d, Double.MAX_EXPONENT
+                    - 15 - Tests.ilogb(d));
+            for (int j = 0; j <= 13; j += 1) {
+                testHypotCase(3 * d, 4 * d, 5 * d, 2.5);
+                d *= 2.0; // increase exponent by 1
+            }
+        }
+
+        // Test for monotonicity failures.  Fix one argument and test
+        // two numbers before and two numbers after each chosen value;
+        // i.e.
+        //
+        // pcNeighbors[] =
+        // {nextDown(nextDown(pc)),
+        // nextDown(pc),
+        // pc,
+        // nextUp(pc),
+        // nextUp(nextUp(pc))}
+        //
+        // and we test that hypot(pcNeighbors[i]) <= hypot(pcNeighbors[i+1])
+        {
+            double[] pcNeighbors = new double[5];
+            double[] pcNeighborsHypot = new double[5];
+            double[] pcNeighborsStrictHypot = new double[5];
+
+            for (int i = -18; i <= 18; i++) {
+                double pc = Math.scalb(1.0, i);
+
+                pcNeighbors[2] = pc;
+                pcNeighbors[1] = Math.nextDown(pc);
+                pcNeighbors[0] = Math.nextDown(pcNeighbors[1]);
+                pcNeighbors[3] = Math.nextUp(pc);
+                pcNeighbors[4] = Math.nextUp(pcNeighbors[3]);
+
+                for (int j = 0; j < pcNeighbors.length; j++) {
+                    pcNeighborsHypot[j] = Math.hypot(2.0, pcNeighbors[j]);
+                    pcNeighborsStrictHypot[j] = StrictMath.hypot(2.0, pcNeighbors[j]);
+                }
+
+                for (int j = 0; j < pcNeighborsHypot.length - 1; j++) {
+                    if (pcNeighborsHypot[j] > pcNeighborsHypot[j + 1]) {
+                        Assert.fail("Monotonicity failure for Math.hypot on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsHypot[j] + " and " +
+                                pcNeighborsHypot[j + 1]);
+                    }
+
+                    if (pcNeighborsStrictHypot[j] > pcNeighborsStrictHypot[j + 1]) {
+                        Assert.fail("Monotonicity failure for StrictMath.hypot on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsStrictHypot[j] + " and " +
+                                pcNeighborsStrictHypot[j + 1]);
+                    }
+                }
+            }
+        }
+    }
+
+    static void testHypotCase(double input1, double input2, double expected) {
+        testHypotCase(input1, input2, expected, 1);
+    }
+
+    static void testHypotCase(double input1, double input2, double expected, double ulps) {
+        if (expected < 0.0) {
+            Assert.fail("Result of hypot must be greater than or equal to zero");
+        }
+
+        // Test Math and StrictMath methods with no inputs negated,
+        // each input negated singly, and both inputs negated.  Also
+        // test inputs in reversed order.
+
+        for (int i = -1; i <= 1; i += 2) {
+            for (int j = -1; j <= 1; j += 2) {
+                double x = i * input1;
+                double y = j * input2;
+                Tests.testUlpDiff("Math.hypot", x, y,
+                        Math.hypot(x, y), expected, ulps);
+                Tests.testUlpDiff("Math.hypot", y, x,
+                        Math.hypot(y, x), expected, ulps);
+
+                Tests.testUlpDiff("StrictMath.hypot", x, y,
+                        StrictMath.hypot(x, y), expected, ulps);
+                Tests.testUlpDiff("StrictMath.hypot", y, x,
+                        StrictMath.hypot(y, x), expected, ulps);
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/IeeeRecommendedTests.java b/ojluni/src/test/java/lang/Math/IeeeRecommendedTests.java
new file mode 100644
index 0000000..d85c72e
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/IeeeRecommendedTests.java
@@ -0,0 +1,1567 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main IeeeRecommendedTests
+ * @bug 4860891 4826732 4780454 4939441 4826652 8078672
+ * @summary Tests for IEEE 754[R] recommended functions and similar methods (use -Dseed=X to set PRNG seed)
+ * @author Joseph D. Darcy
+ * @key randomness
+ */
+package test.java.lang.Math;
+
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+public class IeeeRecommendedTests {
+
+    private IeeeRecommendedTests() {
+    }
+
+    static final float NaNf = Float.NaN;
+    static final double NaNd = Double.NaN;
+    static final float infinityF = Float.POSITIVE_INFINITY;
+    static final double infinityD = Double.POSITIVE_INFINITY;
+
+    static final float Float_MAX_VALUEmm = 0x1.fffffcP+127f;
+    static final float Float_MAX_SUBNORMAL = 0x0.fffffeP-126f;
+    static final float Float_MAX_SUBNORMALmm = 0x0.fffffcP-126f;
+
+    static final double Double_MAX_VALUEmm = 0x1.ffffffffffffeP+1023;
+    static final double Double_MAX_SUBNORMAL = 0x0.fffffffffffffP-1022;
+    static final double Double_MAX_SUBNORMALmm = 0x0.ffffffffffffeP-1022;
+
+    // Initialize shared random number generator
+    static java.util.Random rand = new Random();
+
+    /**
+     * Returns a floating-point power of two in the normal range.
+     */
+    static double powerOfTwoD(int n) {
+        return Double.longBitsToDouble((((long) n + (long) Double.MAX_EXPONENT) <<
+                (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                & DoubleConsts.EXP_BIT_MASK);
+    }
+
+    /**
+     * Returns a floating-point power of two in the normal range.
+     */
+    static float powerOfTwoF(int n) {
+        return Float.intBitsToFloat(((n + Float.MAX_EXPONENT) <<
+                (FloatConsts.SIGNIFICAND_WIDTH - 1))
+                & FloatConsts.EXP_BIT_MASK);
+    }
+
+    /* ******************** getExponent tests ****************************** */
+
+    /*
+     * The tests for getExponent should test the special values (NaN, +/-
+     * infinity, etc.), test the endpoints of each binade (set of
+     * floating-point values with the same exponent), and for good
+     * measure, test some random values within each binade.  Testing
+     * the endpoints of each binade includes testing both positive and
+     * negative numbers.  Subnormal values with different normalized
+     * exponents should be tested too.  Both Math and StrictMath
+     * methods should return the same results.
+     */
+
+    /*
+     * Test Math.getExponent and StrictMath.getExponent with +d and -d.
+     */
+    static void testGetExponentCase(float f, int expected) {
+        float minus_f = -f;
+
+        Tests.test("Math.getExponent(float)", f,
+                Math.getExponent(f), expected);
+        Tests.test("Math.getExponent(float)", minus_f,
+                Math.getExponent(minus_f), expected);
+
+        Tests.test("StrictMath.getExponent(float)", f,
+                StrictMath.getExponent(f), expected);
+        Tests.test("StrictMath.getExponent(float)", minus_f,
+                StrictMath.getExponent(minus_f), expected);
+    }
+
+    /*
+     * Test Math.getExponent and StrictMath.getExponent with +d and -d.
+     */
+    static void testGetExponentCase(double d, int expected) {
+        double minus_d = -d;
+
+        Tests.test("Math.getExponent(double)", d,
+                Math.getExponent(d), expected);
+        Tests.test("Math.getExponent(double)", minus_d,
+                Math.getExponent(minus_d), expected);
+
+        Tests.test("StrictMath.getExponent(double)", d,
+                StrictMath.getExponent(d), expected);
+        Tests.test("StrictMath.getExponent(double)", minus_d,
+                StrictMath.getExponent(minus_d), expected);
+    }
+
+    @Test
+    public void testFloatGetExponent() {
+        float[] specialValues = {NaNf,
+                Float.POSITIVE_INFINITY,
+                +0.0f,
+                +1.0f,
+                +2.0f,
+                +16.0f,
+                +Float.MIN_VALUE,
+                +Float_MAX_SUBNORMAL,
+                +Float.MIN_NORMAL,
+                +Float.MAX_VALUE
+        };
+
+        int[] specialResults = {Float.MAX_EXPONENT + 1, // NaN results
+                Float.MAX_EXPONENT + 1, // Infinite results
+                Float.MIN_EXPONENT - 1, // Zero results
+                0,
+                1,
+                4,
+                Float.MIN_EXPONENT - 1,
+                -Float.MAX_EXPONENT,
+                Float.MIN_EXPONENT,
+                Float.MAX_EXPONENT
+        };
+
+        // Special value tests
+        for (int i = 0; i < specialValues.length; i++) {
+            testGetExponentCase(specialValues[i], specialResults[i]);
+        }
+
+        // Normal exponent tests
+        for (int i = Float.MIN_EXPONENT; i <= Float.MAX_EXPONENT; i++) {
+            // Create power of two
+            float po2 = powerOfTwoF(i);
+
+            testGetExponentCase(po2, i);
+
+            // Generate some random bit patterns for the significand
+            for (int j = 0; j < 10; j++) {
+                int randSignif = rand.nextInt();
+                float randFloat;
+
+                randFloat = Float.intBitsToFloat( // Exponent
+                        (Float.floatToIntBits(po2) &
+                                (~FloatConsts.SIGNIF_BIT_MASK)) |
+                                // Significand
+                                (randSignif &
+                                        FloatConsts.SIGNIF_BIT_MASK));
+
+                testGetExponentCase(randFloat, i);
+            }
+
+            if (i > Float.MIN_EXPONENT) {
+                float po2minus = Math.nextAfter(po2, Float.NEGATIVE_INFINITY);
+                testGetExponentCase(po2minus, i - 1);
+            }
+        }
+
+        // Subnormal exponent tests
+
+        /*
+         * Start with MIN_VALUE, left shift, test high value, low
+         * values, and random in between.
+         *
+         * Use nextAfter to calculate, high value of previous binade,
+         * loop count i will indicate how many random bits, if any are
+         * needed.
+         */
+
+        float top = Float.MIN_VALUE;
+        for (int i = 1;
+                i < FloatConsts.SIGNIFICAND_WIDTH;
+                i++, top *= 2.0f) {
+
+            testGetExponentCase(top, Float.MIN_EXPONENT - 1);
+
+            // Test largest value in next smaller binade
+            if (i >= 3) {// (i == 1) would test 0.0;
+                // (i == 2) would just retest MIN_VALUE
+                testGetExponentCase(Math.nextAfter(top, 0.0f), Float.MIN_EXPONENT - 1);
+
+                if (i >= 10) {
+                    // create a bit mask with (i-1) 1's in the low order
+                    // bits
+                    int mask = ~((~0) << (i - 1));
+                    float randFloat = Float.intBitsToFloat( // Exponent
+                            Float.floatToIntBits(top) |
+                                    // Significand
+                                    (rand.nextInt() & mask));
+
+                    testGetExponentCase(randFloat, Float.MIN_EXPONENT - 1);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testDoubleGetExponent() {
+        double[] specialValues = {NaNd,
+                infinityD,
+                +0.0,
+                +1.0,
+                +2.0,
+                +16.0,
+                +Double.MIN_VALUE,
+                +Double_MAX_SUBNORMAL,
+                +Double.MIN_NORMAL,
+                +Double.MAX_VALUE
+        };
+
+        int[] specialResults = {Double.MAX_EXPONENT + 1, // NaN results
+                Double.MAX_EXPONENT + 1, // Infinite results
+                Double.MIN_EXPONENT - 1, // Zero results
+                0,
+                1,
+                4,
+                Double.MIN_EXPONENT - 1,
+                -Double.MAX_EXPONENT,
+                Double.MIN_EXPONENT,
+                Double.MAX_EXPONENT
+        };
+
+        // Special value tests
+        for (int i = 0; i < specialValues.length; i++) {
+            testGetExponentCase(specialValues[i], specialResults[i]);
+        }
+
+        // Normal exponent tests
+        for (int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
+            // Create power of two
+            double po2 = powerOfTwoD(i);
+
+            testGetExponentCase(po2, i);
+
+            // Generate some random bit patterns for the significand
+            for (int j = 0; j < 10; j++) {
+                long randSignif = rand.nextLong();
+                double randFloat;
+
+                randFloat = Double.longBitsToDouble( // Exponent
+                        (Double.doubleToLongBits(po2) &
+                                (~DoubleConsts.SIGNIF_BIT_MASK)) |
+                                // Significand
+                                (randSignif &
+                                        DoubleConsts.SIGNIF_BIT_MASK));
+
+                testGetExponentCase(randFloat, i);
+            }
+
+            if (i > Double.MIN_EXPONENT) {
+                double po2minus = Math.nextAfter(po2,
+                        Double.NEGATIVE_INFINITY);
+                testGetExponentCase(po2minus, i - 1);
+            }
+        }
+
+        // Subnormal exponent tests
+
+        /*
+         * Start with MIN_VALUE, left shift, test high value, low
+         * values, and random in between.
+         *
+         * Use nextAfter to calculate, high value of previous binade;
+         * loop count i will indicate how many random bits, if any are
+         * needed.
+         */
+
+        double top = Double.MIN_VALUE;
+        for (int i = 1;
+                i < DoubleConsts.SIGNIFICAND_WIDTH;
+                i++, top *= 2.0f) {
+
+            testGetExponentCase(top,
+                    Double.MIN_EXPONENT - 1);
+
+            // Test largest value in next smaller binade
+            if (i >= 3) {// (i == 1) would test 0.0;
+                // (i == 2) would just retest MIN_VALUE
+                testGetExponentCase(Math.nextAfter(top, 0.0),
+                        Double.MIN_EXPONENT - 1);
+
+                if (i >= 10) {
+                    // create a bit mask with (i-1) 1's in the low order
+                    // bits
+                    long mask = ~((~0L) << (i - 1));
+                    double randFloat = Double.longBitsToDouble( // Exponent
+                            Double.doubleToLongBits(top) |
+                                    // Significand
+                                    (rand.nextLong() & mask));
+
+                    testGetExponentCase(randFloat,
+                            Double.MIN_EXPONENT - 1);
+                }
+            }
+        }
+    }
+
+
+    /* ******************** nextAfter tests ****************************** */
+
+    static void testNextAfterCase(float start, double direction, float expected) {
+        float minus_start = -start;
+        double minus_direction = -direction;
+        float minus_expected = -expected;
+
+        Tests.test("Math.nextAfter(float,double)", start, direction,
+                Math.nextAfter(start, direction), expected);
+        Tests.test("Math.nextAfter(float,double)", minus_start, minus_direction,
+                Math.nextAfter(minus_start, minus_direction), minus_expected);
+
+        Tests.test("StrictMath.nextAfter(float,double)", start, direction,
+                StrictMath.nextAfter(start, direction), expected);
+        Tests.test("StrictMath.nextAfter(float,double)", minus_start, minus_direction,
+                StrictMath.nextAfter(minus_start, minus_direction), minus_expected);
+    }
+
+    static void testNextAfterCase(double start, double direction, double expected) {
+        double minus_start = -start;
+        double minus_direction = -direction;
+        double minus_expected = -expected;
+
+        Tests.test("Math.nextAfter(double,double)", start, direction,
+                Math.nextAfter(start, direction), expected);
+        Tests.test("Math.nextAfter(double,double)", minus_start, minus_direction,
+                Math.nextAfter(minus_start, minus_direction), minus_expected);
+
+        Tests.test("StrictMath.nextAfter(double,double)", start, direction,
+                StrictMath.nextAfter(start, direction), expected);
+        Tests.test("StrictMath.nextAfter(double,double)", minus_start, minus_direction,
+                StrictMath.nextAfter(minus_start, minus_direction), minus_expected);
+    }
+
+    @Test
+    public void testFloatNextAfter() {
+        /*
+         * Each row of the testCases matrix represents one test case
+         * for nexAfter; given the input of the first two columns, the
+         * result in the last column is expected.
+         */
+        float[][] testCases = {
+                {NaNf, NaNf, NaNf},
+                {NaNf, 0.0f, NaNf},
+                {0.0f, NaNf, NaNf},
+                {NaNf, infinityF, NaNf},
+                {infinityF, NaNf, NaNf},
+
+                {infinityF, infinityF, infinityF},
+                {infinityF, -infinityF, Float.MAX_VALUE},
+                {infinityF, 0.0f, Float.MAX_VALUE},
+
+                {Float.MAX_VALUE, infinityF, infinityF},
+                {Float.MAX_VALUE, -infinityF, Float_MAX_VALUEmm},
+                {Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE},
+                {Float.MAX_VALUE, 0.0f, Float_MAX_VALUEmm},
+
+                {Float_MAX_VALUEmm, Float.MAX_VALUE, Float.MAX_VALUE},
+                {Float_MAX_VALUEmm, infinityF, Float.MAX_VALUE},
+                {Float_MAX_VALUEmm, Float_MAX_VALUEmm, Float_MAX_VALUEmm},
+
+                {Float.MIN_NORMAL, infinityF, Float.MIN_NORMAL +
+                        Float.MIN_VALUE},
+                {Float.MIN_NORMAL, -infinityF, Float_MAX_SUBNORMAL},
+                {Float.MIN_NORMAL, 1.0f, Float.MIN_NORMAL +
+                        Float.MIN_VALUE},
+                {Float.MIN_NORMAL, -1.0f, Float_MAX_SUBNORMAL},
+                {Float.MIN_NORMAL, Float.MIN_NORMAL, Float.MIN_NORMAL},
+
+                {Float_MAX_SUBNORMAL, Float.MIN_NORMAL, Float.MIN_NORMAL},
+                {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL},
+                {Float_MAX_SUBNORMAL, 0.0f, Float_MAX_SUBNORMALmm},
+
+                {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL, Float_MAX_SUBNORMAL},
+                {Float_MAX_SUBNORMALmm, 0.0f, Float_MAX_SUBNORMALmm - Float.MIN_VALUE},
+                {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMALmm},
+
+                {Float.MIN_VALUE, 0.0f, 0.0f},
+                {-Float.MIN_VALUE, 0.0f, -0.0f},
+                {Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE},
+                {Float.MIN_VALUE, 1.0f, 2 * Float.MIN_VALUE},
+
+                // Make sure zero behavior is tested
+                {0.0f, 0.0f, 0.0f},
+                {0.0f, -0.0f, -0.0f},
+                {-0.0f, 0.0f, 0.0f},
+                {-0.0f, -0.0f, -0.0f},
+                {0.0f, infinityF, Float.MIN_VALUE},
+                {0.0f, -infinityF, -Float.MIN_VALUE},
+                {-0.0f, infinityF, Float.MIN_VALUE},
+                {-0.0f, -infinityF, -Float.MIN_VALUE},
+                {0.0f, Float.MIN_VALUE, Float.MIN_VALUE},
+                {0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE},
+                {-0.0f, Float.MIN_VALUE, Float.MIN_VALUE},
+                {-0.0f, -Float.MIN_VALUE, -Float.MIN_VALUE}
+        };
+
+        for (float[] testCase : testCases) {
+            testNextAfterCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+    @Test
+    public void testDoubleNextAfter() {
+        /*
+         * Each row of the testCases matrix represents one test case
+         * for nexAfter; given the input of the first two columns, the
+         * result in the last column is expected.
+         */
+        double[][] testCases = {
+                {NaNd, NaNd, NaNd},
+                {NaNd, 0.0d, NaNd},
+                {0.0d, NaNd, NaNd},
+                {NaNd, infinityD, NaNd},
+                {infinityD, NaNd, NaNd},
+
+                {infinityD, infinityD, infinityD},
+                {infinityD, -infinityD, Double.MAX_VALUE},
+                {infinityD, 0.0d, Double.MAX_VALUE},
+
+                {Double.MAX_VALUE, infinityD, infinityD},
+                {Double.MAX_VALUE, -infinityD, Double_MAX_VALUEmm},
+                {Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE},
+                {Double.MAX_VALUE, 0.0d, Double_MAX_VALUEmm},
+
+                {Double_MAX_VALUEmm, Double.MAX_VALUE, Double.MAX_VALUE},
+                {Double_MAX_VALUEmm, infinityD, Double.MAX_VALUE},
+                {Double_MAX_VALUEmm, Double_MAX_VALUEmm, Double_MAX_VALUEmm},
+
+                {Double.MIN_NORMAL, infinityD, Double.MIN_NORMAL +
+                        Double.MIN_VALUE},
+                {Double.MIN_NORMAL, -infinityD, Double_MAX_SUBNORMAL},
+                {Double.MIN_NORMAL, 1.0f, Double.MIN_NORMAL +
+                        Double.MIN_VALUE},
+                {Double.MIN_NORMAL, -1.0f, Double_MAX_SUBNORMAL},
+                {Double.MIN_NORMAL, Double.MIN_NORMAL, Double.MIN_NORMAL},
+
+                {Double_MAX_SUBNORMAL, Double.MIN_NORMAL, Double.MIN_NORMAL},
+                {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL},
+                {Double_MAX_SUBNORMAL, 0.0d, Double_MAX_SUBNORMALmm},
+
+                {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL, Double_MAX_SUBNORMAL},
+                {Double_MAX_SUBNORMALmm, 0.0d, Double_MAX_SUBNORMALmm - Double.MIN_VALUE},
+                {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMALmm},
+
+                {Double.MIN_VALUE, 0.0d, 0.0d},
+                {-Double.MIN_VALUE, 0.0d, -0.0d},
+                {Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE},
+                {Double.MIN_VALUE, 1.0f, 2 * Double.MIN_VALUE},
+
+                // Make sure zero behavior is tested
+                {0.0d, 0.0d, 0.0d},
+                {0.0d, -0.0d, -0.0d},
+                {-0.0d, 0.0d, 0.0d},
+                {-0.0d, -0.0d, -0.0d},
+                {0.0d, infinityD, Double.MIN_VALUE},
+                {0.0d, -infinityD, -Double.MIN_VALUE},
+                {-0.0d, infinityD, Double.MIN_VALUE},
+                {-0.0d, -infinityD, -Double.MIN_VALUE},
+                {0.0d, Double.MIN_VALUE, Double.MIN_VALUE},
+                {0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE},
+                {-0.0d, Double.MIN_VALUE, Double.MIN_VALUE},
+                {-0.0d, -Double.MIN_VALUE, -Double.MIN_VALUE}
+        };
+
+        for (double[] testCase : testCases) {
+            testNextAfterCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+    /* ******************** nextUp tests ********************************* */
+
+    @Test
+    public void testFloatNextUp() {
+        /*
+         * Each row of testCases represents one test case for nextUp;
+         * the first column is the input and the second column is the
+         * expected result.
+         */
+        float[][] testCases = {
+                {NaNf, NaNf},
+                {-infinityF, -Float.MAX_VALUE},
+                {-Float.MAX_VALUE, -Float_MAX_VALUEmm},
+                {-Float.MIN_NORMAL, -Float_MAX_SUBNORMAL},
+                {-Float_MAX_SUBNORMAL, -Float_MAX_SUBNORMALmm},
+                {-Float.MIN_VALUE, -0.0f},
+                {-0.0f, Float.MIN_VALUE},
+                {+0.0f, Float.MIN_VALUE},
+                {Float.MIN_VALUE, Float.MIN_VALUE * 2},
+                {Float_MAX_SUBNORMALmm, Float_MAX_SUBNORMAL},
+                {Float_MAX_SUBNORMAL, Float.MIN_NORMAL},
+                {Float.MIN_NORMAL, Float.MIN_NORMAL + Float.MIN_VALUE},
+                {Float_MAX_VALUEmm, Float.MAX_VALUE},
+                {Float.MAX_VALUE, infinityF},
+                {infinityF, infinityF}
+        };
+
+        for (float[] testCase : testCases) {
+            Tests.test("Math.nextUp(float)",
+                    testCase[0], Math.nextUp(testCase[0]), testCase[1]);
+
+            Tests.test("StrictMath.nextUp(float)",
+                    testCase[0], StrictMath.nextUp(testCase[0]), testCase[1]);
+        }
+    }
+
+    @Test
+    public void testDoubleNextUp() {
+        /*
+         * Each row of testCases represents one test case for nextUp;
+         * the first column is the input and the second column is the
+         * expected result.
+         */
+        double[][] testCases = {
+                {NaNd, NaNd},
+                {-infinityD, -Double.MAX_VALUE},
+                {-Double.MAX_VALUE, -Double_MAX_VALUEmm},
+                {-Double.MIN_NORMAL, -Double_MAX_SUBNORMAL},
+                {-Double_MAX_SUBNORMAL, -Double_MAX_SUBNORMALmm},
+                {-Double.MIN_VALUE, -0.0d},
+                {-0.0d, Double.MIN_VALUE},
+                {+0.0d, Double.MIN_VALUE},
+                {Double.MIN_VALUE, Double.MIN_VALUE * 2},
+                {Double_MAX_SUBNORMALmm, Double_MAX_SUBNORMAL},
+                {Double_MAX_SUBNORMAL, Double.MIN_NORMAL},
+                {Double.MIN_NORMAL, Double.MIN_NORMAL + Double.MIN_VALUE},
+                {Double_MAX_VALUEmm, Double.MAX_VALUE},
+                {Double.MAX_VALUE, infinityD},
+                {infinityD, infinityD}
+        };
+
+        for (double[] testCase : testCases) {
+            Tests.test("Math.nextUp(double)",
+                    testCase[0], Math.nextUp(testCase[0]), testCase[1]);
+
+            Tests.test("StrictMath.nextUp(double)",
+                    testCase[0], StrictMath.nextUp(testCase[0]), testCase[1]);
+        }
+    }
+
+    /* ******************** nextDown tests ********************************* */
+
+    @Test
+    public void testFloatNextDown() {
+        /*
+         * Each row of testCases represents one test case for nextDown;
+         * the first column is the input and the second column is the
+         * expected result.
+         */
+        float[][] testCases = {
+                {NaNf, NaNf},
+                {-infinityF, -infinityF},
+                {-Float.MAX_VALUE, -infinityF},
+                {-Float_MAX_VALUEmm, -Float.MAX_VALUE},
+                {-Float_MAX_SUBNORMAL, -Float.MIN_NORMAL},
+                {-Float_MAX_SUBNORMALmm, -Float_MAX_SUBNORMAL},
+                {-0.0f, -Float.MIN_VALUE},
+                {+0.0f, -Float.MIN_VALUE},
+                {Float.MIN_VALUE, 0.0f},
+                {Float.MIN_VALUE * 2, Float.MIN_VALUE},
+                {Float_MAX_SUBNORMAL, Float_MAX_SUBNORMALmm},
+                {Float.MIN_NORMAL, Float_MAX_SUBNORMAL},
+                {Float.MIN_NORMAL +
+                        Float.MIN_VALUE, Float.MIN_NORMAL},
+                {Float.MAX_VALUE, Float_MAX_VALUEmm},
+                {infinityF, Float.MAX_VALUE},
+        };
+
+        for (float[] testCase : testCases) {
+            Tests.test("Math.nextDown(float)",
+                    testCase[0], Math.nextDown(testCase[0]), testCase[1]);
+
+            Tests.test("StrictMath.nextDown(float)",
+                    testCase[0], StrictMath.nextDown(testCase[0]), testCase[1]);
+        }
+    }
+
+    @Test
+    public void testDoubleNextDown() {
+        /*
+         * Each row of testCases represents one test case for nextDown;
+         * the first column is the input and the second column is the
+         * expected result.
+         */
+        double[][] testCases = {
+                {NaNd, NaNd},
+                {-infinityD, -infinityD},
+                {-Double.MAX_VALUE, -infinityD},
+                {-Double_MAX_VALUEmm, -Double.MAX_VALUE},
+                {-Double_MAX_SUBNORMAL, -Double.MIN_NORMAL},
+                {-Double_MAX_SUBNORMALmm, -Double_MAX_SUBNORMAL},
+                {-0.0d, -Double.MIN_VALUE},
+                {+0.0d, -Double.MIN_VALUE},
+                {Double.MIN_VALUE, 0.0d},
+                {Double.MIN_VALUE * 2, Double.MIN_VALUE},
+                {Double_MAX_SUBNORMAL, Double_MAX_SUBNORMALmm},
+                {Double.MIN_NORMAL, Double_MAX_SUBNORMAL},
+                {Double.MIN_NORMAL +
+                        Double.MIN_VALUE, Double.MIN_NORMAL},
+                {Double.MAX_VALUE, Double_MAX_VALUEmm},
+                {infinityD, Double.MAX_VALUE},
+        };
+
+        for (double[] testCase : testCases) {
+            Tests.test("Math.nextDown(double)",
+                    testCase[0], Math.nextDown(testCase[0]), testCase[1]);
+
+            Tests.test("StrictMath.nextDown(double)",
+                    testCase[0], StrictMath.nextDown(testCase[0]), testCase[1]);
+        }
+    }
+
+
+    /* ********************** boolean tests ****************************** */
+
+    /*
+     * Combined tests for boolean functions, isFinite, isInfinite,
+     * isNaN, isUnordered.
+     */
+    @Test
+    public void testFloatBooleanMethods() {
+        float[] testCases = {
+                NaNf,
+                -infinityF,
+                infinityF,
+                -Float.MAX_VALUE,
+                -3.0f,
+                -1.0f,
+                -Float.MIN_NORMAL,
+                -Float_MAX_SUBNORMALmm,
+                -Float_MAX_SUBNORMAL,
+                -Float.MIN_VALUE,
+                -0.0f,
+                +0.0f,
+                Float.MIN_VALUE,
+                Float_MAX_SUBNORMALmm,
+                Float_MAX_SUBNORMAL,
+                Float.MIN_NORMAL,
+                1.0f,
+                3.0f,
+                Float_MAX_VALUEmm,
+                Float.MAX_VALUE
+        };
+
+        for (int i = 0; i < testCases.length; i++) {
+            // isNaN
+            Tests.test("Float.isNaN(float)", testCases[i],
+                    Float.isNaN(testCases[i]), (i == 0));
+
+            // isFinite
+            Tests.test("Float.isFinite(float)", testCases[i],
+                    Float.isFinite(testCases[i]), (i >= 3));
+
+            // isInfinite
+            Tests.test("Float.isInfinite(float)", testCases[i],
+                    Float.isInfinite(testCases[i]), (i == 1 || i == 2));
+
+            // isUnorderd
+            for (int j = 0; j < testCases.length; j++) {
+                Tests.test("Tests.isUnordered(float, float)", testCases[i], testCases[j],
+                        Tests.isUnordered(testCases[i], testCases[j]), (i == 0 || j == 0));
+            }
+        }
+    }
+
+    @Test
+    public void testDoubleBooleanMethods() {
+        double[] testCases = {
+                NaNd,
+                -infinityD,
+                infinityD,
+                -Double.MAX_VALUE,
+                -3.0d,
+                -1.0d,
+                -Double.MIN_NORMAL,
+                -Double_MAX_SUBNORMALmm,
+                -Double_MAX_SUBNORMAL,
+                -Double.MIN_VALUE,
+                -0.0d,
+                +0.0d,
+                Double.MIN_VALUE,
+                Double_MAX_SUBNORMALmm,
+                Double_MAX_SUBNORMAL,
+                Double.MIN_NORMAL,
+                1.0d,
+                3.0d,
+                Double_MAX_VALUEmm,
+                Double.MAX_VALUE
+        };
+
+        for (int i = 0; i < testCases.length; i++) {
+            // isNaN
+            Tests.test("Double.isNaN(double)", testCases[i],
+                    Double.isNaN(testCases[i]), (i == 0));
+
+            // isFinite
+            Tests.test("Double.isFinite(double)", testCases[i],
+                    Double.isFinite(testCases[i]), (i >= 3));
+
+            // isInfinite
+            Tests.test("Double.isInfinite(double)", testCases[i],
+                    Double.isInfinite(testCases[i]), (i == 1 || i == 2));
+
+            // isUnorderd
+            for (int j = 0; j < testCases.length; j++) {
+                Tests.test("Tests.isUnordered(double, double)", testCases[i], testCases[j],
+                        Tests.isUnordered(testCases[i], testCases[j]), (i == 0 || j == 0));
+            }
+        }
+    }
+
+    /* ******************** copySign tests******************************** */
+    @Test
+    public void testFloatCopySign() {
+        // testCases[0] are logically positive numbers;
+        // testCases[1] are negative numbers.
+        float[][] testCases = {
+                {+0.0f,
+                        Float.MIN_VALUE,
+                        Float_MAX_SUBNORMALmm,
+                        Float_MAX_SUBNORMAL,
+                        Float.MIN_NORMAL,
+                        1.0f,
+                        3.0f,
+                        Float_MAX_VALUEmm,
+                        Float.MAX_VALUE,
+                        infinityF,
+                },
+                {-infinityF,
+                        -Float.MAX_VALUE,
+                        -3.0f,
+                        -1.0f,
+                        -Float.MIN_NORMAL,
+                        -Float_MAX_SUBNORMALmm,
+                        -Float_MAX_SUBNORMAL,
+                        -Float.MIN_VALUE,
+                        -0.0f}
+        };
+
+        float[] NaNs = {Float.intBitsToFloat(0x7fc00000),       // "positive" NaN
+                Float.intBitsToFloat(0xFfc00000)};      // "negative" NaN
+
+        // Tests shared between raw and non-raw versions
+        for (int i = 0; i < 2; i++) {
+            for (int j = 0; j < 2; j++) {
+                for (int m = 0; m < testCases[i].length; m++) {
+                    for (int n = 0; n < testCases[j].length; n++) {
+                        // copySign(magnitude, sign)
+                        Tests.test("Math.copySign(float,float)",
+                                testCases[i][m], testCases[j][n],
+                                Math.copySign(testCases[i][m], testCases[j][n]),
+                                (j == 0 ? 1.0f : -1.0f) * Math.abs(testCases[i][m]));
+
+                        Tests.test("StrictMath.copySign(float,float)",
+                                testCases[i][m], testCases[j][n],
+                                StrictMath.copySign(testCases[i][m], testCases[j][n]),
+                                (j == 0 ? 1.0f : -1.0f) * Math.abs(testCases[i][m]));
+                    }
+                }
+            }
+        }
+
+        // For rawCopySign, NaN may effectively have either sign bit
+        // while for copySign NaNs are treated as if they always have
+        // a zero sign bit (i.e. as positive numbers)
+        for (int i = 0; i < 2; i++) {
+            for (float naN : NaNs) {
+                for (int m = 0; m < testCases[i].length; m++) {
+                    Tests.test("StrictMath.copySign(float,float)",
+                            testCases[i][m], naN,
+                            StrictMath.copySign(testCases[i][m], naN),
+                            Math.abs(testCases[i][m]));
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testDoubleCopySign() {
+        // testCases[0] are logically positive numbers;
+        // testCases[1] are negative numbers.
+        double[][] testCases = {
+                {+0.0d,
+                        Double.MIN_VALUE,
+                        Double_MAX_SUBNORMALmm,
+                        Double_MAX_SUBNORMAL,
+                        Double.MIN_NORMAL,
+                        1.0d,
+                        3.0d,
+                        Double_MAX_VALUEmm,
+                        Double.MAX_VALUE,
+                        infinityD,
+                },
+                {-infinityD,
+                        -Double.MAX_VALUE,
+                        -3.0d,
+                        -1.0d,
+                        -Double.MIN_NORMAL,
+                        -Double_MAX_SUBNORMALmm,
+                        -Double_MAX_SUBNORMAL,
+                        -Double.MIN_VALUE,
+                        -0.0d}
+        };
+
+        double[] NaNs = {Double.longBitsToDouble(0x7ff8000000000000L),  // "positive" NaN
+                Double.longBitsToDouble(0xfff8000000000000L),  // "negative" NaN
+                Double.longBitsToDouble(0x7FF0000000000001L),
+                Double.longBitsToDouble(0xFFF0000000000001L),
+                Double.longBitsToDouble(0x7FF8555555555555L),
+                Double.longBitsToDouble(0xFFF8555555555555L),
+                Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL),
+                Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL),
+                Double.longBitsToDouble(0x7FFDeadBeef00000L),
+                Double.longBitsToDouble(0xFFFDeadBeef00000L),
+                Double.longBitsToDouble(0x7FFCafeBabe00000L),
+                Double.longBitsToDouble(0xFFFCafeBabe00000L)};
+
+        // Tests shared between Math and StrictMath versions
+        for (int i = 0; i < 2; i++) {
+            for (int j = 0; j < 2; j++) {
+                for (int m = 0; m < testCases[i].length; m++) {
+                    for (int n = 0; n < testCases[j].length; n++) {
+                        // copySign(magnitude, sign)
+                        Tests.test("Math.copySign(double,double)",
+                                testCases[i][m], testCases[j][n],
+                                Math.copySign(testCases[i][m], testCases[j][n]),
+                                (j == 0 ? 1.0f : -1.0f) * Math.abs(testCases[i][m]));
+
+                        Tests.test("StrictMath.copySign(double,double)",
+                                testCases[i][m], testCases[j][n],
+                                StrictMath.copySign(testCases[i][m], testCases[j][n]),
+                                (j == 0 ? 1.0f : -1.0f) * Math.abs(testCases[i][m]));
+                    }
+                }
+            }
+        }
+
+        // For Math.copySign, NaN may effectively have either sign bit
+        // while for StrictMath.copySign NaNs are treated as if they
+        // always have a zero sign bit (i.e. as positive numbers)
+        for (int i = 0; i < 2; i++) {
+            for (double naN : NaNs) {
+                for (int m = 0; m < testCases[i].length; m++) {
+                    Tests.test("StrictMath.copySign(double,double)",
+                            testCases[i][m], naN,
+                            StrictMath.copySign(testCases[i][m], naN),
+                            Math.abs(testCases[i][m]));
+                }
+            }
+        }
+    }
+
+    /* ************************ scalb tests ******************************* */
+
+    static void testScalbCase(float value, int scale_factor, float expected) {
+        Tests.test("Math.scalb(float,int)",
+                value, scale_factor,
+                Math.scalb(value, scale_factor), expected);
+
+        Tests.test("Math.scalb(float,int)",
+                -value, scale_factor,
+                Math.scalb(-value, scale_factor), -expected);
+
+        Tests.test("StrictMath.scalb(float,int)",
+                value, scale_factor,
+                StrictMath.scalb(value, scale_factor), expected);
+
+        Tests.test("StrictMath.scalb(float,int)",
+                -value, scale_factor,
+                StrictMath.scalb(-value, scale_factor), -expected);
+    }
+
+    @Test
+    public void testFloatScalb() {
+        int MAX_SCALE = Float.MAX_EXPONENT + -Float.MIN_EXPONENT +
+                FloatConsts.SIGNIFICAND_WIDTH + 1;
+
+        // Arguments x, where scalb(x,n) is x for any n.
+        float[] identityTestCases = {NaNf,
+                -0.0f,
+                +0.0f,
+                infinityF,
+                -infinityF
+        };
+
+        float[] subnormalTestCases = {
+                Float.MIN_VALUE,
+                3.0f * Float.MIN_VALUE,
+                Float_MAX_SUBNORMALmm,
+                Float_MAX_SUBNORMAL
+        };
+
+        float[] someTestCases = {
+                Float.MIN_VALUE,
+                3.0f * Float.MIN_VALUE,
+                Float_MAX_SUBNORMALmm,
+                Float_MAX_SUBNORMAL,
+                Float.MIN_NORMAL,
+                1.0f,
+                2.0f,
+                3.0f,
+                (float) Math.PI,
+                Float_MAX_VALUEmm,
+                Float.MAX_VALUE
+        };
+
+        int[] oneMultiplyScalingFactors = {
+                Float.MIN_EXPONENT,
+                Float.MIN_EXPONENT + 1,
+                -3,
+                -2,
+                -1,
+                0,
+                1,
+                2,
+                3,
+                Float.MAX_EXPONENT - 1,
+                Float.MAX_EXPONENT
+        };
+
+        int[] manyScalingFactors = {
+                Integer.MIN_VALUE,
+                Integer.MIN_VALUE + 1,
+                -MAX_SCALE - 1,
+                -MAX_SCALE,
+                -MAX_SCALE + 1,
+
+                2 * Float.MIN_EXPONENT - 1,       // -253
+                2 * Float.MIN_EXPONENT,         // -252
+                2 * Float.MIN_EXPONENT + 1,       // -251
+
+                Float.MIN_EXPONENT - FloatConsts.SIGNIFICAND_WIDTH,
+                FloatConsts.MIN_SUB_EXPONENT,
+                -Float.MAX_EXPONENT,          // -127
+                Float.MIN_EXPONENT,           // -126
+
+                -2,
+                -1,
+                0,
+                1,
+                2,
+
+                Float.MAX_EXPONENT - 1,         // 126
+                Float.MAX_EXPONENT,           // 127
+                Float.MAX_EXPONENT + 1,         // 128
+
+                2 * Float.MAX_EXPONENT - 1,       // 253
+                2 * Float.MAX_EXPONENT,         // 254
+                2 * Float.MAX_EXPONENT + 1,       // 255
+
+                MAX_SCALE - 1,
+                MAX_SCALE,
+                MAX_SCALE + 1,
+                Integer.MAX_VALUE - 1,
+                Integer.MAX_VALUE
+        };
+
+        // Test cases where scaling is always a no-op
+        for (float identityTestCase : identityTestCases) {
+            for (int manyScalingFactor : manyScalingFactors) {
+                testScalbCase(identityTestCase, manyScalingFactor, identityTestCase);
+            }
+        }
+
+        // Test cases where result is 0.0 or infinity due to magnitude
+        // of the scaling factor
+        for (float someTestCase : someTestCases) {
+            for (int scaleFactor : manyScalingFactors) {
+                if (Math.abs(scaleFactor) >= MAX_SCALE) {
+                    testScalbCase(someTestCase,
+                            scaleFactor,
+                            Math.copySign((scaleFactor > 0 ? infinityF : 0.0f), someTestCase));
+                }
+            }
+        }
+
+        // Test cases that could be done with one floating-point
+        // multiply.
+        for (float someTestCase : someTestCases) {
+            for (int scaleFactor : oneMultiplyScalingFactors) {
+                testScalbCase(someTestCase,
+                        scaleFactor,
+                        someTestCase * powerOfTwoF(scaleFactor));
+            }
+        }
+
+        // Create 2^MAX_EXPONENT
+        float twoToTheMaxExp = 1.0f; // 2^0
+        for (int i = 0; i < Float.MAX_EXPONENT; i++) {
+            twoToTheMaxExp *= 2.0f;
+        }
+
+        // Scale-up subnormal values until they all overflow
+        for (float subnormalTestCase : subnormalTestCases) {
+            float scale = 1.0f; // 2^j
+
+            for (int scaleFactor = Float.MAX_EXPONENT * 2; scaleFactor < MAX_SCALE;
+                    scaleFactor++) {// MAX_SCALE -1 should cause overflow
+
+                testScalbCase(subnormalTestCase,
+                        scaleFactor,
+                        (Tests.ilogb(subnormalTestCase) + scaleFactor > Float.MAX_EXPONENT) ?
+                                Math.copySign(infinityF, subnormalTestCase) : // overflow
+                                // calculate right answer
+                                twoToTheMaxExp * (twoToTheMaxExp * (scale * subnormalTestCase)));
+                scale *= 2.0f;
+            }
+        }
+
+        // Scale down a large number until it underflows.  By scaling
+        // down MAX_NORMALmm, the first subnormal result will be exact
+        // but the next one will round -- all those results can be
+        // checked by halving a separate value in the loop.  Actually,
+        // we can keep halving and checking until the product is zero
+        // since:
+        //
+        // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact
+        // it will round *up*
+        //
+        // 2. When rounding first occurs in the expected product, it
+        // too rounds up, to 2^-MAX_EXPONENT.
+        //
+        // Halving expected after rounding happends to give the same
+        // result as the scalb operation.
+        float expected = Float_MAX_VALUEmm * 0.5f;
+        for (int i = -1; i > -MAX_SCALE; i--) {
+            testScalbCase(Float_MAX_VALUEmm, i, expected);
+
+            expected *= 0.5f;
+        }
+
+        // Tricky rounding tests:
+        // Scale down a large number into subnormal range such that if
+        // scalb is being implemented with multiple floating-point
+        // multiplies, the value would round twice if the multiplies
+        // were done in the wrong order.
+
+        float value = 0x8.0000bP-5f;
+        expected = 0x1.00001p-129f;
+
+        for (int i = 0; i < 129; i++) {
+            testScalbCase(value,
+                    -127 - i,
+                    expected);
+            value *= 2.0f;
+        }
+    }
+
+    static void testScalbCase(double value, int scale_factor, double expected) {
+        Tests.test("Math.scalb(double,int)",
+                value, scale_factor,
+                Math.scalb(value, scale_factor), expected);
+
+        Tests.test("Math.scalb(double,int)",
+                -value, scale_factor,
+                Math.scalb(-value, scale_factor), -expected);
+
+        Tests.test("StrictMath.scalb(double,int)",
+                value, scale_factor,
+                StrictMath.scalb(value, scale_factor), expected);
+
+        Tests.test("StrictMath.scalb(double,int)",
+                -value, scale_factor,
+                StrictMath.scalb(-value, scale_factor), -expected);
+    }
+
+    @Test
+    public void testDoubleScalb() {
+        int MAX_SCALE = Double.MAX_EXPONENT + -Double.MIN_EXPONENT +
+                DoubleConsts.SIGNIFICAND_WIDTH + 1;
+
+        // Arguments x, where scalb(x,n) is x for any n.
+        double[] identityTestCases = {NaNd,
+                -0.0,
+                +0.0,
+                infinityD,
+        };
+
+        double[] subnormalTestCases = {
+                Double.MIN_VALUE,
+                3.0d * Double.MIN_VALUE,
+                Double_MAX_SUBNORMALmm,
+                Double_MAX_SUBNORMAL
+        };
+
+        double[] someTestCases = {
+                Double.MIN_VALUE,
+                3.0d * Double.MIN_VALUE,
+                Double_MAX_SUBNORMALmm,
+                Double_MAX_SUBNORMAL,
+                Double.MIN_NORMAL,
+                1.0d,
+                2.0d,
+                3.0d,
+                Math.PI,
+                Double_MAX_VALUEmm,
+                Double.MAX_VALUE
+        };
+
+        int[] oneMultiplyScalingFactors = {
+                Double.MIN_EXPONENT,
+                Double.MIN_EXPONENT + 1,
+                -3,
+                -2,
+                -1,
+                0,
+                1,
+                2,
+                3,
+                Double.MAX_EXPONENT - 1,
+                Double.MAX_EXPONENT
+        };
+
+        int[] manyScalingFactors = {
+                Integer.MIN_VALUE,
+                Integer.MIN_VALUE + 1,
+                -MAX_SCALE - 1,
+                -MAX_SCALE,
+                -MAX_SCALE + 1,
+
+                2 * Double.MIN_EXPONENT - 1,      // -2045
+                2 * Double.MIN_EXPONENT,        // -2044
+                2 * Double.MIN_EXPONENT + 1,      // -2043
+
+                Double.MIN_EXPONENT,          // -1022
+                Double.MIN_EXPONENT - DoubleConsts.SIGNIFICAND_WIDTH,
+                DoubleConsts.MIN_SUB_EXPONENT,
+                -Double.MAX_EXPONENT,         // -1023
+                Double.MIN_EXPONENT,          // -1022
+
+                -2,
+                -1,
+                0,
+                1,
+                2,
+
+                Double.MAX_EXPONENT - 1,        // 1022
+                Double.MAX_EXPONENT,          // 1023
+                Double.MAX_EXPONENT + 1,        // 1024
+
+                2 * Double.MAX_EXPONENT - 1,      // 2045
+                2 * Double.MAX_EXPONENT,        // 2046
+                2 * Double.MAX_EXPONENT + 1,      // 2047
+
+                MAX_SCALE - 1,
+                MAX_SCALE,
+                MAX_SCALE + 1,
+                Integer.MAX_VALUE - 1,
+                Integer.MAX_VALUE
+        };
+
+        // Test cases where scaling is always a no-op
+        for (double identityTestCase : identityTestCases) {
+            for (int manyScalingFactor : manyScalingFactors) {
+                testScalbCase(identityTestCase,
+                        manyScalingFactor,
+                        identityTestCase);
+            }
+        }
+
+        // Test cases where result is 0.0 or infinity due to magnitude
+        // of the scaling factor
+        for (double someTestCase : someTestCases) {
+            for (int scaleFactor : manyScalingFactors) {
+                if (Math.abs(scaleFactor) >= MAX_SCALE) {
+                    testScalbCase(someTestCase,
+                            scaleFactor,
+                            Math.copySign((scaleFactor > 0 ? infinityD : 0.0), someTestCase));
+                }
+            }
+        }
+
+        // Test cases that could be done with one floating-point
+        // multiply.
+        for (double someTestCase : someTestCases) {
+            for (int scaleFactor : oneMultiplyScalingFactors) {
+                testScalbCase(someTestCase,
+                        scaleFactor,
+                        someTestCase * powerOfTwoD(scaleFactor));
+            }
+        }
+
+        // Create 2^MAX_EXPONENT
+        double twoToTheMaxExp = 1.0; // 2^0
+        for (int i = 0; i < Double.MAX_EXPONENT; i++) {
+            twoToTheMaxExp *= 2.0;
+        }
+
+        // Scale-up subnormal values until they all overflow
+        for (double subnormalTestCase : subnormalTestCases) {
+            double scale = 1.0; // 2^j
+
+            for (int scaleFactor = Double.MAX_EXPONENT * 2; scaleFactor < MAX_SCALE;
+                    scaleFactor++) { // MAX_SCALE -1 should cause overflow
+
+                testScalbCase(subnormalTestCase,
+                        scaleFactor,
+                        (Tests.ilogb(subnormalTestCase) + scaleFactor > Double.MAX_EXPONENT) ?
+                                Math.copySign(infinityD, subnormalTestCase) : // overflow
+                                // calculate right answer
+                                twoToTheMaxExp * (twoToTheMaxExp * (scale * subnormalTestCase)));
+                scale *= 2.0;
+            }
+        }
+
+        // Scale down a large number until it underflows.  By scaling
+        // down MAX_NORMALmm, the first subnormal result will be exact
+        // but the next one will round -- all those results can be
+        // checked by halving a separate value in the loop.  Actually,
+        // we can keep halving and checking until the product is zero
+        // since:
+        //
+        // 1. If the scalb of MAX_VALUEmm is subnormal and *not* exact
+        // it will round *up*
+        //
+        // 2. When rounding first occurs in the expected product, it
+        // too rounds up, to 2^-MAX_EXPONENT.
+        //
+        // Halving expected after rounding happends to give the same
+        // result as the scalb operation.
+        double expected = Double_MAX_VALUEmm * 0.5f;
+        for (int i = -1; i > -MAX_SCALE; i--) {
+            testScalbCase(Double_MAX_VALUEmm, i, expected);
+
+            expected *= 0.5;
+        }
+
+        // Tricky rounding tests:
+        // Scale down a large number into subnormal range such that if
+        // scalb is being implemented with multiple floating-point
+        // multiplies, the value would round twice if the multiplies
+        // were done in the wrong order.
+
+        double value = 0x1.000000000000bP-1;
+        expected = 0x0.2000000000001P-1022;
+        for (int i = 0; i < Double.MAX_EXPONENT + 2; i++) {
+            testScalbCase(value,
+                    -1024 - i,
+                    expected);
+            value *= 2.0;
+        }
+    }
+
+    /* ************************* ulp tests ******************************* */
+
+
+    /*
+     * Test Math.ulp and StrictMath.ulp with +d and -d.
+     */
+    static void testUlpCase(float f, float expected) {
+        float minus_f = -f;
+
+        Tests.test("Math.ulp(float)", f,
+                Math.ulp(f), expected);
+        Tests.test("Math.ulp(float)", minus_f,
+                Math.ulp(minus_f), expected);
+        Tests.test("StrictMath.ulp(float)", f,
+                StrictMath.ulp(f), expected);
+        Tests.test("StrictMath.ulp(float)", minus_f,
+                StrictMath.ulp(minus_f), expected);
+    }
+
+    static void testUlpCase(double d, double expected) {
+        double minus_d = -d;
+
+        Tests.test("Math.ulp(double)", d,
+                Math.ulp(d), expected);
+        Tests.test("Math.ulp(double)", minus_d,
+                Math.ulp(minus_d), expected);
+        Tests.test("StrictMath.ulp(double)", d,
+                StrictMath.ulp(d), expected);
+        Tests.test("StrictMath.ulp(double)", minus_d,
+                StrictMath.ulp(minus_d), expected);
+    }
+
+    @Test
+    public void testFloatUlp() {
+        float[] specialValues = {NaNf,
+                Float.POSITIVE_INFINITY,
+                +0.0f,
+                +1.0f,
+                +2.0f,
+                +16.0f,
+                +Float.MIN_VALUE,
+                +Float_MAX_SUBNORMAL,
+                +Float.MIN_NORMAL,
+                +Float.MAX_VALUE
+        };
+
+        float[] specialResults = {NaNf,
+                Float.POSITIVE_INFINITY,
+                Float.MIN_VALUE,
+                powerOfTwoF(-23),
+                powerOfTwoF(-22),
+                powerOfTwoF(-19),
+                Float.MIN_VALUE,
+                Float.MIN_VALUE,
+                Float.MIN_VALUE,
+                powerOfTwoF(104)
+        };
+
+        // Special value tests
+        for (int i = 0; i < specialValues.length; i++) {
+            testUlpCase(specialValues[i], specialResults[i]);
+        }
+
+        // Normal exponent tests
+        for (int i = Float.MIN_EXPONENT; i <= Float.MAX_EXPONENT; i++) {
+            float expected;
+
+            // Create power of two
+            float po2 = powerOfTwoF(i);
+            expected = Math.scalb(1.0f, i - (FloatConsts.SIGNIFICAND_WIDTH - 1));
+
+            testUlpCase(po2, expected);
+
+            // Generate some random bit patterns for the significand
+            for (int j = 0; j < 10; j++) {
+                int randSignif = rand.nextInt();
+                float randFloat;
+
+                randFloat = Float.intBitsToFloat( // Exponent
+                        (Float.floatToIntBits(po2) &
+                                (~FloatConsts.SIGNIF_BIT_MASK)) |
+                                // Significand
+                                (randSignif &
+                                        FloatConsts.SIGNIF_BIT_MASK));
+
+                testUlpCase(randFloat, expected);
+            }
+
+            if (i > Float.MIN_EXPONENT) {
+                float po2minus = Math.nextAfter(po2,
+                        Float.NEGATIVE_INFINITY);
+                testUlpCase(po2minus, expected / 2.0f);
+            }
+        }
+
+        // Subnormal tests
+
+        /*
+         * Start with MIN_VALUE, left shift, test high value, low
+         * values, and random in between.
+         *
+         * Use nextAfter to calculate, high value of previous binade,
+         * loop count i will indicate how many random bits, if any are
+         * needed.
+         */
+
+        float top = Float.MIN_VALUE;
+        for (int i = 1;
+                i < FloatConsts.SIGNIFICAND_WIDTH;
+                i++, top *= 2.0f) {
+
+            testUlpCase(top, Float.MIN_VALUE);
+
+            // Test largest value in next smaller binade
+            if (i >= 3) {// (i == 1) would test 0.0;
+                // (i == 2) would just retest MIN_VALUE
+                testUlpCase(Math.nextAfter(top, 0.0f),
+                        Float.MIN_VALUE);
+
+                if (i >= 10) {
+                    // create a bit mask with (i-1) 1's in the low order
+                    // bits
+                    int mask = ~((~0) << (i - 1));
+                    float randFloat = Float.intBitsToFloat( // Exponent
+                            Float.floatToIntBits(top) |
+                                    // Significand
+                                    (rand.nextInt() & mask));
+
+                    testUlpCase(randFloat, Float.MIN_VALUE);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testDoubleUlp() {
+        double[] specialValues = {NaNd,
+                Double.POSITIVE_INFINITY,
+                +0.0d,
+                +1.0d,
+                +2.0d,
+                +16.0d,
+                +Double.MIN_VALUE,
+                +Double_MAX_SUBNORMAL,
+                +Double.MIN_NORMAL,
+                +Double.MAX_VALUE
+        };
+
+        double[] specialResults = {NaNf,
+                Double.POSITIVE_INFINITY,
+                Double.MIN_VALUE,
+                powerOfTwoD(-52),
+                powerOfTwoD(-51),
+                powerOfTwoD(-48),
+                Double.MIN_VALUE,
+                Double.MIN_VALUE,
+                Double.MIN_VALUE,
+                powerOfTwoD(971)
+        };
+
+        // Special value tests
+        for (int i = 0; i < specialValues.length; i++) {
+            testUlpCase(specialValues[i], specialResults[i]);
+        }
+
+        // Normal exponent tests
+        for (int i = Double.MIN_EXPONENT; i <= Double.MAX_EXPONENT; i++) {
+            double expected;
+
+            // Create power of two
+            double po2 = powerOfTwoD(i);
+            expected = Math.scalb(1.0, i - (DoubleConsts.SIGNIFICAND_WIDTH - 1));
+
+            testUlpCase(po2, expected);
+
+            // Generate some random bit patterns for the significand
+            for (int j = 0; j < 10; j++) {
+                long randSignif = rand.nextLong();
+                double randDouble;
+
+                randDouble = Double.longBitsToDouble( // Exponent
+                        (Double.doubleToLongBits(po2) &
+                                (~DoubleConsts.SIGNIF_BIT_MASK)) |
+                                // Significand
+                                (randSignif &
+                                        DoubleConsts.SIGNIF_BIT_MASK));
+
+                testUlpCase(randDouble, expected);
+            }
+
+            if (i > Double.MIN_EXPONENT) {
+                double po2minus = Math.nextAfter(po2,
+                        Double.NEGATIVE_INFINITY);
+                testUlpCase(po2minus, expected / 2.0f);
+            }
+        }
+
+        // Subnormal tests
+
+        /*
+         * Start with MIN_VALUE, left shift, test high value, low
+         * values, and random in between.
+         *
+         * Use nextAfter to calculate, high value of previous binade,
+         * loop count i will indicate how many random bits, if any are
+         * needed.
+         */
+
+        double top = Double.MIN_VALUE;
+        for (int i = 1;
+                i < DoubleConsts.SIGNIFICAND_WIDTH;
+                i++, top *= 2.0f) {
+
+            testUlpCase(top, Double.MIN_VALUE);
+
+            // Test largest value in next smaller binade
+            if (i >= 3) {// (i == 1) would test 0.0;
+                // (i == 2) would just retest MIN_VALUE
+                testUlpCase(Math.nextAfter(top, 0.0f),
+                        Double.MIN_VALUE);
+
+                if (i >= 10) {
+                    // create a bit mask with (i-1) 1's in the low order
+                    // bits
+                    int mask = ~((~0) << (i - 1));
+                    double randDouble = Double.longBitsToDouble( // Exponent
+                            Double.doubleToLongBits(top) |
+                                    // Significand
+                                    (rand.nextLong() & mask));
+
+                    testUlpCase(randDouble, Double.MIN_VALUE);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testFloatSignum() {
+        float[][] testCases = {
+                {NaNf, NaNf},
+                {-infinityF, -1.0f},
+                {-Float.MAX_VALUE, -1.0f},
+                {-Float.MIN_NORMAL, -1.0f},
+                {-1.0f, -1.0f},
+                {-2.0f, -1.0f},
+                {-Float_MAX_SUBNORMAL, -1.0f},
+                {-Float.MIN_VALUE, -1.0f},
+                {-0.0f, -0.0f},
+                {+0.0f, +0.0f},
+                {Float.MIN_VALUE, 1.0f},
+                {Float_MAX_SUBNORMALmm, 1.0f},
+                {Float_MAX_SUBNORMAL, 1.0f},
+                {Float.MIN_NORMAL, 1.0f},
+                {1.0f, 1.0f},
+                {2.0f, 1.0f},
+                {Float_MAX_VALUEmm, 1.0f},
+                {Float.MAX_VALUE, 1.0f},
+                {infinityF, 1.0f}
+        };
+
+        for (float[] testCase : testCases) {
+            Tests.test("Math.signum(float)",
+                    testCase[0], Math.signum(testCase[0]), testCase[1]);
+            Tests.test("StrictMath.signum(float)",
+                    testCase[0], StrictMath.signum(testCase[0]), testCase[1]);
+        }
+    }
+
+    @Test
+    public void testDoubleSignum() {
+        double[][] testCases = {
+                {NaNd, NaNd},
+                {-infinityD, -1.0},
+                {-Double.MAX_VALUE, -1.0},
+                {-Double.MIN_NORMAL, -1.0},
+                {-1.0, -1.0},
+                {-2.0, -1.0},
+                {-Double_MAX_SUBNORMAL, -1.0},
+                {-Double.MIN_VALUE, -1.0d},
+                {-0.0d, -0.0d},
+                {+0.0d, +0.0d},
+                {Double.MIN_VALUE, 1.0},
+                {Double_MAX_SUBNORMALmm, 1.0},
+                {Double_MAX_SUBNORMAL, 1.0},
+                {Double.MIN_NORMAL, 1.0},
+                {1.0, 1.0},
+                {2.0, 1.0},
+                {Double_MAX_VALUEmm, 1.0},
+                {Double.MAX_VALUE, 1.0},
+                {infinityD, 1.0}
+        };
+
+        for (double[] testCase : testCases) {
+            Tests.test("Math.signum(double)",
+                    testCase[0], Math.signum(testCase[0]), testCase[1]);
+            Tests.test("StrictMath.signum(double)",
+                    testCase[0], StrictMath.signum(testCase[0]), testCase[1]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/Log10Tests.java b/ojluni/src/test/java/lang/Math/Log10Tests.java
new file mode 100644
index 0000000..1a928d1
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/Log10Tests.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4074599 4939441
+ * @summary Tests for {Math, StrictMath}.log10
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class Log10Tests {
+
+    private Log10Tests() {
+    }
+
+    static final double infinityD = Double.POSITIVE_INFINITY;
+    static final double NaNd = Double.NaN;
+    static final double LN_10 = StrictMath.log(10.0);
+
+    // Initialize shared random number generator
+    static java.util.Random rand = new java.util.Random(0L);
+
+    static void testLog10Case(double input, double expected) {
+        Tests.test("Math.log10(double)", input,
+                Math.log10(input), expected);
+
+        Tests.test("StrictMath.log10(double)", input,
+                StrictMath.log10(input), expected);
+    }
+
+    @Test
+    public void testLog10() {
+        double[][] testCases = {
+                {Double.NaN, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
+                {Double.NEGATIVE_INFINITY, NaNd},
+                {-8.0, NaNd},
+                {-1.0, NaNd},
+                {-Double.MIN_NORMAL, NaNd},
+                {-Double.MIN_VALUE, NaNd},
+                {-0.0, -infinityD},
+                {+0.0, -infinityD},
+                {+1.0, 0.0},
+                {Double.POSITIVE_INFINITY, infinityD},
+        };
+
+        // Test special cases
+        for (double[] aCase : testCases) {
+            testLog10Case(aCase[0], aCase[1]);
+        }
+
+        // Test log10(10^n) == n for integer n; 10^n, n < 0 is not
+        // exactly representable as a floating-point value -- up to
+        // 10^22 can be represented exactly
+        double testCase = 1.0;
+        for (int i = 0; i < 23; i++) {
+            testLog10Case(testCase, i);
+            testCase *= 10.0;
+        }
+
+        // Test for gross inaccuracy by comparing to log; should be
+        // within a few ulps of log(x)/log(10)
+        for (int i = 0; i < 10000; i++) {
+            double input = Double.longBitsToDouble(rand.nextLong());
+            if (!Double.isFinite(input)) {
+                continue; // avoid testing NaN and infinite values
+            } else {
+                input = Math.abs(input);
+
+                double expected = StrictMath.log(input) / LN_10;
+                if (!Double.isFinite(expected)) {
+                    continue; // if log(input) overflowed, try again
+                } else {
+                    double result;
+
+                    if (Math.abs(((result = Math.log10(input)) - expected) / Math.ulp(expected))
+                            > 3) {
+                        Assert.fail("For input " + input +
+                                ", Math.log10 was more than 3 ulps different from " +
+                                "log(input)/log(10): log10(input) = " + result +
+                                "\tlog(input)/log(10) = " + expected);
+                    }
+
+                    if (Math.abs(
+                            ((result = StrictMath.log10(input)) - expected) / Math.ulp(expected))
+                            > 3) {
+                        Assert.fail("For input " + input +
+                                ", StrictMath.log10 was more than 3 ulps different from " +
+                                "log(input)/log(10): log10(input) = " + result +
+                                "\tlog(input)/log(10) = " + expected);
+                    }
+
+
+                }
+            }
+        }
+
+        // Test for accuracy and monotonicity near log10(1.0).  From
+        // the Taylor expansion of log,
+        // log10(1+z) ~= (z -(z^2)/2)/LN_10;
+        {
+            double[] neighbors = new double[40];
+            double[] neighborsStrict = new double[40];
+            double z = Double.NaN;
+
+            // Test inputs greater than 1.0.
+            neighbors[0] = Math.log10(1.0);
+            neighborsStrict[0] = StrictMath.log10(1.0);
+
+            double[] input = new double[40];
+            int half = input.length / 2;
+
+            // Initialize input to the 40 consecutive double values
+            // "centered" at 1.0.
+            double up = Double.NaN;
+            double down = Double.NaN;
+            for (int i = 0; i < half; i++) {
+                if (i == 0) {
+                    input[half] = 1.0;
+                    up = Math.nextUp(1.0);
+                    down = Math.nextDown(1.0);
+                } else {
+                    input[half + i] = up;
+                    input[half - i] = down;
+                    up = Math.nextUp(up);
+                    down = Math.nextDown(down);
+                }
+            }
+            input[0] = Math.nextDown(input[1]);
+
+            for (int i = 0; i < neighbors.length; i++) {
+                neighbors[i] = Math.log10(input[i]);
+                neighborsStrict[i] = StrictMath.log10(input[i]);
+
+                // Test accuracy.
+                z = input[i] - 1.0;
+                double expected = (z - (z * z) * 0.5) / LN_10;
+                if (Math.abs(neighbors[i] - expected) > 3 * Math.ulp(expected)) {
+                    Assert.fail("For input near 1.0 " + input[i] +
+                            ", Math.log10(1+z) was more than 3 ulps different from " +
+                            "(z-(z^2)/2)/ln(10): log10(input) = " + neighbors[i] +
+                            "\texpected about = " + expected);
+                }
+
+                if (Math.abs(neighborsStrict[i] - expected) > 3 * Math.ulp(expected)) {
+                    Assert.fail("For input near 1.0 " + input[i] +
+                            ", StrictMath.log10(1+z) was more than 3 ulps different from " +
+                            "(z-(z^2)/2)/ln(10): log10(input) = " + neighborsStrict[i] +
+                            "\texpected about = " + expected);
+                }
+
+                // Test monotonicity
+                if (i > 0) {
+                    if (neighbors[i - 1] > neighbors[i]) {
+                        Assert.fail("Monotonicity failure for Math.log10  at " + input[i] +
+                                " and prior value.");
+                    }
+
+                    if (neighborsStrict[i - 1] > neighborsStrict[i]) {
+                        Assert.fail("Monotonicity failure for StrictMath.log10  at " + input[i] +
+                                " and prior value.");
+                    }
+                }
+            }
+
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/Log1pTests.java b/ojluni/src/test/java/lang/Math/Log1pTests.java
new file mode 100644
index 0000000..790f331
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/Log1pTests.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main Log1pTests
+ * @bug 4851638 4939441 8078672
+ * @summary Tests for {Math, StrictMath}.log1p (use -Dseed=X to set PRNG seed)
+ * @author Joseph D. Darcy
+ * @key randomness
+ */
+package test.java.lang.Math;
+
+import java.util.Random;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class Log1pTests {
+
+    private Log1pTests() {
+    }
+
+    static final double infinityD = Double.POSITIVE_INFINITY;
+    static final double NaNd = Double.NaN;
+
+    /**
+     * Formulation taken from HP-15C Advanced Functions Handbook, part number HP 0015-90011, p 181.
+     * This is accurate to a few ulps.
+     */
+    static double hp15cLogp(double x) {
+        double u = 1.0 + x;
+        return (u == 1.0 ? x : StrictMath.log(u) * x / (u - 1));
+    }
+
+    /*
+     * The Taylor expansion of ln(1 + x) for -1 < x <= 1 is:
+     *
+     * x - x^2/2 + x^3/3 - ... -(-x^j)/j
+     *
+     * Therefore, for small values of x, log1p(x) ~= x.  For large
+     * values of x, log1p(x) ~= log(x).
+     *
+     * Also x/(x+1) < ln(1+x) < x
+     */
+
+    @Test
+    public void testLog1p() {
+        double[][] testCases = {
+                {Double.NaN, NaNd},
+                {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
+                {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
+                {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
+                {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
+                {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
+                {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
+                {Double.NEGATIVE_INFINITY, NaNd},
+                {-8.0, NaNd},
+                {-1.0, -infinityD},
+                {-0.0, -0.0},
+                {+0.0, +0.0},
+                {infinityD, infinityD},
+        };
+
+        // Test special cases
+        for (double[] testCase : testCases) {
+            testLog1pCaseWithUlpDiff(testCase[0], testCase[1], 0);
+        }
+
+        // For |x| < 2^-54 log1p(x) ~= x
+        for (int i = DoubleConsts.MIN_SUB_EXPONENT; i <= -54; i++) {
+            double d = Math.scalb(2, i);
+            testLog1pCase(d, d);
+            testLog1pCase(-d, -d);
+        }
+
+        // For x > 2^53 log1p(x) ~= log(x)
+        for (int i = 53; i <= Double.MAX_EXPONENT; i++) {
+            double d = Math.scalb(2, i);
+            testLog1pCaseWithUlpDiff(d, StrictMath.log(d), 2.001);
+        }
+
+        // Construct random values with exponents ranging from -53 to
+        // 52 and compare against HP-15C formula.
+        java.util.Random rand = new Random();
+        for (int i = 0; i < 1000; i++) {
+            double d = rand.nextDouble();
+
+            d = Math.scalb(d, -53 - Tests.ilogb(d));
+
+            for (int j = -53; j <= 52; j++) {
+                testLog1pCaseWithUlpDiff(d, hp15cLogp(d), 5);
+
+                d *= 2.0; // increase exponent by 1
+            }
+        }
+
+        // Test for monotonicity failures near values y-1 where y ~=
+        // e^x.  Test two numbers before and two numbers after each
+        // chosen value; i.e.
+        //
+        // pcNeighbors[] =
+        // {nextDown(nextDown(pc)),
+        // nextDown(pc),
+        // pc,
+        // nextUp(pc),
+        // nextUp(nextUp(pc))}
+        //
+        // and we test that log1p(pcNeighbors[i]) <= log1p(pcNeighbors[i+1])
+        {
+            double[] pcNeighbors = new double[5];
+            double[] pcNeighborsLog1p = new double[5];
+            double[] pcNeighborsStrictLog1p = new double[5];
+
+            for (int i = -36; i <= 36; i++) {
+                double pc = StrictMath.pow(Math.E, i) - 1;
+
+                pcNeighbors[2] = pc;
+                pcNeighbors[1] = Math.nextDown(pc);
+                pcNeighbors[0] = Math.nextDown(pcNeighbors[1]);
+                pcNeighbors[3] = Math.nextUp(pc);
+                pcNeighbors[4] = Math.nextUp(pcNeighbors[3]);
+
+                for (int j = 0; j < pcNeighbors.length; j++) {
+                    pcNeighborsLog1p[j] = Math.log1p(pcNeighbors[j]);
+                    pcNeighborsStrictLog1p[j] = StrictMath.log1p(pcNeighbors[j]);
+                }
+
+                for (int j = 0; j < pcNeighborsLog1p.length - 1; j++) {
+                    if (pcNeighborsLog1p[j] > pcNeighborsLog1p[j + 1]) {
+                        Assert.fail("Monotonicity failure for Math.log1p on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsLog1p[j] + " and " +
+                                pcNeighborsLog1p[j + 1]);
+                    }
+
+                    if (pcNeighborsStrictLog1p[j] > pcNeighborsStrictLog1p[j + 1]) {
+                        Assert.fail("Monotonicity failure for StrictMath.log1p on " +
+                                pcNeighbors[j] + " and " +
+                                pcNeighbors[j + 1] + "\n\treturned " +
+                                pcNeighborsStrictLog1p[j] + " and " +
+                                pcNeighborsStrictLog1p[j + 1]);
+                    }
+
+
+                }
+
+            }
+        }
+    }
+
+    public static void testLog1pCase(double input, double expected) {
+        testLog1pCaseWithUlpDiff(input, expected, 1);
+    }
+
+    public static void testLog1pCaseWithUlpDiff(double input, double expected, double ulps) {
+        Tests.testUlpDiff("Math.lop1p(double)",
+                input, Math.log1p(input),
+                expected, ulps);
+        Tests.testUlpDiff("StrictMath.log1p(double)",
+                input, StrictMath.log1p(input),
+                expected, ulps);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/MinMax.java b/ojluni/src/test/java/lang/Math/MinMax.java
new file mode 100644
index 0000000..978eb2f
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/MinMax.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 4010528 4010529
+   @summary Math.min and Math.max should treat negative zero as strictly
+            less than positive zero
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class MinMax {
+
+    static void test(String what, float result, float correctResult) {
+        final String resultString = Float.toString(result);
+        final String correctString = Float.toString(correctResult);
+        final String message = what + ": got " + result + ", expected " + correctResult;
+        Assert.assertEquals(resultString, correctString, message);
+    }
+
+    static void test(String what, double result, double correctResult) {
+        final String resultString = Double.toString(result);
+        final String correctString = Double.toString(correctResult);
+        final String message = what + ": got " + result + ", expected " + correctResult;
+        Assert.assertEquals(resultString, correctString, message);
+    }
+
+    @Test
+    public void testMinMax() {
+        float fnz = -0.0f;
+        float fpz = +0.0f;
+
+        test("Math.min(fnz, fnz)", Math.min(fnz, fnz), fnz);
+        test("Math.min(fnz, fpz)", Math.min(fnz, fpz), fnz);
+        test("Math.min(fpz, fnz)", Math.min(fpz, fnz), fnz);
+        test("Math.min(fpz, fpz)", Math.min(fpz, fpz), fpz);
+
+        test("Math.min(-1.0f, fnz)", Math.min(-1.0f, fnz), -1.0f);
+        test("Math.min(-1.0f, fpz)", Math.min(-1.0f, fpz), -1.0f);
+        test("Math.min(+1.0f, fnz)", Math.min(+1.0f, fnz), fnz);
+        test("Math.min(+1.0f, fpz)", Math.min(+1.0f, fpz), fpz);
+        test("Math.min(-1.0f, +1.0f)", Math.min(-1.0f, +1.0f), -1.0f);
+        test("Math.min(fnz, -1.0f)", Math.min(fnz, -1.0f), -1.0f);
+        test("Math.min(fpz, -1.0f)", Math.min(fpz, -1.0f), -1.0f);
+        test("Math.min(fnz, +1.0f)", Math.min(fnz, +1.0f), fnz);
+        test("Math.min(fpz, +1.0f)", Math.min(fpz, +1.0f), fpz);
+        test("Math.min(+1.0f, -1.0f)", Math.min(+1.0f, -1.0f), -1.0f);
+
+        test("Math.max(fnz, fnz)", Math.max(fnz, fnz), fnz);
+        test("Math.max(fnz, fpz)", Math.max(fnz, fpz), fpz);
+        test("Math.max(fpz, fnz)", Math.max(fpz, fnz), fpz);
+        test("Math.max(fpz, fpz)", Math.max(fpz, fpz), fpz);
+
+        test("Math.max(-1.0f, fnz)", Math.max(-1.0f, fnz), fnz);
+        test("Math.max(-1.0f, fpz)", Math.max(-1.0f, fpz), fpz);
+        test("Math.max(+1.0f, fnz)", Math.max(+1.0f, fnz), +1.0f);
+        test("Math.max(+1.0f, fpz)", Math.max(+1.0f, fpz), +1.0f);
+        test("Math.max(-1.0f, +1.0f)", Math.max(-1.0f, +1.0f), +1.0f);
+        test("Math.max(fnz, -1.0f)", Math.max(fnz, -1.0f), fnz);
+        test("Math.max(fpz, -1.0f)", Math.max(fpz, -1.0f), fpz);
+        test("Math.max(fnz, +1.0f)", Math.max(fnz, +1.0f), +1.0f);
+        test("Math.max(fpz, +1.0f)", Math.max(fpz, +1.0f), +1.0f);
+        test("Math.max(+1.0f, -1.0f)", Math.max(+1.0f, -1.0f), +1.0f);
+
+        double dnz = -0.0d;
+        double dpz = +0.0d;
+
+        test("Math.min(dnz, dnz)", Math.min(dnz, dnz), dnz);
+        test("Math.min(dnz, dpz)", Math.min(dnz, dpz), dnz);
+        test("Math.min(dpz, dnz)", Math.min(dpz, dnz), dnz);
+        test("Math.min(dpz, dpz)", Math.min(dpz, dpz), dpz);
+
+        test("Math.min(-1.0d, dnz)", Math.min(-1.0d, dnz), -1.0d);
+        test("Math.min(-1.0d, dpz)", Math.min(-1.0d, dpz), -1.0d);
+        test("Math.min(+1.0d, dnz)", Math.min(+1.0d, dnz), dnz);
+        test("Math.min(+1.0d, dpz)", Math.min(+1.0d, dpz), dpz);
+        test("Math.min(-1.0d, +1.0d)", Math.min(-1.0d, +1.0d), -1.0d);
+        test("Math.min(dnz, -1.0d)", Math.min(dnz, -1.0d), -1.0d);
+        test("Math.min(dpz, -1.0d)", Math.min(dpz, -1.0d), -1.0d);
+        test("Math.min(dnz, +1.0d)", Math.min(dnz, +1.0d), dnz);
+        test("Math.min(dpz, +1.0d)", Math.min(dpz, +1.0d), dpz);
+        test("Math.min(+1.0d, -1.0d)", Math.min(+1.0d, -1.0d), -1.0d);
+
+        test("Math.max(dnz, dnz)", Math.max(dnz, dnz), dnz);
+        test("Math.max(dnz, dpz)", Math.max(dnz, dpz), dpz);
+        test("Math.max(dpz, dnz)", Math.max(dpz, dnz), dpz);
+        test("Math.max(dpz, dpz)", Math.max(dpz, dpz), dpz);
+
+        test("Math.max(-1.0d, dnz)", Math.max(-1.0d, dnz), dnz);
+        test("Math.max(-1.0d, dpz)", Math.max(-1.0d, dpz), dpz);
+        test("Math.max(+1.0d, dnz)", Math.max(+1.0d, dnz), +1.0d);
+        test("Math.max(+1.0d, dpz)", Math.max(+1.0d, dpz), +1.0d);
+        test("Math.max(-1.0d, +1.0d)", Math.max(-1.0d, +1.0d), +1.0d);
+        test("Math.max(dnz, -1.0d)", Math.max(dnz, -1.0d), dnz);
+        test("Math.max(dpz, -1.0d)", Math.max(dpz, -1.0d), dpz);
+        test("Math.max(dnz, +1.0d)", Math.max(dnz, +1.0d), +1.0d);
+        test("Math.max(dpz, +1.0d)", Math.max(dpz, +1.0d), +1.0d);
+        test("Math.max(+1.0d, -1.0d)", Math.max(+1.0d, -1.0d), +1.0d);
+
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/Math/MultiplicationTests.java b/ojluni/src/test/java/lang/Math/MultiplicationTests.java
index 5bd17a6..1feee2f 100644
--- a/ojluni/src/test/java/lang/Math/MultiplicationTests.java
+++ b/ojluni/src/test/java/lang/Math/MultiplicationTests.java
@@ -34,29 +34,29 @@
     // Calculate high 64 bits of 128 product using BigInteger.
     private static long multiplyHighBigInt(long x, long y) {
         return BigInteger.valueOf(x).multiply(BigInteger.valueOf(y))
-            .shiftRight(64).longValue();
+                .shiftRight(64).longValue();
     }
 
     @Test
     public void testMultiplyHigh() {
         // check some boundary cases
         long[][] v = new long[][]{
-            {0L, 0L},
-            {-1L, 0L},
-            {0L, -1L},
-            {1L, 0L},
-            {0L, 1L},
-            {-1L, -1L},
-            {-1L, 1L},
-            {1L, -1L},
-            {1L, 1L},
-            {Long.MAX_VALUE, Long.MAX_VALUE},
-            {Long.MAX_VALUE, -Long.MAX_VALUE},
-            {-Long.MAX_VALUE, Long.MAX_VALUE},
-            {-Long.MAX_VALUE, -Long.MAX_VALUE},
-            {Long.MAX_VALUE, Long.MIN_VALUE},
-            {Long.MIN_VALUE, Long.MAX_VALUE},
-            {Long.MIN_VALUE, Long.MIN_VALUE}
+                {0L, 0L},
+                {-1L, 0L},
+                {0L, -1L},
+                {1L, 0L},
+                {0L, 1L},
+                {-1L, -1L},
+                {-1L, 1L},
+                {1L, -1L},
+                {1L, 1L},
+                {Long.MAX_VALUE, Long.MAX_VALUE},
+                {Long.MAX_VALUE, -Long.MAX_VALUE},
+                {-Long.MAX_VALUE, Long.MAX_VALUE},
+                {-Long.MAX_VALUE, -Long.MAX_VALUE},
+                {Long.MAX_VALUE, Long.MIN_VALUE},
+                {Long.MIN_VALUE, Long.MAX_VALUE},
+                {Long.MIN_VALUE, Long.MIN_VALUE}
         };
 
         for (long[] xy : v) {
diff --git a/ojluni/src/test/java/lang/Math/PowTests.java b/ojluni/src/test/java/lang/Math/PowTests.java
new file mode 100644
index 0000000..9c4f9a0
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/PowTests.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4984407 5033578 8134795
+ * @summary Tests for {Math, StrictMath}.pow
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Math;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class PowTests {
+
+    private PowTests() {
+    }
+
+    static final double infinityD = Double.POSITIVE_INFINITY;
+
+    static void testPowCase(double input1, double input2, double expected) {
+        Tests.test("StrictMath.pow(double, double)", input1, input2,
+                StrictMath.pow(input1, input2), expected);
+
+        // BEGIN Android-added: Document that the results from Math are based on libm's behavior.
+        // The cases known to differ with libm's pow():
+        //   If the first argument is 1.0 then result is always 1.0 (not NaN).
+        //   If the first argument is -1.0 and the second argument is infinite, the result is 1.0 (not
+        //   NaN).
+        // Tests.test("Math.pow(double, double)", input1, input2,
+        //         Math.pow(input1, input2), expected);
+        double strictMathExpected = expected;
+        if (input1 == 1.0) {
+            strictMathExpected = 1.0;
+        } else if (input1 == -1.0 && Double.isInfinite(input2)) {
+            strictMathExpected = 1.0;
+        }
+        Tests.test("Math.pow(double, double)", input1, input2,
+                Math.pow(input1, input2), strictMathExpected);
+        // END Android-added: Document that the results from Math are based on libm's behavior.
+    }
+
+
+    static void testStrictPowCase(double input1, double input2, double expected) {
+        Tests.test("StrictMath.pow(double, double)", input1, input2,
+                StrictMath.pow(input1, input2), expected);
+    }
+
+    static void testNonstrictPowCase(double input1, double input2, double expected) {
+        Tests.test("Math.pow(double, double)", input1, input2,
+                Math.pow(input1, input2), expected);
+    }
+
+    /*
+     * Test for bad negation implementation.
+     */
+    @Test
+    public void testPow() {
+        double[][] testCases = {
+                {-0.0, 3.0, -0.0},
+                {-0.0, 4.0, 0.0},
+                {-infinityD, -3.0, -0.0},
+                {-infinityD, -4.0, 0.0},
+        };
+
+        for (double[] testCase : testCases) {
+            testPowCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+    /*
+     * Test cross-product of different kinds of arguments.
+     */
+    @Test
+    public void testCrossProduct() {
+        double[] testData = {
+                Double.NEGATIVE_INFINITY,
+/* > -oo */                     -Double.MAX_VALUE,
+/**/                            (double) Long.MIN_VALUE,
+/**/                            (double) -((1L << 53) + 2L),
+                                -0x1.0p65,
+                                -0x1.0000000000001p64,
+                                -0x1.0p64,
+/**/                            (double) -((1L << 53)),
+/**/                            (double) -((1L << 53) - 1L),
+/**/                            -((double) Integer.MAX_VALUE + 4.0),
+/**/                            (double) Integer.MIN_VALUE - 1.0,
+/**/                            (double) Integer.MIN_VALUE,
+/**/                            (double) Integer.MIN_VALUE + 1.0,
+                                -0x1.0p31 + 2.0,
+                                -0x1.0p31 + 1.0,
+                                -0x1.0000000000001p31,
+                                -0x1.0p31,
+/**/                            -Math.PI,
+/**/                            -3.0,
+/**/                            -Math.E,
+/**/                            -2.0,
+/**/                            -1.0000000000000004,
+/* < -1.0 */                    -1.0000000000000002, // nextAfter(-1.0, -oo)
+                                -1.0,
+/* > -1.0 */                    -0.9999999999999999, // nextAfter(-1.0, +oo)
+/* > -1.0 */                    -0.9999999999999998,
+                                -0x1.fffffp-1,
+                                -0x1.ffffeffffffffp-1,
+/**/                            -0.5,
+/**/                            -1.0 / 3.0,
+/* < 0.0 */                     -Double.MIN_VALUE,
+                                -0.0,
+                                +0.0,
+/* > 0.0 */                     +Double.MIN_VALUE,
+/**/                            +1.0 / 3.0,
+/**/                            +0.5,
+                                +0x1.ffffeffffffffp-1,
+                                +0x1.fffffp-1,
+/**/                            +0.9999999999999998,
+/* < +1.0 */                    +0.9999999999999999, // nextAfter(-1.0, +oo)
+                                +1.0,
+/* > 1.0 */                     +1.0000000000000002, // nextAfter(+1.0, +oo)
+/**/                            +1.0000000000000004,
+/**/                            +2.0,
+/**/                            +Math.E,
+/**/                            +3.0,
+/**/                            +Math.PI,
+                                0x1.0p31,
+                                0x1.0000000000001p31,
+                                0x1.0p31 + 1.0,
+                                0x1.0p31 + 2.0,
+/**/                            -(double) Integer.MIN_VALUE - 1.0,
+/**/                            -(double) Integer.MIN_VALUE,
+/**/                            -(double) Integer.MIN_VALUE + 1.0,
+/**/                            (double) Integer.MAX_VALUE + 4.0,
+/**/                            (double) ((1L << 53) - 1L),
+/**/                            (double) ((1L << 53)),
+/**/                            (double) ((1L << 53) + 2L),
+                                0x1.0p64,
+                                0x1.0000000000001p64,
+                                0x1.0p65,
+/**/                            -(double) Long.MIN_VALUE,
+/* < oo */                      Double.MAX_VALUE,
+                                Double.POSITIVE_INFINITY,
+                                Double.NaN
+        };
+
+        double NaN = Double.NaN;
+        for (double x : testData) {
+            for (double y : testData) {
+                double expected = NaN;
+                double actual;
+
+                // First, switch on y
+                if (Double.isNaN(y)) {
+                    expected = NaN;
+                } else if (y == 0.0) {
+                    expected = 1.0;
+                } else if (Double.isInfinite(y)) {
+                    if (y > 0) { // x ^ (+oo)
+                        if (Math.abs(x) > 1.0) {
+                            expected = Double.POSITIVE_INFINITY;
+                        } else if (Math.abs(x) == 1.0) {
+                            expected = NaN;
+                        } else if (Math.abs(x) < 1.0) {
+                            expected = +0.0;
+                        } else { // x is NaN
+                            assert Double.isNaN(x);
+                            expected = NaN;
+                        }
+                    } else { // x ^ (-oo)
+                        if (Math.abs(x) > 1.0) {
+                            expected = +0.0;
+                        } else if (Math.abs(x) == 1.0) {
+                            expected = NaN;
+                        } else if (Math.abs(x) < 1.0) {
+                            expected = Double.POSITIVE_INFINITY;
+                        } else { // x is NaN
+                            assert Double.isNaN(x);
+                            expected = NaN;
+                        }
+                    } /* end Double.isInfinite(y) */
+                } else if (y == 1.0) {
+                    expected = x;
+                } else if (Double.isNaN(x)) { // Now start switching on x
+                    Assert.assertNotEquals(y, 0.0);
+                    expected = NaN;
+                } else if (x == Double.NEGATIVE_INFINITY) {
+                    expected = (y < 0.0) ? f2(y) : f1(y);
+                } else if (x == Double.POSITIVE_INFINITY) {
+                    expected = (y < 0.0) ? +0.0 : Double.POSITIVE_INFINITY;
+                } else if (equivalent(x, +0.0)) {
+                    Assert.assertNotEquals(y, 0.0);
+                    expected = (y < 0.0) ? Double.POSITIVE_INFINITY : +0.0;
+                } else if (equivalent(x, -0.0)) {
+                    Assert.assertNotEquals(y, 0.0);
+                    expected = (y < 0.0) ? f1(y) : f2(y);
+                } else if (x < 0.0) {
+                    Assert.assertNotEquals(y, 0.0);
+                    testStrictPowCase(x, y, f3(x, y));
+                    testNonstrictPowCase(x, y, f3ns(x, y));
+                    continue;
+                } else {
+                    // go to next iteration
+                    expected = NaN;
+                    continue;
+                }
+
+                testPowCase(x, y, expected);
+            } // y
+        } // x
+    }
+
+    static boolean equivalent(double a, double b) {
+        return Double.compare(a, b) == 0;
+    }
+
+    static double f1(double y) {
+        return (intClassify(y) == 1) ?
+                Double.NEGATIVE_INFINITY :
+                Double.POSITIVE_INFINITY;
+    }
+
+    static double f2(double y) {
+        return (intClassify(y) == 1) ? -0.0 : 0.0;
+    }
+
+    static double f3(double x, double y) {
+        switch (intClassify(y)) {
+            case 0:
+                return StrictMath.pow(Math.abs(x), y);
+            // break;
+
+            case 1:
+                return -StrictMath.pow(Math.abs(x), y);
+            // break;
+
+            case -1:
+                return Double.NaN;
+            // break;
+
+            default:
+                throw new AssertionError("Bad classification.");
+                // break;
+        }
+    }
+
+    static double f3ns(double x, double y) {
+        switch (intClassify(y)) {
+            case 0:
+                return Math.pow(Math.abs(x), y);
+            // break;
+
+            case 1:
+                return -Math.pow(Math.abs(x), y);
+            // break;
+
+            case -1:
+                return Double.NaN;
+            // break;
+
+            default:
+                throw new AssertionError("Bad classification.");
+                // break;
+        }
+    }
+
+    static boolean isFinite(double a) {
+        return (0.0 * a == 0);
+    }
+
+    /**
+     * Return classification of argument: -1 for non-integers, 0 for even integers, 1 for odd
+     * integers.
+     */
+    static int intClassify(double a) {
+        if (!isFinite(a) || // NaNs and infinities
+                (a != Math.floor(a))) { // only integers are fixed-points of floor
+            return -1;
+        } else {
+            // Determine if argument is an odd or even integer.
+
+            a = StrictMath.abs(a); // absolute value doesn't affect odd/even
+
+            if (a + 1.0 == a) { // a > maximum odd floating-point integer
+                return 0; // Large integers are all even
+            } else { // Convert double -> long and look at low-order bit
+                long ell = (long) a;
+                return ((ell & 0x1L) == (long) 1) ? 1 : 0;
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/Rint.java b/ojluni/src/test/java/lang/Math/Rint.java
new file mode 100644
index 0000000..f11572f
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/Rint.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4101566 4831589
+ * @summary Check for correct implementation of Math.rint(double)
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+
+public class Rint {
+
+    static void testRintCase(double input, double expected) {
+        Tests.test("Math.rint", input, Math.rint(input), expected);
+        Tests.test("Math.rint", -input, Math.rint(-input), -expected);
+        Tests.test("StrictMath.rint",
+                input, StrictMath.rint(input), expected);
+        Tests.test("StrictMath.rint", -input,
+                StrictMath.rint(-input), -expected);
+    }
+
+    @Test
+    public void testRint() {
+        double twoToThe52 = Math.scalb(1.0, 52); // 2^52
+
+        double[][] testCases = {
+                {0.0, 0.0},
+                {Double.MIN_VALUE, 0.0},
+                {Math.nextDown(Double.MIN_NORMAL), 0.0},
+                {Double.MIN_NORMAL, 0.0},
+
+                {0.2, 0.0},
+
+                {Math.nextDown(0.5), 0.0},
+                {0.5, 0.0},
+                {Math.nextUp(0.5), 1.0},
+
+                {0.7, 1.0},
+                {Math.nextDown(1.0), 1.0},
+                {1.0, 1.0},
+                {Math.nextUp(1.0), 1.0},
+
+                {Math.nextDown(1.5), 1.0},
+                {1.5, 2.0},
+                {Math.nextUp(1.5), 2.0},
+
+                {4.2, 4.0},
+                {4.5, 4.0},
+                {4.7, 5.0},
+
+                {7.5, 8.0},
+                {7.2, 7.0},
+                {7.7, 8.0},
+
+                {150000.75, 150001.0},
+                {300000.5, 300000.0},
+                {Math.nextUp(300000.5), 300001.0},
+                {Math.nextDown(300000.75), 300001.0},
+                {300000.75, 300001.0},
+                {Math.nextUp(300000.75), 300001.0},
+                {300000.99, 300001.0},
+                {262144.75, 262145.0}, //(2^18 ) + 0.75
+                {499998.75, 499999.0},
+                {524287.75, 524288.0}, //(2^19 -1) + 0.75
+                {524288.75, 524289.0},
+
+                {Math.nextDown(twoToThe52), twoToThe52},
+                {twoToThe52, twoToThe52},
+                {Math.nextUp(twoToThe52), Math.nextUp(twoToThe52)},
+
+                {Double.MAX_VALUE, Double.MAX_VALUE},
+                {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY},
+                {Double.NaN, Double.NaN}
+
+        };
+
+        for (double[] testCase : testCases) {
+            testRintCase(testCase[0], testCase[1]);
+        }
+
+        // Test values throughout exponent range
+        for (double d = Double.MIN_VALUE;
+                d < Double.POSITIVE_INFINITY; d *= 2) {
+            testRintCase(d, ((d <= 0.5) ? 0.0 : d));
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/RoundTests.java b/ojluni/src/test/java/lang/Math/RoundTests.java
new file mode 100644
index 0000000..36e1984
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/RoundTests.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 6430675 8010430
+ * @summary Check for correct implementation of {Math, StrictMath}.round
+ */
+public class RoundTests {
+
+    @Test
+    public void testNearDoubleHalfCases() {
+        double[][] testCases = {
+                {+0x1.fffffffffffffp-2, 0.0},
+                {+0x1.0p-1, 1.0}, // +0.5
+                {+0x1.0000000000001p-1, 1.0},
+
+                {-0x1.fffffffffffffp-2, 0.0},
+                {-0x1.0p-1, 0.0}, // -0.5
+                {-0x1.0000000000001p-1, -1.0},
+        };
+
+        for (double[] testCase : testCases) {
+            testNearHalfCases(testCase[0], (long) testCase[1]);
+        }
+    }
+
+    private static void testNearHalfCases(double input, double expected) {
+        Tests.test("Math.round", input, Math.round(input), expected);
+        Tests.test("StrictMath.round", input, StrictMath.round(input), expected);
+    }
+
+    @Test
+    public void testNearFloatHalfCases() {
+        float[][] testCases = {
+                {+0x1.fffffep-2f, 0.0f},
+                {+0x1.0p-1f, 1.0f}, // +0.5
+                {+0x1.000002p-1f, 1.0f},
+
+                {-0x1.fffffep-2f, 0.0f},
+                {-0x1.0p-1f, 0.0f}, // -0.5
+                {-0x1.000002p-1f, -1.0f},
+        };
+
+        for (float[] testCase : testCases) {
+            testNearHalfCases(testCase[0], (int) testCase[1]);
+        }
+    }
+
+    private static void testNearHalfCases(float input, float expected) {
+        Tests.test("Math.round", input, Math.round(input), expected);
+        Tests.test("StrictMath.round", input, StrictMath.round(input), expected);
+    }
+
+    @Test
+    public void testSpecialCases() {
+        Tests.test("Math.round", Float.NaN, Math.round(Float.NaN), 0.0F);
+        Tests.test("Math.round", Float.POSITIVE_INFINITY,
+                Math.round(Float.POSITIVE_INFINITY), Integer.MAX_VALUE);
+        Tests.test("Math.round", Float.NEGATIVE_INFINITY,
+                Math.round(Float.NEGATIVE_INFINITY), Integer.MIN_VALUE);
+        Tests.test("Math.round", -(float) Integer.MIN_VALUE,
+                Math.round(-(float) Integer.MIN_VALUE), Integer.MAX_VALUE);
+        Tests.test("Math.round", (float) Integer.MIN_VALUE,
+                Math.round((float) Integer.MIN_VALUE), Integer.MIN_VALUE);
+        Tests.test("Math.round", 0F, Math.round(0F), 0.0F);
+        Tests.test("Math.round", Float.MIN_VALUE,
+                Math.round(Float.MIN_VALUE), 0.0F);
+        Tests.test("Math.round", -Float.MIN_VALUE,
+                Math.round(-Float.MIN_VALUE), 0.0F);
+
+        Tests.test("Math.round", Double.NaN, Math.round(Double.NaN), 0.0);
+        Tests.test("Math.round", Double.POSITIVE_INFINITY,
+                Math.round(Double.POSITIVE_INFINITY), Long.MAX_VALUE);
+        Tests.test("Math.round", Double.NEGATIVE_INFINITY,
+                Math.round(Double.NEGATIVE_INFINITY), Long.MIN_VALUE);
+        Tests.test("Math.round", -(double) Long.MIN_VALUE,
+                Math.round(-(double) Long.MIN_VALUE), Long.MAX_VALUE);
+        Tests.test("Math.round", (double) Long.MIN_VALUE,
+                Math.round((double) Long.MIN_VALUE), Long.MIN_VALUE);
+        Tests.test("Math.round", 0, Math.round(0), 0.0);
+        Tests.test("Math.round", Double.MIN_VALUE,
+                Math.round(Double.MIN_VALUE), 0.0);
+        Tests.test("Math.round", -Double.MIN_VALUE,
+                Math.round(-Double.MIN_VALUE), 0.0);
+    }
+
+    @Test
+    public void testUnityULPCases() {
+        for (float sign : new float[]{-1, 1}) {
+            for (float v1 : new float[]{1 << 23, 1 << 24}) {
+                for (int k = -5; k <= 5; k++) {
+                    float value = (v1 + k) * sign;
+                    float actual = Math.round(value);
+                    Tests.test("Math.round", value, actual, value);
+                }
+            }
+        }
+
+        for (double sign : new double[]{-1, 1}) {
+            for (double v1 : new double[]{1L << 52, 1L << 53}) {
+                for (int k = -5; k <= 5; k++) {
+                    double value = (v1 + k) * sign;
+                    double actual = Math.round(value);
+                    Tests.test("Math.round", value, actual, value);
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/SinCosCornerCasesTests.java b/ojluni/src/test/java/lang/Math/SinCosCornerCasesTests.java
new file mode 100644
index 0000000..e2f2a23
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/SinCosCornerCasesTests.java
@@ -0,0 +1,2910 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8143353
+ * @summary Test corner cases of sin and cos
+ * @build Tests
+ * @build SinCosCornerCasesTests
+ * @run main SinCosCornerCasesTests
+ * @author Vivek Deshpande
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+
+public class SinCosCornerCasesTests {
+
+    private SinCosCornerCasesTests() {
+    }
+
+    @Test
+    public void testCornerCasesSin() {
+        double[][] testCases = {
+                {0x1.9283586503fep-5, 0x1.9259e3708bd3ap-5, 0x1.9259e3708bd39p-5},
+                {-0x1.9283586503fep-5, -0x1.9259e3708bd3ap-5, -0x1.9259e3708bd39p-5},
+                {0x1.d7bdcd778049fp-5, 0x1.d77b117f230d6p-5, 0x1.d77b117f230d5p-5},
+                {-0x1.d7bdcd778049fp-5, -0x1.d77b117f230d6p-5, -0x1.d77b117f230d5p-5},
+                {0x1.a202b3fb84788p-4, 0x1.a1490c8c06ba7p-4, 0x1.a1490c8c06ba6p-4},
+                {-0x1.a202b3fb84788p-4, -0x1.a1490c8c06ba7p-4, -0x1.a1490c8c06ba6p-4},
+                {0x1.d037cb27ee6dfp-3, 0x1.cc40c3805229ap-3, 0x1.cc40c3805229bp-3},
+                {-0x1.d037cb27ee6dfp-3, -0x1.cc40c3805229ap-3, -0x1.cc40c3805229bp-3},
+                {0x1.d5064e6fe82c5p-3, 0x1.d0ef799001ba9p-3, 0x1.d0ef799001baap-3},
+                {-0x1.d5064e6fe82c5p-3, -0x1.d0ef799001ba9p-3, -0x1.d0ef799001baap-3},
+                {0x1.fe767739d0f6dp-2, 0x1.e9950730c4696p-2, 0x1.e9950730c4696p-2},
+                {-0x1.fe767739d0f6dp-2, -0x1.e9950730c4696p-2, -0x1.e9950730c4696p-2},
+                {0x1.d98c4c612718dp-1, 0x1.98dcd09337793p-1, 0x1.98dcd09337792p-1},
+                {-0x1.d98c4c612718dp-1, -0x1.98dcd09337793p-1, -0x1.98dcd09337792p-1},
+                {0x1.921fb54442d18p0, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p0, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.0000001f8p500, 0x1.70a9d825b5064p-1, 0x1.70a9d825b5065p-1},
+                {0x1.0000001f8p500, -0x1.70a9d825b5064p-1, -0x1.70a9d825b5065p-1},
+                {-0x1.00c0bf8p700, 0x1.bf3980c6c1e9fp-1, 0x1.bf3980c6c1eap-1},
+                {0x1.00c0bf8p700, -0x1.bf3980c6c1e9fp-1, -0x1.bf3980c6c1eap-1},
+                {-0x1.13fffffffff8p6, 0x1.d62899d48b43ap-4, 0x1.d62899d48b439p-4},
+                {0x1.13fffffffff8p6, -0x1.d62899d48b43ap-4, -0x1.d62899d48b439p-4},
+                {-0x1.17c5920767dfcp-5, -0x1.17b7a60ce1f15p-5, -0x1.17b7a60ce1f14p-5},
+                {0x1.17c5920767dfcp-5, 0x1.17b7a60ce1f15p-5, 0x1.17b7a60ce1f14p-5},
+                {-0x1.1d99be08713ccp2, 0x1.f0192b794fbbep-1, 0x1.f0192b794fbbfp-1},
+                {0x1.1d99be08713ccp2, -0x1.f0192b794fbbep-1, -0x1.f0192b794fbbfp-1},
+                {-0x1.1ddbfd64fc0d3p81, -0x1.5e61328c0034fp-3, -0x1.5e61328c0034ep-3},
+                {0x1.1ddbfd64fc0d3p81, 0x1.5e61328c0034fp-3, 0x1.5e61328c0034ep-3},
+                {-0x1.1e2a1563e068ep7, 0x1.fb028c5df1db4p-1, 0x1.fb028c5df1db3p-1},
+                {0x1.1e2a1563e068ep7, -0x1.fb028c5df1db4p-1, -0x1.fb028c5df1db3p-1},
+                {-0x1.2e07a91314dp-3, -0x1.2cefb196ba208p-3, -0x1.2cefb196ba207p-3},
+                {0x1.2e07a91314dp-3, 0x1.2cefb196ba208p-3, 0x1.2cefb196ba207p-3},
+                {-0x1.3bcec270444e2p3, 0x1.b80f489d3edf5p-2, 0x1.b80f489d3edf4p-2},
+                {0x1.3bcec270444e2p3, -0x1.b80f489d3edf5p-2, -0x1.b80f489d3edf4p-2},
+                {-0x1.500000000004p-20, -0x1.4fffffffffa39p-20, -0x1.4fffffffffa38p-20},
+                {0x1.500000000004p-20, 0x1.4fffffffffa39p-20, 0x1.4fffffffffa38p-20},
+                {-0x1.559001a42d90cp1, -0x1.d29da5b44f51cp-2, -0x1.d29da5b44f51bp-2},
+                {0x1.559001a42d90cp1, 0x1.d29da5b44f51cp-2, 0x1.d29da5b44f51bp-2},
+                {-0x1.597bf3e9776b7p99, -0x1.f85f526147f78p-1, -0x1.f85f526147f79p-1},
+                {0x1.597bf3e9776b7p99, 0x1.f85f526147f78p-1, 0x1.f85f526147f79p-1},
+                {-0x1.6c6cbc45dc8dep7, -0x1.6d61b58c99c43p-59, -0x1.6d61b58c99c42p-59},
+                {0x1.6c6cbc45dc8dep7, 0x1.6d61b58c99c43p-59, 0x1.6d61b58c99c42p-59},
+                {-0x1.73d8d173f90dp4, 0x1.e5c3c08a258a8p-1, 0x1.e5c3c08a258a7p-1},
+                {0x1.73d8d173f90dp4, -0x1.e5c3c08a258a8p-1, -0x1.e5c3c08a258a7p-1},
+                {-0x1.8c202d3a31802p6, 0x1.feb36806ca5fbp-1, 0x1.feb36806ca5fcp-1},
+                {0x1.8c202d3a31802p6, -0x1.feb36806ca5fbp-1, -0x1.feb36806ca5fcp-1},
+                {-0x1.acd538b1a6d5dp-1, -0x1.7c6c7b01b98dap-1, -0x1.7c6c7b01b98d9p-1},
+                {0x1.acd538b1a6d5dp-1, 0x1.7c6c7b01b98dap-1, 0x1.7c6c7b01b98d9p-1},
+                {-0x1.b7525ac97e0d2p2, -0x1.191be2059dcb6p-1, -0x1.191be2059dcb5p-1},
+                {0x1.b7525ac97e0d2p2, 0x1.191be2059dcb6p-1, 0x1.191be2059dcb5p-1},
+                {-0x1.bee5fa8a84b02p0, -0x1.f8305993a212cp-1, -0x1.f8305993a212dp-1},
+                {0x1.bee5fa8a84b02p0, 0x1.f8305993a212cp-1, 0x1.f8305993a212dp-1},
+                {-0x1.c393979fe5921p9, 0x1.ff3b13530fd71p-1, 0x1.ff3b13530fd7p-1},
+                {0x1.c393979fe5921p9, -0x1.ff3b13530fd71p-1, -0x1.ff3b13530fd7p-1},
+                {-0x1.c48ffc72563c8p18, -0x1.f119da81a4da6p-1, -0x1.f119da81a4da5p-1},
+                {0x1.c48ffc72563c8p18, 0x1.f119da81a4da6p-1, 0x1.f119da81a4da5p-1},
+                {-0x1.c79548bc31856p3, -0x1.fd73b81e04cccp-1, -0x1.fd73b81e04ccdp-1},
+                {0x1.c79548bc31856p3, 0x1.fd73b81e04cccp-1, 0x1.fd73b81e04ccdp-1},
+                {-0x1.cb6p-3, -0x1.c7885aef33a95p-3, -0x1.c7885aef33a94p-3},
+                {0x1.cb6p-3, 0x1.c7885aef33a95p-3, 0x1.c7885aef33a94p-3},
+                {-0x1.e64ddaf7bd72fp-7, -0x1.e6494911eedd1p-7, -0x1.e6494911eeddp-7},
+                {0x1.e64ddaf7bd72fp-7, 0x1.e6494911eedd1p-7, 0x1.e6494911eeddp-7},
+                {-0x1.ecdd0fbf07942p5, 0x1.e180eef5b1c88p-1, 0x1.e180eef5b1c89p-1},
+                {0x1.ecdd0fbf07942p5, -0x1.e180eef5b1c88p-1, -0x1.e180eef5b1c89p-1},
+                {-0x1.f073a23292337p2, -0x1.fd98d20c1be44p-1, -0x1.fd98d20c1be43p-1},
+                {0x1.f073a23292337p2, 0x1.fd98d20c1be44p-1, 0x1.fd98d20c1be43p-1},
+                {-0x1.f5e4c410f4ef8p15, -0x1.7268c112297c8p-5, -0x1.7268c112297c9p-5},
+                {0x1.f5e4c410f4ef8p15, 0x1.7268c112297c8p-5, 0x1.7268c112297c9p-5},
+                {-0x1.f8000000002p95, 0x1.420796146070ep-18, 0x1.420796146070fp-18},
+                {0x1.f8000000002p95, -0x1.420796146070ep-18, -0x1.420796146070fp-18},
+                {-0x1.f9365d79546e1p-2, -0x1.e4f6dc499d9ccp-2, -0x1.e4f6dc499d9cdp-2},
+                {0x1.f9365d79546e1p-2, 0x1.e4f6dc499d9ccp-2, 0x1.e4f6dc499d9cdp-2},
+                {-0x1.ffffffffffe7ep1023, 0x1.b2ef99b140d65p-14, 0x1.b2ef99b140d66p-14},
+                {0x1.ffffffffffe7ep1023, -0x1.b2ef99b140d65p-14, -0x1.b2ef99b140d66p-14},
+                {0x1.0p15, 0x1.db0ffc3ecc6e4p-1, 0x1.db0ffc3ecc6e3p-1},
+                {-0x1.0p15, -0x1.db0ffc3ecc6e4p-1, -0x1.db0ffc3ecc6e3p-1},
+                {0x1.0000000000001p13, -0x1.e98f87098b627p-1, -0x1.e98f87098b626p-1},
+                {-0x1.0000000000001p13, 0x1.e98f87098b627p-1, 0x1.e98f87098b626p-1},
+                {0x1.0000000000001p52, 0x1.053c35068e10dp-4, 0x1.053c35068e10ep-4},
+                {-0x1.0000000000001p52, -0x1.053c35068e10dp-4, -0x1.053c35068e10ep-4},
+                {0x1.0000000000001p228, 0x1.72d421b6884e5p-1, 0x1.72d421b6884e6p-1},
+                {-0x1.0000000000001p228, -0x1.72d421b6884e5p-1, -0x1.72d421b6884e6p-1},
+                {0x1.0000000000001p491, 0x1.77fba987c5654p-1, 0x1.77fba987c5653p-1},
+                {-0x1.0000000000001p491, -0x1.77fba987c5654p-1, -0x1.77fba987c5653p-1},
+                {0x1.0000000000003p215, -0x1.723b2625331afp-1, -0x1.723b2625331bp-1},
+                {-0x1.0000000000003p215, 0x1.723b2625331afp-1, 0x1.723b2625331bp-1},
+                {0x1.0000000000006p0, 0x1.aed548f090cf5p-1, 0x1.aed548f090cf4p-1},
+                {-0x1.0000000000006p0, -0x1.aed548f090cf5p-1, -0x1.aed548f090cf4p-1},
+                {0x1.0000000000007p8, -0x1.ff983208c7dc9p-1, -0x1.ff983208c7dcap-1},
+                {-0x1.0000000000007p8, 0x1.ff983208c7dc9p-1, 0x1.ff983208c7dcap-1},
+                {0x1.0000000000007p275, 0x1.ffef29dc38453p-1, 0x1.ffef29dc38452p-1},
+                {-0x1.0000000000007p275, -0x1.ffef29dc38453p-1, -0x1.ffef29dc38452p-1},
+                {0x1.0000000000007p449, -0x1.fa88c375723c1p-8, -0x1.fa88c375723cp-8},
+                {-0x1.0000000000007p449, 0x1.fa88c375723c1p-8, 0x1.fa88c375723cp-8},
+                {0x1.0000000000011p644, 0x1.fff5322c94eaep-1, 0x1.fff5322c94eafp-1},
+                {-0x1.0000000000011p644, -0x1.fff5322c94eaep-1, -0x1.fff5322c94eafp-1},
+                {0x1.000000000001fp164, -0x1.a73630af8f15cp-1, -0x1.a73630af8f15bp-1},
+                {-0x1.000000000001fp164, 0x1.a73630af8f15cp-1, 0x1.a73630af8f15bp-1},
+                {0x1.0000000000038p380, 0x1.1c548f9249e44p-2, 0x1.1c548f9249e45p-2},
+                {-0x1.0000000000038p380, -0x1.1c548f9249e44p-2, -0x1.1c548f9249e45p-2},
+                {0x1.0000000000118p380, 0x1.ca965bd2c4dffp-3, 0x1.ca965bd2c4dfep-3},
+                {-0x1.0000000000118p380, -0x1.ca965bd2c4dffp-3, -0x1.ca965bd2c4dfep-3},
+                {0x1.000000000012cp2, -0x1.837b9dddc24dp-1, -0x1.837b9dddc24cfp-1},
+                {-0x1.000000000012cp2, 0x1.837b9dddc24dp-1, 0x1.837b9dddc24cfp-1},
+                {0x1.00000000001f8p700, 0x1.d82c1784c3eccp-2, 0x1.d82c1784c3ecbp-2},
+                {-0x1.00000000001f8p700, -0x1.d82c1784c3eccp-2, -0x1.d82c1784c3ecbp-2},
+                {0x1.00000000002p-7, 0x1.fffeaaaaef2eep-8, 0x1.fffeaaaaef2efp-8},
+                {-0x1.00000000002p-7, -0x1.fffeaaaaef2eep-8, -0x1.fffeaaaaef2efp-8},
+                {0x1.00000000002p40, -0x1.0871bddd90fc6p-1, -0x1.0871bddd90fc5p-1},
+                {-0x1.00000000002p40, 0x1.0871bddd90fc6p-1, 0x1.0871bddd90fc5p-1},
+                {0x1.0000000000201p-7, 0x1.fffeaaaaef2fp-8, 0x1.fffeaaaaef2f1p-8},
+                {-0x1.0000000000201p-7, -0x1.fffeaaaaef2fp-8, -0x1.fffeaaaaef2f1p-8},
+                {0x1.0000000000221p-7, 0x1.fffeaaaaef33p-8, 0x1.fffeaaaaef331p-8},
+                {-0x1.0000000000221p-7, -0x1.fffeaaaaef33p-8, -0x1.fffeaaaaef331p-8},
+                {0x1.000000000023ap-7, 0x1.fffeaaaaef362p-8, 0x1.fffeaaaaef363p-8},
+                {-0x1.000000000023ap-7, -0x1.fffeaaaaef362p-8, -0x1.fffeaaaaef363p-8},
+                {0x1.0000000004p45, 0x1.e0c6edfa93601p-9, 0x1.e0c6edfa93602p-9},
+                {-0x1.0000000004p45, -0x1.e0c6edfa93601p-9, -0x1.e0c6edfa93602p-9},
+                {0x1.0000000cp40, 0x1.ea1f618356db1p-5, 0x1.ea1f618356dbp-5},
+                {-0x1.0000000cp40, -0x1.ea1f618356db1p-5, -0x1.ea1f618356dbp-5},
+                {0x1.00000013c86f4p-2, 0x1.faaeed7587542p-3, 0x1.faaeed7587541p-3},
+                {-0x1.00000013c86f4p-2, -0x1.faaeed7587542p-3, -0x1.faaeed7587541p-3},
+                {0x1.001p13, 0x1.540bc7785680bp-1, 0x1.540bc7785680ap-1},
+                {-0x1.001p13, -0x1.540bc7785680bp-1, -0x1.540bc7785680ap-1},
+                {0x1.003p699, -0x1.37a7cb907a2e5p-1, -0x1.37a7cb907a2e6p-1},
+                {-0x1.003p699, 0x1.37a7cb907a2e5p-1, 0x1.37a7cb907a2e6p-1},
+                {0x1.0038p40, -0x1.29e5845fc54b5p-1, -0x1.29e5845fc54b6p-1},
+                {-0x1.0038p40, 0x1.29e5845fc54b5p-1, 0x1.29e5845fc54b6p-1},
+                {0x1.007p10, 0x1.ffe5ca4656491p-1, 0x1.ffe5ca4656492p-1},
+                {-0x1.007p10, -0x1.ffe5ca4656491p-1, -0x1.ffe5ca4656492p-1},
+                {0x1.007p25, 0x1.ea4df82db014bp-1, 0x1.ea4df82db014ap-1},
+                {-0x1.007p25, -0x1.ea4df82db014bp-1, -0x1.ea4df82db014ap-1},
+                {0x1.007p41, 0x1.fe757aef1c80cp-1, 0x1.fe757aef1c80dp-1},
+                {-0x1.007p41, -0x1.fe757aef1c80cp-1, -0x1.fe757aef1c80dp-1},
+                {0x1.00cp41, 0x1.e9b71805ec068p-7, 0x1.e9b71805ec069p-7},
+                {-0x1.00cp41, -0x1.e9b71805ec068p-7, -0x1.e9b71805ec069p-7},
+                {0x1.01c00000001p0, 0x1.b0b6d0a540583p-1, 0x1.b0b6d0a540582p-1},
+                {-0x1.01c00000001p0, -0x1.b0b6d0a540583p-1, -0x1.b0b6d0a540582p-1},
+                {0x1.02322e46da919p-2, 0x1.fef0092627012p-3, 0x1.fef0092627013p-3},
+                {-0x1.02322e46da919p-2, -0x1.fef0092627012p-3, -0x1.fef0092627013p-3},
+                {0x1.02a236478p-2, 0x1.ffc90059804a1p-3, 0x1.ffc90059804ap-3},
+                {-0x1.02a236478p-2, -0x1.ffc90059804a1p-3, -0x1.ffc90059804ap-3},
+                {0x1.02a65d08ca5e5p-2, 0x1.ffd10a6b5429fp-3, 0x1.ffd10a6b5429ep-3},
+                {-0x1.02a65d08ca5e5p-2, -0x1.ffd10a6b5429fp-3, -0x1.ffd10a6b5429ep-3},
+                {0x1.02a65d2dce49ap-2, 0x1.ffd10ab302a3fp-3, 0x1.ffd10ab302a4p-3},
+                {-0x1.02a65d2dce49ap-2, -0x1.ffd10ab302a3fp-3, -0x1.ffd10ab302a4p-3},
+                {0x1.02ae7238ap-2, 0x1.ffe0b1764ca4cp-3, 0x1.ffe0b1764ca4dp-3},
+                {-0x1.02ae7238ap-2, -0x1.ffe0b1764ca4cp-3, -0x1.ffe0b1764ca4dp-3},
+                {0x1.0501d22221dacp621, -0x1.f68f0e26c0f6bp-3, -0x1.f68f0e26c0f6ap-3},
+                {-0x1.0501d22221dacp621, 0x1.f68f0e26c0f6bp-3, 0x1.f68f0e26c0f6ap-3},
+                {0x1.06ffffffffff8p0, 0x1.b63c41f09eb75p-1, 0x1.b63c41f09eb74p-1},
+                {-0x1.06ffffffffff8p0, -0x1.b63c41f09eb75p-1, -0x1.b63c41f09eb74p-1},
+                {0x1.07023d3d44215p12, -0x1.ffdc173adabb2p-1, -0x1.ffdc173adabb1p-1},
+                {-0x1.07023d3d44215p12, 0x1.ffdc173adabb2p-1, 0x1.ffdc173adabb1p-1},
+                {0x1.0895a7a3e8ae6p-5, 0x1.0889e11bef135p-5, 0x1.0889e11bef136p-5},
+                {-0x1.0895a7a3e8ae6p-5, -0x1.0889e11bef135p-5, -0x1.0889e11bef136p-5},
+                {0x1.08d5d69840601p-5, 0x1.08ca077c76445p-5, 0x1.08ca077c76446p-5},
+                {-0x1.08d5d69840601p-5, -0x1.08ca077c76445p-5, -0x1.08ca077c76446p-5},
+                {0x1.0ep6, -0x1.ff7fbe518023fp-1, -0x1.ff7fbe518023ep-1},
+                {-0x1.0ep6, 0x1.ff7fbe518023fp-1, 0x1.ff7fbe518023ep-1},
+                {0x1.107ba49c346e4p9, -0x1.fd6c68b877afep-1, -0x1.fd6c68b877affp-1},
+                {-0x1.107ba49c346e4p9, 0x1.fd6c68b877afep-1, 0x1.fd6c68b877affp-1},
+                {0x1.149154477444p745, -0x1.a2ba6bc70bce4p-1, -0x1.a2ba6bc70bce5p-1},
+                {-0x1.149154477444p745, 0x1.a2ba6bc70bce4p-1, 0x1.a2ba6bc70bce5p-1},
+                {0x1.1663c0e51818p-5, 0x1.165609790f235p-5, 0x1.165609790f234p-5},
+                {-0x1.1663c0e51818p-5, -0x1.165609790f235p-5, -0x1.165609790f234p-5},
+                {0x1.1745d1745d176p238, -0x1.fc0523ff94e45p-1, -0x1.fc0523ff94e44p-1},
+                {-0x1.1745d1745d176p238, 0x1.fc0523ff94e45p-1, 0x1.fc0523ff94e44p-1},
+                {0x1.17472a408a3ep97, 0x1.f34a729c584bdp-1, 0x1.f34a729c584bcp-1},
+                {-0x1.17472a408a3ep97, -0x1.f34a729c584bdp-1, -0x1.f34a729c584bcp-1},
+                {0x1.178d91b6b992dp-5, 0x1.177fae169fdf1p-5, 0x1.177fae169fdfp-5},
+                {-0x1.178d91b6b992dp-5, -0x1.177fae169fdf1p-5, -0x1.177fae169fdfp-5},
+                {0x1.178d91b6bad4ep-5, 0x1.177fae16a120fp-5, 0x1.177fae16a120ep-5},
+                {-0x1.178d91b6bad4ep-5, -0x1.177fae16a120fp-5, -0x1.177fae16a120ep-5},
+                {0x1.178d91b6bbabap-5, 0x1.177fae16a1f79p-5, 0x1.177fae16a1f78p-5},
+                {-0x1.178d91b6bbabap-5, -0x1.177fae16a1f79p-5, -0x1.177fae16a1f78p-5},
+                {0x1.178d91b6bdc45p-5, 0x1.177fae16a40ffp-5, 0x1.177fae16a40fep-5},
+                {-0x1.178d91b6bdc45p-5, -0x1.177fae16a40ffp-5, -0x1.177fae16a40fep-5},
+                {0x1.19752dbee5f6ap933, 0x1.297c768f2413p-1, 0x1.297c768f24131p-1},
+                {-0x1.19752dbee5f6ap933, -0x1.297c768f2413p-1, -0x1.297c768f24131p-1},
+                {0x1.1b3009cfe4dbcp8, 0x1.b826df5cafafap-2, 0x1.b826df5cafafbp-2},
+                {-0x1.1b3009cfe4dbcp8, -0x1.b826df5cafafap-2, -0x1.b826df5cafafbp-2},
+                {0x1.1f6475d95bf18p3, 0x1.b7a5956250b6bp-2, 0x1.b7a5956250b6ap-2},
+                {-0x1.1f6475d95bf18p3, -0x1.b7a5956250b6bp-2, -0x1.b7a5956250b6ap-2},
+                {0x1.229148a452291p118, 0x1.4db6566b64548p-1, 0x1.4db6566b64547p-1},
+                {-0x1.229148a452291p118, -0x1.4db6566b64548p-1, -0x1.4db6566b64547p-1},
+                {0x1.268p-1, 0x1.1686fee2c49a8p-1, 0x1.1686fee2c49a7p-1},
+                {-0x1.268p-1, -0x1.1686fee2c49a8p-1, -0x1.1686fee2c49a7p-1},
+                {0x1.26fb3844dd19p-2, 0x1.22eb21a44d627p-2, 0x1.22eb21a44d628p-2},
+                {-0x1.26fb3844dd19p-2, -0x1.22eb21a44d627p-2, -0x1.22eb21a44d628p-2},
+                {0x1.27fffffffe6bp0, 0x1.d4a216d89b2b3p-1, 0x1.d4a216d89b2b4p-1},
+                {-0x1.27fffffffe6bp0, -0x1.d4a216d89b2b3p-1, -0x1.d4a216d89b2b4p-1},
+                {0x1.284b84048d481p204, -0x1.76c9b0f3a22f8p-1, -0x1.76c9b0f3a22f7p-1},
+                {-0x1.284b84048d481p204, 0x1.76c9b0f3a22f8p-1, 0x1.76c9b0f3a22f7p-1},
+                {0x1.2999e3109cad4p2, -0x1.ff01226f97d33p-1, -0x1.ff01226f97d32p-1},
+                {-0x1.2999e3109cad4p2, 0x1.ff01226f97d33p-1, 0x1.ff01226f97d32p-1},
+                {0x1.2aap-5, 0x1.2a8f11e7ae82cp-5, 0x1.2a8f11e7ae82dp-5},
+                {-0x1.2aap-5, -0x1.2a8f11e7ae82cp-5, -0x1.2a8f11e7ae82dp-5},
+                {0x1.2b14d3be0c23p-5, 0x1.2b03d1bf773dfp-5, 0x1.2b03d1bf773ep-5},
+                {-0x1.2b14d3be0c23p-5, -0x1.2b03d1bf773dfp-5, -0x1.2b03d1bf773ep-5},
+                {0x1.2b7cb44849981p2, -0x1.ffb90ee641792p-1, -0x1.ffb90ee641791p-1},
+                {-0x1.2b7cb44849981p2, 0x1.ffb90ee641792p-1, 0x1.ffb90ee641791p-1},
+                {0x1.2becc8685258p200, -0x1.ffffff79e71a4p-1, -0x1.ffffff79e71a3p-1},
+                {-0x1.2becc8685258p200, 0x1.ffffff79e71a4p-1, 0x1.ffffff79e71a3p-1},
+                {0x1.2cfa14ce27cd5p2, -0x1.fff9edaf85b77p-1, -0x1.fff9edaf85b76p-1},
+                {-0x1.2cfa14ce27cd5p2, 0x1.fff9edaf85b77p-1, 0x1.fff9edaf85b76p-1},
+                {0x1.2dp-4, 0x1.2cbaaa4cebb52p-4, 0x1.2cbaaa4cebb51p-4},
+                {-0x1.2dp-4, -0x1.2cbaaa4cebb52p-4, -0x1.2cbaaa4cebb51p-4},
+                {0x1.2d76d18721be8p2, -0x1.ffffbc177e01p-1, -0x1.ffffbc177e00fp-1},
+                {-0x1.2d76d18721be8p2, 0x1.ffffbc177e01p-1, 0x1.ffffbc177e00fp-1},
+                {0x1.302a494e0909p97, 0x1.745843dfafefdp-18, 0x1.745843dfafefep-18},
+                {-0x1.302a494e0909p97, -0x1.745843dfafefdp-18, -0x1.745843dfafefep-18},
+                {0x1.31cc731cc731cp1000, 0x1.ffcc568d42376p-1, 0x1.ffcc568d42377p-1},
+                {-0x1.31cc731cc731cp1000, -0x1.ffcc568d42376p-1, -0x1.ffcc568d42377p-1},
+                {0x1.328463d4f8ca6p441, 0x1.b676077d4faf8p-1, 0x1.b676077d4faf7p-1},
+                {-0x1.328463d4f8ca6p441, -0x1.b676077d4faf8p-1, -0x1.b676077d4faf7p-1},
+                {0x1.32ce90b32171ep18, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.32ce90b32171ep18, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.35debd7f020ecp-5, 0x1.35cbd3240d149p-5, 0x1.35cbd3240d148p-5},
+                {-0x1.35debd7f020ecp-5, -0x1.35cbd3240d149p-5, -0x1.35cbd3240d148p-5},
+                {0x1.3bb3487893405p-7, 0x1.3bb2086559faap-7, 0x1.3bb2086559fa9p-7},
+                {-0x1.3bb3487893405p-7, -0x1.3bb2086559faap-7, -0x1.3bb2086559fa9p-7},
+                {0x1.3bb3487893407p-7, 0x1.3bb2086559facp-7, 0x1.3bb2086559fabp-7},
+                {-0x1.3bb3487893407p-7, -0x1.3bb2086559facp-7, -0x1.3bb2086559fabp-7},
+                {0x1.3bb681d65aa6p100, 0x1.dff197edc51d2p-16, 0x1.dff197edc51d3p-16},
+                {-0x1.3bb681d65aa6p100, -0x1.dff197edc51d2p-16, -0x1.dff197edc51d3p-16},
+                {0x1.3f9aa8626042fp83, -0x1.5d08d3dbb41bp-3, -0x1.5d08d3dbb41afp-3},
+                {-0x1.3f9aa8626042fp83, 0x1.5d08d3dbb41bp-3, 0x1.5d08d3dbb41afp-3},
+                {0x1.3fep19, 0x1.fb503983f94bbp-3, 0x1.fb503983f94bcp-3},
+                {-0x1.3fep19, -0x1.fb503983f94bbp-3, -0x1.fb503983f94bcp-3},
+                {0x1.4285478f1e3c8p58, -0x1.d3876eacc9ee7p-1, -0x1.d3876eacc9ee6p-1},
+                {-0x1.4285478f1e3c8p58, 0x1.d3876eacc9ee7p-1, 0x1.d3876eacc9ee6p-1},
+                {0x1.42cbcf45a169ep-5, 0x1.42b66d54f69c1p-5, 0x1.42b66d54f69cp-5},
+                {-0x1.42cbcf45a169ep-5, -0x1.42b66d54f69c1p-5, -0x1.42b66d54f69cp-5},
+                {0x1.43fffffffff6ap557, 0x1.b45e9e9427554p-1, 0x1.b45e9e9427553p-1},
+                {-0x1.43fffffffff6ap557, -0x1.b45e9e9427554p-1, -0x1.b45e9e9427553p-1},
+                {0x1.44p-17, 0x1.43ffffffea603p-17, 0x1.43ffffffea602p-17},
+                {-0x1.44p-17, -0x1.43ffffffea603p-17, -0x1.43ffffffea602p-17},
+                {0x1.4748c08dc0976p200, -0x1.6a4e98d2d8b1cp-1, -0x1.6a4e98d2d8b1bp-1},
+                {-0x1.4748c08dc0976p200, 0x1.6a4e98d2d8b1cp-1, 0x1.6a4e98d2d8b1bp-1},
+                {0x1.478fc08p43, -0x1.b57ca8aacf2a9p-1, -0x1.b57ca8aacf2aap-1},
+                {-0x1.478fc08p43, 0x1.b57ca8aacf2a9p-1, 0x1.b57ca8aacf2aap-1},
+                {0x1.4cf36d17c596ep200, 0x1.ffe38008ef6b5p-1, 0x1.ffe38008ef6b4p-1},
+                {-0x1.4cf36d17c596ep200, -0x1.ffe38008ef6b5p-1, -0x1.ffe38008ef6b4p-1},
+                {0x1.4f0f308p488, 0x1.d6457a3f12e6cp-1, 0x1.d6457a3f12e6dp-1},
+                {-0x1.4f0f308p488, -0x1.d6457a3f12e6cp-1, -0x1.d6457a3f12e6dp-1},
+                {0x1.5p-20, 0x1.4fffffffff9f9p-20, 0x1.4fffffffff9f8p-20},
+                {-0x1.5p-20, -0x1.4fffffffff9f9p-20, -0x1.4fffffffff9f8p-20},
+                {0x1.5143e25a488f1p3, -0x1.cbad095f503a2p-1, -0x1.cbad095f503a1p-1},
+                {-0x1.5143e25a488f1p3, 0x1.cbad095f503a2p-1, 0x1.cbad095f503a1p-1},
+                {0x1.51f0f44da4df4p200, -0x1.f942d6262e82ep-5, -0x1.f942d6262e82dp-5},
+                {-0x1.51f0f44da4df4p200, 0x1.f942d6262e82ep-5, 0x1.f942d6262e82dp-5},
+                {0x1.52ad6c5a3602fp16, -0x1.fc466ccaece8p-3, -0x1.fc466ccaece81p-3},
+                {-0x1.52ad6c5a3602fp16, 0x1.fc466ccaece8p-3, 0x1.fc466ccaece81p-3},
+                {0x1.52f00ep793, 0x1.d69c3cf4eecdep-1, 0x1.d69c3cf4eecddp-1},
+                {-0x1.52f00ep793, -0x1.d69c3cf4eecdep-1, -0x1.d69c3cf4eecddp-1},
+                {0x1.5555555555556p239, 0x1.e120292f3d495p-1, 0x1.e120292f3d496p-1},
+                {-0x1.5555555555556p239, -0x1.e120292f3d495p-1, -0x1.e120292f3d496p-1},
+                {0x1.5a0000008p6, -0x1.fd1d85b7ef004p-1, -0x1.fd1d85b7ef003p-1},
+                {-0x1.5a0000008p6, 0x1.fd1d85b7ef004p-1, 0x1.fd1d85b7ef003p-1},
+                {0x1.5b063ad2dd08fp-6, 0x1.5aff9664b07e2p-6, 0x1.5aff9664b07e1p-6},
+                {-0x1.5b063ad2dd08fp-6, -0x1.5aff9664b07e2p-6, -0x1.5aff9664b07e1p-6},
+                {0x1.5b179d75fa285p2, -0x1.83f8bbb59f2f8p-1, -0x1.83f8bbb59f2f9p-1},
+                {-0x1.5b179d75fa285p2, 0x1.83f8bbb59f2f8p-1, 0x1.83f8bbb59f2f9p-1},
+                {0x1.5bb5967402f9cp79, 0x1.fa865b0d99497p-1, 0x1.fa865b0d99496p-1},
+                {-0x1.5bb5967402f9cp79, -0x1.fa865b0d99497p-1, -0x1.fa865b0d99496p-1},
+                {0x1.5bea01p468, 0x1.e8a523fce884dp-2, 0x1.e8a523fce884ep-2},
+                {-0x1.5bea01p468, -0x1.e8a523fce884dp-2, -0x1.e8a523fce884ep-2},
+                {0x1.5f19fbc507af6p9, -0x1.ff2ad941f0a41p-1, -0x1.ff2ad941f0a4p-1},
+                {-0x1.5f19fbc507af6p9, 0x1.ff2ad941f0a41p-1, 0x1.ff2ad941f0a4p-1},
+                {0x1.60a610a658da9p889, -0x1.75ce4a0d0bd03p-1, -0x1.75ce4a0d0bd04p-1},
+                {-0x1.60a610a658da9p889, 0x1.75ce4a0d0bd03p-1, 0x1.75ce4a0d0bd04p-1},
+                {0x1.62ad7ce17143dp62, -0x1.721586594ab48p-1, -0x1.721586594ab49p-1},
+                {-0x1.62ad7ce17143dp62, 0x1.721586594ab48p-1, 0x1.721586594ab49p-1},
+                {0x1.645926cc1132cp9, 0x1.b8d27019d1b9fp-2, 0x1.b8d27019d1b9ep-2},
+                {-0x1.645926cc1132cp9, -0x1.b8d27019d1b9fp-2, -0x1.b8d27019d1b9ep-2},
+                {0x1.647e25d391f17p-9, 0x1.647e09059c1eap-9, 0x1.647e09059c1e9p-9},
+                {-0x1.647e25d391f17p-9, -0x1.647e09059c1eap-9, -0x1.647e09059c1e9p-9},
+                {0x1.64ef438p142, -0x1.8d3b53ff85a82p-1, -0x1.8d3b53ff85a83p-1},
+                {-0x1.64ef438p142, 0x1.8d3b53ff85a82p-1, 0x1.8d3b53ff85a83p-1},
+                {0x1.6599665996658p3, -0x1.f7c8630e62a02p-1, -0x1.f7c8630e62a01p-1},
+                {-0x1.6599665996658p3, 0x1.f7c8630e62a02p-1, 0x1.f7c8630e62a01p-1},
+                {0x1.672p-5, 0x1.67028e3602035p-5, 0x1.67028e3602034p-5},
+                {-0x1.672p-5, -0x1.67028e3602035p-5, -0x1.67028e3602034p-5},
+                {0x1.688ae6c138ea8p299, 0x1.bc60c8c33cb5fp-2, 0x1.bc60c8c33cb5ep-2},
+                {-0x1.688ae6c138ea8p299, -0x1.bc60c8c33cb5fp-2, -0x1.bc60c8c33cb5ep-2},
+                {0x1.6aa78p17, -0x1.fc3b4bb8b012ep-1, -0x1.fc3b4bb8b012fp-1},
+                {-0x1.6aa78p17, 0x1.fc3b4bb8b012ep-1, 0x1.fc3b4bb8b012fp-1},
+                {0x1.6ac5b262ca1ffp849, 0x1.0p0, 0x1.0p0},
+                {-0x1.6ac5b262ca1ffp849, -0x1.0p0, -0x1.0p0},
+                {0x1.6d88083749412p4, -0x1.82317836a97c8p-1, -0x1.82317836a97c9p-1},
+                {-0x1.6d88083749412p4, 0x1.82317836a97c8p-1, 0x1.82317836a97c9p-1},
+                {0x1.6f8p-6, 0x1.6f781c78cc82bp-6, 0x1.6f781c78cc82ap-6},
+                {-0x1.6f8p-6, -0x1.6f781c78cc82bp-6, -0x1.6f781c78cc82ap-6},
+                {0x1.729aa6859d1f4p396, -0x1.fdbe5085494aep-1, -0x1.fdbe5085494afp-1},
+                {-0x1.729aa6859d1f4p396, 0x1.fdbe5085494aep-1, 0x1.fdbe5085494afp-1},
+                {0x1.73e2dbe9a2f8p10, -0x1.fffffae862b5p-1, -0x1.fffffae862b4fp-1},
+                {-0x1.73e2dbe9a2f8p10, 0x1.fffffae862b5p-1, 0x1.fffffae862b4fp-1},
+                {0x1.769cde0b90b8p-7, 0x1.769ac74459b06p-7, 0x1.769ac74459b05p-7},
+                {-0x1.769cde0b90b8p-7, -0x1.769ac74459b06p-7, -0x1.769ac74459b05p-7},
+                {0x1.76cp-5, 0x1.769e8afb6a4ecp-5, 0x1.769e8afb6a4ebp-5},
+                {-0x1.76cp-5, -0x1.769e8afb6a4ecp-5, -0x1.769e8afb6a4ebp-5},
+                {0x1.78001p0, 0x1.fd562611f5bd4p-1, 0x1.fd562611f5bd5p-1},
+                {-0x1.78001p0, -0x1.fd562611f5bd4p-1, -0x1.fd562611f5bd5p-1},
+                {0x1.7ap0, 0x1.fdba784ca00f2p-1, 0x1.fdba784ca00f1p-1},
+                {-0x1.7ap0, -0x1.fdba784ca00f2p-1, -0x1.fdba784ca00f1p-1},
+                {0x1.7abd870381c2dp38, 0x1.f930c222a8683p-5, 0x1.f930c222a8682p-5},
+                {-0x1.7abd870381c2dp38, -0x1.f930c222a8683p-5, -0x1.f930c222a8682p-5},
+                {0x1.7dc945c21248p95, 0x1.ffeb2ff2b6923p-1, 0x1.ffeb2ff2b6924p-1},
+                {-0x1.7dc945c21248p95, -0x1.ffeb2ff2b6923p-1, -0x1.ffeb2ff2b6924p-1},
+                {0x1.7f73e1594b70cp98, 0x1.b279153c23fb2p-2, 0x1.b279153c23fb1p-2},
+                {-0x1.7f73e1594b70cp98, -0x1.b279153c23fb2p-2, -0x1.b279153c23fb1p-2},
+                {0x1.7f7ef77e83f1ap21, -0x1.599fad35cf60bp-41, -0x1.599fad35cf60ap-41},
+                {-0x1.7f7ef77e83f1ap21, 0x1.599fad35cf60bp-41, 0x1.599fad35cf60ap-41},
+                {0x1.8p0, 0x1.feb7a9b2c6d8bp-1, 0x1.feb7a9b2c6d8ap-1},
+                {-0x1.8p0, -0x1.feb7a9b2c6d8bp-1, -0x1.feb7a9b2c6d8ap-1},
+                {0x1.8p6, 0x1.f798d01ec615cp-1, 0x1.f798d01ec615bp-1},
+                {-0x1.8p6, -0x1.f798d01ec615cp-1, -0x1.f798d01ec615bp-1},
+                {0x1.8132ceb1c4f39p0, 0x1.fee1a2a977bcfp-1, 0x1.fee1a2a977bcep-1},
+                {-0x1.8132ceb1c4f39p0, -0x1.fee1a2a977bcfp-1, -0x1.fee1a2a977bcep-1},
+                {0x1.81ae0dffa3b33p959, -0x1.24245af4cd995p-52, -0x1.24245af4cd994p-52},
+                {-0x1.81ae0dffa3b33p959, 0x1.24245af4cd995p-52, 0x1.24245af4cd994p-52},
+                {0x1.85ec5a399a2e6p1, 0x1.85d41b0bf3091p-4, 0x1.85d41b0bf309p-4},
+                {-0x1.85ec5a399a2e6p1, -0x1.85d41b0bf3091p-4, -0x1.85d41b0bf309p-4},
+                {0x1.86a0092754022p16, 0x1.1e42ae3cfbdc6p-24, 0x1.1e42ae3cfbdc7p-24},
+                {-0x1.86a0092754022p16, -0x1.1e42ae3cfbdc6p-24, -0x1.1e42ae3cfbdc7p-24},
+                {0x1.8720588p392, -0x1.dbf4e594cefe1p-1, -0x1.dbf4e594cefe2p-1},
+                {-0x1.8720588p392, 0x1.dbf4e594cefe1p-1, 0x1.dbf4e594cefe2p-1},
+                {0x1.8929354ebc6aap43, 0x1.44302d6a82d4p-9, 0x1.44302d6a82d41p-9},
+                {-0x1.8929354ebc6aap43, -0x1.44302d6a82d4p-9, -0x1.44302d6a82d41p-9},
+                {0x1.8a791e4791e75p-5, 0x1.8a52189ec3487p-5, 0x1.8a52189ec3488p-5},
+                {-0x1.8a791e4791e75p-5, -0x1.8a52189ec3487p-5, -0x1.8a52189ec3488p-5},
+                {0x1.8ba761438f5edp11, -0x1.fe8566e538123p-1, -0x1.fe8566e538122p-1},
+                {-0x1.8ba761438f5edp11, 0x1.fe8566e538123p-1, 0x1.fe8566e538122p-1},
+                {0x1.8eaf16de6392p0, 0x1.fff42aca4cb5ap-1, 0x1.fff42aca4cb5bp-1},
+                {-0x1.8eaf16de6392p0, -0x1.fff42aca4cb5ap-1, -0x1.fff42aca4cb5bp-1},
+                {0x1.9p0, 0x1.fffb7d3f3a253p-1, 0x1.fffb7d3f3a252p-1},
+                {-0x1.9p0, -0x1.fffb7d3f3a253p-1, -0x1.fffb7d3f3a252p-1},
+                {0x1.91a5657fb6a9ap6, -0x1.e815770667fd9p-4, -0x1.e815770667fd8p-4},
+                {-0x1.91a5657fb6a9ap6, 0x1.e815770667fd9p-4, 0x1.e815770667fd8p-4},
+                {0x1.921fb54468847p37, -0x1.fffffffd311dcp-1, -0x1.fffffffd311ddp-1},
+                {-0x1.921fb54468847p37, 0x1.fffffffd311dcp-1, 0x1.fffffffd311ddp-1},
+                {0x1.921ff54442d18p2, 0x1.ffffffff875e6p-17, 0x1.ffffffff875e5p-17},
+                {-0x1.921ff54442d18p2, -0x1.ffffffff875e6p-17, -0x1.ffffffff875e5p-17},
+                {0x1.928p2, 0x1.812a5da3777cdp-8, 0x1.812a5da3777cep-8},
+                {-0x1.928p2, -0x1.812a5da3777cdp-8, -0x1.812a5da3777cep-8},
+                {0x1.94ap0, 0x1.fff9be8d82573p-1, 0x1.fff9be8d82572p-1},
+                {-0x1.94ap0, -0x1.fff9be8d82573p-1, -0x1.fff9be8d82572p-1},
+                {0x1.94a5294a51bdep-5, 0x1.947b0ace235f3p-5, 0x1.947b0ace235f2p-5},
+                {-0x1.94a5294a51bdep-5, -0x1.947b0ace235f3p-5, -0x1.947b0ace235f2p-5},
+                {0x1.94a5294a52948p100, 0x1.c34f70e55a708p-2, 0x1.c34f70e55a707p-2},
+                {-0x1.94a5294a52948p100, -0x1.c34f70e55a708p-2, -0x1.c34f70e55a707p-2},
+                {0x1.95361b8f7697dp-5, 0x1.950bcfc0f3d51p-5, 0x1.950bcfc0f3d5p-5},
+                {-0x1.95361b8f7697dp-5, -0x1.950bcfc0f3d51p-5, -0x1.950bcfc0f3d5p-5},
+                {0x1.956p-1, 0x1.6c548bfcce696p-1, 0x1.6c548bfcce695p-1},
+                {-0x1.956p-1, -0x1.6c548bfcce696p-1, -0x1.6c548bfcce695p-1},
+                {0x1.962p0, 0x1.ffeffdbf67ca6p-1, 0x1.ffeffdbf67ca7p-1},
+                {-0x1.962p0, -0x1.ffeffdbf67ca6p-1, -0x1.ffeffdbf67ca7p-1},
+                {0x1.97330d2ea16d9p-5, 0x1.9708213bf67f5p-5, 0x1.9708213bf67f4p-5},
+                {-0x1.97330d2ea16d9p-5, -0x1.9708213bf67f5p-5, -0x1.9708213bf67f4p-5},
+                {0x1.9756f073b6b61p-5, 0x1.972bf92713d51p-5, 0x1.972bf92713d5p-5},
+                {-0x1.9756f073b6b61p-5, -0x1.972bf92713d51p-5, -0x1.972bf92713d5p-5},
+                {0x1.97935055cec1bp-5, 0x1.976845ebe7119p-5, 0x1.976845ebe7118p-5},
+                {-0x1.97935055cec1bp-5, -0x1.976845ebe7119p-5, -0x1.976845ebe7118p-5},
+                {0x1.98p-4, 0x1.97535cee51a43p-4, 0x1.97535cee51a42p-4},
+                {-0x1.98p-4, -0x1.97535cee51a43p-4, -0x1.97535cee51a42p-4},
+                {0x1.999999a42160cp-1, 0x1.6f494c3356177p-1, 0x1.6f494c3356178p-1},
+                {-0x1.999999a42160cp-1, -0x1.6f494c3356177p-1, -0x1.6f494c3356178p-1},
+                {0x1.999999aab8f5p-1, 0x1.6f494c37edd6ep-1, 0x1.6f494c37edd6dp-1},
+                {-0x1.999999aab8f5p-1, -0x1.6f494c37edd6ep-1, -0x1.6f494c37edd6dp-1},
+                {0x1.9a2324b9c6326p-1, 0x1.6fa912bdeaab2p-1, 0x1.6fa912bdeaab3p-1},
+                {-0x1.9a2324b9c6326p-1, -0x1.6fa912bdeaab2p-1, -0x1.6fa912bdeaab3p-1},
+                {0x1.9bcp-1, 0x1.70c7ef4ef9b34p-1, 0x1.70c7ef4ef9b35p-1},
+                {-0x1.9bcp-1, -0x1.70c7ef4ef9b34p-1, -0x1.70c7ef4ef9b35p-1},
+                {0x1.a0d1d817d6c4ap0, 0x1.ff28176ad3164p-1, 0x1.ff28176ad3163p-1},
+                {-0x1.a0d1d817d6c4ap0, -0x1.ff28176ad3164p-1, -0x1.ff28176ad3163p-1},
+                {0x1.a141c9de12fdfp-1, 0x1.749468a7248dep-1, 0x1.749468a7248ddp-1},
+                {-0x1.a141c9de12fdfp-1, -0x1.749468a7248dep-1, -0x1.749468a7248ddp-1},
+                {0x1.a251bc6766f2p-1, 0x1.754ebb7e73f46p-1, 0x1.754ebb7e73f45p-1},
+                {-0x1.a251bc6766f2p-1, -0x1.754ebb7e73f46p-1, -0x1.754ebb7e73f45p-1},
+                {0x1.a2689ae1b86ddp62, -0x1.7c3bfefa74bd1p-1, -0x1.7c3bfefa74bdp-1},
+                {-0x1.a2689ae1b86ddp62, 0x1.7c3bfefa74bd1p-1, 0x1.7c3bfefa74bdp-1},
+                {0x1.a3f66180c455p100, -0x1.ffff4f3648e03p-1, -0x1.ffff4f3648e02p-1},
+                {-0x1.a3f66180c455p100, 0x1.ffff4f3648e03p-1, 0x1.ffff4f3648e02p-1},
+                {0x1.a3fdd2a5286c3p1, -0x1.1cf463983c0e3p-3, -0x1.1cf463983c0e2p-3},
+                {-0x1.a3fdd2a5286c3p1, 0x1.1cf463983c0e3p-3, 0x1.1cf463983c0e2p-3},
+                {0x1.a44p0, 0x1.feb7948d224d8p-1, 0x1.feb7948d224d7p-1},
+                {-0x1.a44p0, -0x1.feb7948d224d8p-1, -0x1.feb7948d224d7p-1},
+                {0x1.a701ef3c7d54bp-1, 0x1.78801e3e11665p-1, 0x1.78801e3e11664p-1},
+                {-0x1.a701ef3c7d54bp-1, -0x1.78801e3e11665p-1, -0x1.78801e3e11664p-1},
+                {0x1.a8c01fd43cp537, -0x1.fff11e871d59cp-1, -0x1.fff11e871d59dp-1},
+                {-0x1.a8c01fd43cp537, 0x1.fff11e871d59cp-1, 0x1.fff11e871d59dp-1},
+                {0x1.a8e29b7602f3bp0, 0x1.fdfa4366eb733p-1, 0x1.fdfa4366eb734p-1},
+                {-0x1.a8e29b7602f3bp0, -0x1.fdfa4366eb733p-1, -0x1.fdfa4366eb734p-1},
+                {0x1.a94p0, 0x1.fde98b94e7948p-1, 0x1.fde98b94e7947p-1},
+                {-0x1.a94p0, -0x1.fde98b94e7948p-1, -0x1.fde98b94e7947p-1},
+                {0x1.aa445fce93b82p2, 0x1.7931cba100008p-2, 0x1.7931cba100009p-2},
+                {-0x1.aa445fce93b82p2, -0x1.7931cba100008p-2, -0x1.7931cba100009p-2},
+                {0x1.aaa3fbc359fbep-1, 0x1.7af3f76c7a708p-1, 0x1.7af3f76c7a709p-1},
+                {-0x1.aaa3fbc359fbep-1, -0x1.7af3f76c7a708p-1, -0x1.7af3f76c7a709p-1},
+                {0x1.abdd3dbd4d86p119, 0x1.fd74e53ae32fdp-6, 0x1.fd74e53ae32fcp-6},
+                {-0x1.abdd3dbd4d86p119, -0x1.fd74e53ae32fdp-6, -0x1.fd74e53ae32fcp-6},
+                {0x1.ae2165a0c9f8ep-1, 0x1.7d4a7bf183a34p-1, 0x1.7d4a7bf183a33p-1},
+                {-0x1.ae2165a0c9f8ep-1, -0x1.7d4a7bf183a34p-1, -0x1.7d4a7bf183a33p-1},
+                {0x1.ae8dfefcfe13bp2, 0x1.b81410edc79e1p-2, 0x1.b81410edc79ep-2},
+                {-0x1.ae8dfefcfe13bp2, -0x1.b81410edc79e1p-2, -0x1.b81410edc79ep-2},
+                {0x1.b5597f950ee8cp29, -0x1.ff751561dc50ap-2, -0x1.ff751561dc509p-2},
+                {-0x1.b5597f950ee8cp29, 0x1.ff751561dc50ap-2, 0x1.ff751561dc509p-2},
+                {0x1.bab62ed655019p970, 0x1.027d184afb198p-52, 0x1.027d184afb199p-52},
+                {-0x1.bab62ed655019p970, -0x1.027d184afb198p-52, -0x1.027d184afb199p-52},
+                {0x1.bc573c4ffffffp-10, 0x1.bc572e5e413e1p-10, 0x1.bc572e5e413e2p-10},
+                {-0x1.bc573c4ffffffp-10, -0x1.bc572e5e413e1p-10, -0x1.bc572e5e413e2p-10},
+                {0x1.bef5cd25ab1adp9, 0x1.fb300f1e39afep-1, 0x1.fb300f1e39affp-1},
+                {-0x1.bef5cd25ab1adp9, -0x1.fb300f1e39afep-1, -0x1.fb300f1e39affp-1},
+                {0x1.bfdf6df2a24c1p-2, 0x1.b1baaf622d3a3p-2, 0x1.b1baaf622d3a2p-2},
+                {-0x1.bfdf6df2a24c1p-2, -0x1.b1baaf622d3a3p-2, -0x1.b1baaf622d3a2p-2},
+                {0x1.bfffffdffffffp-1, 0x1.88fb762c35ce4p-1, 0x1.88fb762c35ce3p-1},
+                {-0x1.bfffffdffffffp-1, -0x1.88fb762c35ce4p-1, -0x1.88fb762c35ce3p-1},
+                {0x1.c2b489520e376p920, 0x1.fe0ebff99ab8dp-1, 0x1.fe0ebff99ab8cp-1},
+                {-0x1.c2b489520e376p920, -0x1.fe0ebff99ab8dp-1, -0x1.fe0ebff99ab8cp-1},
+                {0x1.c54beb008547p5, 0x1.cf7f749f2a836p-4, 0x1.cf7f749f2a835p-4},
+                {-0x1.c54beb008547p5, -0x1.cf7f749f2a836p-4, -0x1.cf7f749f2a835p-4},
+                {0x1.c5ad34f5f472ap-2, 0x1.b6facf6658915p-2, 0x1.b6facf6658914p-2},
+                {-0x1.c5ad34f5f472ap-2, -0x1.b6facf6658915p-2, -0x1.b6facf6658914p-2},
+                {0x1.c728fc2f34bd6p-2, 0x1.b851cd9b84ee7p-2, 0x1.b851cd9b84ee6p-2},
+                {-0x1.c728fc2f34bd6p-2, -0x1.b851cd9b84ee7p-2, -0x1.b851cd9b84ee6p-2},
+                {0x1.c92b0f6105089p-2, 0x1.ba21b53cf2ff3p-2, 0x1.ba21b53cf2ff2p-2},
+                {-0x1.c92b0f6105089p-2, -0x1.ba21b53cf2ff3p-2, -0x1.ba21b53cf2ff2p-2},
+                {0x1.c9dfbbe9ec704p-5, 0x1.c9a2b68e30ec7p-5, 0x1.c9a2b68e30ec8p-5},
+                {-0x1.c9dfbbe9ec704p-5, -0x1.c9a2b68e30ec7p-5, -0x1.c9a2b68e30ec8p-5},
+                {0x1.caf31bd7ee217p0, 0x1.f370115c9ab35p-1, 0x1.f370115c9ab36p-1},
+                {-0x1.caf31bd7ee217p0, -0x1.f370115c9ab35p-1, -0x1.f370115c9ab36p-1},
+                {0x1.cb44e86bc192bp648, -0x1.dd38a1f1d289bp-54, -0x1.dd38a1f1d289cp-54},
+                {-0x1.cb44e86bc192bp648, 0x1.dd38a1f1d289bp-54, 0x1.dd38a1f1d289cp-54},
+                {0x1.cb44e86bc192bp649, 0x1.dd38a1f1d289bp-53, 0x1.dd38a1f1d289cp-53},
+                {-0x1.cb44e86bc192bp649, -0x1.dd38a1f1d289bp-53, -0x1.dd38a1f1d289cp-53},
+                {0x1.cb6p-3, 0x1.c7885aef33a95p-3, 0x1.c7885aef33a94p-3},
+                {-0x1.cb6p-3, -0x1.c7885aef33a95p-3, -0x1.c7885aef33a94p-3},
+                {0x1.ce2271d2f662fp-4, 0x1.cd279aa6196b6p-4, 0x1.cd279aa6196b5p-4},
+                {-0x1.ce2271d2f662fp-4, -0x1.cd279aa6196b6p-4, -0x1.cd279aa6196b5p-4},
+                {0x1.d0000000004p-1, 0x1.930b705f9fad2p-1, 0x1.930b705f9fad1p-1},
+                {-0x1.d0000000004p-1, -0x1.930b705f9fad2p-1, -0x1.930b705f9fad1p-1},
+                {0x1.d01p199, 0x1.7ef24c8e67d9ap-1, 0x1.7ef24c8e67d9bp-1},
+                {-0x1.d01p199, -0x1.7ef24c8e67d9ap-1, -0x1.7ef24c8e67d9bp-1},
+                {0x1.d024ba6f953cfp1000, 0x1.ffff124c001abp-1, 0x1.ffff124c001aap-1},
+                {-0x1.d024ba6f953cfp1000, -0x1.ffff124c001abp-1, -0x1.ffff124c001aap-1},
+                {0x1.d4067c60f471ep1, -0x1.f83a0983dd15dp-2, -0x1.f83a0983dd15ep-2},
+                {-0x1.d4067c60f471ep1, 0x1.f83a0983dd15dp-2, 0x1.f83a0983dd15ep-2},
+                {0x1.d7de6263bcaabp-5, 0x1.d79b9896ff555p-5, 0x1.d79b9896ff554p-5},
+                {-0x1.d7de6263bcaabp-5, -0x1.d79b9896ff555p-5, -0x1.d79b9896ff554p-5},
+                {0x1.d800000002274p0, 0x1.ed0b908a2983p-1, 0x1.ed0b908a2982fp-1},
+                {-0x1.d800000002274p0, -0x1.ed0b908a2983p-1, -0x1.ed0b908a2982fp-1},
+                {0x1.d96e058p488, -0x1.f2c217cbc7dcdp-1, -0x1.f2c217cbc7dccp-1},
+                {-0x1.d96e058p488, 0x1.f2c217cbc7dcdp-1, 0x1.f2c217cbc7dccp-1},
+                {0x1.d98c4c612718dp-1, 0x1.98dcd09337793p-1, 0x1.98dcd09337792p-1},
+                {-0x1.d98c4c612718dp-1, -0x1.98dcd09337793p-1, -0x1.98dcd09337792p-1},
+                {0x1.db8p-5, 0x1.db3ba8775ca26p-5, 0x1.db3ba8775ca25p-5},
+                {-0x1.db8p-5, -0x1.db3ba8775ca26p-5, -0x1.db3ba8775ca25p-5},
+                {0x1.de386d6090303p200, -0x1.9fee37697d582p-2, -0x1.9fee37697d583p-2},
+                {-0x1.de386d6090303p200, 0x1.9fee37697d582p-2, 0x1.9fee37697d583p-2},
+                {0x1.de5e5054e921bp35, -0x1.5361ee6553188p-53, -0x1.5361ee6553189p-53},
+                {-0x1.de5e5054e921bp35, 0x1.5361ee6553188p-53, 0x1.5361ee6553189p-53},
+                {0x1.df77ddf77ddf4p10, 0x1.fec48d5e769ecp-1, 0x1.fec48d5e769ebp-1},
+                {-0x1.df77ddf77ddf4p10, -0x1.fec48d5e769ecp-1, -0x1.fec48d5e769ebp-1},
+                {0x1.e1562b0448a86p1, -0x1.2902a83d72632p-1, -0x1.2902a83d72633p-1},
+                {-0x1.e1562b0448a86p1, 0x1.2902a83d72632p-1, 0x1.2902a83d72633p-1},
+                {0x1.e2700cdc86635p-1, 0x1.9e26c7bc96b69p-1, 0x1.9e26c7bc96b68p-1},
+                {-0x1.e2700cdc86635p-1, -0x1.9e26c7bc96b69p-1, -0x1.9e26c7bc96b68p-1},
+                {0x1.e64ddaf7bd73p-7, 0x1.e6494911eedd2p-7, 0x1.e6494911eedd1p-7},
+                {-0x1.e64ddaf7bd73p-7, -0x1.e6494911eedd2p-7, -0x1.e6494911eedd1p-7},
+                {0x1.eb7239bca8afap-5, 0x1.eb26c690bda25p-5, 0x1.eb26c690bda24p-5},
+                {-0x1.eb7239bca8afap-5, -0x1.eb26c690bda25p-5, -0x1.eb26c690bda24p-5},
+                {0x1.ef7b83f7bdef4p3, 0x1.c73238790a4cfp-3, 0x1.c73238790a4cep-3},
+                {-0x1.ef7b83f7bdef4p3, -0x1.c73238790a4cfp-3, -0x1.c73238790a4cep-3},
+                {0x1.f20000000109bp-3, 0x1.ed1b575acb8c8p-3, 0x1.ed1b575acb8c9p-3},
+                {-0x1.f20000000109bp-3, -0x1.ed1b575acb8c8p-3, -0x1.ed1b575acb8c9p-3},
+                {0x1.f40ca67a9e8d7p9, 0x1.c1b50a56c8809p-1, 0x1.c1b50a56c880ap-1},
+                {-0x1.f40ca67a9e8d7p9, -0x1.c1b50a56c8809p-1, -0x1.c1b50a56c880ap-1},
+                {0x1.f7224d2c7754p-2, 0x1.e321fea643a96p-2, 0x1.e321fea643a97p-2},
+                {-0x1.f7224d2c7754p-2, -0x1.e321fea643a96p-2, -0x1.e321fea643a97p-2},
+                {0x1.f78a0d05e60e2p6, 0x1.c1269b020a108p-3, 0x1.c1269b020a107p-3},
+                {-0x1.f78a0d05e60e2p6, -0x1.c1269b020a108p-3, -0x1.c1269b020a107p-3},
+                {0x1.f7bdef7bdf073p-5, 0x1.f76cae28a0775p-5, 0x1.f76cae28a0774p-5},
+                {-0x1.f7bdef7bdf073p-5, -0x1.f76cae28a0775p-5, -0x1.f76cae28a0774p-5},
+                {0x1.f8502d5955443p-2, 0x1.e42c139dc2054p-2, 0x1.e42c139dc2053p-2},
+                {-0x1.f8502d5955443p-2, -0x1.e42c139dc2054p-2, -0x1.e42c139dc2053p-2},
+                {0x1.f8fc824d2693bp61, 0x1.0fa749e07f64p-9, 0x1.0fa749e07f63fp-9},
+                {-0x1.f8fc824d2693bp61, -0x1.0fa749e07f64p-9, -0x1.0fa749e07f63fp-9},
+                {0x1.f8fffffffffffp2, 0x1.ffa80324e2d8fp-1, 0x1.ffa80324e2d8ep-1},
+                {-0x1.f8fffffffffffp2, -0x1.ffa80324e2d8fp-1, -0x1.ffa80324e2d8ep-1},
+                {0x1.fd8p1, -0x1.7cdf79d5e37b8p-1, -0x1.7cdf79d5e37b9p-1},
+                {-0x1.fd8p1, 0x1.7cdf79d5e37b8p-1, 0x1.7cdf79d5e37b9p-1},
+                {0x1.fd9364d936596p-5, 0x1.fd3f48847a1d1p-5, 0x1.fd3f48847a1d2p-5},
+                {-0x1.fd9364d936596p-5, -0x1.fd3f48847a1d1p-5, -0x1.fd3f48847a1d2p-5},
+                {0x1.fe8p-3, 0x1.f93ad471d262fp-3, 0x1.f93ad471d263p-3},
+                {-0x1.fe8p-3, -0x1.f93ad471d262fp-3, -0x1.f93ad471d263p-3},
+                {0x1.febb646e2ee57p13, 0x1.83b3062414974p-1, 0x1.83b3062414973p-1},
+                {-0x1.febb646e2ee57p13, -0x1.83b3062414974p-1, -0x1.83b3062414973p-1},
+                {0x1.feeffffffffc6p995, 0x1.3b45bd7449775p-1, 0x1.3b45bd7449776p-1},
+                {-0x1.feeffffffffc6p995, -0x1.3b45bd7449775p-1, -0x1.3b45bd7449776p-1},
+                {0x1.ff8ffffffffffp7, -0x1.eefb59d143646p-1, -0x1.eefb59d143645p-1},
+                {-0x1.ff8ffffffffffp7, 0x1.eefb59d143646p-1, 0x1.eefb59d143645p-1},
+                {0x1.ff8ffffffffffp870, -0x1.56433f0c6bceep-1, -0x1.56433f0c6bcefp-1},
+                {-0x1.ff8ffffffffffp870, 0x1.56433f0c6bceep-1, 0x1.56433f0c6bcefp-1},
+                {0x1.ffcfff8p19, -0x1.930006246a6cp-2, -0x1.930006246a6c1p-2},
+                {-0x1.ffcfff8p19, 0x1.930006246a6cp-2, 0x1.930006246a6c1p-2},
+                {0x1.ffcfff8p365, 0x1.ded37a1f0aa6dp-1, 0x1.ded37a1f0aa6ep-1},
+                {-0x1.ffcfff8p365, -0x1.ded37a1f0aa6dp-1, -0x1.ded37a1f0aa6ep-1},
+                {0x1.ffcffffffff6cp720, -0x1.93e4d96b621ep-1, -0x1.93e4d96b621e1p-1},
+                {-0x1.ffcffffffff6cp720, 0x1.93e4d96b621ep-1, 0x1.93e4d96b621e1p-1},
+                {0x1.ffcfffffffff9p320, 0x1.9068b90e42606p-1, 0x1.9068b90e42605p-1},
+                {-0x1.ffcfffffffff9p320, -0x1.9068b90e42606p-1, -0x1.9068b90e42605p-1},
+                {0x1.ffcffffffffffp12, 0x1.cf81642e7421cp-1, 0x1.cf81642e7421dp-1},
+                {-0x1.ffcffffffffffp12, -0x1.cf81642e7421cp-1, -0x1.cf81642e7421dp-1},
+                {0x1.ffcffffffffffp404, 0x1.ffffffe61fe61p-1, 0x1.ffffffe61fe62p-1},
+                {-0x1.ffcffffffffffp404, -0x1.ffffffe61fe61p-1, -0x1.ffffffe61fe62p-1},
+                {0x1.ffeffffffffccp995, -0x1.406ee9ae91e17p-1, -0x1.406ee9ae91e16p-1},
+                {-0x1.ffeffffffffccp995, 0x1.406ee9ae91e17p-1, 0x1.406ee9ae91e16p-1},
+                {0x1.ffeffffffffffp-3, 0x1.fa9f6ca0ec44ep-3, 0x1.fa9f6ca0ec44fp-3},
+                {-0x1.ffeffffffffffp-3, -0x1.fa9f6ca0ec44ep-3, -0x1.fa9f6ca0ec44fp-3},
+                {0x1.ffeffffffffffp55, 0x1.6b491db8b66d9p-4, 0x1.6b491db8b66d8p-4},
+                {-0x1.ffeffffffffffp55, -0x1.6b491db8b66d9p-4, -0x1.6b491db8b66d8p-4},
+                {0x1.ffeffffffffffp180, 0x1.fb0ab102cb13p-1, 0x1.fb0ab102cb12fp-1},
+                {-0x1.ffeffffffffffp180, -0x1.fb0ab102cb13p-1, -0x1.fb0ab102cb12fp-1},
+                {0x1.ffeffffffffffp706, 0x1.e4315ec04635dp-3, 0x1.e4315ec04635cp-3},
+                {-0x1.ffeffffffffffp706, -0x1.e4315ec04635dp-3, -0x1.e4315ec04635cp-3},
+                {0x1.fff1fffffffffp41, 0x1.ffffc39997ef6p-1, 0x1.ffffc39997ef7p-1},
+                {-0x1.fff1fffffffffp41, -0x1.ffffc39997ef6p-1, -0x1.ffffc39997ef7p-1},
+                {0x1.fff6b89ffffffp-7, 0x1.fff163992831fp-7, 0x1.fff163992831ep-7},
+                {-0x1.fff6b89ffffffp-7, -0x1.fff163992831fp-7, -0x1.fff163992831ep-7},
+                {0x1.fffdffff0001fp105, -0x1.d9757a05fcc43p-1, -0x1.d9757a05fcc42p-1},
+                {-0x1.fffdffff0001fp105, 0x1.d9757a05fcc43p-1, 0x1.d9757a05fcc42p-1},
+                {0x1.ffff0c0000002p1, -0x1.83791fe63a17ap-1, -0x1.83791fe63a17bp-1},
+                {-0x1.ffff0c0000002p1, 0x1.83791fe63a17ap-1, 0x1.83791fe63a17bp-1},
+                {0x1.ffffc00000055p150, -0x1.d9d3a85acc50dp-1, -0x1.d9d3a85acc50cp-1},
+                {-0x1.ffffc00000055p150, 0x1.d9d3a85acc50dp-1, 0x1.d9d3a85acc50cp-1},
+                {0x1.ffffe3fffffffp40, -0x1.f25d858dcdee7p-3, -0x1.f25d858dcdee8p-3},
+                {-0x1.ffffe3fffffffp40, 0x1.f25d858dcdee7p-3, 0x1.f25d858dcdee8p-3},
+                {0x1.ffffefffcffaep0, 0x1.d18f7bfe557ecp-1, 0x1.d18f7bfe557ebp-1},
+                {-0x1.ffffefffcffaep0, -0x1.d18f7bfe557ecp-1, -0x1.d18f7bfe557ebp-1},
+                {0x1.fffffbfffffffp228, -0x1.bc14ebf6bfb52p-4, -0x1.bc14ebf6bfb51p-4},
+                {-0x1.fffffbfffffffp228, 0x1.bc14ebf6bfb52p-4, 0x1.bc14ebf6bfb51p-4},
+                {0x1.fffffbfffffffp735, 0x1.bb887a06f6c51p-3, 0x1.bb887a06f6c5p-3},
+                {-0x1.fffffbfffffffp735, -0x1.bb887a06f6c51p-3, -0x1.bb887a06f6c5p-3},
+                {0x1.fffffefffffffp-5, 0x1.ffaaadef54e2fp-5, 0x1.ffaaadef54e3p-5},
+                {-0x1.fffffefffffffp-5, -0x1.ffaaadef54e2fp-5, -0x1.ffaaadef54e3p-5},
+                {0x1.ffffff8p119, 0x1.d4a3c62c5be09p-1, 0x1.d4a3c62c5be08p-1},
+                {-0x1.ffffff8p119, -0x1.d4a3c62c5be09p-1, -0x1.d4a3c62c5be08p-1},
+                {0x1.ffffff8p192, 0x1.cec20f197703fp-3, 0x1.cec20f197704p-3},
+                {-0x1.ffffff8p192, -0x1.cec20f197703fp-3, -0x1.cec20f197704p-3},
+                {0x1.ffffff8p543, 0x1.d37aadc7c8662p-2, 0x1.d37aadc7c8663p-2},
+                {-0x1.ffffff8p543, -0x1.d37aadc7c8662p-2, -0x1.d37aadc7c8663p-2},
+                {0x1.ffffffc0018ffp2, 0x1.fa8d2a4d0a202p-1, 0x1.fa8d2a4d0a203p-1},
+                {-0x1.ffffffc0018ffp2, -0x1.fa8d2a4d0a202p-1, -0x1.fa8d2a4d0a203p-1},
+                {0x1.ffffffffeffffp2, 0x1.fa8d2a029f978p-1, 0x1.fa8d2a029f977p-1},
+                {-0x1.ffffffffeffffp2, -0x1.fa8d2a029f978p-1, -0x1.fa8d2a029f977p-1},
+                {0x1.fffffffff825p943, -0x1.2763f02a2d1eap-4, -0x1.2763f02a2d1e9p-4},
+                {-0x1.fffffffff825p943, 0x1.2763f02a2d1eap-4, 0x1.2763f02a2d1e9p-4},
+                {0x1.fffffffffe09dp320, 0x1.fcff128f77ddbp-1, 0x1.fcff128f77ddap-1},
+                {-0x1.fffffffffe09dp320, -0x1.fcff128f77ddbp-1, -0x1.fcff128f77ddap-1},
+                {0x1.fffffffffe6e3p720, -0x1.fcc0bfedd84a6p-1, -0x1.fcc0bfedd84a5p-1},
+                {-0x1.fffffffffe6e3p720, 0x1.fcc0bfedd84a6p-1, 0x1.fcc0bfedd84a5p-1},
+                {0x1.ffffffffffe7fp-1, 0x1.aed548f090c1ep-1, 0x1.aed548f090c1dp-1},
+                {-0x1.ffffffffffe7fp-1, -0x1.aed548f090c1ep-1, -0x1.aed548f090c1dp-1},
+                {0x1.ffffffffffeffp250, -0x1.f5e11def99d2bp-1, -0x1.f5e11def99d2cp-1},
+                {-0x1.ffffffffffeffp250, 0x1.f5e11def99d2bp-1, 0x1.f5e11def99d2cp-1},
+                {0x1.fffffffffff78p920, 0x1.8a9cbf48fec9fp-1, 0x1.8a9cbf48fecap-1},
+                {-0x1.fffffffffff78p920, -0x1.8a9cbf48fec9fp-1, -0x1.8a9cbf48fecap-1},
+                {0x1.fffffffffff83p150, -0x1.7eba5894844ccp-3, -0x1.7eba5894844cdp-3},
+                {-0x1.fffffffffff83p150, 0x1.7eba5894844ccp-3, 0x1.7eba5894844cdp-3},
+                {0x1.fffffffffffd5p995, 0x1.92c4f06d2cdd1p-1, 0x1.92c4f06d2cdd2p-1},
+                {-0x1.fffffffffffd5p995, -0x1.92c4f06d2cdd1p-1, -0x1.92c4f06d2cdd2p-1},
+                {0x1.fffffffffffe8p720, -0x1.3d5f7deb1d3bbp-1, -0x1.3d5f7deb1d3bap-1},
+                {-0x1.fffffffffffe8p720, 0x1.3d5f7deb1d3bbp-1, 0x1.3d5f7deb1d3bap-1},
+                {0x1.fffffffffffebp920, -0x1.91349b0ae90e5p-1, -0x1.91349b0ae90e6p-1},
+                {-0x1.fffffffffffebp920, 0x1.91349b0ae90e5p-1, 0x1.91349b0ae90e6p-1},
+                {0x1.ffffffffffff1p1, -0x1.837b9dddc1e88p-1, -0x1.837b9dddc1e87p-1},
+                {-0x1.ffffffffffff1p1, 0x1.837b9dddc1e88p-1, 0x1.837b9dddc1e87p-1},
+                {0x1.ffffffffffff1p245, 0x1.510e062e7fa2p-1, 0x1.510e062e7fa21p-1},
+                {-0x1.ffffffffffff1p245, -0x1.510e062e7fa2p-1, -0x1.510e062e7fa21p-1},
+                {0x1.ffffffffffff3p-2, 0x1.eaee8744b05e5p-2, 0x1.eaee8744b05e4p-2},
+                {-0x1.ffffffffffff3p-2, -0x1.eaee8744b05e5p-2, -0x1.eaee8744b05e4p-2},
+                {0x1.ffffffffffff4p845, 0x1.8a4dee8f40628p-1, 0x1.8a4dee8f40627p-1},
+                {-0x1.ffffffffffff4p845, -0x1.8a4dee8f40628p-1, -0x1.8a4dee8f40627p-1},
+                {0x1.ffffffffffff4p1020, 0x1.5118d6bbde07ep-1, 0x1.5118d6bbde07fp-1},
+                {-0x1.ffffffffffff4p1020, -0x1.5118d6bbde07ep-1, -0x1.5118d6bbde07fp-1},
+                {0x1.ffffffffffff8p616, -0x1.5cd5c53cf30a9p-1, -0x1.5cd5c53cf30aap-1},
+                {-0x1.ffffffffffff8p616, 0x1.5cd5c53cf30a9p-1, 0x1.5cd5c53cf30aap-1},
+                {0x1.ffffffffffffcp475, 0x1.ffffa1f0d7dafp-1, 0x1.ffffa1f0d7dbp-1},
+                {-0x1.ffffffffffffcp475, -0x1.ffffa1f0d7dafp-1, -0x1.ffffa1f0d7dbp-1},
+                {0x1.ffffffffffffep970, 0x1.51e9d840106d7p-1, 0x1.51e9d840106d8p-1},
+                {-0x1.ffffffffffffep970, -0x1.51e9d840106d7p-1, -0x1.51e9d840106d8p-1},
+                {-0x0.0000000000001p-1022, -0x0.0000000000001p-1022, -0x0.0p0},
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0p0},
+                {-0x0.0p0, -0x0.0p0, -0x0.0p0},
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0p0},
+                {-0x0.0000000000001p-1022, -0x0.0000000000001p-1022, -0x0.0p0},
+                {-0x1.0000000000001p-1022, -0x1.0000000000001p-1022, -0x1.0000000000001p-1022},
+                {0x1.0000000000001p-1022, 0x1.0000000000001p-1022, 0x1.0000000000001p-1022},
+                {-0x1.0p-1022, -0x1.0p-1022, -0x1.0p-1022},
+                {0x1.0p-1022, 0x1.0p-1022, 0x1.0p-1022},
+                {-0x0.fffffffffffffp-1022, -0x0.fffffffffffffp-1022, -0x0.fffffffffffffp-1022},
+                {0x0.fffffffffffffp-1022, 0x0.fffffffffffffp-1022, 0x0.fffffffffffffp-1022},
+                {0x0.fffffffffffffp-1022, 0x0.fffffffffffffp-1022, 0x0.fffffffffffffp-1022},
+                {-0x0.fffffffffffffp-1022, -0x0.fffffffffffffp-1022, -0x0.fffffffffffffp-1022},
+                {0x1.0p-1022, 0x1.0p-1022, 0x1.0p-1022},
+                {-0x1.0p-1022, -0x1.0p-1022, -0x1.0p-1022},
+                {0x1.0000000000001p-1022, 0x1.0000000000001p-1022, 0x1.0000000000001p-1022},
+                {-0x1.0000000000001p-1022, -0x1.0000000000001p-1022, -0x1.0000000000001p-1022},
+                {0x1.999999999999ap-13, 0x1.9999996de8ca2p-13, 0x1.9999996de8ca1p-13},
+                {-0x1.999999999999ap-13, -0x1.9999996de8ca2p-13, -0x1.9999996de8ca1p-13},
+                {0x1.999999999999ap-12, 0x1.999998ead65b9p-12, 0x1.999998ead65bap-12},
+                {-0x1.999999999999ap-12, -0x1.999998ead65b9p-12, -0x1.999998ead65bap-12},
+                {0x1.3333333333334p-11, 0x1.3333320c49bacp-11, 0x1.3333320c49babp-11},
+                {-0x1.3333333333334p-11, -0x1.3333320c49bacp-11, -0x1.3333320c49babp-11},
+                {0x1.999999999999ap-11, 0x1.999996de8ca29p-11, 0x1.999996de8ca28p-11},
+                {-0x1.999999999999ap-11, -0x1.999996de8ca29p-11, -0x1.999996de8ca28p-11},
+                {0x1.0p-10, 0x1.fffffaaaaaaefp-11, 0x1.fffffaaaaaaeep-11},
+                {-0x1.0p-10, -0x1.fffffaaaaaaefp-11, -0x1.fffffaaaaaaeep-11},
+                {0x1.3333333333333p-10, 0x1.33332e978d553p-10, 0x1.33332e978d552p-10},
+                {-0x1.3333333333333p-10, -0x1.33332e978d553p-10, -0x1.33332e978d552p-10},
+                {0x1.6666666666666p-10, 0x1.66665f1529bp-10, 0x1.66665f1529affp-10},
+                {-0x1.6666666666666p-10, -0x1.66665f1529bp-10, -0x1.66665f1529affp-10},
+                {0x1.9999999999999p-10, 0x1.99998ead65cep-10, 0x1.99998ead65cdfp-10},
+                {-0x1.9999999999999p-10, -0x1.99998ead65cep-10, -0x1.99998ead65cdfp-10},
+                {0x1.cccccccccccccp-10, 0x1.ccccbd3f7d15dp-10, 0x1.ccccbd3f7d15ep-10},
+                {-0x1.cccccccccccccp-10, -0x1.ccccbd3f7d15dp-10, -0x1.ccccbd3f7d15ep-10},
+                {0x1.0666666666666p-7, 0x1.0665ae9c7b44fp-7, 0x1.0665ae9c7b44ep-7},
+                {-0x1.0666666666666p-7, -0x1.0665ae9c7b44fp-7, -0x1.0665ae9c7b44ep-7},
+                {0x1.cccccccccccccp-7, 0x1.ccc8e97b59f62p-7, 0x1.ccc8e97b59f61p-7},
+                {-0x1.cccccccccccccp-7, -0x1.ccc8e97b59f62p-7, -0x1.ccc8e97b59f61p-7},
+                {0x1.4999999999999p-6, 0x1.4993e8a8ff79bp-6, 0x1.4993e8a8ff79cp-6},
+                {-0x1.4999999999999p-6, -0x1.4993e8a8ff79bp-6, -0x1.4993e8a8ff79cp-6},
+                {0x1.accccccccccccp-6, 0x1.acc044c56db0ep-6, 0x1.acc044c56db0fp-6},
+                {-0x1.accccccccccccp-6, -0x1.acc044c56db0ep-6, -0x1.acc044c56db0fp-6},
+                {0x1.08p-5, 0x1.07f44d67cf41bp-5, 0x1.07f44d67cf41ap-5},
+                {-0x1.08p-5, -0x1.07f44d67cf41bp-5, -0x1.07f44d67cf41ap-5},
+                {0x1.399999999999ap-5, 0x1.3985fe46f1c87p-5, 0x1.3985fe46f1c88p-5},
+                {-0x1.399999999999ap-5, -0x1.3985fe46f1c87p-5, -0x1.3985fe46f1c88p-5},
+                {0x1.6b33333333334p-5, 0x1.6b14bde93ac5fp-5, 0x1.6b14bde93ac6p-5},
+                {-0x1.6b33333333334p-5, -0x1.6b14bde93ac5fp-5, -0x1.6b14bde93ac6p-5},
+                {0x1.9cccccccccccep-5, 0x1.9ca0153ed8397p-5, 0x1.9ca0153ed8396p-5},
+                {-0x1.9cccccccccccep-5, -0x1.9ca0153ed8397p-5, -0x1.9ca0153ed8396p-5},
+                {0x1.ce66666666666p-5, 0x1.ce278d4027d34p-5, 0x1.ce278d4027d35p-5},
+                {-0x1.ce66666666666p-5, -0x1.ce278d4027d34p-5, -0x1.ce278d4027d35p-5},
+                {0x1.5e7fc4369bdadp-1, 0x1.43c1e9c171a66p-1, 0x1.43c1e9c171a67p-1},
+                {-0x1.5e7fc4369bdadp-1, -0x1.43c1e9c171a66p-1, -0x1.43c1e9c171a67p-1},
+                {0x1.4e7fc4369bdadp0, 0x1.ee3d6bcea09cap-1, 0x1.ee3d6bcea09cbp-1},
+                {-0x1.4e7fc4369bdadp0, -0x1.ee3d6bcea09cap-1, -0x1.ee3d6bcea09cbp-1},
+                {0x1.edbfa651e9c84p0, 0x1.df8e22ea809d6p-1, 0x1.df8e22ea809d7p-1},
+                {-0x1.edbfa651e9c84p0, -0x1.df8e22ea809d6p-1, -0x1.df8e22ea809d7p-1},
+                {0x1.467fc4369bdadp1, 0x1.1d3479eac7ae3p-1, 0x1.1d3479eac7ae4p-1},
+                {-0x1.467fc4369bdadp1, -0x1.1d3479eac7ae3p-1, -0x1.1d3479eac7ae4p-1},
+                {0x1.961fb54442d18p1, -0x1.ffeaaaeeee84bp-6, -0x1.ffeaaaeeee84cp-6},
+                {-0x1.961fb54442d18p1, 0x1.ffeaaaeeee84bp-6, 0x1.ffeaaaeeee84cp-6},
+                {0x1.e5bfa651e9c83p1, -0x1.3734d32d49bd1p-1, -0x1.3734d32d49bdp-1},
+                {-0x1.e5bfa651e9c83p1, 0x1.3734d32d49bd1p-1, 0x1.3734d32d49bdp-1},
+                {0x1.1aafcbafc85f7p2, -0x1.e9d25d19911e2p-1, -0x1.e9d25d19911e3p-1},
+                {-0x1.1aafcbafc85f7p2, 0x1.e9d25d19911e2p-1, 0x1.e9d25d19911e3p-1},
+                {0x1.427fc4369bdadp2, -0x1.e4ecdc5a4e466p-1, -0x1.e4ecdc5a4e465p-1},
+                {-0x1.427fc4369bdadp2, 0x1.e4ecdc5a4e466p-1, 0x1.e4ecdc5a4e465p-1},
+                {0x1.6a4fbcbd6f562p2, -0x1.2a59f10344262p-1, -0x1.2a59f10344261p-1},
+                {-0x1.6a4fbcbd6f562p2, 0x1.2a59f10344262p-1, 0x1.2a59f10344261p-1},
+                {0x1.6af2eff0a2896p2, -0x1.26312443bd35fp-1, -0x1.26312443bd36p-1},
+                {-0x1.6af2eff0a2896p2, 0x1.26312443bd35fp-1, 0x1.26312443bd36p-1},
+                {0x1.43c62a9d02414p2, -0x1.e18e660a5e2fbp-1, -0x1.e18e660a5e2fcp-1},
+                {-0x1.43c62a9d02414p2, 0x1.e18e660a5e2fbp-1, 0x1.e18e660a5e2fcp-1},
+                {0x1.1c99654961f92p2, -0x1.ee0e83a0198b7p-1, -0x1.ee0e83a0198b6p-1},
+                {-0x1.1c99654961f92p2, 0x1.ee0e83a0198b7p-1, 0x1.ee0e83a0198b6p-1},
+                {0x1.ead93feb8361fp1, -0x1.4727747338e46p-1, -0x1.4727747338e47p-1},
+                {-0x1.ead93feb8361fp1, 0x1.4727747338e46p-1, 0x1.4727747338e47p-1},
+                {0x1.9c7fb54442d1ap1, -0x1.4ba2f75dda5fep-4, -0x1.4ba2f75dda5ffp-4},
+                {-0x1.9c7fb54442d1ap1, 0x1.4ba2f75dda5fep-4, 0x1.4ba2f75dda5ffp-4},
+                {0x1.4e262a9d02415p1, 0x1.034c4d633b4efp-1, 0x1.034c4d633b4fp-1},
+                {-0x1.4e262a9d02415p1, -0x1.034c4d633b4efp-1, -0x1.034c4d633b4fp-1},
+                {0x1.ff993feb8362p0, 0x1.d1e4cde2f3945p-1, 0x1.d1e4cde2f3944p-1},
+                {-0x1.ff993feb8362p0, -0x1.d1e4cde2f3945p-1, -0x1.d1e4cde2f3944p-1},
+                {0x1.62e62a9d02416p0, 0x1.f750235c94992p-1, 0x1.f750235c94993p-1},
+                {-0x1.62e62a9d02416p0, -0x1.f750235c94992p-1, -0x1.f750235c94993p-1},
+                {0x1.8c662a9d02419p-1, 0x1.65f7d571279b1p-1, 0x1.65f7d571279bp-1},
+                {-0x1.8c662a9d02419p-1, -0x1.65f7d571279b1p-1, -0x1.65f7d571279bp-1},
+                {-0x1.a8aa1d11c44ffp0, -0x1.fe043f57369d7p-1, -0x1.fe043f57369d6p-1},
+                {0x1.a8aa1d11c44ffp0, 0x1.fe043f57369d7p-1, 0x1.fe043f57369d6p-1},
+                {-0x1.95ec8b9e03d54p0, -0x1.fff18f24f3e4cp-1, -0x1.fff18f24f3e4bp-1},
+                {0x1.95ec8b9e03d54p0, 0x1.fff18f24f3e4cp-1, 0x1.fff18f24f3e4bp-1},
+                {-0x1.832efa2a435a9p0, -0x1.ff20d961624e7p-1, -0x1.ff20d961624e8p-1},
+                {0x1.832efa2a435a9p0, 0x1.ff20d961624e7p-1, 0x1.ff20d961624e8p-1},
+                {-0x1.707168b682dfep0, -0x1.fb933c40107fdp-1, -0x1.fb933c40107fep-1},
+                {0x1.707168b682dfep0, 0x1.fb933c40107fdp-1, 0x1.fb933c40107fep-1},
+                {-0x1.5db3d742c2653p0, -0x1.f54d971881ad7p-1, -0x1.f54d971881ad6p-1},
+                {0x1.5db3d742c2653p0, 0x1.f54d971881ad7p-1, 0x1.f54d971881ad6p-1},
+                {-0x1.4af645cf01ea8p0, -0x1.ec5883b7b6cf5p-1, -0x1.ec5883b7b6cf4p-1},
+                {0x1.4af645cf01ea8p0, 0x1.ec5883b7b6cf5p-1, 0x1.ec5883b7b6cf4p-1},
+                {-0x1.3838b45b416fdp0, -0x1.e0c04a94e1731p-1, -0x1.e0c04a94e173p-1},
+                {0x1.3838b45b416fdp0, 0x1.e0c04a94e1731p-1, 0x1.e0c04a94e173p-1},
+                {-0x1.257b22e780f52p0, -0x1.d294d1f96c7ecp-1, -0x1.d294d1f96c7ebp-1},
+                {0x1.257b22e780f52p0, 0x1.d294d1f96c7ecp-1, 0x1.d294d1f96c7ebp-1},
+                {-0x1.12bd9173c07abp0, -0x1.c1e9883373d7fp-1, -0x1.c1e9883373d7ep-1},
+                {0x1.12bd9173c07abp0, 0x1.c1e9883373d7fp-1, 0x1.c1e9883373d7ep-1},
+                {-0x1.ea5c3ed5b385p-1, -0x1.a2c289d9d055bp-1, -0x1.a2c289d9d055ap-1},
+                {0x1.ea5c3ed5b385p-1, 0x1.a2c289d9d055bp-1, 0x1.a2c289d9d055ap-1},
+                {-0x1.d4b87dab670ap-1, -0x1.95f05257dbcb6p-1, -0x1.95f05257dbcb5p-1},
+                {0x1.d4b87dab670ap-1, 0x1.95f05257dbcb6p-1, 0x1.95f05257dbcb5p-1},
+                {-0x1.bf14bc811a8fp-1, -0x1.88647f26a6e0fp-1, -0x1.88647f26a6e1p-1},
+                {0x1.bf14bc811a8fp-1, 0x1.88647f26a6e0fp-1, 0x1.88647f26a6e1p-1},
+                {-0x1.a970fb56ce14p-1, -0x1.7a2541dfd4e75p-1, -0x1.7a2541dfd4e76p-1},
+                {0x1.a970fb56ce14p-1, 0x1.7a2541dfd4e75p-1, 0x1.7a2541dfd4e76p-1},
+                {-0x1.93cd3a2c8199p-1, -0x1.6b391e25bc26dp-1, -0x1.6b391e25bc26cp-1},
+                {0x1.93cd3a2c8199p-1, 0x1.6b391e25bc26dp-1, 0x1.6b391e25bc26cp-1},
+                {-0x1.7e297902351ep-1, -0x1.5ba6e6a8e7065p-1, -0x1.5ba6e6a8e7066p-1},
+                {0x1.7e297902351ep-1, 0x1.5ba6e6a8e7065p-1, 0x1.5ba6e6a8e7066p-1},
+                {-0x1.6885b7d7e8a3p-1, -0x1.4b75ba096fa55p-1, -0x1.4b75ba096fa54p-1},
+                {0x1.6885b7d7e8a3p-1, 0x1.4b75ba096fa55p-1, 0x1.4b75ba096fa54p-1},
+                {-0x1.52e1f6ad9c28p-1, -0x1.3aacff95a3123p-1, -0x1.3aacff95a3122p-1},
+                {0x1.52e1f6ad9c28p-1, 0x1.3aacff95a3123p-1, 0x1.3aacff95a3122p-1},
+                {-0x1.3d3e35834fadp-1, -0x1.295463e769285p-1, -0x1.295463e769284p-1},
+                {0x1.3d3e35834fadp-1, 0x1.295463e769285p-1, 0x1.295463e769284p-1},
+                {-0x1.0a0b02501c799p-1, -0x1.fc769b77e5885p-2, -0x1.fc769b77e5884p-2},
+                {0x1.0a0b02501c799p-1, 0x1.fc769b77e5885p-2, 0x1.fc769b77e5884p-2},
+                {-0x1.d8f7208e6b82cp-2, -0x1.c853c78462de4p-2, -0x1.c853c78462de5p-2},
+                {0x1.d8f7208e6b82cp-2, 0x1.c853c78462de4p-2, 0x1.c853c78462de5p-2},
+                {-0x1.9dd83c7c9e126p-2, -0x1.92aba90aaf272p-2, -0x1.92aba90aaf273p-2},
+                {0x1.9dd83c7c9e126p-2, 0x1.92aba90aaf272p-2, 0x1.92aba90aaf273p-2},
+                {-0x1.62b9586ad0a2p-2, -0x1.5bac064658f39p-2, -0x1.5bac064658f3ap-2},
+                {0x1.62b9586ad0a2p-2, 0x1.5bac064658f39p-2, 0x1.5bac064658f3ap-2},
+                {-0x1.279a74590331ap-2, -0x1.2383ca8078e58p-2, -0x1.2383ca8078e59p-2},
+                {0x1.279a74590331ap-2, 0x1.2383ca8078e58p-2, 0x1.2383ca8078e59p-2},
+                {-0x1.d8f7208e6b829p-3, -0x1.d4c5bc11d2372p-3, -0x1.d4c5bc11d2371p-3},
+                {0x1.d8f7208e6b829p-3, 0x1.d4c5bc11d2372p-3, 0x1.d4c5bc11d2371p-3},
+                {-0x1.62b9586ad0a1ep-3, -0x1.60f3faaf43024p-3, -0x1.60f3faaf43023p-3},
+                {0x1.62b9586ad0a1ep-3, 0x1.60f3faaf43024p-3, 0x1.60f3faaf43023p-3},
+                {-0x1.d8f7208e6b826p-4, -0x1.d7ea3de45a9d6p-4, -0x1.d7ea3de45a9d7p-4},
+                {0x1.d8f7208e6b826p-4, 0x1.d7ea3de45a9d6p-4, 0x1.d7ea3de45a9d7p-4},
+                {-0x1.d8f7208e6b82dp-5, -0x1.d8b3df489987ap-5, -0x1.d8b3df489987bp-5},
+                {0x1.d8f7208e6b82dp-5, 0x1.d8b3df489987ap-5, 0x1.d8b3df489987bp-5},
+                {0x1.d8f7208e6b82dp-5, 0x1.d8b3df489987ap-5, 0x1.d8b3df489987bp-5},
+                {-0x1.d8f7208e6b82dp-5, -0x1.d8b3df489987ap-5, -0x1.d8b3df489987bp-5},
+                {0x1.d8f7208e6b82dp-4, 0x1.d7ea3de45a9ddp-4, 0x1.d7ea3de45a9dep-4},
+                {-0x1.d8f7208e6b82dp-4, -0x1.d7ea3de45a9ddp-4, -0x1.d7ea3de45a9dep-4},
+                {0x1.62b9586ad0a22p-3, 0x1.60f3faaf43028p-3, 0x1.60f3faaf43027p-3},
+                {-0x1.62b9586ad0a22p-3, -0x1.60f3faaf43028p-3, -0x1.60f3faaf43027p-3},
+                {0x1.d8f7208e6b82dp-3, 0x1.d4c5bc11d2376p-3, 0x1.d4c5bc11d2375p-3},
+                {-0x1.d8f7208e6b82dp-3, -0x1.d4c5bc11d2376p-3, -0x1.d4c5bc11d2375p-3},
+                {0x1.279a74590331cp-2, 0x1.2383ca8078e5ap-2, 0x1.2383ca8078e5bp-2},
+                {-0x1.279a74590331cp-2, -0x1.2383ca8078e5ap-2, -0x1.2383ca8078e5bp-2},
+                {0x1.62b9586ad0a22p-2, 0x1.5bac064658f3bp-2, 0x1.5bac064658f3cp-2},
+                {-0x1.62b9586ad0a22p-2, -0x1.5bac064658f3bp-2, -0x1.5bac064658f3cp-2},
+                {0x1.9dd83c7c9e128p-2, 0x1.92aba90aaf274p-2, 0x1.92aba90aaf275p-2},
+                {-0x1.9dd83c7c9e128p-2, -0x1.92aba90aaf274p-2, -0x1.92aba90aaf275p-2},
+                {0x1.d8f7208e6b82ep-2, 0x1.c853c78462de6p-2, 0x1.c853c78462de7p-2},
+                {-0x1.d8f7208e6b82ep-2, -0x1.c853c78462de6p-2, -0x1.c853c78462de7p-2},
+                {0x1.0a0b02501c799p-1, 0x1.fc769b77e5885p-2, 0x1.fc769b77e5884p-2},
+                {-0x1.0a0b02501c799p-1, -0x1.fc769b77e5885p-2, -0x1.fc769b77e5884p-2},
+                {0x1.3d3e35834faccp-1, 0x1.295463e769281p-1, 0x1.295463e769282p-1},
+                {-0x1.3d3e35834faccp-1, -0x1.295463e769281p-1, -0x1.295463e769282p-1},
+                {0x1.52e1f6ad9c27cp-1, 0x1.3aacff95a312p-1, 0x1.3aacff95a311fp-1},
+                {-0x1.52e1f6ad9c27cp-1, -0x1.3aacff95a312p-1, -0x1.3aacff95a311fp-1},
+                {0x1.6885b7d7e8a2cp-1, 0x1.4b75ba096fa52p-1, 0x1.4b75ba096fa51p-1},
+                {-0x1.6885b7d7e8a2cp-1, -0x1.4b75ba096fa52p-1, -0x1.4b75ba096fa51p-1},
+                {0x1.7e297902351dcp-1, 0x1.5ba6e6a8e7062p-1, 0x1.5ba6e6a8e7063p-1},
+                {-0x1.7e297902351dcp-1, -0x1.5ba6e6a8e7062p-1, -0x1.5ba6e6a8e7063p-1},
+                {0x1.93cd3a2c8198cp-1, 0x1.6b391e25bc26ap-1, 0x1.6b391e25bc269p-1},
+                {-0x1.93cd3a2c8198cp-1, -0x1.6b391e25bc26ap-1, -0x1.6b391e25bc269p-1},
+                {0x1.a970fb56ce13cp-1, 0x1.7a2541dfd4e73p-1, 0x1.7a2541dfd4e72p-1},
+                {-0x1.a970fb56ce13cp-1, -0x1.7a2541dfd4e73p-1, -0x1.7a2541dfd4e72p-1},
+                {0x1.bf14bc811a8ecp-1, 0x1.88647f26a6e0dp-1, 0x1.88647f26a6e0cp-1},
+                {-0x1.bf14bc811a8ecp-1, -0x1.88647f26a6e0dp-1, -0x1.88647f26a6e0cp-1},
+                {0x1.d4b87dab6709cp-1, 0x1.95f05257dbcb4p-1, 0x1.95f05257dbcb3p-1},
+                {-0x1.d4b87dab6709cp-1, -0x1.95f05257dbcb4p-1, -0x1.95f05257dbcb3p-1},
+                {0x1.ea5c3ed5b384cp-1, 0x1.a2c289d9d0558p-1, 0x1.a2c289d9d0559p-1},
+                {-0x1.ea5c3ed5b384cp-1, -0x1.a2c289d9d0558p-1, -0x1.a2c289d9d0559p-1},
+                {0x1.12bd9173c07abp0, 0x1.c1e9883373d7fp-1, 0x1.c1e9883373d7ep-1},
+                {-0x1.12bd9173c07abp0, -0x1.c1e9883373d7fp-1, -0x1.c1e9883373d7ep-1},
+                {0x1.257b22e780f56p0, 0x1.d294d1f96c7efp-1, 0x1.d294d1f96c7fp-1},
+                {-0x1.257b22e780f56p0, -0x1.d294d1f96c7efp-1, -0x1.d294d1f96c7fp-1},
+                {0x1.3838b45b41701p0, 0x1.e0c04a94e1733p-1, 0x1.e0c04a94e1734p-1},
+                {-0x1.3838b45b41701p0, -0x1.e0c04a94e1733p-1, -0x1.e0c04a94e1734p-1},
+                {0x1.4af645cf01eacp0, 0x1.ec5883b7b6cf7p-1, 0x1.ec5883b7b6cf8p-1},
+                {-0x1.4af645cf01eacp0, -0x1.ec5883b7b6cf7p-1, -0x1.ec5883b7b6cf8p-1},
+                {0x1.5db3d742c2657p0, 0x1.f54d971881ad8p-1, 0x1.f54d971881ad9p-1},
+                {-0x1.5db3d742c2657p0, -0x1.f54d971881ad8p-1, -0x1.f54d971881ad9p-1},
+                {0x1.707168b682e02p0, 0x1.fb933c40107fep-1, 0x1.fb933c40107ffp-1},
+                {-0x1.707168b682e02p0, -0x1.fb933c40107fep-1, -0x1.fb933c40107ffp-1},
+                {0x1.832efa2a435adp0, 0x1.ff20d961624e7p-1, 0x1.ff20d961624e8p-1},
+                {-0x1.832efa2a435adp0, -0x1.ff20d961624e7p-1, -0x1.ff20d961624e8p-1},
+                {0x1.95ec8b9e03d58p0, 0x1.fff18f24f3e4bp-1, 0x1.fff18f24f3e4cp-1},
+                {-0x1.95ec8b9e03d58p0, -0x1.fff18f24f3e4bp-1, -0x1.fff18f24f3e4cp-1},
+                {0x1.a8aa1d11c44ffp0, 0x1.fe043f57369d7p-1, 0x1.fe043f57369d6p-1},
+                {-0x1.a8aa1d11c44ffp0, -0x1.fe043f57369d7p-1, -0x1.fe043f57369d6p-1},
+                {0x1.04aff6d330942p0, 0x1.b3d3695acc413p-1, 0x1.b3d3695acc414p-1},
+                {-0x1.04aff6d330942p0, -0x1.b3d3695acc413p-1, -0x1.b3d3695acc414p-1},
+                {0x1.04b09e98dcdb4p0, 0x1.b3d41972dc806p-1, 0x1.b3d41972dc807p-1},
+                {-0x1.04b09e98dcdb4p0, -0x1.b3d41972dc806p-1, -0x1.b3d41972dc807p-1},
+                {0x1.04b1465e89226p0, 0x1.b3d4c98a318fbp-1, 0x1.b3d4c98a318fcp-1},
+                {-0x1.04b1465e89226p0, -0x1.b3d4c98a318fbp-1, -0x1.b3d4c98a318fcp-1},
+                {0x1.04b1ee2435698p0, 0x1.b3d579a0cb6eep-1, 0x1.b3d579a0cb6efp-1},
+                {-0x1.04b1ee2435698p0, -0x1.b3d579a0cb6eep-1, -0x1.b3d579a0cb6efp-1},
+                {0x1.04b295e9e1b0ap0, 0x1.b3d629b6aa1dap-1, 0x1.b3d629b6aa1d9p-1},
+                {-0x1.04b295e9e1b0ap0, -0x1.b3d629b6aa1dap-1, -0x1.b3d629b6aa1d9p-1},
+                {0x1.04b33daf8df7cp0, 0x1.b3d6d9cbcd9bap-1, 0x1.b3d6d9cbcd9b9p-1},
+                {-0x1.04b33daf8df7cp0, -0x1.b3d6d9cbcd9bap-1, -0x1.b3d6d9cbcd9b9p-1},
+                {0x1.04b3e5753a3eep0, 0x1.b3d789e035e89p-1, 0x1.b3d789e035e8ap-1},
+                {-0x1.04b3e5753a3eep0, -0x1.b3d789e035e89p-1, -0x1.b3d789e035e8ap-1},
+                {0x1.04b48d3ae686p0, 0x1.b3d839f3e3043p-1, 0x1.b3d839f3e3044p-1},
+                {-0x1.04b48d3ae686p0, -0x1.b3d839f3e3043p-1, -0x1.b3d839f3e3044p-1},
+                {0x1.04b5350092ccfp0, 0x1.b3d8ea06d4eep-1, 0x1.b3d8ea06d4ee1p-1},
+                {-0x1.04b5350092ccfp0, -0x1.b3d8ea06d4eep-1, -0x1.b3d8ea06d4ee1p-1},
+                {-0x0.0000000000001p-1022, -0x0.0000000000001p-1022, -0x0.0p0},
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0p0},
+                {-0x0.0p0, -0x0.0p0, -0x0.0p0},
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0p0},
+                {-0x0.0000000000001p-1022, -0x0.0000000000001p-1022, -0x0.0p0},
+                {0x1.279a74590331bp-1, 0x1.1773d561fd506p-1, 0x1.1773d561fd507p-1},
+                {-0x1.279a74590331bp-1, -0x1.1773d561fd506p-1, -0x1.1773d561fd507p-1},
+                {0x1.279a74590331cp-1, 0x1.1773d561fd507p-1, 0x1.1773d561fd508p-1},
+                {-0x1.279a74590331cp-1, -0x1.1773d561fd507p-1, -0x1.1773d561fd508p-1},
+                {0x1.279a74590331dp-1, 0x1.1773d561fd508p-1, 0x1.1773d561fd509p-1},
+                {-0x1.279a74590331dp-1, -0x1.1773d561fd508p-1, -0x1.1773d561fd509p-1},
+                {0x1.bb67ae8584ca9p0, 0x1.f95b8e7107419p-1, 0x1.f95b8e7107418p-1},
+                {-0x1.bb67ae8584ca9p0, -0x1.f95b8e7107419p-1, -0x1.f95b8e7107418p-1},
+                {0x1.bb67ae8584caap0, 0x1.f95b8e7107418p-1, 0x1.f95b8e7107419p-1},
+                {-0x1.bb67ae8584caap0, -0x1.f95b8e7107418p-1, -0x1.f95b8e7107419p-1},
+                {0x1.bb67ae8584cabp0, 0x1.f95b8e7107418p-1, 0x1.f95b8e7107419p-1},
+                {-0x1.bb67ae8584cabp0, -0x1.f95b8e7107418p-1, -0x1.f95b8e7107419p-1},
+                {0x1.bffffffffffffp-2, 0x1.b1d8305321616p-2, 0x1.b1d8305321615p-2},
+                {-0x1.bffffffffffffp-2, -0x1.b1d8305321616p-2, -0x1.b1d8305321615p-2},
+                {0x1.cp-2, 0x1.b1d8305321617p-2, 0x1.b1d8305321616p-2},
+                {-0x1.cp-2, -0x1.b1d8305321617p-2, -0x1.b1d8305321616p-2},
+                {0x1.c000000000001p-2, 0x1.b1d8305321617p-2, 0x1.b1d8305321618p-2},
+                {-0x1.c000000000001p-2, -0x1.b1d8305321617p-2, -0x1.b1d8305321618p-2},
+                {0x1.5ffffffffffffp-1, 0x1.44eb381cf386ap-1, 0x1.44eb381cf3869p-1},
+                {-0x1.5ffffffffffffp-1, -0x1.44eb381cf386ap-1, -0x1.44eb381cf3869p-1},
+                {0x1.6p-1, 0x1.44eb381cf386bp-1, 0x1.44eb381cf386ap-1},
+                {-0x1.6p-1, -0x1.44eb381cf386bp-1, -0x1.44eb381cf386ap-1},
+                {0x1.6000000000001p-1, 0x1.44eb381cf386cp-1, 0x1.44eb381cf386bp-1},
+                {-0x1.6000000000001p-1, -0x1.44eb381cf386cp-1, -0x1.44eb381cf386bp-1},
+                {0x1.2ffffffffffffp0, 0x1.dad902fa8ac86p-1, 0x1.dad902fa8ac87p-1},
+                {-0x1.2ffffffffffffp0, -0x1.dad902fa8ac86p-1, -0x1.dad902fa8ac87p-1},
+                {0x1.3p0, 0x1.dad902fa8ac87p-1, 0x1.dad902fa8ac88p-1},
+                {-0x1.3p0, -0x1.dad902fa8ac87p-1, -0x1.dad902fa8ac88p-1},
+                {0x1.3000000000001p0, 0x1.dad902fa8ac88p-1, 0x1.dad902fa8ac87p-1},
+                {-0x1.3000000000001p0, -0x1.dad902fa8ac88p-1, -0x1.dad902fa8ac87p-1},
+                {0x1.37fffffffffffp1, 0x1.4b707a7acdedp-1, 0x1.4b707a7acdecfp-1},
+                {-0x1.37fffffffffffp1, -0x1.4b707a7acdedp-1, -0x1.4b707a7acdecfp-1},
+                {0x1.38p1, 0x1.4b707a7acdecdp-1, 0x1.4b707a7acdeccp-1},
+                {-0x1.38p1, -0x1.4b707a7acdecdp-1, -0x1.4b707a7acdeccp-1},
+                {0x1.3800000000001p1, 0x1.4b707a7acdecap-1, 0x1.4b707a7acdec9p-1},
+                {-0x1.3800000000001p1, -0x1.4b707a7acdecap-1, -0x1.4b707a7acdec9p-1},
+                {0x1.069c8b46b3792p-4, 0x1.066e7eb76f5c6p-4, 0x1.066e7eb76f5c7p-4},
+                {-0x1.069c8b46b3792p-4, -0x1.066e7eb76f5c6p-4, -0x1.066e7eb76f5c7p-4},
+                {0x1.069c8b46b3792p-3, 0x1.05e4761ab8d8fp-3, 0x1.05e4761ab8d9p-3},
+                {-0x1.069c8b46b3792p-3, -0x1.05e4761ab8d8fp-3, -0x1.05e4761ab8d9p-3},
+                {0x1.89ead0ea0d35bp-3, 0x1.877e2cd4f6fdap-3, 0x1.877e2cd4f6fd9p-3},
+                {-0x1.89ead0ea0d35bp-3, -0x1.877e2cd4f6fdap-3, -0x1.877e2cd4f6fd9p-3},
+                {0x1.069c8b46b3792p-2, 0x1.03be06f97cbeep-2, 0x1.03be06f97cbefp-2},
+                {-0x1.069c8b46b3792p-2, -0x1.03be06f97cbeep-2, -0x1.03be06f97cbefp-2},
+                {0x1.4843ae1860576p-2, 0x1.42abba8c72fbcp-2, 0x1.42abba8c72fbbp-2},
+                {-0x1.4843ae1860576p-2, -0x1.42abba8c72fbcp-2, -0x1.42abba8c72fbbp-2},
+                {0x1.89ead0ea0d35ap-2, 0x1.8045fe64e62dcp-2, 0x1.8045fe64e62ddp-2},
+                {-0x1.89ead0ea0d35ap-2, -0x1.8045fe64e62dcp-2, -0x1.8045fe64e62ddp-2},
+                {0x1.cb91f3bbba13ep-2, 0x1.bc4c04d71abbfp-2, 0x1.bc4c04d71abbep-2},
+                {-0x1.cb91f3bbba13ep-2, -0x1.bc4c04d71abbfp-2, -0x1.bc4c04d71abbep-2},
+                {0x1.069c8b46b3791p-1, 0x1.f67ea975b86ap-2, 0x1.f67ea975b86a1p-2},
+                {-0x1.069c8b46b3791p-1, -0x1.f67ea975b86ap-2, -0x1.f67ea975b86a1p-2},
+                {0x1.27701caf89e83p-1, 0x1.175059bf0d425p-1, 0x1.175059bf0d426p-1},
+                {-0x1.27701caf89e83p-1, -0x1.175059bf0d425p-1, -0x1.175059bf0d426p-1},
+                {0x1.4843ae1860575p-1, 0x1.323b8b1fb4ba2p-1, 0x1.323b8b1fb4ba3p-1},
+                {-0x1.4843ae1860575p-1, -0x1.323b8b1fb4ba2p-1, -0x1.323b8b1fb4ba3p-1},
+                {0x1.69173f8136c67p-1, 0x1.4be4979c5efb3p-1, 0x1.4be4979c5efb4p-1},
+                {-0x1.69173f8136c67p-1, -0x1.4be4979c5efb3p-1, -0x1.4be4979c5efb4p-1},
+                {0x1.89ead0ea0d359p-1, 0x1.643080d67acc1p-1, 0x1.643080d67acc2p-1},
+                {-0x1.89ead0ea0d359p-1, -0x1.643080d67acc1p-1, -0x1.643080d67acc2p-1},
+                {0x1.aabe6252e3a4bp-1, 0x1.7b05b7b6c612ep-1, 0x1.7b05b7b6c612fp-1},
+                {-0x1.aabe6252e3a4bp-1, -0x1.7b05b7b6c612ep-1, -0x1.7b05b7b6c612fp-1},
+                {0x1.cb91f3bbba13dp-1, 0x1.904c37505de49p-1, 0x1.904c37505de48p-1},
+                {-0x1.cb91f3bbba13dp-1, -0x1.904c37505de49p-1, -0x1.904c37505de48p-1},
+                {0x1.ec6585249082fp-1, 0x1.a3ed9e252938ap-1, 0x1.a3ed9e252938bp-1},
+                {-0x1.ec6585249082fp-1, -0x1.a3ed9e252938ap-1, -0x1.a3ed9e252938bp-1},
+                {0x1.069c8b46b3791p0, 0x1.b5d545b109bf9p-1, 0x1.b5d545b109bfap-1},
+                {-0x1.069c8b46b3791p0, -0x1.b5d545b109bf9p-1, -0x1.b5d545b109bfap-1},
+                {0x1.170653fb1eb0ap0, 0x1.c5f058230e7fdp-1, 0x1.c5f058230e7fep-1},
+                {-0x1.170653fb1eb0ap0, -0x1.c5f058230e7fdp-1, -0x1.c5f058230e7fep-1},
+                {0x1.27701caf89e83p0, 0x1.d42de42dce134p-1, 0x1.d42de42dce135p-1},
+                {-0x1.27701caf89e83p0, -0x1.d42de42dce134p-1, -0x1.d42de42dce135p-1},
+                {0x1.37d9e563f51fcp0, 0x1.e07eeeda109cbp-1, 0x1.e07eeeda109ccp-1},
+                {-0x1.37d9e563f51fcp0, -0x1.e07eeeda109cbp-1, -0x1.e07eeeda109ccp-1},
+                {0x1.4843ae1860575p0, 0x1.ead6834909b93p-1, 0x1.ead6834909b94p-1},
+                {-0x1.4843ae1860575p0, -0x1.ead6834909b93p-1, -0x1.ead6834909b94p-1},
+                {0x1.58ad76cccb8eep0, 0x1.f329c0558e968p-1, 0x1.f329c0558e967p-1},
+                {-0x1.58ad76cccb8eep0, -0x1.f329c0558e968p-1, -0x1.f329c0558e967p-1},
+                {0x1.69173f8136c67p0, 0x1.f96fe405f1ac6p-1, 0x1.f96fe405f1ac5p-1},
+                {-0x1.69173f8136c67p0, -0x1.f96fe405f1ac6p-1, -0x1.f96fe405f1ac5p-1},
+                {0x1.79810835a1fep0, 0x1.fda254c27a01fp-1, 0x1.fda254c27a02p-1},
+                {-0x1.79810835a1fep0, -0x1.fda254c27a01fp-1, -0x1.fda254c27a02p-1},
+                {0x1.89ead0ea0d359p0, 0x1.ffbca846c4fcap-1, 0x1.ffbca846c4fc9p-1},
+                {-0x1.89ead0ea0d359p0, -0x1.ffbca846c4fcap-1, -0x1.ffbca846c4fc9p-1},
+                {0x1.9a54999e786d2p0, 0x1.ffbca846c4fcap-1, 0x1.ffbca846c4fc9p-1},
+                {-0x1.9a54999e786d2p0, -0x1.ffbca846c4fcap-1, -0x1.ffbca846c4fc9p-1},
+                {0x1.aabe6252e3a4bp0, 0x1.fda254c27a02p-1, 0x1.fda254c27a021p-1},
+                {-0x1.aabe6252e3a4bp0, -0x1.fda254c27a02p-1, -0x1.fda254c27a021p-1},
+                {0x1.bb282b074edc4p0, 0x1.f96fe405f1ac8p-1, 0x1.f96fe405f1ac7p-1},
+                {-0x1.bb282b074edc4p0, -0x1.f96fe405f1ac8p-1, -0x1.f96fe405f1ac7p-1},
+                {0x1.cb91f3bbba13dp0, 0x1.f329c0558e96ap-1, 0x1.f329c0558e96bp-1},
+                {-0x1.cb91f3bbba13dp0, -0x1.f329c0558e96ap-1, -0x1.f329c0558e96bp-1},
+                {0x1.dbfbbc70254b6p0, 0x1.ead6834909b96p-1, 0x1.ead6834909b97p-1},
+                {-0x1.dbfbbc70254b6p0, -0x1.ead6834909b96p-1, -0x1.ead6834909b97p-1},
+                {0x1.ec6585249082fp0, 0x1.e07eeeda109cfp-1, 0x1.e07eeeda109dp-1},
+                {-0x1.ec6585249082fp0, -0x1.e07eeeda109cfp-1, -0x1.e07eeeda109dp-1},
+                {0x1.fccf4dd8fbba8p0, 0x1.d42de42dce139p-1, 0x1.d42de42dce138p-1},
+                {-0x1.fccf4dd8fbba8p0, -0x1.d42de42dce139p-1, -0x1.d42de42dce138p-1},
+                {0x1.069c8b46b3791p1, 0x1.c5f058230e801p-1, 0x1.c5f058230e802p-1},
+                {-0x1.069c8b46b3791p1, -0x1.c5f058230e801p-1, -0x1.c5f058230e802p-1},
+                {0x1.0ed16fa0e914ep1, 0x1.b5d545b109bfdp-1, 0x1.b5d545b109bfcp-1},
+                {-0x1.0ed16fa0e914ep1, -0x1.b5d545b109bfdp-1, -0x1.b5d545b109bfcp-1},
+                {0x1.170653fb1eb0bp1, 0x1.a3ed9e252938dp-1, 0x1.a3ed9e252938ep-1},
+                {-0x1.170653fb1eb0bp1, -0x1.a3ed9e252938dp-1, -0x1.a3ed9e252938ep-1},
+                {0x1.1f3b3855544c8p1, 0x1.904c37505de4cp-1, 0x1.904c37505de4bp-1},
+                {-0x1.1f3b3855544c8p1, -0x1.904c37505de4cp-1, -0x1.904c37505de4bp-1},
+                {0x1.27701caf89e85p1, 0x1.7b05b7b6c613p-1, 0x1.7b05b7b6c612fp-1},
+                {-0x1.27701caf89e85p1, -0x1.7b05b7b6c613p-1, -0x1.7b05b7b6c612fp-1},
+                {0x1.2fa50109bf842p1, 0x1.643080d67acc1p-1, 0x1.643080d67acc2p-1},
+                {-0x1.2fa50109bf842p1, -0x1.643080d67acc1p-1, -0x1.643080d67acc2p-1},
+                {0x1.37d9e563f51ffp1, 0x1.4be4979c5efb2p-1, 0x1.4be4979c5efb1p-1},
+                {-0x1.37d9e563f51ffp1, -0x1.4be4979c5efb2p-1, -0x1.4be4979c5efb1p-1},
+                {0x1.400ec9be2abbcp1, 0x1.323b8b1fb4b9fp-1, 0x1.323b8b1fb4b9ep-1},
+                {-0x1.400ec9be2abbcp1, -0x1.323b8b1fb4b9fp-1, -0x1.323b8b1fb4b9ep-1},
+                {0x1.4843ae1860579p1, 0x1.175059bf0d42p-1, 0x1.175059bf0d421p-1},
+                {-0x1.4843ae1860579p1, -0x1.175059bf0d42p-1, -0x1.175059bf0d421p-1},
+                {0x1.5078927295f36p1, 0x1.f67ea975b8692p-2, 0x1.f67ea975b8693p-2},
+                {-0x1.5078927295f36p1, -0x1.f67ea975b8692p-2, -0x1.f67ea975b8693p-2},
+                {0x1.58ad76cccb8f3p1, 0x1.bc4c04d71abadp-2, 0x1.bc4c04d71abaep-2},
+                {-0x1.58ad76cccb8f3p1, -0x1.bc4c04d71abadp-2, -0x1.bc4c04d71abaep-2},
+                {0x1.60e25b27012bp1, 0x1.8045fe64e62c6p-2, 0x1.8045fe64e62c7p-2},
+                {-0x1.60e25b27012bp1, -0x1.8045fe64e62c6p-2, -0x1.8045fe64e62c7p-2},
+                {0x1.69173f8136c6dp1, 0x1.42abba8c72fa1p-2, 0x1.42abba8c72fa2p-2},
+                {-0x1.69173f8136c6dp1, -0x1.42abba8c72fa1p-2, -0x1.42abba8c72fa2p-2},
+                {0x1.714c23db6c62ap1, 0x1.03be06f97cbdp-2, 0x1.03be06f97cbcfp-2},
+                {-0x1.714c23db6c62ap1, -0x1.03be06f97cbdp-2, -0x1.03be06f97cbcfp-2},
+                {0x1.79810835a1fe7p1, 0x1.877e2cd4f6f94p-3, 0x1.877e2cd4f6f95p-3},
+                {-0x1.79810835a1fe7p1, -0x1.877e2cd4f6f94p-3, -0x1.877e2cd4f6f95p-3},
+                {0x1.81b5ec8fd79a4p1, 0x1.05e4761ab8d42p-3, 0x1.05e4761ab8d43p-3},
+                {-0x1.81b5ec8fd79a4p1, -0x1.05e4761ab8d42p-3, -0x1.05e4761ab8d43p-3},
+                {0x1.89ead0ea0d35bp1, 0x1.066e7eb76f5ddp-4, 0x1.066e7eb76f5dep-4},
+                {-0x1.89ead0ea0d35bp1, -0x1.066e7eb76f5ddp-4, -0x1.066e7eb76f5dep-4},
+                {-0x1.81b5ec8fd799fp2, 0x1.03be06f97cbf1p-2, 0x1.03be06f97cbfp-2},
+                {0x1.81b5ec8fd799fp2, -0x1.03be06f97cbf1p-2, -0x1.03be06f97cbfp-2},
+                {-0x1.714c23db6c626p2, 0x1.f67ea975b86a2p-2, 0x1.f67ea975b86a3p-2},
+                {0x1.714c23db6c626p2, -0x1.f67ea975b86a2p-2, -0x1.f67ea975b86a3p-2},
+                {-0x1.60e25b27012adp2, 0x1.643080d67acc2p-1, 0x1.643080d67acc3p-1},
+                {0x1.60e25b27012adp2, -0x1.643080d67acc2p-1, -0x1.643080d67acc3p-1},
+                {-0x1.5078927295f34p2, 0x1.b5d545b109bf9p-1, 0x1.b5d545b109bfap-1},
+                {0x1.5078927295f34p2, -0x1.b5d545b109bf9p-1, -0x1.b5d545b109bfap-1},
+                {-0x1.400ec9be2abbbp2, 0x1.ead6834909b93p-1, 0x1.ead6834909b94p-1},
+                {0x1.400ec9be2abbbp2, -0x1.ead6834909b93p-1, -0x1.ead6834909b94p-1},
+                {-0x1.2fa50109bf842p2, 0x1.ffbca846c4fcap-1, 0x1.ffbca846c4fc9p-1},
+                {0x1.2fa50109bf842p2, -0x1.ffbca846c4fcap-1, -0x1.ffbca846c4fc9p-1},
+                {-0x1.1f3b3855544c9p2, 0x1.f329c0558e96ap-1, 0x1.f329c0558e96bp-1},
+                {0x1.1f3b3855544c9p2, -0x1.f329c0558e96ap-1, -0x1.f329c0558e96bp-1},
+                {-0x1.0ed16fa0e915p2, 0x1.c5f058230e802p-1, 0x1.c5f058230e803p-1},
+                {0x1.0ed16fa0e915p2, -0x1.c5f058230e802p-1, -0x1.c5f058230e803p-1},
+                {-0x1.fccf4dd8fbbaep1, 0x1.7b05b7b6c6136p-1, 0x1.7b05b7b6c6137p-1},
+                {0x1.fccf4dd8fbbaep1, -0x1.7b05b7b6c6136p-1, -0x1.7b05b7b6c6137p-1},
+                {-0x1.dbfbbc70254bcp1, 0x1.175059bf0d42fp-1, 0x1.175059bf0d43p-1},
+                {0x1.dbfbbc70254bcp1, -0x1.175059bf0d42fp-1, -0x1.175059bf0d43p-1},
+                {-0x1.bb282b074edcap1, 0x1.42abba8c72fd2p-2, 0x1.42abba8c72fd3p-2},
+                {0x1.bb282b074edcap1, -0x1.42abba8c72fd2p-2, -0x1.42abba8c72fd3p-2},
+                {-0x1.9a54999e786d8p1, 0x1.066e7eb76f62bp-4, 0x1.066e7eb76f62cp-4},
+                {0x1.9a54999e786d8p1, -0x1.066e7eb76f62bp-4, -0x1.066e7eb76f62cp-4},
+                {-0x1.79810835a1fe6p1, -0x1.877e2cd4f6fa4p-3, -0x1.877e2cd4f6fa5p-3},
+                {0x1.79810835a1fe6p1, 0x1.877e2cd4f6fa4p-3, 0x1.877e2cd4f6fa5p-3},
+                {-0x1.58ad76cccb8f4p1, -0x1.bc4c04d71aba6p-2, -0x1.bc4c04d71aba5p-2},
+                {0x1.58ad76cccb8f4p1, 0x1.bc4c04d71aba6p-2, 0x1.bc4c04d71aba5p-2},
+                {-0x1.37d9e563f5202p1, -0x1.4be4979c5efa8p-1, -0x1.4be4979c5efa9p-1},
+                {0x1.37d9e563f5202p1, 0x1.4be4979c5efa8p-1, 0x1.4be4979c5efa9p-1},
+                {-0x1.170653fb1eb1p1, -0x1.a3ed9e2529382p-1, -0x1.a3ed9e2529383p-1},
+                {0x1.170653fb1eb1p1, 0x1.a3ed9e2529382p-1, 0x1.a3ed9e2529383p-1},
+                {-0x1.ec6585249083cp0, -0x1.e07eeeda109c6p-1, -0x1.e07eeeda109c7p-1},
+                {0x1.ec6585249083cp0, 0x1.e07eeeda109c6p-1, 0x1.e07eeeda109c7p-1},
+                {-0x1.aabe6252e3a58p0, -0x1.fda254c27a01ep-1, -0x1.fda254c27a01dp-1},
+                {0x1.aabe6252e3a58p0, 0x1.fda254c27a01ep-1, 0x1.fda254c27a01dp-1},
+                {-0x1.69173f8136c74p0, -0x1.f96fe405f1acap-1, -0x1.f96fe405f1acbp-1},
+                {0x1.69173f8136c74p0, 0x1.f96fe405f1acap-1, 0x1.f96fe405f1acbp-1},
+                {-0x1.27701caf89e9p0, -0x1.d42de42dce13fp-1, -0x1.d42de42dce13ep-1},
+                {0x1.27701caf89e9p0, 0x1.d42de42dce13fp-1, 0x1.d42de42dce13ep-1},
+                {-0x1.cb91f3bbba157p-1, -0x1.904c37505de59p-1, -0x1.904c37505de5ap-1},
+                {0x1.cb91f3bbba157p-1, 0x1.904c37505de59p-1, 0x1.904c37505de5ap-1},
+                {-0x1.4843ae186058ep-1, -0x1.323b8b1fb4bb6p-1, -0x1.323b8b1fb4bb7p-1},
+                {0x1.4843ae186058ep-1, 0x1.323b8b1fb4bb6p-1, 0x1.323b8b1fb4bb7p-1},
+                {-0x1.89ead0ea0d38ap-2, -0x1.8045fe64e6309p-2, -0x1.8045fe64e6308p-2},
+                {0x1.89ead0ea0d38ap-2, 0x1.8045fe64e6309p-2, 0x1.8045fe64e6308p-2},
+                {-0x1.069c8b46b37fp-3, -0x1.05e4761ab8decp-3, -0x1.05e4761ab8dedp-3},
+                {0x1.069c8b46b37fp-3, 0x1.05e4761ab8decp-3, 0x1.05e4761ab8dedp-3},
+                {0x1.069c8b46b3734p-3, 0x1.05e4761ab8d32p-3, 0x1.05e4761ab8d31p-3},
+                {-0x1.069c8b46b3734p-3, -0x1.05e4761ab8d32p-3, -0x1.05e4761ab8d31p-3},
+                {0x1.89ead0ea0d32cp-2, 0x1.8045fe64e62b2p-2, 0x1.8045fe64e62b1p-2},
+                {-0x1.89ead0ea0d32cp-2, -0x1.8045fe64e62b2p-2, -0x1.8045fe64e62b1p-2},
+                {0x1.4843ae186055fp-1, 0x1.323b8b1fb4b9p-1, 0x1.323b8b1fb4b91p-1},
+                {-0x1.4843ae186055fp-1, -0x1.323b8b1fb4b9p-1, -0x1.323b8b1fb4b91p-1},
+                {0x1.cb91f3bbba128p-1, 0x1.904c37505de3cp-1, 0x1.904c37505de3bp-1},
+                {-0x1.cb91f3bbba128p-1, -0x1.904c37505de3cp-1, -0x1.904c37505de3bp-1},
+                {0x1.27701caf89e78p0, 0x1.d42de42dce12bp-1, 0x1.d42de42dce12cp-1},
+                {-0x1.27701caf89e78p0, -0x1.d42de42dce12bp-1, -0x1.d42de42dce12cp-1},
+                {0x1.69173f8136c5cp0, 0x1.f96fe405f1ac2p-1, 0x1.f96fe405f1ac3p-1},
+                {-0x1.69173f8136c5cp0, -0x1.f96fe405f1ac2p-1, -0x1.f96fe405f1ac3p-1},
+                {0x1.aabe6252e3a4p0, 0x1.fda254c27a022p-1, 0x1.fda254c27a023p-1},
+                {-0x1.aabe6252e3a4p0, -0x1.fda254c27a022p-1, -0x1.fda254c27a023p-1},
+                {0x1.ec65852490824p0, 0x1.e07eeeda109d7p-1, 0x1.e07eeeda109d6p-1},
+                {-0x1.ec65852490824p0, -0x1.e07eeeda109d7p-1, -0x1.e07eeeda109d6p-1},
+                {0x1.170653fb1eb04p1, 0x1.a3ed9e252939ep-1, 0x1.a3ed9e252939dp-1},
+                {-0x1.170653fb1eb04p1, -0x1.a3ed9e252939ep-1, -0x1.a3ed9e252939dp-1},
+                {0x1.37d9e563f51f6p1, 0x1.4be4979c5efcdp-1, 0x1.4be4979c5efccp-1},
+                {-0x1.37d9e563f51f6p1, -0x1.4be4979c5efcdp-1, -0x1.4be4979c5efccp-1},
+                {0x1.58ad76cccb8e8p1, 0x1.bc4c04d71abfcp-2, 0x1.bc4c04d71abfdp-2},
+                {-0x1.58ad76cccb8e8p1, -0x1.bc4c04d71abfcp-2, -0x1.bc4c04d71abfdp-2},
+                {0x1.79810835a1fdap1, 0x1.877e2cd4f7061p-3, 0x1.877e2cd4f706p-3},
+                {-0x1.79810835a1fdap1, -0x1.877e2cd4f7061p-3, -0x1.877e2cd4f706p-3},
+                {0x1.9a54999e786ccp1, -0x1.066e7eb76f4acp-4, -0x1.066e7eb76f4adp-4},
+                {-0x1.9a54999e786ccp1, 0x1.066e7eb76f4acp-4, 0x1.066e7eb76f4adp-4},
+                {0x1.bb282b074edbep1, -0x1.42abba8c72f77p-2, -0x1.42abba8c72f78p-2},
+                {-0x1.bb282b074edbep1, 0x1.42abba8c72f77p-2, 0x1.42abba8c72f78p-2},
+                {0x1.dbfbbc70254bp1, -0x1.175059bf0d407p-1, -0x1.175059bf0d406p-1},
+                {-0x1.dbfbbc70254bp1, 0x1.175059bf0d407p-1, 0x1.175059bf0d406p-1},
+                {0x1.fccf4dd8fbba2p1, -0x1.7b05b7b6c6116p-1, -0x1.7b05b7b6c6117p-1},
+                {-0x1.fccf4dd8fbba2p1, 0x1.7b05b7b6c6116p-1, 0x1.7b05b7b6c6117p-1},
+                {0x1.0ed16fa0e914ap2, -0x1.c5f058230e7ecp-1, -0x1.c5f058230e7ebp-1},
+                {-0x1.0ed16fa0e914ap2, 0x1.c5f058230e7ecp-1, 0x1.c5f058230e7ebp-1},
+                {0x1.1f3b3855544c3p2, -0x1.f329c0558e96p-1, -0x1.f329c0558e95fp-1},
+                {-0x1.1f3b3855544c3p2, 0x1.f329c0558e96p-1, 0x1.f329c0558e95fp-1},
+                {0x1.2fa50109bf83cp2, -0x1.ffbca846c4fcbp-1, -0x1.ffbca846c4fccp-1},
+                {-0x1.2fa50109bf83cp2, 0x1.ffbca846c4fcbp-1, 0x1.ffbca846c4fccp-1},
+                {0x1.400ec9be2abb5p2, -0x1.ead6834909ba1p-1, -0x1.ead6834909bap-1},
+                {-0x1.400ec9be2abb5p2, 0x1.ead6834909ba1p-1, 0x1.ead6834909bap-1},
+                {0x1.5078927295f2ep2, -0x1.b5d545b109c12p-1, -0x1.b5d545b109c13p-1},
+                {-0x1.5078927295f2ep2, 0x1.b5d545b109c12p-1, 0x1.b5d545b109c13p-1},
+                {0x1.60e25b27012a7p2, -0x1.643080d67ace4p-1, -0x1.643080d67ace5p-1},
+                {-0x1.60e25b27012a7p2, 0x1.643080d67ace4p-1, 0x1.643080d67ace5p-1},
+                {0x1.714c23db6c62p2, -0x1.f67ea975b86f6p-2, -0x1.f67ea975b86f5p-2},
+                {-0x1.714c23db6c62p2, 0x1.f67ea975b86f6p-2, 0x1.f67ea975b86f5p-2},
+                {0x1.81b5ec8fd7999p2, -0x1.03be06f97cc4dp-2, -0x1.03be06f97cc4ep-2},
+                {-0x1.81b5ec8fd7999p2, 0x1.03be06f97cc4dp-2, 0x1.03be06f97cc4ep-2},
+                {0x1.effffffffffffp-5, 0x1.efb26ef930c4cp-5, 0x1.efb26ef930c4dp-5},
+                {-0x1.effffffffffffp-5, -0x1.efb26ef930c4cp-5, -0x1.efb26ef930c4dp-5},
+                {0x1.fp-5, 0x1.efb26ef930c4dp-5, 0x1.efb26ef930c4ep-5},
+                {-0x1.fp-5, -0x1.efb26ef930c4dp-5, -0x1.efb26ef930c4ep-5},
+                {0x1.f000000000001p-5, 0x1.efb26ef930c4ep-5, 0x1.efb26ef930c4fp-5},
+                {-0x1.f000000000001p-5, -0x1.efb26ef930c4ep-5, -0x1.efb26ef930c4fp-5},
+                {0x1.f7fffffffffffp-4, 0x1.f6baaa131de63p-4, 0x1.f6baaa131de64p-4},
+                {-0x1.f7fffffffffffp-4, -0x1.f6baaa131de63p-4, -0x1.f6baaa131de64p-4},
+                {0x1.f8p-4, 0x1.f6baaa131de64p-4, 0x1.f6baaa131de65p-4},
+                {-0x1.f8p-4, -0x1.f6baaa131de64p-4, -0x1.f6baaa131de65p-4},
+                {0x1.f800000000001p-4, 0x1.f6baaa131de65p-4, 0x1.f6baaa131de66p-4},
+                {-0x1.f800000000001p-4, -0x1.f6baaa131de65p-4, -0x1.f6baaa131de66p-4},
+                {0x1.4bfffffffffffp-3, 0x1.4a8c3b4e9c7ffp-3, 0x1.4a8c3b4e9c8p-3},
+                {-0x1.4bfffffffffffp-3, -0x1.4a8c3b4e9c7ffp-3, -0x1.4a8c3b4e9c8p-3},
+                {0x1.4cp-3, 0x1.4a8c3b4e9c8p-3, 0x1.4a8c3b4e9c7ffp-3},
+                {-0x1.4cp-3, -0x1.4a8c3b4e9c8p-3, -0x1.4a8c3b4e9c7ffp-3},
+                {0x1.4c00000000001p-3, 0x1.4a8c3b4e9c801p-3, 0x1.4a8c3b4e9c8p-3},
+                {-0x1.4c00000000001p-3, -0x1.4a8c3b4e9c801p-3, -0x1.4a8c3b4e9c8p-3},
+                {0x1.3333333333332p-2, 0x1.2e9cd95baba32p-2, 0x1.2e9cd95baba33p-2},
+                {-0x1.3333333333332p-2, -0x1.2e9cd95baba32p-2, -0x1.2e9cd95baba33p-2},
+                {0x1.3333333333333p-2, 0x1.2e9cd95baba33p-2, 0x1.2e9cd95baba34p-2},
+                {-0x1.3333333333333p-2, -0x1.2e9cd95baba33p-2, -0x1.2e9cd95baba34p-2},
+                {0x1.3333333333334p-2, 0x1.2e9cd95baba34p-2, 0x1.2e9cd95baba35p-2},
+                {-0x1.3333333333334p-2, -0x1.2e9cd95baba34p-2, -0x1.2e9cd95baba35p-2},
+                {0x1.594317acc4ef8p-1, 0x1.3faefc7a5466fp-1, 0x1.3faefc7a5466ep-1},
+                {-0x1.594317acc4ef8p-1, -0x1.3faefc7a5466fp-1, -0x1.3faefc7a5466ep-1},
+                {0x1.594317acc4ef9p-1, 0x1.3faefc7a5467p-1, 0x1.3faefc7a5466fp-1},
+                {-0x1.594317acc4ef9p-1, -0x1.3faefc7a5467p-1, -0x1.3faefc7a5466fp-1},
+                {0x1.594317acc4efap-1, 0x1.3faefc7a5467p-1, 0x1.3faefc7a54671p-1},
+                {-0x1.594317acc4efap-1, -0x1.3faefc7a5467p-1, -0x1.3faefc7a54671p-1},
+                {0x1.8ffffffffffffp-1, 0x1.6888a4e134b2ep-1, 0x1.6888a4e134b2dp-1},
+                {-0x1.8ffffffffffffp-1, -0x1.6888a4e134b2ep-1, -0x1.6888a4e134b2dp-1},
+                {0x1.9p-1, 0x1.6888a4e134b2fp-1, 0x1.6888a4e134b2ep-1},
+                {-0x1.9p-1, -0x1.6888a4e134b2fp-1, -0x1.6888a4e134b2ep-1},
+                {0x1.9000000000001p-1, 0x1.6888a4e134b2fp-1, 0x1.6888a4e134b3p-1},
+                {-0x1.9000000000001p-1, -0x1.6888a4e134b2fp-1, -0x1.6888a4e134b3p-1},
+                {-0x0.0000000000001p-1022, -0x0.0000000000001p-1022, -0x0.0p0},
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0p0},
+                {-0x0.0p0, -0x0.0p0, -0x0.0p0},
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0p0},
+                {-0x0.0000000000001p-1022, -0x0.0000000000001p-1022, -0x0.0p0},
+                {0x1.921fb54442d17p-5, 0x1.91f65f10dd813p-5, 0x1.91f65f10dd812p-5},
+                {-0x1.921fb54442d17p-5, -0x1.91f65f10dd813p-5, -0x1.91f65f10dd812p-5},
+                {0x1.921fb54442d18p-5, 0x1.91f65f10dd814p-5, 0x1.91f65f10dd813p-5},
+                {-0x1.921fb54442d18p-5, -0x1.91f65f10dd814p-5, -0x1.91f65f10dd813p-5},
+                {0x1.921fb54442d19p-5, 0x1.91f65f10dd815p-5, 0x1.91f65f10dd814p-5},
+                {-0x1.921fb54442d19p-5, -0x1.91f65f10dd815p-5, -0x1.91f65f10dd814p-5},
+                {0x1.921fb54442d17p-4, 0x1.917a6bc29b42bp-4, 0x1.917a6bc29b42ap-4},
+                {-0x1.921fb54442d17p-4, -0x1.917a6bc29b42bp-4, -0x1.917a6bc29b42ap-4},
+                {0x1.921fb54442d18p-4, 0x1.917a6bc29b42cp-4, 0x1.917a6bc29b42bp-4},
+                {-0x1.921fb54442d18p-4, -0x1.917a6bc29b42cp-4, -0x1.917a6bc29b42bp-4},
+                {0x1.921fb54442d19p-4, 0x1.917a6bc29b42dp-4, 0x1.917a6bc29b42cp-4},
+                {-0x1.921fb54442d19p-4, -0x1.917a6bc29b42dp-4, -0x1.917a6bc29b42cp-4},
+                {0x1.921fb54442d17p-3, 0x1.8f8b83c69a609p-3, 0x1.8f8b83c69a60ap-3},
+                {-0x1.921fb54442d17p-3, -0x1.8f8b83c69a609p-3, -0x1.8f8b83c69a60ap-3},
+                {0x1.921fb54442d18p-3, 0x1.8f8b83c69a60ap-3, 0x1.8f8b83c69a60bp-3},
+                {-0x1.921fb54442d18p-3, -0x1.8f8b83c69a60ap-3, -0x1.8f8b83c69a60bp-3},
+                {0x1.921fb54442d19p-3, 0x1.8f8b83c69a60bp-3, 0x1.8f8b83c69a60cp-3},
+                {-0x1.921fb54442d19p-3, -0x1.8f8b83c69a60bp-3, -0x1.8f8b83c69a60cp-3},
+                {0x1.921fb54442d17p-2, 0x1.87de2a6aea962p-2, 0x1.87de2a6aea961p-2},
+                {-0x1.921fb54442d17p-2, -0x1.87de2a6aea962p-2, -0x1.87de2a6aea961p-2},
+                {0x1.921fb54442d18p-2, 0x1.87de2a6aea963p-2, 0x1.87de2a6aea962p-2},
+                {-0x1.921fb54442d18p-2, -0x1.87de2a6aea963p-2, -0x1.87de2a6aea962p-2},
+                {0x1.921fb54442d19p-2, 0x1.87de2a6aea964p-2, 0x1.87de2a6aea963p-2},
+                {-0x1.921fb54442d19p-2, -0x1.87de2a6aea964p-2, -0x1.87de2a6aea963p-2},
+                {0x1.921fb54442d17p-1, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcbp-1},
+                {-0x1.921fb54442d17p-1, -0x1.6a09e667f3bccp-1, -0x1.6a09e667f3bcbp-1},
+                {0x1.921fb54442d18p-1, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcdp-1},
+                {-0x1.921fb54442d18p-1, -0x1.6a09e667f3bccp-1, -0x1.6a09e667f3bcdp-1},
+                {0x1.921fb54442d19p-1, 0x1.6a09e667f3bcdp-1, 0x1.6a09e667f3bcep-1},
+                {-0x1.921fb54442d19p-1, -0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bcep-1},
+                {0x1.921fb54442d17p0, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p0, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p0, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p0, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p0, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p0, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.921fb54442d17p1, 0x1.469898cc51702p-51, 0x1.469898cc51701p-51},
+                {-0x1.921fb54442d17p1, -0x1.469898cc51702p-51, -0x1.469898cc51701p-51},
+                {0x1.921fb54442d18p1, 0x1.1a62633145c07p-53, 0x1.1a62633145c06p-53},
+                {-0x1.921fb54442d18p1, -0x1.1a62633145c07p-53, -0x1.1a62633145c06p-53},
+                {0x1.921fb54442d19p1, -0x1.72cece675d1fdp-52, -0x1.72cece675d1fcp-52},
+                {-0x1.921fb54442d19p1, 0x1.72cece675d1fdp-52, 0x1.72cece675d1fcp-52},
+                {0x1.921fb54442d17p2, -0x1.469898cc51702p-50, -0x1.469898cc51701p-50},
+                {-0x1.921fb54442d17p2, 0x1.469898cc51702p-50, 0x1.469898cc51701p-50},
+                {0x1.921fb54442d18p2, -0x1.1a62633145c07p-52, -0x1.1a62633145c06p-52},
+                {-0x1.921fb54442d18p2, 0x1.1a62633145c07p-52, 0x1.1a62633145c06p-52},
+                {0x1.921fb54442d19p2, 0x1.72cece675d1fdp-51, 0x1.72cece675d1fcp-51},
+                {-0x1.921fb54442d19p2, -0x1.72cece675d1fdp-51, -0x1.72cece675d1fcp-51},
+                {0x1.921fb54442d17p3, -0x1.469898cc51702p-49, -0x1.469898cc51701p-49},
+                {-0x1.921fb54442d17p3, 0x1.469898cc51702p-49, 0x1.469898cc51701p-49},
+                {0x1.921fb54442d18p3, -0x1.1a62633145c07p-51, -0x1.1a62633145c06p-51},
+                {-0x1.921fb54442d18p3, 0x1.1a62633145c07p-51, 0x1.1a62633145c06p-51},
+                {0x1.921fb54442d19p3, 0x1.72cece675d1fdp-50, 0x1.72cece675d1fcp-50},
+                {-0x1.921fb54442d19p3, -0x1.72cece675d1fdp-50, -0x1.72cece675d1fcp-50},
+                {0x1.921fb54442d17p4, -0x1.469898cc51702p-48, -0x1.469898cc51701p-48},
+                {-0x1.921fb54442d17p4, 0x1.469898cc51702p-48, 0x1.469898cc51701p-48},
+                {0x1.921fb54442d18p4, -0x1.1a62633145c07p-50, -0x1.1a62633145c06p-50},
+                {-0x1.921fb54442d18p4, 0x1.1a62633145c07p-50, 0x1.1a62633145c06p-50},
+                {0x1.921fb54442d19p4, 0x1.72cece675d1fdp-49, 0x1.72cece675d1fcp-49},
+                {-0x1.921fb54442d19p4, -0x1.72cece675d1fdp-49, -0x1.72cece675d1fcp-49},
+                {0x1.921fb54442d17p5, -0x1.469898cc51702p-47, -0x1.469898cc51701p-47},
+                {-0x1.921fb54442d17p5, 0x1.469898cc51702p-47, 0x1.469898cc51701p-47},
+                {0x1.921fb54442d18p5, -0x1.1a62633145c07p-49, -0x1.1a62633145c06p-49},
+                {-0x1.921fb54442d18p5, 0x1.1a62633145c07p-49, 0x1.1a62633145c06p-49},
+                {0x1.921fb54442d19p5, 0x1.72cece675d1fdp-48, 0x1.72cece675d1fcp-48},
+                {-0x1.921fb54442d19p5, -0x1.72cece675d1fdp-48, -0x1.72cece675d1fcp-48},
+                {0x1.921fb54442d17p6, -0x1.469898cc51702p-46, -0x1.469898cc51701p-46},
+                {-0x1.921fb54442d17p6, 0x1.469898cc51702p-46, 0x1.469898cc51701p-46},
+                {0x1.921fb54442d18p6, -0x1.1a62633145c07p-48, -0x1.1a62633145c06p-48},
+                {-0x1.921fb54442d18p6, 0x1.1a62633145c07p-48, 0x1.1a62633145c06p-48},
+                {0x1.921fb54442d19p6, 0x1.72cece675d1fdp-47, 0x1.72cece675d1fcp-47},
+                {-0x1.921fb54442d19p6, -0x1.72cece675d1fdp-47, -0x1.72cece675d1fcp-47},
+                {0x1.921fb54442d17p7, -0x1.469898cc51702p-45, -0x1.469898cc51701p-45},
+                {-0x1.921fb54442d17p7, 0x1.469898cc51702p-45, 0x1.469898cc51701p-45},
+                {0x1.921fb54442d18p7, -0x1.1a62633145c07p-47, -0x1.1a62633145c06p-47},
+                {-0x1.921fb54442d18p7, 0x1.1a62633145c07p-47, 0x1.1a62633145c06p-47},
+                {0x1.921fb54442d19p7, 0x1.72cece675d1fdp-46, 0x1.72cece675d1fcp-46},
+                {-0x1.921fb54442d19p7, -0x1.72cece675d1fdp-46, -0x1.72cece675d1fcp-46},
+                {0x1.2d97c7f3321d1p1, 0x1.6a09e667f3bdp-1, 0x1.6a09e667f3bcfp-1},
+                {-0x1.2d97c7f3321d1p1, -0x1.6a09e667f3bdp-1, -0x1.6a09e667f3bcfp-1},
+                {0x1.2d97c7f3321d2p1, 0x1.6a09e667f3bcdp-1, 0x1.6a09e667f3bcep-1},
+                {-0x1.2d97c7f3321d2p1, -0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bcep-1},
+                {0x1.2d97c7f3321d3p1, 0x1.6a09e667f3bcap-1, 0x1.6a09e667f3bcbp-1},
+                {-0x1.2d97c7f3321d3p1, -0x1.6a09e667f3bcap-1, -0x1.6a09e667f3bcbp-1},
+                {0x1.f6a7a2955385dp1, -0x1.6a09e667f3bc9p-1, -0x1.6a09e667f3bc8p-1},
+                {-0x1.f6a7a2955385dp1, 0x1.6a09e667f3bc9p-1, 0x1.6a09e667f3bc8p-1},
+                {0x1.f6a7a2955385ep1, -0x1.6a09e667f3bccp-1, -0x1.6a09e667f3bcbp-1},
+                {-0x1.f6a7a2955385ep1, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcbp-1},
+                {0x1.f6a7a2955385fp1, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcfp-1},
+                {-0x1.f6a7a2955385fp1, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcfp-1},
+                {0x1.2d97c7f3321d1p2, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d1p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.2d97c7f3321d2p2, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d2p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.2d97c7f3321d3p2, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d3p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.5fdbbe9bba774p2, -0x1.6a09e667f3bd4p-1, -0x1.6a09e667f3bd3p-1},
+                {-0x1.5fdbbe9bba774p2, 0x1.6a09e667f3bd4p-1, 0x1.6a09e667f3bd3p-1},
+                {0x1.5fdbbe9bba775p2, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcdp-1},
+                {-0x1.5fdbbe9bba775p2, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcdp-1},
+                {0x1.5fdbbe9bba776p2, -0x1.6a09e667f3bc8p-1, -0x1.6a09e667f3bc9p-1},
+                {-0x1.5fdbbe9bba776p2, 0x1.6a09e667f3bc8p-1, 0x1.6a09e667f3bc9p-1},
+                {0x1.c463abeccb2bap2, 0x1.6a09e667f3bc5p-1, 0x1.6a09e667f3bc6p-1},
+                {-0x1.c463abeccb2bap2, -0x1.6a09e667f3bc5p-1, -0x1.6a09e667f3bc6p-1},
+                {0x1.c463abeccb2bbp2, 0x1.6a09e667f3bcbp-1, 0x1.6a09e667f3bcap-1},
+                {-0x1.c463abeccb2bbp2, -0x1.6a09e667f3bcbp-1, -0x1.6a09e667f3bcap-1},
+                {0x1.c463abeccb2bcp2, 0x1.6a09e667f3bd1p-1, 0x1.6a09e667f3bdp-1},
+                {-0x1.c463abeccb2bcp2, -0x1.6a09e667f3bd1p-1, -0x1.6a09e667f3bdp-1},
+                {0x1.f6a7a2955385dp2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.f6a7a2955385dp2, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.f6a7a2955385ep2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.f6a7a2955385ep2, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.f6a7a2955385fp2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.f6a7a2955385fp2, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.1475cc9eedeffp3, 0x1.6a09e667f3bdfp-1, 0x1.6a09e667f3bep-1},
+                {-0x1.1475cc9eedeffp3, -0x1.6a09e667f3bdfp-1, -0x1.6a09e667f3bep-1},
+                {0x1.1475cc9eedfp3, 0x1.6a09e667f3bd4p-1, 0x1.6a09e667f3bd5p-1},
+                {-0x1.1475cc9eedfp3, -0x1.6a09e667f3bd4p-1, -0x1.6a09e667f3bd5p-1},
+                {0x1.1475cc9eedf01p3, 0x1.6a09e667f3bc9p-1, 0x1.6a09e667f3bcap-1},
+                {-0x1.1475cc9eedf01p3, -0x1.6a09e667f3bc9p-1, -0x1.6a09e667f3bcap-1},
+                {0x1.2d97c7f3321d1p3, 0x1.34f272993d141p-49, 0x1.34f272993d142p-49},
+                {-0x1.2d97c7f3321d1p3, -0x1.34f272993d141p-49, -0x1.34f272993d142p-49},
+                {0x1.2d97c7f3321d2p3, 0x1.a79394c9e8a0ap-52, 0x1.a79394c9e8a0bp-52},
+                {-0x1.2d97c7f3321d2p3, -0x1.a79394c9e8a0ap-52, -0x1.a79394c9e8a0bp-52},
+                {0x1.2d97c7f3321d3p3, -0x1.961b1acd85d7dp-50, -0x1.961b1acd85d7ep-50},
+                {-0x1.2d97c7f3321d3p3, 0x1.961b1acd85d7dp-50, 0x1.961b1acd85d7ep-50},
+                {0x1.46b9c347764a2p3, -0x1.6a09e667f3bb9p-1, -0x1.6a09e667f3bbap-1},
+                {-0x1.46b9c347764a2p3, 0x1.6a09e667f3bb9p-1, 0x1.6a09e667f3bbap-1},
+                {0x1.46b9c347764a3p3, -0x1.6a09e667f3bc4p-1, -0x1.6a09e667f3bc5p-1},
+                {-0x1.46b9c347764a3p3, 0x1.6a09e667f3bc4p-1, 0x1.6a09e667f3bc5p-1},
+                {0x1.46b9c347764a4p3, -0x1.6a09e667f3bdp-1, -0x1.6a09e667f3bcfp-1},
+                {-0x1.46b9c347764a4p3, 0x1.6a09e667f3bdp-1, 0x1.6a09e667f3bcfp-1},
+                {0x1.5fdbbe9bba774p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.5fdbbe9bba774p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.5fdbbe9bba775p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.5fdbbe9bba775p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.5fdbbe9bba776p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.5fdbbe9bba776p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.78fdb9effea45p3, -0x1.6a09e667f3bep-1, -0x1.6a09e667f3be1p-1},
+                {-0x1.78fdb9effea45p3, 0x1.6a09e667f3bep-1, 0x1.6a09e667f3be1p-1},
+                {0x1.78fdb9effea46p3, -0x1.6a09e667f3bd5p-1, -0x1.6a09e667f3bd6p-1},
+                {-0x1.78fdb9effea46p3, 0x1.6a09e667f3bd5p-1, 0x1.6a09e667f3bd6p-1},
+                {0x1.78fdb9effea47p3, -0x1.6a09e667f3bcap-1, -0x1.6a09e667f3bc9p-1},
+                {-0x1.78fdb9effea47p3, 0x1.6a09e667f3bcap-1, 0x1.6a09e667f3bc9p-1},
+                {0x1.ab41b09886fe8p3, 0x1.6a09e667f3bb8p-1, 0x1.6a09e667f3bb9p-1},
+                {-0x1.ab41b09886fe8p3, -0x1.6a09e667f3bb8p-1, -0x1.6a09e667f3bb9p-1},
+                {0x1.ab41b09886fe9p3, 0x1.6a09e667f3bc4p-1, 0x1.6a09e667f3bc3p-1},
+                {-0x1.ab41b09886fe9p3, -0x1.6a09e667f3bc4p-1, -0x1.6a09e667f3bc3p-1},
+                {0x1.ab41b09886feap3, 0x1.6a09e667f3bcfp-1, 0x1.6a09e667f3bcep-1},
+                {-0x1.ab41b09886feap3, -0x1.6a09e667f3bcfp-1, -0x1.6a09e667f3bcep-1},
+                {0x1.c463abeccb2bap3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.c463abeccb2bap3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.c463abeccb2bbp3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.c463abeccb2bbp3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.c463abeccb2bcp3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.c463abeccb2bcp3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.dd85a7410f58bp3, 0x1.6a09e667f3be1p-1, 0x1.6a09e667f3be2p-1},
+                {-0x1.dd85a7410f58bp3, -0x1.6a09e667f3be1p-1, -0x1.6a09e667f3be2p-1},
+                {0x1.dd85a7410f58cp3, 0x1.6a09e667f3bd6p-1, 0x1.6a09e667f3bd5p-1},
+                {-0x1.dd85a7410f58cp3, -0x1.6a09e667f3bd6p-1, -0x1.6a09e667f3bd5p-1},
+                {0x1.dd85a7410f58dp3, 0x1.6a09e667f3bcbp-1, 0x1.6a09e667f3bcap-1},
+                {-0x1.dd85a7410f58dp3, -0x1.6a09e667f3bcbp-1, -0x1.6a09e667f3bcap-1},
+                {0x1.f6a7a2955385dp3, 0x1.583ebeff65cc2p-49, 0x1.583ebeff65cc3p-49},
+                {-0x1.f6a7a2955385dp3, -0x1.583ebeff65cc2p-49, -0x1.583ebeff65cc3p-49},
+                {0x1.f6a7a2955385ep3, 0x1.60fafbfd97309p-51, 0x1.60fafbfd97308p-51},
+                {-0x1.f6a7a2955385ep3, -0x1.60fafbfd97309p-51, -0x1.60fafbfd97308p-51},
+                {0x1.f6a7a2955385fp3, -0x1.4f8282013467cp-50, -0x1.4f8282013467bp-50},
+                {-0x1.f6a7a2955385fp3, 0x1.4f8282013467cp-50, 0x1.4f8282013467bp-50},
+                {0x1.07e4cef4cbd96p4, -0x1.6a09e667f3ba1p-1, -0x1.6a09e667f3bap-1},
+                {-0x1.07e4cef4cbd96p4, 0x1.6a09e667f3ba1p-1, 0x1.6a09e667f3bap-1},
+                {0x1.07e4cef4cbd97p4, -0x1.6a09e667f3bb8p-1, -0x1.6a09e667f3bb7p-1},
+                {-0x1.07e4cef4cbd97p4, 0x1.6a09e667f3bb8p-1, 0x1.6a09e667f3bb7p-1},
+                {0x1.07e4cef4cbd98p4, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcfp-1},
+                {-0x1.07e4cef4cbd98p4, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcfp-1},
+                {0x1.1475cc9eedeffp4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.1475cc9eedeffp4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.1475cc9eedfp4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.1475cc9eedfp4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.1475cc9eedf01p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.1475cc9eedf01p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.2106ca4910068p4, -0x1.6a09e667f3bedp-1, -0x1.6a09e667f3beep-1},
+                {-0x1.2106ca4910068p4, 0x1.6a09e667f3bedp-1, 0x1.6a09e667f3beep-1},
+                {0x1.2106ca4910069p4, -0x1.6a09e667f3bd7p-1, -0x1.6a09e667f3bd6p-1},
+                {-0x1.2106ca4910069p4, 0x1.6a09e667f3bd7p-1, 0x1.6a09e667f3bd6p-1},
+                {0x1.2106ca491006ap4, -0x1.6a09e667f3bcp-1, -0x1.6a09e667f3bc1p-1},
+                {-0x1.2106ca491006ap4, 0x1.6a09e667f3bcp-1, 0x1.6a09e667f3bc1p-1},
+                {0x1.2d97c7f3321d1p4, -0x1.34f272993d141p-48, -0x1.34f272993d142p-48},
+                {-0x1.2d97c7f3321d1p4, 0x1.34f272993d141p-48, 0x1.34f272993d142p-48},
+                {0x1.2d97c7f3321d2p4, -0x1.a79394c9e8a0ap-51, -0x1.a79394c9e8a0bp-51},
+                {-0x1.2d97c7f3321d2p4, 0x1.a79394c9e8a0ap-51, 0x1.a79394c9e8a0bp-51},
+                {0x1.2d97c7f3321d3p4, 0x1.961b1acd85d7dp-49, 0x1.961b1acd85d7ep-49},
+                {-0x1.2d97c7f3321d3p4, -0x1.961b1acd85d7dp-49, -0x1.961b1acd85d7ep-49},
+                {0x1.3a28c59d54339p4, 0x1.6a09e667f3bap-1, 0x1.6a09e667f3ba1p-1},
+                {-0x1.3a28c59d54339p4, -0x1.6a09e667f3bap-1, -0x1.6a09e667f3ba1p-1},
+                {0x1.3a28c59d5433ap4, 0x1.6a09e667f3bb7p-1, 0x1.6a09e667f3bb6p-1},
+                {-0x1.3a28c59d5433ap4, -0x1.6a09e667f3bb7p-1, -0x1.6a09e667f3bb6p-1},
+                {0x1.3a28c59d5433bp4, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcdp-1},
+                {-0x1.3a28c59d5433bp4, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcdp-1},
+                {0x1.46b9c347764a2p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.46b9c347764a2p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.46b9c347764a3p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.46b9c347764a3p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.46b9c347764a4p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.46b9c347764a4p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.534ac0f19860bp4, 0x1.6a09e667f3beep-1, 0x1.6a09e667f3befp-1},
+                {-0x1.534ac0f19860bp4, -0x1.6a09e667f3beep-1, -0x1.6a09e667f3befp-1},
+                {0x1.534ac0f19860cp4, 0x1.6a09e667f3bd8p-1, 0x1.6a09e667f3bd7p-1},
+                {-0x1.534ac0f19860cp4, -0x1.6a09e667f3bd8p-1, -0x1.6a09e667f3bd7p-1},
+                {0x1.534ac0f19860dp4, 0x1.6a09e667f3bc1p-1, 0x1.6a09e667f3bcp-1},
+                {-0x1.534ac0f19860dp4, -0x1.6a09e667f3bc1p-1, -0x1.6a09e667f3bcp-1},
+                {0x1.5fdbbe9bba774p4, 0x1.3dc585b2c7422p-48, 0x1.3dc585b2c7421p-48},
+                {-0x1.5fdbbe9bba774p4, -0x1.3dc585b2c7422p-48, -0x1.3dc585b2c7421p-48},
+                {0x1.5fdbbe9bba775p4, 0x1.ee2c2d963a10cp-51, 0x1.ee2c2d963a10dp-51},
+                {-0x1.5fdbbe9bba775p4, -0x1.ee2c2d963a10cp-51, -0x1.ee2c2d963a10dp-51},
+                {0x1.5fdbbe9bba776p4, -0x1.8474f49a717bdp-49, -0x1.8474f49a717bcp-49},
+                {-0x1.5fdbbe9bba776p4, 0x1.8474f49a717bdp-49, 0x1.8474f49a717bcp-49},
+                {0x1.6c6cbc45dc8dcp4, -0x1.6a09e667f3b9fp-1, -0x1.6a09e667f3bap-1},
+                {-0x1.6c6cbc45dc8dcp4, 0x1.6a09e667f3b9fp-1, 0x1.6a09e667f3bap-1},
+                {0x1.6c6cbc45dc8ddp4, -0x1.6a09e667f3bb6p-1, -0x1.6a09e667f3bb5p-1},
+                {-0x1.6c6cbc45dc8ddp4, 0x1.6a09e667f3bb6p-1, 0x1.6a09e667f3bb5p-1},
+                {0x1.6c6cbc45dc8dep4, -0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bccp-1},
+                {-0x1.6c6cbc45dc8dep4, 0x1.6a09e667f3bcdp-1, 0x1.6a09e667f3bccp-1},
+                {0x1.78fdb9effea45p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.78fdb9effea45p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.78fdb9effea46p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.78fdb9effea46p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.78fdb9effea47p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.78fdb9effea47p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.858eb79a20baep4, -0x1.6a09e667f3befp-1, -0x1.6a09e667f3beep-1},
+                {-0x1.858eb79a20baep4, 0x1.6a09e667f3befp-1, 0x1.6a09e667f3beep-1},
+                {0x1.858eb79a20bafp4, -0x1.6a09e667f3bd8p-1, -0x1.6a09e667f3bd9p-1},
+                {-0x1.858eb79a20bafp4, 0x1.6a09e667f3bd8p-1, 0x1.6a09e667f3bd9p-1},
+                {0x1.858eb79a20bbp4, -0x1.6a09e667f3bc2p-1, -0x1.6a09e667f3bc1p-1},
+                {-0x1.858eb79a20bbp4, 0x1.6a09e667f3bc2p-1, 0x1.6a09e667f3bc1p-1},
+                {0x1.fffffffffffffp62, 0x1.fa7299b17573dp-1, 0x1.fa7299b17573ep-1},
+                {-0x1.fffffffffffffp62, -0x1.fa7299b17573dp-1, -0x1.fa7299b17573ep-1},
+                {0x1.0p63, 0x1.fff6dfd42dc54p-1, 0x1.fff6dfd42dc55p-1},
+                {-0x1.0p63, -0x1.fff6dfd42dc54p-1, -0x1.fff6dfd42dc55p-1},
+                {0x1.0000000000001p63, 0x1.e456b818e7397p-1, 0x1.e456b818e7396p-1},
+                {-0x1.0000000000001p63, -0x1.e456b818e7397p-1, -0x1.e456b818e7396p-1},
+                {0x1.fffffffffffffp26, -0x1.86dcca0d689e8p-1, -0x1.86dcca0d689e7p-1},
+                {-0x1.fffffffffffffp26, 0x1.86dcca0d689e8p-1, 0x1.86dcca0d689e7p-1},
+                {0x1.0p27, -0x1.86dcc9babb0a4p-1, -0x1.86dcc9babb0a5p-1},
+                {-0x1.0p27, 0x1.86dcc9babb0a4p-1, 0x1.86dcc9babb0a5p-1},
+                {0x1.0000000000001p27, -0x1.86dcc9155fe18p-1, -0x1.86dcc9155fe19p-1},
+                {-0x1.0000000000001p27, 0x1.86dcc9155fe18p-1, 0x1.86dcc9155fe19p-1},
+                {0x1.fffffffffffffp23, -0x1.8f22f84d42da2p-1, -0x1.8f22f84d42da1p-1},
+                {-0x1.fffffffffffffp23, 0x1.8f22f84d42da2p-1, 0x1.8f22f84d42da1p-1},
+                {0x1.0p24, -0x1.8f22f8433d6eep-1, -0x1.8f22f8433d6edp-1},
+                {-0x1.0p24, 0x1.8f22f8433d6eep-1, 0x1.8f22f8433d6edp-1},
+                {0x1.0000000000001p24, -0x1.8f22f82f32986p-1, -0x1.8f22f82f32985p-1},
+                {-0x1.0000000000001p24, 0x1.8f22f82f32986p-1, 0x1.8f22f82f32985p-1},
+                {0x1.fffffffffffffp1, -0x1.837b9dddc1eacp-1, -0x1.837b9dddc1eabp-1},
+                {-0x1.fffffffffffffp1, 0x1.837b9dddc1eacp-1, 0x1.837b9dddc1eabp-1},
+                {0x1.0p2, -0x1.837b9dddc1eaep-1, -0x1.837b9dddc1eafp-1},
+                {-0x1.0p2, 0x1.837b9dddc1eaep-1, 0x1.837b9dddc1eafp-1},
+                {0x1.0000000000001p2, -0x1.837b9dddc1eb4p-1, -0x1.837b9dddc1eb3p-1},
+                {-0x1.0000000000001p2, 0x1.837b9dddc1eb4p-1, 0x1.837b9dddc1eb3p-1},
+                {0x1.fffffffffffffp0, 0x1.d18f6ead1b447p-1, 0x1.d18f6ead1b446p-1},
+                {-0x1.fffffffffffffp0, -0x1.d18f6ead1b447p-1, -0x1.d18f6ead1b446p-1},
+                {0x1.0p1, 0x1.d18f6ead1b446p-1, 0x1.d18f6ead1b445p-1},
+                {-0x1.0p1, -0x1.d18f6ead1b446p-1, -0x1.d18f6ead1b445p-1},
+                {0x1.0000000000001p1, 0x1.d18f6ead1b444p-1, 0x1.d18f6ead1b445p-1},
+                {-0x1.0000000000001p1, -0x1.d18f6ead1b444p-1, -0x1.d18f6ead1b445p-1},
+                {0x1.fffffffffffffp-1, 0x1.aed548f090cedp-1, 0x1.aed548f090ceep-1},
+                {-0x1.fffffffffffffp-1, -0x1.aed548f090cedp-1, -0x1.aed548f090ceep-1},
+                {0x1.0p0, 0x1.aed548f090ceep-1, 0x1.aed548f090cefp-1},
+                {-0x1.0p0, -0x1.aed548f090ceep-1, -0x1.aed548f090cefp-1},
+                {0x1.0000000000001p0, 0x1.aed548f090cefp-1, 0x1.aed548f090cfp-1},
+                {-0x1.0000000000001p0, -0x1.aed548f090cefp-1, -0x1.aed548f090cfp-1},
+                {0x1.fffffffffffffp-2, 0x1.eaee8744b05efp-2, 0x1.eaee8744b05fp-2},
+                {-0x1.fffffffffffffp-2, -0x1.eaee8744b05efp-2, -0x1.eaee8744b05fp-2},
+                {0x1.0p-1, 0x1.eaee8744b05fp-2, 0x1.eaee8744b05efp-2},
+                {-0x1.0p-1, -0x1.eaee8744b05fp-2, -0x1.eaee8744b05efp-2},
+                {0x1.0000000000001p-1, 0x1.eaee8744b05f2p-2, 0x1.eaee8744b05f1p-2},
+                {-0x1.0000000000001p-1, -0x1.eaee8744b05f2p-2, -0x1.eaee8744b05f1p-2},
+                {0x1.fffffffffffffp-3, 0x1.faaeed4f31576p-3, 0x1.faaeed4f31575p-3},
+                {-0x1.fffffffffffffp-3, -0x1.faaeed4f31576p-3, -0x1.faaeed4f31575p-3},
+                {0x1.0p-2, 0x1.faaeed4f31577p-3, 0x1.faaeed4f31576p-3},
+                {-0x1.0p-2, -0x1.faaeed4f31577p-3, -0x1.faaeed4f31576p-3},
+                {0x1.0000000000001p-2, 0x1.faaeed4f31579p-3, 0x1.faaeed4f31578p-3},
+                {-0x1.0000000000001p-2, -0x1.faaeed4f31579p-3, -0x1.faaeed4f31578p-3},
+                {0x1.fffffffffffffp-4, 0x1.feaaeee86ee35p-4, 0x1.feaaeee86ee34p-4},
+                {-0x1.fffffffffffffp-4, -0x1.feaaeee86ee35p-4, -0x1.feaaeee86ee34p-4},
+                {0x1.0p-3, 0x1.feaaeee86ee36p-4, 0x1.feaaeee86ee35p-4},
+                {-0x1.0p-3, -0x1.feaaeee86ee36p-4, -0x1.feaaeee86ee35p-4},
+                {0x1.0000000000001p-3, 0x1.feaaeee86ee38p-4, 0x1.feaaeee86ee37p-4},
+                {-0x1.0000000000001p-3, -0x1.feaaeee86ee38p-4, -0x1.feaaeee86ee37p-4},
+                {0x1.fffffffffffffp-5, 0x1.ffaaaeeed4edap-5, 0x1.ffaaaeeed4ed9p-5},
+                {-0x1.fffffffffffffp-5, -0x1.ffaaaeeed4edap-5, -0x1.ffaaaeeed4ed9p-5},
+                {0x1.0p-4, 0x1.ffaaaeeed4edbp-5, 0x1.ffaaaeeed4edap-5},
+                {-0x1.0p-4, -0x1.ffaaaeeed4edbp-5, -0x1.ffaaaeeed4edap-5},
+                {0x1.0000000000001p-4, 0x1.ffaaaeeed4eddp-5, 0x1.ffaaaeeed4edcp-5},
+                {-0x1.0000000000001p-4, -0x1.ffaaaeeed4eddp-5, -0x1.ffaaaeeed4edcp-5},
+                {0x1.fffffffffffffp-6, 0x1.ffeaaaeeee86ep-6, 0x1.ffeaaaeeee86dp-6},
+                {-0x1.fffffffffffffp-6, -0x1.ffeaaaeeee86ep-6, -0x1.ffeaaaeeee86dp-6},
+                {0x1.0p-5, 0x1.ffeaaaeeee86fp-6, 0x1.ffeaaaeeee86ep-6},
+                {-0x1.0p-5, -0x1.ffeaaaeeee86fp-6, -0x1.ffeaaaeeee86ep-6},
+                {0x1.0000000000001p-5, 0x1.ffeaaaeeee871p-6, 0x1.ffeaaaeeee87p-6},
+                {-0x1.0000000000001p-5, -0x1.ffeaaaeeee871p-6, -0x1.ffeaaaeeee87p-6},
+                {0x1.fffffffffffffp-7, 0x1.fffaaaaeeeed4p-7, 0x1.fffaaaaeeeed3p-7},
+                {-0x1.fffffffffffffp-7, -0x1.fffaaaaeeeed4p-7, -0x1.fffaaaaeeeed3p-7},
+                {0x1.0p-6, 0x1.fffaaaaeeeed5p-7, 0x1.fffaaaaeeeed4p-7},
+                {-0x1.0p-6, -0x1.fffaaaaeeeed5p-7, -0x1.fffaaaaeeeed4p-7},
+                {0x1.0000000000001p-6, 0x1.fffaaaaeeeed7p-7, 0x1.fffaaaaeeeed6p-7},
+                {-0x1.0000000000001p-6, -0x1.fffaaaaeeeed7p-7, -0x1.fffaaaaeeeed6p-7},
+                {0x1.fffffffffffffp-15, 0x1.fffffffaaaaaap-15, 0x1.fffffffaaaaa9p-15},
+                {-0x1.fffffffffffffp-15, -0x1.fffffffaaaaaap-15, -0x1.fffffffaaaaa9p-15},
+                {0x1.0p-14, 0x1.fffffffaaaaabp-15, 0x1.fffffffaaaaaap-15},
+                {-0x1.0p-14, -0x1.fffffffaaaaabp-15, -0x1.fffffffaaaaaap-15},
+                {0x1.0000000000001p-14, 0x1.fffffffaaaaadp-15, 0x1.fffffffaaaaacp-15},
+                {-0x1.0000000000001p-14, -0x1.fffffffaaaaadp-15, -0x1.fffffffaaaaacp-15},
+                {0x1.fffffffffffffp-28, 0x1.fffffffffffffp-28, 0x1.ffffffffffffep-28},
+                {-0x1.fffffffffffffp-28, -0x1.fffffffffffffp-28, -0x1.ffffffffffffep-28},
+                {0x1.0p-27, 0x1.0p-27, 0x1.fffffffffffffp-28},
+                {-0x1.0p-27, -0x1.0p-27, -0x1.fffffffffffffp-28},
+                {0x1.0000000000001p-27, 0x1.0000000000001p-27, 0x1.0p-27},
+                {-0x1.0000000000001p-27, -0x1.0000000000001p-27, -0x1.0p-27},
+                {0x1.fffffffffffffp-31, 0x1.fffffffffffffp-31, 0x1.ffffffffffffep-31},
+                {-0x1.fffffffffffffp-31, -0x1.fffffffffffffp-31, -0x1.ffffffffffffep-31},
+                {0x1.0p-30, 0x1.0p-30, 0x1.fffffffffffffp-31},
+                {-0x1.0p-30, -0x1.0p-30, -0x1.fffffffffffffp-31},
+                {0x1.0000000000001p-30, 0x1.0000000000001p-30, 0x1.0p-30},
+                {-0x1.0000000000001p-30, -0x1.0000000000001p-30, -0x1.0p-30},
+                {-0x1.fffffffffffffp1023, -0x1.452fc98b34e97p-8, -0x1.452fc98b34e96p-8},
+                {0x1.fffffffffffffp1023, 0x1.452fc98b34e97p-8, 0x1.452fc98b34e96p-8},
+                {0x1.fffffffffffffp1023, 0x1.452fc98b34e97p-8, 0x1.452fc98b34e96p-8},
+                {-0x1.fffffffffffffp1023, -0x1.452fc98b34e97p-8, -0x1.452fc98b34e96p-8},
+                {0x1.fffffffffffffp1023, 0x1.452fc98b34e97p-8, 0x1.452fc98b34e96p-8},
+                {-0x1.fffffffffffffp1023, -0x1.452fc98b34e97p-8, -0x1.452fc98b34e96p-8},
+                {0x1.ffffffffffffep1023, 0x1.daa3677c6ee8ap-1, 0x1.daa3677c6ee8bp-1},
+                {-0x1.ffffffffffffep1023, -0x1.daa3677c6ee8ap-1, -0x1.daa3677c6ee8bp-1},
+                {0x1.921fb54442d18p1, 0x1.1a62633145c07p-53, 0x1.1a62633145c06p-53},
+                {-0x1.921fb54442d18p1, -0x1.1a62633145c07p-53, -0x1.1a62633145c06p-53},
+                {0x1.921fb54442d18p0, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p0, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.0000000000001p0, 0x1.aed548f090cefp-1, 0x1.aed548f090cfp-1},
+                {-0x1.0000000000001p0, -0x1.aed548f090cefp-1, -0x1.aed548f090cfp-1},
+                {0x1.0p0, 0x1.aed548f090ceep-1, 0x1.aed548f090cefp-1},
+                {-0x1.0p0, -0x1.aed548f090ceep-1, -0x1.aed548f090cefp-1},
+                {0x1.fffffffffffffp-1, 0x1.aed548f090cedp-1, 0x1.aed548f090ceep-1},
+                {-0x1.fffffffffffffp-1, -0x1.aed548f090cedp-1, -0x1.aed548f090ceep-1},
+                {0x1.921fb54442d18p-1, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcdp-1},
+                {-0x1.921fb54442d18p-1, -0x1.6a09e667f3bccp-1, -0x1.6a09e667f3bcdp-1},
+                {0x1.0000000000001p-1022, 0x1.0000000000001p-1022, 0x1.0000000000001p-1022},
+                {-0x1.0000000000001p-1022, -0x1.0000000000001p-1022, -0x1.0000000000001p-1022},
+                {0x1.0p-1022, 0x1.0p-1022, 0x1.0p-1022},
+                {-0x1.0p-1022, -0x1.0p-1022, -0x1.0p-1022},
+                {0x0.fffffffffffffp-1022, 0x0.fffffffffffffp-1022, 0x0.fffffffffffffp-1022},
+                {-0x0.fffffffffffffp-1022, -0x0.fffffffffffffp-1022, -0x0.fffffffffffffp-1022},
+                {0x0.ffffffffffffep-1022, 0x0.ffffffffffffep-1022, 0x0.ffffffffffffep-1022},
+                {-0x0.ffffffffffffep-1022, -0x0.ffffffffffffep-1022, -0x0.ffffffffffffep-1022},
+                {0x0.0000000000002p-1022, 0x0.0000000000002p-1022, 0x0.0000000000002p-1022},
+                {-0x0.0000000000002p-1022, -0x0.0000000000002p-1022, -0x0.0000000000001p-1022},
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0p0},
+                {-0x0.0000000000001p-1022, -0x0.0000000000001p-1022, -0x0.0p0},
+                {0x0.0p0, 0x0.0p0, 0x0.0p0},
+                {-0x0.0p0, -0x0.0p0, -0x0.0p0}
+
+        };
+
+        for (double[] testCase : testCases) {
+            testSinCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+    private static void testSinCase(double input, double bound1, double bound2) {
+        Tests.testBounds("Math.sin", input, Math.sin(input), bound1, bound2);
+    }
+
+    @Test
+    public void testCornerCasesCos() {
+        double[][] testCases = {
+                {0x1.feb1f7920e248p-2, 0x1.c1a27ae836f13p-1, 0x1.c1a27ae836f12p-1},
+                {-0x1.feb1f7920e248p-2, 0x1.c1a27ae836f13p-1, 0x1.c1a27ae836f12p-1},
+                {0x1.7cb7648526f99p-1, 0x1.78daf01036d0dp-1, 0x1.78daf01036d0cp-1},
+                {-0x1.7cb7648526f99p-1, 0x1.78daf01036d0dp-1, 0x1.78daf01036d0cp-1},
+                {0x1.549ec0c0c5afap-5, 0x1.ff8eb6a91ecbp-1, 0x1.ff8eb6a91ecb1p-1},
+                {-0x1.549ec0c0c5afap-5, 0x1.ff8eb6a91ecbp-1, 0x1.ff8eb6a91ecb1p-1},
+                {0x1.16e534ee3658p-4, 0x1.fed0476fc75cap-1, 0x1.fed0476fc75c9p-1},
+                {-0x1.16e534ee3658p-4, 0x1.fed0476fc75cap-1, 0x1.fed0476fc75c9p-1},
+                {0x1.efeef61d39ac2p-3, 0x1.f10fc61e2c78fp-1, 0x1.f10fc61e2c78ep-1},
+                {-0x1.efeef61d39ac2p-3, 0x1.f10fc61e2c78fp-1, 0x1.f10fc61e2c78ep-1},
+                {0x1.c65a170474549p-1, 0x1.434a3645be208p-1, 0x1.434a3645be209p-1},
+                {-0x1.c65a170474549p-1, 0x1.434a3645be208p-1, 0x1.434a3645be209p-1},
+                {0x1.6b8a6273d7c21p0, 0x1.337fc5b072c53p-3, 0x1.337fc5b072c52p-3},
+                {-0x1.6b8a6273d7c21p0, 0x1.337fc5b072c53p-3, 0x1.337fc5b072c52p-3},
+                {-0x1.036f4ba7e90aap-2, 0x1.efa7cddb128fcp-1, 0x1.efa7cddb128fbp-1},
+                {0x1.036f4ba7e90aap-2, 0x1.efa7cddb128fcp-1, 0x1.efa7cddb128fbp-1},
+                {-0x1.1500766c9df2p-31, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.1500766c9df2p-31, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.1e2a1563e068ep-2, 0x1.ec231802917bep-1, 0x1.ec231802917bdp-1},
+                {0x1.1e2a1563e068ep-2, 0x1.ec231802917bep-1, 0x1.ec231802917bdp-1},
+                {-0x1.2115aa73f8d05p5, 0x1.dc044ac92b7fcp-8, 0x1.dc044ac92b7fbp-8},
+                {0x1.2115aa73f8d05p5, 0x1.dc044ac92b7fcp-8, 0x1.dc044ac92b7fbp-8},
+                {-0x1.34e3bcdf8f69ap2, 0x1.d1fa67c50dd53p-4, 0x1.d1fa67c50dd52p-4},
+                {0x1.34e3bcdf8f69ap2, 0x1.d1fa67c50dd53p-4, 0x1.d1fa67c50dd52p-4},
+                {-0x1.380000000000bp7, 0x1.e2f8d19fb8db8p-2, 0x1.e2f8d19fb8db9p-2},
+                {0x1.380000000000bp7, 0x1.e2f8d19fb8db8p-2, 0x1.e2f8d19fb8db9p-2},
+                {-0x1.440000004p6, 0x1.8da9c90c3eda1p-1, 0x1.8da9c90c3eda2p-1},
+                {0x1.440000004p6, 0x1.8da9c90c3eda1p-1, 0x1.8da9c90c3eda2p-1},
+                {-0x1.550c8ee67a4c4p29, 0x1.b59b320603f83p-1, 0x1.b59b320603f84p-1},
+                {0x1.550c8ee67a4c4p29, 0x1.b59b320603f83p-1, 0x1.b59b320603f84p-1},
+                {-0x1.711789fdb2e8ap-13, 0x1.ffffff7af6c88p-1, 0x1.ffffff7af6c89p-1},
+                {0x1.711789fdb2e8ap-13, 0x1.ffffff7af6c88p-1, 0x1.ffffff7af6c89p-1},
+                {-0x1.77e000002p8, 0x1.c1b68ebb0b4fep-2, 0x1.c1b68ebb0b4ffp-2},
+                {0x1.77e000002p8, 0x1.c1b68ebb0b4fep-2, 0x1.c1b68ebb0b4ffp-2},
+                {-0x1.8106561931b43p0, 0x1.1161e1dad76dcp-4, 0x1.1161e1dad76dbp-4},
+                {0x1.8106561931b43p0, 0x1.1161e1dad76dcp-4, 0x1.1161e1dad76dbp-4},
+                {-0x1.825be2461cad4p0, 0x1.f828c3226b3d7p-5, 0x1.f828c3226b3d8p-5},
+                {0x1.825be2461cad4p0, 0x1.f828c3226b3d7p-5, 0x1.f828c3226b3d8p-5},
+                {-0x1.8288755803b08p0, 0x1.f2990d742e9fbp-5, 0x1.f2990d742e9fap-5},
+                {0x1.8288755803b08p0, 0x1.f2990d742e9fbp-5, 0x1.f2990d742e9fap-5},
+                {-0x1.8a75701f4ccd3p1, -0x1.ff150dda7524dp-1, -0x1.ff150dda7524cp-1},
+                {0x1.8a75701f4ccd3p1, -0x1.ff150dda7524dp-1, -0x1.ff150dda7524cp-1},
+                {-0x1.b389316f37f37p3, 0x1.015c47c32b574p-1, 0x1.015c47c32b575p-1},
+                {0x1.b389316f37f37p3, 0x1.015c47c32b574p-1, 0x1.015c47c32b575p-1},
+                {-0x1.c602c465d7d27p6, 0x1.d681a366a0534p-1, 0x1.d681a366a0535p-1},
+                {0x1.c602c465d7d27p6, 0x1.d681a366a0534p-1, 0x1.d681a366a0535p-1},
+                {-0x1.cfb81fe69664cp4, -0x1.84e896c7543d6p-1, -0x1.84e896c7543d5p-1},
+                {0x1.cfb81fe69664cp4, -0x1.84e896c7543d6p-1, -0x1.84e896c7543d5p-1},
+                {-0x1.d08f2d86b12c6p13, 0x1.fc5dcfddd54cp-1, 0x1.fc5dcfddd54c1p-1},
+                {0x1.d08f2d86b12c6p13, 0x1.fc5dcfddd54cp-1, 0x1.fc5dcfddd54c1p-1},
+                {-0x1.de13f0943c494p99, 0x1.fe83235fbe016p-3, 0x1.fe83235fbe015p-3},
+                {0x1.de13f0943c494p99, 0x1.fe83235fbe016p-3, 0x1.fe83235fbe015p-3},
+                {-0x1.de3c1f1285e8bp3, -0x1.720321239ec5p-1, -0x1.720321239ec4fp-1},
+                {0x1.de3c1f1285e8bp3, -0x1.720321239ec5p-1, -0x1.720321239ec4fp-1},
+                {-0x1.fffffffffff7fp1023, 0x1.f7143c8bba407p-4, 0x1.f7143c8bba406p-4},
+                {0x1.fffffffffff7fp1023, 0x1.f7143c8bba407p-4, 0x1.f7143c8bba406p-4},
+                {-0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {0x1.0000000000001p51, 0x1.055e457ac1227p-5, 0x1.055e457ac1228p-5},
+                {-0x1.0000000000001p51, 0x1.055e457ac1227p-5, 0x1.055e457ac1228p-5},
+                {0x1.0000000000003p-1, 0x1.c1528065b7d4ep-1, 0x1.c1528065b7d4fp-1},
+                {-0x1.0000000000003p-1, 0x1.c1528065b7d4ep-1, 0x1.c1528065b7d4fp-1},
+                {0x1.0000000000003p-32, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.0000000000003p-32, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.000000000002p150, 0x1.fffea444bc05ep-1, 0x1.fffea444bc05fp-1},
+                {-0x1.000000000002p150, 0x1.fffea444bc05ep-1, 0x1.fffea444bc05fp-1},
+                {0x1.0000000000038p380, -0x1.ebddee876f434p-1, -0x1.ebddee876f433p-1},
+                {-0x1.0000000000038p380, -0x1.ebddee876f434p-1, -0x1.ebddee876f433p-1},
+                {0x1.0000000000118p380, -0x1.f2ffc51dc6968p-1, -0x1.f2ffc51dc6969p-1},
+                {-0x1.0000000000118p380, -0x1.f2ffc51dc6968p-1, -0x1.f2ffc51dc6969p-1},
+                {0x1.00000000003ffp641, -0x1.f8fbb4d358b2p-1, -0x1.f8fbb4d358b21p-1},
+                {-0x1.00000000003ffp641, -0x1.f8fbb4d358b2p-1, -0x1.f8fbb4d358b21p-1},
+                {0x1.0000000001p1, -0x1.aa2265753e668p-2, -0x1.aa2265753e669p-2},
+                {-0x1.0000000001p1, -0x1.aa2265753e668p-2, -0x1.aa2265753e669p-2},
+                {0x1.000000008p452, 0x1.fd1242c25994dp-1, 0x1.fd1242c25994ep-1},
+                {-0x1.000000008p452, 0x1.fd1242c25994dp-1, 0x1.fd1242c25994ep-1},
+                {0x1.00000000effafp-7, 0x1.fffc0001554dap-1, 0x1.fffc0001554dbp-1},
+                {-0x1.00000000effafp-7, 0x1.fffc0001554dap-1, 0x1.fffc0001554dbp-1},
+                {0x1.00000114fefe2p0, 0x1.14a27f2925522p-1, 0x1.14a27f2925523p-1},
+                {-0x1.00000114fefe2p0, 0x1.14a27f2925522p-1, 0x1.14a27f2925523p-1},
+                {0x1.000007p40, 0x1.bf81e0269c59dp-3, 0x1.bf81e0269c59cp-3},
+                {-0x1.000007p40, 0x1.bf81e0269c59dp-3, 0x1.bf81e0269c59cp-3},
+                {0x1.00000acadb3d3p0, 0x1.14a26ed1960d6p-1, 0x1.14a26ed1960d7p-1},
+                {-0x1.00000acadb3d3p0, 0x1.14a26ed1960d6p-1, 0x1.14a26ed1960d7p-1},
+                {0x1.00003p-17, 0x1.ffffffffbfffep-1, 0x1.ffffffffbffffp-1},
+                {-0x1.00003p-17, 0x1.ffffffffbfffep-1, 0x1.ffffffffbffffp-1},
+                {0x1.00003ffffffaep-18, 0x1.ffffffffeffffp-1, 0x1.fffffffffp-1},
+                {-0x1.00003ffffffaep-18, 0x1.ffffffffeffffp-1, 0x1.fffffffffp-1},
+                {0x1.00003ffffffffp-18, 0x1.ffffffffeffffp-1, 0x1.fffffffffp-1},
+                {-0x1.00003ffffffffp-18, 0x1.ffffffffeffffp-1, 0x1.fffffffffp-1},
+                {0x1.00007ffffdeap41, -0x1.dab7efeb35baep-2, -0x1.dab7efeb35badp-2},
+                {-0x1.00007ffffdeap41, -0x1.dab7efeb35baep-2, -0x1.dab7efeb35badp-2},
+                {0x1.0000ffff8p-19, 0x1.fffffffffcp-1, 0x1.fffffffffbfffp-1},
+                {-0x1.0000ffff8p-19, 0x1.fffffffffcp-1, 0x1.fffffffffbfffp-1},
+                {0x1.0003fff800051p-20, 0x1.ffffffffffp-1, 0x1.fffffffffefffp-1},
+                {-0x1.0003fff800051p-20, 0x1.ffffffffffp-1, 0x1.fffffffffefffp-1},
+                {0x1.0003fff800096p-20, 0x1.ffffffffffp-1, 0x1.fffffffffefffp-1},
+                {-0x1.0003fff800096p-20, 0x1.ffffffffffp-1, 0x1.fffffffffefffp-1},
+                {0x1.000fd2p334, -0x1.fbf2b71a23a58p-2, -0x1.fbf2b71a23a57p-2},
+                {-0x1.000fd2p334, -0x1.fbf2b71a23a58p-2, -0x1.fbf2b71a23a57p-2},
+                {0x1.003p514, 0x1.fccc87eae7737p-5, 0x1.fccc87eae7736p-5},
+                {-0x1.003p514, 0x1.fccc87eae7737p-5, 0x1.fccc87eae7736p-5},
+                {0x1.00600000015f4p41, -0x1.a43f40d92b7edp-7, -0x1.a43f40d92b7eep-7},
+                {-0x1.00600000015f4p41, -0x1.a43f40d92b7edp-7, -0x1.a43f40d92b7eep-7},
+                {0x1.007p-1, 0x1.c11cc38f40ab3p-1, 0x1.c11cc38f40ab2p-1},
+                {-0x1.007p-1, 0x1.c11cc38f40ab3p-1, 0x1.c11cc38f40ab2p-1},
+                {0x1.007p-21, 0x1.ffffffffffbfcp-1, 0x1.ffffffffffbfdp-1},
+                {-0x1.007p-21, 0x1.ffffffffffbfcp-1, 0x1.ffffffffffbfdp-1},
+                {0x1.00cp40, 0x1.e9ba98231f734p-8, 0x1.e9ba98231f735p-8},
+                {-0x1.00cp40, 0x1.e9ba98231f734p-8, 0x1.e9ba98231f735p-8},
+                {0x1.011p-4, 0x1.fefdf48ed649dp-1, 0x1.fefdf48ed649cp-1},
+                {-0x1.011p-4, 0x1.fefdf48ed649dp-1, 0x1.fefdf48ed649cp-1},
+                {0x1.011p996, -0x1.ffc16a0f12ff2p-1, -0x1.ffc16a0f12ff3p-1},
+                {-0x1.011p996, -0x1.ffc16a0f12ff2p-1, -0x1.ffc16a0f12ff3p-1},
+                {0x1.02p-2, 0x1.efd5b61a30a38p-1, 0x1.efd5b61a30a39p-1},
+                {-0x1.02p-2, 0x1.efd5b61a30a38p-1, 0x1.efd5b61a30a39p-1},
+                {0x1.0204260c18307p59, 0x1.c97b8161dc50ap-2, 0x1.c97b8161dc50bp-2},
+                {-0x1.0204260c18307p59, 0x1.c97b8161dc50ap-2, 0x1.c97b8161dc50bp-2},
+                {0x1.02e78a321155ep1, -0x1.bf26a3c9b9fbfp-2, -0x1.bf26a3c9b9fbep-2},
+                {-0x1.02e78a321155ep1, -0x1.bf26a3c9b9fbfp-2, -0x1.bf26a3c9b9fbep-2},
+                {0x1.04p-4, 0x1.fef806b1f84e5p-1, 0x1.fef806b1f84e4p-1},
+                {-0x1.04p-4, 0x1.fef806b1f84e5p-1, 0x1.fef806b1f84e4p-1},
+                {0x1.04bde8bb80258p98, 0x1.fe851fbf87d17p-1, 0x1.fe851fbf87d18p-1},
+                {-0x1.04bde8bb80258p98, 0x1.fe851fbf87d17p-1, 0x1.fe851fbf87d18p-1},
+                {0x1.077e749e37ceep236, 0x1.70f6a51da8effp-1, 0x1.70f6a51da8efep-1},
+                {-0x1.077e749e37ceep236, 0x1.70f6a51da8effp-1, 0x1.70f6a51da8efep-1},
+                {0x1.07f8p300, 0x1.6b408c856bda6p-3, 0x1.6b408c856bda5p-3},
+                {-0x1.07f8p300, 0x1.6b408c856bda6p-3, 0x1.6b408c856bda5p-3},
+                {0x1.07f9bea1b3546p27, 0x1.2b2f965ae40fcp-1, 0x1.2b2f965ae40fdp-1},
+                {-0x1.07f9bea1b3546p27, 0x1.2b2f965ae40fcp-1, 0x1.2b2f965ae40fdp-1},
+                {0x1.090d18372f2d5p4, -0x1.4eed2f3fc76a8p-1, -0x1.4eed2f3fc76a7p-1},
+                {-0x1.090d18372f2d5p4, -0x1.4eed2f3fc76a8p-1, -0x1.4eed2f3fc76a7p-1},
+                {0x1.0b4p-3, 0x1.fba59aecee5p-1, 0x1.fba59aecee501p-1},
+                {-0x1.0b4p-3, 0x1.fba59aecee5p-1, 0x1.fba59aecee501p-1},
+                {0x1.0c0d5c2af3c2ep346, 0x1.fffd1bcda7a7dp-1, 0x1.fffd1bcda7a7ep-1},
+                {-0x1.0c0d5c2af3c2ep346, 0x1.fffd1bcda7a7dp-1, 0x1.fffd1bcda7a7ep-1},
+                {0x1.0d30596ee91fdp216, -0x1.e4dfe83129286p-1, -0x1.e4dfe83129287p-1},
+                {-0x1.0d30596ee91fdp216, -0x1.e4dfe83129286p-1, -0x1.e4dfe83129287p-1},
+                {0x1.0d6p0, 0x1.fb8432886a284p-2, 0x1.fb8432886a283p-2},
+                {-0x1.0d6p0, 0x1.fb8432886a284p-2, 0x1.fb8432886a283p-2},
+                {0x1.0e9474c68831cp-10, 0x1.ffffee202854p-1, 0x1.ffffee202853fp-1},
+                {-0x1.0e9474c68831cp-10, 0x1.ffffee202854p-1, 0x1.ffffee202853fp-1},
+                {0x1.113bae4049849p2, -0x1.b70d3d5584b1bp-2, -0x1.b70d3d5584b1ap-2},
+                {-0x1.113bae4049849p2, -0x1.b70d3d5584b1bp-2, -0x1.b70d3d5584b1ap-2},
+                {0x1.12eb87097654p-4, 0x1.fed8df58f626p-1, 0x1.fed8df58f625fp-1},
+                {-0x1.12eb87097654p-4, 0x1.fed8df58f626p-1, 0x1.fed8df58f625fp-1},
+                {0x1.13cp0, 0x1.e536ae395dfcep-2, 0x1.e536ae395dfcfp-2},
+                {-0x1.13cp0, 0x1.e536ae395dfcep-2, 0x1.e536ae395dfcfp-2},
+                {0x1.16e534ee3658p-4, 0x1.fed0476fc75cap-1, 0x1.fed0476fc75c9p-1},
+                {-0x1.16e534ee3658p-4, 0x1.fed0476fc75cap-1, 0x1.fed0476fc75c9p-1},
+                {0x1.17fffffffea98p-3, 0x1.fb38e82e3193ap-1, 0x1.fb38e82e3193bp-1},
+                {-0x1.17fffffffea98p-3, 0x1.fb38e82e3193ap-1, 0x1.fb38e82e3193bp-1},
+                {0x1.18p-3, 0x1.fb38e82e3188p-1, 0x1.fb38e82e3187fp-1},
+                {-0x1.18p-3, 0x1.fb38e82e3188p-1, 0x1.fb38e82e3187fp-1},
+                {0x1.1a191ebbb4d7fp7, -0x1.e59647f1fe9c7p-1, -0x1.e59647f1fe9c8p-1},
+                {-0x1.1a191ebbb4d7fp7, -0x1.e59647f1fe9c7p-1, -0x1.e59647f1fe9c8p-1},
+                {0x1.1da84f2b7b1d8p7, -0x1.d0dca1f8715bep-4, -0x1.d0dca1f8715bdp-4},
+                {-0x1.1da84f2b7b1d8p7, -0x1.d0dca1f8715bep-4, -0x1.d0dca1f8715bdp-4},
+                {0x1.201e973251302p0, 0x1.b917ebbc30e1ep-2, 0x1.b917ebbc30e1dp-2},
+                {-0x1.201e973251302p0, 0x1.b917ebbc30e1ep-2, 0x1.b917ebbc30e1dp-2},
+                {0x1.21e02p-7, 0x1.fffadf12ff414p-1, 0x1.fffadf12ff415p-1},
+                {-0x1.21e02p-7, 0x1.fffadf12ff414p-1, 0x1.fffadf12ff415p-1},
+                {0x1.27e29a4b985bfp1, -0x1.598a4dab3de5ap-1, -0x1.598a4dab3de59p-1},
+                {-0x1.27e29a4b985bfp1, -0x1.598a4dab3de5ap-1, -0x1.598a4dab3de59p-1},
+                {0x1.2a1f28dbfb6cp-3, 0x1.fa95c1154abf5p-1, 0x1.fa95c1154abf6p-1},
+                {-0x1.2a1f28dbfb6cp-3, 0x1.fa95c1154abf5p-1, 0x1.fa95c1154abf6p-1},
+                {0x1.2b8p1, -0x1.6412293adb7bcp-1, -0x1.6412293adb7bdp-1},
+                {-0x1.2b8p1, -0x1.6412293adb7bcp-1, -0x1.6412293adb7bdp-1},
+                {0x1.31199def72f4dp-7, 0x1.fffa518a7d0e7p-1, 0x1.fffa518a7d0e8p-1},
+                {-0x1.31199def72f4dp-7, 0x1.fffa518a7d0e7p-1, 0x1.fffa518a7d0e8p-1},
+                {0x1.31260e1485014p4, 0x1.f36895fe177f8p-1, 0x1.f36895fe177f7p-1},
+                {-0x1.31260e1485014p4, 0x1.f36895fe177f8p-1, 0x1.f36895fe177f7p-1},
+                {0x1.34e964cd103bdp2, 0x1.d36207b4fee17p-4, 0x1.d36207b4fee16p-4},
+                {-0x1.34e964cd103bdp2, 0x1.d36207b4fee17p-4, 0x1.d36207b4fee16p-4},
+                {0x1.37618a0ba785p1, -0x1.84a37f4fa7616p-1, -0x1.84a37f4fa7617p-1},
+                {-0x1.37618a0ba785p1, -0x1.84a37f4fa7616p-1, -0x1.84a37f4fa7617p-1},
+                {0x1.379704f5f1eb3p24, -0x1.c830bbc99e229p-39, -0x1.c830bbc99e22ap-39},
+                {-0x1.379704f5f1eb3p24, -0x1.c830bbc99e229p-39, -0x1.c830bbc99e22ap-39},
+                {0x1.3b61dd166d47p2, 0x1.b5daaa233bd5p-3, 0x1.b5daaa233bd4fp-3},
+                {-0x1.3b61dd166d47p2, 0x1.b5daaa233bd5p-3, 0x1.b5daaa233bd4fp-3},
+                {0x1.3c011022acbdp37, -0x1.ffd00dc4db401p-4, -0x1.ffd00dc4db4p-4},
+                {-0x1.3c011022acbdp37, -0x1.ffd00dc4db401p-4, -0x1.ffd00dc4db4p-4},
+                {0x1.3e7788e900b7p727, -0x1.14052b4016ff5p-1, -0x1.14052b4016ff6p-1},
+                {-0x1.3e7788e900b7p727, -0x1.14052b4016ff5p-1, -0x1.14052b4016ff6p-1},
+                {0x1.423eafdcc2779p-10, 0x1.ffffe6a5e4198p-1, 0x1.ffffe6a5e4197p-1},
+                {-0x1.423eafdcc2779p-10, 0x1.ffffe6a5e4198p-1, 0x1.ffffe6a5e4197p-1},
+                {0x1.4321828c1b538p119, -0x1.fe09fc3d16feep-6, -0x1.fe09fc3d16fedp-6},
+                {-0x1.4321828c1b538p119, -0x1.fe09fc3d16feep-6, -0x1.fe09fc3d16fedp-6},
+                {0x1.43506cb22975dp22, 0x1.b685d949a27ap-14, 0x1.b685d949a27a1p-14},
+                {-0x1.43506cb22975dp22, 0x1.b685d949a27ap-14, 0x1.b685d949a27a1p-14},
+                {0x1.439f63495786ap67, 0x1.fe398090e203cp-1, 0x1.fe398090e203bp-1},
+                {-0x1.439f63495786ap67, 0x1.fe398090e203cp-1, 0x1.fe398090e203bp-1},
+                {0x1.457538a6bd073p-4, 0x1.fe6274e000974p-1, 0x1.fe6274e000973p-1},
+                {-0x1.457538a6bd073p-4, 0x1.fe6274e000974p-1, 0x1.fe6274e000973p-1},
+                {0x1.478fc08p43, 0x1.09fcb69359c0ap-1, 0x1.09fcb69359c09p-1},
+                {-0x1.478fc08p43, 0x1.09fcb69359c0ap-1, 0x1.09fcb69359c09p-1},
+                {0x1.48a45797cbe63p61, -0x1.20c2158511e79p-9, -0x1.20c2158511e78p-9},
+                {-0x1.48a45797cbe63p61, -0x1.20c2158511e79p-9, -0x1.20c2158511e78p-9},
+                {0x1.4a62e0e12c173p-1, 0x1.990d17aae253p-1, 0x1.990d17aae2531p-1},
+                {-0x1.4a62e0e12c173p-1, 0x1.990d17aae253p-1, 0x1.990d17aae2531p-1},
+                {0x1.4c596642a9488p9, 0x1.fdd4f1e00b387p-3, 0x1.fdd4f1e00b388p-3},
+                {-0x1.4c596642a9488p9, 0x1.fdd4f1e00b387p-3, 0x1.fdd4f1e00b388p-3},
+                {0x1.4dp-4, 0x1.fe4f141032f38p-1, 0x1.fe4f141032f37p-1},
+                {-0x1.4dp-4, 0x1.fe4f141032f38p-1, 0x1.fe4f141032f37p-1},
+                {0x1.4f0f308p488, 0x1.94e9f45d43c14p-2, 0x1.94e9f45d43c13p-2},
+                {-0x1.4f0f308p488, 0x1.94e9f45d43c14p-2, 0x1.94e9f45d43c13p-2},
+                {0x1.52f00ep793, 0x1.9355f69ad4326p-2, 0x1.9355f69ad4327p-2},
+                {-0x1.52f00ep793, 0x1.9355f69ad4326p-2, 0x1.9355f69ad4327p-2},
+                {0x1.52f06c730ec02p2, 0x1.1a19be8bea10ap-1, 0x1.1a19be8bea10bp-1},
+                {-0x1.52f06c730ec02p2, 0x1.1a19be8bea10ap-1, 0x1.1a19be8bea10bp-1},
+                {0x1.53e7d5845fe3dp220, 0x1.385d92ec0c734p-1, 0x1.385d92ec0c733p-1},
+                {-0x1.53e7d5845fe3dp220, 0x1.385d92ec0c734p-1, 0x1.385d92ec0c733p-1},
+                {0x1.59p-20, 0x1.fffffffffe2f1p-1, 0x1.fffffffffe2fp-1},
+                {-0x1.59p-20, 0x1.fffffffffe2f1p-1, 0x1.fffffffffe2fp-1},
+                {0x1.592f1176f098p86, -0x1.ffd7bc28ded92p-1, -0x1.ffd7bc28ded91p-1},
+                {-0x1.592f1176f098p86, -0x1.ffd7bc28ded92p-1, -0x1.ffd7bc28ded91p-1},
+                {0x1.5999999dc09dcp1, -0x1.cee28b3d79799p-1, -0x1.cee28b3d7979ap-1},
+                {-0x1.5999999dc09dcp1, -0x1.cee28b3d79799p-1, -0x1.cee28b3d7979ap-1},
+                {0x1.5bea01p468, 0x1.c1f1eb08c2604p-1, 0x1.c1f1eb08c2605p-1},
+                {-0x1.5bea01p468, 0x1.c1f1eb08c2604p-1, 0x1.c1f1eb08c2605p-1},
+                {0x1.5cb80a6135e5ap1000, 0x1.fffe35ab09a65p-1, 0x1.fffe35ab09a66p-1},
+                {-0x1.5cb80a6135e5ap1000, 0x1.fffe35ab09a65p-1, 0x1.fffe35ab09a66p-1},
+                {0x1.5d5be48730d2dp13, -0x1.07b85f606e75dp-3, -0x1.07b85f606e75ep-3},
+                {-0x1.5d5be48730d2dp13, -0x1.07b85f606e75dp-3, -0x1.07b85f606e75ep-3},
+                {0x1.614p-21, 0x1.ffffffffff862p-1, 0x1.ffffffffff863p-1},
+                {-0x1.614p-21, 0x1.ffffffffff862p-1, 0x1.ffffffffff863p-1},
+                {0x1.62adc8a660364p1, -0x1.dd3a806e89cf2p-1, -0x1.dd3a806e89cf1p-1},
+                {-0x1.62adc8a660364p1, -0x1.dd3a806e89cf2p-1, -0x1.dd3a806e89cf1p-1},
+                {0x1.64ef438p142, -0x1.4308b14f4b6eep-1, -0x1.4308b14f4b6edp-1},
+                {-0x1.64ef438p142, -0x1.4308b14f4b6eep-1, -0x1.4308b14f4b6edp-1},
+                {0x1.652p0, 0x1.6623d2eb6add2p-3, 0x1.6623d2eb6add1p-3},
+                {-0x1.652p0, 0x1.6623d2eb6add2p-3, 0x1.6623d2eb6add1p-3},
+                {0x1.65865b2cb08a2p-7, 0x1.fff832c50f472p-1, 0x1.fff832c50f471p-1},
+                {-0x1.65865b2cb08a2p-7, 0x1.fff832c50f472p-1, 0x1.fff832c50f471p-1},
+                {0x1.6a937daabc20ep375, 0x1.acc251be33023p-1, 0x1.acc251be33022p-1},
+                {-0x1.6a937daabc20ep375, 0x1.acc251be33023p-1, 0x1.acc251be33022p-1},
+                {0x1.6ac5b262ca1ffp849, -0x1.14ae72e6ba22fp-61, -0x1.14ae72e6ba22ep-61},
+                {-0x1.6ac5b262ca1ffp849, -0x1.14ae72e6ba22fp-61, -0x1.14ae72e6ba22ep-61},
+                {0x1.6f7bdef7bdef4p3, 0x1.e0619960a11c6p-2, 0x1.e0619960a11c7p-2},
+                {-0x1.6f7bdef7bdef4p3, 0x1.e0619960a11c6p-2, 0x1.e0619960a11c7p-2},
+                {0x1.739ce759ce738p200, 0x1.8d23f97901a3p-1, 0x1.8d23f97901a31p-1},
+                {-0x1.739ce759ce738p200, 0x1.8d23f97901a3p-1, 0x1.8d23f97901a31p-1},
+                {0x1.7450c3f49d0b2p-11, 0x1.fffff78a14ba1p-1, 0x1.fffff78a14bap-1},
+                {-0x1.7450c3f49d0b2p-11, 0x1.fffff78a14ba1p-1, 0x1.fffff78a14bap-1},
+                {0x1.749fe53f963fdp0, 0x1.d6f1c727fb2ccp-4, 0x1.d6f1c727fb2cbp-4},
+                {-0x1.749fe53f963fdp0, 0x1.d6f1c727fb2ccp-4, 0x1.d6f1c727fb2cbp-4},
+                {0x1.74af6725c6206p1, -0x1.f284b5028c184p-1, -0x1.f284b5028c185p-1},
+                {-0x1.74af6725c6206p1, -0x1.f284b5028c184p-1, -0x1.f284b5028c185p-1},
+                {0x1.7550d28ffccc4p1, -0x1.f3165a0b306b2p-1, -0x1.f3165a0b306b1p-1},
+                {-0x1.7550d28ffccc4p1, -0x1.f3165a0b306b2p-1, -0x1.f3165a0b306b1p-1},
+                {0x1.775e397cd6aap6, 0x1.d66d2078ebdecp-1, 0x1.d66d2078ebdebp-1},
+                {-0x1.775e397cd6aap6, 0x1.d66d2078ebdecp-1, 0x1.d66d2078ebdebp-1},
+                {0x1.799302bf7f29p-1, 0x1.7af9a13085f53p-1, 0x1.7af9a13085f54p-1},
+                {-0x1.799302bf7f29p-1, 0x1.7af9a13085f53p-1, 0x1.7af9a13085f54p-1},
+                {0x1.799fffffffffdp-6, 0x1.ffdd2fdac0c25p-1, 0x1.ffdd2fdac0c24p-1},
+                {-0x1.799fffffffffdp-6, 0x1.ffdd2fdac0c25p-1, 0x1.ffdd2fdac0c24p-1},
+                {0x1.7a3692ca9449p-7, 0x1.fff744f185a73p-1, 0x1.fff744f185a74p-1},
+                {-0x1.7a3692ca9449p-7, 0x1.fff744f185a73p-1, 0x1.fff744f185a74p-1},
+                {0x1.7a66a638ac5b5p-1, 0x1.7a6b326b690fbp-1, 0x1.7a6b326b690fap-1},
+                {-0x1.7a66a638ac5b5p-1, 0x1.7a6b326b690fbp-1, 0x1.7a6b326b690fap-1},
+                {0x1.7ba65462b49ap0, 0x1.671fdb64ffbeep-4, 0x1.671fdb64ffbedp-4},
+                {-0x1.7ba65462b49ap0, 0x1.671fdb64ffbeep-4, 0x1.671fdb64ffbedp-4},
+                {0x1.7cdf37cdf37c9p239, 0x1.ffa55490f206ep-1, 0x1.ffa55490f206fp-1},
+                {-0x1.7cdf37cdf37c9p239, 0x1.ffa55490f206ep-1, 0x1.ffa55490f206fp-1},
+                {0x1.7d542565f472ep0, 0x1.4c5b5970a3a49p-4, 0x1.4c5b5970a3a48p-4},
+                {-0x1.7d542565f472ep0, 0x1.4c5b5970a3a49p-4, 0x1.4c5b5970a3a48p-4},
+                {0x1.7da0751649058p0, 0x1.479a5667c63f6p-4, 0x1.479a5667c63f5p-4},
+                {-0x1.7da0751649058p0, 0x1.479a5667c63f6p-4, 0x1.479a5667c63f5p-4},
+                {0x1.7e0ddcda6cc0dp-7, 0x1.fff717511dcb5p-1, 0x1.fff717511dcb6p-1},
+                {-0x1.7e0ddcda6cc0dp-7, 0x1.fff717511dcb5p-1, 0x1.fff717511dcb6p-1},
+                {0x1.7f6p-21, 0x1.ffffffffff707p-1, 0x1.ffffffffff708p-1},
+                {-0x1.7f6p-21, 0x1.ffffffffff707p-1, 0x1.ffffffffff708p-1},
+                {0x1.7f90117d44c74p100, -0x1.fff9e1554698p-1, -0x1.fff9e15546981p-1},
+                {-0x1.7f90117d44c74p100, -0x1.fff9e1554698p-1, -0x1.fff9e15546981p-1},
+                {0x1.7ffffffffef7ap-6, 0x1.ffdc006bff7eap-1, 0x1.ffdc006bff7e9p-1},
+                {-0x1.7ffffffffef7ap-6, 0x1.ffdc006bff7eap-1, 0x1.ffdc006bff7e9p-1},
+                {0x1.7fffffffffa26p-6, 0x1.ffdc006bff7e8p-1, 0x1.ffdc006bff7e7p-1},
+                {-0x1.7fffffffffa26p-6, 0x1.ffdc006bff7e8p-1, 0x1.ffdc006bff7e7p-1},
+                {0x1.7ffffffffff8p-6, 0x1.ffdc006bff7e7p-1, 0x1.ffdc006bff7e6p-1},
+                {-0x1.7ffffffffff8p-6, 0x1.ffdc006bff7e7p-1, 0x1.ffdc006bff7e6p-1},
+                {0x1.80ep-1, 0x1.760718ab44398p-1, 0x1.760718ab44397p-1},
+                {-0x1.80ep-1, 0x1.760718ab44398p-1, 0x1.760718ab44397p-1},
+                {0x1.81ae0dffa3b33p959, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.81ae0dffa3b33p959, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.81d612289c5cfp1, -0x1.fbdc48125b345p-1, -0x1.fbdc48125b346p-1},
+                {-0x1.81d612289c5cfp1, -0x1.fbdc48125b345p-1, -0x1.fbdc48125b346p-1},
+                {0x1.8220192270a0ep0, 0x1.ff9e396651ccap-5, 0x1.ff9e396651cc9p-5},
+                {-0x1.8220192270a0ep0, 0x1.ff9e396651ccap-5, 0x1.ff9e396651cc9p-5},
+                {0x1.822bb780e9104p0, 0x1.fe2b26dddb5c9p-5, 0x1.fe2b26dddb5c8p-5},
+                {-0x1.822bb780e9104p0, 0x1.fe2b26dddb5c9p-5, 0x1.fe2b26dddb5c8p-5},
+                {0x1.82c119c4b8e49p0, 0x1.eb87cff7c9115p-5, 0x1.eb87cff7c9116p-5},
+                {-0x1.82c119c4b8e49p0, 0x1.eb87cff7c9115p-5, 0x1.eb87cff7c9116p-5},
+                {0x1.82c119c4b9fc4p0, 0x1.eb87cff7a62b7p-5, 0x1.eb87cff7a62b8p-5},
+                {-0x1.82c119c4b9fc4p0, 0x1.eb87cff7a62b7p-5, 0x1.eb87cff7a62b8p-5},
+                {0x1.82c119c4ba808p0, 0x1.eb87cff795ab1p-5, 0x1.eb87cff795ab2p-5},
+                {-0x1.82c119c4ba808p0, 0x1.eb87cff795ab1p-5, 0x1.eb87cff795ab2p-5},
+                {0x1.832c9fc76527p0, 0x1.de1d17ab0d6a5p-5, 0x1.de1d17ab0d6a4p-5},
+                {-0x1.832c9fc76527p0, 0x1.de1d17ab0d6a5p-5, 0x1.de1d17ab0d6a4p-5},
+                {0x1.833956ce7d1f9p0, 0x1.dc86e7bec0c45p-5, 0x1.dc86e7bec0c44p-5},
+                {-0x1.833956ce7d1f9p0, 0x1.dc86e7bec0c45p-5, 0x1.dc86e7bec0c44p-5},
+                {0x1.834574eb1c099p0, 0x1.db03cbb942a7bp-5, 0x1.db03cbb942a7ap-5},
+                {-0x1.834574eb1c099p0, 0x1.db03cbb942a7bp-5, 0x1.db03cbb942a7ap-5},
+                {0x1.83aba5688e13ep0, 0x1.ce431710d1507p-5, 0x1.ce431710d1508p-5},
+                {-0x1.83aba5688e13ep0, 0x1.ce431710d1507p-5, 0x1.ce431710d1508p-5},
+                {0x1.83b38bbafd75bp0, 0x1.cd46b3a77f6ddp-5, 0x1.cd46b3a77f6dep-5},
+                {-0x1.83b38bbafd75bp0, 0x1.cd46b3a77f6ddp-5, 0x1.cd46b3a77f6dep-5},
+                {0x1.86a017cb1c31cp16, -0x1.ff29bc666bee7p-1, -0x1.ff29bc666bee6p-1},
+                {-0x1.86a017cb1c31cp16, -0x1.ff29bc666bee7p-1, -0x1.ff29bc666bee6p-1},
+                {0x1.8720588p392, -0x1.7968916e4c646p-2, -0x1.7968916e4c647p-2},
+                {-0x1.8720588p392, -0x1.7968916e4c646p-2, -0x1.7968916e4c647p-2},
+                {0x1.88a2288a22888p9, 0x1.fb97c7e452918p-1, 0x1.fb97c7e452917p-1},
+                {-0x1.88a2288a22888p9, 0x1.fb97c7e452918p-1, 0x1.fb97c7e452917p-1},
+                {0x1.8cf013991c308p1000, -0x1.ae44a5f01bf63p-1, -0x1.ae44a5f01bf64p-1},
+                {-0x1.8cf013991c308p1000, -0x1.ae44a5f01bf63p-1, -0x1.ae44a5f01bf64p-1},
+                {0x1.9p-2, 0x1.d96e82f71a9dcp-1, 0x1.d96e82f71a9ddp-1},
+                {-0x1.9p-2, 0x1.d96e82f71a9dcp-1, 0x1.d96e82f71a9ddp-1},
+                {0x1.9p0, 0x1.0fd9d5c093df5p-7, 0x1.0fd9d5c093df4p-7},
+                {-0x1.9p0, 0x1.0fd9d5c093df5p-7, 0x1.0fd9d5c093df4p-7},
+                {0x1.90000000006bp0, 0x1.0fd9d5c05e5fdp-7, 0x1.0fd9d5c05e5fcp-7},
+                {-0x1.90000000006bp0, 0x1.0fd9d5c05e5fdp-7, 0x1.0fd9d5c05e5fcp-7},
+                {0x1.900c206d44162p6, 0x1.bc8be725417d8p-1, 0x1.bc8be725417d9p-1},
+                {-0x1.900c206d44162p6, 0x1.bc8be725417d8p-1, 0x1.bc8be725417d9p-1},
+                {0x1.900c2af7baef3p-19, 0x1.fffffffff63b6p-1, 0x1.fffffffff63b7p-1},
+                {-0x1.900c2af7baef3p-19, 0x1.fffffffff63b6p-1, 0x1.fffffffff63b7p-1},
+                {0x1.900f11bd8955dp6, 0x1.bd464c9352d11p-1, 0x1.bd464c9352d1p-1},
+                {-0x1.900f11bd8955dp6, 0x1.bd464c9352d11p-1, 0x1.bd464c9352d1p-1},
+                {0x1.910b35c3253d4p100, 0x1.fffffda85cdd1p-1, 0x1.fffffda85cddp-1},
+                {-0x1.910b35c3253d4p100, 0x1.fffffda85cdd1p-1, 0x1.fffffda85cddp-1},
+                {0x1.921fb54442d18p0, 0x1.1a62633145c07p-54, 0x1.1a62633145c06p-54},
+                {-0x1.921fb54442d18p0, 0x1.1a62633145c07p-54, 0x1.1a62633145c06p-54},
+                {0x1.922p0, -0x1.2aeef4b9ea1aep-18, -0x1.2aeef4b9ea1afp-18},
+                {-0x1.922p0, -0x1.2aeef4b9ea1aep-18, -0x1.2aeef4b9ea1afp-18},
+                {0x1.9220354442d18p0, -0x1.ffffffffd9048p-18, -0x1.ffffffffd9049p-18},
+                {-0x1.9220354442d18p0, -0x1.ffffffffd9048p-18, -0x1.ffffffffd9049p-18},
+                {0x1.9251f93aeb59dp12, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.9251f93aeb59dp12, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.943be221d909ap2, 0x1.ffb8c4d1f78a8p-1, 0x1.ffb8c4d1f78a9p-1},
+                {-0x1.943be221d909ap2, 0x1.ffb8c4d1f78a8p-1, 0x1.ffb8c4d1f78a9p-1},
+                {0x1.94af699302875p-7, 0x1.fff6011fdddabp-1, 0x1.fff6011fdddacp-1},
+                {-0x1.94af699302875p-7, 0x1.fff6011fdddabp-1, 0x1.fff6011fdddacp-1},
+                {0x1.999999ab7b0edp-2, 0x1.d7954e7a3ee99p-1, 0x1.d7954e7a3ee9ap-1},
+                {-0x1.999999ab7b0edp-2, 0x1.d7954e7a3ee99p-1, 0x1.d7954e7a3ee9ap-1},
+                {0x1.999999bd4190bp-2, 0x1.d7954e76c8e31p-1, 0x1.d7954e76c8e3p-1},
+                {-0x1.999999bd4190bp-2, 0x1.d7954e76c8e31p-1, 0x1.d7954e76c8e3p-1},
+                {0x1.9bd0f19479a24p2, 0x1.fa23cfb820224p-1, 0x1.fa23cfb820225p-1},
+                {-0x1.9bd0f19479a24p2, 0x1.fa23cfb820224p-1, 0x1.fa23cfb820225p-1},
+                {0x1.9c55835e7e83ep8, -0x1.6a09e667f3af1p-1, -0x1.6a09e667f3afp-1},
+                {-0x1.9c55835e7e83ep8, -0x1.6a09e667f3af1p-1, -0x1.6a09e667f3afp-1},
+                {0x1.9c9942b14448dp-7, 0x1.fff59c1255809p-1, 0x1.fff59c125580ap-1},
+                {-0x1.9c9942b14448dp-7, 0x1.fff59c1255809p-1, 0x1.fff59c125580ap-1},
+                {0x1.9d3d92485e2b5p523, 0x1.ffece5cab4ca5p-1, 0x1.ffece5cab4ca6p-1},
+                {-0x1.9d3d92485e2b5p523, 0x1.ffece5cab4ca5p-1, 0x1.ffece5cab4ca6p-1},
+                {0x1.a0d068341a08p1000, -0x1.ff55301d3a781p-5, -0x1.ff55301d3a78p-5},
+                {-0x1.a0d068341a08p1000, -0x1.ff55301d3a781p-5, -0x1.ff55301d3a78p-5},
+                {0x1.a7ep-1, 0x1.5a5615acd0dcp-1, 0x1.5a5615acd0dc1p-1},
+                {-0x1.a7ep-1, 0x1.5a5615acd0dcp-1, 0x1.5a5615acd0dc1p-1},
+                {0x1.a858343863965p119, 0x1.766ad27a1de5p-14, 0x1.766ad27a1de4fp-14},
+                {-0x1.a858343863965p119, 0x1.766ad27a1de5p-14, 0x1.766ad27a1de4fp-14},
+                {0x1.ab190633d88eap3, 0x1.6bd4d5be72494p-1, 0x1.6bd4d5be72493p-1},
+                {-0x1.ab190633d88eap3, 0x1.6bd4d5be72494p-1, 0x1.6bd4d5be72493p-1},
+                {0x1.af4bd2f4bd2fp-21, 0x1.ffffffffff4a5p-1, 0x1.ffffffffff4a6p-1},
+                {-0x1.af4bd2f4bd2fp-21, 0x1.ffffffffff4a5p-1, 0x1.ffffffffff4a6p-1},
+                {0x1.afa70300aee6p72, 0x1.7ff2934ad29a8p-1, 0x1.7ff2934ad29a7p-1},
+                {-0x1.afa70300aee6p72, 0x1.7ff2934ad29a8p-1, 0x1.7ff2934ad29a7p-1},
+                {0x1.b5ab427cffb4cp94, 0x1.ff866aebdce0ap-1, 0x1.ff866aebdce0bp-1},
+                {-0x1.b5ab427cffb4cp94, 0x1.ff866aebdce0ap-1, 0x1.ff866aebdce0bp-1},
+                {0x1.b951f1572eba5p23, -0x1.f54f5227a4e84p-60, -0x1.f54f5227a4e83p-60},
+                {-0x1.b951f1572eba5p23, -0x1.f54f5227a4e84p-60, -0x1.f54f5227a4e83p-60},
+                {0x1.b96e5b96e5b91p-8, 0x1.fffd06d35579cp-1, 0x1.fffd06d35579dp-1},
+                {-0x1.b96e5b96e5b91p-8, 0x1.fffd06d35579cp-1, 0x1.fffd06d35579dp-1},
+                {0x1.ba3b18395d17bp8, -0x1.7c4128e2aff4cp-1, -0x1.7c4128e2aff4bp-1},
+                {-0x1.ba3b18395d17bp8, -0x1.7c4128e2aff4cp-1, -0x1.7c4128e2aff4bp-1},
+                {0x1.bab62ed655019p970, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.bab62ed655019p970, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.bd55aa411ab46p-13, 0x1.ffffff3e53446p-1, 0x1.ffffff3e53447p-1},
+                {-0x1.bd55aa411ab46p-13, 0x1.ffffff3e53446p-1, 0x1.ffffff3e53447p-1},
+                {0x1.bd616d4fe95cdp36, -0x1.7fdb07b9f77ep-1, -0x1.7fdb07b9f77e1p-1},
+                {-0x1.bd616d4fe95cdp36, -0x1.7fdb07b9f77ep-1, -0x1.7fdb07b9f77e1p-1},
+                {0x1.beap-6, 0x1.ffcf4da76222dp-1, 0x1.ffcf4da76222cp-1},
+                {-0x1.beap-6, 0x1.ffcf4da76222dp-1, 0x1.ffcf4da76222cp-1},
+                {0x1.c11516af585a4p1, -0x1.ddee13357ec6fp-1, -0x1.ddee13357ec7p-1},
+                {-0x1.c11516af585a4p1, -0x1.ddee13357ec6fp-1, -0x1.ddee13357ec7p-1},
+                {0x1.c75e54de4c06ep2, 0x1.58cccec059da2p-1, 0x1.58cccec059da1p-1},
+                {-0x1.c75e54de4c06ep2, 0x1.58cccec059da2p-1, 0x1.58cccec059da1p-1},
+                {0x1.cb44e86bc192bp648, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.cb44e86bc192bp648, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.cb44e86bc192bp649, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.cb44e86bc192bp649, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.cd5a6f8762affp1, -0x1.ca281d7fe44bp-1, -0x1.ca281d7fe44b1p-1},
+                {-0x1.cd5a6f8762affp1, -0x1.ca281d7fe44bp-1, -0x1.ca281d7fe44b1p-1},
+                {0x1.d0cb95f02ad77p464, 0x1.e80ad4fe54c72p-5, 0x1.e80ad4fe54c71p-5},
+                {-0x1.d0cb95f02ad77p464, 0x1.e80ad4fe54c72p-5, 0x1.e80ad4fe54c71p-5},
+                {0x1.d31bd604903ap2, 0x1.0df8eb409efe4p-1, 0x1.0df8eb409efe3p-1},
+                {-0x1.d31bd604903ap2, 0x1.0df8eb409efe4p-1, 0x1.0df8eb409efe3p-1},
+                {0x1.d32f4610180f6p-5, 0x1.ff2ae968efe71p-1, 0x1.ff2ae968efe7p-1},
+                {-0x1.d32f4610180f6p-5, 0x1.ff2ae968efe71p-1, 0x1.ff2ae968efe7p-1},
+                {0x1.d96e058p488, -0x1.cec307a674d3fp-3, -0x1.cec307a674d3ep-3},
+                {-0x1.d96e058p488, -0x1.cec307a674d3fp-3, -0x1.cec307a674d3ep-3},
+                {0x1.db0803c392b4cp15, -0x1.ac8dbf9cdc955p-5, -0x1.ac8dbf9cdc954p-5},
+                {-0x1.db0803c392b4cp15, -0x1.ac8dbf9cdc955p-5, -0x1.ac8dbf9cdc954p-5},
+                {0x1.db0803c3ff51dp15, -0x1.ac94870ca6317p-5, -0x1.ac94870ca6316p-5},
+                {-0x1.db0803c3ff51dp15, -0x1.ac94870ca6317p-5, -0x1.ac94870ca6316p-5},
+                {0x1.dc4p-5, 0x1.ff229073fd8b6p-1, 0x1.ff229073fd8b5p-1},
+                {-0x1.dc4p-5, 0x1.ff229073fd8b6p-1, 0x1.ff229073fd8b5p-1},
+                {0x1.dcf73dcf73dccp-5, 0x1.ff21e5f976p-1, 0x1.ff21e5f975fffp-1},
+                {-0x1.dcf73dcf73dccp-5, 0x1.ff21e5f976p-1, 0x1.ff21e5f975fffp-1},
+                {0x1.dffffffffffffp-1, 0x1.2f011326420e5p-1, 0x1.2f011326420e6p-1},
+                {-0x1.dffffffffffffp-1, 0x1.2f011326420e5p-1, 0x1.2f011326420e6p-1},
+                {0x1.e123691a7c4bep26, 0x1.f72c8e16dbc79p-1, 0x1.f72c8e16dbc78p-1},
+                {-0x1.e123691a7c4bep26, 0x1.f72c8e16dbc79p-1, 0x1.f72c8e16dbc78p-1},
+                {0x1.e666666f9cf49p0, -0x1.4b0c6bb623f58p-2, -0x1.4b0c6bb623f57p-2},
+                {-0x1.e666666f9cf49p0, -0x1.4b0c6bb623f58p-2, -0x1.4b0c6bb623f57p-2},
+                {0x1.e83accfc50b7p995, 0x1.fd74b55875885p-1, 0x1.fd74b55875884p-1},
+                {-0x1.e83accfc50b7p995, 0x1.fd74b55875885p-1, 0x1.fd74b55875884p-1},
+                {0x1.e8ep-7, 0x1.fff169b6ab7d1p-1, 0x1.fff169b6ab7d2p-1},
+                {-0x1.e8ep-7, 0x1.fff169b6ab7d1p-1, 0x1.fff169b6ab7d2p-1},
+                {0x1.eaf5ea5317442p4, 0x1.7d39c9f1b0b3cp-1, 0x1.7d39c9f1b0b3dp-1},
+                {-0x1.eaf5ea5317442p4, 0x1.7d39c9f1b0b3cp-1, 0x1.7d39c9f1b0b3dp-1},
+                {0x1.eb0c2b00b1b83p4, 0x1.7f13af7081a68p-1, 0x1.7f13af7081a67p-1},
+                {-0x1.eb0c2b00b1b83p4, 0x1.7f13af7081a68p-1, 0x1.7f13af7081a67p-1},
+                {0x1.ebc6b555311c4p15, -0x1.7ad7b88a1fe1p-1, -0x1.7ad7b88a1fe0fp-1},
+                {-0x1.ebc6b555311c4p15, -0x1.7ad7b88a1fe1p-1, -0x1.7ad7b88a1fe0fp-1},
+                {0x1.ef7bdef7bdef2p239, 0x1.b06b2b58a2a24p-5, 0x1.b06b2b58a2a23p-5},
+                {-0x1.ef7bdef7bdef2p239, 0x1.b06b2b58a2a24p-5, 0x1.b06b2b58a2a23p-5},
+                {0x1.efbbeefbbeef8p15, 0x1.fe6ded53172a7p-1, 0x1.fe6ded53172a6p-1},
+                {-0x1.efbbeefbbeef8p15, 0x1.fe6ded53172a7p-1, 0x1.fe6ded53172a6p-1},
+                {0x1.f07c1f07c1ef7p239, -0x1.fe2bcb87a7e16p-1, -0x1.fe2bcb87a7e15p-1},
+                {-0x1.f07c1f07c1ef7p239, -0x1.fe2bcb87a7e16p-1, -0x1.fe2bcb87a7e15p-1},
+                {0x1.f0f2b5e060b29p1, -0x1.79d08d6b3a883p-1, -0x1.79d08d6b3a882p-1},
+                {-0x1.f0f2b5e060b29p1, -0x1.79d08d6b3a883p-1, -0x1.79d08d6b3a882p-1},
+                {0x1.f4p-3, 0x1.f0d11d321178ep-1, 0x1.f0d11d321178dp-1},
+                {-0x1.f4p-3, 0x1.f0d11d321178ep-1, 0x1.f0d11d321178dp-1},
+                {0x1.f43d49f947e87p9, 0x1.e3ff5b15f723ep-4, 0x1.e3ff5b15f723dp-4},
+                {-0x1.f43d49f947e87p9, 0x1.e3ff5b15f723ep-4, 0x1.e3ff5b15f723dp-4},
+                {0x1.f7fffffffffffp1, -0x1.6636c9f6a87aap-1, -0x1.6636c9f6a87a9p-1},
+                {-0x1.f7fffffffffffp1, -0x1.6636c9f6a87aap-1, -0x1.6636c9f6a87a9p-1},
+                {0x1.f8fffffffffffp-6, 0x1.ffc1be3309286p-1, 0x1.ffc1be3309285p-1},
+                {-0x1.f8fffffffffffp-6, 0x1.ffc1be3309286p-1, 0x1.ffc1be3309285p-1},
+                {0x1.f9p-6, 0x1.ffc1be3309285p-1, 0x1.ffc1be3309286p-1},
+                {-0x1.f9p-6, 0x1.ffc1be3309285p-1, 0x1.ffc1be3309286p-1},
+                {0x1.fa0236523ce54p344, -0x1.fffffffcab0d6p-1, -0x1.fffffffcab0d5p-1},
+                {-0x1.fa0236523ce54p344, -0x1.fffffffcab0d6p-1, -0x1.fffffffcab0d5p-1},
+                {0x1.fceab54d37dap-4, 0x1.fc0d98ace2308p-1, 0x1.fc0d98ace2309p-1},
+                {-0x1.fceab54d37dap-4, 0x1.fc0d98ace2308p-1, 0x1.fc0d98ace2309p-1},
+                {0x1.fd0072fffffffp2, -0x1.9589bca128b92p-4, -0x1.9589bca128b91p-4},
+                {-0x1.fd0072fffffffp2, -0x1.9589bca128b92p-4, -0x1.9589bca128b91p-4},
+                {0x1.fe0f827673422p62, -0x1.4d304b07fc898p-2, -0x1.4d304b07fc897p-2},
+                {-0x1.fe0f827673422p62, -0x1.4d304b07fc898p-2, -0x1.4d304b07fc897p-2},
+                {0x1.feb1f7920e248p-2, 0x1.c1a27ae836f13p-1, 0x1.c1a27ae836f12p-1},
+                {-0x1.feb1f7920e248p-2, 0x1.c1a27ae836f13p-1, 0x1.c1a27ae836f12p-1},
+                {0x1.feeffffffffc6p995, -0x1.936b64e955979p-1, -0x1.936b64e955978p-1},
+                {-0x1.feeffffffffc6p995, -0x1.936b64e955979p-1, -0x1.936b64e955978p-1},
+                {0x1.ff8ffffffffffp-7, 0x1.fff007147ea57p-1, 0x1.fff007147ea58p-1},
+                {-0x1.ff8ffffffffffp-7, 0x1.fff007147ea57p-1, 0x1.fff007147ea58p-1},
+                {0x1.ff8ffffffffffp-10, 0x1.ffffc01bfe443p-1, 0x1.ffffc01bfe442p-1},
+                {-0x1.ff8ffffffffffp-10, 0x1.ffffc01bfe443p-1, 0x1.ffffc01bfe442p-1},
+                {0x1.ff8ffffffffffp870, 0x1.7cc9fb75317aep-1, 0x1.7cc9fb75317afp-1},
+                {-0x1.ff8ffffffffffp870, 0x1.7cc9fb75317aep-1, 0x1.7cc9fb75317afp-1},
+                {0x1.ffcfff8p19, 0x1.d6aea48015589p-1, 0x1.d6aea48015588p-1},
+                {-0x1.ffcfff8p19, 0x1.d6aea48015589p-1, 0x1.d6aea48015588p-1},
+                {0x1.ffcfff8p365, -0x1.6a9972eee19bbp-2, -0x1.6a9972eee19bap-2},
+                {-0x1.ffcfff8p365, -0x1.6a9972eee19bbp-2, -0x1.6a9972eee19bap-2},
+                {0x1.ffcffffffff6cp720, -0x1.3aaa15f7544b7p-1, -0x1.3aaa15f7544b6p-1},
+                {-0x1.ffcffffffff6cp720, -0x1.3aaa15f7544b7p-1, -0x1.3aaa15f7544b6p-1},
+                {0x1.ffcfffffffff9p320, 0x1.3f164bce055c5p-1, 0x1.3f164bce055c4p-1},
+                {-0x1.ffcfffffffff9p320, 0x1.3f164bce055c5p-1, 0x1.3f164bce055c4p-1},
+                {0x1.ffcffffffffffp-11, 0x1.fffff002fff15p-1, 0x1.fffff002fff14p-1},
+                {-0x1.ffcffffffffffp-11, 0x1.fffff002fff15p-1, 0x1.fffff002fff14p-1},
+                {0x1.ffcffffffffffp405, -0x1.ffffff987f986p-1, -0x1.ffffff987f985p-1},
+                {-0x1.ffcffffffffffp405, -0x1.ffffff987f986p-1, -0x1.ffffff987f985p-1},
+                {0x1.ffcffffffffffp567, -0x1.ffff6235a25eep-1, -0x1.ffff6235a25edp-1},
+                {-0x1.ffcffffffffffp567, -0x1.ffff6235a25eep-1, -0x1.ffff6235a25edp-1},
+                {0x1.ffefff8ffffffp16, 0x1.fdf11ae4608b1p-3, 0x1.fdf11ae4608bp-3},
+                {-0x1.ffefff8ffffffp16, 0x1.fdf11ae4608b1p-3, 0x1.fdf11ae4608bp-3},
+                {0x1.ffeffffffffccp995, 0x1.8f5525ab4583cp-1, 0x1.8f5525ab4583dp-1},
+                {-0x1.ffeffffffffccp995, 0x1.8f5525ab4583cp-1, 0x1.8f5525ab4583dp-1},
+                {0x1.ffeffffffffffp77, 0x1.a0af44a45c057p-8, 0x1.a0af44a45c056p-8},
+                {-0x1.ffeffffffffffp77, 0x1.a0af44a45c057p-8, 0x1.a0af44a45c056p-8},
+                {0x1.ffeffffffffffp122, -0x1.df7546c31bf8dp-1, -0x1.df7546c31bf8cp-1},
+                {-0x1.ffeffffffffffp122, -0x1.df7546c31bf8dp-1, -0x1.df7546c31bf8cp-1},
+                {0x1.ffeffffffffffp179, -0x1.825a7bea27d5bp-1, -0x1.825a7bea27d5cp-1},
+                {-0x1.ffeffffffffffp179, -0x1.825a7bea27d5bp-1, -0x1.825a7bea27d5cp-1},
+                {0x1.ffeffffffffffp238, -0x1.1be2ab2078d54p-1, -0x1.1be2ab2078d55p-1},
+                {-0x1.ffeffffffffffp238, -0x1.1be2ab2078d54p-1, -0x1.1be2ab2078d55p-1},
+                {0x1.fff0000002511p492, -0x1.a4cc5f838f529p-7, -0x1.a4cc5f838f52ap-7},
+                {-0x1.fff0000002511p492, -0x1.a4cc5f838f529p-7, -0x1.a4cc5f838f52ap-7},
+                {0x1.fff1fffffffffp41, 0x1.f16437d6119f9p-10, 0x1.f16437d6119f8p-10},
+                {-0x1.fff1fffffffffp41, 0x1.f16437d6119f9p-10, 0x1.f16437d6119f8p-10},
+                {0x1.ffffc7fffffffp45, 0x1.898324c2f1cfcp-11, 0x1.898324c2f1cfdp-11},
+                {-0x1.ffffc7fffffffp45, 0x1.898324c2f1cfcp-11, 0x1.898324c2f1cfdp-11},
+                {0x1.ffffdf1ffffffp-3, 0x1.f0154c00688f8p-1, 0x1.f0154c00688f9p-1},
+                {-0x1.ffffdf1ffffffp-3, 0x1.f0154c00688f8p-1, 0x1.f0154c00688f9p-1},
+                {0x1.fffff8fffffffp-6, 0x1.ffc00157126a8p-1, 0x1.ffc00157126a7p-1},
+                {-0x1.fffff8fffffffp-6, 0x1.ffc00157126a8p-1, 0x1.ffc00157126a7p-1},
+                {0x1.fffffbfffffffp968, -0x1.e0d9f0f38c73fp-2, -0x1.e0d9f0f38c74p-2},
+                {-0x1.fffffbfffffffp968, -0x1.e0d9f0f38c73fp-2, -0x1.e0d9f0f38c74p-2},
+                {0x1.fffffcfffffffp40, 0x1.fff4699dd560bp-1, 0x1.fff4699dd560cp-1},
+                {-0x1.fffffcfffffffp40, 0x1.fff4699dd560bp-1, 0x1.fff4699dd560cp-1},
+                {0x1.ffffff000004p-5, 0x1.ff0015559f228p-1, 0x1.ff0015559f229p-1},
+                {-0x1.ffffff000004p-5, 0x1.ff0015559f228p-1, 0x1.ff0015559f229p-1},
+                {0x1.ffffff8p119, -0x1.9c6951cccd39cp-2, -0x1.9c6951cccd39bp-2},
+                {-0x1.ffffff8p119, -0x1.9c6951cccd39cp-2, -0x1.9c6951cccd39bp-2},
+                {0x1.ffffff8p192, -0x1.f2c2263590035p-1, -0x1.f2c2263590034p-1},
+                {-0x1.ffffff8p192, -0x1.f2c2263590035p-1, -0x1.f2c2263590034p-1},
+                {0x1.ffffff8p543, 0x1.c7884d6cfb551p-1, 0x1.c7884d6cfb552p-1},
+                {-0x1.ffffff8p543, 0x1.c7884d6cfb551p-1, 0x1.c7884d6cfb552p-1},
+                {0x1.ffffffc3fffffp500, 0x1.e66c79e776a1fp-2, 0x1.e66c79e776a1ep-2},
+                {-0x1.ffffffc3fffffp500, 0x1.e66c79e776a1fp-2, 0x1.e66c79e776a1ep-2},
+                {0x1.ffffffe1fffffp700, 0x1.c7c9a9c57c0b2p-3, 0x1.c7c9a9c57c0b3p-3},
+                {-0x1.ffffffe1fffffp700, 0x1.c7c9a9c57c0b2p-3, 0x1.c7c9a9c57c0b3p-3},
+                {0x1.ffffffff0f0ffp400, 0x1.7bb28daf5f9aep-1, 0x1.7bb28daf5f9adp-1},
+                {-0x1.ffffffff0f0ffp400, 0x1.7bb28daf5f9aep-1, 0x1.7bb28daf5f9adp-1},
+                {0x1.ffffffff3ffffp-4, 0x1.fc015527d8bb3p-1, 0x1.fc015527d8bb4p-1},
+                {-0x1.ffffffff3ffffp-4, 0x1.fc015527d8bb3p-1, 0x1.fc015527d8bb4p-1},
+                {0x1.ffffffff8ffffp3, -0x1.ea5257eb66e3cp-1, -0x1.ea5257eb66e3bp-1},
+                {-0x1.ffffffff8ffffp3, -0x1.ea5257eb66e3cp-1, -0x1.ea5257eb66e3bp-1},
+                {0x1.fffffffffbcffp1, -0x1.4eaa606dbef97p-1, -0x1.4eaa606dbef96p-1},
+                {-0x1.fffffffffbcffp1, -0x1.4eaa606dbef97p-1, -0x1.4eaa606dbef96p-1},
+                {0x1.fffffffffe0b5p720, -0x1.fc9cd6b5f0095p-1, -0x1.fc9cd6b5f0094p-1},
+                {-0x1.fffffffffe0b5p720, -0x1.fc9cd6b5f0095p-1, -0x1.fc9cd6b5f0094p-1},
+                {0x1.fffffffffe7ffp41, 0x1.e96ac045dd139p-3, 0x1.e96ac045dd138p-3},
+                {-0x1.fffffffffe7ffp41, 0x1.e96ac045dd139p-3, 0x1.e96ac045dd138p-3},
+                {0x1.fffffffffee09p720, -0x1.fcaf39cfb94d5p-1, -0x1.fcaf39cfb94d4p-1},
+                {-0x1.fffffffffee09p720, -0x1.fcaf39cfb94d5p-1, -0x1.fcaf39cfb94d4p-1},
+                {0x1.ffffffffffdffp40, 0x1.8432232a6d1dap-1, 0x1.8432232a6d1dbp-1},
+                {-0x1.ffffffffffdffp40, 0x1.8432232a6d1dap-1, 0x1.8432232a6d1dbp-1},
+                {0x1.ffffffffffeffp41, 0x1.9e375143139dap-6, 0x1.9e375143139d9p-6},
+                {-0x1.ffffffffffeffp41, 0x1.9e375143139dap-6, 0x1.9e375143139d9p-6},
+                {0x1.fffffffffff4ap-8, 0x1.fffc000155552p-1, 0x1.fffc000155553p-1},
+                {-0x1.fffffffffff4ap-8, 0x1.fffc000155552p-1, 0x1.fffc000155553p-1},
+                {0x1.fffffffffff78p920, 0x1.463a895c4ea5dp-1, 0x1.463a895c4ea5cp-1},
+                {-0x1.fffffffffff78p920, 0x1.463a895c4ea5dp-1, 0x1.463a895c4ea5cp-1},
+                {0x1.fffffffffffd5p995, 0x1.3c1a48635cf38p-1, 0x1.3c1a48635cf39p-1},
+                {-0x1.fffffffffffd5p995, 0x1.3c1a48635cf38p-1, 0x1.3c1a48635cf39p-1},
+                {0x1.fffffffffffe8p720, 0x1.91c4e0708bd48p-1, 0x1.91c4e0708bd49p-1},
+                {-0x1.fffffffffffe8p720, 0x1.91c4e0708bd48p-1, 0x1.91c4e0708bd49p-1},
+                {0x1.fffffffffffebp920, -0x1.3e15cb849b5eap-1, -0x1.3e15cb849b5ebp-1},
+                {-0x1.fffffffffffebp920, -0x1.3e15cb849b5eap-1, -0x1.3e15cb849b5ebp-1},
+                {0x1.ffffffffffff1p245, -0x1.816808349b80ep-1, -0x1.816808349b80dp-1},
+                {-0x1.ffffffffffff1p245, -0x1.816808349b80ep-1, -0x1.816808349b80dp-1},
+                {0x1.ffffffffffff4p845, 0x1.4699c814c5f07p-1, 0x1.4699c814c5f08p-1},
+                {-0x1.ffffffffffff4p845, 0x1.4699c814c5f07p-1, 0x1.4699c814c5f08p-1},
+                {0x1.ffffffffffff4p1020, -0x1.815e92b7a2a01p-1, -0x1.815e92b7a2a02p-1},
+                {-0x1.ffffffffffff4p1020, -0x1.815e92b7a2a01p-1, -0x1.815e92b7a2a02p-1},
+                {0x1.ffffffffffffcp45, -0x1.3e8d028153202p-10, -0x1.3e8d028153201p-10},
+                {-0x1.ffffffffffffcp45, -0x1.3e8d028153202p-10, -0x1.3e8d028153201p-10},
+                {0x1.ffffffffffffep105, 0x1.7d6765714c786p-1, 0x1.7d6765714c785p-1},
+                {-0x1.ffffffffffffep105, 0x1.7d6765714c786p-1, 0x1.7d6765714c785p-1},
+                {0x1.ffffffffffffep480, -0x1.f869fb14d2569p-3, -0x1.f869fb14d2568p-3},
+                {-0x1.ffffffffffffep480, -0x1.f869fb14d2569p-3, -0x1.f869fb14d2568p-3},
+                {0x1.ffffffffffffep970, -0x1.80a75b369d3c4p-1, -0x1.80a75b369d3c3p-1},
+                {-0x1.ffffffffffffep970, -0x1.80a75b369d3c4p-1, -0x1.80a75b369d3c3p-1},
+                {0x1.0000000000001p42, -0x1.9dba69e853bd8p-4, -0x1.9dba69e853bd7p-4},
+                {-0x1.0000000000001p42, -0x1.9dba69e853bd8p-4, -0x1.9dba69e853bd7p-4},
+                {-0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0p0, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x1.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x1.0p-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.0p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.fffffffffffffp-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.fffffffffffffp-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.fffffffffffffp-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.fffffffffffffp-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.0p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x1.0p-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x1.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.999999999999ap-13, 0x1.ffffff5c28f5dp-1, 0x1.ffffff5c28f5cp-1},
+                {-0x1.999999999999ap-13, 0x1.ffffff5c28f5dp-1, 0x1.ffffff5c28f5cp-1},
+                {0x1.999999999999ap-12, 0x1.fffffd70a3d79p-1, 0x1.fffffd70a3d7ap-1},
+                {-0x1.999999999999ap-12, 0x1.fffffd70a3d79p-1, 0x1.fffffd70a3d7ap-1},
+                {0x1.3333333333334p-11, 0x1.fffffa3d70a6ap-1, 0x1.fffffa3d70a69p-1},
+                {-0x1.3333333333334p-11, 0x1.fffffa3d70a6ap-1, 0x1.fffffa3d70a69p-1},
+                {0x1.999999999999ap-11, 0x1.fffff5c28f64ep-1, 0x1.fffff5c28f64fp-1},
+                {-0x1.999999999999ap-11, 0x1.fffff5c28f64ep-1, 0x1.fffff5c28f64fp-1},
+                {0x1.0p-10, 0x1.fffff00000155p-1, 0x1.fffff00000156p-1},
+                {-0x1.0p-10, 0x1.fffff00000155p-1, 0x1.fffff00000156p-1},
+                {0x1.3333333333333p-10, 0x1.ffffe8f5c2bbap-1, 0x1.ffffe8f5c2bb9p-1},
+                {-0x1.3333333333333p-10, 0x1.ffffe8f5c2bbap-1, 0x1.ffffe8f5c2bb9p-1},
+                {0x1.6666666666666p-10, 0x1.ffffe0a3d75c3p-1, 0x1.ffffe0a3d75c4p-1},
+                {-0x1.6666666666666p-10, 0x1.ffffe0a3d75c3p-1, 0x1.ffffe0a3d75c4p-1},
+                {0x1.9999999999999p-10, 0x1.ffffd70a3dfc7p-1, 0x1.ffffd70a3dfc8p-1},
+                {-0x1.9999999999999p-10, 0x1.ffffd70a3dfc7p-1, 0x1.ffffd70a3dfc8p-1},
+                {0x1.cccccccccccccp-10, 0x1.ffffcc28f6a28p-1, 0x1.ffffcc28f6a29p-1},
+                {-0x1.cccccccccccccp-10, 0x1.ffffcc28f6a28p-1, 0x1.ffffcc28f6a29p-1},
+                {0x1.0666666666666p-7, 0x1.fffbcc2a6e87p-1, 0x1.fffbcc2a6e86fp-1},
+                {-0x1.0666666666666p-7, 0x1.fffbcc2a6e87p-1, 0x1.fffbcc2a6e86fp-1},
+                {0x1.cccccccccccccp-7, 0x1.fff30a4b6fcc1p-1, 0x1.fff30a4b6fcc2p-1},
+                {-0x1.cccccccccccccp-7, 0x1.fff30a4b6fcc1p-1, 0x1.fff30a4b6fcc2p-1},
+                {0x1.4999999999999p-6, 0x1.ffe57a780f38cp-1, 0x1.ffe57a780f38dp-1},
+                {-0x1.4999999999999p-6, 0x1.ffe57a780f38cp-1, 0x1.ffe57a780f38dp-1},
+                {0x1.accccccccccccp-6, 0x1.ffd31cd0e1d63p-1, 0x1.ffd31cd0e1d62p-1},
+                {-0x1.accccccccccccp-6, 0x1.ffd31cd0e1d63p-1, 0x1.ffd31cd0e1d62p-1},
+                {0x1.08p-5, 0x1.ffbbf18207543p-1, 0x1.ffbbf18207542p-1},
+                {-0x1.08p-5, 0x1.ffbbf18207543p-1, 0x1.ffbbf18207542p-1},
+                {0x1.399999999999ap-5, 0x1.ff9ff8c3299f5p-1, 0x1.ff9ff8c3299f6p-1},
+                {-0x1.399999999999ap-5, 0x1.ff9ff8c3299f5p-1, 0x1.ff9ff8c3299f6p-1},
+                {0x1.6b33333333334p-5, 0x1.ff7f32d77c5b2p-1, 0x1.ff7f32d77c5b1p-1},
+                {-0x1.6b33333333334p-5, 0x1.ff7f32d77c5b2p-1, 0x1.ff7f32d77c5b1p-1},
+                {0x1.9cccccccccccep-5, 0x1.ff59a00dbc409p-1, 0x1.ff59a00dbc408p-1},
+                {-0x1.9cccccccccccep-5, 0x1.ff59a00dbc409p-1, 0x1.ff59a00dbc408p-1},
+                {0x1.ce66666666666p-5, 0x1.ff2f40c02e60fp-1, 0x1.ff2f40c02e61p-1},
+                {-0x1.ce66666666666p-5, 0x1.ff2f40c02e60fp-1, 0x1.ff2f40c02e61p-1},
+                {0x1.5e7fc4369bdadp-1, 0x1.8ca46c7d8975ep-1, 0x1.8ca46c7d8975fp-1},
+                {-0x1.5e7fc4369bdadp-1, 0x1.8ca46c7d8975ep-1, 0x1.8ca46c7d8975fp-1},
+                {0x1.4e7fc4369bdadp0, 0x1.0b5d3802fc799p-2, 0x1.0b5d3802fc79ap-2},
+                {-0x1.4e7fc4369bdadp0, 0x1.0b5d3802fc799p-2, 0x1.0b5d3802fc79ap-2},
+                {0x1.edbfa651e9c84p0, -0x1.66b96f53323afp-2, -0x1.66b96f53323bp-2},
+                {-0x1.edbfa651e9c84p0, -0x1.66b96f53323afp-2, -0x1.66b96f53323bp-2},
+                {0x1.467fc4369bdadp1, -0x1.a93554888c33p-1, -0x1.a93554888c32fp-1},
+                {-0x1.467fc4369bdadp1, -0x1.a93554888c33p-1, -0x1.a93554888c32fp-1},
+                {0x1.961fb54442d18p1, -0x1.ffc00155527d3p-1, -0x1.ffc00155527d2p-1},
+                {-0x1.961fb54442d18p1, -0x1.ffc00155527d3p-1, -0x1.ffc00155527d2p-1},
+                {0x1.e5bfa651e9c83p1, -0x1.96907c5c7c25cp-1, -0x1.96907c5c7c25bp-1},
+                {-0x1.e5bfa651e9c83p1, -0x1.96907c5c7c25cp-1, -0x1.96907c5c7c25bp-1},
+                {0x1.1aafcbafc85f7p2, -0x1.2a1e5a50f948dp-2, -0x1.2a1e5a50f948cp-2},
+                {-0x1.1aafcbafc85f7p2, -0x1.2a1e5a50f948dp-2, -0x1.2a1e5a50f948cp-2},
+                {0x1.427fc4369bdadp2, 0x1.4894f695dc56cp-2, 0x1.4894f695dc56bp-2},
+                {-0x1.427fc4369bdadp2, 0x1.4894f695dc56cp-2, 0x1.4894f695dc56bp-2},
+                {0x1.6a4fbcbd6f562p2, 0x1.a016ea3a692cep-1, 0x1.a016ea3a692cfp-1},
+                {-0x1.6a4fbcbd6f562p2, 0x1.a016ea3a692cep-1, 0x1.a016ea3a692cfp-1},
+                {0x1.6af2eff0a2896p2, 0x1.a30a69f5537ecp-1, 0x1.a30a69f5537ebp-1},
+                {-0x1.6af2eff0a2896p2, 0x1.a30a69f5537ecp-1, 0x1.a30a69f5537ebp-1},
+                {0x1.43c62a9d02414p2, 0x1.5bd62e8b04ad6p-2, 0x1.5bd62e8b04ad5p-2},
+                {-0x1.43c62a9d02414p2, 0x1.5bd62e8b04ad6p-2, 0x1.5bd62e8b04ad5p-2},
+                {0x1.1c99654961f92p2, -0x1.0cb71f671e634p-2, -0x1.0cb71f671e635p-2},
+                {-0x1.1c99654961f92p2, -0x1.0cb71f671e634p-2, -0x1.0cb71f671e635p-2},
+                {0x1.ead93feb8361fp1, -0x1.89d86aa8521c1p-1, -0x1.89d86aa8521c2p-1},
+                {-0x1.ead93feb8361fp1, -0x1.89d86aa8521c1p-1, -0x1.89d86aa8521c2p-1},
+                {0x1.9c7fb54442d1ap1, -0x1.fe51ac554a16bp-1, -0x1.fe51ac554a16ap-1},
+                {-0x1.9c7fb54442d1ap1, -0x1.fe51ac554a16bp-1, -0x1.fe51ac554a16ap-1},
+                {0x1.4e262a9d02415p1, -0x1.b97c04d08bc5dp-1, -0x1.b97c04d08bc5ep-1},
+                {-0x1.4e262a9d02415p1, -0x1.b97c04d08bc5dp-1, -0x1.b97c04d08bc5ep-1},
+                {0x1.ff993feb8362p0, -0x1.a8ac8a3e58f6dp-2, -0x1.a8ac8a3e58f6cp-2},
+                {-0x1.ff993feb8362p0, -0x1.a8ac8a3e58f6dp-2, -0x1.a8ac8a3e58f6cp-2},
+                {0x1.62e62a9d02416p0, 0x1.77a8b9b3d254bp-3, 0x1.77a8b9b3d254ap-3},
+                {-0x1.62e62a9d02416p0, 0x1.77a8b9b3d254bp-3, 0x1.77a8b9b3d254ap-3},
+                {0x1.8c662a9d02419p-1, 0x1.6e1061205dd79p-1, 0x1.6e1061205dd7ap-1},
+                {-0x1.8c662a9d02419p-1, 0x1.6e1061205dd79p-1, 0x1.6e1061205dd7ap-1},
+                {-0x1.a8aa1d11c44ffp0, -0x1.682f3cc3c7a09p-4, -0x1.682f3cc3c7a08p-4},
+                {0x1.a8aa1d11c44ffp0, -0x1.682f3cc3c7a09p-4, -0x1.682f3cc3c7a08p-4},
+                {-0x1.95ec8b9e03d54p0, -0x1.e6669a270c36dp-7, -0x1.e6669a270c36ep-7},
+                {0x1.95ec8b9e03d54p0, -0x1.e6669a270c36dp-7, -0x1.e6669a270c36ep-7},
+                {-0x1.832efa2a435a9p0, 0x1.ddd1ec25e209fp-5, 0x1.ddd1ec25e20ap-5},
+                {0x1.832efa2a435a9p0, 0x1.ddd1ec25e209fp-5, 0x1.ddd1ec25e20ap-5},
+                {-0x1.707168b682dfep0, 0x1.0cab9115640dap-3, 0x1.0cab9115640d9p-3},
+                {0x1.707168b682dfep0, 0x1.0cab9115640dap-3, 0x1.0cab9115640d9p-3},
+                {-0x1.5db3d742c2653p0, 0x1.a0723a95492eep-3, 0x1.a0723a95492edp-3},
+                {0x1.5db3d742c2653p0, 0x1.a0723a95492eep-3, 0x1.a0723a95492edp-3},
+                {-0x1.4af645cf01ea8p0, 0x1.18fee96a1a586p-2, 0x1.18fee96a1a585p-2},
+                {0x1.4af645cf01ea8p0, 0x1.18fee96a1a586p-2, 0x1.18fee96a1a585p-2},
+                {-0x1.3838b45b416fdp0, 0x1.6043621b13be3p-2, 0x1.6043621b13be2p-2},
+                {0x1.3838b45b416fdp0, 0x1.6043621b13be3p-2, 0x1.6043621b13be2p-2},
+                {-0x1.257b22e780f52p0, 0x1.a5a4ccf40d9dap-2, 0x1.a5a4ccf40d9d9p-2},
+                {0x1.257b22e780f52p0, 0x1.a5a4ccf40d9dap-2, 0x1.a5a4ccf40d9d9p-2},
+                {-0x1.12bd9173c07abp0, 0x1.e8c405f36f85cp-2, 0x1.e8c405f36f85bp-2},
+                {0x1.12bd9173c07abp0, 0x1.e8c405f36f85cp-2, 0x1.e8c405f36f85bp-2},
+                {-0x1.ea5c3ed5b385p-1, 0x1.26976a6c4e0f8p-1, 0x1.26976a6c4e0f9p-1},
+                {0x1.ea5c3ed5b385p-1, 0x1.26976a6c4e0f8p-1, 0x1.26976a6c4e0f9p-1},
+                {-0x1.d4b87dab670ap-1, 0x1.3805a1882009fp-1, 0x1.3805a188200ap-1},
+                {0x1.d4b87dab670ap-1, 0x1.3805a1882009fp-1, 0x1.3805a188200ap-1},
+                {-0x1.bf14bc811a8fp-1, 0x1.48e52e0a65bcbp-1, 0x1.48e52e0a65bccp-1},
+                {0x1.bf14bc811a8fp-1, 0x1.48e52e0a65bcbp-1, 0x1.48e52e0a65bccp-1},
+                {-0x1.a970fb56ce14p-1, 0x1.592e58ea0a9efp-1, 0x1.592e58ea0a9eep-1},
+                {0x1.a970fb56ce14p-1, 0x1.592e58ea0a9efp-1, 0x1.592e58ea0a9eep-1},
+                {-0x1.93cd3a2c8199p-1, 0x1.68d9afe052d1fp-1, 0x1.68d9afe052d2p-1},
+                {0x1.93cd3a2c8199p-1, 0x1.68d9afe052d1fp-1, 0x1.68d9afe052d2p-1},
+                {-0x1.7e297902351ep-1, 0x1.77e008d0775e7p-1, 0x1.77e008d0775e8p-1},
+                {0x1.7e297902351ep-1, 0x1.77e008d0775e7p-1, 0x1.77e008d0775e8p-1},
+                {-0x1.6885b7d7e8a3p-1, 0x1.863a850e438fep-1, 0x1.863a850e438ffp-1},
+                {0x1.6885b7d7e8a3p-1, 0x1.863a850e438fep-1, 0x1.863a850e438ffp-1},
+                {-0x1.52e1f6ad9c28p-1, 0x1.93e2948233fcep-1, 0x1.93e2948233fcfp-1},
+                {0x1.52e1f6ad9c28p-1, 0x1.93e2948233fcep-1, 0x1.93e2948233fcfp-1},
+                {-0x1.3d3e35834fadp-1, 0x1.a0d1f8a9a791dp-1, 0x1.a0d1f8a9a791ep-1},
+                {0x1.3d3e35834fadp-1, 0x1.a0d1f8a9a791dp-1, 0x1.a0d1f8a9a791ep-1},
+                {-0x1.0a0b02501c799p-1, 0x1.bc6bd861e13dep-1, 0x1.bc6bd861e13dfp-1},
+                {0x1.0a0b02501c799p-1, 0x1.bc6bd861e13dep-1, 0x1.bc6bd861e13dfp-1},
+                {-0x1.d8f7208e6b82cp-2, 0x1.ca59c6fa3d9cep-1, 0x1.ca59c6fa3d9cfp-1},
+                {0x1.d8f7208e6b82cp-2, 0x1.ca59c6fa3d9cep-1, 0x1.ca59c6fa3d9cfp-1},
+                {-0x1.9dd83c7c9e126p-2, 0x1.d6c0b125791dp-1, 0x1.d6c0b125791cfp-1},
+                {0x1.9dd83c7c9e126p-2, 0x1.d6c0b125791dp-1, 0x1.d6c0b125791cfp-1},
+                {-0x1.62b9586ad0a2p-2, 0x1.e196026182986p-1, 0x1.e196026182985p-1},
+                {0x1.62b9586ad0a2p-2, 0x1.e196026182986p-1, 0x1.e196026182985p-1},
+                {-0x1.279a74590331ap-2, 0x1.ead07cc635696p-1, 0x1.ead07cc635697p-1},
+                {0x1.279a74590331ap-2, 0x1.ead07cc635696p-1, 0x1.ead07cc635697p-1},
+                {-0x1.d8f7208e6b829p-3, 0x1.f26840e7b2189p-1, 0x1.f26840e7b2188p-1},
+                {0x1.d8f7208e6b829p-3, 0x1.f26840e7b2189p-1, 0x1.f26840e7b2188p-1},
+                {-0x1.62b9586ad0a1ep-3, 0x1.f856d48db797ep-1, 0x1.f856d48db797dp-1},
+                {0x1.62b9586ad0a1ep-3, 0x1.f856d48db797ep-1, 0x1.f856d48db797dp-1},
+                {-0x1.d8f7208e6b826p-4, 0x1.fc97283a42479p-1, 0x1.fc97283a4247ap-1},
+                {0x1.d8f7208e6b826p-4, 0x1.fc97283a42479p-1, 0x1.fc97283a4247ap-1},
+                {-0x1.d8f7208e6b82dp-5, 0x1.ff259b7ab9f5p-1, 0x1.ff259b7ab9f4fp-1},
+                {0x1.d8f7208e6b82dp-5, 0x1.ff259b7ab9f5p-1, 0x1.ff259b7ab9f4fp-1},
+                {0x1.d8f7208e6b82dp-5, 0x1.ff259b7ab9f5p-1, 0x1.ff259b7ab9f4fp-1},
+                {-0x1.d8f7208e6b82dp-5, 0x1.ff259b7ab9f5p-1, 0x1.ff259b7ab9f4fp-1},
+                {0x1.d8f7208e6b82dp-4, 0x1.fc97283a42479p-1, 0x1.fc97283a4247ap-1},
+                {-0x1.d8f7208e6b82dp-4, 0x1.fc97283a42479p-1, 0x1.fc97283a4247ap-1},
+                {0x1.62b9586ad0a22p-3, 0x1.f856d48db797ep-1, 0x1.f856d48db797dp-1},
+                {-0x1.62b9586ad0a22p-3, 0x1.f856d48db797ep-1, 0x1.f856d48db797dp-1},
+                {0x1.d8f7208e6b82dp-3, 0x1.f26840e7b2189p-1, 0x1.f26840e7b2188p-1},
+                {-0x1.d8f7208e6b82dp-3, 0x1.f26840e7b2189p-1, 0x1.f26840e7b2188p-1},
+                {0x1.279a74590331cp-2, 0x1.ead07cc635696p-1, 0x1.ead07cc635697p-1},
+                {-0x1.279a74590331cp-2, 0x1.ead07cc635696p-1, 0x1.ead07cc635697p-1},
+                {0x1.62b9586ad0a22p-2, 0x1.e196026182985p-1, 0x1.e196026182986p-1},
+                {-0x1.62b9586ad0a22p-2, 0x1.e196026182985p-1, 0x1.e196026182986p-1},
+                {0x1.9dd83c7c9e128p-2, 0x1.d6c0b125791dp-1, 0x1.d6c0b125791cfp-1},
+                {-0x1.9dd83c7c9e128p-2, 0x1.d6c0b125791dp-1, 0x1.d6c0b125791cfp-1},
+                {0x1.d8f7208e6b82ep-2, 0x1.ca59c6fa3d9cep-1, 0x1.ca59c6fa3d9cdp-1},
+                {-0x1.d8f7208e6b82ep-2, 0x1.ca59c6fa3d9cep-1, 0x1.ca59c6fa3d9cdp-1},
+                {0x1.0a0b02501c799p-1, 0x1.bc6bd861e13dep-1, 0x1.bc6bd861e13dfp-1},
+                {-0x1.0a0b02501c799p-1, 0x1.bc6bd861e13dep-1, 0x1.bc6bd861e13dfp-1},
+                {0x1.3d3e35834faccp-1, 0x1.a0d1f8a9a792p-1, 0x1.a0d1f8a9a791fp-1},
+                {-0x1.3d3e35834faccp-1, 0x1.a0d1f8a9a792p-1, 0x1.a0d1f8a9a791fp-1},
+                {0x1.52e1f6ad9c27cp-1, 0x1.93e2948233fd1p-1, 0x1.93e2948233fdp-1},
+                {-0x1.52e1f6ad9c27cp-1, 0x1.93e2948233fd1p-1, 0x1.93e2948233fdp-1},
+                {0x1.6885b7d7e8a2cp-1, 0x1.863a850e439p-1, 0x1.863a850e43901p-1},
+                {-0x1.6885b7d7e8a2cp-1, 0x1.863a850e439p-1, 0x1.863a850e43901p-1},
+                {0x1.7e297902351dcp-1, 0x1.77e008d0775eap-1, 0x1.77e008d0775e9p-1},
+                {-0x1.7e297902351dcp-1, 0x1.77e008d0775eap-1, 0x1.77e008d0775e9p-1},
+                {0x1.93cd3a2c8198cp-1, 0x1.68d9afe052d22p-1, 0x1.68d9afe052d21p-1},
+                {-0x1.93cd3a2c8198cp-1, 0x1.68d9afe052d22p-1, 0x1.68d9afe052d21p-1},
+                {0x1.a970fb56ce13cp-1, 0x1.592e58ea0a9f2p-1, 0x1.592e58ea0a9f1p-1},
+                {-0x1.a970fb56ce13cp-1, 0x1.592e58ea0a9f2p-1, 0x1.592e58ea0a9f1p-1},
+                {0x1.bf14bc811a8ecp-1, 0x1.48e52e0a65bcep-1, 0x1.48e52e0a65bcfp-1},
+                {-0x1.bf14bc811a8ecp-1, 0x1.48e52e0a65bcep-1, 0x1.48e52e0a65bcfp-1},
+                {0x1.d4b87dab6709cp-1, 0x1.3805a188200a2p-1, 0x1.3805a188200a3p-1},
+                {-0x1.d4b87dab6709cp-1, 0x1.3805a188200a2p-1, 0x1.3805a188200a3p-1},
+                {0x1.ea5c3ed5b384cp-1, 0x1.26976a6c4e0fcp-1, 0x1.26976a6c4e0fbp-1},
+                {-0x1.ea5c3ed5b384cp-1, 0x1.26976a6c4e0fcp-1, 0x1.26976a6c4e0fbp-1},
+                {0x1.12bd9173c07abp0, 0x1.e8c405f36f85cp-2, 0x1.e8c405f36f85bp-2},
+                {-0x1.12bd9173c07abp0, 0x1.e8c405f36f85cp-2, 0x1.e8c405f36f85bp-2},
+                {0x1.257b22e780f56p0, 0x1.a5a4ccf40d9cbp-2, 0x1.a5a4ccf40d9ccp-2},
+                {-0x1.257b22e780f56p0, 0x1.a5a4ccf40d9cbp-2, 0x1.a5a4ccf40d9ccp-2},
+                {0x1.3838b45b41701p0, 0x1.6043621b13bd4p-2, 0x1.6043621b13bd3p-2},
+                {-0x1.3838b45b41701p0, 0x1.6043621b13bd4p-2, 0x1.6043621b13bd3p-2},
+                {0x1.4af645cf01eacp0, 0x1.18fee96a1a576p-2, 0x1.18fee96a1a577p-2},
+                {-0x1.4af645cf01eacp0, 0x1.18fee96a1a576p-2, 0x1.18fee96a1a577p-2},
+                {0x1.5db3d742c2657p0, 0x1.a0723a95492cfp-3, 0x1.a0723a95492cep-3},
+                {-0x1.5db3d742c2657p0, 0x1.a0723a95492cfp-3, 0x1.a0723a95492cep-3},
+                {0x1.707168b682e02p0, 0x1.0cab9115640bap-3, 0x1.0cab9115640b9p-3},
+                {-0x1.707168b682e02p0, 0x1.0cab9115640bap-3, 0x1.0cab9115640b9p-3},
+                {0x1.832efa2a435adp0, 0x1.ddd1ec25e201fp-5, 0x1.ddd1ec25e202p-5},
+                {-0x1.832efa2a435adp0, 0x1.ddd1ec25e201fp-5, 0x1.ddd1ec25e202p-5},
+                {0x1.95ec8b9e03d58p0, -0x1.e6669a270c56dp-7, -0x1.e6669a270c56ep-7},
+                {-0x1.95ec8b9e03d58p0, -0x1.e6669a270c56dp-7, -0x1.e6669a270c56ep-7},
+                {0x1.a8aa1d11c44ffp0, -0x1.682f3cc3c7a09p-4, -0x1.682f3cc3c7a08p-4},
+                {-0x1.a8aa1d11c44ffp0, -0x1.682f3cc3c7a09p-4, -0x1.682f3cc3c7a08p-4},
+                {0x1.04aff6d330942p0, 0x1.0cb3469a29ea6p-1, 0x1.0cb3469a29ea7p-1},
+                {-0x1.04aff6d330942p0, 0x1.0cb3469a29ea6p-1, 0x1.0cb3469a29ea7p-1},
+                {0x1.04b09e98dcdb4p0, 0x1.0cb228fa7f811p-1, 0x1.0cb228fa7f812p-1},
+                {-0x1.04b09e98dcdb4p0, 0x1.0cb228fa7f811p-1, 0x1.0cb228fa7f812p-1},
+                {0x1.04b1465e89226p0, 0x1.0cb10b5a61b06p-1, 0x1.0cb10b5a61b05p-1},
+                {-0x1.04b1465e89226p0, 0x1.0cb10b5a61b06p-1, 0x1.0cb10b5a61b05p-1},
+                {0x1.04b1ee2435698p0, 0x1.0cafedb9d078bp-1, 0x1.0cafedb9d078ap-1},
+                {-0x1.04b1ee2435698p0, 0x1.0cafedb9d078bp-1, 0x1.0cafedb9d078ap-1},
+                {0x1.04b295e9e1b0ap0, 0x1.0caed018cbda8p-1, 0x1.0caed018cbda7p-1},
+                {-0x1.04b295e9e1b0ap0, 0x1.0caed018cbda8p-1, 0x1.0caed018cbda7p-1},
+                {0x1.04b33daf8df7cp0, 0x1.0cadb27753d65p-1, 0x1.0cadb27753d66p-1},
+                {-0x1.04b33daf8df7cp0, 0x1.0cadb27753d65p-1, 0x1.0cadb27753d66p-1},
+                {0x1.04b3e5753a3eep0, 0x1.0cac94d5686cbp-1, 0x1.0cac94d5686cap-1},
+                {-0x1.04b3e5753a3eep0, 0x1.0cac94d5686cbp-1, 0x1.0cac94d5686cap-1},
+                {0x1.04b48d3ae686p0, 0x1.0cab7733099dfp-1, 0x1.0cab7733099ep-1},
+                {-0x1.04b48d3ae686p0, 0x1.0cab7733099dfp-1, 0x1.0cab7733099ep-1},
+                {0x1.04b5350092ccfp0, 0x1.0caa5990376bp-1, 0x1.0caa5990376b1p-1},
+                {-0x1.04b5350092ccfp0, 0x1.0caa5990376bp-1, 0x1.0caa5990376b1p-1},
+                {-0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0p0, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.279a74590331bp-1, 0x1.ad02c771c35edp-1, 0x1.ad02c771c35eep-1},
+                {-0x1.279a74590331bp-1, 0x1.ad02c771c35edp-1, 0x1.ad02c771c35eep-1},
+                {0x1.279a74590331cp-1, 0x1.ad02c771c35edp-1, 0x1.ad02c771c35ecp-1},
+                {-0x1.279a74590331cp-1, 0x1.ad02c771c35edp-1, 0x1.ad02c771c35ecp-1},
+                {0x1.279a74590331dp-1, 0x1.ad02c771c35ecp-1, 0x1.ad02c771c35edp-1},
+                {-0x1.279a74590331dp-1, 0x1.ad02c771c35ecp-1, 0x1.ad02c771c35edp-1},
+                {0x1.bb67ae8584ca9p0, -0x1.48d1ddd2b2b4p-3, -0x1.48d1ddd2b2b3fp-3},
+                {-0x1.bb67ae8584ca9p0, -0x1.48d1ddd2b2b4p-3, -0x1.48d1ddd2b2b3fp-3},
+                {0x1.bb67ae8584caap0, -0x1.48d1ddd2b2b47p-3, -0x1.48d1ddd2b2b48p-3},
+                {-0x1.bb67ae8584caap0, -0x1.48d1ddd2b2b47p-3, -0x1.48d1ddd2b2b48p-3},
+                {0x1.bb67ae8584cabp0, -0x1.48d1ddd2b2b4fp-3, -0x1.48d1ddd2b2b5p-3},
+                {-0x1.bb67ae8584cabp0, -0x1.48d1ddd2b2b4fp-3, -0x1.48d1ddd2b2b5p-3},
+                {0x1.bffffffffffffp-2, 0x1.cfc6cfa52adap-1, 0x1.cfc6cfa52ad9fp-1},
+                {-0x1.bffffffffffffp-2, 0x1.cfc6cfa52adap-1, 0x1.cfc6cfa52ad9fp-1},
+                {0x1.cp-2, 0x1.cfc6cfa52ad9fp-1, 0x1.cfc6cfa52adap-1},
+                {-0x1.cp-2, 0x1.cfc6cfa52ad9fp-1, 0x1.cfc6cfa52adap-1},
+                {0x1.c000000000001p-2, 0x1.cfc6cfa52ad9fp-1, 0x1.cfc6cfa52adap-1},
+                {-0x1.c000000000001p-2, 0x1.cfc6cfa52ad9fp-1, 0x1.cfc6cfa52adap-1},
+                {0x1.5ffffffffffffp-1, 0x1.8bb105a5dc901p-1, 0x1.8bb105a5dc902p-1},
+                {-0x1.5ffffffffffffp-1, 0x1.8bb105a5dc901p-1, 0x1.8bb105a5dc902p-1},
+                {0x1.6p-1, 0x1.8bb105a5dc9p-1, 0x1.8bb105a5dc901p-1},
+                {-0x1.6p-1, 0x1.8bb105a5dc9p-1, 0x1.8bb105a5dc901p-1},
+                {0x1.6000000000001p-1, 0x1.8bb105a5dc9p-1, 0x1.8bb105a5dc8ffp-1},
+                {-0x1.6000000000001p-1, 0x1.8bb105a5dc9p-1, 0x1.8bb105a5dc8ffp-1},
+                {0x1.2ffffffffffffp0, 0x1.7ef4842f0bcd1p-2, 0x1.7ef4842f0bcd2p-2},
+                {-0x1.2ffffffffffffp0, 0x1.7ef4842f0bcd1p-2, 0x1.7ef4842f0bcd2p-2},
+                {0x1.3p0, 0x1.7ef4842f0bccdp-2, 0x1.7ef4842f0bccep-2},
+                {-0x1.3p0, 0x1.7ef4842f0bccdp-2, 0x1.7ef4842f0bccep-2},
+                {0x1.3000000000001p0, 0x1.7ef4842f0bccap-2, 0x1.7ef4842f0bcc9p-2},
+                {-0x1.3000000000001p0, 0x1.7ef4842f0bccap-2, 0x1.7ef4842f0bcc9p-2},
+                {0x1.37fffffffffffp1, -0x1.863efa361dc22p-1, -0x1.863efa361dc23p-1},
+                {-0x1.37fffffffffffp1, -0x1.863efa361dc22p-1, -0x1.863efa361dc23p-1},
+                {0x1.38p1, -0x1.863efa361dc25p-1, -0x1.863efa361dc26p-1},
+                {-0x1.38p1, -0x1.863efa361dc25p-1, -0x1.863efa361dc26p-1},
+                {0x1.3800000000001p1, -0x1.863efa361dc28p-1, -0x1.863efa361dc27p-1},
+                {-0x1.3800000000001p1, -0x1.863efa361dc28p-1, -0x1.863efa361dc27p-1},
+                {0x1.069c8b46b3792p-4, 0x1.fef2b2d21cf6cp-1, 0x1.fef2b2d21cf6dp-1},
+                {-0x1.069c8b46b3792p-4, 0x1.fef2b2d21cf6cp-1, 0x1.fef2b2d21cf6dp-1},
+                {0x1.069c8b46b3792p-3, 0x1.fbcbe693bd8edp-1, 0x1.fbcbe693bd8ecp-1},
+                {-0x1.069c8b46b3792p-3, 0x1.fbcbe693bd8edp-1, 0x1.fbcbe693bd8ecp-1},
+                {0x1.89ead0ea0d35bp-3, 0x1.f68eebfcbb5e8p-1, 0x1.f68eebfcbb5e9p-1},
+                {-0x1.89ead0ea0d35bp-3, 0x1.f68eebfcbb5e8p-1, 0x1.f68eebfcbb5e9p-1},
+                {0x1.069c8b46b3792p-2, 0x1.ef4145b4aedp-1, 0x1.ef4145b4aecffp-1},
+                {-0x1.069c8b46b3792p-2, 0x1.ef4145b4aedp-1, 0x1.ef4145b4aecffp-1},
+                {0x1.4843ae1860576p-2, 0x1.e5eaa286fbbc6p-1, 0x1.e5eaa286fbbc7p-1},
+                {-0x1.4843ae1860576p-2, 0x1.e5eaa286fbbc6p-1, 0x1.e5eaa286fbbc7p-1},
+                {0x1.89ead0ea0d35ap-2, 0x1.da94d54dd4c08p-1, 0x1.da94d54dd4c09p-1},
+                {-0x1.89ead0ea0d35ap-2, 0x1.da94d54dd4c08p-1, 0x1.da94d54dd4c09p-1},
+                {0x1.cb91f3bbba13ep-2, 0x1.cd4bca9cb5c71p-1, 0x1.cd4bca9cb5c72p-1},
+                {-0x1.cb91f3bbba13ep-2, 0x1.cd4bca9cb5c71p-1, 0x1.cd4bca9cb5c72p-1},
+                {0x1.069c8b46b3791p-1, 0x1.be1d7c3534c4p-1, 0x1.be1d7c3534c41p-1},
+                {-0x1.069c8b46b3791p-1, 0x1.be1d7c3534c4p-1, 0x1.be1d7c3534c41p-1},
+                {0x1.27701caf89e83p-1, 0x1.ad19e2535aa96p-1, 0x1.ad19e2535aa97p-1},
+                {-0x1.27701caf89e83p-1, 0x1.ad19e2535aa96p-1, 0x1.ad19e2535aa97p-1},
+                {0x1.4843ae1860575p-1, 0x1.9a52e2e0fbcb4p-1, 0x1.9a52e2e0fbcb3p-1},
+                {-0x1.4843ae1860575p-1, 0x1.9a52e2e0fbcb4p-1, 0x1.9a52e2e0fbcb3p-1},
+                {0x1.69173f8136c67p-1, 0x1.85dc3ea1bbceap-1, 0x1.85dc3ea1bbce9p-1},
+                {-0x1.69173f8136c67p-1, 0x1.85dc3ea1bbceap-1, 0x1.85dc3ea1bbce9p-1},
+                {0x1.89ead0ea0d359p-1, 0x1.6fcb7c6b8b91ap-1, 0x1.6fcb7c6b8b919p-1},
+                {-0x1.89ead0ea0d359p-1, 0x1.6fcb7c6b8b91ap-1, 0x1.6fcb7c6b8b919p-1},
+                {0x1.aabe6252e3a4bp-1, 0x1.5837d2817cf3p-1, 0x1.5837d2817cf31p-1},
+                {-0x1.aabe6252e3a4bp-1, 0x1.5837d2817cf3p-1, 0x1.5837d2817cf31p-1},
+                {0x1.cb91f3bbba13dp-1, 0x1.3f3a0e28bedd4p-1, 0x1.3f3a0e28bedd5p-1},
+                {-0x1.cb91f3bbba13dp-1, 0x1.3f3a0e28bedd4p-1, 0x1.3f3a0e28bedd5p-1},
+                {0x1.ec6585249082fp-1, 0x1.24ec799171643p-1, 0x1.24ec799171642p-1},
+                {-0x1.ec6585249082fp-1, 0x1.24ec799171643p-1, 0x1.24ec799171642p-1},
+                {0x1.069c8b46b3791p0, 0x1.096ac02ec42c8p-1, 0x1.096ac02ec42c9p-1},
+                {-0x1.069c8b46b3791p0, 0x1.096ac02ec42c8p-1, 0x1.096ac02ec42c9p-1},
+                {0x1.170653fb1eb0ap0, 0x1.d9a3a336edb76p-2, 0x1.d9a3a336edb77p-2},
+                {-0x1.170653fb1eb0ap0, 0x1.d9a3a336edb76p-2, 0x1.d9a3a336edb77p-2},
+                {0x1.27701caf89e83p0, 0x1.9e7f8652b4758p-2, 0x1.9e7f8652b4759p-2},
+                {-0x1.27701caf89e83p0, 0x1.9e7f8652b4758p-2, 0x1.9e7f8652b4759p-2},
+                {0x1.37d9e563f51fcp0, 0x1.61a76077aee08p-2, 0x1.61a76077aee07p-2},
+                {-0x1.37d9e563f51fcp0, 0x1.61a76077aee08p-2, 0x1.61a76077aee07p-2},
+                {0x1.4843ae1860575p0, 0x1.235b331d8f749p-2, 0x1.235b331d8f748p-2},
+                {-0x1.4843ae1860575p0, 0x1.235b331d8f749p-2, 0x1.235b331d8f748p-2},
+                {0x1.58ad76cccb8eep0, 0x1.c7b90e3024594p-3, 0x1.c7b90e3024593p-3},
+                {-0x1.58ad76cccb8eep0, 0x1.c7b90e3024594p-3, 0x1.c7b90e3024593p-3},
+                {0x1.69173f8136c67p0, 0x1.46dc4f4ce83dap-3, 0x1.46dc4f4ce83dbp-3},
+                {-0x1.69173f8136c67p0, 0x1.46dc4f4ce83dap-3, 0x1.46dc4f4ce83dbp-3},
+                {0x1.79810835a1fep0, 0x1.894f70befbb9ap-4, 0x1.894f70befbb99p-4},
+                {-0x1.79810835a1fep0, 0x1.894f70befbb9ap-4, 0x1.894f70befbb99p-4},
+                {0x1.89ead0ea0d359p0, 0x1.069107ae9333p-5, 0x1.069107ae9332fp-5},
+                {-0x1.89ead0ea0d359p0, 0x1.069107ae9333p-5, 0x1.069107ae9332fp-5},
+                {0x1.9a54999e786d2p0, -0x1.069107ae9327ep-5, -0x1.069107ae9327fp-5},
+                {-0x1.9a54999e786d2p0, -0x1.069107ae9327ep-5, -0x1.069107ae9327fp-5},
+                {0x1.aabe6252e3a4bp0, -0x1.894f70befbb41p-4, -0x1.894f70befbb42p-4},
+                {-0x1.aabe6252e3a4bp0, -0x1.894f70befbb41p-4, -0x1.894f70befbb42p-4},
+                {0x1.bb282b074edc4p0, -0x1.46dc4f4ce83afp-3, -0x1.46dc4f4ce83aep-3},
+                {-0x1.bb282b074edc4p0, -0x1.46dc4f4ce83afp-3, -0x1.46dc4f4ce83aep-3},
+                {0x1.cb91f3bbba13dp0, -0x1.c7b90e3024569p-3, -0x1.c7b90e3024568p-3},
+                {-0x1.cb91f3bbba13dp0, -0x1.c7b90e3024569p-3, -0x1.c7b90e3024568p-3},
+                {0x1.dbfbbc70254b6p0, -0x1.235b331d8f734p-2, -0x1.235b331d8f733p-2},
+                {-0x1.dbfbbc70254b6p0, -0x1.235b331d8f734p-2, -0x1.235b331d8f733p-2},
+                {0x1.ec6585249082fp0, -0x1.61a76077aedf3p-2, -0x1.61a76077aedf2p-2},
+                {-0x1.ec6585249082fp0, -0x1.61a76077aedf3p-2, -0x1.61a76077aedf2p-2},
+                {0x1.fccf4dd8fbba8p0, -0x1.9e7f8652b4744p-2, -0x1.9e7f8652b4743p-2},
+                {-0x1.fccf4dd8fbba8p0, -0x1.9e7f8652b4744p-2, -0x1.9e7f8652b4743p-2},
+                {0x1.069c8b46b3791p1, -0x1.d9a3a336edb66p-2, -0x1.d9a3a336edb65p-2},
+                {-0x1.069c8b46b3791p1, -0x1.d9a3a336edb66p-2, -0x1.d9a3a336edb65p-2},
+                {0x1.0ed16fa0e914ep1, -0x1.096ac02ec42c2p-1, -0x1.096ac02ec42c3p-1},
+                {-0x1.0ed16fa0e914ep1, -0x1.096ac02ec42c2p-1, -0x1.096ac02ec42c3p-1},
+                {0x1.170653fb1eb0bp1, -0x1.24ec79917163ep-1, -0x1.24ec79917163dp-1},
+                {-0x1.170653fb1eb0bp1, -0x1.24ec79917163ep-1, -0x1.24ec79917163dp-1},
+                {0x1.1f3b3855544c8p1, -0x1.3f3a0e28bedd1p-1, -0x1.3f3a0e28beddp-1},
+                {-0x1.1f3b3855544c8p1, -0x1.3f3a0e28bedd1p-1, -0x1.3f3a0e28beddp-1},
+                {0x1.27701caf89e85p1, -0x1.5837d2817cf2fp-1, -0x1.5837d2817cf2ep-1},
+                {-0x1.27701caf89e85p1, -0x1.5837d2817cf2fp-1, -0x1.5837d2817cf2ep-1},
+                {0x1.2fa50109bf842p1, -0x1.6fcb7c6b8b91ap-1, -0x1.6fcb7c6b8b919p-1},
+                {-0x1.2fa50109bf842p1, -0x1.6fcb7c6b8b91ap-1, -0x1.6fcb7c6b8b919p-1},
+                {0x1.37d9e563f51ffp1, -0x1.85dc3ea1bbcebp-1, -0x1.85dc3ea1bbceap-1},
+                {-0x1.37d9e563f51ffp1, -0x1.85dc3ea1bbcebp-1, -0x1.85dc3ea1bbceap-1},
+                {0x1.400ec9be2abbcp1, -0x1.9a52e2e0fbcb6p-1, -0x1.9a52e2e0fbcb5p-1},
+                {-0x1.400ec9be2abbcp1, -0x1.9a52e2e0fbcb6p-1, -0x1.9a52e2e0fbcb5p-1},
+                {0x1.4843ae1860579p1, -0x1.ad19e2535aa9ap-1, -0x1.ad19e2535aa99p-1},
+                {-0x1.4843ae1860579p1, -0x1.ad19e2535aa9ap-1, -0x1.ad19e2535aa99p-1},
+                {0x1.5078927295f36p1, -0x1.be1d7c3534c44p-1, -0x1.be1d7c3534c45p-1},
+                {-0x1.5078927295f36p1, -0x1.be1d7c3534c44p-1, -0x1.be1d7c3534c45p-1},
+                {0x1.58ad76cccb8f3p1, -0x1.cd4bca9cb5c76p-1, -0x1.cd4bca9cb5c75p-1},
+                {-0x1.58ad76cccb8f3p1, -0x1.cd4bca9cb5c76p-1, -0x1.cd4bca9cb5c75p-1},
+                {0x1.60e25b27012bp1, -0x1.da94d54dd4c0dp-1, -0x1.da94d54dd4c0cp-1},
+                {-0x1.60e25b27012bp1, -0x1.da94d54dd4c0dp-1, -0x1.da94d54dd4c0cp-1},
+                {0x1.69173f8136c6dp1, -0x1.e5eaa286fbbcbp-1, -0x1.e5eaa286fbbcap-1},
+                {-0x1.69173f8136c6dp1, -0x1.e5eaa286fbbcbp-1, -0x1.e5eaa286fbbcap-1},
+                {0x1.714c23db6c62ap1, -0x1.ef4145b4aed04p-1, -0x1.ef4145b4aed03p-1},
+                {-0x1.714c23db6c62ap1, -0x1.ef4145b4aed04p-1, -0x1.ef4145b4aed03p-1},
+                {0x1.79810835a1fe7p1, -0x1.f68eebfcbb5ecp-1, -0x1.f68eebfcbb5ebp-1},
+                {-0x1.79810835a1fe7p1, -0x1.f68eebfcbb5ecp-1, -0x1.f68eebfcbb5ebp-1},
+                {0x1.81b5ec8fd79a4p1, -0x1.fbcbe693bd8efp-1, -0x1.fbcbe693bd8fp-1},
+                {-0x1.81b5ec8fd79a4p1, -0x1.fbcbe693bd8efp-1, -0x1.fbcbe693bd8fp-1},
+                {0x1.89ead0ea0d35bp1, -0x1.fef2b2d21cf6cp-1, -0x1.fef2b2d21cf6bp-1},
+                {-0x1.89ead0ea0d35bp1, -0x1.fef2b2d21cf6cp-1, -0x1.fef2b2d21cf6bp-1},
+                {-0x1.81b5ec8fd799fp2, 0x1.ef4145b4aecffp-1, 0x1.ef4145b4aedp-1},
+                {0x1.81b5ec8fd799fp2, 0x1.ef4145b4aecffp-1, 0x1.ef4145b4aedp-1},
+                {-0x1.714c23db6c626p2, 0x1.be1d7c3534c4p-1, 0x1.be1d7c3534c3fp-1},
+                {0x1.714c23db6c626p2, 0x1.be1d7c3534c4p-1, 0x1.be1d7c3534c3fp-1},
+                {-0x1.60e25b27012adp2, 0x1.6fcb7c6b8b919p-1, 0x1.6fcb7c6b8b918p-1},
+                {0x1.60e25b27012adp2, 0x1.6fcb7c6b8b919p-1, 0x1.6fcb7c6b8b918p-1},
+                {-0x1.5078927295f34p2, 0x1.096ac02ec42c8p-1, 0x1.096ac02ec42c9p-1},
+                {0x1.5078927295f34p2, 0x1.096ac02ec42c8p-1, 0x1.096ac02ec42c9p-1},
+                {-0x1.400ec9be2abbbp2, 0x1.235b331d8f748p-2, 0x1.235b331d8f749p-2},
+                {0x1.400ec9be2abbbp2, 0x1.235b331d8f748p-2, 0x1.235b331d8f749p-2},
+                {-0x1.2fa50109bf842p2, 0x1.069107ae9332cp-5, 0x1.069107ae9332dp-5},
+                {0x1.2fa50109bf842p2, 0x1.069107ae9332cp-5, 0x1.069107ae9332dp-5},
+                {-0x1.1f3b3855544c9p2, -0x1.c7b90e3024569p-3, -0x1.c7b90e302456ap-3},
+                {0x1.1f3b3855544c9p2, -0x1.c7b90e3024569p-3, -0x1.c7b90e302456ap-3},
+                {-0x1.0ed16fa0e915p2, -0x1.d9a3a336edb63p-2, -0x1.d9a3a336edb62p-2},
+                {0x1.0ed16fa0e915p2, -0x1.d9a3a336edb63p-2, -0x1.d9a3a336edb62p-2},
+                {-0x1.fccf4dd8fbbaep1, -0x1.5837d2817cf28p-1, -0x1.5837d2817cf27p-1},
+                {0x1.fccf4dd8fbbaep1, -0x1.5837d2817cf28p-1, -0x1.5837d2817cf27p-1},
+                {-0x1.dbfbbc70254bcp1, -0x1.ad19e2535aa9p-1, -0x1.ad19e2535aa8fp-1},
+                {0x1.dbfbbc70254bcp1, -0x1.ad19e2535aa9p-1, -0x1.ad19e2535aa8fp-1},
+                {-0x1.bb282b074edcap1, -0x1.e5eaa286fbbc3p-1, -0x1.e5eaa286fbbc2p-1},
+                {0x1.bb282b074edcap1, -0x1.e5eaa286fbbc3p-1, -0x1.e5eaa286fbbc2p-1},
+                {-0x1.9a54999e786d8p1, -0x1.fef2b2d21cf6bp-1, -0x1.fef2b2d21cf6cp-1},
+                {0x1.9a54999e786d8p1, -0x1.fef2b2d21cf6bp-1, -0x1.fef2b2d21cf6cp-1},
+                {-0x1.79810835a1fe6p1, -0x1.f68eebfcbb5ebp-1, -0x1.f68eebfcbb5eap-1},
+                {0x1.79810835a1fe6p1, -0x1.f68eebfcbb5ebp-1, -0x1.f68eebfcbb5eap-1},
+                {-0x1.58ad76cccb8f4p1, -0x1.cd4bca9cb5c77p-1, -0x1.cd4bca9cb5c78p-1},
+                {0x1.58ad76cccb8f4p1, -0x1.cd4bca9cb5c77p-1, -0x1.cd4bca9cb5c78p-1},
+                {-0x1.37d9e563f5202p1, -0x1.85dc3ea1bbcf3p-1, -0x1.85dc3ea1bbcf2p-1},
+                {0x1.37d9e563f5202p1, -0x1.85dc3ea1bbcf3p-1, -0x1.85dc3ea1bbcf2p-1},
+                {-0x1.170653fb1eb1p1, -0x1.24ec79917164ep-1, -0x1.24ec79917164fp-1},
+                {0x1.170653fb1eb1p1, -0x1.24ec79917164ep-1, -0x1.24ec79917164fp-1},
+                {-0x1.ec6585249083cp0, -0x1.61a76077aee24p-2, -0x1.61a76077aee23p-2},
+                {0x1.ec6585249083cp0, -0x1.61a76077aee24p-2, -0x1.61a76077aee23p-2},
+                {-0x1.aabe6252e3a58p0, -0x1.894f70befbc1p-4, -0x1.894f70befbc11p-4},
+                {0x1.aabe6252e3a58p0, -0x1.894f70befbc1p-4, -0x1.894f70befbc11p-4},
+                {-0x1.69173f8136c74p0, 0x1.46dc4f4ce8374p-3, 0x1.46dc4f4ce8373p-3},
+                {0x1.69173f8136c74p0, 0x1.46dc4f4ce8374p-3, 0x1.46dc4f4ce8373p-3},
+                {-0x1.27701caf89e9p0, 0x1.9e7f8652b4729p-2, 0x1.9e7f8652b4728p-2},
+                {0x1.27701caf89e9p0, 0x1.9e7f8652b4729p-2, 0x1.9e7f8652b4728p-2},
+                {-0x1.cb91f3bbba157p-1, 0x1.3f3a0e28bedcp-1, 0x1.3f3a0e28bedbfp-1},
+                {0x1.cb91f3bbba157p-1, 0x1.3f3a0e28bedcp-1, 0x1.3f3a0e28bedbfp-1},
+                {-0x1.4843ae186058ep-1, 0x1.9a52e2e0fbca5p-1, 0x1.9a52e2e0fbca4p-1},
+                {0x1.4843ae186058ep-1, 0x1.9a52e2e0fbca5p-1, 0x1.9a52e2e0fbca4p-1},
+                {-0x1.89ead0ea0d38ap-2, 0x1.da94d54dd4bffp-1, 0x1.da94d54dd4cp-1},
+                {0x1.89ead0ea0d38ap-2, 0x1.da94d54dd4bffp-1, 0x1.da94d54dd4cp-1},
+                {-0x1.069c8b46b37fp-3, 0x1.fbcbe693bd8eap-1, 0x1.fbcbe693bd8e9p-1},
+                {0x1.069c8b46b37fp-3, 0x1.fbcbe693bd8eap-1, 0x1.fbcbe693bd8e9p-1},
+                {0x1.069c8b46b3734p-3, 0x1.fbcbe693bd8fp-1, 0x1.fbcbe693bd8efp-1},
+                {-0x1.069c8b46b3734p-3, 0x1.fbcbe693bd8fp-1, 0x1.fbcbe693bd8efp-1},
+                {0x1.89ead0ea0d32cp-2, 0x1.da94d54dd4c11p-1, 0x1.da94d54dd4c12p-1},
+                {-0x1.89ead0ea0d32cp-2, 0x1.da94d54dd4c11p-1, 0x1.da94d54dd4c12p-1},
+                {0x1.4843ae186055fp-1, 0x1.9a52e2e0fbcc1p-1, 0x1.9a52e2e0fbccp-1},
+                {-0x1.4843ae186055fp-1, 0x1.9a52e2e0fbcc1p-1, 0x1.9a52e2e0fbccp-1},
+                {0x1.cb91f3bbba128p-1, 0x1.3f3a0e28bede4p-1, 0x1.3f3a0e28bede5p-1},
+                {-0x1.cb91f3bbba128p-1, 0x1.3f3a0e28bede4p-1, 0x1.3f3a0e28bede5p-1},
+                {0x1.27701caf89e78p0, 0x1.9e7f8652b478p-2, 0x1.9e7f8652b4781p-2},
+                {-0x1.27701caf89e78p0, 0x1.9e7f8652b478p-2, 0x1.9e7f8652b4781p-2},
+                {0x1.69173f8136c5cp0, 0x1.46dc4f4ce8431p-3, 0x1.46dc4f4ce8432p-3},
+                {-0x1.69173f8136c5cp0, 0x1.46dc4f4ce8431p-3, 0x1.46dc4f4ce8432p-3},
+                {0x1.aabe6252e3a4p0, -0x1.894f70befba92p-4, -0x1.894f70befba93p-4},
+                {-0x1.aabe6252e3a4p0, -0x1.894f70befba92p-4, -0x1.894f70befba93p-4},
+                {0x1.ec65852490824p0, -0x1.61a76077aedcap-2, -0x1.61a76077aedc9p-2},
+                {-0x1.ec65852490824p0, -0x1.61a76077aedcap-2, -0x1.61a76077aedc9p-2},
+                {0x1.170653fb1eb04p1, -0x1.24ec799171627p-1, -0x1.24ec799171626p-1},
+                {-0x1.170653fb1eb04p1, -0x1.24ec799171627p-1, -0x1.24ec799171626p-1},
+                {0x1.37d9e563f51f6p1, -0x1.85dc3ea1bbcd3p-1, -0x1.85dc3ea1bbcd4p-1},
+                {-0x1.37d9e563f51f6p1, -0x1.85dc3ea1bbcd3p-1, -0x1.85dc3ea1bbcd4p-1},
+                {0x1.58ad76cccb8e8p1, -0x1.cd4bca9cb5c63p-1, -0x1.cd4bca9cb5c62p-1},
+                {-0x1.58ad76cccb8e8p1, -0x1.cd4bca9cb5c63p-1, -0x1.cd4bca9cb5c62p-1},
+                {0x1.79810835a1fdap1, -0x1.f68eebfcbb5e2p-1, -0x1.f68eebfcbb5e1p-1},
+                {-0x1.79810835a1fdap1, -0x1.f68eebfcbb5e2p-1, -0x1.f68eebfcbb5e1p-1},
+                {0x1.9a54999e786ccp1, -0x1.fef2b2d21cf6ep-1, -0x1.fef2b2d21cf6fp-1},
+                {-0x1.9a54999e786ccp1, -0x1.fef2b2d21cf6ep-1, -0x1.fef2b2d21cf6fp-1},
+                {0x1.bb282b074edbep1, -0x1.e5eaa286fbbd2p-1, -0x1.e5eaa286fbbd1p-1},
+                {-0x1.bb282b074edbep1, -0x1.e5eaa286fbbd2p-1, -0x1.e5eaa286fbbd1p-1},
+                {0x1.dbfbbc70254bp1, -0x1.ad19e2535aaaap-1, -0x1.ad19e2535aaabp-1},
+                {-0x1.dbfbbc70254bp1, -0x1.ad19e2535aaaap-1, -0x1.ad19e2535aaabp-1},
+                {0x1.fccf4dd8fbba2p1, -0x1.5837d2817cf4bp-1, -0x1.5837d2817cf4ap-1},
+                {-0x1.fccf4dd8fbba2p1, -0x1.5837d2817cf4bp-1, -0x1.5837d2817cf4ap-1},
+                {0x1.0ed16fa0e914ap2, -0x1.d9a3a336edbb8p-2, -0x1.d9a3a336edbb7p-2},
+                {-0x1.0ed16fa0e914ap2, -0x1.d9a3a336edbb8p-2, -0x1.d9a3a336edbb7p-2},
+                {0x1.1f3b3855544c3p2, -0x1.c7b90e3024625p-3, -0x1.c7b90e3024624p-3},
+                {-0x1.1f3b3855544c3p2, -0x1.c7b90e3024625p-3, -0x1.c7b90e3024624p-3},
+                {0x1.2fa50109bf83cp2, 0x1.069107ae9302dp-5, 0x1.069107ae9302cp-5},
+                {-0x1.2fa50109bf83cp2, 0x1.069107ae9302dp-5, 0x1.069107ae9302cp-5},
+                {0x1.400ec9be2abb5p2, 0x1.235b331d8f6ecp-2, 0x1.235b331d8f6edp-2},
+                {-0x1.400ec9be2abb5p2, 0x1.235b331d8f6ecp-2, 0x1.235b331d8f6edp-2},
+                {0x1.5078927295f2ep2, 0x1.096ac02ec429fp-1, 0x1.096ac02ec42ap-1},
+                {-0x1.5078927295f2ep2, 0x1.096ac02ec429fp-1, 0x1.096ac02ec42ap-1},
+                {0x1.60e25b27012a7p2, 0x1.6fcb7c6b8b8f7p-1, 0x1.6fcb7c6b8b8f8p-1},
+                {-0x1.60e25b27012a7p2, 0x1.6fcb7c6b8b8f7p-1, 0x1.6fcb7c6b8b8f8p-1},
+                {0x1.714c23db6c62p2, 0x1.be1d7c3534c28p-1, 0x1.be1d7c3534c29p-1},
+                {-0x1.714c23db6c62p2, 0x1.be1d7c3534c28p-1, 0x1.be1d7c3534c29p-1},
+                {0x1.81b5ec8fd7999p2, 0x1.ef4145b4aecf3p-1, 0x1.ef4145b4aecf4p-1},
+                {-0x1.81b5ec8fd7999p2, 0x1.ef4145b4aecf3p-1, 0x1.ef4145b4aecf4p-1},
+                {0x1.effffffffffffp-5, 0x1.ff0fd2c96adfcp-1, 0x1.ff0fd2c96adfbp-1},
+                {-0x1.effffffffffffp-5, 0x1.ff0fd2c96adfcp-1, 0x1.ff0fd2c96adfbp-1},
+                {0x1.fp-5, 0x1.ff0fd2c96adfcp-1, 0x1.ff0fd2c96adfbp-1},
+                {-0x1.fp-5, 0x1.ff0fd2c96adfcp-1, 0x1.ff0fd2c96adfbp-1},
+                {0x1.f000000000001p-5, 0x1.ff0fd2c96adfcp-1, 0x1.ff0fd2c96adfbp-1},
+                {-0x1.f000000000001p-5, 0x1.ff0fd2c96adfcp-1, 0x1.ff0fd2c96adfbp-1},
+                {0x1.f7fffffffffffp-4, 0x1.fc210055467fep-1, 0x1.fc210055467ffp-1},
+                {-0x1.f7fffffffffffp-4, 0x1.fc210055467fep-1, 0x1.fc210055467ffp-1},
+                {0x1.f8p-4, 0x1.fc210055467fep-1, 0x1.fc210055467ffp-1},
+                {-0x1.f8p-4, 0x1.fc210055467fep-1, 0x1.fc210055467ffp-1},
+                {0x1.f800000000001p-4, 0x1.fc210055467fep-1, 0x1.fc210055467ffp-1},
+                {-0x1.f800000000001p-4, 0x1.fc210055467fep-1, 0x1.fc210055467ffp-1},
+                {0x1.4bfffffffffffp-3, 0x1.f94984b2552e2p-1, 0x1.f94984b2552e1p-1},
+                {-0x1.4bfffffffffffp-3, 0x1.f94984b2552e2p-1, 0x1.f94984b2552e1p-1},
+                {0x1.4cp-3, 0x1.f94984b2552e2p-1, 0x1.f94984b2552e1p-1},
+                {-0x1.4cp-3, 0x1.f94984b2552e2p-1, 0x1.f94984b2552e1p-1},
+                {0x1.4c00000000001p-3, 0x1.f94984b2552e2p-1, 0x1.f94984b2552e1p-1},
+                {-0x1.4c00000000001p-3, 0x1.f94984b2552e2p-1, 0x1.f94984b2552e1p-1},
+                {0x1.3333333333332p-2, 0x1.e921dd42f09bbp-1, 0x1.e921dd42f09bap-1},
+                {-0x1.3333333333332p-2, 0x1.e921dd42f09bbp-1, 0x1.e921dd42f09bap-1},
+                {0x1.3333333333333p-2, 0x1.e921dd42f09bap-1, 0x1.e921dd42f09bbp-1},
+                {-0x1.3333333333333p-2, 0x1.e921dd42f09bap-1, 0x1.e921dd42f09bbp-1},
+                {0x1.3333333333334p-2, 0x1.e921dd42f09bap-1, 0x1.e921dd42f09bbp-1},
+                {-0x1.3333333333334p-2, 0x1.e921dd42f09bap-1, 0x1.e921dd42f09bbp-1},
+                {0x1.594317acc4ef8p-1, 0x1.8feedb86bf0efp-1, 0x1.8feedb86bf0fp-1},
+                {-0x1.594317acc4ef8p-1, 0x1.8feedb86bf0efp-1, 0x1.8feedb86bf0fp-1},
+                {0x1.594317acc4ef9p-1, 0x1.8feedb86bf0efp-1, 0x1.8feedb86bf0eep-1},
+                {-0x1.594317acc4ef9p-1, 0x1.8feedb86bf0efp-1, 0x1.8feedb86bf0eep-1},
+                {0x1.594317acc4efap-1, 0x1.8feedb86bf0eep-1, 0x1.8feedb86bf0edp-1},
+                {-0x1.594317acc4efap-1, 0x1.8feedb86bf0eep-1, 0x1.8feedb86bf0edp-1},
+                {0x1.8ffffffffffffp-1, 0x1.6b898fa9efb5ep-1, 0x1.6b898fa9efb5dp-1},
+                {-0x1.8ffffffffffffp-1, 0x1.6b898fa9efb5ep-1, 0x1.6b898fa9efb5dp-1},
+                {0x1.9p-1, 0x1.6b898fa9efb5dp-1, 0x1.6b898fa9efb5ep-1},
+                {-0x1.9p-1, 0x1.6b898fa9efb5dp-1, 0x1.6b898fa9efb5ep-1},
+                {0x1.9000000000001p-1, 0x1.6b898fa9efb5cp-1, 0x1.6b898fa9efb5dp-1},
+                {-0x1.9000000000001p-1, 0x1.6b898fa9efb5cp-1, 0x1.6b898fa9efb5dp-1},
+                {-0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0p0, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.921fb54442d17p-5, 0x1.ff621e3796d7ep-1, 0x1.ff621e3796d7dp-1},
+                {-0x1.921fb54442d17p-5, 0x1.ff621e3796d7ep-1, 0x1.ff621e3796d7dp-1},
+                {0x1.921fb54442d18p-5, 0x1.ff621e3796d7ep-1, 0x1.ff621e3796d7dp-1},
+                {-0x1.921fb54442d18p-5, 0x1.ff621e3796d7ep-1, 0x1.ff621e3796d7dp-1},
+                {0x1.921fb54442d19p-5, 0x1.ff621e3796d7ep-1, 0x1.ff621e3796d7dp-1},
+                {-0x1.921fb54442d19p-5, 0x1.ff621e3796d7ep-1, 0x1.ff621e3796d7dp-1},
+                {0x1.921fb54442d17p-4, 0x1.fd88da3d12526p-1, 0x1.fd88da3d12525p-1},
+                {-0x1.921fb54442d17p-4, 0x1.fd88da3d12526p-1, 0x1.fd88da3d12525p-1},
+                {0x1.921fb54442d18p-4, 0x1.fd88da3d12526p-1, 0x1.fd88da3d12525p-1},
+                {-0x1.921fb54442d18p-4, 0x1.fd88da3d12526p-1, 0x1.fd88da3d12525p-1},
+                {0x1.921fb54442d19p-4, 0x1.fd88da3d12526p-1, 0x1.fd88da3d12525p-1},
+                {-0x1.921fb54442d19p-4, 0x1.fd88da3d12526p-1, 0x1.fd88da3d12525p-1},
+                {0x1.921fb54442d17p-3, 0x1.f6297cff75cbp-1, 0x1.f6297cff75cb1p-1},
+                {-0x1.921fb54442d17p-3, 0x1.f6297cff75cbp-1, 0x1.f6297cff75cb1p-1},
+                {0x1.921fb54442d18p-3, 0x1.f6297cff75cbp-1, 0x1.f6297cff75cb1p-1},
+                {-0x1.921fb54442d18p-3, 0x1.f6297cff75cbp-1, 0x1.f6297cff75cb1p-1},
+                {0x1.921fb54442d19p-3, 0x1.f6297cff75cbp-1, 0x1.f6297cff75cb1p-1},
+                {-0x1.921fb54442d19p-3, 0x1.f6297cff75cbp-1, 0x1.f6297cff75cb1p-1},
+                {0x1.921fb54442d17p-2, 0x1.d906bcf328d46p-1, 0x1.d906bcf328d47p-1},
+                {-0x1.921fb54442d17p-2, 0x1.d906bcf328d46p-1, 0x1.d906bcf328d47p-1},
+                {0x1.921fb54442d18p-2, 0x1.d906bcf328d46p-1, 0x1.d906bcf328d47p-1},
+                {-0x1.921fb54442d18p-2, 0x1.d906bcf328d46p-1, 0x1.d906bcf328d47p-1},
+                {0x1.921fb54442d19p-2, 0x1.d906bcf328d46p-1, 0x1.d906bcf328d47p-1},
+                {-0x1.921fb54442d19p-2, 0x1.d906bcf328d46p-1, 0x1.d906bcf328d47p-1},
+                {0x1.921fb54442d17p-1, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcdp-1},
+                {-0x1.921fb54442d17p-1, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcdp-1},
+                {0x1.921fb54442d18p-1, 0x1.6a09e667f3bcdp-1, 0x1.6a09e667f3bccp-1},
+                {-0x1.921fb54442d18p-1, 0x1.6a09e667f3bcdp-1, 0x1.6a09e667f3bccp-1},
+                {0x1.921fb54442d19p-1, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcdp-1},
+                {-0x1.921fb54442d19p-1, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcdp-1},
+                {0x1.921fb54442d17p0, 0x1.469898cc51702p-52, 0x1.469898cc51701p-52},
+                {-0x1.921fb54442d17p0, 0x1.469898cc51702p-52, 0x1.469898cc51701p-52},
+                {0x1.921fb54442d18p0, 0x1.1a62633145c07p-54, 0x1.1a62633145c06p-54},
+                {-0x1.921fb54442d18p0, 0x1.1a62633145c07p-54, 0x1.1a62633145c06p-54},
+                {0x1.921fb54442d19p0, -0x1.72cece675d1fdp-53, -0x1.72cece675d1fcp-53},
+                {-0x1.921fb54442d19p0, -0x1.72cece675d1fdp-53, -0x1.72cece675d1fcp-53},
+                {0x1.921fb54442d17p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.921fb54442d17p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p2, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d17p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p3, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d17p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d17p5, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p5, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p5, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p5, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p5, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p5, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d17p6, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p6, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p6, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p6, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p6, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p6, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d17p7, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d17p7, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p7, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p7, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.921fb54442d19p7, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d19p7, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.2d97c7f3321d1p1, -0x1.6a09e667f3bc9p-1, -0x1.6a09e667f3bcap-1},
+                {-0x1.2d97c7f3321d1p1, -0x1.6a09e667f3bc9p-1, -0x1.6a09e667f3bcap-1},
+                {0x1.2d97c7f3321d2p1, -0x1.6a09e667f3bccp-1, -0x1.6a09e667f3bcbp-1},
+                {-0x1.2d97c7f3321d2p1, -0x1.6a09e667f3bccp-1, -0x1.6a09e667f3bcbp-1},
+                {0x1.2d97c7f3321d3p1, -0x1.6a09e667f3bcfp-1, -0x1.6a09e667f3bcep-1},
+                {-0x1.2d97c7f3321d3p1, -0x1.6a09e667f3bcfp-1, -0x1.6a09e667f3bcep-1},
+                {0x1.f6a7a2955385dp1, -0x1.6a09e667f3bdp-1, -0x1.6a09e667f3bd1p-1},
+                {-0x1.f6a7a2955385dp1, -0x1.6a09e667f3bdp-1, -0x1.6a09e667f3bd1p-1},
+                {0x1.f6a7a2955385ep1, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcdp-1},
+                {-0x1.f6a7a2955385ep1, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcdp-1},
+                {0x1.f6a7a2955385fp1, -0x1.6a09e667f3bcbp-1, -0x1.6a09e667f3bcap-1},
+                {-0x1.f6a7a2955385fp1, -0x1.6a09e667f3bcbp-1, -0x1.6a09e667f3bcap-1},
+                {0x1.2d97c7f3321d1p2, -0x1.34f272993d141p-50, -0x1.34f272993d142p-50},
+                {-0x1.2d97c7f3321d1p2, -0x1.34f272993d141p-50, -0x1.34f272993d142p-50},
+                {0x1.2d97c7f3321d2p2, -0x1.a79394c9e8a0ap-53, -0x1.a79394c9e8a0bp-53},
+                {-0x1.2d97c7f3321d2p2, -0x1.a79394c9e8a0ap-53, -0x1.a79394c9e8a0bp-53},
+                {0x1.2d97c7f3321d3p2, 0x1.961b1acd85d7dp-51, 0x1.961b1acd85d7ep-51},
+                {-0x1.2d97c7f3321d3p2, 0x1.961b1acd85d7dp-51, 0x1.961b1acd85d7ep-51},
+                {0x1.5fdbbe9bba774p2, 0x1.6a09e667f3bc6p-1, 0x1.6a09e667f3bc5p-1},
+                {-0x1.5fdbbe9bba774p2, 0x1.6a09e667f3bc6p-1, 0x1.6a09e667f3bc5p-1},
+                {0x1.5fdbbe9bba775p2, 0x1.6a09e667f3bcbp-1, 0x1.6a09e667f3bccp-1},
+                {-0x1.5fdbbe9bba775p2, 0x1.6a09e667f3bcbp-1, 0x1.6a09e667f3bccp-1},
+                {0x1.5fdbbe9bba776p2, 0x1.6a09e667f3bd1p-1, 0x1.6a09e667f3bdp-1},
+                {-0x1.5fdbbe9bba776p2, 0x1.6a09e667f3bd1p-1, 0x1.6a09e667f3bdp-1},
+                {0x1.c463abeccb2bap2, 0x1.6a09e667f3bd4p-1, 0x1.6a09e667f3bd3p-1},
+                {-0x1.c463abeccb2bap2, 0x1.6a09e667f3bd4p-1, 0x1.6a09e667f3bd3p-1},
+                {0x1.c463abeccb2bbp2, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcfp-1},
+                {-0x1.c463abeccb2bbp2, 0x1.6a09e667f3bcep-1, 0x1.6a09e667f3bcfp-1},
+                {0x1.c463abeccb2bcp2, 0x1.6a09e667f3bc9p-1, 0x1.6a09e667f3bc8p-1},
+                {-0x1.c463abeccb2bcp2, 0x1.6a09e667f3bc9p-1, 0x1.6a09e667f3bc8p-1},
+                {0x1.f6a7a2955385dp2, 0x1.583ebeff65cc2p-50, 0x1.583ebeff65cc3p-50},
+                {-0x1.f6a7a2955385dp2, 0x1.583ebeff65cc2p-50, 0x1.583ebeff65cc3p-50},
+                {0x1.f6a7a2955385ep2, 0x1.60fafbfd97309p-52, 0x1.60fafbfd97308p-52},
+                {-0x1.f6a7a2955385ep2, 0x1.60fafbfd97309p-52, 0x1.60fafbfd97308p-52},
+                {0x1.f6a7a2955385fp2, -0x1.4f8282013467cp-51, -0x1.4f8282013467bp-51},
+                {-0x1.f6a7a2955385fp2, -0x1.4f8282013467cp-51, -0x1.4f8282013467bp-51},
+                {0x1.1475cc9eedeffp3, -0x1.6a09e667f3bb9p-1, -0x1.6a09e667f3bbap-1},
+                {-0x1.1475cc9eedeffp3, -0x1.6a09e667f3bb9p-1, -0x1.6a09e667f3bbap-1},
+                {0x1.1475cc9eedfp3, -0x1.6a09e667f3bc5p-1, -0x1.6a09e667f3bc4p-1},
+                {-0x1.1475cc9eedfp3, -0x1.6a09e667f3bc5p-1, -0x1.6a09e667f3bc4p-1},
+                {0x1.1475cc9eedf01p3, -0x1.6a09e667f3bdp-1, -0x1.6a09e667f3bd1p-1},
+                {-0x1.1475cc9eedf01p3, -0x1.6a09e667f3bdp-1, -0x1.6a09e667f3bd1p-1},
+                {0x1.2d97c7f3321d1p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d1p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.2d97c7f3321d2p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d2p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.2d97c7f3321d3p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d3p3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.46b9c347764a2p3, -0x1.6a09e667f3bep-1, -0x1.6a09e667f3be1p-1},
+                {-0x1.46b9c347764a2p3, -0x1.6a09e667f3bep-1, -0x1.6a09e667f3be1p-1},
+                {0x1.46b9c347764a3p3, -0x1.6a09e667f3bd5p-1, -0x1.6a09e667f3bd4p-1},
+                {-0x1.46b9c347764a3p3, -0x1.6a09e667f3bd5p-1, -0x1.6a09e667f3bd4p-1},
+                {0x1.46b9c347764a4p3, -0x1.6a09e667f3bc9p-1, -0x1.6a09e667f3bcap-1},
+                {-0x1.46b9c347764a4p3, -0x1.6a09e667f3bc9p-1, -0x1.6a09e667f3bcap-1},
+                {0x1.5fdbbe9bba774p3, -0x1.3dc585b2c7422p-49, -0x1.3dc585b2c7421p-49},
+                {-0x1.5fdbbe9bba774p3, -0x1.3dc585b2c7422p-49, -0x1.3dc585b2c7421p-49},
+                {0x1.5fdbbe9bba775p3, -0x1.ee2c2d963a10cp-52, -0x1.ee2c2d963a10dp-52},
+                {-0x1.5fdbbe9bba775p3, -0x1.ee2c2d963a10cp-52, -0x1.ee2c2d963a10dp-52},
+                {0x1.5fdbbe9bba776p3, 0x1.8474f49a717bdp-50, 0x1.8474f49a717bcp-50},
+                {-0x1.5fdbbe9bba776p3, 0x1.8474f49a717bdp-50, 0x1.8474f49a717bcp-50},
+                {0x1.78fdb9effea45p3, 0x1.6a09e667f3bb9p-1, 0x1.6a09e667f3bb8p-1},
+                {-0x1.78fdb9effea45p3, 0x1.6a09e667f3bb9p-1, 0x1.6a09e667f3bb8p-1},
+                {0x1.78fdb9effea46p3, 0x1.6a09e667f3bc4p-1, 0x1.6a09e667f3bc3p-1},
+                {-0x1.78fdb9effea46p3, 0x1.6a09e667f3bc4p-1, 0x1.6a09e667f3bc3p-1},
+                {0x1.78fdb9effea47p3, 0x1.6a09e667f3bcfp-1, 0x1.6a09e667f3bdp-1},
+                {-0x1.78fdb9effea47p3, 0x1.6a09e667f3bcfp-1, 0x1.6a09e667f3bdp-1},
+                {0x1.ab41b09886fe8p3, 0x1.6a09e667f3be1p-1, 0x1.6a09e667f3bep-1},
+                {-0x1.ab41b09886fe8p3, 0x1.6a09e667f3be1p-1, 0x1.6a09e667f3bep-1},
+                {0x1.ab41b09886fe9p3, 0x1.6a09e667f3bd6p-1, 0x1.6a09e667f3bd5p-1},
+                {-0x1.ab41b09886fe9p3, 0x1.6a09e667f3bd6p-1, 0x1.6a09e667f3bd5p-1},
+                {0x1.ab41b09886feap3, 0x1.6a09e667f3bcap-1, 0x1.6a09e667f3bcbp-1},
+                {-0x1.ab41b09886feap3, 0x1.6a09e667f3bcap-1, 0x1.6a09e667f3bcbp-1},
+                {0x1.c463abeccb2bap3, 0x1.4f6babe5db9e2p-49, 0x1.4f6babe5db9e1p-49},
+                {-0x1.c463abeccb2bap3, 0x1.4f6babe5db9e2p-49, 0x1.4f6babe5db9e1p-49},
+                {0x1.c463abeccb2bbp3, 0x1.3daeaf976e788p-51, 0x1.3daeaf976e787p-51},
+                {-0x1.c463abeccb2bbp3, 0x1.3daeaf976e788p-51, 0x1.3daeaf976e787p-51},
+                {0x1.c463abeccb2bcp3, -0x1.6128a83448c3cp-50, -0x1.6128a83448c3dp-50},
+                {-0x1.c463abeccb2bcp3, -0x1.6128a83448c3cp-50, -0x1.6128a83448c3dp-50},
+                {0x1.dd85a7410f58bp3, -0x1.6a09e667f3bb8p-1, -0x1.6a09e667f3bb7p-1},
+                {-0x1.dd85a7410f58bp3, -0x1.6a09e667f3bb8p-1, -0x1.6a09e667f3bb7p-1},
+                {0x1.dd85a7410f58cp3, -0x1.6a09e667f3bc3p-1, -0x1.6a09e667f3bc4p-1},
+                {-0x1.dd85a7410f58cp3, -0x1.6a09e667f3bc3p-1, -0x1.6a09e667f3bc4p-1},
+                {0x1.dd85a7410f58dp3, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcfp-1},
+                {-0x1.dd85a7410f58dp3, -0x1.6a09e667f3bcep-1, -0x1.6a09e667f3bcfp-1},
+                {0x1.f6a7a2955385dp3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.f6a7a2955385dp3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.f6a7a2955385ep3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.f6a7a2955385ep3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.f6a7a2955385fp3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.f6a7a2955385fp3, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.07e4cef4cbd96p4, -0x1.6a09e667f3bf8p-1, -0x1.6a09e667f3bf9p-1},
+                {-0x1.07e4cef4cbd96p4, -0x1.6a09e667f3bf8p-1, -0x1.6a09e667f3bf9p-1},
+                {0x1.07e4cef4cbd97p4, -0x1.6a09e667f3be2p-1, -0x1.6a09e667f3be1p-1},
+                {-0x1.07e4cef4cbd97p4, -0x1.6a09e667f3be2p-1, -0x1.6a09e667f3be1p-1},
+                {0x1.07e4cef4cbd98p4, -0x1.6a09e667f3bcbp-1, -0x1.6a09e667f3bccp-1},
+                {-0x1.07e4cef4cbd98p4, -0x1.6a09e667f3bcbp-1, -0x1.6a09e667f3bccp-1},
+                {0x1.1475cc9eedeffp4, -0x1.b088e90c77fd1p-48, -0x1.b088e90c77fd2p-48},
+                {-0x1.1475cc9eedeffp4, -0x1.b088e90c77fd1p-48, -0x1.b088e90c77fd2p-48},
+                {0x1.1475cc9eedfp4, -0x1.6111d218effa2p-49, -0x1.6111d218effa3p-49},
+                {-0x1.1475cc9eedfp4, -0x1.6111d218effa2p-49, -0x1.6111d218effa3p-49},
+                {0x1.1475cc9eedf01p4, 0x1.3ddc5bce200bbp-50, 0x1.3ddc5bce200bcp-50},
+                {-0x1.1475cc9eedf01p4, 0x1.3ddc5bce200bbp-50, 0x1.3ddc5bce200bcp-50},
+                {0x1.2106ca4910068p4, 0x1.6a09e667f3bacp-1, 0x1.6a09e667f3babp-1},
+                {-0x1.2106ca4910068p4, 0x1.6a09e667f3bacp-1, 0x1.6a09e667f3babp-1},
+                {0x1.2106ca4910069p4, 0x1.6a09e667f3bc3p-1, 0x1.6a09e667f3bc2p-1},
+                {-0x1.2106ca4910069p4, 0x1.6a09e667f3bc3p-1, 0x1.6a09e667f3bc2p-1},
+                {0x1.2106ca491006ap4, 0x1.6a09e667f3bd9p-1, 0x1.6a09e667f3bdap-1},
+                {-0x1.2106ca491006ap4, 0x1.6a09e667f3bd9p-1, 0x1.6a09e667f3bdap-1},
+                {0x1.2d97c7f3321d1p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d1p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.2d97c7f3321d2p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d2p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.2d97c7f3321d3p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.2d97c7f3321d3p4, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.3a28c59d54339p4, 0x1.6a09e667f3bf9p-1, 0x1.6a09e667f3bfap-1},
+                {-0x1.3a28c59d54339p4, 0x1.6a09e667f3bf9p-1, 0x1.6a09e667f3bfap-1},
+                {0x1.3a28c59d5433ap4, 0x1.6a09e667f3be2p-1, 0x1.6a09e667f3be3p-1},
+                {-0x1.3a28c59d5433ap4, 0x1.6a09e667f3be2p-1, 0x1.6a09e667f3be3p-1},
+                {0x1.3a28c59d5433bp4, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcbp-1},
+                {-0x1.3a28c59d5433bp4, 0x1.6a09e667f3bccp-1, 0x1.6a09e667f3bcbp-1},
+                {0x1.46b9c347764a2p4, 0x1.b95bfc26022b1p-48, 0x1.b95bfc26022b2p-48},
+                {-0x1.46b9c347764a2p4, 0x1.b95bfc26022b1p-48, 0x1.b95bfc26022b2p-48},
+                {0x1.46b9c347764a3p4, 0x1.72b7f84c04563p-49, 0x1.72b7f84c04562p-49},
+                {-0x1.46b9c347764a3p4, 0x1.72b7f84c04563p-49, 0x1.72b7f84c04562p-49},
+                {0x1.46b9c347764a4p4, -0x1.1a900f67f753ap-50, -0x1.1a900f67f753bp-50},
+                {-0x1.46b9c347764a4p4, -0x1.1a900f67f753ap-50, -0x1.1a900f67f753bp-50},
+                {0x1.534ac0f19860bp4, -0x1.6a09e667f3babp-1, -0x1.6a09e667f3bacp-1},
+                {-0x1.534ac0f19860bp4, -0x1.6a09e667f3babp-1, -0x1.6a09e667f3bacp-1},
+                {0x1.534ac0f19860cp4, -0x1.6a09e667f3bc2p-1, -0x1.6a09e667f3bc1p-1},
+                {-0x1.534ac0f19860cp4, -0x1.6a09e667f3bc2p-1, -0x1.6a09e667f3bc1p-1},
+                {0x1.534ac0f19860dp4, -0x1.6a09e667f3bd8p-1, -0x1.6a09e667f3bd9p-1},
+                {-0x1.534ac0f19860dp4, -0x1.6a09e667f3bd8p-1, -0x1.6a09e667f3bd9p-1},
+                {0x1.5fdbbe9bba774p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.5fdbbe9bba774p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.5fdbbe9bba775p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.5fdbbe9bba775p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.5fdbbe9bba776p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.5fdbbe9bba776p4, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.6c6cbc45dc8dcp4, -0x1.6a09e667f3bfap-1, -0x1.6a09e667f3bf9p-1},
+                {-0x1.6c6cbc45dc8dcp4, -0x1.6a09e667f3bfap-1, -0x1.6a09e667f3bf9p-1},
+                {0x1.6c6cbc45dc8ddp4, -0x1.6a09e667f3be3p-1, -0x1.6a09e667f3be4p-1},
+                {-0x1.6c6cbc45dc8ddp4, -0x1.6a09e667f3be3p-1, -0x1.6a09e667f3be4p-1},
+                {0x1.6c6cbc45dc8dep4, -0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bccp-1},
+                {-0x1.6c6cbc45dc8dep4, -0x1.6a09e667f3bcdp-1, -0x1.6a09e667f3bccp-1},
+                {0x1.78fdb9effea45p4, -0x1.c22f0f3f8c592p-48, -0x1.c22f0f3f8c591p-48},
+                {-0x1.78fdb9effea45p4, -0x1.c22f0f3f8c592p-48, -0x1.c22f0f3f8c591p-48},
+                {0x1.78fdb9effea46p4, -0x1.845e1e7f18b23p-49, -0x1.845e1e7f18b24p-49},
+                {-0x1.78fdb9effea46p4, -0x1.845e1e7f18b23p-49, -0x1.845e1e7f18b24p-49},
+                {0x1.78fdb9effea47p4, 0x1.ee8786039d373p-51, 0x1.ee8786039d374p-51},
+                {-0x1.78fdb9effea47p4, 0x1.ee8786039d373p-51, 0x1.ee8786039d374p-51},
+                {0x1.858eb79a20baep4, 0x1.6a09e667f3baap-1, 0x1.6a09e667f3babp-1},
+                {-0x1.858eb79a20baep4, 0x1.6a09e667f3baap-1, 0x1.6a09e667f3babp-1},
+                {0x1.858eb79a20bafp4, 0x1.6a09e667f3bc1p-1, 0x1.6a09e667f3bcp-1},
+                {-0x1.858eb79a20bafp4, 0x1.6a09e667f3bc1p-1, 0x1.6a09e667f3bcp-1},
+                {0x1.858eb79a20bbp4, 0x1.6a09e667f3bd8p-1, 0x1.6a09e667f3bd7p-1},
+                {-0x1.858eb79a20bbp4, 0x1.6a09e667f3bd8p-1, 0x1.6a09e667f3bd7p-1},
+                {0x1.fffffffffffffp62, -0x1.2ccaf641d4262p-3, -0x1.2ccaf641d4261p-3},
+                {-0x1.fffffffffffffp62, -0x1.2ccaf641d4262p-3, -0x1.2ccaf641d4261p-3},
+                {0x1.0p63, 0x1.82aa375b3c33ep-7, 0x1.82aa375b3c33fp-7},
+                {-0x1.0p63, 0x1.82aa375b3c33ep-7, 0x1.82aa375b3c33fp-7},
+                {0x1.0000000000001p63, 0x1.4c0622a6e35dep-2, 0x1.4c0622a6e35ddp-2},
+                {-0x1.0000000000001p63, 0x1.4c0622a6e35dep-2, 0x1.4c0622a6e35ddp-2},
+                {0x1.fffffffffffffp26, 0x1.4ab650b8c6073p-1, 0x1.4ab650b8c6074p-1},
+                {-0x1.fffffffffffffp26, 0x1.4ab650b8c6073p-1, 0x1.4ab650b8c6074p-1},
+                {0x1.0p27, 0x1.4ab6511a7d39bp-1, 0x1.4ab6511a7d39ap-1},
+                {-0x1.0p27, 0x1.4ab6511a7d39bp-1, 0x1.4ab6511a7d39ap-1},
+                {0x1.0000000000001p27, 0x1.4ab651ddeb9e6p-1, 0x1.4ab651ddeb9e7p-1},
+                {-0x1.0000000000001p27, 0x1.4ab651ddeb9e6p-1, 0x1.4ab651ddeb9e7p-1},
+                {0x1.fffffffffffffp23, 0x1.40ad67e777b1ep-1, 0x1.40ad67e777b1dp-1},
+                {-0x1.fffffffffffffp23, 0x1.40ad67e777b1ep-1, 0x1.40ad67e777b1dp-1},
+                {0x1.0p24, 0x1.40ad67f3f0c9ap-1, 0x1.40ad67f3f0c9bp-1},
+                {-0x1.0p24, 0x1.40ad67f3f0c9ap-1, 0x1.40ad67f3f0c9bp-1},
+                {0x1.0000000000001p24, 0x1.40ad680ce2f92p-1, 0x1.40ad680ce2f93p-1},
+                {-0x1.0000000000001p24, 0x1.40ad680ce2f92p-1, 0x1.40ad680ce2f93p-1},
+                {0x1.fffffffffffffp1, -0x1.4eaa606db24c4p-1, -0x1.4eaa606db24c3p-1},
+                {-0x1.fffffffffffffp1, -0x1.4eaa606db24c4p-1, -0x1.4eaa606db24c3p-1},
+                {0x1.0p2, -0x1.4eaa606db24c1p-1, -0x1.4eaa606db24cp-1},
+                {-0x1.0p2, -0x1.4eaa606db24c1p-1, -0x1.4eaa606db24cp-1},
+                {0x1.0000000000001p2, -0x1.4eaa606db24bbp-1, -0x1.4eaa606db24bap-1},
+                {-0x1.0000000000001p2, -0x1.4eaa606db24bbp-1, -0x1.4eaa606db24bap-1},
+                {0x1.fffffffffffffp0, -0x1.aa22657537201p-2, -0x1.aa22657537202p-2},
+                {-0x1.fffffffffffffp0, -0x1.aa22657537201p-2, -0x1.aa22657537202p-2},
+                {0x1.0p1, -0x1.aa22657537205p-2, -0x1.aa22657537204p-2},
+                {-0x1.0p1, -0x1.aa22657537205p-2, -0x1.aa22657537204p-2},
+                {0x1.0000000000001p1, -0x1.aa2265753720cp-2, -0x1.aa2265753720bp-2},
+                {-0x1.0000000000001p1, -0x1.aa2265753720cp-2, -0x1.aa2265753720bp-2},
+                {0x1.fffffffffffffp-1, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068dp-1},
+                {-0x1.fffffffffffffp-1, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068dp-1},
+                {0x1.0p0, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068bp-1},
+                {-0x1.0p0, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068bp-1},
+                {0x1.0000000000001p0, 0x1.14a280fb5068ap-1, 0x1.14a280fb50689p-1},
+                {-0x1.0000000000001p0, 0x1.14a280fb5068ap-1, 0x1.14a280fb50689p-1},
+                {0x1.fffffffffffffp-2, 0x1.c1528065b7d5p-1, 0x1.c1528065b7d4fp-1},
+                {-0x1.fffffffffffffp-2, 0x1.c1528065b7d5p-1, 0x1.c1528065b7d4fp-1},
+                {0x1.0p-1, 0x1.c1528065b7d5p-1, 0x1.c1528065b7d4fp-1},
+                {-0x1.0p-1, 0x1.c1528065b7d5p-1, 0x1.c1528065b7d4fp-1},
+                {0x1.0000000000001p-1, 0x1.c1528065b7d4fp-1, 0x1.c1528065b7d5p-1},
+                {-0x1.0000000000001p-1, 0x1.c1528065b7d4fp-1, 0x1.c1528065b7d5p-1},
+                {0x1.fffffffffffffp-3, 0x1.f01549f7deea2p-1, 0x1.f01549f7deea1p-1},
+                {-0x1.fffffffffffffp-3, 0x1.f01549f7deea2p-1, 0x1.f01549f7deea1p-1},
+                {0x1.0p-2, 0x1.f01549f7deea1p-1, 0x1.f01549f7deea2p-1},
+                {-0x1.0p-2, 0x1.f01549f7deea1p-1, 0x1.f01549f7deea2p-1},
+                {0x1.0000000000001p-2, 0x1.f01549f7deea1p-1, 0x1.f01549f7deea2p-1},
+                {-0x1.0000000000001p-2, 0x1.f01549f7deea1p-1, 0x1.f01549f7deea2p-1},
+                {0x1.fffffffffffffp-4, 0x1.fc015527d5bd3p-1, 0x1.fc015527d5bd4p-1},
+                {-0x1.fffffffffffffp-4, 0x1.fc015527d5bd3p-1, 0x1.fc015527d5bd4p-1},
+                {0x1.0p-3, 0x1.fc015527d5bd3p-1, 0x1.fc015527d5bd4p-1},
+                {-0x1.0p-3, 0x1.fc015527d5bd3p-1, 0x1.fc015527d5bd4p-1},
+                {0x1.0000000000001p-3, 0x1.fc015527d5bd3p-1, 0x1.fc015527d5bd4p-1},
+                {-0x1.0000000000001p-3, 0x1.fc015527d5bd3p-1, 0x1.fc015527d5bd4p-1},
+                {0x1.fffffffffffffp-5, 0x1.ff0015549f4d3p-1, 0x1.ff0015549f4d4p-1},
+                {-0x1.fffffffffffffp-5, 0x1.ff0015549f4d3p-1, 0x1.ff0015549f4d4p-1},
+                {0x1.0p-4, 0x1.ff0015549f4d3p-1, 0x1.ff0015549f4d4p-1},
+                {-0x1.0p-4, 0x1.ff0015549f4d3p-1, 0x1.ff0015549f4d4p-1},
+                {0x1.0000000000001p-4, 0x1.ff0015549f4d3p-1, 0x1.ff0015549f4d4p-1},
+                {-0x1.0000000000001p-4, 0x1.ff0015549f4d3p-1, 0x1.ff0015549f4d4p-1},
+                {0x1.fffffffffffffp-6, 0x1.ffc00155527d3p-1, 0x1.ffc00155527d2p-1},
+                {-0x1.fffffffffffffp-6, 0x1.ffc00155527d3p-1, 0x1.ffc00155527d2p-1},
+                {0x1.0p-5, 0x1.ffc00155527d3p-1, 0x1.ffc00155527d2p-1},
+                {-0x1.0p-5, 0x1.ffc00155527d3p-1, 0x1.ffc00155527d2p-1},
+                {0x1.0000000000001p-5, 0x1.ffc00155527d3p-1, 0x1.ffc00155527d2p-1},
+                {-0x1.0000000000001p-5, 0x1.ffc00155527d3p-1, 0x1.ffc00155527d2p-1},
+                {0x1.fffffffffffffp-7, 0x1.fff000155549fp-1, 0x1.fff00015554ap-1},
+                {-0x1.fffffffffffffp-7, 0x1.fff000155549fp-1, 0x1.fff00015554ap-1},
+                {0x1.0p-6, 0x1.fff000155549fp-1, 0x1.fff00015554ap-1},
+                {-0x1.0p-6, 0x1.fff000155549fp-1, 0x1.fff00015554ap-1},
+                {0x1.0000000000001p-6, 0x1.fff000155549fp-1, 0x1.fff00015554ap-1},
+                {-0x1.0000000000001p-6, 0x1.fff000155549fp-1, 0x1.fff00015554ap-1},
+                {0x1.fffffffffffffp-15, 0x1.fffffffp-1, 0x1.fffffff000001p-1},
+                {-0x1.fffffffffffffp-15, 0x1.fffffffp-1, 0x1.fffffff000001p-1},
+                {0x1.0p-14, 0x1.fffffffp-1, 0x1.fffffff000001p-1},
+                {-0x1.0p-14, 0x1.fffffffp-1, 0x1.fffffff000001p-1},
+                {0x1.0000000000001p-14, 0x1.fffffffp-1, 0x1.fffffff000001p-1},
+                {-0x1.0000000000001p-14, 0x1.fffffffp-1, 0x1.fffffff000001p-1},
+                {0x1.fffffffffffffp-28, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.fffffffffffffp-28, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.0p-27, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.0p-27, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.0000000000001p-27, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.0000000000001p-27, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.fffffffffffffp-31, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.fffffffffffffp-31, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.0p-30, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.0p-30, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {0x1.0000000000001p-30, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.0000000000001p-30, 0x1.0p0, 0x1.fffffffffffffp-1},
+                {-0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {-0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {-0x1.fffffffffffffp1023, -0x1.fffe62ecfab75p-1, -0x1.fffe62ecfab76p-1},
+                {0x1.ffffffffffffep1023, 0x1.7ffdfb4c5309p-2, 0x1.7ffdfb4c5308fp-2},
+                {-0x1.ffffffffffffep1023, 0x1.7ffdfb4c5309p-2, 0x1.7ffdfb4c5308fp-2},
+                {0x1.921fb54442d18p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {-0x1.921fb54442d18p1, -0x1.0p0, -0x1.fffffffffffffp-1},
+                {0x1.921fb54442d18p0, 0x1.1a62633145c07p-54, 0x1.1a62633145c06p-54},
+                {-0x1.921fb54442d18p0, 0x1.1a62633145c07p-54, 0x1.1a62633145c06p-54},
+                {0x1.0000000000001p0, 0x1.14a280fb5068ap-1, 0x1.14a280fb50689p-1},
+                {-0x1.0000000000001p0, 0x1.14a280fb5068ap-1, 0x1.14a280fb50689p-1},
+                {0x1.0p0, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068bp-1},
+                {-0x1.0p0, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068bp-1},
+                {0x1.fffffffffffffp-1, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068dp-1},
+                {-0x1.fffffffffffffp-1, 0x1.14a280fb5068cp-1, 0x1.14a280fb5068dp-1},
+                {0x1.921fb54442d18p-1, 0x1.6a09e667f3bcdp-1, 0x1.6a09e667f3bccp-1},
+                {-0x1.921fb54442d18p-1, 0x1.6a09e667f3bcdp-1, 0x1.6a09e667f3bccp-1},
+                {0x1.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x1.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x1.0p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x1.0p-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.fffffffffffffp-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.fffffffffffffp-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.ffffffffffffep-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.ffffffffffffep-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000002p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0000000000002p-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {-0x0.0000000000001p-1022, 0x1.0p0, 0x1.0p0},
+                {0x0.0p0, 0x1.0p0, 0x1.0p0},
+                {-0x0.0p0, 0x1.0p0, 0x1.0p0}
+        };
+
+        for (double[] testCase : testCases) {
+            testCosCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+    private static void testCosCase(double input, double bound1, double bound2) {
+        Tests.testBounds("Math.cos", input, Math.cos(input), bound1, bound2);
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/TanTests.java b/ojluni/src/test/java/lang/Math/TanTests.java
new file mode 100644
index 0000000..4c8fd70
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/TanTests.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5033578
+ * @summary Tests for {Math, StrictMath}.tan
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class TanTests {
+
+    private TanTests() {
+    }
+
+    static void testTanCase(double input, double expected, double ulps) {
+        Tests.testUlpDiff("StrictMath.tan(double, double)", input,
+                StrictMath.tan(input), expected, ulps);
+        Tests.testUlpDiff("Math.tan(double, double)", input,
+                Math.tan(input), expected, ulps);
+    }
+
+    @Test
+    public void testTan() {
+        double[][] testCases = {
+                // 1.1 ulp case from Gonnet
+                {0x1.31b97c4000001p24, -0x1.d08538b656222p34, 1.9},
+                // Remaining test cases adapted from work by Alex Liu
+                {0x1.be1b2d17ba207p6, -0x1.cf489c89f8066p49, 1.100000},
+                {0x1.e0a9e6ab97de7p7, 0x1.d31ce95f57459p50, 1.100000},
+                {0x1.23f8c5bcf003ep11, 0x1.f022585dbb50ap50, 1.100000},
+                {0x1.44bdb557e1dc1p20, 0x1.b67eaf362701fp49, 1.100000},
+                {0x1.604759040fb6fp68, 0x1.d574bc1f9e903p50, 1.100000},
+                {0x1.3d33fa4e5ba47p70, 0x1.ce1dd6e33fef8p49, 1.100000},
+                {0x1.f19e5d71b26bap85, 0x1.c2536a9119dd2p55, 1.100000},
+                {0x1.43ed062d2d62cp88, -0x1.c94b0c5b7b05p49, 1.100000},
+                {0x1.b7b895b030bep88, -0x1.cba9ebb0f20b9p51, 1.100000},
+                {0x1.a86090fe7c144p95, 0x1.d5ad72ca48bbfp48, 1.100000},
+                {0x1.d199df0700a61p95, -0x1.b8dd636f8dba7p49, 1.100000},
+                {0x1.d713037d1d222p106, -0x1.d57f035fd0146p48, 1.100000},
+                {0x1.ed1f6b066569bp115, 0x1.840af46cc9bep48, 1.100000},
+                {0x1.16800a51eff75p118, 0x1.c9f91caf08a6ap49, 1.100000},
+                {0x1.c1169c1040ecdp134, 0x1.e44a7eb56cb7p48, 1.100000},
+                {0x1.19b0fb40dddd5p145, -0x1.f1b1c235774b2p48, 1.100000},
+                {0x1.4d6b47f2480f8p162, 0x1.da1c2010795a5p51, 1.100000},
+                {0x1.682ff8e5429ddp163, -0x1.95a7aee1e93bep55, 1.100000},
+                {0x1.d0569fad9657dp204, -0x1.8f2ca17123aa5p49, 1.100000},
+                {0x1.55505de5bbc14p206, -0x1.e8d28e39ddf9p50, 1.100000},
+                {0x1.cf497083e6c77p206, -0x1.fd3fbaa40de18p49, 1.100000},
+                {0x1.c5b30c8686203p214, 0x1.f4d14469638a9p48, 1.100000},
+                {0x1.60d15b12ff0b7p217, 0x1.bc150932bd3d7p48, 1.100000},
+                {0x1.07cc6858d980bp218, -0x1.f3f7355c983a5p51, 1.100000},
+                {0x1.e06a67cd86969p218, 0x1.b0873124d98afp51, 1.100000},
+                {0x1.49704174c38e3p229, 0x1.e0301142ccbc2p49, 1.100000},
+                {0x1.ea19ceab3b06ap230, -0x1.fc22e687f0482p48, 1.100000},
+                {0x1.0c905503fea72p236, -0x1.7d4e9a45014d5p49, 1.100000},
+                {0x1.28eb1f8ddd7c3p257, -0x1.a951893680c71p49, 1.100000},
+                {0x1.310b11af2bfbep260, 0x1.84d458039c2e6p48, 1.100000},
+                {0x1.f3c172bb7afc2p265, -0x1.fb3139d3ba04fp49, 1.100000},
+                {0x1.54a28326cfedep267, 0x1.f416de8fb60bap53, 1.100000},
+                {0x1.5a5154d9d609dp269, -0x1.83d74cea8141p51, 1.100000},
+                {0x1.3ee75fd803b21p275, 0x1.b9ab67b61bf65p50, 1.100000},
+                {0x1.f4a4c781834d9p277, -0x1.d639ec63bf3b6p49, 1.100000},
+                {0x1.2053d5c14cf78p279, 0x1.fc31413372cdcp50, 1.100000},
+                {0x1.896d0a9acee4cp298, 0x1.f9136d6e27a5cp48, 1.100000},
+                {0x1.f010da08a862p302, -0x1.fd812c5e13483p49, 1.100000},
+                {0x1.65f2e272f729fp308, -0x1.f9f642ddaa32dp49, 1.100000},
+                {0x1.a8afbc4edb07dp309, 0x1.fa0d458320902p52, 1.100000},
+                {0x1.4d311a5447cdep329, -0x1.f7e98fe193e81p49, 1.100000},
+                {0x1.808f66338b21bp345, -0x1.bceaf45f61155p49, 1.100000},
+                {0x1.5a34aacf5ded1p350, 0x1.d41f0f13fadd4p49, 1.100000},
+                {0x1.3e8b85532bad1p354, -0x1.f0b21179d663ep49, 1.100000},
+                {0x1.1c2ecf01570acp394, -0x1.c215c9e2b7b24p49, 1.100000},
+                {0x1.666eba99d2837p402, 0x1.fbd5c4b527506p48, 1.100000},
+                {0x1.6cc39f07fafbbp460, -0x1.f087548a00e7cp49, 1.100000},
+                {0x1.9481228fea3ffp463, -0x1.c585e64ff44c8p48, 1.100000},
+                {0x1.79c3af0b4d0d4p466, 0x1.c9ed3716691f2p51, 1.100000},
+                {0x1.993ea84c3e23bp468, 0x1.a6b3954fc37f3p49, 1.100000},
+                {0x1.cfd6b13f64408p470, -0x1.f4db7cc2c09bp47, 1.100000},
+                {0x1.b820ccdd52299p473, 0x1.77a1ff863b0f3p52, 1.100000},
+                {0x1.157ef3a1528a5p475, -0x1.f4e14ddc45e49p51, 1.100000},
+                {0x1.b492a8997bc36p478, -0x1.e0db26b7f03e8p48, 1.100000},
+                {0x1.e0ea5674b831bp480, 0x1.e0ad6b3cdccdfp48, 1.100000},
+                {0x1.c62ac8b32cb9ep497, 0x1.c95d00a36f677p48, 1.100000},
+                {0x1.467f1daf12b43p498, 0x1.c6d3fdc096f0bp50, 1.100000},
+                {0x1.336e5a83e390cp502, 0x1.fc873dae28572p48, 1.100000},
+                {0x1.aaab1de0d6727p506, -0x1.e0482967d0354p49, 1.100000},
+                {0x1.e5ce06a12139cp507, 0x1.cea42e29735bdp49, 1.100000},
+                {0x1.87dad74d0dda8p516, -0x1.b2cde6c0a8b9fp48, 1.100000},
+                {0x1.e4feb94ee0989p524, -0x1.b227d0d0ffaa8p49, 1.100000},
+                {0x1.31c082b1361ebp525, 0x1.a7ed49158d736p49, 1.100000},
+                {0x1.56913865b3e16p531, 0x1.eeb7a32591c3bp52, 1.100000},
+                {0x1.36ade1fa883cap544, -0x1.fa087aadc0cbp48, 1.100000},
+                {0x1.de57314df4af8p559, 0x1.c686aa5a41075p49, 1.100000},
+                {0x1.0bb29bf7960ddp586, -0x1.d29ae1a3023cep50, 1.100000},
+                {0x1.049a584685941p588, -0x1.eebfb159dba67p51, 1.100000},
+                {0x1.33c1d4257b294p589, 0x1.ea1eedabea109p48, 1.100000},
+                {0x1.3587e511bf47bp590, 0x1.c897858ce0ca9p48, 1.100000},
+                {0x1.d12ee010c0facp590, 0x1.ab5b4b5065aa3p48, 1.100000},
+                {0x1.87bbed5af48d9p605, 0x1.f512c3b2be7cap50, 1.100000},
+                {0x1.a0b1131240cebp605, -0x1.fa373983fd571p48, 1.100000},
+                {0x1.116fdda1a04c9p616, -0x1.d76fdbc8552f3p51, 1.100000},
+                {0x1.67ebae833a034p620, 0x1.e1313af0a4075p50, 1.100000},
+                {0x1.9a50fbc5b0fecp627, 0x1.d89150884fbf7p50, 1.100000},
+                {0x1.6d625e0757e9cp631, -0x1.d0a5ecf002555p49, 1.100000},
+                {0x1.e880344cc9913p636, -0x1.fafd04caaf58bp48, 1.100000},
+                {0x1.e0a180b843cc5p650, 0x1.ea2aea3b8c953p49, 1.100000},
+                {0x1.fa91ce15157b2p652, 0x1.e6f5f4d47d83fp48, 1.100000},
+                {0x1.7696347caf8dfp654, 0x1.e0d36f2aef7dap51, 1.100000},
+                {0x1.886484b536161p666, -0x1.e3c96481e335bp51, 1.100000},
+                {0x1.0aa3ff2b41abdp675, -0x1.b3300ee04b4c8p50, 1.100000},
+                {0x1.d695ac08fe897p675, -0x1.c27fd21ecb13p51, 1.100000},
+                {0x1.4c1e532d7a99ap680, 0x1.e2ec695260c39p49, 1.100000},
+                {0x1.44a9f3e395802p685, -0x1.e7273ab9ce8e2p52, 1.100000},
+                {0x1.3a25ec2b43d45p697, -0x1.d23187ba6321ep49, 1.100000},
+                {0x1.96f5c2420c3fdp716, -0x1.ea06ab71ad719p49, 1.100000},
+                {0x1.926c063a9406bp741, 0x1.e3d3d9262fd66p48, 1.100000},
+                {0x1.1a57713d6fd93p754, -0x1.c10074d49490dp48, 1.100000},
+                {0x1.739387922e672p772, 0x1.bda527e215a3cp49, 1.100000},
+                {0x1.d286eff17f4d4p793, 0x1.d01c678ebfa1p49, 1.100000},
+                {0x1.f3d777206a062p794, -0x1.d8604b6d18385p49, 1.100000},
+                {0x1.ae91e6574da91p826, -0x1.fd1b26ab656c2p49, 1.100000},
+                {0x1.4422b3c871c9p836, 0x1.9d2cab1f3aebcp48, 1.100000},
+                {0x1.7ff8537071e1p840, 0x1.badde451c6ed7p48, 1.100000},
+                {0x1.c6fe9202e219dp845, -0x1.b2aa20745de3p51, 1.100000},
+                {0x1.a95a0b4015d88p846, 0x1.cdf5dfd045657p50, 1.100000},
+                {0x1.f823b9cff0daep867, 0x1.fd72fce3d5505p48, 1.100000},
+                {0x1.a6bee2afcd2fp886, 0x1.fe06265cd3aebp49, 1.100000},
+                {0x1.7b034b3412d17p892, 0x1.e48055812d391p50, 1.100000},
+                {0x1.58588f8cda276p894, 0x1.f806fddf0dd05p53, 1.100000},
+                {0x1.ce750a7963463p896, 0x1.e94f1f4018402p48, 1.100000},
+                {0x1.3d50a91fe82cfp897, 0x1.cd518fda10e95p48, 1.100000},
+                {0x1.f82dea1c0b809p897, -0x1.d6a0ef08179c5p48, 1.100000},
+                {0x1.38673e8c6a4afp903, 0x1.f4113a036478p48, 1.100000},
+                {0x1.dfb75e4a7432p911, 0x1.eb7bc6cb4d7f3p48, 1.100000},
+                {0x1.1230b975a72b3p916, -0x1.e1042be0759f9p48, 1.100000},
+                {0x1.302c2f5a4e6e5p916, 0x1.f66a9874cd60ap48, 1.100000},
+                {0x1.04e07a1d67b93p921, 0x1.87735139f6a0bp53, 1.100000},
+                {0x1.5a3eb79cd06fap931, -0x1.e00930c219ef3p51, 1.100000},
+                {0x1.8fb45679936fp937, 0x1.9a427588645c4p50, 1.100000},
+                {0x1.c4abb225260c6p964, -0x1.d1e64e91ac6ap50, 1.100000},
+                {0x1.b43e449b25382p982, -0x1.f1848cc5ac4fep50, 1.100000},
+                {0x1.504d9d7179b1ap983, 0x1.a4e51ea807786p48, 1.100000},
+                {0x1.83a5af80fb39bp987, 0x1.a6dde6c2220ebp48, 1.100000},
+                {0x1.5d978d9ad84c8p1011, 0x1.ec96900bfd1ddp51, 1.100000},
+        };
+
+        for (double[] testCase : testCases) {
+            testTanCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/Tests.java b/ojluni/src/test/java/lang/Math/Tests.java
new file mode 100644
index 0000000..e10d51b
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/Tests.java
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Shared static test methods for numerical tests.  Sharing these
+ * helper test methods avoids repeated functions in the various test
+ * programs.  The test methods return 1 for a test failure and 0 for
+ * success.  The order of arguments to the test methods is generally
+ * the test name, followed by the test arguments, the computed result,
+ * and finally the expected result.
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class Tests {
+
+    private Tests() {
+    }
+
+    ; // do not instantiate
+
+    public static String toHexString(float f) {
+        if (!Float.isNaN(f)) {
+            return Float.toHexString(f);
+        } else {
+            return "NaN(0x" + Integer.toHexString(Float.floatToRawIntBits(f)) + ")";
+        }
+    }
+
+    public static String toHexString(double d) {
+        if (!Double.isNaN(d)) {
+            return Double.toHexString(d);
+        } else {
+            return "NaN(0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + ")";
+        }
+    }
+
+    /**
+     * Return the floating-point value next larger in magnitude.
+     */
+    public static double nextOut(double d) {
+        if (d > 0.0) {
+            return Math.nextUp(d);
+        } else {
+            return -Math.nextUp(-d);
+        }
+    }
+
+    /**
+     * Returns unbiased exponent of a {@code float}; for subnormal values, the number is treated as
+     * if it were normalized.  That is for all finite, non-zero, positive numbers
+     * <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is
+     * always in the range [1, 2).
+     * <p>
+     * Special cases:
+     * <ul>
+     * <li> If the argument is NaN, then the result is 2<sup>30</sup>.
+     * <li> If the argument is infinite, then the result is 2<sup>28</sup>.
+     * <li> If the argument is zero, then the result is -(2<sup>28</sup>).
+     * </ul>
+     *
+     * @param d double number which exponent is to be extracted
+     * @return unbiased exponent of the argument.
+     */
+    public static int ilogb(double d) {
+        int exponent = Math.getExponent(d);
+
+        switch (exponent) {
+            case Double.MAX_EXPONENT + 1:       // NaN or infinity
+                if (Double.isNaN(d)) {
+                    return (1 << 30);         // 2^30
+                } else // infinite value
+                {
+                    return (1 << 28);         // 2^28
+                }
+
+            case Double.MIN_EXPONENT - 1:       // zero or subnormal
+                if (d == 0.0) {
+                    return -(1 << 28);        // -(2^28)
+                } else {
+                    long transducer = Double.doubleToRawLongBits(d);
+
+                    /*
+                     * To avoid causing slow arithmetic on subnormals,
+                     * the scaling to determine when d's significand
+                     * is normalized is done in integer arithmetic.
+                     * (there must be at least one "1" bit in the
+                     * significand since zero has been screened out.
+                     */
+
+                    // isolate significand bits
+                    transducer &= DoubleConsts.SIGNIF_BIT_MASK;
+                    Assert.assertNotEquals(transducer, 0L);
+
+                    // This loop is simple and functional. We might be
+                    // able to do something more clever that was faster;
+                    // e.g. number of leading zero detection on
+                    // (transducer << (# exponent and sign bits).
+                    while (transducer <
+                            (1L << (DoubleConsts.SIGNIFICAND_WIDTH - 1))) {
+                        transducer *= 2;
+                        exponent--;
+                    }
+                    exponent++;
+                    Assert.assertTrue(exponent >=
+                            Double.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH - 1) &&
+                            exponent < Double.MIN_EXPONENT);
+                    return exponent;
+                }
+
+            default:
+                Assert.assertTrue(exponent >= Double.MIN_EXPONENT &&
+                        exponent <= Double.MAX_EXPONENT);
+                return exponent;
+        }
+    }
+
+    /**
+     * Returns unbiased exponent of a {@code float}; for subnormal values, the number is treated as
+     * if it were normalized.  That is for all finite, non-zero, positive numbers
+     * <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is
+     * always in the range [1, 2).
+     * <p>
+     * Special cases:
+     * <ul>
+     * <li> If the argument is NaN, then the result is 2<sup>30</sup>.
+     * <li> If the argument is infinite, then the result is 2<sup>28</sup>.
+     * <li> If the argument is zero, then the result is -(2<sup>28</sup>).
+     * </ul>
+     *
+     * @param f floating-point number whose exponent is to be extracted
+     * @return unbiased exponent of the argument.
+     */
+    public static int ilogb(float f) {
+        int exponent = Math.getExponent(f);
+
+        switch (exponent) {
+            case Float.MAX_EXPONENT + 1:        // NaN or infinity
+                if (Float.isNaN(f)) {
+                    return (1 << 30);         // 2^30
+                } else // infinite value
+                {
+                    return (1 << 28);         // 2^28
+                }
+
+            case Float.MIN_EXPONENT - 1:        // zero or subnormal
+                if (f == 0.0f) {
+                    return -(1 << 28);        // -(2^28)
+                } else {
+                    int transducer = Float.floatToRawIntBits(f);
+
+                    /*
+                     * To avoid causing slow arithmetic on subnormals,
+                     * the scaling to determine when f's significand
+                     * is normalized is done in integer arithmetic.
+                     * (there must be at least one "1" bit in the
+                     * significand since zero has been screened out.
+                     */
+
+                    // isolate significand bits
+                    transducer &= FloatConsts.SIGNIF_BIT_MASK;
+                    Assert.assertNotEquals(transducer, 0L);
+
+                    // This loop is simple and functional. We might be
+                    // able to do something more clever that was faster;
+                    // e.g. number of leading zero detection on
+                    // (transducer << (# exponent and sign bits).
+                    while (transducer <
+                            (1 << (FloatConsts.SIGNIFICAND_WIDTH - 1))) {
+                        transducer *= 2;
+                        exponent--;
+                    }
+                    exponent++;
+                    Assert.assertTrue(exponent >=
+                            Float.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH - 1) &&
+                            exponent < Float.MIN_EXPONENT);
+                    return exponent;
+                }
+
+            default:
+                Assert.assertTrue(exponent >= Float.MIN_EXPONENT &&
+                        exponent <= Float.MAX_EXPONENT);
+                return exponent;
+        }
+    }
+
+    /**
+     * Returns {@code true} if the unordered relation holds between the two arguments.  When two
+     * floating-point values are unordered, one value is neither less than, equal to, nor greater
+     * than the other.  For the unordered relation to be true, at least one argument must be a
+     * {@code NaN}.
+     *
+     * @param arg1 the first argument
+     * @param arg2 the second argument
+     * @return {@code true} if at least one argument is a NaN, {@code false} otherwise.
+     */
+    public static boolean isUnordered(float arg1, float arg2) {
+        return Float.isNaN(arg1) || Float.isNaN(arg2);
+    }
+
+    /**
+     * Returns {@code true} if the unordered relation holds between the two arguments.  When two
+     * floating-point values are unordered, one value is neither less than, equal to, nor greater
+     * than the other.  For the unordered relation to be true, at least one argument must be a
+     * {@code NaN}.
+     *
+     * @param arg1 the first argument
+     * @param arg2 the second argument
+     * @return {@code true} if at least one argument is a NaN, {@code false} otherwise.
+     */
+    public static boolean isUnordered(double arg1, double arg2) {
+        return Double.isNaN(arg1) || Double.isNaN(arg2);
+    }
+
+    public static void test(String testName, float input,
+            boolean result, boolean expected) {
+        Assert.assertEquals(result, expected, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\n" +
+                "\tgot       " + result + ").");
+    }
+
+    public static void test(String testName, double input,
+            boolean result, boolean expected) {
+        Assert.assertEquals(result, expected, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\n" +
+                "\tgot       " + result + ").");
+    }
+
+    public static void test(String testName, float input1, float input2,
+            boolean result, boolean expected) {
+        Assert.assertEquals(result, expected, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\t(" + toHexString(input2) + ")\n" +
+                "\texpected  " + expected + "\n" +
+                "\tgot       " + result + ").");
+    }
+
+    public static void test(String testName, double input1, double input2,
+            boolean result, boolean expected) {
+        Assert.assertEquals(result, expected, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\t(" + toHexString(input2) + ")\n" +
+                "\texpected  " + expected + "\n" +
+                "\tgot       " + result + ").");
+    }
+
+    public static void test(String testName, float input,
+            int result, int expected) {
+        Assert.assertEquals(result, expected, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\n" +
+                "\tgot       " + result + ").");
+    }
+
+    public static void test(String testName, double input,
+            int result, int expected) {
+        Assert.assertEquals(result, expected, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\n" +
+                "\tgot       " + result + ").");
+    }
+
+    public static void test(String testName, float input,
+            float result, float expected) {
+        Assert.assertEquals(result, expected, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+
+    public static void test(String testName, double input,
+            double result, double expected) {
+        Assert.assertEquals(Double.compare(expected, result), 0, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+    public static void test(String testName,
+            float input1, double input2,
+            float result, float expected) {
+        Assert.assertEquals(Float.compare(expected, result), 0, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\t(" + toHexString(input2) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+    public static void test(String testName,
+            double input1, double input2,
+            double result, double expected) {
+        Assert.assertEquals(Double.compare(expected, result), 0, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\t(" + toHexString(input2) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+    public static void test(String testName,
+            float input1, int input2,
+            float result, float expected) {
+        Assert.assertEquals(Float.compare(expected, result), 0, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+    public static void test(String testName,
+            double input1, int input2,
+            double result, double expected) {
+        Assert.assertEquals(Double.compare(expected, result), 0, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+    public static void test(String testName,
+            float input1, float input2, float input3,
+            float result, float expected) {
+        Assert.assertEquals(Float.compare(expected, result), 0, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\t(" + toHexString(input2) + ") and"
+                + input3 + "\t(" + toHexString(input3) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+    public static void test(String testName,
+            double input1, double input2, double input3,
+            double result, double expected) {
+        Assert.assertEquals(Double.compare(expected, result), 0, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\t(" + toHexString(input2) + ") and"
+                + input3 + "\t(" + toHexString(input3) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ").");
+    }
+
+    static int testUlpCore(double result, double expected, double ulps) {
+        // We assume we won't be unlucky and have an inexact expected
+        // be nextDown(2^i) when 2^i would be the correctly rounded
+        // answer.  This would cause the ulp size to be half as large
+        // as it should be, doubling the measured error).
+
+        if (Double.compare(expected, result) == 0) {
+            return 0;   // result and expected are equivalent
+        } else {
+            if (ulps == 0.0) {
+                // Equivalent results required but not found
+                return 1;
+            } else {
+                double difference = expected - result;
+                if (isUnordered(expected, result) ||
+                        Double.isNaN(difference) ||
+                        // fail if greater than or unordered
+                        !(Math.abs(difference / Math.ulp(expected)) <= Math.abs(ulps))) {
+                    return 1;
+                } else {
+                    return 0;
+                }
+            }
+        }
+    }
+
+    // One input argument.
+    public static void testUlpDiff(String testName, double input,
+            double result, double expected, double ulps) {
+        int code = testUlpCore(result, expected, ulps);
+        Assert.assertEquals(code, 0, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ");\n" +
+                "\tdifference greater than ulp tolerance " + ulps);
+    }
+
+    // Two input arguments.
+    public static void testUlpDiff(String testName, double input1, double input2,
+            double result, double expected, double ulps) {
+        int code = testUlpCore(result, expected, ulps);
+        Assert.assertEquals(code, 0, "Failure for " + testName + ":\n" +
+                "\tFor inputs " + input1 + "\t(" + toHexString(input1) + ") and "
+                + input2 + "\t(" + toHexString(input2) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ");\n" +
+                "\tdifference greater than ulp tolerance " + ulps);
+    }
+
+    // For a successful test, the result must be within the ulp bound of
+    // expected AND the result must have absolute value less than or
+    // equal to absBound.
+    public static void testUlpDiffWithAbsBound(String testName, double input,
+            double result, double expected,
+            double ulps, double absBound) {
+        int code = 0;   // return code value
+
+        if (!(StrictMath.abs(result) <= StrictMath.abs(absBound)) &&
+                !Double.isNaN(expected)) {
+            code = 1;
+        } else {
+            code = testUlpCore(result, expected, ulps);
+        }
+
+        Assert.assertEquals(code, 0, "Failure for " + testName + ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                "\tgot       " + result + "\t(" + toHexString(result) + ");\n" +
+                "\tdifference greater than ulp tolerance " + ulps +
+                " or the result has larger magnitude than " + absBound);
+    }
+
+    // For a successful test, the result must be within the ulp bound of
+    // expected AND the result must have absolute value greater than
+    // or equal to the lowerBound.
+    public static void testUlpDiffWithLowerBound(String testName, double input,
+            double result, double expected,
+            double ulps, double lowerBound) {
+        int code = 0;   // return code value
+
+        if (!(result >= lowerBound) && !Double.isNaN(expected)) {
+            code = 1;
+        } else {
+            code = testUlpCore(result, expected, ulps);
+        }
+
+        Assert.assertEquals(code, 0, "Failure for " + testName +
+                ":\n" +
+                "\tFor input " + input + "\t(" + toHexString(input) + ")" +
+                "\n\texpected  " + expected + "\t(" + toHexString(expected) + ")" +
+                "\n\tgot       " + result + "\t(" + toHexString(result) + ");" +
+                "\ndifference greater than ulp tolerance " + ulps +
+                " or result not greater than or equal to the bound " + lowerBound);
+    }
+
+    public static void testTolerance(String testName, double input,
+            double result, double expected, double tolerance) {
+        if (Double.compare(expected, result) != 0) {
+            double difference = expected - result;
+            Assert.assertFalse(isUnordered(expected, result) ||
+                            Double.isNaN(difference) ||
+                            // fail if greater than or unordered
+                            !(Math.abs((difference) / expected) <= StrictMath.pow(10, -tolerance)),
+                    "Failure for " + testName + ":\n" +
+                            "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                            "\texpected  " + expected + "\t(" + toHexString(expected) + ")\n" +
+                            "\tgot       " + result + "\t(" + toHexString(result) + ");\n" +
+                            "\tdifference greater than tolerance 10^-" + tolerance);
+        }
+    }
+
+    // For a successful test, the result must be within the upper and
+    // lower bounds.
+    public static void testBounds(String testName, double input, double result,
+            double bound1, double bound2) {
+        if (!((result >= bound1 && result <= bound2) || (result <= bound1 && result >= bound2))) {
+            double lowerBound = Math.min(bound1, bound2);
+            double upperBound = Math.max(bound1, bound2);
+            Assert.fail("Failure for " + testName + ":\n" +
+                    "\tFor input " + input + "\t(" + toHexString(input) + ")\n" +
+                    "\tgot       " + result + "\t(" + toHexString(result) + ");\n" +
+                    "\toutside of range\n" +
+                    "\t[" + lowerBound + "\t(" + toHexString(lowerBound) + "), " +
+                    upperBound + "\t(" + toHexString(upperBound) + ")]");
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/Math/WorstCaseTests.java b/ojluni/src/test/java/lang/Math/WorstCaseTests.java
new file mode 100644
index 0000000..47c0a2f
--- /dev/null
+++ b/ojluni/src/test/java/lang/Math/WorstCaseTests.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4900206
+ * @summary Test worst case behavior of exp, log, sin, cos, etc.
+ * @build Tests
+ * @build WorstCaseTests
+ * @run main WorstCaseTests
+ * @run main/othervm -Xcomp WorstCaseTests
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.Math;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * Use "Table Maker's Dilemma" results from Jean-Michel Muller and Vincent Lef&egrave;vre, to test
+ * the math library.  See http://perso.ens-lyon.fr/jean-michel.muller/TMD.html for original test
+ * vectors from 2000 and see http://perso.ens-lyon.fr/jean-michel.muller/TMDworstcases.pdf with
+ * additional test vectors from 2003.  The latter link also contains some information about the
+ * methodology used to produce the test vectors.
+ *
+ * Most of the Java math library methods tested here have a 1-ulp error bound from their
+ * specifications.  This implies the returned value must be one of the two representable
+ * floating-point numbers bracketing the exact result.  The expected value in the test vectors below
+ * is the truncation of the exact value.  Therefore, the computed result must either be that value
+ * or the value next larger in magnitude.  The hyperbolic transcendental functions sinh and cosh
+ * have a larger 2.5 ulp error bound in their specification, but the JDK implementation complies
+ * with a 1 ulp bound on the worst-case values.  Therefore, no addition leeway is afforded when
+ * testing sinh and cosh.
+ */
+public class WorstCaseTests {
+
+    private WorstCaseTests() {
+    }
+
+    @Test
+    public void testWorstExp() {
+        double[][] testCases = {
+                {-0x1.E8BDBFCD9144Ep3, 0x1.F3E558CF4DE54p-23},
+                {-0x1.71E0B869B5E79p2, 0x1.951C6DC5D24E2p-9},
+                {-0x1.02393D5976769p1, 0x1.1064B2C103DDAp-3},
+                {-0x1.2A9CAD9998262p0, 0x1.3EF1E9B3A81C7p-2},
+                {-0x1.CC37EF7DE7501p0, 0x1.534D4DE870713p-3},
+                {-0x1.22E24FA3D5CF9p-1, 0x1.2217147B85EA9p-1},
+                {-0x1.DC2B5DF1F7D3Dp-1, 0x1.9403FD0EE51C8p-2},
+                {-0x1.290EA09E36479p-3, 0x1.BADED30CBF1C3p-1},
+                {-0x1.A2FEFEFD580DFp-13, 0x1.FFE5D0BB7EABFp-1},
+                {-0x1.ED318EFB627EAp-27, 0x1.FFFFFF84B39C4p-1},
+                {-0x1.4BD46601AE1EFp-31, 0x1.FFFFFFFAD0AE6p-1},
+                {-0x1.1000000000242p-42, 0x1.FFFFFFFFFF780p-1},
+                {-0x1.2000000000288p-42, 0x1.FFFFFFFFFF700p-1},
+                {-0x1.8000000000012p-48, 0x1.FFFFFFFFFFFD0p-1},
+                {-0x1.0000000000001p-51, 0x1.FFFFFFFFFFFFCp-1},
+
+                {+0x1.FFFFFFFFFFFFFp-53, 0x1.0000000000000p0},
+                {+0x1.FFFFFFFFFFFE0p-48, 0x1.000000000001Fp0},
+                {+0x1.7FFE7FFEE0024p-32, 0x1.000000017FFE8p0},
+                {+0x1.80017FFEDFFDCp-32, 0x1.0000000180017p0},
+                {+0x1.9E9CBBFD6080Bp-31, 0x1.000000033D397p0},
+                {+0x1.D7A7D893609E5p-26, 0x1.00000075E9F64p0},
+                {+0x1.BA07D73250DE7p-14, 0x1.0006E83736F8Cp0},
+                {+0x1.D77FD13D27FFFp-11, 0x1.003AF6C37C1D3p0},
+                {+0x1.6A4D1AF9CC989p-8, 0x1.016B4DF3299D7p0},
+                {+0x1.ACCFBE46B4EF0p-1, 0x2.4F85C9783DCE0p0},
+                {+0x1.ACA7AE8DA5A7Bp0, 0x5.55F52B35F955Ap0},
+                {+0x1.D6336A88077AAp0, 0x6.46A37FD503FDCp0},
+                {+0x2.85DC78FB8928Cp0, 0xC.76F2496CB038Fp0},
+                {+0x1.76E7E5D7B6EACp3, 0x1.DE7CD6751029Ap16},
+                {+0x1.A8EAD058BC6B8p3, 0x1.1D71965F516ADp19},
+                {+0x1.1D5C2DAEBE367p4, 0x1.A8C02E974C314p25},
+                {+0x1.C44CE0D716A1Ap4, 0x1.B890CA8637AE1p40},
+        };
+
+        for (double[] testCase : testCases) {
+            testExpCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testExpCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.exp", input, Math.exp(input), expected, out);
+        Tests.testBounds("StrictMath.exp", input, StrictMath.exp(input), expected, out);
+    }
+
+    @Test
+    public void testWorstLog() {
+        double[][] testCases = {
+                {+0x1.0000000000001p0, +0x1.FFFFFFFFFFFFFp-53},
+                {+0x2.0012ECB039C9Cp0, +0x1.62F71C4656B60p-1},
+                {+0x6.46A37FD503FDCp0, +0x1.D6336A88077A9p+0},
+                {+0x7.78DFECC7F57Fp0, +0x2.02DD059DB46Bp+0},
+                {+0x9.588CCF24BB9C8p0, +0x2.3C24DEBB2BE7p+0},
+                {+0xA.AF87550D97E4p0, +0x2.5E706595A7ABEp+0},
+                {+0xC.76F2496CB039p0, +0x2.85DC78FB8928Cp+0},
+                {+0x11.1867637CBD03p0, +0x2.D6BBEFC79A842p+0},
+                {+0x13.D9D7D597A9DDp0, +0x2.FCFE12AE07DDCp+0},
+                {+0x17.F3825778AAAFp0, +0x3.2D0F907F5E00Cp+0},
+                {+0x1AC.50B409C8AEEp0, +0x6.0F52F37AECFCCp+0},
+                {+0x1.DE7CD6751029Ap16, +0x1.76E7E5D7B6EABp+3},
+        };
+
+        for (double[] testCase : testCases) {
+            testLogCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testLogCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.log", input, Math.log(input), expected, out);
+        Tests.testBounds("StrictMath.log", input, StrictMath.log(input), expected, out);
+    }
+
+    @Test
+    public void testWorstSin() {
+        double[][] testCases = {
+                {+0x1.E0000000001C2p-20, +0x1.DFFFFFFFFF02Ep-20},
+                {+0x1.598BAE9E632F6p-7, +0x1.598A0AEA48996p-7},
+
+                {+0x1.9283586503FEp-5, +0x1.9259E3708BD39p-5},
+                {+0x1.D7BDCD778049Fp-5, +0x1.D77B117F230D5p-5},
+                {+0x1.A202B3FB84788p-4, +0x1.A1490C8C06BA6p-4},
+                {+0x1.D037CB27EE6DFp-3, +0x1.CC40C3805229Ap-3},
+                {+0x1.D5064E6FE82C5p-3, +0x1.D0EF799001BA9p-3},
+                {+0x1.FE767739D0F6Dp-2, +0x1.E9950730C4695p-2},
+                {+0x1.D98C4C612718Dp-1, +0x1.98DCD09337792p-1},
+                {+0x1.921FB54442D18p-0, +0x1.FFFFFFFFFFFFFp-1},
+
+                {+0x1.6756745770A51p+1, +0x1.4FF350E412821p-2},
+        };
+
+        for (double[] testCase : testCases) {
+            testSinCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testSinCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.sin", input, Math.sin(input), expected, out);
+        Tests.testBounds("StrictMath.sin", input, StrictMath.sin(input), expected, out);
+    }
+
+    @Test
+    public void testWorstAsin() {
+        double[][] testCases = {
+                {+0x1.DFFFFFFFFF02Ep-20, +0x1.E0000000001C1p-20},
+                {+0x1.DFFFFFFFFC0B8p-19, +0x1.E000000000707p-19},
+
+                {+0x1.9259E3708BD3Ap-5, +0x1.9283586503FEp-5},
+                {+0x1.D77B117F230D6p-5, +0x1.D7BDCD778049Fp-5},
+                {+0x1.A1490C8C06BA7p-4, +0x1.A202B3FB84788p-4},
+                {+0x1.9697CB602C582p-3, +0x1.994FFB5DAF0F9p-3},
+                {+0x1.D0EF799001BA9p-3, +0x1.D5064E6FE82C4p-3},
+                {+0x1.E9950730C4696p-2, +0x1.FE767739D0F6Dp-2},
+                {+0x1.1ED06D50F7E88p-1, +0x1.30706F699466Dp-1},
+                {+0x1.D5B05A89D3E77p-1, +0x1.29517AB4C132Ap+0},
+                {+0x1.E264357EA0E29p-1, +0x1.3AA301F6EBB1Dp+0},
+        };
+
+        for (double[] testCase : testCases) {
+            testAsinCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testAsinCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.asin", input, Math.asin(input), expected, out);
+        Tests.testBounds("StrictMath.asin", input, StrictMath.asin(input), expected, out);
+    }
+
+    @Test
+    public void testWorstCos() {
+        double[][] testCases = {
+                {+0x1.8000000000009p-23, +0x0.FFFFFFFFFFFB8p+0},
+                {+0x1.8000000000024p-22, +0x0.FFFFFFFFFFEE0p+0},
+                {+0x1.2000000000F30p-18, +0x0.FFFFFFFFF5E00p+0},
+                {+0x1.06B505550E6B2p-9, +0x0.FFFFDE4D1FDFFp+0},
+                {+0x1.97CCD3D2C438Fp-6, +0x0.FFEBB35D43854p+0},
+
+                {+0x1.549EC0C0C5AFAp-5, +0x1.FF8EB6A91ECB0p-1},
+                {+0x1.16E534EE36580p-4, +0x1.FED0476FC75C9p-1},
+                {+0x1.EFEEF61D39AC2p-3, +0x1.F10FC61E2C78Ep-1},
+                {+0x1.FEB1F7920E248p-2, +0x1.C1A27AE836F12p-1},
+                {+0x1.7CB7648526F99p-1, +0x1.78DAF01036D0Cp-1},
+                {+0x1.C65A170474549p-1, +0x1.434A3645BE208p-1},
+                {+0x1.6B8A6273D7C21p+0, +0x1.337FC5B072C52p-3},
+        };
+
+        for (double[] testCase : testCases) {
+            testCosCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testCosCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.cos", input, Math.cos(input), expected, out);
+        Tests.testBounds("StrictMath.cos", input, StrictMath.cos(input), expected, out);
+    }
+
+    @Test
+    public void testWorstAcos() {
+        double[][] testCases = {
+                {+0x1.FD737BE914578p-11, +0x1.91E006D41D8D8p+0},
+                {+0x1.4182199998587p-1, +0x1.C8A538AE83D1Fp-1},
+                {+0x1.E45A1C93651ECp-1, +0x1.520DC553F6B23p-2},
+                {+0x1.F10FC61E2C78Fp-1, +0x1.EFEEF61D39AC1p-3},
+        };
+
+        for (double[] testCase : testCases) {
+            testAcosCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testAcosCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.acos", input, Math.acos(input), expected, out);
+        Tests.testBounds("StrictMath.acos", input, StrictMath.acos(input), expected, out);
+    }
+
+    @Test
+    public void testWorstTan() {
+        double[][] testCases = {
+                {+0x1.DFFFFFFFFFF1Fp-22, +0x1.E000000000151p-22},
+                {+0x1.67FFFFFFFA114p-18, +0x1.6800000008E61p-18},
+
+                {+0x1.50486B2F87014p-5, +0x1.5078CEBFF9C72p-5},
+                {+0x1.52C39EF070CADp-4, +0x1.5389E6DF41978p-4},
+                {+0x1.A33F32AC5CEB5p-3, +0x1.A933FE176B375p-3},
+                {+0x1.D696BFA988DB9p-2, +0x1.FAC71CD34EEA6p-2},
+                {+0x1.46AC372243536p-1, +0x1.7BA49F739829Ep-1},
+                {+0x0.A3561B9121A9Bp+0, +0x0.BDD24FB9CC14Fp+0},
+        };
+
+        for (double[] testCase : testCases) {
+            testTanCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testTanCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.tan", input, Math.tan(input), expected, out);
+        Tests.testBounds("StrictMath.tan", input, StrictMath.tan(input), expected, out);
+    }
+
+    @Test
+    public void testWorstAtan() {
+        double[][] testCases = {
+                {+0x1.E000000000546p-21, +0x1.DFFFFFFFFFC7Cp-21},
+                {+0x1.22E8D75E2BC7Fp-11, +0x1.22E8D5694AD2Bp-11},
+
+                {+0x1.0FC9F1FABE658p-5, +0x1.0FB06EDE9973Ap-5},
+                {+0x1.1BBE9C255698Dp-5, +0x1.1BA1951DB1D6Dp-5},
+                {+0x1.8DDD25AB90CA1p-5, +0x1.8D8D2D4BD6FA2p-5},
+                {+0x1.5389E6DF41979p-4, +0x1.52C39EF070CADp-4},
+                {+0x1.A933FE176B375p-3, +0x1.A33F32AC5CEB4p-3},
+                {+0x1.0F6E5D9960397p-2, +0x1.09544B71AD4A6p-2},
+                {+0x1.7BA49F739829Fp-1, +0x1.46AC372243536p-1},
+
+                {+0x0.BDD24FB9CC14F8p+0, +0x0.A3561B9121A9Bp+0},
+        };
+
+        for (double[] testCase : testCases) {
+            testAtanCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testAtanCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.atan", input, Math.atan(input), expected, out);
+        Tests.testBounds("StrictMath.atan", input, StrictMath.atan(input), expected, out);
+    }
+
+    @Test
+    public void testWorstPow2() {
+        double[][] testCases = {
+                {+0x1.16A76EC41B516p-1, +0x1.7550685A42C63p+0},
+                {+0x1.3E34FA6AB969Ep-1, +0x1.89D948A94FE16p+0},
+                {+0x1.4A63FF1D53F53p-1, +0x1.90661DA12D528p+0},
+                {+0x1.B32A6C92D1185p-1, +0x1.CD6B37EDECEAFp+0},
+
+                {+0x1.25DD9EEDAC79Ap+0, +0x1.1BA39FF28E3E9p+1},
+        };
+
+        for (double[] testCase : testCases) {
+            testPow2Case(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testPow2Case(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.pow2", input, Math.pow(2, input), expected, out);
+        Tests.testBounds("StrictMath.pow2", input, StrictMath.pow(2, input), expected, out);
+    }
+
+    // 2.5 ulp error bound in the specification; the implementation
+    // does better on the tested values.
+    @Test
+    public void testWorstSinh() {
+        double[][] testCases = {
+                {+0x1.DFFFFFFFFFE3Ep-20, +0x1.E000000000FD1p-20},
+                {+0x1.DFFFFFFFFE3E0p-18, +0x1.E00000000FD1Fp-18},
+                {+0x1.135E31FDD05D3p-5, +0x1.136B78B25CC57p-5},
+                {+0x1.0DC68D5E8F959p-3, +0x1.0E8E73DC4FEE3p-3},
+                {+0x1.616CC75D49226p-2, +0x1.687BD068C1C1Ep-2},
+                {+0x1.3FFC12B81CBC2p+0, +0x1.9A0FF413A1AF2p+0},
+                {+0x2.FE008C44BACA2p+0, +0x9.F08A43ED03AEp+0},
+                {+0x1.C089FCF166171p+4, +0x1.5C452E0E37569p+39},
+                {+0x1.E07E71BFCF06Fp+5, +0x1.91EC4412C344Fp+85},
+                {+0x1.54CD1FEA7663Ap+7, +0x1.C90810D354618p+244},
+                {+0x1.D6479EBA7C971p+8, +0x1.62A88613629B5p+677},
+        };
+
+        for (double[] testCase : testCases) {
+            testSinhCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testSinhCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.sinh", input, Math.sinh(input), expected, out);
+        Tests.testBounds("StrictMath.sinh", input, StrictMath.sinh(input), expected, out);
+    }
+
+    // 2.5 ulp error bound in the specification; the implementation
+    // does better on the tested values.
+    @Test
+    public void testWorstCosh() {
+        double[][] testCases = {
+                {+0x1.17D8A9F206217p-6, +0x1.00098F5F09BE3p+0},
+                {+0x1.BF0305E2C6C37p-3, +0x1.061F4C39E16F2p+0},
+                {+0x1.03923F2B47C07p-1, +0x1.219C1989E3372p+0},
+                {+0x1.A6031CD5F93BAp-1, +0x1.5BFF041B260FDp+0},
+                {+0x1.104B648F113A1p+0, +0x1.9EFDCA62B7009p+0},
+                {+0x1.EA5F2F2E4B0C5p+1, +0x17.10DB0CD0FED5p+0},
+        };
+
+        for (double[] testCase : testCases) {
+            testCoshCase(testCase[0], testCase[1]);
+        }
+    }
+
+    private static void testCoshCase(double input, double expected) {
+        double out = Tests.nextOut(expected);
+        Tests.testBounds("Math.cosh", input, Math.cosh(input), expected, out);
+        Tests.testBounds("StrictMath.cosh", input, StrictMath.cosh(input), expected, out);
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/CubeRootTests.java b/ojluni/src/test/java/lang/StrictMath/CubeRootTests.java
new file mode 100644
index 0000000..0114574
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/CubeRootTests.java
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4347132 8136799
+ * @key randomness
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @build Tests
+ * @build FdlibmTranslit
+ * @build CubeRootTests
+ * @run main CubeRootTests
+ * @summary Tests specifically for StrictMath.cbrt
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.StrictMath;
+
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+/**
+ * The tests in ../Math/CubeRootTests.java test properties that should hold for any cube root
+ * implementation, including the FDLIBM-based one required for StrictMath.cbrt.  Therefore, the test
+ * cases in ../Math/CubeRootTests.java are run against both the Math and StrictMath versions of cube
+ * root.  The role of this test is to verify that the FDLIBM cbrt algorithm is being used by running
+ * golden file tests on values that may vary from one conforming cube root implementation to
+ * another.
+ */
+
+public class CubeRootTests {
+
+    private CubeRootTests() {
+    }
+
+    static void testCubeRootCase(double input, double expected) {
+        double minus_input = -input;
+        double minus_expected = -expected;
+
+        Tests.test("StrictMath.cbrt(double)", input,
+                StrictMath.cbrt(input), expected);
+        Tests.test("StrictMath.cbrt(double)", minus_input,
+                StrictMath.cbrt(minus_input), minus_expected);
+    }
+
+    @Test
+    public void testCubeRoot() {
+        int failures = 0;
+        double[][] testCases = {
+                {0x1.ffffffffffffep-766, 0x1.fffffffffffffp-256},
+                {0x1.ffffffffffffep-763, 0x1.fffffffffffffp-255},
+                {0x1.ffffffffffffep-760, 0x1.fffffffffffffp-254},
+                {0x1.ffffffffffffep-757, 0x1.fffffffffffffp-253},
+                {0x1.ffffffffffffep-754, 0x1.fffffffffffffp-252},
+                {0x1.ffffffffffffep-751, 0x1.fffffffffffffp-251},
+                {0x1.ffffffffffffep-748, 0x1.fffffffffffffp-250},
+                {0x1.ffffffffffffep-745, 0x1.fffffffffffffp-249},
+                {0x1.ffffffffffffep-742, 0x1.fffffffffffffp-248},
+                {0x1.ffffffffffffep-739, 0x1.fffffffffffffp-247},
+                {0x1.ffffffffffffep-1006, 0x1.fffffffffffffp-336},
+                {0x1.ffffffffffffep-736, 0x1.fffffffffffffp-246},
+                {0x1.ffffffffffffep-733, 0x1.fffffffffffffp-245},
+                {0x1.ffffffffffffep-730, 0x1.fffffffffffffp-244},
+                {0x1.ffffffffffffep-727, 0x1.fffffffffffffp-243},
+                {0x1.ffffffffffffep-724, 0x1.fffffffffffffp-242},
+                {0x1.ffffffffffffep-721, 0x1.fffffffffffffp-241},
+                {0x1.ffffffffffffep-718, 0x1.fffffffffffffp-240},
+                {0x1.ffffffffffffep-715, 0x1.fffffffffffffp-239},
+                {0x1.ffffffffffffep-712, 0x1.fffffffffffffp-238},
+                {0x1.ffffffffffffep-709, 0x1.fffffffffffffp-237},
+                {0x1.ffffffffffffep-706, 0x1.fffffffffffffp-236},
+                {0x1.ffffffffffffep-703, 0x1.fffffffffffffp-235},
+                {0x1.ffffffffffffep-700, 0x1.fffffffffffffp-234},
+                {0x1.ffffffffffffep-697, 0x1.fffffffffffffp-233},
+                {0x1.ffffffffffffep-694, 0x1.fffffffffffffp-232},
+                {0x1.ffffffffffffep-691, 0x1.fffffffffffffp-231},
+                {0x1.ffffffffffffep-1003, 0x1.fffffffffffffp-335},
+                {0x1.ffffffffffffep-688, 0x1.fffffffffffffp-230},
+                {0x1.ffffffffffffep-685, 0x1.fffffffffffffp-229},
+                {0x1.ffffffffffffep-682, 0x1.fffffffffffffp-228},
+                {0x1.ffffffffffffep-679, 0x1.fffffffffffffp-227},
+                {0x1.ffffffffffffep-676, 0x1.fffffffffffffp-226},
+                {0x1.ffffffffffffep-673, 0x1.fffffffffffffp-225},
+                {0x1.ffffffffffffep-670, 0x1.fffffffffffffp-224},
+                {0x1.ffffffffffffep-667, 0x1.fffffffffffffp-223},
+                {0x1.ffffffffffffep-664, 0x1.fffffffffffffp-222},
+                {0x1.ffffffffffffep-661, 0x1.fffffffffffffp-221},
+                {0x1.ffffffffffffep-658, 0x1.fffffffffffffp-220},
+                {0x1.ffffffffffffep-655, 0x1.fffffffffffffp-219},
+                {0x1.ffffffffffffep-652, 0x1.fffffffffffffp-218},
+                {0x1.ffffffffffffep-649, 0x1.fffffffffffffp-217},
+                {0x1.ffffffffffffep-646, 0x1.fffffffffffffp-216},
+                {0x1.ffffffffffffep-643, 0x1.fffffffffffffp-215},
+                {0x1.ffffffffffffep-1000, 0x1.fffffffffffffp-334},
+                {0x1.ffffffffffffep-640, 0x1.fffffffffffffp-214},
+                {0x1.ffffffffffffep-637, 0x1.fffffffffffffp-213},
+                {0x1.ffffffffffffep-634, 0x1.fffffffffffffp-212},
+                {0x1.ffffffffffffep-631, 0x1.fffffffffffffp-211},
+                {0x1.ffffffffffffep-628, 0x1.fffffffffffffp-210},
+                {0x1.ffffffffffffep-625, 0x1.fffffffffffffp-209},
+                {0x1.ffffffffffffep-622, 0x1.fffffffffffffp-208},
+                {0x1.ffffffffffffep-619, 0x1.fffffffffffffp-207},
+                {0x1.ffffffffffffep-616, 0x1.fffffffffffffp-206},
+                {0x1.ffffffffffffep-613, 0x1.fffffffffffffp-205},
+                {0x1.ffffffffffffep-610, 0x1.fffffffffffffp-204},
+                {0x1.ffffffffffffep-607, 0x1.fffffffffffffp-203},
+                {0x1.ffffffffffffep-604, 0x1.fffffffffffffp-202},
+                {0x1.ffffffffffffep-601, 0x1.fffffffffffffp-201},
+                {0x1.ffffffffffffep-598, 0x1.fffffffffffffp-200},
+                {0x1.ffffffffffffep-595, 0x1.fffffffffffffp-199},
+                {0x1.ffffffffffffep-997, 0x1.fffffffffffffp-333},
+                {0x1.ffffffffffffep-592, 0x1.fffffffffffffp-198},
+                {0x1.ffffffffffffep-589, 0x1.fffffffffffffp-197},
+                {0x1.ffffffffffffep-586, 0x1.fffffffffffffp-196},
+                {0x1.ffffffffffffep-583, 0x1.fffffffffffffp-195},
+                {0x1.ffffffffffffep-580, 0x1.fffffffffffffp-194},
+                {0x1.ffffffffffffep-577, 0x1.fffffffffffffp-193},
+                {0x1.ffffffffffffep-574, 0x1.fffffffffffffp-192},
+                {0x1.ffffffffffffep-571, 0x1.fffffffffffffp-191},
+                {0x1.ffffffffffffep-568, 0x1.fffffffffffffp-190},
+                {0x1.ffffffffffffep-565, 0x1.fffffffffffffp-189},
+                {0x1.ffffffffffffep-562, 0x1.fffffffffffffp-188},
+                {0x1.ffffffffffffep-559, 0x1.fffffffffffffp-187},
+                {0x1.ffffffffffffep-556, 0x1.fffffffffffffp-186},
+                {0x1.ffffffffffffep-553, 0x1.fffffffffffffp-185},
+                {0x1.ffffffffffffep-550, 0x1.fffffffffffffp-184},
+                {0x1.ffffffffffffep-547, 0x1.fffffffffffffp-183},
+                {0x1.ffffffffffffep-994, 0x1.fffffffffffffp-332},
+                {0x1.ffffffffffffep-544, 0x1.fffffffffffffp-182},
+                {0x1.ffffffffffffep-541, 0x1.fffffffffffffp-181},
+                {0x1.ffffffffffffep-538, 0x1.fffffffffffffp-180},
+                {0x1.ffffffffffffep-535, 0x1.fffffffffffffp-179},
+                {0x1.ffffffffffffep-532, 0x1.fffffffffffffp-178},
+                {0x1.ffffffffffffep-529, 0x1.fffffffffffffp-177},
+                {0x0.00000000001fp-1022, 0x1.fa9c313858568p-356},
+                {0x1.ffffffffffffep-526, 0x1.fffffffffffffp-176},
+                {0x1.ffffffffffffep-523, 0x1.fffffffffffffp-175},
+                {0x1.ffffffffffffep-520, 0x1.fffffffffffffp-174},
+                {0x1.ffffffffffffep-517, 0x1.fffffffffffffp-173},
+                {0x0.00000000001fdp-1022, 0x1.feff7f94ea34dp-356},
+                {0x1.ffffffffffffep-514, 0x1.fffffffffffffp-172},
+                {0x0.00000001fffe7p-1022, 0x1.ffff7aaa87f1bp-352},
+                {0x0.00000001fffffp-1022, 0x1.fffffaaaaa9c7p-352},
+                {0x0.00001ffffff4p-1022, 0x1.ffffffcp-348},
+                {0x0.00001ffffffffp-1022, 0x1.ffffffffaaaabp-348},
+                {0x0.01ffffffffffcp-1022, 0x1.ffffffffffeabp-344},
+                {0x1.ffffffffffffep-511, 0x1.fffffffffffffp-171},
+                {0x1.ffffffffffffep-508, 0x1.fffffffffffffp-170},
+                {0x1.ffffffffffffep-505, 0x1.fffffffffffffp-169},
+                {0x1.ffffffffffffep-502, 0x1.fffffffffffffp-168},
+                {0x1.ffffffffffffep-499, 0x1.fffffffffffffp-167},
+                {0x1.ffffffffffffep-991, 0x1.fffffffffffffp-331},
+                {0x1.ffffffffffffep-496, 0x1.fffffffffffffp-166},
+                {0x1.ffffffffffffep-493, 0x1.fffffffffffffp-165},
+                {0x1.ffffffffffffep-490, 0x1.fffffffffffffp-164},
+                {0x1.ffffffffffffep-487, 0x1.fffffffffffffp-163},
+                {0x1.ffffffffffffep-484, 0x1.fffffffffffffp-162},
+                {0x1.ffffffffffffep-481, 0x1.fffffffffffffp-161},
+                {0x1.ffffffffffffep-478, 0x1.fffffffffffffp-160},
+                {0x1.ffffffffffffep-475, 0x1.fffffffffffffp-159},
+                {0x1.ffffffffffffep-472, 0x1.fffffffffffffp-158},
+                {0x1.ffffffffffffep-469, 0x1.fffffffffffffp-157},
+                {0x1.ffffffffffffep-466, 0x1.fffffffffffffp-156},
+                {0x1.ffffffffffffep-463, 0x1.fffffffffffffp-155},
+                {0x1.ffffffffffffep-460, 0x1.fffffffffffffp-154},
+                {0x1.ffffffffffffep-457, 0x1.fffffffffffffp-153},
+                {0x1.ffffffffffffep-454, 0x1.fffffffffffffp-152},
+                {0x1.ffffffffffffep-451, 0x1.fffffffffffffp-151},
+                {0x1.ffffffffffffep-988, 0x1.fffffffffffffp-330},
+                {0x1.ffffffffffffep-448, 0x1.fffffffffffffp-150},
+                {0x1.ffffffffffffep-445, 0x1.fffffffffffffp-149},
+                {0x1.ffffffffffffep-442, 0x1.fffffffffffffp-148},
+                {0x1.ffffffffffffep-439, 0x1.fffffffffffffp-147},
+                {0x1.ffffffffffffep-436, 0x1.fffffffffffffp-146},
+                {0x1.ffffffffffffep-433, 0x1.fffffffffffffp-145},
+                {0x1.ffffffffffffep-430, 0x1.fffffffffffffp-144},
+                {0x1.ffffffffffffep-427, 0x1.fffffffffffffp-143},
+                {0x1.ffffffffffffep-424, 0x1.fffffffffffffp-142},
+                {0x1.ffffffffffffep-421, 0x1.fffffffffffffp-141},
+                {0x1.ffffffffffffep-418, 0x1.fffffffffffffp-140},
+                {0x1.ffffffffffffep-415, 0x1.fffffffffffffp-139},
+                {0x1.ffffffffffffep-412, 0x1.fffffffffffffp-138},
+                {0x1.ffffffffffffep-409, 0x1.fffffffffffffp-137},
+                {0x1.ffffffffffffep-406, 0x1.fffffffffffffp-136},
+                {0x1.ffffffffffffep-403, 0x1.fffffffffffffp-135},
+                {0x1.ffffffffffffep-985, 0x1.fffffffffffffp-329},
+                {0x1.ffffffffffffep-400, 0x1.fffffffffffffp-134},
+                {0x1.ffffffffffffep-397, 0x1.fffffffffffffp-133},
+                {0x1.ffffffffffffep-394, 0x1.fffffffffffffp-132},
+                {0x1.ffffffffffffep-391, 0x1.fffffffffffffp-131},
+                {0x1.ffffffffffffep-388, 0x1.fffffffffffffp-130},
+                {0x1.ffffffffffffep-385, 0x1.fffffffffffffp-129},
+                {0x1.ffffffffffffep-382, 0x1.fffffffffffffp-128},
+                {0x1.ffffffffffffep-379, 0x1.fffffffffffffp-127},
+                {0x1.ffffffffffffep-376, 0x1.fffffffffffffp-126},
+                {0x1.ffffffffffffep-373, 0x1.fffffffffffffp-125},
+                {0x1.ffffffffffffep-370, 0x1.fffffffffffffp-124},
+                {0x1.ffffffffffffep-367, 0x1.fffffffffffffp-123},
+                {0x1.ffffffffffffep-364, 0x1.fffffffffffffp-122},
+                {0x1.ffffffffffffep-361, 0x1.fffffffffffffp-121},
+                {0x1.ffffffffffffep-358, 0x1.fffffffffffffp-120},
+                {0x1.ffffffffffffep-355, 0x1.fffffffffffffp-119},
+                {0x1.ffffffffffffep-982, 0x1.fffffffffffffp-328},
+                {0x1.ffffffffffffep-352, 0x1.fffffffffffffp-118},
+                {0x1.ffffffffffffep-349, 0x1.fffffffffffffp-117},
+                {0x1.ffffffffffffep-346, 0x1.fffffffffffffp-116},
+                {0x1.ffffffffffffep-343, 0x1.fffffffffffffp-115},
+                {0x1.ffffffffffffep-340, 0x1.fffffffffffffp-114},
+                {0x1.ffffffffffffep-337, 0x1.fffffffffffffp-113},
+                {0x1.ffffffffffffep-334, 0x1.fffffffffffffp-112},
+                {0x1.ffffffffffffep-331, 0x1.fffffffffffffp-111},
+                {0x1.ffffffffffffep-328, 0x1.fffffffffffffp-110},
+                {0x1.ffffffffffffep-325, 0x1.fffffffffffffp-109},
+                {0x1.ffffffffffffep-322, 0x1.fffffffffffffp-108},
+                {0x1.ffffffffffffep-319, 0x1.fffffffffffffp-107},
+                {0x1.ffffffffffffep-316, 0x1.fffffffffffffp-106},
+                {0x1.ffffffffffffep-313, 0x1.fffffffffffffp-105},
+                {0x1.ffffffffffffep-310, 0x1.fffffffffffffp-104},
+                {0x1.ffffffffffffep-307, 0x1.fffffffffffffp-103},
+                {0x1.ffffffffffffep-979, 0x1.fffffffffffffp-327},
+                {0x1.ffffffffffffep-304, 0x1.fffffffffffffp-102},
+                {0x1.ffffffffffffep-301, 0x1.fffffffffffffp-101},
+                {0x1.ffffffffffffep-298, 0x1.fffffffffffffp-100},
+                {0x1.ffffffffffffep-295, 0x1.fffffffffffffp-99},
+                {0x1.ffffffffffffep-292, 0x1.fffffffffffffp-98},
+                {0x1.ffffffffffffep-289, 0x1.fffffffffffffp-97},
+                {0x1.ffffffffffffep-286, 0x1.fffffffffffffp-96},
+                {0x1.ffffffffffffep-283, 0x1.fffffffffffffp-95},
+                {0x1.ffffffffffffep-280, 0x1.fffffffffffffp-94},
+                {0x1.ffffffffffffep-277, 0x1.fffffffffffffp-93},
+                {0x1.ffffffffffffep-274, 0x1.fffffffffffffp-92},
+                {0x1.ffffffffffffep-271, 0x1.fffffffffffffp-91},
+                {0x1.ffffffffffffep-268, 0x1.fffffffffffffp-90},
+                {0x1.ffffffffffffep-265, 0x1.fffffffffffffp-89},
+                {0x1.ffffffffffffep-262, 0x1.fffffffffffffp-88},
+                {0x1.ffffffffffffep-259, 0x1.fffffffffffffp-87},
+                {0x1.ffffffffffffep-1021, 0x1.fffffffffffffp-341},
+                {0x1.ffffffffffffep-976, 0x1.fffffffffffffp-326},
+                {0x1.ffffffffffffep-256, 0x1.fffffffffffffp-86},
+                {0x1.ffffffffffffep-253, 0x1.fffffffffffffp-85},
+                {0x1.ffffffffffffep-250, 0x1.fffffffffffffp-84},
+                {0x1.ffffffffffffep-247, 0x1.fffffffffffffp-83},
+                {0x1.ffffffffffffep-244, 0x1.fffffffffffffp-82},
+                {0x1.ffffffffffffep-241, 0x1.fffffffffffffp-81},
+                {0x1.ffffffffffffep-238, 0x1.fffffffffffffp-80},
+                {0x1.ffffffffffffep-235, 0x1.fffffffffffffp-79},
+                {0x1.ffffffffffffep-232, 0x1.fffffffffffffp-78},
+                {0x1.ffffffffffffep-229, 0x1.fffffffffffffp-77},
+                {0x1.ffffffffffffep-226, 0x1.fffffffffffffp-76},
+                {0x1.ffffffffffffep-223, 0x1.fffffffffffffp-75},
+                {0x1.ffffffffffffep-220, 0x1.fffffffffffffp-74},
+                {0x1.ffffffffffffep-217, 0x1.fffffffffffffp-73},
+                {0x1.ffffffffffffep-214, 0x1.fffffffffffffp-72},
+                {0x1.ffffffffffffep-211, 0x1.fffffffffffffp-71},
+                {0x1.ffffffffffffep-973, 0x1.fffffffffffffp-325},
+                {0x1.ffffffffffffep-208, 0x1.fffffffffffffp-70},
+                {0x1.ffffffffffffep-205, 0x1.fffffffffffffp-69},
+                {0x1.ffffffffffffep-202, 0x1.fffffffffffffp-68},
+                {0x1.ffffffffffffep-199, 0x1.fffffffffffffp-67},
+                {0x1.ffffffffffffep-196, 0x1.fffffffffffffp-66},
+                {0x1.ffffffffffffep-193, 0x1.fffffffffffffp-65},
+                {0x1.ffffffffffffep-190, 0x1.fffffffffffffp-64},
+                {0x1.ffffffffffffep-187, 0x1.fffffffffffffp-63},
+                {0x1.ffffffffffffep-184, 0x1.fffffffffffffp-62},
+                {0x1.ffffffffffffep-181, 0x1.fffffffffffffp-61},
+                {0x1.ffffffffffffep-178, 0x1.fffffffffffffp-60},
+                {0x1.ffffffffffffep-175, 0x1.fffffffffffffp-59},
+                {0x1.ffffffffffffep-172, 0x1.fffffffffffffp-58},
+                {0x1.ffffffffffffep-169, 0x1.fffffffffffffp-57},
+                {0x1.ffffffffffffep-166, 0x1.fffffffffffffp-56},
+                {0x1.ffffffffffffep-163, 0x1.fffffffffffffp-55},
+                {0x1.ffffffffffffep-970, 0x1.fffffffffffffp-324},
+                {0x1.ffffffffffffep-160, 0x1.fffffffffffffp-54},
+                {0x1.ffffffffffffep-157, 0x1.fffffffffffffp-53},
+                {0x1.ffffffffffffep-154, 0x1.fffffffffffffp-52},
+                {0x1.ffffffffffffep-151, 0x1.fffffffffffffp-51},
+                {0x1.ffffffffffffep-148, 0x1.fffffffffffffp-50},
+                {0x1.ffffffffffffep-145, 0x1.fffffffffffffp-49},
+                {0x1.ffffffffffffep-142, 0x1.fffffffffffffp-48},
+                {0x1.ffffffffffffep-139, 0x1.fffffffffffffp-47},
+                {0x1.ffffffffffffep-136, 0x1.fffffffffffffp-46},
+                {0x1.ffffffffffffep-133, 0x1.fffffffffffffp-45},
+                {0x1.ffffffffffffep-130, 0x1.fffffffffffffp-44},
+                {0x1.ffffffffffffep-127, 0x1.fffffffffffffp-43},
+                {0x1.ffffffffffffep-124, 0x1.fffffffffffffp-42},
+                {0x1.ffffffffffffep-121, 0x1.fffffffffffffp-41},
+                {0x1.ffffffffffffep-118, 0x1.fffffffffffffp-40},
+                {0x1.ffffffffffffep-115, 0x1.fffffffffffffp-39},
+                {0x1.ffffffffffffep-967, 0x1.fffffffffffffp-323},
+                {0x1.ffffffffffffep-112, 0x1.fffffffffffffp-38},
+                {0x1.ffffffffffffep-109, 0x1.fffffffffffffp-37},
+                {0x1.ffffffffffffep-106, 0x1.fffffffffffffp-36},
+                {0x1.ffffffffffffep-103, 0x1.fffffffffffffp-35},
+                {0x1.ffffffffffffep-100, 0x1.fffffffffffffp-34},
+                {0x1.ffffffffffffep-97, 0x1.fffffffffffffp-33},
+                {0x1.ffffffffffffep-94, 0x1.fffffffffffffp-32},
+                {0x1.ffffffffffffep-91, 0x1.fffffffffffffp-31},
+                {0x1.ffffffffffffep-88, 0x1.fffffffffffffp-30},
+                {0x1.ffffffffffffep-85, 0x1.fffffffffffffp-29},
+                {0x1.ffffffffffffep-82, 0x1.fffffffffffffp-28},
+                {0x1.ffffffffffffep-79, 0x1.fffffffffffffp-27},
+                {0x1.ffffffffffffep-76, 0x1.fffffffffffffp-26},
+                {0x1.ffffffffffffep-73, 0x1.fffffffffffffp-25},
+                {0x1.ffffffffffffep-70, 0x1.fffffffffffffp-24},
+                {0x1.ffffffffffffep-67, 0x1.fffffffffffffp-23},
+                {0x1.ffffffffffffep-964, 0x1.fffffffffffffp-322},
+                {0x1.ffffffffffffep-64, 0x1.fffffffffffffp-22},
+                {0x1.ffffffffffffep-61, 0x1.fffffffffffffp-21},
+                {0x1.ffffffffffffep-58, 0x1.fffffffffffffp-20},
+                {0x1.ffffffffffffep-55, 0x1.fffffffffffffp-19},
+                {0x1.ffffffffffffep-52, 0x1.fffffffffffffp-18},
+                {0x1.ffffffffffffep-49, 0x1.fffffffffffffp-17},
+                {0x1.ffffffffffffep-46, 0x1.fffffffffffffp-16},
+                {0x1.ffffffffffffep-43, 0x1.fffffffffffffp-15},
+                {0x1.ffffffffffffep-40, 0x1.fffffffffffffp-14},
+                {0x1.ffffffffffffep-37, 0x1.fffffffffffffp-13},
+                {0x1.ffffffffffffep-34, 0x1.fffffffffffffp-12},
+                {0x1.ffffffffffffep-31, 0x1.fffffffffffffp-11},
+                {0x1.ffffffffffffep-28, 0x1.fffffffffffffp-10},
+                {0x1.ffffffffffffep-25, 0x1.fffffffffffffp-9},
+                {0x1.ffffffffffffep-22, 0x1.fffffffffffffp-8},
+                {0x0.000000000003ep-1022, 0x1.fa9c313858568p-357},
+                {0x1.ffffffffffffep-19, 0x1.fffffffffffffp-7},
+                {0x1.ffffffffffffep-961, 0x1.fffffffffffffp-321},
+                {0x1.ffffffffffffep-16, 0x1.fffffffffffffp-6},
+                {0x1.ffffffffffffep-13, 0x1.fffffffffffffp-5},
+                {0x1.ffffffffffffep-10, 0x1.fffffffffffffp-4},
+                {0x1.ffffffffffffep-7, 0x1.fffffffffffffp-3},
+                {0x0.000000000003fp-1022, 0x1.fd51bf2069fe6p-357},
+                {0x1.ffffffffffffep-4, 0x1.fffffffffffffp-2},
+                {0x1.ffffffffffffep-1, 0x1.fffffffffffffp-1},
+                {0x0.000000003fffcp-1022, 0x1.ffff55551c71bp-353},
+                {0x0.000003fffffe8p-1022, 0x1.ffffffcp-349},
+                {0x0.000003ffffffcp-1022, 0x1.fffffff555555p-349},
+                {0x0.003fffffffff9p-1022, 0x1.fffffffffed55p-345},
+                {0x1.ffffffffffffep2, 0x1.fffffffffffffp0},
+                {0x1.bp4, 0x1.8p1},
+                {0x1.ffffffffffffep5, 0x1.fffffffffffffp1},
+                {0x1.f3ffffffffff4p6, 0x1.3fffffffffffep2},
+                {0x1.f3ffffffffffcp6, 0x1.3ffffffffffffp2},
+                {0x1.bp7, 0x1.8p2},
+                {0x1.56ffffffffffep8, 0x1.bffffffffffffp2},
+                {0x1.ffffffffffffep8, 0x1.fffffffffffffp2},
+                {0x1.6c8p9, 0x1.2p3},
+                {0x1.f3ffffffffff4p9, 0x1.3fffffffffffep3},
+                {0x1.f3ffffffffffcp9, 0x1.3ffffffffffffp3},
+                {0x1.4cbfffffffffcp10, 0x1.5fffffffffffep3},
+                {0x1.4cbfffffffffep10, 0x1.5ffffffffffffp3},
+                {0x1.bp10, 0x1.8p3},
+                {0x1.129ffffffffa4p11, 0x1.9ffffffffffd1p3},
+                {0x1.129fffffffffep11, 0x1.9ffffffffffffp3},
+                {0x1.56ffffffffffep11, 0x1.bffffffffffffp3},
+                {0x1.a5ep11, 0x1.ep3},
+                {0x1.ffffffffffffep11, 0x1.fffffffffffffp3},
+                {0x1.330fffffffc1ep12, 0x1.0fffffffffedbp4},
+                {0x1.331p12, 0x1.1p4},
+                {0x1.6c8p12, 0x1.2p4},
+                {0x1.acafffffffffap12, 0x1.2ffffffffffffp4},
+                {0x1.acafffffffffep12, 0x1.2ffffffffffffp4},
+                {0x1.ffffffffffffep-958, 0x1.fffffffffffffp-320},
+                {0x1.ffffffffffffep-955, 0x1.fffffffffffffp-319},
+                {0x1.ffffffffffffep-952, 0x1.fffffffffffffp-318},
+                {0x1.ffffffffffffep-949, 0x1.fffffffffffffp-317},
+                {0x1.ffffffffffffep-946, 0x1.fffffffffffffp-316},
+                {0x1.ffffffffffffep-943, 0x1.fffffffffffffp-315},
+                {0x1.ffffffffffffep-940, 0x1.fffffffffffffp-314},
+                {0x1.ffffffffffffep-937, 0x1.fffffffffffffp-313},
+                {0x1.ffffffffffffep-934, 0x1.fffffffffffffp-312},
+                {0x1.ffffffffffffep-931, 0x1.fffffffffffffp-311},
+                {0x1.ffffffffffffep-1018, 0x1.fffffffffffffp-340},
+                {0x1.ffffffffffffep-928, 0x1.fffffffffffffp-310},
+                {0x1.ffffffffffffep-925, 0x1.fffffffffffffp-309},
+                {0x1.ffffffffffffep-922, 0x1.fffffffffffffp-308},
+                {0x1.ffffffffffffep-919, 0x1.fffffffffffffp-307},
+                {0x1.ffffffffffffep-916, 0x1.fffffffffffffp-306},
+                {0x1.ffffffffffffep-913, 0x1.fffffffffffffp-305},
+                {0x1.ffffffffffffep-910, 0x1.fffffffffffffp-304},
+                {0x1.ffffffffffffep-907, 0x1.fffffffffffffp-303},
+                {0x1.ffffffffffffep-904, 0x1.fffffffffffffp-302},
+                {0x0.0000000000007p-1022, 0x1.e9b5dba58189ep-358},
+                {0x1.ffffffffffffep-901, 0x1.fffffffffffffp-301},
+                {0x1.ffffffffffffep-898, 0x1.fffffffffffffp-300},
+                {0x0.0000000007ffp-1022, 0x1.ffeaa9c70ca31p-354},
+                {0x0.0000000007ffep-1022, 0x1.fffd5551c7149p-354},
+                {0x0.0000007fffffdp-1022, 0x1.ffffffcp-350},
+                {0x0.0000007fffffep-1022, 0x1.ffffffd555555p-350},
+                {0x0.0007ffffffffap-1022, 0x1.fffffffff8p-346},
+                {0x0.7ffffffffffffp-1022, 0x1.fffffffffffffp-342},
+                {0x1.ffffffffffffep-895, 0x1.fffffffffffffp-299},
+                {0x1.ffffffffffffep-892, 0x1.fffffffffffffp-298},
+                {0x1.ffffffffffffep-889, 0x1.fffffffffffffp-297},
+                {0x1.ffffffffffffep-886, 0x1.fffffffffffffp-296},
+                {0x1.ffffffffffffep-883, 0x1.fffffffffffffp-295},
+                {0x1.ffffffffffffep-1015, 0x1.fffffffffffffp-339},
+                {0x1.ffffffffffffep-880, 0x1.fffffffffffffp-294},
+                {0x1.ffffffffffffep-877, 0x1.fffffffffffffp-293},
+                {0x1.ffffffffffffep-874, 0x1.fffffffffffffp-292},
+                {0x1.ffffffffffffep-871, 0x1.fffffffffffffp-291},
+                {0x1.ffffffffffffep-868, 0x1.fffffffffffffp-290},
+                {0x1.ffffffffffffep-865, 0x1.fffffffffffffp-289},
+                {0x1.ffffffffffffep-862, 0x1.fffffffffffffp-288},
+                {0x1.ffffffffffffep-859, 0x1.fffffffffffffp-287},
+                {0x1.ffffffffffffep-856, 0x1.fffffffffffffp-286},
+                {0x1.ffffffffffffep-853, 0x1.fffffffffffffp-285},
+                {0x1.ffffffffffffep-850, 0x1.fffffffffffffp-284},
+                {0x1.ffffffffffffep-847, 0x1.fffffffffffffp-283},
+                {0x1.ffffffffffffep-844, 0x1.fffffffffffffp-282},
+                {0x1.ffffffffffffep-841, 0x1.fffffffffffffp-281},
+                {0x1.ffffffffffffep-838, 0x1.fffffffffffffp-280},
+                {0x1.ffffffffffffep-835, 0x1.fffffffffffffp-279},
+                {0x1.ffffffffffffep-1012, 0x1.fffffffffffffp-338},
+                {0x1.ffffffffffffep-832, 0x1.fffffffffffffp-278},
+                {0x1.ffffffffffffep-829, 0x1.fffffffffffffp-277},
+                {0x1.ffffffffffffep-826, 0x1.fffffffffffffp-276},
+                {0x1.ffffffffffffep-823, 0x1.fffffffffffffp-275},
+                {0x1.ffffffffffffep-820, 0x1.fffffffffffffp-274},
+                {0x1.ffffffffffffep-817, 0x1.fffffffffffffp-273},
+                {0x1.ffffffffffffep-814, 0x1.fffffffffffffp-272},
+                {0x1.ffffffffffffep-811, 0x1.fffffffffffffp-271},
+                {0x1.ffffffffffffep-808, 0x1.fffffffffffffp-270},
+                {0x1.ffffffffffffep-805, 0x1.fffffffffffffp-269},
+                {0x1.ffffffffffffep-802, 0x1.fffffffffffffp-268},
+                {0x1.ffffffffffffep-799, 0x1.fffffffffffffp-267},
+                {0x1.ffffffffffffep-796, 0x1.fffffffffffffp-266},
+                {0x1.ffffffffffffep-793, 0x1.fffffffffffffp-265},
+                {0x1.ffffffffffffep-790, 0x1.fffffffffffffp-264},
+                {0x1.ffffffffffffep-787, 0x1.fffffffffffffp-263},
+                {0x1.ffffffffffffep-1009, 0x1.fffffffffffffp-337},
+                {0x1.ffffffffffffep-784, 0x1.fffffffffffffp-262},
+                {0x1.ffffffffffffep-781, 0x1.fffffffffffffp-261},
+                {0x1.ffffffffffffep-778, 0x1.fffffffffffffp-260},
+                {0x1.ffffffffffffep-775, 0x1.fffffffffffffp-259},
+                {0x1.ffffffffffffep-772, 0x1.fffffffffffffp-258},
+                {0x1.ffffffffffffep-769, 0x1.fffffffffffffp-257},
+                {0x0.0000000000ffep-1022, 0x1.ffeaa9c70ca31p-355},
+                {0x0.0000000000fffp-1022, 0x1.fff5551c6fcd6p-355},
+                {0x0.0000000ffff86p-1022, 0x1.ffffaeaa9dbf1p-351},
+                {0x0.0000000ffffffp-1022, 0x1.ffffff5555552p-351},
+                {0x0.0000ffffffap-1022, 0x1.ffffffcp-347},
+                {0x0.0000ffffffff8p-1022, 0x1.ffffffffaaaabp-347},
+                {0x0.0fffffffffffbp-1022, 0x1.fffffffffffcbp-343}
+        };
+
+        for (double[] testCase : testCases) {
+            testCubeRootCase(testCase[0], testCase[1]);
+        }
+    }
+
+    // Initialize shared random number generator
+    private static final java.util.Random random = new Random();
+
+    /**
+     * Test StrictMath.cbrt against transliteration port of cbrt.
+     */
+    @Test
+    public void testAgainstTranslit() {
+        double x;
+
+        // Test just above subnormal threshold...
+        x = Double.MIN_NORMAL;
+        testRange(x, Math.ulp(x), 1000);
+
+        // ... and just below subnormal threshold ...
+        x = Math.nextDown(Double.MIN_NORMAL);
+        testRange(x, -Math.ulp(x), 1000);
+
+        // ... and near zero.
+        testRange(0.0, Double.MIN_VALUE, 1000);
+
+        x = Tests.createRandomDouble(random);
+
+        // Make the increment twice the ulp value in case the random
+        // value is near an exponent threshold. Don't worry about test
+        // elements overflowing to infinity if the starting value is
+        // near Double.MAX_VALUE.
+        testRange(x, 2.0 * Math.ulp(x), 1000);
+    }
+
+    private static void testRange(double start, double increment, int count) {
+        double x = start;
+        for (int i = 0; i < count; i++, x += increment) {
+            testCubeRootCase(x, FdlibmTranslit.Cbrt.compute(x));
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/ExactArithTests.java b/ojluni/src/test/java/lang/StrictMath/ExactArithTests.java
index 0ce1306..88881b6 100644
--- a/ojluni/src/test/java/lang/StrictMath/ExactArithTests.java
+++ b/ojluni/src/test/java/lang/StrictMath/ExactArithTests.java
@@ -29,11 +29,10 @@
 import static org.testng.Assert.fail;
 
 /**
+ * @author Roger Riggs
  * @test Test for StrictMath.*Exact integer and long methods.
  * @bug 6708398
  * @summary Basic tests for StrictMath exact arithmetic operations.
- *
- * @author Roger Riggs
  */
 public class ExactArithTests {
 
@@ -41,30 +40,30 @@
     /**
      * The count of test errors.
      *
-    private static int errors = 0;
+     private static int errors = 0;
 
-    /**
+     /**
      * @param args the command line arguments
      *
     public static void main(String[] args) {
-        testIntegerExact();
-        testLongExact();
+    testIntegerExact();
+    testLongExact();
 
-        if (errors > 0) {
-            throw new RuntimeException(errors + " errors found in ExactArithTests.");
-        }
+    if (errors > 0) {
+    throw new RuntimeException(errors + " errors found in ExactArithTests.");
+    }
     }
 
     static void fail(String message) {
-        errors++;
-        System.err.println(message);
+    errors++;
+    System.err.println(message);
     }
-    */
+     */
     // END Android-removed: main(), error counter.
 
     /**
-     * Test StrictMath.addExact, multiplyExact, subtractExact, toIntValue methods
-     * with {@code int} arguments.
+     * Test StrictMath.addExact, multiplyExact, subtractExact, toIntValue methods with {@code int}
+     * arguments.
      */
     // Android-added: @Test annotation.
     @Test
@@ -89,9 +88,8 @@
     }
 
     /**
-     * Test exact arithmetic by comparing with the same operations using long
-     * and checking that the result is the same as the integer truncation.
-     * Errors are reported with {@link fail}.
+     * Test exact arithmetic by comparing with the same operations using long and checking that the
+     * result is the same as the integer truncation. Errors are reported with {@link fail}.
      *
      * @param x first parameter
      * @param y second parameter
@@ -102,14 +100,17 @@
             int sum = StrictMath.addExact(x, y);
             long sum2 = (long) x + (long) y;
             if ((int) sum2 != sum2) {
-                fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected Arithmetic exception");
+                fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ") = " + sum
+                        + "; expected Arithmetic exception");
             } else if (sum != sum2) {
-                fail("FAIL: long StrictMath.addExact(" + x + " + " + y + ") = " + sum + "; expected: " + sum2);
+                fail("FAIL: long StrictMath.addExact(" + x + " + " + y + ") = " + sum
+                        + "; expected: " + sum2);
             }
         } catch (ArithmeticException ex) {
             long sum2 = (long) x + (long) y;
             if ((int) sum2 == sum2) {
-                fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: int StrictMath.addExact(" + x + " + " + y + ")"
+                        + "; Unexpected exception: " + ex);
 
             }
         }
@@ -119,13 +120,15 @@
             int diff = StrictMath.subtractExact(x, y);
             long diff2 = (long) x - (long) y;
             if ((int) diff2 != diff2) {
-                fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ") = " + diff + "; expected: " + diff2);
+                fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ") = " + diff
+                        + "; expected: " + diff2);
             }
 
         } catch (ArithmeticException ex) {
             long diff2 = (long) x - (long) y;
             if ((int) diff2 == diff2) {
-                fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: int StrictMath.subtractExact(" + x + " - " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
@@ -134,20 +137,22 @@
             int product = StrictMath.multiplyExact(x, y);
             long m2 = (long) x * (long) y;
             if ((int) m2 != m2) {
-                fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ") = " + product + "; expected: " + m2);
+                fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ") = " + product
+                        + "; expected: " + m2);
             }
         } catch (ArithmeticException ex) {
             long m2 = (long) x * (long) y;
             if ((int) m2 == m2) {
-                fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: int StrictMath.multiplyExact(" + x + " * " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
     }
 
     /**
-     * Test StrictMath.addExact, multiplyExact, subtractExact, toIntExact methods
-     * with {@code long} arguments.
+     * Test StrictMath.addExact, multiplyExact, subtractExact, toIntExact methods with {@code long}
+     * arguments.
      */
     // Android-added: @Test annotation.
     @Test
@@ -167,23 +172,20 @@
         testLongExactTwice(Long.MAX_VALUE, -1);
         testLongExactTwice(Long.MIN_VALUE, -2);
         testLongExactTwice(Long.MAX_VALUE, -2);
-        testLongExactTwice(Long.MIN_VALUE/2, 2);
+        testLongExactTwice(Long.MIN_VALUE / 2, 2);
         testLongExactTwice(Long.MAX_VALUE, 2);
         testLongExactTwice(Integer.MAX_VALUE, Integer.MAX_VALUE);
         testLongExactTwice(Integer.MAX_VALUE, -Integer.MAX_VALUE);
-        testLongExactTwice(Integer.MAX_VALUE+1, Integer.MAX_VALUE+1);
-        testLongExactTwice(Integer.MAX_VALUE+1, -Integer.MAX_VALUE+1);
-        testLongExactTwice(Integer.MIN_VALUE-1, Integer.MIN_VALUE-1);
-        testLongExactTwice(Integer.MIN_VALUE-1, -Integer.MIN_VALUE-1);
-        testLongExactTwice(Integer.MIN_VALUE/2, 2);
+        testLongExactTwice(Integer.MAX_VALUE + 1, Integer.MAX_VALUE + 1);
+        testLongExactTwice(Integer.MAX_VALUE + 1, -Integer.MAX_VALUE + 1);
+        testLongExactTwice(Integer.MIN_VALUE - 1, Integer.MIN_VALUE - 1);
+        testLongExactTwice(Integer.MIN_VALUE - 1, -Integer.MIN_VALUE - 1);
+        testLongExactTwice(Integer.MIN_VALUE / 2, 2);
 
     }
 
     /**
-     * Test each of the exact operations with the arguments and
-     * with the arguments reversed.
-     * @param x
-     * @param y
+     * Test each of the exact operations with the arguments and with the arguments reversed.
      */
     static void testLongExactTwice(long x, long y) {
         testLongExact(x, y);
@@ -192,9 +194,9 @@
 
 
     /**
-     * Test long exact arithmetic by comparing with the same operations using BigInteger
-     * and checking that the result is the same as the long truncation.
-     * Errors are reported with {@link fail}.
+     * Test long exact arithmetic by comparing with the same operations using BigInteger and
+     * checking that the result is the same as the long truncation. Errors are reported with {@link
+     * fail}.
      *
      * @param x first parameter
      * @param y second parameter
@@ -210,7 +212,8 @@
             checkResult("long StrictMath.addExact", x, y, sum, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long StrictMath.addExact(" + x + " + " + y + "); Unexpected exception: " + ex);
+                fail("FAIL: long StrictMath.addExact(" + x + " + " + y + "); Unexpected exception: "
+                        + ex);
             }
         }
 
@@ -221,7 +224,8 @@
             checkResult("long StrictMath.subtractExact", x, y, diff, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long StrictMath.subtractExact(" + x + " - " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: long StrictMath.subtractExact(" + x + " - " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
@@ -232,19 +236,22 @@
             checkResult("long StrictMath.multiplyExact", x, y, product, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
 
         try {
             // Test toIntExact
             int value = StrictMath.toIntExact(x);
-            if ((long)value != x) {
-                fail("FAIL: " + "long StrictMath.toIntExact" + "(" + x + ") = " + value + "; expected an arithmetic exception: ");
+            if ((long) value != x) {
+                fail("FAIL: " + "long StrictMath.toIntExact" + "(" + x + ") = " + value
+                        + "; expected an arithmetic exception: ");
             }
         } catch (ArithmeticException ex) {
             if (resultBig.bitLength() <= 32) {
-                fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: long StrictMath.toIntExact(" + x + ")" + "; Unexpected exception: "
+                        + ex);
             }
         }
 
@@ -252,6 +259,7 @@
 
     /**
      * Compare the expected and actual results.
+     *
      * @param message message for the error
      * @param x first argument
      * @param y second argument
@@ -261,15 +269,17 @@
     static void checkResult(String message, long x, long y, long result, BigInteger expected) {
         BigInteger resultBig = BigInteger.valueOf(result);
         if (!inLongRange(expected)) {
-            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected an arithmetic exception: ");
+            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result
+                    + "; expected an arithmetic exception: ");
         } else if (!resultBig.equals(expected)) {
-            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected " + expected);
+            fail("FAIL: " + message + "(" + x + ", " + y + ") = " + result + "; expected "
+                    + expected);
         }
     }
 
     /**
      * Check if the value fits in 64 bits (a long).
-     * @param value
+     *
      * @return true if the value fits in 64 bits (including the sign).
      */
     static boolean inLongRange(BigInteger value) {
@@ -277,9 +287,9 @@
     }
 
     // BEGIN Android-added: add multiplyExact(long, int) based on Math.ExactArithTests.
+
     /**
-     * Test StrictMath.multiplyExact method with {@code long} and {@code int}
-     * arguments.
+     * Test StrictMath.multiplyExact method with {@code long} and {@code int} arguments.
      */
     @Test
     static void testLongIntExact() {
@@ -298,21 +308,21 @@
         testLongIntExact(Long.MAX_VALUE, -1);
         testLongIntExact(Long.MIN_VALUE, -2);
         testLongIntExact(Long.MAX_VALUE, -2);
-        testLongIntExact(Long.MIN_VALUE/2, 2);
+        testLongIntExact(Long.MIN_VALUE / 2, 2);
         testLongIntExact(Long.MAX_VALUE, 2);
         testLongIntExact(Integer.MAX_VALUE, Integer.MAX_VALUE);
         testLongIntExact(Integer.MAX_VALUE, -Integer.MAX_VALUE);
-        testLongIntExact((long)Integer.MAX_VALUE+1L, Integer.MAX_VALUE);
-        testLongIntExact((long)Integer.MAX_VALUE+1L, -Integer.MAX_VALUE+1);
-        testLongIntExact((long)Integer.MIN_VALUE-1L, Integer.MIN_VALUE);
-        testLongIntExact((long)Integer.MIN_VALUE-1, Integer.MAX_VALUE);
-        testLongIntExact(Integer.MIN_VALUE/2, 2);
+        testLongIntExact((long) Integer.MAX_VALUE + 1L, Integer.MAX_VALUE);
+        testLongIntExact((long) Integer.MAX_VALUE + 1L, -Integer.MAX_VALUE + 1);
+        testLongIntExact((long) Integer.MIN_VALUE - 1L, Integer.MIN_VALUE);
+        testLongIntExact((long) Integer.MIN_VALUE - 1, Integer.MAX_VALUE);
+        testLongIntExact(Integer.MIN_VALUE / 2, 2);
     }
 
     /**
-     * Test long-int exact arithmetic by comparing with the same operations using BigInteger
-     * and checking that the result is the same as the long truncation.
-     * Errors are reported with {@link fail}.
+     * Test long-int exact arithmetic by comparing with the same operations using BigInteger and
+     * checking that the result is the same as the long truncation. Errors are reported with {@link
+     * fail}.
      *
      * @param x first parameter
      * @param y second parameter
@@ -329,7 +339,8 @@
             checkResult("long StrictMath.multiplyExact", x, y, product, resultBig);
         } catch (ArithmeticException ex) {
             if (inLongRange(resultBig)) {
-                fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex);
+                fail("FAIL: long StrictMath.multiplyExact(" + x + " * " + y + ")"
+                        + "; Unexpected exception: " + ex);
             }
         }
     }
diff --git a/ojluni/src/test/java/lang/StrictMath/ExpTests.java b/ojluni/src/test/java/lang/StrictMath/ExpTests.java
new file mode 100644
index 0000000..9688537
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/ExpTests.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8139688
+ * @key randomness
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @build Tests
+ * @build FdlibmTranslit
+ * @build ExpTests
+ * @run main ExpTests
+ * @summary Tests specifically for StrictMath.exp
+ */
+package test.java.lang.StrictMath;
+
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+/**
+ * The role of this test is to verify that the FDLIBM exp algorithm is being used by running golden
+ * file style tests on values that may vary from one conforming exponential implementation to
+ * another.
+ */
+
+public class ExpTests {
+
+    private ExpTests() {
+    }
+
+    // From the fdlibm source, the overflow threshold in hex is:
+    // 0x4086_2E42_FEFA_39EF.
+    static final double EXP_OVERFLOW_THRESH = Double.longBitsToDouble(0x4086_2E42_FEFA_39EFL);
+
+    // From the fdlibm source, the underflow threshold in hex is:
+    // 0xc087_4910_D52D_3051L.
+    static final double EXP_UNDERFLOW_THRESH = Double.longBitsToDouble(0xc087_4910_D52D_3051L);
+
+    @Test
+    public void testExp() {
+        double[][] testCases = {
+                // Some of these could be moved to common Math/StrictMath exp testing.
+                {Double.NaN, Double.NaN},
+                {Double.MAX_VALUE, Double.POSITIVE_INFINITY},
+                {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY},
+                {Double.NEGATIVE_INFINITY, +0.0},
+                {EXP_OVERFLOW_THRESH, 0x1.ffff_ffff_fff2ap1023},
+                {Math.nextUp(EXP_OVERFLOW_THRESH), Double.POSITIVE_INFINITY},
+                {Math.nextDown(EXP_UNDERFLOW_THRESH), +0.0},
+                {EXP_UNDERFLOW_THRESH, +Double.MIN_VALUE},
+        };
+
+        for (double[] testCase : testCases) {
+            testExpCase(testCase[0], testCase[1]);
+        }
+    }
+
+    static void testExpCase(double input, double expected) {
+        Tests.test("StrictMath.exp(double)", input,
+                StrictMath.exp(input), expected);
+    }
+
+    // Initialize shared random number generator
+    private static final java.util.Random random = new Random();
+
+    /**
+     * Test StrictMath.exp against transliteration port of exp.
+     */
+    @Test
+    public void testAgainstTranslit() {
+        double[] decisionPoints = {
+                // Near overflow threshold
+                EXP_OVERFLOW_THRESH - 512 * Math.ulp(EXP_OVERFLOW_THRESH),
+
+                // Near underflow threshold
+                EXP_UNDERFLOW_THRESH - 512 * Math.ulp(EXP_UNDERFLOW_THRESH),
+
+                // Straddle algorithm conditional checks
+                Double.longBitsToDouble(0x4086_2E42_0000_0000L - 512L),
+                Double.longBitsToDouble(0x3fd6_2e42_0000_0000L - 512L),
+                Double.longBitsToDouble(0x3FF0_A2B2_0000_0000L - 512L),
+                Double.longBitsToDouble(0x3e30_0000_0000_0000L - 512L),
+
+                // Other notable points
+                Double.MIN_NORMAL - Math.ulp(Double.MIN_NORMAL) * 512,
+                -Double.MIN_VALUE * 512,
+        };
+
+        for (double decisionPoint : decisionPoints) {
+            double ulp = Math.ulp(decisionPoint);
+            testRange(decisionPoint - 1024 * ulp, ulp, 1_024);
+        }
+
+        // Try out some random values
+        for (int i = 0; i < 100; i++) {
+            double x = Tests.createRandomDouble(random);
+            testRange(x, Math.ulp(x), 100);
+        }
+    }
+
+    private static void testRange(double start, double increment, int count) {
+        double x = start;
+        for (int i = 0; i < count; i++, x += increment) {
+            testExpCase(x, FdlibmTranslit.Exp.compute(x));
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/Expm1Tests.java b/ojluni/src/test/java/lang/StrictMath/Expm1Tests.java
new file mode 100644
index 0000000..97b3c8e
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/Expm1Tests.java
@@ -0,0 +1,783 @@
+/*
+ * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4851638
+ * @summary Tests for StrictMath.expm1
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.StrictMath;
+
+import org.testng.annotations.Test;
+
+/**
+ * The tests in ../Math/Expm1Tests.java test properties that should hold for any expm1
+ * implementation, including the FDLIBM-based one required for StrictMath.expm1.  Therefore, the
+ * test cases in ../Math/Expm1Tests.java are run against both the Math and StrictMath versions of
+ * expm1.  The role of this test is to verify that the FDLIBM expm1 algorithm is being used by
+ * running golden file tests on values that may vary from one conforming expm1 implementation to
+ * another.
+ */
+
+public class Expm1Tests {
+
+    private Expm1Tests() {
+    }
+
+    static void testExpm1Case(double input, double expected) {
+        Tests.test("StrictMath.expm1(double)", input, StrictMath.expm1(input), expected);
+    }
+
+    @Test
+    public void testExpm1() {
+        // Test cases in the range [-36.75, 710]
+        double[][] testCases = {
+                {-0x1.580000008c619p3, -0x1.fffd3069586f6p-1},
+                {-0x1.380000008c721p3, -0x1.fff85bf4a6e98p-1},
+                {-0x1.180000008c9fap3, -0x1.ffeb3aeb95524p-1},
+                {-0x1.f0000001197ccp2, -0x1.ffc78aadc116ap-1},
+                {-0x1.b0000001197e7p2, -0x1.ff6687cca710bp-1},
+                {-0x1.70000001197f6p2, -0x1.fe5ed3992a519p-1},
+                {-0x1.30000001198p2, -0x1.fb9201482bdfap-1},
+                {-0x1.e000000233006p1, -0x1.f3f57b658d6fbp-1},
+                {-0x1.6000000233012p1, -0x1.df44d8ee30b76p-1},
+                {-0x1.c000000466028p0, -0x1.a7071a097ed5ep-1},
+                {-0x1.80000008cc052p-1, -0x1.0e25f8a4a95b7p-1},
+                {0x1.ffffffdccfeb7p-3, 0x1.22d78ef909144p-2},
+                {0x1.3ffffffb99fd7p0, 0x1.3ec38ed3629a6p1},
+                {0x1.1ffffffdccfebp1, 0x1.0f9b882a107edp3},
+                {0x1.9ffffffdccfebp1, 0x1.8ca53b70fa11bp4},
+                {0x1.0ffffffee67f6p2, 0x1.146bf132050c5p6},
+                {0x1.4ffffffee67f5p2, 0x1.7b21ede9f0bdap7},
+                {0x1.8ffffffee67f5p2, 0x1.0281a438aa523p9},
+                {0x1.cffffffee67f5p2, 0x1.5fc6b5cf322c4p10},
+                {0x1.07ffffff733fap3, 0x1.de5406b276b92p11},
+                {0x1.27ffffff733fap3, 0x1.451c8690d1567p13},
+                {0x1.47ffffff733fap3, 0x1.b9e62ae5924dfp14},
+                {0x1.67ffffff733fap3, 0x1.2c4eeb7089cp16},
+                {0x1.87ffffff733fap3, 0x1.982a24f2ab78ap17},
+                {0x1.a7ffffff733fap3, 0x1.1560a14319349p19},
+                {0x1.c7ffffff733fap3, 0x1.78fed772b40f2p20},
+                {0x1.e7ffffff733fap3, 0x1.0031f18ee602fp22},
+                {0x1.03ffffffb99fdp4, 0x1.5c348d8118f26p23},
+                {0x1.13ffffffb99fdp4, 0x1.d942943e22d74p24},
+                {0x1.23ffffffb99fcp4, 0x1.419d1309466ep26},
+                {0x1.33ffffffb99fcp4, 0x1.b51e403430afep27},
+                {0x1.43ffffffb99fcp4, 0x1.290d76c47bd4cp29},
+                {0x1.53ffffffb99fcp4, 0x1.93bc8061146dp30},
+                {0x1.63ffffffb99fbp4, 0x1.125e0665544a5p32},
+                {0x1.73ffffffb99fbp4, 0x1.74e75f9de5d7cp33},
+                {0x1.83ffffffb99fbp4, 0x1.fad42d3f28732p34},
+                {0x1.93ffffffb99fbp4, 0x1.586d071cb8f87p36},
+                {0x1.a3ffffffb99fbp4, 0x1.d41f91d0b4e6ep37},
+                {0x1.b3ffffffb99fbp4, 0x1.3e1f6e5bc0242p39},
+                {0x1.c3ffffffb99fbp4, 0x1.b05fa9aebfa64p40},
+                {0x1.d3ffffffb99fbp4, 0x1.25d410cc90a38p42},
+                {0x1.e3ffffffb99fbp4, 0x1.8f5aab33aa6c6p43},
+                {0x1.f3ffffffb99fbp4, 0x1.0f63a91bc9797p45},
+                {0x1.01ffffffdccfep5, 0x1.70db367c88b28p46},
+                {0x1.09ffffffdccfep5, 0x1.f553e36d2975fp47},
+                {0x1.11ffffffdccfep5, 0x1.54afff2230e99p49},
+                {0x1.19ffffffdccfep5, 0x1.cf0ad451f1e9fp50},
+                {0x1.21ffffffdccfep5, 0x1.3aab7c88ef991p52},
+                {0x1.29ffffffdccfep5, 0x1.abae41ecccd22p53},
+                {0x1.31ffffffdccfep5, 0x1.22a3a0462535fp55},
+                {0x1.39ffffffdccfdp5, 0x1.8b050329f95c8p56},
+                {0x1.41ffffffdccfdp5, 0x1.0c719224d80a2p58},
+                {0x1.49ffffffdccfdp5, 0x1.6cda4c755ea56p59},
+                {0x1.51ffffffdccfdp5, 0x1.efe2e2b6ad6ebp60},
+                {0x1.59ffffffdccfdp5, 0x1.50fd5a6337c61p62},
+                {0x1.61ffffffdccfdp5, 0x1.ca043518d78acp63},
+                {0x1.69ffffffdccfdp5, 0x1.374122dd2fbdbp65},
+                {0x1.71ffffffdccfdp5, 0x1.a709e46cc671ep66},
+                {0x1.79ffffffdccfdp5, 0x1.1f7c0c5482bf3p68},
+                {0x1.81ffffffdccfdp5, 0x1.86bb667297515p69},
+                {0x1.89ffffffdccfcp5, 0x1.0987aa8375abcp71},
+                {0x1.91ffffffdccfcp5, 0x1.68e48248f27ddp72},
+                {0x1.99ffffffdccfcp5, 0x1.ea8100a2e27e9p73},
+                {0x1.a1ffffffdccfcp5, 0x1.4d54fc02d9352p75},
+                {0x1.a9ffffffdccfcp5, 0x1.c50b8ceab6ad1p76},
+                {0x1.b1ffffffdccfcp5, 0x1.33e046afc7062p78},
+                {0x1.b9ffffffdccfcp5, 0x1.a2726cf2e78e3p79},
+                {0x1.c1ffffffdccfcp5, 0x1.1c5d3c581edf2p81},
+                {0x1.c9ffffffdccfcp5, 0x1.827db3961daecp82},
+                {0x1.d1ffffffdccfbp5, 0x1.06a5db797b4b2p84},
+                {0x1.d9ffffffdccfbp5, 0x1.64f9b90e23fb4p85},
+                {0x1.e1ffffffdccfbp5, 0x1.e52e132ebafe2p86},
+                {0x1.e9ffffffdccfbp5, 0x1.49b6c774442efp88},
+                {0x1.f1ffffffdccfbp5, 0x1.c020b4f9d926cp89},
+                {0x1.f9ffffffdccfbp5, 0x1.3088cda20d465p91},
+                {0x1.00ffffffee67ep6, 0x1.9de7b7a818186p92},
+                {0x1.04ffffffee67ep6, 0x1.194717f5da259p94},
+                {0x1.08ffffffee67ep6, 0x1.7e4bc97a2360dp95},
+                {0x1.0cffffffee67ep6, 0x1.03cc0e87f367bp97},
+                {0x1.10ffffffee67ep6, 0x1.6119d231b67f5p98},
+                {0x1.14ffffffee67ep6, 0x1.dfe9f0cbe5942p99},
+                {0x1.18ffffffee67ep6, 0x1.4622a079fc2a6p101},
+                {0x1.1cffffffee67ep6, 0x1.bb4386e45ae94p102},
+                {0x1.20ffffffee67ep6, 0x1.2d3a9d9e9fe6p104},
+                {0x1.24ffffffee67ep6, 0x1.9969a118d6261p105},
+                {0x1.28ffffffee67ep6, 0x1.1639871642331p107},
+                {0x1.2cffffffee67ep6, 0x1.7a2587603a84bp108},
+                {0x1.30ffffffee67ep6, 0x1.00fa2d6e6a76ep110},
+                {0x1.34ffffffee67ep6, 0x1.5d44af7562574p111},
+                {0x1.38ffffffee67ep6, 0x1.dab4705f88c02p112},
+                {0x1.3cffffffee67ep6, 0x1.42986b24fc9dcp114},
+                {0x1.40ffffffee67ep6, 0x1.b673dcb2fe519p115},
+                {0x1.44ffffffee67ep6, 0x1.29f59cd896383p117},
+                {0x1.48ffffffee67ep6, 0x1.94f806342143cp118},
+                {0x1.4cffffffee67ep6, 0x1.133471e4d5b38p120},
+                {0x1.50ffffffee67ep6, 0x1.760acce4f0e03p121},
+                {0x1.54ffffffee67ep6, 0x1.fc604454828ddp122},
+                {0x1.58ffffffee67ep6, 0x1.597a32eee8c46p124},
+                {0x1.5cffffffee67ep6, 0x1.d58d694102246p125},
+                {0x1.60ffffffee67ep6, 0x1.3f180bd3df0d2p127},
+                {0x1.64ffffffee67ep6, 0x1.b1b190d803f07p128},
+                {0x1.68ffffffee67ep6, 0x1.26b9b1cab82dap130},
+                {0x1.6cffffffee67ep6, 0x1.9092c44a68bc1p131},
+                {0x1.70ffffffee67ep6, 0x1.1037c0cf4a5a6p133},
+                {0x1.74ffffffee67ep6, 0x1.71fb79fed30fbp134},
+                {0x1.78ffffffee67ep6, 0x1.f6dbadec024eep135},
+                {0x1.7cffffffee67ep6, 0x1.55ba3f072a6dbp137},
+                {0x1.80ffffffee67ep6, 0x1.d074b338a9163p138},
+                {0x1.84ffffffee67ep6, 0x1.3ba167320351ap140},
+                {0x1.88ffffffee67ep6, 0x1.acfc7e2e0558bp141},
+                {0x1.8cffffffee67ep6, 0x1.2386c336b7163p143},
+                {0x1.90ffffffee67ep6, 0x1.8c39b90c7cdap144},
+                {0x1.94ffffffee67ep6, 0x1.0d435c84d4e66p146},
+                {0x1.98ffffffee67ep6, 0x1.6df76efd7275ep147},
+                {0x1.9cffffffee67ep6, 0x1.f1666c9163f86p148},
+                {0x1.a0ffffffee67ep6, 0x1.5204b679406b7p150},
+                {0x1.a4ffffffee67ep6, 0x1.cb6a267e94b7ap151},
+                {0x1.a8ffffffee67ep6, 0x1.38346236ba483p153},
+                {0x1.acffffffee67ep6, 0x1.a8547ff6d3311p154},
+                {0x1.b0ffffffee67ep6, 0x1.205cb8246899ap156},
+                {0x1.b4ffffffee67ep6, 0x1.87ecc28a831c1p157},
+                {0x1.b8ffffffee67ep6, 0x1.0a572df57323ep159},
+                {0x1.bcffffffee67ep6, 0x1.69fe8c886de24p160},
+                {0x1.c0ffffffee67ep6, 0x1.ec0055aa644acp161},
+                {0x1.c4ffffffee67ep6, 0x1.4e597c5197d13p163},
+                {0x1.c8ffffffee67ep6, 0x1.c66d9bb965746p164},
+                {0x1.ccffffffee67ep6, 0x1.34d0e22472ce2p166},
+                {0x1.d0ffffffee67ep6, 0x1.a3b971da5668ap167},
+                {0x1.d4ffffffee67ep6, 0x1.1d3b77e103d1ap169},
+                {0x1.d8ffffffee67ep6, 0x1.83abbf32ed4f6p170},
+                {0x1.dcffffffee67ep6, 0x1.07731e5137e95p172},
+                {0x1.e0ffffffee67ep6, 0x1.6610b39e7ce7p173},
+                {0x1.e4ffffffee67ep6, 0x1.e6a93f132076cp174},
+                {0x1.e8ffffffee67ep6, 0x1.4ab873ed0fb2cp176},
+                {0x1.ecffffffee67ep6, 0x1.c17eebfd11debp177},
+                {0x1.f0ffffffee67ep6, 0x1.3176cc87e9082p179},
+                {0x1.f4ffffffee67ep6, 0x1.9f2b2fe57487ap180},
+                {0x1.f8ffffffee67ep6, 0x1.1a22e9fe60816p182},
+                {0x1.fcffffffee67ep6, 0x1.7f768dd1738aap183},
+                {0x1.007ffffff733fp7, 0x1.049717079907bp185},
+                {0x1.027ffffff733fp7, 0x1.622dc5947dd63p186},
+                {0x1.047ffffff733fp7, 0x1.e160ff1ccd30cp187},
+                {0x1.067ffffff733fp7, 0x1.472180f8199d7p189},
+                {0x1.087ffffff733fp7, 0x1.bc9df0c9b6e0fp190},
+                {0x1.0a7ffffff733fp7, 0x1.2e26073757ed6p192},
+                {0x1.0c7ffffff733fp7, 0x1.9aa99688f714bp193},
+                {0x1.0e7ffffff733fp7, 0x1.1712f6523864dp195},
+                {0x1.107ffffff733fp7, 0x1.7b4d0d8e11012p196},
+                {0x1.127ffffff733fp7, 0x1.01c301c6bf29cp198},
+                {0x1.147ffffff733fp7, 0x1.5e55a41486608p199},
+                {0x1.167ffffff733fp7, 0x1.dc276c8c7156p200},
+                {0x1.187ffffff733fp7, 0x1.4394876ddc7dap202},
+                {0x1.1a7ffffff733fp7, 0x1.b7ca840a6b3bap203},
+                {0x1.1c7ffffff733fp7, 0x1.2ade7851ad0fep205},
+                {0x1.1e7ffffff733fp7, 0x1.963482987606p206},
+                {0x1.207ffffff733fp7, 0x1.140b84f56a91bp208},
+                {0x1.227ffffff733fp7, 0x1.772f1dec03a66p209},
+                {0x1.247ffffff733fp7, 0x1.fded90f5af3ap210},
+                {0x1.267ffffff733fp7, 0x1.5a88311cf6cbdp212},
+                {0x1.287ffffff733fp7, 0x1.d6fc5e99a419dp213},
+                {0x1.2a7ffffff733fp7, 0x1.40116b9759ebap215},
+                {0x1.2c7ffffff733fp7, 0x1.b304801416466p216},
+                {0x1.2e7ffffff733fp7, 0x1.27a0063dbe9cep218},
+                {0x1.307ffffff733fp7, 0x1.91cbd14945353p219},
+                {0x1.327ffffff733fp7, 0x1.110c7e4340e4fp221},
+                {0x1.347ffffff733fp7, 0x1.731c9ec8ce996p222},
+                {0x1.367ffffff733fp7, 0x1.f864aa9acffbdp223},
+                {0x1.387ffffff733fp7, 0x1.56c54eff8fbcdp225},
+                {0x1.3a7ffffff733fp7, 0x1.d1dfaced4eb1p226},
+                {0x1.3c7ffffff733fp7, 0x1.3c98120a95d78p228},
+                {0x1.3e7ffffff733fp7, 0x1.ae4bbfa449eaap229},
+                {0x1.407ffffff733fp7, 0x1.246a97a9838dcp231},
+                {0x1.427ffffff733fp7, 0x1.8d6f603164cebp232},
+                {0x1.447ffffff733fp7, 0x1.0e15cad8b775ep234},
+                {0x1.467ffffff733fp7, 0x1.6f15705b3f514p235},
+                {0x1.487ffffff733fp7, 0x1.f2eb25494787dp236},
+                {0x1.4a7ffffff733fp7, 0x1.530ce0608a8acp238},
+                {0x1.4c7ffffff733fp7, 0x1.ccd12fa07172p239},
+                {0x1.4e7ffffff733fp7, 0x1.39285fa9c08e7p241},
+                {0x1.507ffffff733fp7, 0x1.a9a01de01fd02p242},
+                {0x1.527ffffff733fp7, 0x1.213e13894e05p244},
+                {0x1.547ffffff733fp7, 0x1.891f0d4674b33p245},
+                {0x1.567ffffff733fp7, 0x1.0b275393c60b2p247},
+                {0x1.587ffffff733fp7, 0x1.6b1973327581dp248},
+                {0x1.5a7ffffff733fp7, 0x1.ed80d645874cfp249},
+                {0x1.5c7ffffff733fp7, 0x1.4f5ec835b4172p251},
+                {0x1.5e7ffffff733fp7, 0x1.c7d0bf3aec5fcp252},
+                {0x1.607ffffff733fp7, 0x1.35c239a263125p254},
+                {0x1.627ffffff733fp7, 0x1.a501765319bp255},
+                {0x1.647ffffff733fp7, 0x1.1e1a611707cfbp257},
+                {0x1.667ffffff733fp7, 0x1.84dab6dcaac3cp258},
+                {0x1.687ffffff733fp7, 0x1.08410192ab89ep260},
+                {0x1.6a7ffffff733fp7, 0x1.67288834edb2fp261},
+                {0x1.6c7ffffff733fp7, 0x1.e825934abdad9p262},
+                {0x1.6e7ffffff733fp7, 0x1.4bbae9c58a222p264},
+                {0x1.707ffffff733fp7, 0x1.c2de34b24b161p265},
+                {0x1.727ffffff733fp7, 0x1.3265856c8dbdcp267},
+                {0x1.747ffffff733fp7, 0x1.a06fa4ee04c8ep268},
+                {0x1.767ffffff733fp7, 0x1.1aff67d171068p270},
+                {0x1.787ffffff733fp7, 0x1.80a23ba5cc0fep271},
+                {0x1.7a7ffffff733fp7, 0x1.0562be333b5b6p273},
+                {0x1.7c7ffffff733fp7, 0x1.6342909f8e806p274},
+                {0x1.7e7ffffff733fp7, 0x1.e2d932898c11cp275},
+                {0x1.807ffffff733ep7, 0x1.482128a65b0aap277},
+                {0x1.827ffffff733ep7, 0x1.bdf9696894p278},
+                {0x1.847ffffff733ep7, 0x1.2f1228ca0924p280},
+                {0x1.867ffffff733ep7, 0x1.9bea8605e05b8p281},
+                {0x1.887ffffff733ep7, 0x1.17ed0f7b60befp283},
+                {0x1.8a7ffffff733ep7, 0x1.7c757ab028d2cp284},
+                {0x1.8c7ffffff733ep7, 0x1.028c73122cbaap286},
+                {0x1.8e7ffffff733ep7, 0x1.5f676e04b872p287},
+                {0x1.907ffffff733ep7, 0x1.dd9b8aa6c07f4p288},
+                {0x1.927ffffff733ep7, 0x1.449168bd6830bp290},
+                {0x1.947ffffff733ep7, 0x1.b922372b1b22fp291},
+                {0x1.967ffffff733ep7, 0x1.2bc809c589606p293},
+                {0x1.987ffffff733ep7, 0x1.9771f652c776ap294},
+                {0x1.9a7ffffff733ep7, 0x1.14e3401b07fc7p296},
+                {0x1.9c7ffffff733ep7, 0x1.785453659b7d4p297},
+                {0x1.9e7ffffff733ep7, 0x1.ff7c1414d829fp298},
+                {0x1.a07ffffff733ep7, 0x1.5b97024b58a63p300},
+                {0x1.a27ffffff733ep7, 0x1.d86c72ba13072p301},
+                {0x1.a47ffffff733ep7, 0x1.410b8e3e0a59p303},
+                {0x1.a67ffffff733ep7, 0x1.b458783157a34p304},
+                {0x1.a87ffffff733ep7, 0x1.28870eb1e33efp306},
+                {0x1.aa7ffffff733ep7, 0x1.9305d2eedd47p307},
+                {0x1.ac7ffffff733ep7, 0x1.11e1e1f93656cp309},
+                {0x1.ae7ffffff733ep7, 0x1.743ea58a8a142p310},
+                {0x1.b07ffffff733ep7, 0x1.f9eeda68dbff6p311},
+                {0x1.b27ffffff733ep7, 0x1.57d12fadfda18p313},
+                {0x1.b47ffffff733ep7, 0x1.d34bc24ce61e7p314},
+                {0x1.b67ffffff733ep7, 0x1.3d8f7da8d8d95p316},
+                {0x1.b87ffffff733ep7, 0x1.af9c071bbd116p317},
+                {0x1.ba7ffffff733ep7, 0x1.254f1e2943f7fp319},
+                {0x1.bc7ffffff733ep7, 0x1.8ea5f9553ce5ep320},
+                {0x1.be7ffffff733ep7, 0x1.0ee8dda0a100cp322},
+                {0x1.c07ffffff733ep7, 0x1.7034513ceac7dp323},
+                {0x1.c27ffffff733ep7, 0x1.f4710dcb08bdcp324},
+                {0x1.c47ffffff733ep7, 0x1.5415d8b9ef19cp326},
+                {0x1.c67ffffff733ep7, 0x1.ce3951590b045p327},
+                {0x1.c87ffffff733ep7, 0x1.3a1d1bcad2ec4p329},
+                {0x1.ca7ffffff733ep7, 0x1.aaecbef297a4ap330},
+                {0x1.cc7ffffff733ep7, 0x1.22201f0c6ae88p332},
+                {0x1.ce7ffffff733ep7, 0x1.8a524760ebdc1p333},
+                {0x1.d07ffffff733ep7, 0x1.0bf81bdd2ba52p335},
+                {0x1.d27ffffff733ep7, 0x1.6c3536f34b0c2p336},
+                {0x1.d47ffffff733ep7, 0x1.ef02835e6a7d8p337},
+                {0x1.d67ffffff733ep7, 0x1.5064e04e480fep339},
+                {0x1.d87ffffff733ep7, 0x1.c934f847894a8p340},
+                {0x1.da7ffffff733ep7, 0x1.36b44dbc8b633p342},
+                {0x1.dc7ffffff733ep7, 0x1.a64a7b24ebae2p343},
+                {0x1.de7ffffff733ep7, 0x1.1ef9f881e57b8p345},
+                {0x1.e07ffffff733ep7, 0x1.860a9b4bcf9dfp346},
+                {0x1.e27ffffff733ep7, 0x1.090f85bb33493p348},
+                {0x1.e47ffffff733ep7, 0x1.6841377bd96e9p349},
+                {0x1.e67ffffff733ep7, 0x1.e9a310bd2715dp350},
+                {0x1.e87ffffff733ep7, 0x1.4cbe299b1372dp352},
+                {0x1.ea7ffffff733ep7, 0x1.c43e8fef69d0dp353},
+                {0x1.ec7ffffff733ep7, 0x1.3354f8e156a72p355},
+                {0x1.ee7ffffff733ep7, 0x1.a1b51787582dfp356},
+                {0x1.f07ffffff733ep7, 0x1.1bdc91f54d333p358},
+                {0x1.f27ffffff733ep7, 0x1.81ced3ada5ec9p359},
+                {0x1.f47ffffff733ep7, 0x1.062f0486db268p361},
+                {0x1.f67ffffff733ep7, 0x1.645833fb72196p362},
+                {0x1.f87ffffff733ep7, 0x1.e4528bf7332d2p363},
+                {0x1.fa7ffffff733ep7, 0x1.492198206b3aep365},
+                {0x1.fc7ffffff733ep7, 0x1.bf55f194851b5p366},
+                {0x1.fe7ffffff733ep7, 0x1.2fff02e67affep368},
+                {0x1.003ffffffb99fp8, 0x1.9d2c7052fc80ep369},
+                {0x1.013ffffffb99fp8, 0x1.18c7d31687cep371},
+                {0x1.023ffffffb99fp8, 0x1.7d9ecf7b00132p372},
+                {0x1.033ffffffb99fp8, 0x1.035681cb5b766p374},
+                {0x1.043ffffffb99fp8, 0x1.607a0decadfaep375},
+                {0x1.053ffffffb99fp8, 0x1.df10cb910ae14p376},
+                {0x1.063ffffffb99fp8, 0x1.458f0fad99f57p378},
+                {0x1.073ffffffb99fp8, 0x1.ba7af6e654fa2p379},
+                {0x1.083ffffffb99fp8, 0x1.2cb251c2631d6p381},
+                {0x1.093ffffffb99fp8, 0x1.98b06224611f2p382},
+                {0x1.0a3ffffffb99fp8, 0x1.15bba3d909807p384},
+                {0x1.0b3ffffffb99fp8, 0x1.797a6e0440f8fp385},
+                {0x1.0c3ffffffb99fp8, 0x1.0085e752522ap387},
+                {0x1.0d3ffffffb99fp8, 0x1.5ca6a71ef489ep388},
+                {0x1.0e3ffffffb99fp8, 0x1.d9dda6826dfc7p389},
+                {0x1.0f3ffffffb99fp8, 0x1.420674603ebb2p391},
+                {0x1.103ffffffb99fp8, 0x1.b5ad79fec979p392},
+                {0x1.113ffffffb99fp8, 0x1.296ecbb3d2db7p394},
+                {0x1.123ffffffb99fp8, 0x1.9440c9fa6362ap395},
+                {0x1.133ffffffb99fp8, 0x1.12b7ec73193e4p397},
+                {0x1.143ffffffb99fp8, 0x1.75618ef49dffep398},
+                {0x1.153ffffffb99fp8, 0x1.fb7a3e462b12ap399},
+                {0x1.163ffffffb99fp8, 0x1.58dde1b590206p401},
+                {0x1.173ffffffb99fp8, 0x1.d4b8f4351faecp402},
+                {0x1.183ffffffb99fp8, 0x1.3e87aaa373892p404},
+                {0x1.193ffffffb99fp8, 0x1.b0ed5561210d9p405},
+                {0x1.1a3ffffffb99fp8, 0x1.263457411e3a5p407},
+                {0x1.1b3ffffffb99fp8, 0x1.8fdd8535244cdp408},
+                {0x1.1c3ffffffb99fp8, 0x1.0fbc955d170d1p410},
+                {0x1.1d3ffffffb99fp8, 0x1.7154125122a86p411},
+                {0x1.1e3ffffffb99fp8, 0x1.f5f8270411675p412},
+                {0x1.1f3ffffffb99fp8, 0x1.551fa026c4e4cp414},
+                {0x1.203ffffffb99fp8, 0x1.cfa28c83a9c15p415},
+                {0x1.213ffffffb99fp8, 0x1.3b12972ef5f7ap417},
+                {0x1.223ffffffb99fp8, 0x1.ac3a63f8c3fc9p418},
+                {0x1.233ffffffb99fp8, 0x1.2302db376285dp420},
+                {0x1.243ffffffb99fp8, 0x1.8b867194fa443p421},
+                {0x1.253ffffffb99fp8, 0x1.0cc98750c45aep423},
+                {0x1.263ffffffb99fp8, 0x1.6d51d877b6f1bp424},
+                {0x1.273ffffffb99fp8, 0x1.f0855ddfe3faap425},
+                {0x1.283ffffffb99fp8, 0x1.516bc53aea3aap427},
+                {0x1.293ffffffb99fp8, 0x1.ca9a47b823396p428},
+                {0x1.2a3ffffffb99fp8, 0x1.37a71f0652462p430},
+                {0x1.2b3ffffffb99fp8, 0x1.a794811822eb3p431},
+                {0x1.2c3ffffffb99fp8, 0x1.1fda3ea9c1a4fp433},
+                {0x1.2d3ffffffb99fp8, 0x1.873b6d3965cp434},
+                {0x1.2e3ffffffb99fp8, 0x1.09deab488e539p436},
+                {0x1.2f3ffffffb99fp8, 0x1.695ac21e2870ep437},
+                {0x1.303ffffffb99fp8, 0x1.eb21b852a647cp438},
+                {0x1.313ffffffb99fp8, 0x1.4dc2340b86b4cp440},
+                {0x1.323ffffffb99fp8, 0x1.c59ffe8afa62cp441},
+                {0x1.333ffffffb99fp8, 0x1.3445277810b78p443},
+                {0x1.343ffffffb99fp8, 0x1.a2fb88779894fp444},
+                {0x1.353ffffffb99fp8, 0x1.1cba68f09f8c5p446},
+                {0x1.363ffffffb99fp8, 0x1.82fc56a008db6p447},
+                {0x1.373ffffffb99fp8, 0x1.06fbea7eda2dfp449},
+                {0x1.383ffffffb99fp8, 0x1.656eb0513614ep450},
+                {0x1.393ffffffb99fp8, 0x1.e5cd0c4b86aaap451},
+                {0x1.3a3ffffffb99fp8, 0x1.4a22d0026e7ffp453},
+                {0x1.3b3ffffffb99fp8, 0x1.c0b38a21c236cp454},
+                {0x1.3c3ffffffb99fp8, 0x1.30ec961ce5379p456},
+                {0x1.3d3ffffffb99fp8, 0x1.9e6f56344e9dp457},
+                {0x1.3e3ffffffb99fp8, 0x1.19a341a8e1ccbp459},
+                {0x1.3f3ffffffb99fp8, 0x1.7ec90ca3a1c6dp460},
+                {0x1.403ffffffb99fp8, 0x1.04212e6d536d6p462},
+                {0x1.413ffffffb99fp8, 0x1.618d84739e91cp463},
+                {0x1.423ffffffb99fp8, 0x1.e087302e9607ap464},
+                {0x1.433ffffffb99fp8, 0x1.468d7cd8e4417p466},
+                {0x1.443ffffffb99fp8, 0x1.bbd4c40e0317cp467},
+                {0x1.453ffffffb99fp8, 0x1.2d9d50d6e1436p469},
+                {0x1.463ffffffb99fp8, 0x1.99efc6cf25729p470},
+                {0x1.473ffffffb99fp8, 0x1.1694b0b33138ap472},
+                {0x1.483ffffffb99fp8, 0x1.7aa16e7b0810dp473},
+                {0x1.493ffffffb99fp8, 0x1.014e60cc3c10bp475},
+                {0x1.4a3ffffffb99fp8, 0x1.5db7203d316b3p476},
+                {0x1.4b3ffffffb99fp8, 0x1.db4ffad383047p477},
+                {0x1.4c3ffffffb99fp8, 0x1.43021e96bc60ep479},
+                {0x1.4d3ffffffb99fp8, 0x1.b703864c0ed74p480},
+                {0x1.4e3ffffffb99fp8, 0x1.2a573dd0a80e6p482},
+                {0x1.4f3ffffffb99fp8, 0x1.957cb72b9f3f6p483},
+                {0x1.503ffffffb99fp8, 0x1.138e9e333d9afp485},
+                {0x1.513ffffffb99fp8, 0x1.76855bb82cbcep486},
+                {0x1.523ffffffb99fp8, 0x1.fd06d7237d52bp487},
+                {0x1.533ffffffb99fp8, 0x1.59eb65b9e296ap489},
+                {0x1.543ffffffb99fp8, 0x1.d627438458c6ap490},
+                {0x1.553ffffffb99fp8, 0x1.3f80999182b7ap492},
+                {0x1.563ffffffb99fp8, 0x1.b23fab41d7fcdp493},
+                {0x1.573ffffffb99fp8, 0x1.271a437ca4dd9p495},
+                {0x1.583ffffffb99fp8, 0x1.9116048ecdd82p496},
+                {0x1.593ffffffb99fp8, 0x1.1090f28f03784p498},
+                {0x1.5a3ffffffb99fp8, 0x1.7274b4471d222p499},
+                {0x1.5b3ffffffb99fp8, 0x1.f78071e284acfp500},
+                {0x1.5c3ffffffb99fp8, 0x1.562a3748e0ae8p502},
+                {0x1.5d3ffffffb99fp8, 0x1.d10ce1fc412f2p503},
+                {0x1.5e3ffffffb99fp8, 0x1.3c08d26ba29edp505},
+                {0x1.5f3ffffffb99fp8, 0x1.ad890dbdcc46ap506},
+                {0x1.603ffffffb99fp8, 0x1.23e648944393ap508},
+                {0x1.613ffffffb99fp8, 0x1.8cbb8c9e43a63p509},
+                {0x1.623ffffffb99fp8, 0x1.0d9b966e13d61p511},
+                {0x1.633ffffffb99fp8, 0x1.6e6f586d0888dp512},
+                {0x1.643ffffffb99fp8, 0x1.f20966b5813aep513},
+                {0x1.653ffffffb99fp8, 0x1.5273779badaf2p515},
+                {0x1.663ffffffb99fp8, 0x1.cc00ae664a89p516},
+                {0x1.673ffffffb99fp8, 0x1.389aae1391554p518},
+                {0x1.683ffffffb99fp8, 0x1.a8df88f5b2588p519},
+                {0x1.693ffffffb99fp8, 0x1.20bb34172b66ap521},
+                {0x1.6a3ffffffb99fp8, 0x1.886d2d5f07833p522},
+                {0x1.6b3ffffffb99fp8, 0x1.0aae72b8de01ep524},
+                {0x1.6c3ffffffb99fp8, 0x1.6a7528c7487fep525},
+                {0x1.6d3ffffffb99fp8, 0x1.eca18af43a36cp526},
+                {0x1.6e3ffffffb99fp8, 0x1.4ec709b53a35fp528},
+                {0x1.6f3ffffffb99fp8, 0x1.c702815c30a11p529},
+                {0x1.703ffffffb99fp8, 0x1.353611c2fab72p531},
+                {0x1.713ffffffb99fp8, 0x1.a442f8858a925p532},
+                {0x1.723ffffffb99fp8, 0x1.1d98ed4a7bba3p534},
+                {0x1.733ffffffb99fp8, 0x1.842ac5348b7cep535},
+                {0x1.743ffffffb99fp8, 0x1.07c97097fb529p537},
+                {0x1.753ffffffb99fp8, 0x1.6686064a6be2ap538},
+                {0x1.763ffffffb99fp8, 0x1.e748b46cfe14cp539},
+                {0x1.773ffffffb99fp8, 0x1.4b24d0e9033c7p541},
+                {0x1.783ffffffb99fp8, 0x1.c21233e5293dap542},
+                {0x1.793ffffffb99fp8, 0x1.31dae2fdf0407p544},
+                {0x1.7a3ffffffb99fp8, 0x1.9fb3386e7303dp545},
+                {0x1.7b3ffffffb99fp8, 0x1.1a7f5bb80b183p547},
+                {0x1.7c3ffffffb99fp8, 0x1.7ff432dfa67a9p548},
+                {0x1.7d3ffffffb99fp8, 0x1.04ec79737cde7p550},
+                {0x1.7e3ffffffb99fp8, 0x1.62a1d2414486ep551},
+                {0x1.7f3ffffffb99fp8, 0x1.e1feb963592a3p552},
+                {0x1.803ffffffb99fp8, 0x1.478cb0da3248p554},
+                {0x1.813ffffffb99fp8, 0x1.bd2f9f74b3ecep555},
+                {0x1.823ffffffb99fp8, 0x1.2e8907921a545p557},
+                {0x1.833ffffffb99fp8, 0x1.9b3025158e763p558},
+                {0x1.843ffffffb99fp8, 0x1.176e672da841p560},
+                {0x1.853ffffffb99fp8, 0x1.7bc9557d90bb5p561},
+                {0x1.863ffffffb99fp8, 0x1.021776f23b20ap563},
+                {0x1.873ffffffb99fp8, 0x1.5ec86e4bf78ccp564},
+                {0x1.883ffffffb99fp8, 0x1.dcc3708ecfe88p565},
+                {0x1.893ffffffb99fp8, 0x1.43fe8d7ac0079p567},
+                {0x1.8a3ffffffb99fp8, 0x1.b85a9de96d206p568},
+                {0x1.8b3ffffffb99fp8, 0x1.2b406595ebc2fp570},
+                {0x1.8c3ffffffb99fp8, 0x1.96b99b42ee81ep571},
+                {0x1.8d3ffffffb99fp8, 0x1.1465f7bc5d4f3p573},
+                {0x1.8e3ffffffb99fp8, 0x1.77aa0c86e3254p574},
+                {0x1.8f3ffffffb99fp8, 0x1.fe94a5f24f127p575},
+                {0x1.903ffffffb99fp8, 0x1.5af9bc5f10484p577},
+                {0x1.913ffffffb99fp8, 0x1.d796b1199ca0dp578},
+                {0x1.923ffffffb99fp8, 0x1.407a4b0a99581p580},
+                {0x1.933ffffffb99fp8, 0x1.b393098be48c6p581},
+                {0x1.943ffffffb99fp8, 0x1.2800e367d7873p583},
+                {0x1.953ffffffb99fp8, 0x1.924f782080a9p584},
+                {0x1.963ffffffb99fp8, 0x1.1165f5b7b4e77p586},
+                {0x1.973ffffffb99fp8, 0x1.739637ce995dep587},
+                {0x1.983ffffffb99fp8, 0x1.f909ef553fe1dp588},
+                {0x1.993ffffffb99fp8, 0x1.57359ec295bd8p590},
+                {0x1.9a3ffffffb99fp8, 0x1.d278529f70c72p591},
+                {0x1.9b3ffffffb99fp8, 0x1.3cffce16c6a9fp593},
+                {0x1.9c3ffffffb99fp8, 0x1.aed8bd0d76c2ep594},
+                {0x1.9d3ffffffb99fp8, 0x1.24ca67ad88b68p596},
+                {0x1.9e3ffffffb99fp8, 0x1.8df19938fe6d4p597},
+                {0x1.9f3ffffffb99fp8, 0x1.0e6e49b5016fbp599},
+                {0x1.a03ffffffb99fp8, 0x1.6f8db78116a48p600},
+                {0x1.a13ffffffb99fp8, 0x1.f38e9ecb87da4p601},
+                {0x1.a23ffffffb99fp8, 0x1.537bf81122a93p603},
+                {0x1.a33ffffffb99fp8, 0x1.cd682d2c39ab4p604},
+                {0x1.a43ffffffb99fp8, 0x1.398efb7895c02p606},
+                {0x1.a53ffffffb99fp8, 0x1.aa2b938729ffap607},
+                {0x1.a63ffffffb99fp8, 0x1.219cd9531c9cep609},
+                {0x1.a73ffffffb99fp8, 0x1.899fdc76e059bp610},
+                {0x1.a83ffffffb99fp8, 0x1.0b7edc8aa647ep612},
+                {0x1.a93ffffffb99fp8, 0x1.6b906c232d65ep613},
+                {0x1.aa3ffffffb99fp8, 0x1.ee22898b97fbep614},
+                {0x1.ab3ffffffb99fp8, 0x1.4fccab37000cep616},
+                {0x1.ac3ffffffb99fp8, 0x1.c866193ae89dbp617},
+                {0x1.ad3ffffffb99fp8, 0x1.3627b854c5c27p619},
+                {0x1.ae3ffffffb99fp8, 0x1.a58b68788e1e6p620},
+                {0x1.af3ffffffb99fp8, 0x1.1e781f8a5efe5p622},
+                {0x1.b03ffffffb99fp8, 0x1.855a202353f77p623},
+                {0x1.b13ffffffb99fp8, 0x1.0897974f62fe1p625},
+                {0x1.b23ffffffb99fp8, 0x1.679e369129826p626},
+                {0x1.b33ffffffb99fp8, 0x1.e8c58542c521dp627},
+                {0x1.b43ffffffb99fp8, 0x1.4c279b7142392p629},
+                {0x1.b53ffffffb99fp8, 0x1.c371efb43e76ep630},
+                {0x1.b63ffffffb99fp8, 0x1.32c9ea1ab59ccp632},
+                {0x1.b73ffffffb99fp8, 0x1.a0f817c69fb0ap633},
+                {0x1.b83ffffffb99fp8, 0x1.1b5c21ca08788p635},
+                {0x1.b93ffffffb99fp8, 0x1.812042e534a64p636},
+                {0x1.ba3ffffffb99fp8, 0x1.05b86359a079cp638},
+                {0x1.bb3ffffffb99fp8, 0x1.63b6f7fddd3efp639},
+                {0x1.bc3ffffffb99fp8, 0x1.e3776813fda8ep640},
+                {0x1.bd3ffffffb99fp8, 0x1.488cac4ce84e7p642},
+                {0x1.be3ffffffb99fp8, 0x1.be8b89ed9a77dp643},
+                {0x1.bf3ffffffb99fp8, 0x1.2f75768394a5p645},
+                {0x1.c03ffffffb99fp8, 0x1.9c717dbaae2b8p646},
+                {0x1.c13ffffffb99fp8, 0x1.1848c7ccfefe3p648},
+                {0x1.c23ffffffb99fp8, 0x1.7cf223c0074fbp649},
+                {0x1.c33ffffffb99fp8, 0x1.02e12a3ec0173p651},
+                {0x1.c43ffffffb99fp8, 0x1.5fda91f1b0d98p652},
+                {0x1.c53ffffffb99fp8, 0x1.de38089682abp653},
+                {0x1.c63ffffffb99fp8, 0x1.44fbc1a5fe2ddp655},
+                {0x1.c73ffffffb99fp8, 0x1.b9b2c1a7cc7aap656},
+                {0x1.c83ffffffb99fp8, 0x1.2c2a43919580dp658},
+                {0x1.c93ffffffb99fp8, 0x1.97f7770145248p659},
+                {0x1.ca3ffffffb99fp8, 0x1.153df9919867p661},
+                {0x1.cb3ffffffb99fp8, 0x1.78cfa212f8edcp662},
+                {0x1.cc3ffffffb99fp8, 0x1.0011d5d26caedp664},
+                {0x1.cd3ffffffb99fp8, 0x1.5c08e649b4b94p665},
+                {0x1.ce3ffffffb99fp8, 0x1.d9073dd4a4c7bp666},
+                {0x1.cf3ffffffb99fp8, 0x1.4174bfa6c0d24p668},
+                {0x1.d03ffffffb99fp8, 0x1.b4e7710dea691p669},
+                {0x1.d13ffffffb99fp8, 0x1.28e8378f2345ap671},
+                {0x1.d23ffffffb99fp8, 0x1.9389e0a91894fp672},
+                {0x1.d33ffffffb99fp8, 0x1.123b9f58df0dap674},
+                {0x1.d43ffffffb99fp8, 0x1.74b89d97dfdd3p675},
+                {0x1.d53ffffffb99fp8, 0x1.fa94a04bdb05cp676},
+                {0x1.d63ffffffb99fp8, 0x1.5841d736b633cp678},
+                {0x1.d73ffffffb99fp8, 0x1.d3e4df4a846ddp679},
+                {0x1.d83ffffffb99fp8, 0x1.3df78ac6c50cep681},
+                {0x1.d93ffffffb99fp8, 0x1.b02972b428f19p682},
+                {0x1.da3ffffffb99fp8, 0x1.25af390e18cbep684},
+                {0x1.db3ffffffb99fp8, 0x1.8f289821f41b9p685},
+                {0x1.dc3ffffffb99fp8, 0x1.0f41a1a5d8764p687},
+                {0x1.dd3ffffffb99fp8, 0x1.70acf6623ff32p688},
+                {0x1.de3ffffffb99fp8, 0x1.f515070ef61acp689},
+                {0x1.df3ffffffb99fp8, 0x1.5485473c56dfcp691},
+                {0x1.e03ffffffb99fp8, 0x1.ced0c4e4d59e4p692},
+                {0x1.e13ffffffb99fp8, 0x1.3a8407ca209c6p694},
+                {0x1.e23ffffffb99fp8, 0x1.ab78a196b76fdp695},
+                {0x1.e33ffffffb99fp8, 0x1.227f2ee6fa305p697},
+                {0x1.e43ffffffb99fp8, 0x1.8ad37b3bad33ep698},
+                {0x1.e53ffffffb99fp8, 0x1.0c4fe93ccdf88p700},
+                {0x1.e63ffffffb99fp8, 0x1.6cac8cde514efp701},
+                {0x1.e73ffffffb99fp8, 0x1.efa4b5032b54fp702},
+                {0x1.e83ffffffb99fp8, 0x1.50d31930266e8p704},
+                {0x1.e93ffffffb99fp8, 0x1.c9cac6ffa71cbp705},
+                {0x1.ea3ffffffb99fp8, 0x1.371a1bc09599dp707},
+                {0x1.eb3ffffffb99fp8, 0x1.a6d4d9189f018p708},
+                {0x1.ec3ffffffb99fp8, 0x1.1f580038307ccp710},
+                {0x1.ed3ffffffb99fp8, 0x1.868a6825185b7p711},
+                {0x1.ee3ffffffb99fp8, 0x1.09665f229766bp713},
+                {0x1.ef3ffffffb99fp8, 0x1.68b741d009e02p714},
+                {0x1.f03ffffffb99fp8, 0x1.ea437fb4bc319p715},
+                {0x1.f13ffffffb99fp8, 0x1.4d2b3038bf046p717},
+                {0x1.f23ffffffb99ep8, 0x1.c4d2be652cea4p718},
+                {0x1.f33ffffffb99ep8, 0x1.33b9ac04c0212p720},
+                {0x1.f43ffffffb99ep8, 0x1.a23df502a4a3ap721},
+                {0x1.f53ffffffb99ep8, 0x1.1c39946547606p723},
+                {0x1.f63ffffffb99ep8, 0x1.824d3d6b0103dp724},
+                {0x1.f73ffffffb99ep8, 0x1.0684ec9be79c4p726},
+                {0x1.f83ffffffb99ep8, 0x1.64ccf65229834p727},
+                {0x1.f93ffffffb99ep8, 0x1.e4f13d25df78ap728},
+                {0x1.fa3ffffffb99ep8, 0x1.498d6fcce3f5ep730},
+                {0x1.fb3ffffffb99ep8, 0x1.bfe8844c8ea89p731},
+                {0x1.fc3ffffffb99ep8, 0x1.30629e3b46a18p733},
+                {0x1.fd3ffffffb99ep8, 0x1.9db3d1822eed1p734},
+                {0x1.fe3ffffffb99ep8, 0x1.1923d3162d5cep736},
+                {0x1.ff3ffffffb99ep8, 0x1.7e1bd9f724dbcp737},
+                {0x1.001ffffffdccfp9, 0x1.03ab7b2c9b517p739},
+                {0x1.009ffffffdccfp9, 0x1.60ed8bd54933ep740},
+                {0x1.011ffffffdccfp9, 0x1.dfadc3cd79f32p741},
+                {0x1.019ffffffdccfp9, 0x1.45f9bbb2a35d1p743},
+                {0x1.021ffffffdccfp9, 0x1.bb0bf258b833ap744},
+                {0x1.029ffffffdccfp9, 0x1.2d14d8520baf7p746},
+                {0x1.031ffffffdccfp9, 0x1.99364b282dd34p747},
+                {0x1.039ffffffdccfp9, 0x1.1616a4367556fp749},
+                {0x1.041ffffffdccfp9, 0x1.79f61d0f30fbp750},
+                {0x1.049ffffffdccfp9, 0x1.00d9f49709365p752},
+                {0x1.051ffffffdccfp9, 0x1.5d18e41eebfc4p753},
+                {0x1.059ffffffdccfp9, 0x1.da78ea95d97f9p754},
+                {0x1.061ffffffdccfp9, 0x1.426ff7fe794b6p756},
+                {0x1.069ffffffdccfp9, 0x1.b63ce2972ea1ep757},
+                {0x1.071ffffffdccfp9, 0x1.29d0407f62d33p759},
+                {0x1.079ffffffdccfp9, 0x1.94c53ee806803p760},
+                {0x1.081ffffffdccfp9, 0x1.1311eff49ae9ap762},
+                {0x1.089ffffffdccfp9, 0x1.75dbe653c2ceap763},
+                {0x1.091ffffffdccfp9, 0x1.fc2085b6a9375p764},
+                {0x1.099ffffffdccfp9, 0x1.594ee148935c8p766},
+                {0x1.0a1ffffffdccfp9, 0x1.d55288db74dc3p767},
+                {0x1.0a9ffffffdccfp9, 0x1.3ef00912762eap769},
+                {0x1.0b1ffffffdccfp9, 0x1.b17b2f7ee7f4ep770},
+                {0x1.0b9ffffffdccfp9, 0x1.2694bd41472c4p772},
+                {0x1.0c1ffffffdccfp9, 0x1.90608a1681a3ep773},
+                {0x1.0c9ffffffdccfp9, 0x1.10159ec1486a4p775},
+                {0x1.0d1ffffffdccfp9, 0x1.71cd15bf6b516p776},
+                {0x1.0d9ffffffdccfp9, 0x1.f69ca06d83551p777},
+                {0x1.0e1ffffffdccfp9, 0x1.558f65bed5d1ap779},
+                {0x1.0e9ffffffdccfp9, 0x1.d03a766bae541p780},
+                {0x1.0f1ffffffdccfp9, 0x1.3b79d39d672c6p782},
+                {0x1.0f9ffffffdccfp9, 0x1.acc6b3ef261e7p783},
+                {0x1.101ffffffdccfp9, 0x1.2362355c94574p785},
+                {0x1.109ffffffdccfp9, 0x1.8c080a68bcd97p786},
+                {0x1.111ffffffdccfp9, 0x1.0d21994e9f02ap788},
+                {0x1.119ffffffdccfp9, 0x1.6dc98ba5b51bp789},
+                {0x1.121ffffffdccfp9, 0x1.f1280e4617147p790},
+                {0x1.129ffffffdccfp9, 0x1.51da544077fa2p792},
+                {0x1.131ffffffdccfp9, 0x1.cb308b8399fb7p793},
+                {0x1.139ffffffdccfp9, 0x1.380d3c9a00e7ep795},
+                {0x1.141ffffffdccfp9, 0x1.a81f4b2e55334p796},
+                {0x1.149ffffffdccfp9, 0x1.20388fdc417d5p798},
+                {0x1.151ffffffdccfp9, 0x1.87bb9df31efbp799},
+                {0x1.159ffffffdccfp9, 0x1.0a35c88f80cbp801},
+                {0x1.161ffffffdccfp9, 0x1.69d128b22d25ap802},
+                {0x1.169ffffffdccfp9, 0x1.ebc2a4ab78bb5p803},
+                {0x1.171ffffffdccfp9, 0x1.4e2f8fdd883d6p805},
+                {0x1.179ffffffdccfp9, 0x1.c634a0cec7546p806},
+                {0x1.181ffffffdccfp9, 0x1.34aa294e0c99ep808},
+                {0x1.189ffffffdccfp9, 0x1.a384d0e8ecc3p809},
+                {0x1.191ffffffdccfp9, 0x1.1d17b4109e865p811},
+                {0x1.199ffffffdccfp9, 0x1.837b23284f5e9p812},
+                {0x1.1a1ffffffdccfp9, 0x1.075215b6dcdc8p814},
+                {0x1.1a9ffffffdccfp9, 0x1.65e3cde76e421p815},
+                {0x1.1b1ffffffdccfp9, 0x1.e66c397f0e285p816},
+                {0x1.1b9ffffffdccfp9, 0x1.4a8efbf67ceccp818},
+                {0x1.1c1ffffffdccfp9, 0x1.c1468f660e51bp819},
+                {0x1.1c9ffffffdccfp9, 0x1.31507f4997713p821},
+                {0x1.1d1ffffffdccfp9, 0x1.9ef72130544cep822},
+                {0x1.1d9ffffffdccfp9, 0x1.19ff898e9368dp824},
+                {0x1.1e1ffffffdccfp9, 0x1.7f4678d82ff18p825},
+                {0x1.1e9ffffffdccfp9, 0x1.04766a36fd582p827},
+                {0x1.1f1ffffffdccfp9, 0x1.62015c9e2f34p828},
+                {0x1.1f9ffffffdccfp9, 0x1.e124a317460fp829},
+                {0x1.201ffffffdccfp9, 0x1.46f87c3b54d8ep831},
+                {0x1.209ffffffdccfp9, 0x1.bc6630ce5faecp832},
+                {0x1.211ffffffdccfp9, 0x1.2e00246624382p834},
+                {0x1.219ffffffdccfp9, 0x1.9a761879cac82p835},
+                {0x1.221ffffffdccfp9, 0x1.16eff82ee1911p837},
+                {0x1.229ffffffdccfp9, 0x1.7b1d7e2eda2c6p838},
+                {0x1.231ffffffdccfp9, 0x1.01a2afc0d75c2p840},
+                {0x1.239ffffffdccfp9, 0x1.5e29b684536ep841},
+                {0x1.241ffffffdccfp9, 0x1.dbebb83e52c5dp842},
+                {0x1.249ffffffdccfp9, 0x1.436bf4aaba53p844},
+                {0x1.251ffffffdccfp9, 0x1.b7935ef798935p845},
+                {0x1.259ffffffdccfp9, 0x1.2ab8fec5df362p847},
+                {0x1.261ffffffdccfp9, 0x1.9601939d5137dp848},
+                {0x1.269ffffffdccfp9, 0x1.13e8e80d6759dp850},
+                {0x1.271ffffffdccfp9, 0x1.770012b39ed67p851},
+                {0x1.279ffffffdccfp9, 0x1.fdada086b9c52p852},
+                {0x1.281ffffffdccfp9, 0x1.5a5cbd9bfe665p854},
+                {0x1.289ffffffdccfp9, 0x1.d6c15030e89c1p855},
+                {0x1.291ffffffdccfp9, 0x1.3fe9499128953p857},
+                {0x1.299ffffffdccfp9, 0x1.b2cdf43b59797p858},
+                {0x1.2a1ffffffdccfp9, 0x1.277af4d2d449ap860},
+                {0x1.2a9ffffffdccfp9, 0x1.91996fd498417p861},
+                {0x1.2b1ffffffdccfp9, 0x1.10ea41886590dp863},
+                {0x1.2b9ffffffdccfp9, 0x1.72ee16480890ep864},
+                {0x1.2c1ffffffdccfp9, 0x1.f8256bd5a1072p865},
+                {0x1.2c9ffffffdccfp9, 0x1.569a543aa97d8p867},
+                {0x1.2d1ffffffdccfp9, 0x1.d1a5429cffadp868},
+                {0x1.2d9ffffffdccfp9, 0x1.3c705f8813894p870},
+                {0x1.2e1ffffffdccfp9, 0x1.ae15cb5be04dap871},
+                {0x1.2e9ffffffdccfp9, 0x1.2445ed3e27324p873},
+                {0x1.2f1ffffffdccfp9, 0x1.8d3d8ab9f0bdep874},
+                {0x1.2f9ffffffdccfp9, 0x1.0df3ed3fc701dp876},
+                {0x1.301ffffffdccfp9, 0x1.6ee76926e122bp877},
+                {0x1.309ffffffdccfp9, 0x1.f2ac9640362cap878},
+                {0x1.311ffffffdccfp9, 0x1.52e25d083c6f6p880},
+                {0x1.319ffffffdccfp9, 0x1.cc9767a099276p881},
+                {0x1.321ffffffdccfp9, 0x1.39011b7511e91p883},
+                {0x1.329ffffffdccfp9, 0x1.a96abf82e5bedp884},
+                {0x1.331ffffffdccfp9, 0x1.2119ceff4e062p886},
+                {0x1.339ffffffdccfp9, 0x1.88edc2473f3cfp887},
+                {0x1.341ffffffdccfp9, 0x1.0b05d4146a019p889},
+                {0x1.349ffffffdccfp9, 0x1.6aebebe3397ccp890},
+                {0x1.351ffffffdccfp9, 0x1.ed42f5104656ep891},
+                {0x1.359ffffffdccfp9, 0x1.4f34bafe2847bp893},
+                {0x1.361ffffffdccfp9, 0x1.c79797c887ff8p894},
+                {0x1.369ffffffdccfp9, 0x1.359b628909b0ap896},
+                {0x1.371ffffffdccfp9, 0x1.a4ccac407db6ep897},
+                {0x1.379ffffffdccfp9, 0x1.1df681534dcc2p899},
+                {0x1.381ffffffdccfp9, 0x1.84a9f4d4f272ap900},
+                {0x1.389ffffffdccfp9, 0x1.081fdf276bf44p902},
+                {0x1.391ffffffdccfp9, 0x1.66fb7f67746f6p903},
+                {0x1.399ffffffdccfp9, 0x1.e7e85e064cb73p904},
+                {0x1.3a1ffffffdccfp9, 0x1.4b91516684d28p906},
+                {0x1.3a9ffffffdccfp9, 0x1.c2a5ac0f3d022p907},
+                {0x1.3b1ffffffdccfp9, 0x1.323f1a3f5edc4p909},
+                {0x1.3b9ffffffdccfp9, 0x1.a03b6d89faf11p910},
+                {0x1.3c1ffffffdccfp9, 0x1.1adbebbbf9351p912},
+                {0x1.3c9ffffffdccfp9, 0x1.80720118fc863p913},
+                {0x1.3d1ffffffdccfp9, 0x1.0541f7d976c95p915},
+                {0x1.3d9ffffffdccfp9, 0x1.631604f454091p916},
+                {0x1.3e1ffffffdccfp9, 0x1.e29ca75828ca4p917},
+                {0x1.3e9ffffffdccfp9, 0x1.47f803db3082ep919},
+                {0x1.3f1ffffffdccfp9, 0x1.bdc17ddb963f2p920},
+                {0x1.3f9ffffffdccfp9, 0x1.2eec285d246c2p922},
+                {0x1.401ffffffdccfp9, 0x1.9bb6dfb8d5a7bp923},
+                {0x1.409ffffffdccfp9, 0x1.17c9f5ff316ddp925},
+                {0x1.411ffffffdccfp9, 0x1.7c45c625cf3bcp926},
+                {0x1.419ffffffdccfp9, 0x1.026c07ca1067p928},
+                {0x1.421ffffffdccfp9, 0x1.5f3b5e200997dp929},
+                {0x1.429ffffffdccfp9, 0x1.dd5fa7afd8289p930},
+                {0x1.431ffffffdccfp9, 0x1.4468b644f2c7fp932},
+                {0x1.439ffffffdccfp9, 0x1.b8eae6ffb1c26p933},
+                {0x1.441ffffffdccfp9, 0x1.2ba272f04fa72p935},
+                {0x1.449ffffffdccfp9, 0x1.973edf89954efp936},
+                {0x1.451ffffffdccfp9, 0x1.14c088262904bp938},
+                {0x1.459ffffffdccfp9, 0x1.782523695aef2p939},
+                {0x1.461ffffffdccfp9, 0x1.ff3bf1add8023p940},
+                {0x1.469ffffffdccfp9, 0x1.5b6b6cd54844dp942},
+                {0x1.471ffffffdccfp9, 0x1.d831362a33e02p943},
+                {0x1.479ffffffdccfp9, 0x1.40e34cdaa0c9dp945},
+                {0x1.481ffffffdccfp9, 0x1.b421c1b7c391cp946},
+                {0x1.489ffffffdccfp9, 0x1.2861e04eed965p948},
+                {0x1.491ffffffdccfp9, 0x1.92d34a1abd55p949},
+                {0x1.499ffffffdccfp9, 0x1.11bf8a7ca8dc9p951},
+                {0x1.4a1ffffffdccfp9, 0x1.740ff8ac10594p952},
+                {0x1.4a9ffffffdccfp9, 0x1.f9af6a367aa8cp953},
+                {0x1.4b1ffffffdccfp9, 0x1.57a613525a444p955},
+                {0x1.4b9ffffffdccfp9, 0x1.d3112a55b14f7p956},
+                {0x1.4c1ffffffdccfp9, 0x1.3d67ac204487bp958},
+                {0x1.4c9ffffffdccfp9, 0x1.af65e8a8eee76p959},
+                {0x1.4d1ffffffdccfp9, 0x1.252a57165ab35p961},
+                {0x1.4d9ffffffdccfp9, 0x1.8e73fcebbcdf2p962},
+                {0x1.4e1ffffffdccfp9, 0x1.0ec6e5905727p964},
+                {0x1.4e9ffffffdccfp9, 0x1.7006260fe518p965},
+                {0x1.4f1ffffffdccfp9, 0x1.f4324dde1b853p966},
+                {0x1.4f9ffffffdccfp9, 0x1.53eb342838912p968},
+                {0x1.501ffffffdccfp9, 0x1.cdff5c312677p969},
+                {0x1.509ffffffdccfp9, 0x1.39f5b8e646512p971},
+                {0x1.511ffffffdccfp9, 0x1.aab736e0229e8p972},
+                {0x1.519ffffffdccfp9, 0x1.21fbbe2a7cc33p974},
+                {0x1.521ffffffdccfp9, 0x1.8a20d5dbe17b1p975},
+                {0x1.529ffffffdccfp9, 0x1.0bd6823000616p977},
+                {0x1.531ffffffdccfp9, 0x1.6c078c0f5af0cp978},
+                {0x1.539ffffffdccfp9, 0x1.eec471cd26923p979},
+                {0x1.541ffffffdccfp9, 0x1.503ab239a52eep981},
+                {0x1.549ffffffdccfp9, 0x1.c8fba42a91b8p982},
+                {0x1.551ffffffdccfp9, 0x1.368d584898928p984},
+                {0x1.559ffffffdccfp9, 0x1.a61587d0f8cb4p985},
+                {0x1.561ffffffdccfp9, 0x1.1ed5fcb4fed8p987},
+                {0x1.569ffffffdccfp9, 0x1.85d9b3294cbccp988},
+                {0x1.571ffffffdccfp9, 0x1.08ee496ae24e1p990},
+                {0x1.579ffffffdccfp9, 0x1.68140b7c89c5cp991},
+                {0x1.581ffffffdccfp9, 0x1.e965aba3129a2p992},
+                {0x1.589ffffffdccfp9, 0x1.4c9470ba47e91p994},
+                {0x1.591ffffffdccfp9, 0x1.c405db1de4f69p995},
+                {0x1.599ffffffdccfp9, 0x1.332e6fade5fp997},
+                {0x1.5a1ffffffdccfp9, 0x1.a180b7549973p998},
+                {0x1.5a9ffffffdccfp9, 0x1.1bb8fa248f731p1000},
+                {0x1.5b1ffffffdccfp9, 0x1.819e736fecc0ap1001},
+                {0x1.5b9ffffffdccfp9, 0x1.060e248ff8e45p1003},
+                {0x1.5c1ffffffdccfp9, 0x1.642b85802c37dp1004},
+                {0x1.5c9ffffffdccfp9, 0x1.e415d17516714p1005},
+                {0x1.5d1ffffffdccfp9, 0x1.48f8532dcd8aap1007},
+                {0x1.5d9ffffffdccfp9, 0x1.bf1dda53d4168p1008},
+                {0x1.5e1ffffffdccfp9, 0x1.2fd8e4c6c1a74p1010},
+                {0x1.5e9ffffffdccfp9, 0x1.9cf8a1a8a05e1p1011},
+                {0x1.5f1ffffffdccfp9, 0x1.18a49e2c20c14p1013},
+                {0x1.5f9ffffffdccfp9, 0x1.7d6ef5a877896p1014},
+                {0x1.601ffffffdccfp9, 0x1.0335fd2d4d32ap1016},
+                {0x1.609ffffffdccfp9, 0x1.604ddb98aeeb6p1017},
+                {0x1.611ffffffdccfp9, 0x1.ded4b9cce1c65p1018},
+                {0x1.619ffffffdccep9, 0x1.45663d67095d1p1020},
+                {0x1.621ffffffdccep9, 0x1.ba437b80a6915p1021},
+                {0x1.629ffffffdccep9, 0x1.2c8c9d8cda0c8p1023},
+        };
+
+        for (double[] testCase : testCases) {
+            testExpm1Case(testCase[0], testCase[1]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/FdlibmTranslit.java b/ojluni/src/test/java/lang/StrictMath/FdlibmTranslit.java
new file mode 100644
index 0000000..e0e26ca
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/FdlibmTranslit.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.StrictMath;
+
+/**
+ * A transliteration of the "Freely Distributable Math Library" algorithms from C into Java. That
+ * is, this port of the algorithms is as close to the C originals as possible while still being
+ * readable legal Java.
+ */
+public class FdlibmTranslit {
+
+    private FdlibmTranslit() {
+    }
+
+    /**
+     * Return the low-order 32 bits of the double argument as an int.
+     */
+    private static int __LO(double x) {
+        long transducer = Double.doubleToRawLongBits(x);
+        return (int) transducer;
+    }
+
+    /**
+     * Return a double with its low-order bits of the second argument and the high-order bits of the
+     * first argument..
+     */
+    private static double __LO(double x, int low) {
+        long transX = Double.doubleToRawLongBits(x);
+        return Double.longBitsToDouble((transX & 0xFFFF_FFFF_0000_0000L) |
+                (low & 0x0000_0000_FFFF_FFFFL));
+    }
+
+    /**
+     * Return the high-order 32 bits of the double argument as an int.
+     */
+    private static int __HI(double x) {
+        long transducer = Double.doubleToRawLongBits(x);
+        return (int) (transducer >> 32);
+    }
+
+    /**
+     * Return a double with its high-order bits of the second argument and the low-order bits of the
+     * first argument..
+     */
+    private static double __HI(double x, int high) {
+        long transX = Double.doubleToRawLongBits(x);
+        return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL) |
+                (((long) high)) << 32);
+    }
+
+    public static double hypot(double x, double y) {
+        return Hypot.compute(x, y);
+    }
+
+    /**
+     * cbrt(x) Return cube root of x
+     */
+    public static class Cbrt {
+
+        // unsigned
+        private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
+        private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+        private static final double C = 5.42857142857142815906e-01; /* 19/35     = 0x3FE15F15, 0xF15F15F1 */
+        private static final double D = -7.05306122448979611050e-01; /* -864/1225 = 0xBFE691DE, 0x2532C834 */
+        private static final double E = 1.41428571428571436819e+00; /* 99/70     = 0x3FF6A0EA, 0x0EA0EA0F */
+        private static final double F = 1.60714285714285720630e+00; /* 45/28     = 0x3FF9B6DB, 0x6DB6DB6E */
+        private static final double G = 3.57142857142857150787e-01; /* 5/14      = 0x3FD6DB6D, 0xB6DB6DB7 */
+
+        public static strictfp double compute(double x) {
+            int hx;
+            double r, s, t = 0.0, w;
+            int sign; // unsigned
+
+            hx = __HI(x);           // high word of x
+            sign = hx & 0x80000000;             // sign= sign(x)
+            hx ^= sign;
+            if (hx >= 0x7ff00000) {
+                return (x + x); // cbrt(NaN,INF) is itself
+            }
+            if ((hx | __LO(x)) == 0) {
+                return (x);          // cbrt(0) is itself
+            }
+
+            x = __HI(x, hx);   // x <- |x|
+            // rough cbrt to 5 bits
+            if (hx < 0x00100000) {               // subnormal number
+                t = __HI(t, 0x43500000);          // set t= 2**54
+                t *= x;
+                t = __HI(t, __HI(t) / 3 + B2);
+            } else {
+                t = __HI(t, hx / 3 + B1);
+            }
+
+            // new cbrt to 23 bits, may be implemented in single precision
+            r = t * t / x;
+            s = C + r * t;
+            t *= G + F / (s + E + D / s);
+
+            // chopped to 20 bits and make it larger than cbrt(x)
+            t = __LO(t, 0);
+            t = __HI(t, __HI(t) + 0x00000001);
+
+            // one step newton iteration to 53 bits with error less than 0.667 ulps
+            s = t * t;          // t*t is exact
+            r = x / s;
+            w = t + t;
+            r = (r - t) / (w + r);  // r-s is exact
+            t = t + t * r;
+
+            // restore the sign bit
+            t = __HI(t, __HI(t) | sign);
+            return (t);
+        }
+    }
+
+    /**
+     * hypot(x,y)
+     *
+     * Method : If (assume round-to-nearest) z = x*x + y*y has error less than sqrt(2)/2 ulp, than
+     * sqrt(z) has error less than 1 ulp (exercise).
+     *
+     * So, compute sqrt(x*x + y*y) with some care as follows to get the error below 1 ulp:
+     *
+     * Assume x > y > 0; (if possible, set rounding to round-to-nearest) 1. if x > 2y  use x1*x1 +
+     * (y*y + (x2*(x + x1))) for x*x + y*y where x1 = x with lower 32 bits cleared, x2 = x - x1;
+     * else 2. if x <= 2y use t1*y1 + ((x-y) * (x-y) + (t1*y2 + t2*y)) where t1 = 2x with lower 32
+     * bits cleared, t2 = 2x - t1, y1= y with lower 32 bits chopped, y2 = y - y1.
+     *
+     * NOTE: scaling may be necessary if some argument is too large or too tiny
+     *
+     * Special cases: hypot(x,y) is INF if x or y is +INF or -INF; else hypot(x,y) is NAN if x or y
+     * is NAN.
+     *
+     * Accuracy: hypot(x,y) returns sqrt(x^2 + y^2) with error less than 1 ulps (units in the last
+     * place)
+     */
+    static class Hypot {
+
+        public static double compute(double x, double y) {
+            double a = x;
+            double b = y;
+            double t1, t2, y1, y2, w;
+            int j, k, ha, hb;
+
+            ha = __HI(x) & 0x7fffffff;        // high word of  x
+            hb = __HI(y) & 0x7fffffff;        // high word of  y
+            if (hb > ha) {
+                a = y;
+                b = x;
+                j = ha;
+                ha = hb;
+                hb = j;
+            } else {
+                a = x;
+                b = y;
+            }
+            a = __HI(a, ha);   // a <- |a|
+            b = __HI(b, hb);   // b <- |b|
+            if ((ha - hb) > 0x3c00000) {
+                return a + b;  // x / y > 2**60
+            }
+            k = 0;
+            if (ha > 0x5f300000) {   // a>2**500
+                if (ha >= 0x7ff00000) {       // Inf or NaN
+                    w = a + b;                // for sNaN
+                    if (((ha & 0xfffff) | __LO(a)) == 0) {
+                        w = a;
+                    }
+                    if (((hb ^ 0x7ff00000) | __LO(b)) == 0) {
+                        w = b;
+                    }
+                    return w;
+                }
+                // scale a and b by 2**-600
+                ha -= 0x25800000;
+                hb -= 0x25800000;
+                k += 600;
+                a = __HI(a, ha);
+                b = __HI(b, hb);
+            }
+            if (hb < 0x20b00000) {   // b < 2**-500
+                if (hb <= 0x000fffff) {      // subnormal b or 0 */
+                    if ((hb | (__LO(b))) == 0) {
+                        return a;
+                    }
+                    t1 = 0;
+                    t1 = __HI(t1, 0x7fd00000);  // t1=2^1022
+                    b *= t1;
+                    a *= t1;
+                    k -= 1022;
+                } else {            // scale a and b by 2^600
+                    ha += 0x25800000;       // a *= 2^600
+                    hb += 0x25800000;       // b *= 2^600
+                    k -= 600;
+                    a = __HI(a, ha);
+                    b = __HI(b, hb);
+                }
+            }
+            // medium size a and b
+            w = a - b;
+            if (w > b) {
+                t1 = 0;
+                t1 = __HI(t1, ha);
+                t2 = a - t1;
+                w = Math.sqrt(t1 * t1 - (b * (-b) - t2 * (a + t1)));
+            } else {
+                a = a + a;
+                y1 = 0;
+                y1 = __HI(y1, hb);
+                y2 = b - y1;
+                t1 = 0;
+                t1 = __HI(t1, ha + 0x00100000);
+                t2 = a - t1;
+                w = Math.sqrt(t1 * y1 - (w * (-w) - (t1 * y2 + t2 * b)));
+            }
+            if (k != 0) {
+                t1 = 1.0;
+                int t1_hi = __HI(t1);
+                t1_hi += (k << 20);
+                t1 = __HI(t1, t1_hi);
+                return t1 * w;
+            } else {
+                return w;
+            }
+        }
+    }
+
+    /**
+     * Returns the exponential of x.
+     *
+     * Method 1. Argument reduction: Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. Given x,
+     * find r and integer k such that
+     *
+     * x = k*ln2 + r,  |r| <= 0.5*ln2.
+     *
+     * Here r will be represented as r = hi-lo for better accuracy.
+     *
+     * 2. Approximation of exp(r) by a special rational function on the interval [0,0.34658]: Write
+     * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... We use a special Reme
+     * algorithm on [0,0.34658] to generate a polynomial of degree 5 to approximate R. The maximum
+     * error of this polynomial approximation is bounded by 2**-59. In other words, R(z) ~ 2.0 +
+     * P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 (where z=r*r, and the values of P1 to P5 are
+     * listed below) and |                  5          |     -59 | 2.0+P1*z+...+P5*z   -  R(z) | <=
+     * 2 |                             | The computation of exp(r) thus becomes 2*r exp(r) = 1 +
+     * ------- R - r r*R1(r) = 1 + r + ----------- (for better accuracy) 2 - R1(r) where 2       4
+     * 10 R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).
+     *
+     * 3. Scale back to obtain exp(x): From step 1, we have exp(x) = 2^k * exp(r)
+     *
+     * Special cases: exp(INF) is INF, exp(NaN) is NaN; exp(-INF) is 0, and for finite argument,
+     * only exp(0)=1 is exact.
+     *
+     * Accuracy: according to an error analysis, the error is always less than 1 ulp (unit in the
+     * last place).
+     *
+     * Misc. info. For IEEE double if x >  7.09782712893383973096e+02 then exp(x) overflow if x <
+     * -7.45133219101941108420e+02 then exp(x) underflow
+     *
+     * Constants: The hexadecimal values are the intended ones for the following constants. The
+     * decimal values may be used, provided that the compiler will convert from decimal to binary
+     * accurately enough to produce the hexadecimal values shown.
+     */
+    static class Exp {
+
+        private static final double ONE = 1.0;
+        private static final double[] HAL_F = {0.5, -0.5,};
+        private static final double HUGE = 1.0e+300;
+        private static final double TWOM_1000 = 9.33263618503218878990e-302;      /* 2**-1000=0x01700000,0*/
+        private static final double O_THRESHOLD = 7.09782712893383973096e+02;   /* 0x40862E42, 0xFEFA39EF */
+        private static final double U_THRESHOLD = -7.45133219101941108420e+02;   /* 0xc0874910, 0xD52D3051 */
+        private static final double[] LN_2_HI = {6.93147180369123816490e-01,
+                /* 0x3fe62e42, 0xfee00000 */
+                -6.93147180369123816490e-01};  /* 0xbfe62e42, 0xfee00000 */
+        private static final double[] LN_2_LO = {1.90821492927058770002e-10,
+                /* 0x3dea39ef, 0x35793c76 */
+                -1.90821492927058770002e-10,}; /* 0xbdea39ef, 0x35793c76 */
+        private static final double INV_LN_2 = 1.44269504088896338700e+00;       /* 0x3ff71547, 0x652b82fe */
+        private static final double P1 = 1.66666666666666019037e-01;         /* 0x3FC55555, 0x5555553E */
+        private static final double P2 = -2.77777777770155933842e-03;         /* 0xBF66C16C, 0x16BEBD93 */
+        private static final double P3 = 6.61375632143793436117e-05;         /* 0x3F11566A, 0xAF25DE2C */
+        private static final double P4 = -1.65339022054652515390e-06;         /* 0xBEBBBD41, 0xC5D26BF1 */
+        private static final double P5 = 4.13813679705723846039e-08;         /* 0x3E663769, 0x72BEA4D0 */
+
+        public static strictfp double compute(double x) {
+            double y, hi = 0, lo = 0, c, t;
+            int k = 0, xsb;
+            /*unsigned*/
+            int hx;
+
+            hx = __HI(x);  /* high word of x */
+            xsb = (hx >> 31) & 1;               /* sign bit of x */
+            hx &= 0x7fffffff;               /* high word of |x| */
+
+            /* filter out non-finite argument */
+            if (hx >= 0x40862E42) {                  /* if |x|>=709.78... */
+                if (hx >= 0x7ff00000) {
+                    if (((hx & 0xfffff) | __LO(x)) != 0) {
+                        return x + x;                /* NaN */
+                    } else {
+                        return (xsb == 0) ? x : 0.0;    /* exp(+-inf)={inf,0} */
+                    }
+                }
+                if (x > O_THRESHOLD) {
+                    return HUGE * HUGE; /* overflow */
+                }
+                if (x < U_THRESHOLD) {
+                    return TWOM_1000 * TWOM_1000; /* underflow */
+                }
+            }
+
+            /* argument reduction */
+            if (hx > 0x3fd62e42) {           /* if  |x| > 0.5 ln2 */
+                if (hx < 0x3FF0A2B2) {       /* and |x| < 1.5 ln2 */
+                    hi = x - LN_2_HI[xsb];
+                    lo = LN_2_LO[xsb];
+                    k = 1 - xsb - xsb;
+                } else {
+                    k = (int) (INV_LN_2 * x + HAL_F[xsb]);
+                    t = k;
+                    hi = x - t * LN_2_HI[0];    /* t*ln2HI is exact here */
+                    lo = t * LN_2_LO[0];
+                }
+                x = hi - lo;
+            } else if (hx < 0x3e300000) {     /* when |x|<2**-28 */
+                if (HUGE + x > ONE) {
+                    return ONE + x;/* trigger inexact */
+                }
+            } else {
+                k = 0;
+            }
+
+            /* x is now in primary range */
+            t = x * x;
+            c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+            if (k == 0) {
+                return ONE - ((x * c) / (c - 2.0) - x);
+            } else {
+                y = ONE - ((lo - (x * c) / (2.0 - c)) - hi);
+            }
+            if (k >= -1021) {
+                y = __HI(y, __HI(y) + (k << 20)); /* add k to y's exponent */
+                return y;
+            } else {
+                y = __HI(y, __HI(y) + ((k + 1000) << 20));/* add k to y's exponent */
+                return y * TWOM_1000;
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/HyperbolicTests.java b/ojluni/src/test/java/lang/StrictMath/HyperbolicTests.java
new file mode 100644
index 0000000..e9a18ce
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/HyperbolicTests.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4851625
+ * @summary Tests for StrictMath.{sinh, cosh, tanh}
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.StrictMath;
+
+import org.testng.annotations.Test;
+
+/**
+ * The tests in ../Math/HyperbolicTests.java test properties that should hold for any implementation
+ * of the hyperbolic functions sinh, cos, and tanh, including the FDLIBM-based ones required by the
+ * StrictMath class.  Therefore, the test cases in ../Math/HyperbolicTests.java are run against both
+ * the Math and StrictMath versions of the hyperbolic methods.  The role of this test is to verify
+ * that the FDLIBM algorithms are being used by running golden file tests on values that may vary
+ * from one conforming implementation of the hyperbolics to another.
+ */
+
+public class HyperbolicTests {
+
+    private HyperbolicTests() {
+    }
+
+    static void testSinhCase(double input, double expected) {
+        Tests.test("StrictMath.sinh(double)", input, StrictMath.sinh(input), expected);
+    }
+
+    static void testCoshCase(double input, double expected) {
+        Tests.test("StrictMath.cosh(double)", input, StrictMath.cosh(input), expected);
+    }
+
+    static void testTanhCase(double input, double expected) {
+        Tests.test("StrictMath.tanh(double)", input, StrictMath.tanh(input), expected);
+    }
+
+    @Test
+    public void testSinh() {
+        double[][] testCases = {
+                {0x1.5798ee2308c3ap-27, 0x1.5798ee2308c3bp-27},
+                {0x1.ffffffffffff8p-26, 0x1.ffffffffffffap-26},
+                {0x1.ffffffffffffep-26, 0x1.0p-25},
+                {0x1.ffffffffffff8p-25, 0x1.ffffffffffffep-25},
+                {0x1.ffffffffffffap-25, 0x1.0p-24},
+                {0x1.ad7f29abcaf47p-24, 0x1.ad7f29abcaf53p-24},
+                {0x1.ad7f29abcaf48p-24, 0x1.ad7f29abcaf54p-24},
+                {0x1.fffffffffffeap-24, 0x1.0p-23},
+                {0x1.ffffffffffff8p-24, 0x1.0000000000007p-23},
+                {0x1.fffffffffffaap-23, 0x1.0p-22},
+                {0x1.ffffffffffff8p-23, 0x1.0000000000027p-22},
+                {0x1.ffffffffffeaap-22, 0x1.0p-21},
+                {0x1.ffffffffffff8p-22, 0x1.00000000000a7p-21},
+                {0x1.ffffffffffaaap-21, 0x1.0p-20},
+                {0x1.ffffffffffff8p-21, 0x1.00000000002a7p-20},
+                {0x1.0c6f7a0b5ed8cp-20, 0x1.0c6f7a0b5f09fp-20},
+                {0x1.0c6f7a0b5ed8dp-20, 0x1.0c6f7a0b5f0ap-20},
+                {0x1.fffffffffeaaap-20, 0x1.0p-19},
+                {0x1.ffffffffffff8p-20, 0x1.0000000000aa7p-19},
+                {0x1.ffffffffffff8p-19, 0x1.0000000002aa7p-18},
+                {0x1.ffffffffffff7p-18, 0x1.000000000aaa6p-17},
+                {0x1.4f8b588e368d9p-17, 0x1.4f8b588e4e928p-17},
+                {0x1.ffffffffffffep-17, 0x1.000000002aaa9p-16},
+                {0x1.0p-16, 0x1.000000002aaaap-16},
+                {0x1.fffffffffffffp-16, 0x1.00000000aaaabp-15},
+                {0x1.fffffffffeaaap-15, 0x1.00000002aap-14},
+                {0x1.ffffffffffffep-15, 0x1.00000002aaaa9p-14},
+                {0x1.0p-14, 0x1.00000002aaaaap-14},
+                {0x1.a36e2eb1c3dd4p-14, 0x1.a36e2ebd7e43ap-14},
+                {0x1.a36e2eb1c3f8cp-14, 0x1.a36e2ebd7e5f1p-14},
+                {0x1.a36e2eb1c432cp-14, 0x1.a36e2ebd7e991p-14},
+                {0x1.fffffffffffffp-14, 0x1.0000000aaaaabp-13},
+                {0x1.ffffffffffffep-13, 0x1.0000002aaaaa9p-12},
+                {0x1.0p-12, 0x1.0000002aaaaaap-12},
+                {0x1.ffffffffff7f9p-12, 0x1.000000aaaa6a9p-11},
+                {0x1.fffffffffffffp-12, 0x1.000000aaaaaadp-11},
+                {0x1.ffffffffffffep-11, 0x1.000002aaaaacbp-10},
+                {0x1.0p-10, 0x1.000002aaaaaccp-10},
+                {0x1.0624dd2f1a79p-10, 0x1.0624e00c1c776p-10},
+                {0x1.0624dd2f1a8c9p-10, 0x1.0624e00c1c8bp-10},
+                {0x1.0624dd2f1a9fcp-10, 0x1.0624e00c1c9e3p-10},
+                {0x1.ffffffffffffep-10, 0x1.00000aaaaaccbp-9},
+                {0x1.0p-9, 0x1.00000aaaaacccp-9},
+                {0x1.ffffffffffe4ap-9, 0x1.00002aaaacbf2p-8},
+                {0x1.fffffffffffffp-9, 0x1.00002aaaacccdp-8},
+                {0x1.fffffffffff9dp-8, 0x1.0000aaaaccc9bp-7},
+                {0x1.ffffffffffffep-8, 0x1.0000aaaacccccp-7},
+                {0x1.0p-7, 0x1.0000aaaaccccdp-7},
+                {0x1.47ae147ae146fp-7, 0x1.47af7a654e9e2p-7},
+                {0x1.47ae147ae147ap-7, 0x1.47af7a654e9eep-7},
+                {0x1.47ae147ae147bp-7, 0x1.47af7a654e9efp-7},
+                {0x1.fffffffffffb6p-7, 0x1.0002aaaccccb4p-6},
+                {0x1.fffffffffffcap-7, 0x1.0002aaaccccbep-6},
+                {0x1.ffffffffffff7p-7, 0x1.0002aaaccccd5p-6},
+                {0x1.fffffffffffe9p-6, 0x1.000aaacccd001p-5},
+                {0x1.ffffffffffff7p-6, 0x1.000aaacccd008p-5},
+                {0x1.fffffffffffffp-6, 0x1.000aaacccd00dp-5},
+                {0x1.ffffffffffff6p-5, 0x1.002aacccd9cd7p-4},
+                {0x1.ffffffffffff8p-5, 0x1.002aacccd9cd9p-4},
+                {0x1.0p-4, 0x1.002aacccd9cddp-4},
+                {0x1.9999999999995p-4, 0x1.9a487337b59afp-4},
+                {0x1.9999999999996p-4, 0x1.9a487337b59afp-4},
+                {0x1.9999999999998p-4, 0x1.9a487337b59b1p-4},
+                {0x1.ffffffffffffap-4, 0x1.00aaccd00d2edp-3},
+                {0x1.ffffffffffffcp-4, 0x1.00aaccd00d2efp-3},
+                {0x1.ffffffffffff3p-3, 0x1.02accd9d080fbp-2},
+                {0x1.ffffffffffffdp-3, 0x1.02accd9d08101p-2},
+                {0x1.fffffffffffffp-3, 0x1.02accd9d08101p-2},
+                {0x1.fffffffffffecp-2, 0x1.0acd00fe63b8cp-1},
+                {0x1.ffffffffffffcp-2, 0x1.0acd00fe63b94p-1},
+                {0x1.0p-1, 0x1.0acd00fe63b97p-1},
+                {0x1.ffffffffffff6p-1, 0x1.2cd9fc44eb97ap0},
+                {0x1.ffffffffffffep-1, 0x1.2cd9fc44eb981p0},
+                {0x1.fffffffffffffp0, 0x1.d03cf63b6e19ep1},
+                {0x1.0p1, 0x1.d03cf63b6e1ap1},
+                {0x1.fffffffffffffp1, 0x1.b4a380370362dp4},
+                {0x1.0p2, 0x1.b4a380370363p4},
+                {0x1.ffffffffffffcp2, 0x1.749ea514eca4ep10},
+                {0x1.0p3, 0x1.749ea514eca66p10},
+                {0x1.fffffffffffffp3, 0x1.0f2ebd0a7ffdcp22},
+                {0x1.0p4, 0x1.0f2ebd0a7ffe4p22},
+                {0x1.fffffffffff68p4, 0x1.1f43fcc4b5b83p45},
+                {0x1.fffffffffffd4p4, 0x1.1f43fcc4b6316p45},
+                {0x1.0p5, 0x1.1f43fcc4b662cp45},
+        };
+
+        for (double[] testCase : testCases) {
+            testSinhCase(testCase[0], testCase[1]);
+        }
+    }
+
+    @Test
+    public void testCosh() {
+        double[][] testCases = {
+                {0x1.fffffffffb49fp-8, 0x1.00020000aaaabp0},
+                {0x1.47ae147ae0e45p-7, 0x1.000346de27853p0},
+                {0x1.fffffffffd9f3p-7, 0x1.0008000aaab05p0},
+                {0x1.ffffffffff9f1p-7, 0x1.0008000aaab05p0},
+                {0x1.fffffffffe27dp-6, 0x1.002000aaac169p0},
+                {0x1.ffffffffff27bp-6, 0x1.002000aaac16bp0},
+                {0x1.ffffffffffb9cp-5, 0x1.00800aab05b1ep0},
+                {0x1.ffffffffffd9dp-5, 0x1.00800aab05b1fp0},
+                {0x1.9999999999368p-4, 0x1.0147f40224b2ep0},
+                {0x1.9999999999727p-4, 0x1.0147f40224b35p0},
+                {0x1.ffffffffffed1p-4, 0x1.0200aac16db6cp0},
+                {0x1.fffffffffffd1p-4, 0x1.0200aac16db6ep0},
+                {0x1.ffffffffffeb4p-3, 0x1.080ab05ca613bp0},
+                {0x1.ffffffffffff2p-3, 0x1.080ab05ca6146p0},
+                {0x1.ffffffffffff3p-2, 0x1.20ac1862ae8cep0},
+                {0x1.ffffffffffff9p-2, 0x1.20ac1862ae8dp0},
+                {0x1.0p0, 0x1.8b07551d9f551p0},
+                {0x1.ffffffffffffbp0, 0x1.e18fa0df2d9b3p1},
+                {0x1.ffffffffffffep0, 0x1.e18fa0df2d9b8p1},
+                {0x1.fffffffffffffp0, 0x1.e18fa0df2d9bap1},
+                {0x1.ffffffffffff9p1, 0x1.b4ee858de3e68p4},
+                {0x1.ffffffffffffep1, 0x1.b4ee858de3e7ap4},
+                {0x1.fffffffffffffp1, 0x1.b4ee858de3e7dp4},
+                {0x1.ffffffffffffcp2, 0x1.749eaa93f4e5ep10},
+                {0x1.ffffffffffffdp2, 0x1.749eaa93f4e64p10},
+                {0x1.0p3, 0x1.749eaa93f4e76p10},
+                {0x1.fffffffffff6fp3, 0x1.0f2ebd0a7fb9p22},
+                {0x1.0p4, 0x1.0f2ebd0a8005cp22},
+                {0x1.fffffffffffd4p4, 0x1.1f43fcc4b6316p45},
+                {0x1.0p5, 0x1.1f43fcc4b662cp45},
+        };
+
+        for (double[] testCase : testCases) {
+            testCoshCase(testCase[0], testCase[1]);
+        }
+    }
+
+    @Test
+    public void testTanh() {
+        double[][] testCases = {
+                {0x1.5798ee2308c36p-27, 0x1.5798ee2308c36p-27},
+                {0x1.ffffffffffffep-26, 0x1.ffffffffffffbp-26},
+                {0x1.ffffffffffffep-25, 0x1.ffffffffffff3p-25},
+                {0x1.ad7f29abcaf47p-24, 0x1.ad7f29abcaf2dp-24},
+                {0x1.ad7f29abcaf48p-24, 0x1.ad7f29abcaf2ep-24},
+                {0x1.ffffffffffffep-24, 0x1.fffffffffffd3p-24},
+                {0x1.ffffffffffffep-23, 0x1.fffffffffff53p-23},
+                {0x1.ffffffffffffep-22, 0x1.ffffffffffd53p-22},
+                {0x1.ffffffffffffep-21, 0x1.ffffffffff553p-21},
+                {0x1.0c6f7a0b5ed8dp-20, 0x1.0c6f7a0b5e767p-20},
+                {0x1.ffffffffffffep-20, 0x1.fffffffffd553p-20},
+                {0x1.ffffffffffffep-19, 0x1.fffffffff5553p-19},
+                {0x1.fffffffffffffp-18, 0x1.ffffffffd5555p-18},
+                {0x1.0p-17, 0x1.ffffffffd5556p-18},
+                {0x1.4f8b588e368edp-17, 0x1.4f8b588e0685p-17},
+                {0x1.fffffffffffffp-17, 0x1.ffffffff55554p-17},
+                {0x1.fffffffffffffp-16, 0x1.fffffffd55555p-16},
+                {0x1.0p-15, 0x1.fffffffd55556p-16},
+                {0x1.fffffffffe5ddp-15, 0x1.fffffff553b33p-15},
+                {0x1.fffffffffffffp-15, 0x1.fffffff555554p-15},
+                {0x1.a36e2eb1c432dp-14, 0x1.a36e2e9a4f663p-14},
+                {0x1.ffffffffffffep-14, 0x1.ffffffd555553p-14},
+                {0x1.0p-13, 0x1.ffffffd555555p-14},
+                {0x1.ffffffffffd51p-13, 0x1.ffffff55552aap-13},
+                {0x1.fffffffffffffp-13, 0x1.ffffff5555559p-13},
+                {0x1.ffffffffffffep-12, 0x1.fffffd5555597p-12},
+                {0x1.0p-11, 0x1.fffffd5555599p-12},
+                {0x1.fffffffffff1p-11, 0x1.fffff555558a9p-11},
+                {0x1.0p-10, 0x1.fffff5555599ap-11},
+                {0x1.0624dd2f1a9c6p-10, 0x1.0624d77516cabp-10},
+                {0x1.0624dd2f1a9f8p-10, 0x1.0624d77516cdep-10},
+                {0x1.fffffffffffddp-10, 0x1.ffffd55559976p-10},
+                {0x1.fffffffffffffp-10, 0x1.ffffd55559999p-10},
+                {0x1.ffffffffffffcp-9, 0x1.ffff555599993p-9},
+                {0x1.ffffffffffffep-9, 0x1.ffff555599996p-9},
+                {0x1.ffffffffffff8p-8, 0x1.fffd555999924p-8},
+                {0x1.ffffffffffffep-8, 0x1.fffd555999929p-8},
+                {0x1.47ae147ae1458p-7, 0x1.47ab48ae4593cp-7},
+                {0x1.47ae147ae1464p-7, 0x1.47ab48ae45947p-7},
+                {0x1.ffffffffffffep-7, 0x1.fff5559997df6p-7},
+                {0x1.fffffffffffffp-7, 0x1.fff5559997df8p-7},
+                {0x1.ffffffffffff9p-6, 0x1.ffd559992b1d8p-6},
+                {0x1.ffffffffffffep-6, 0x1.ffd559992b1dcp-6},
+                {0x1.ffffffffffff9p-5, 0x1.ff55997e030d1p-5},
+                {0x1.fffffffffffffp-5, 0x1.ff55997e030d6p-5},
+                {0x1.9999999999996p-4, 0x1.983d7795f4137p-4},
+                {0x1.9999999999997p-4, 0x1.983d7795f4137p-4},
+                {0x1.fffffffffffffp-4, 0x1.fd5992bc4b834p-4},
+                {0x1.0p-3, 0x1.fd5992bc4b834p-4},
+                {0x1.fffffffffffffp-3, 0x1.f597ea69a1c86p-3},
+                {0x1.ffffffffffffcp-2, 0x1.d9353d7568aefp-2},
+                {0x1.ffffffffffffep-2, 0x1.d9353d7568af3p-2},
+                {0x1.ffffffffffffbp-1, 0x1.85efab514f393p-1},
+                {0x1.ffffffffffffep-1, 0x1.85efab514f393p-1},
+                {0x1.fffffffffffd3p0, 0x1.ed9505e1bc3cep-1},
+                {0x1.fffffffffffe1p0, 0x1.ed9505e1bc3cfp-1},
+                {0x1.ffffffffffed8p1, 0x1.ffa81708a0b4p-1},
+                {0x1.fffffffffff92p1, 0x1.ffa81708a0b41p-1},
+        };
+
+        for (double[] testCase : testCases) {
+            testTanhCase(testCase[0], testCase[1]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/HypotTests.java b/ojluni/src/test/java/lang/StrictMath/HypotTests.java
new file mode 100644
index 0000000..d49e267
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/HypotTests.java
@@ -0,0 +1,764 @@
+/*
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4851638
+ * @key randomness
+ * @summary Tests for StrictMath.hypot
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @build Tests
+ * @build FdlibmTranslit
+ * @build HypotTests
+ * @run main HypotTests
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.StrictMath;
+
+import java.util.Random;
+import org.testng.annotations.Test;
+
+/**
+ * The tests in ../Math/HypotTests.java test properties that should hold for any hypot
+ * implementation, including the FDLIBM-based one required for StrictMath.hypot.  Therefore, the
+ * test cases in ../Math/HypotTests.java are run against both the Math and StrictMath versions of
+ * hypot.  The role of this test is to verify that the FDLIBM hypot algorithm is being used by
+ * running golden file tests on values that may vary from one conforming hypot implementation to
+ * another.
+ */
+
+public class HypotTests {
+
+    private HypotTests() {
+    }
+
+    /**
+     * The hypot implementation is commutative, {@code hypot(a, b) == hypot(b, a)}, and independent
+     * of sign, {@code hypot(a, b) == hypot(-a, b) == hypot(a, -b) == hypot(-a, -b)}.
+     */
+    static void testHypotCase(double input1, double input2, double expected) {
+        Tests.test("StrictMath.hypot(double)", input1, input2,
+                StrictMath.hypot(input1, input2), expected);
+
+        Tests.test("StrictMath.hypot(double)", input2, input1,
+                StrictMath.hypot(input2, input1), expected);
+
+        Tests.test("StrictMath.hypot(double)", -input1, input2,
+                StrictMath.hypot(-input1, input2), expected);
+
+        Tests.test("StrictMath.hypot(double)", input2, -input1,
+                StrictMath.hypot(input2, -input1), expected);
+
+        Tests.test("StrictMath.hypot(double)", input1, -input2,
+                StrictMath.hypot(input1, -input2), expected);
+
+        Tests.test("StrictMath.hypot(double)", -input2, input1,
+                StrictMath.hypot(-input2, input1), expected);
+
+        Tests.test("StrictMath.hypot(double)", -input1, -input2,
+                StrictMath.hypot(-input1, -input2), expected);
+
+        Tests.test("StrictMath.hypot(double)", -input2, -input1,
+                StrictMath.hypot(-input2, -input1), expected);
+    }
+
+    @Test
+    public void testHypot() {
+        double[][] testCases = {
+                {0x1.0p0, 0x1.ffffffffffab5p-1, 0x1.6a09e667f39edp0},
+                {0x1.0p0, 0x1.ffffffffffffbp0, 0x1.1e3779b97f4a6p1},
+                {0x1.0p0, 0x1.7ffffffffffffp1, 0x1.94c583ada5b51p1},
+                {0x1.0p0, 0x1.ffffffffffffdp1, 0x1.07e0f66afed06p2},
+                {0x1.0p0, 0x1.3fffffffffffdp2, 0x1.465655f122ff3p2},
+                {0x1.0p0, 0x1.4p2, 0x1.465655f122ff6p2},
+                {0x1.0p0, 0x1.7ffffffffffffp2, 0x1.854bfb363dc38p2},
+                {0x1.0p0, 0x1.8p2, 0x1.854bfb363dc39p2},
+                {0x1.0p0, 0x1.bfffffffffffep2, 0x1.c48c6001f0abdp2},
+                {0x1.0p0, 0x1.fffffffffffffp2, 0x1.01fe03f61badp3},
+                {0x1.0p0, 0x1.1fffffffffffap3, 0x1.21c5b70d9f81dp3},
+                {0x1.0p0, 0x1.3ffffffffffe5p3, 0x1.419894c2329d5p3},
+                {0x1.0p0, 0x1.3ffffffffffe7p3, 0x1.419894c2329d8p3},
+                {0x1.0p0, 0x1.5ffffffffff7ep3, 0x1.617398f2aa9c6p3},
+                {0x1.0p0, 0x1.5ffffffffff8dp3, 0x1.617398f2aa9d5p3},
+                {0x1.0p0, 0x1.7ffffffffff9bp3, 0x1.8154be27734c1p3},
+                {0x1.0p0, 0x1.8p3, 0x1.8154be2773526p3},
+                {0x1.0p0, 0x1.9fffffffffff4p3, 0x1.a13a9cb996644p3},
+                {0x1.0p0, 0x1.9ffffffffffffp3, 0x1.a13a9cb99664fp3},
+                {0x1.0p0, 0x1.bfffffffffffep3, 0x1.c12432fec0327p3},
+                {0x1.0p0, 0x1.cp3, 0x1.c12432fec0329p3},
+                {0x1.0p0, 0x1.dffffffffffbcp3, 0x1.e110c39105f6bp3},
+                {0x1.0p0, 0x1.ep3, 0x1.e110c39105fafp3},
+                {0x1.0p0, 0x1.ffffffffffeafp3, 0x1.007fe00ff5fc8p4},
+                {0x1.0p0, 0x1.0fffffffffff4p4, 0x1.10785dd689a1cp4},
+                {0x1.0p0, 0x1.0fffffffffffbp4, 0x1.10785dd689a23p4},
+                {0x1.0p0, 0x1.1ffffffffff92p4, 0x1.2071b0abcd7cap4},
+                {0x1.0p0, 0x1.1ffffffffff99p4, 0x1.2071b0abcd7d1p4},
+                {0x1.0p0, 0x1.2fffffffffffcp4, 0x1.306bb705ae7bfp4},
+                {0x1.0p0, 0x1.2ffffffffffffp4, 0x1.306bb705ae7c3p4},
+                {0x1.0p0, 0x1.3fffffffffffdp4, 0x1.4066560954a8bp4},
+                {0x1.0p0, 0x1.4fffffffffe14p4, 0x1.506177f548fcfp4},
+                {0x1.0p0, 0x1.5p4, 0x1.506177f5491bbp4},
+                {0x1.0p0, 0x1.5fffffffffffdp4, 0x1.605d0af9d3a42p4},
+                {0x1.0p0, 0x1.5fffffffffffep4, 0x1.605d0af9d3a42p4},
+                {0x1.0p0, 0x1.6fffffffffff8p4, 0x1.7059005e2c015p4},
+                {0x1.0p0, 0x1.6ffffffffffffp4, 0x1.7059005e2c01dp4},
+                {0x1.0p0, 0x1.7fffffffffffdp4, 0x1.80554bdc2dc4dp4},
+                {0x1.0p0, 0x1.7ffffffffffffp4, 0x1.80554bdc2dc4ep4},
+                {0x1.0p0, 0x1.8fffffffffe68p4, 0x1.9051e3235a2cp4},
+                {0x1.0p0, 0x1.9p4, 0x1.9051e3235a458p4},
+                {0x1.0p0, 0x1.9fffffffffff4p4, 0x1.a04ebd789d00cp4},
+                {0x1.0p0, 0x1.ap4, 0x1.a04ebd789d019p4},
+                {0x1.0p0, 0x1.afffffffffed8p4, 0x1.b04bd36b639fbp4},
+                {0x1.0p0, 0x1.affffffffff43p4, 0x1.b04bd36b63a66p4},
+                {0x1.0p0, 0x1.bfffffffffe3ep4, 0x1.c0491e9ab90fdp4},
+                {0x1.0p0, 0x1.cp4, 0x1.c0491e9ab92bfp4},
+                {0x1.0p0, 0x1.cfffffffffed8p4, 0x1.d0469986884d6p4},
+                {0x1.0p0, 0x1.cfffffffffee8p4, 0x1.d0469986884e5p4},
+                {0x1.0p0, 0x1.dfffffffffe5cp4, 0x1.e0443f6a33104p4},
+                {0x1.0p0, 0x1.dffffffffffffp4, 0x1.e0443f6a332a7p4},
+                {0x1.0p0, 0x1.efffffffffff8p4, 0x1.f0420c1e63084p4},
+                {0x1.0p0, 0x1.fp4, 0x1.f0420c1e6308dp4},
+                {0x1.0p0, 0x1.ffffffffffffdp4, 0x1.001ffe003ff5fp5},
+                {0x1.0p0, 0x1.07ffffffffed8p5, 0x1.081f05ef4d755p5},
+                {0x1.0p0, 0x1.07ffffffffee8p5, 0x1.081f05ef4d764p5},
+                {0x1.0p0, 0x1.0fffffffffff4p5, 0x1.101e1c7371c6bp5},
+                {0x1.0p0, 0x1.0fffffffffffbp5, 0x1.101e1c7371c72p5},
+                {0x1.0p0, 0x1.17ffffffffff8p5, 0x1.181d404cf7f51p5},
+                {0x1.0p0, 0x1.17ffffffffffdp5, 0x1.181d404cf7f56p5},
+                {0x1.0p0, 0x1.1fffffffffbf2p5, 0x1.201c705fa7a27p5},
+                {0x1.0p0, 0x1.1fffffffffc65p5, 0x1.201c705fa7a9ap5},
+                {0x1.0p0, 0x1.27ffffffffe08p5, 0x1.281babadfba01p5},
+                {0x1.0p0, 0x1.28p5, 0x1.281babadfbbf9p5},
+                {0x1.0p0, 0x1.2ffffffffff64p5, 0x1.301af15517357p5},
+                {0x1.0p0, 0x1.2ffffffffff6cp5, 0x1.301af1551735ep5},
+                {0x1.0p0, 0x1.37ffffffffc78p5, 0x1.381a40895d3f5p5},
+                {0x1.0p0, 0x1.37ffffffffc88p5, 0x1.381a40895d406p5},
+                {0x1.0p0, 0x1.3fffffffffffdp5, 0x1.4019989389b2dp5},
+                {0x1.0p0, 0x1.4p5, 0x1.4019989389b3p5},
+                {0x1.0p0, 0x1.47fffffffffe8p5, 0x1.4818f8ce34e19p5},
+                {0x1.0p0, 0x1.47ffffffffffap5, 0x1.4818f8ce34e2cp5},
+                {0x1.0p0, 0x1.4fffffffffa64p5, 0x1.501860a3b54bep5},
+                {0x1.0p0, 0x1.4fffffffffe47p5, 0x1.501860a3b58a1p5},
+                {0x1.0p0, 0x1.57ffffffffff8p5, 0x1.5817cf8c4c199p5},
+                {0x1.0p0, 0x1.57fffffffffffp5, 0x1.5817cf8c4c1ap5},
+                {0x1.0p0, 0x1.5fffffffffbeep5, 0x1.6017450c8d3e7p5},
+                {0x1.0p0, 0x1.6p5, 0x1.6017450c8d7f9p5},
+                {0x1.0p0, 0x1.67fffffffffe8p5, 0x1.6816c0b405afp5},
+                {0x1.0p0, 0x1.68p5, 0x1.6816c0b405b09p5},
+                {0x1.0p0, 0x1.6fffffffffb78p5, 0x1.7016421c06043p5},
+                {0x1.0p0, 0x1.7p5, 0x1.7016421c064cbp5},
+                {0x1.0p0, 0x1.77ffffffffffp5, 0x1.7815c8e69cc37p5},
+                {0x1.0p0, 0x1.77ffffffffffcp5, 0x1.7815c8e69cc43p5},
+                {0x1.0p0, 0x1.7ffffffffffffp5, 0x1.801554bda99c5p5},
+                {0x1.0p0, 0x1.87fffffffffdp5, 0x1.8814e55214271p5},
+                {0x1.0p0, 0x1.87ffffffffffcp5, 0x1.8814e5521429ep5},
+                {0x1.0p0, 0x1.8ffffffffffe8p5, 0x1.90147a5b16ce5p5},
+                {0x1.0p0, 0x1.8fffffffffffcp5, 0x1.90147a5b16cfap5},
+                {0x1.0p0, 0x1.97ffffffffffp5, 0x1.98141395a0592p5},
+                {0x1.0p0, 0x1.97fffffffffffp5, 0x1.98141395a05a1p5},
+                {0x1.0p0, 0x1.9fffffffff8f4p5, 0x1.a013b0c3c7377p5},
+                {0x1.0p0, 0x1.9fffffffffb18p5, 0x1.a013b0c3c759bp5},
+                {0x1.0p0, 0x1.a7fffffffffdp5, 0x1.a81351ac4f317p5},
+                {0x1.0p0, 0x1.a7ffffffffffp5, 0x1.a81351ac4f338p5},
+                {0x1.0p0, 0x1.afffffffff698p5, 0x1.b012f61a35d98p5},
+                {0x1.0p0, 0x1.bp5, 0x1.b012f61a367p5},
+                {0x1.0p0, 0x1.b7ffffffff85p5, 0x1.b8129ddc56b26p5},
+                {0x1.0p0, 0x1.b7ffffffff87p5, 0x1.b8129ddc56b45p5},
+                {0x1.0p0, 0x1.bfffffffffffdp5, 0x1.c01248c50d99cp5},
+                {0x1.0p0, 0x1.bfffffffffffep5, 0x1.c01248c50d99cp5},
+                {0x1.0p0, 0x1.c7ffffffffedp5, 0x1.c811f6a9e9676p5},
+                {0x1.0p0, 0x1.c8p5, 0x1.c811f6a9e97a6p5},
+                {0x1.0p0, 0x1.cffffffffffe8p5, 0x1.d011a7636789ep5},
+                {0x1.0p0, 0x1.d7ffffffffffp5, 0x1.d8115accb20f3p5},
+                {0x1.0p0, 0x1.d8p5, 0x1.d8115accb2103p5},
+                {0x1.0p0, 0x1.dfffffffffebcp5, 0x1.e01110c367a41p5},
+                {0x1.0p0, 0x1.ep5, 0x1.e01110c367b85p5},
+                {0x1.0p0, 0x1.e7fffffffffdp5, 0x1.e810c927681fap5},
+                {0x1.0p0, 0x1.e8p5, 0x1.e810c9276822ap5},
+                {0x1.0p0, 0x1.efffffffff7f8p5, 0x1.f01083daa4dadp5},
+                {0x1.0p0, 0x1.fp5, 0x1.f01083daa55b5p5},
+                {0x1.0p0, 0x1.f7ffffffffffp5, 0x1.f81040c0f9c6p5},
+                {0x1.0p0, 0x1.f8p5, 0x1.f81040c0f9c71p5},
+                {0x1.0p0, 0x1.fffffffffffffp5, 0x1.0007ffe000fffp6},
+                {0x1.0p0, 0x1.03fffffffffdp6, 0x1.0407e05f7d188p6},
+                {0x1.0p0, 0x1.03ffffffffffbp6, 0x1.0407e05f7d1b4p6},
+                {0x1.0p0, 0x1.07ffffffff7f8p6, 0x1.0807c1d34edd5p6},
+                {0x1.0p0, 0x1.07ffffffff808p6, 0x1.0807c1d34ede4p6},
+                {0x1.0p0, 0x1.0bffffffff65p6, 0x1.0c07a430870e5p6},
+                {0x1.0p0, 0x1.0bffffffff67p6, 0x1.0c07a43087104p6},
+                {0x1.0p0, 0x1.0fffffffffc54p6, 0x1.1007876cda509p6},
+                {0x1.0p0, 0x1.0fffffffffe0dp6, 0x1.1007876cda6c2p6},
+                {0x1.0p0, 0x1.13fffffffffdp6, 0x1.14076b7e954b4p6},
+                {0x1.0p0, 0x1.13ffffffffffep6, 0x1.14076b7e954e3p6},
+                {0x1.0p0, 0x1.17ffffffffff8p6, 0x1.1807505c9310dp6},
+                {0x1.0p0, 0x1.18p6, 0x1.1807505c93116p6},
+                {0x1.0p0, 0x1.1bfffffffecbp6, 0x1.1c0735fe3197ap6},
+                {0x1.0p0, 0x1.1bffffffff1dbp6, 0x1.1c0735fe31ea5p6},
+                {0x1.0p0, 0x1.1ffffffffebcap6, 0x1.20071c5b4ce64p6},
+                {0x1.0p0, 0x1.1fffffffffaf1p6, 0x1.20071c5b4dd8bp6},
+                {0x1.0p0, 0x1.23ffffffff83p6, 0x1.2407036c309fdp6},
+                {0x1.0p0, 0x1.23ffffffff85p6, 0x1.2407036c30a1cp6},
+                {0x1.0p0, 0x1.27ffffffffba8p6, 0x1.2806eb2991e76p6},
+                {0x1.0p0, 0x1.28p6, 0x1.2806eb29922cep6},
+                {0x1.0p0, 0x1.2bfffffffff7p6, 0x1.2c06d38c8b4ffp6},
+                {0x1.0p0, 0x1.2bfffffffff9p6, 0x1.2c06d38c8b52p6},
+                {0x1.0p0, 0x1.2fffffffffff4p6, 0x1.3006bc8e938c8p6},
+                {0x1.0p0, 0x1.2fffffffffffcp6, 0x1.3006bc8e938cfp6},
+                {0x1.0p0, 0x1.33ffffffff87p6, 0x1.3406a6297821ep6},
+                {0x1.0p0, 0x1.33ffffffff89p6, 0x1.3406a6297823dp6},
+                {0x1.0p0, 0x1.37ffffffff9d8p6, 0x1.380690575943dp6},
+                {0x1.0p0, 0x1.37ffffffff9eap6, 0x1.380690575944fp6},
+                {0x1.0p0, 0x1.3bffffffffffp6, 0x1.3c067b12a2013p6},
+                {0x1.0p0, 0x1.3cp6, 0x1.3c067b12a2024p6},
+                {0x1.0p0, 0x1.3fffffffffe19p6, 0x1.40066656044ep6},
+                {0x1.0p0, 0x1.4p6, 0x1.40066656046c7p6},
+                {0x1.0p0, 0x1.43ffffffff1dp6, 0x1.4406521c75c3p6},
+                {0x1.0p0, 0x1.43ffffffffccfp6, 0x1.4406521c7672fp6},
+                {0x1.0p0, 0x1.47ffffffff8a8p6, 0x1.48063e612ce7ap6},
+                {0x1.0p0, 0x1.47ffffffffcb9p6, 0x1.48063e612d28bp6},
+                {0x1.0p0, 0x1.4bfffffffe1fp6, 0x1.4c062b1f96823p6},
+                {0x1.0p0, 0x1.4cp6, 0x1.4c062b1f98633p6},
+                {0x1.0p0, 0x1.4ffffffffde04p6, 0x1.500618535d07dp6},
+                {0x1.0p0, 0x1.5p6, 0x1.500618535f279p6},
+                {0x1.0p0, 0x1.53fffffffef1p6, 0x1.540605f85c637p6},
+                {0x1.0p0, 0x1.53ffffffffdf3p6, 0x1.540605f85d51ap6},
+                {0x1.0p0, 0x1.57ffffffffff8p6, 0x1.5805f40aa0595p6},
+                {0x1.0p0, 0x1.5bffffffffffp6, 0x1.5c05e286636b5p6},
+                {0x1.0p0, 0x1.5bfffffffffffp6, 0x1.5c05e286636c4p6},
+                {0x1.0p0, 0x1.5ffffffffd9cep6, 0x1.6005d1680baa2p6},
+                {0x1.0p0, 0x1.5fffffffff873p6, 0x1.6005d1680d947p6},
+                {0x1.0p0, 0x1.63ffffffffa5p6, 0x1.6405c0ac30a35p6},
+                {0x1.0p0, 0x1.63ffffffffa7p6, 0x1.6405c0ac30a56p6},
+                {0x1.0p0, 0x1.67ffffffff988p6, 0x1.6805b04f83ac3p6},
+                {0x1.0p0, 0x1.68p6, 0x1.6805b04f8413bp6},
+                {0x1.0p0, 0x1.6bfffffffffep6, 0x1.6c05a04ee40c3p6},
+                {0x1.0p0, 0x1.6cp6, 0x1.6c05a04ee40e3p6},
+                {0x1.0p0, 0x1.6fffffffff018p6, 0x1.700590a74f9b5p6},
+                {0x1.0p0, 0x1.6fffffffffbe2p6, 0x1.700590a75057fp6},
+                {0x1.0p0, 0x1.73ffffffff4ap6, 0x1.74058155e9b72p6},
+                {0x1.0p0, 0x1.74p6, 0x1.74058155ea6d2p6},
+                {0x1.0p0, 0x1.77ffffffffffp6, 0x1.78057257f1868p6},
+                {0x1.0p0, 0x1.78p6, 0x1.78057257f1878p6},
+                {0x1.0p0, 0x1.7bfffffffffep6, 0x1.7c0563aac389bp6},
+                {0x1.0p0, 0x1.7bfffffffffe4p6, 0x1.7c0563aac389fp6},
+                {0x1.0p0, 0x1.7ffffffffffffp6, 0x1.8005554bda349p6},
+                {0x1.0p0, 0x1.8p6, 0x1.8005554bda34bp6},
+                {0x1.0p0, 0x1.83fffffffffap6, 0x1.84054738c9dcdp6},
+                {0x1.0p0, 0x1.84p6, 0x1.84054738c9e2dp6},
+                {0x1.0p0, 0x1.87ffffffff09p6, 0x1.8805396f3f494p6},
+                {0x1.0p0, 0x1.87ffffffff0bp6, 0x1.8805396f3f4b5p6},
+                {0x1.0p0, 0x1.8bfffffffffep6, 0x1.8c052bed02f7ap6},
+                {0x1.0p0, 0x1.8cp6, 0x1.8c052bed02f9bp6},
+                {0x1.0p0, 0x1.8fffffffff7c8p6, 0x1.90051eafee07bp6},
+                {0x1.0p0, 0x1.9p6, 0x1.90051eafee8b3p6},
+                {0x1.0p1, 0x1.fffffffffdcb5p-1, 0x1.1e3779b97f0b5p1},
+                {0x1.0p1, 0x1.ffffffffffab5p0, 0x1.6a09e667f39edp1},
+                {0x1.0p1, 0x1.7ffffffffffffp1, 0x1.cd82b446159f2p1},
+                {0x1.0p1, 0x1.8p1, 0x1.cd82b446159f3p1},
+                {0x1.0p1, 0x1.ffffffffffffbp1, 0x1.1e3779b97f4a6p2},
+                {0x1.0p1, 0x1.3fffffffffffdp2, 0x1.58a68a4a8d9fp2},
+                {0x1.0p1, 0x1.3fffffffffffep2, 0x1.58a68a4a8d9f1p2},
+                {0x1.0p1, 0x1.7ffffffffffffp2, 0x1.94c583ada5b51p2},
+                {0x1.0p1, 0x1.bfffffffffffep2, 0x1.d1ed52076fbe7p2},
+                {0x1.0p1, 0x1.cp2, 0x1.d1ed52076fbe9p2},
+                {0x1.0p1, 0x1.ffffffffffffdp2, 0x1.07e0f66afed06p3},
+                {0x1.0p1, 0x1.1fffffffffff2p3, 0x1.2706821902e8cp3},
+                {0x1.0p1, 0x1.2p3, 0x1.2706821902e9ap3},
+                {0x1.0p1, 0x1.3fffffffffffdp3, 0x1.465655f122ff3p3},
+                {0x1.0p1, 0x1.4p3, 0x1.465655f122ff6p3},
+                {0x1.0p1, 0x1.5ffffffffffd6p3, 0x1.65c55827df1a8p3},
+                {0x1.0p1, 0x1.7ffffffffffffp3, 0x1.854bfb363dc38p3},
+                {0x1.0p1, 0x1.8p3, 0x1.854bfb363dc39p3},
+                {0x1.0p1, 0x1.9ffffffffffe4p3, 0x1.a4e4efeda34c2p3},
+                {0x1.0p1, 0x1.ap3, 0x1.a4e4efeda34dep3},
+                {0x1.0p1, 0x1.bfffffffffffep3, 0x1.c48c6001f0abdp3},
+                {0x1.0p1, 0x1.dfffffffffffcp3, 0x1.e43f746f77956p3},
+                {0x1.0p1, 0x1.ep3, 0x1.e43f746f7795bp3},
+                {0x1.0p1, 0x1.fffffffffffffp3, 0x1.01fe03f61badp4},
+                {0x1.0p1, 0x1.0ffffffffffc4p4, 0x1.11e039f40ee2ap4},
+                {0x1.0p1, 0x1.0ffffffffffc7p4, 0x1.11e039f40ee2dp4},
+                {0x1.0p1, 0x1.1fffffffffffap4, 0x1.21c5b70d9f81dp4},
+                {0x1.0p1, 0x1.2fffffffffffcp4, 0x1.31adf859f9e5ap4},
+                {0x1.0p1, 0x1.2fffffffffffep4, 0x1.31adf859f9e5cp4},
+                {0x1.0p1, 0x1.3ffffffffffe5p4, 0x1.419894c2329d5p4},
+                {0x1.0p1, 0x1.3ffffffffffe7p4, 0x1.419894c2329d8p4},
+                {0x1.0p1, 0x1.4fffffffffff4p4, 0x1.518536f3ca668p4},
+                {0x1.0p1, 0x1.5p4, 0x1.518536f3ca675p4},
+                {0x1.0p1, 0x1.5ffffffffff7ep4, 0x1.617398f2aa9c6p4},
+                {0x1.0p1, 0x1.5ffffffffff8dp4, 0x1.617398f2aa9d5p4},
+                {0x1.0p1, 0x1.6ffffffffffb8p4, 0x1.716380ce70352p4},
+                {0x1.0p1, 0x1.7p4, 0x1.716380ce7039ap4},
+                {0x1.0p1, 0x1.7ffffffffff9bp4, 0x1.8154be27734c1p4},
+                {0x1.0p1, 0x1.8p4, 0x1.8154be2773526p4},
+                {0x1.0p1, 0x1.8ffffffffffe8p4, 0x1.9147284a4142fp4},
+                {0x1.0p1, 0x1.8ffffffffffffp4, 0x1.9147284a41446p4},
+                {0x1.0p1, 0x1.9fffffffffff4p4, 0x1.a13a9cb996644p4},
+                {0x1.0p1, 0x1.9ffffffffffffp4, 0x1.a13a9cb99664fp4},
+                {0x1.0p1, 0x1.affffffffff58p4, 0x1.b12efe0a8f113p4},
+                {0x1.0p1, 0x1.affffffffffd2p4, 0x1.b12efe0a8f18dp4},
+                {0x1.0p1, 0x1.bfffffffffffep4, 0x1.c12432fec0327p4},
+                {0x1.0p1, 0x1.cp4, 0x1.c12432fec0329p4},
+                {0x1.0p1, 0x1.cffffffffffe8p4, 0x1.d11a25cd6ed78p4},
+                {0x1.0p1, 0x1.dp4, 0x1.d11a25cd6ed91p4},
+                {0x1.0p1, 0x1.dffffffffffbcp4, 0x1.e110c39105f6bp4},
+                {0x1.0p1, 0x1.ep4, 0x1.e110c39105fafp4},
+                {0x1.0p1, 0x1.effffffffffe8p4, 0x1.f107fbd0adcf1p4},
+                {0x1.0p1, 0x1.efffffffffff8p4, 0x1.f107fbd0addp4},
+                {0x1.0p1, 0x1.ffffffffffeafp4, 0x1.007fe00ff5fc8p5},
+                {0x1.0p1, 0x1.07fffffffffe8p5, 0x1.087c01e7d5092p5},
+                {0x1.0p1, 0x1.08p5, 0x1.087c01e7d50abp5},
+                {0x1.0p1, 0x1.0fffffffffff4p5, 0x1.10785dd689a1cp5},
+                {0x1.0p1, 0x1.0fffffffffffbp5, 0x1.10785dd689a23p5},
+                {0x1.0p1, 0x1.17ffffffffed8p5, 0x1.1874eee5c5cb1p5},
+                {0x1.0p1, 0x1.17ffffffffee8p5, 0x1.1874eee5c5cc2p5},
+                {0x1.0p1, 0x1.1ffffffffff92p5, 0x1.2071b0abcd7cap5},
+                {0x1.0p1, 0x1.1ffffffffff99p5, 0x1.2071b0abcd7d1p5},
+                {0x1.0p1, 0x1.27ffffffffea8p5, 0x1.286e9f388de9fp5},
+                {0x1.0p1, 0x1.28p5, 0x1.286e9f388dff7p5},
+                {0x1.0p1, 0x1.2fffffffffffcp5, 0x1.306bb705ae7bfp5},
+                {0x1.0p1, 0x1.2ffffffffffffp5, 0x1.306bb705ae7c3p5},
+                {0x1.0p1, 0x1.37ffffffffff8p5, 0x1.3868f4e9108b9p5},
+                {0x1.0p1, 0x1.38p5, 0x1.3868f4e9108c1p5},
+                {0x1.0p1, 0x1.3fffffffffffdp5, 0x1.4066560954a8bp5},
+                {0x1.0p1, 0x1.47ffffffffe28p5, 0x1.4863d7d40ad39p5},
+                {0x1.0p1, 0x1.48p5, 0x1.4863d7d40af11p5},
+                {0x1.0p1, 0x1.4fffffffffe14p5, 0x1.506177f548fcfp5},
+                {0x1.0p1, 0x1.5p5, 0x1.506177f5491bbp5},
+                {0x1.0p1, 0x1.57ffffffffeb8p5, 0x1.585f34506bafbp5},
+                {0x1.0p1, 0x1.58p5, 0x1.585f34506bc43p5},
+                {0x1.0p1, 0x1.5fffffffffffdp5, 0x1.605d0af9d3a42p5},
+                {0x1.0p1, 0x1.5fffffffffffep5, 0x1.605d0af9d3a42p5},
+                {0x1.0p1, 0x1.67ffffffffda8p5, 0x1.685afa317791bp5},
+                {0x1.0p1, 0x1.68p5, 0x1.685afa3177b73p5},
+                {0x1.0p1, 0x1.6fffffffffff8p5, 0x1.7059005e2c015p5},
+                {0x1.0p1, 0x1.6ffffffffffffp5, 0x1.7059005e2c01dp5},
+                {0x1.0p1, 0x1.77ffffffffffp5, 0x1.78571c0982328p5},
+                {0x1.0p1, 0x1.78p5, 0x1.78571c0982339p5},
+                {0x1.0p1, 0x1.7fffffffffffdp5, 0x1.80554bdc2dc4dp5},
+                {0x1.0p1, 0x1.7ffffffffffffp5, 0x1.80554bdc2dc4ep5},
+                {0x1.0p1, 0x1.87fffffffffdp5, 0x1.88538e9ad8dacp5},
+                {0x1.0p1, 0x1.87fffffffffffp5, 0x1.88538e9ad8ddbp5},
+                {0x1.0p1, 0x1.8fffffffffe68p5, 0x1.9051e3235a2cp5},
+                {0x1.0p1, 0x1.9p5, 0x1.9051e3235a458p5},
+                {0x1.0p1, 0x1.97ffffffffffp5, 0x1.9850486a3f17p5},
+                {0x1.0p1, 0x1.97fffffffffffp5, 0x1.9850486a3f17fp5},
+                {0x1.0p1, 0x1.9fffffffffff4p5, 0x1.a04ebd789d00cp5},
+                {0x1.0p1, 0x1.ap5, 0x1.a04ebd789d019p5},
+                {0x1.0p1, 0x1.a7ffffffffe1p5, 0x1.a84d416a2354dp5},
+                {0x1.0p1, 0x1.a8p5, 0x1.a84d416a2373dp5},
+                {0x1.0p1, 0x1.afffffffffed8p5, 0x1.b04bd36b639fbp5},
+                {0x1.0p1, 0x1.affffffffff43p5, 0x1.b04bd36b63a66p5},
+                {0x1.0p1, 0x1.b7ffffffffd7p5, 0x1.b84a72b848951p5},
+                {0x1.0p1, 0x1.b7ffffffffe2bp5, 0x1.b84a72b848a0cp5},
+                {0x1.0p1, 0x1.bfffffffffe3ep5, 0x1.c0491e9ab90fdp5},
+                {0x1.0p1, 0x1.cp5, 0x1.c0491e9ab92bfp5},
+                {0x1.0p1, 0x1.c7fffffffffdp5, 0x1.c847d6695dbc5p5},
+                {0x1.0p1, 0x1.c8p5, 0x1.c847d6695dbf6p5},
+                {0x1.0p1, 0x1.cfffffffffed8p5, 0x1.d0469986884d6p5},
+                {0x1.0p1, 0x1.cfffffffffee8p5, 0x1.d0469986884e5p5},
+                {0x1.0p1, 0x1.d7ffffffffdfp5, 0x1.d845675f37721p5},
+                {0x1.0p1, 0x1.d8p5, 0x1.d845675f37931p5},
+                {0x1.0p1, 0x1.dfffffffffe5cp5, 0x1.e0443f6a33104p5},
+                {0x1.0p1, 0x1.dffffffffffffp5, 0x1.e0443f6a332a7p5},
+                {0x1.0p1, 0x1.e7fffffffff05p5, 0x1.e84321273f31ep5},
+                {0x1.0p1, 0x1.e7fffffffff1p5, 0x1.e84321273f328p5},
+                {0x1.0p1, 0x1.efffffffffff8p5, 0x1.f0420c1e63084p5},
+                {0x1.0p1, 0x1.fp5, 0x1.f0420c1e6308dp5},
+                {0x1.0p1, 0x1.f7ffffffffc3p5, 0x1.f840ffdf40effp5},
+                {0x1.0p1, 0x1.f7fffffffff08p5, 0x1.f840ffdf411d7p5},
+                {0x1.0p1, 0x1.ffffffffffffdp5, 0x1.001ffe003ff5fp6},
+                {0x1.0p1, 0x1.03fffffffffdp6, 0x1.041f800f9f928p6},
+                {0x1.0p1, 0x1.03ffffffffffap6, 0x1.041f800f9f953p6},
+                {0x1.0p1, 0x1.07ffffffffed8p6, 0x1.081f05ef4d755p6},
+                {0x1.0p1, 0x1.07ffffffffee8p6, 0x1.081f05ef4d764p6},
+                {0x1.0p1, 0x1.0bfffffffff5p6, 0x1.0c1e8f739cdcap6},
+                {0x1.0p1, 0x1.0bfffffffff7p6, 0x1.0c1e8f739cde9p6},
+                {0x1.0p1, 0x1.0fffffffffff4p6, 0x1.101e1c7371c6bp6},
+                {0x1.0p1, 0x1.0fffffffffffbp6, 0x1.101e1c7371c72p6},
+                {0x1.0p1, 0x1.13fffffffffdp6, 0x1.141dacc811a34p6},
+                {0x1.0p1, 0x1.13ffffffffffcp6, 0x1.141dacc811a6p6},
+                {0x1.0p1, 0x1.17ffffffffff8p6, 0x1.181d404cf7f51p6},
+                {0x1.0p1, 0x1.17ffffffffffdp6, 0x1.181d404cf7f56p6},
+                {0x1.0p1, 0x1.1bffffffffffp6, 0x1.1c1cd6dfae4a5p6},
+                {0x1.0p1, 0x1.1bffffffffffep6, 0x1.1c1cd6dfae4b4p6},
+                {0x1.0p1, 0x1.1fffffffffbf2p6, 0x1.201c705fa7a27p6},
+                {0x1.0p1, 0x1.1fffffffffc65p6, 0x1.201c705fa7a9ap6},
+                {0x1.0p1, 0x1.23fffffffffdp6, 0x1.241c0cae201cap6},
+                {0x1.0p1, 0x1.23ffffffffffp6, 0x1.241c0cae201ebp6},
+                {0x1.0p1, 0x1.27ffffffffe08p6, 0x1.281babadfba01p6},
+                {0x1.0p1, 0x1.28p6, 0x1.281babadfbbf9p6},
+                {0x1.0p1, 0x1.2bffffffffc1p6, 0x1.2c1b4d43ac4cfp6},
+                {0x1.0p1, 0x1.2bffffffffc3p6, 0x1.2c1b4d43ac4eep6},
+                {0x1.0p1, 0x1.2ffffffffff64p6, 0x1.301af15517357p6},
+                {0x1.0p1, 0x1.2ffffffffff6cp6, 0x1.301af1551735ep6},
+                {0x1.0p1, 0x1.33ffffffffadp6, 0x1.341a97c97b22ep6},
+                {0x1.0p1, 0x1.33ffffffffafp6, 0x1.341a97c97b24fp6},
+                {0x1.0p1, 0x1.37ffffffffc78p6, 0x1.381a40895d3f5p6},
+                {0x1.0p1, 0x1.37ffffffffc88p6, 0x1.381a40895d406p6},
+                {0x1.0p1, 0x1.3bffffffffffp6, 0x1.3c19eb7e71afcp6},
+                {0x1.0p1, 0x1.3bfffffffffffp6, 0x1.3c19eb7e71b0cp6},
+                {0x1.0p1, 0x1.3fffffffffffdp6, 0x1.4019989389b2dp6},
+                {0x1.0p1, 0x1.4p6, 0x1.4019989389b3p6},
+                {0x1.0p1, 0x1.43fffffffffdp6, 0x1.441947b4829e8p6},
+                {0x1.0p1, 0x1.43ffffffffff8p6, 0x1.441947b482a11p6},
+                {0x1.0p1, 0x1.47fffffffffe8p6, 0x1.4818f8ce34e19p6},
+                {0x1.0p1, 0x1.47ffffffffffap6, 0x1.4818f8ce34e2cp6},
+                {0x1.0p1, 0x1.4bffffffffffp6, 0x1.4c18abce6501fp6},
+                {0x1.0p1, 0x1.4bffffffffffcp6, 0x1.4c18abce6502cp6},
+                {0x1.0p1, 0x1.4fffffffffa64p6, 0x1.501860a3b54bep6},
+                {0x1.0p1, 0x1.4fffffffffe47p6, 0x1.501860a3b58a1p6},
+                {0x1.0p1, 0x1.53ffffffffd5p6, 0x1.5418173d9a501p6},
+                {0x1.0p1, 0x1.53ffffffffd7p6, 0x1.5418173d9a522p6},
+                {0x1.0p1, 0x1.57ffffffffff8p6, 0x1.5817cf8c4c199p6},
+                {0x1.0p1, 0x1.57fffffffffffp6, 0x1.5817cf8c4c1ap6},
+                {0x1.0p1, 0x1.5bffffffff83p6, 0x1.5c178980bc34bp6},
+                {0x1.0p1, 0x1.5bffffffff988p6, 0x1.5c178980bc4a3p6},
+                {0x1.0p1, 0x1.5fffffffffbeep6, 0x1.6017450c8d3e7p6},
+                {0x1.0p1, 0x1.6p6, 0x1.6017450c8d7f9p6},
+                {0x1.0p1, 0x1.63fffffffffdp6, 0x1.6417022204f99p6},
+                {0x1.0p1, 0x1.67fffffffffe8p6, 0x1.6816c0b405afp6},
+                {0x1.0p1, 0x1.68p6, 0x1.6816c0b405b09p6},
+                {0x1.0p1, 0x1.6bfffffffffep6, 0x1.6c1680b6059e8p6},
+                {0x1.0p1, 0x1.6cp6, 0x1.6c1680b605a08p6},
+                {0x1.0p1, 0x1.6fffffffffb78p6, 0x1.7016421c06043p6},
+                {0x1.0p1, 0x1.7p6, 0x1.7016421c064cbp6},
+                {0x1.0p1, 0x1.73fffffffffap6, 0x1.741604da8d2b9p6},
+                {0x1.0p1, 0x1.73ffffffffff8p6, 0x1.741604da8d311p6},
+                {0x1.0p1, 0x1.77ffffffffffp6, 0x1.7815c8e69cc37p6},
+                {0x1.0p1, 0x1.77ffffffffffcp6, 0x1.7815c8e69cc43p6},
+                {0x1.0p1, 0x1.7bfffffffffep6, 0x1.7c158e35adde4p6},
+                {0x1.0p1, 0x1.7bfffffffffe8p6, 0x1.7c158e35addecp6},
+                {0x1.0p1, 0x1.7ffffffffffffp6, 0x1.801554bda99c5p6},
+                {0x1.0p1, 0x1.83ffffffffdap6, 0x1.84151c74e35e4p6},
+                {0x1.0p1, 0x1.83ffffffffdep6, 0x1.84151c74e3625p6},
+                {0x1.0p1, 0x1.87fffffffffdp6, 0x1.8814e55214271p6},
+                {0x1.0p1, 0x1.87ffffffffffcp6, 0x1.8814e5521429ep6},
+                {0x1.0p1, 0x1.8bfffffffffep6, 0x1.8c14af4c540b6p6},
+                {0x1.0p1, 0x1.8bffffffffff6p6, 0x1.8c14af4c540cdp6},
+                {0x1.0p1, 0x1.8ffffffffffe8p6, 0x1.90147a5b16ce5p6},
+                {0x1.0p1, 0x1.8fffffffffffcp6, 0x1.90147a5b16cfap6},
+                {0x1.8p1, 0x1.ffffffffffffdp-1, 0x1.94c583ada5b53p1},
+                {0x1.8p1, 0x1.0p1, 0x1.cd82b446159f3p1},
+                {0x1.8p1, 0x1.7fffffffffff7p1, 0x1.0f876ccdf6cd6p2},
+                {0x1.8p1, 0x1.8p1, 0x1.0f876ccdf6cd9p2},
+                {0x1.8p1, 0x1.fffffffffffffp1, 0x1.4p2},
+                {0x1.8p1, 0x1.3ffffffffffe1p2, 0x1.752e50db3a387p2},
+                {0x1.8p1, 0x1.4p2, 0x1.752e50db3a3a2p2},
+                {0x1.8p1, 0x1.7ffffffffffffp2, 0x1.ad5336963eefap2},
+                {0x1.8p1, 0x1.bfffffffffffep2, 0x1.e768d399dc46dp2},
+                {0x1.8p1, 0x1.bffffffffffffp2, 0x1.e768d399dc46fp2},
+                {0x1.8p1, 0x1.fffffffffffffp2, 0x1.11687a8ae14a3p3},
+                {0x1.8p1, 0x1.1fffffffffff2p3, 0x1.2f9422c23c47p3},
+                {0x1.8p1, 0x1.1fffffffffff7p3, 0x1.2f9422c23c475p3},
+                {0x1.8p1, 0x1.3fffffffffff1p3, 0x1.4e16fdacff928p3},
+                {0x1.8p1, 0x1.3fffffffffff4p3, 0x1.4e16fdacff92bp3},
+                {0x1.8p1, 0x1.5ffffffffffffp3, 0x1.6cdb2bbb212ebp3},
+                {0x1.8p1, 0x1.7fffffffffffdp3, 0x1.8bd171a07e388p3},
+                {0x1.8p1, 0x1.7ffffffffffffp3, 0x1.8bd171a07e389p3},
+                {0x1.8p1, 0x1.9ffffffffffe4p3, 0x1.aaeee979b481cp3},
+                {0x1.8p1, 0x1.9ffffffffffecp3, 0x1.aaeee979b4825p3},
+                {0x1.8p1, 0x1.bffffffffffeep3, 0x1.ca2b9714180e5p3},
+                {0x1.8p1, 0x1.cp3, 0x1.ca2b9714180f7p3},
+                {0x1.8p1, 0x1.dfffffffffffcp3, 0x1.e98180e9b47edp3},
+                {0x1.8p1, 0x1.dfffffffffffep3, 0x1.e98180e9b47efp3},
+                {0x1.8p1, 0x1.fffffffffffffp3, 0x1.04760c95db31p4},
+                {0x1.8p1, 0x1.0fffffffffff4p4, 0x1.1433ec467efefp4},
+                {0x1.8p1, 0x1.1ffffffffffeap4, 0x1.23f8fc68ae515p4},
+                {0x1.8p1, 0x1.2p4, 0x1.23f8fc68ae52bp4},
+                {0x1.8p1, 0x1.2fffffffffffcp4, 0x1.33c42213ee0c5p4},
+                {0x1.8p1, 0x1.3p4, 0x1.33c42213ee0c9p4},
+                {0x1.8p1, 0x1.3ffffffffffd9p4, 0x1.439479381ec96p4},
+                {0x1.8p1, 0x1.3fffffffffff6p4, 0x1.439479381ecb3p4},
+                {0x1.8p1, 0x1.4ffffffffffc4p4, 0x1.53694801747d4p4},
+                {0x1.8p1, 0x1.4ffffffffffccp4, 0x1.53694801747dcp4},
+                {0x1.8p1, 0x1.5ffffffffffbep4, 0x1.6341f58bad9d2p4},
+                {0x1.8p1, 0x1.5ffffffffffc2p4, 0x1.6341f58bad9d7p4},
+                {0x1.8p1, 0x1.6fffffffffff8p4, 0x1.731e02ed21f18p4},
+                {0x1.8p1, 0x1.6ffffffffffffp4, 0x1.731e02ed21f2p4},
+                {0x1.8p1, 0x1.7fffffffffffdp4, 0x1.82fd05f129836p4},
+                {0x1.8p1, 0x1.7ffffffffffffp4, 0x1.82fd05f129837p4},
+                {0x1.8p1, 0x1.8ffffffffffa8p4, 0x1.92dea50d28578p4},
+                {0x1.8p1, 0x1.8ffffffffffffp4, 0x1.92dea50d285cep4},
+                {0x1.8p1, 0x1.9ffffffffffe4p4, 0x1.a2c2943e2866p4},
+                {0x1.8p1, 0x1.9fffffffffffcp4, 0x1.a2c2943e28678p4},
+                {0x1.8p1, 0x1.afffffffffff8p4, 0x1.b2a892946f42dp4},
+                {0x1.8p1, 0x1.afffffffffffep4, 0x1.b2a892946f434p4},
+                {0x1.8p1, 0x1.bffffffffffeep4, 0x1.c2906842b6bf3p4},
+                {0x1.8p1, 0x1.bfffffffffff2p4, 0x1.c2906842b6bf8p4},
+                {0x1.8p1, 0x1.cffffffffffe8p4, 0x1.d279e51208c72p4},
+                {0x1.8p1, 0x1.dp4, 0x1.d279e51208c8ap4},
+                {0x1.8p1, 0x1.dfffffffffff4p4, 0x1.e264df234beddp4},
+                {0x1.8p1, 0x1.dfffffffffffcp4, 0x1.e264df234bee4p4},
+                {0x1.8p1, 0x1.efffffffffff8p4, 0x1.f25131ed54d64p4},
+                {0x1.8p1, 0x1.fp4, 0x1.f25131ed54d6cp4},
+                {0x1.8p1, 0x1.fffffffffffffp4, 0x1.011f5eb54147p5},
+                {0x1.8p1, 0x1.07fffffffff88p5, 0x1.0916b2b5fff3ep5},
+                {0x1.8p1, 0x1.07fffffffffaap5, 0x1.0916b2b5fff6p5},
+                {0x1.8p1, 0x1.0ffffffffffc4p5, 0x1.110e8885865b8p5},
+                {0x1.8p1, 0x1.0ffffffffffccp5, 0x1.110e8885865c1p5},
+                {0x1.8p1, 0x1.17fffffffff58p5, 0x1.1906d51932b7ep5},
+                {0x1.8p1, 0x1.17fffffffff77p5, 0x1.1906d51932b9dp5},
+                {0x1.8p1, 0x1.1fffffffffffap5, 0x1.20ff8e9d967d6p5},
+                {0x1.8p1, 0x1.1fffffffffffep5, 0x1.20ff8e9d967dbp5},
+                {0x1.8p1, 0x1.27fffffffffc8p5, 0x1.28f8ac4cd98f2p5},
+                {0x1.8p1, 0x1.27fffffffffd8p5, 0x1.28f8ac4cd9903p5},
+                {0x1.8p1, 0x1.2ffffffffff7cp5, 0x1.30f2264b9c502p5},
+                {0x1.8p1, 0x1.2ffffffffffafp5, 0x1.30f2264b9c535p5},
+                {0x1.8p1, 0x1.37ffffffffff8p5, 0x1.38ebf58b30cb4p5},
+                {0x1.8p1, 0x1.37fffffffffffp5, 0x1.38ebf58b30cbcp5},
+                {0x1.8p1, 0x1.3fffffffffffdp5, 0x1.40e613b03f1dcp5},
+                {0x1.8p1, 0x1.3ffffffffffffp5, 0x1.40e613b03f1dfp5},
+                {0x1.8p1, 0x1.47fffffffffa1p5, 0x1.48e07afd169d5p5},
+                {0x1.8p1, 0x1.47fffffffffa8p5, 0x1.48e07afd169dbp5},
+                {0x1.8p1, 0x1.4ffffffffff84p5, 0x1.50db263f101e3p5},
+                {0x1.8p1, 0x1.4ffffffffff8cp5, 0x1.50db263f101ecp5},
+                {0x1.8p1, 0x1.57ffffffffff8p5, 0x1.58d610be831eep5},
+                {0x1.8p1, 0x1.58p5, 0x1.58d610be831f7p5},
+                {0x1.8p1, 0x1.5fffffffffffap5, 0x1.60d13630e611p5},
+                {0x1.8p1, 0x1.5fffffffffffep5, 0x1.60d13630e6113p5},
+                {0x1.8p1, 0x1.67fffffffffe8p5, 0x1.68cc92acc47abp5},
+                {0x1.8p1, 0x1.68p5, 0x1.68cc92acc47c3p5},
+                {0x1.8p1, 0x1.6fffffffffff8p5, 0x1.70c8229f43a38p5},
+                {0x1.8p1, 0x1.6fffffffffffap5, 0x1.70c8229f43a3ap5},
+                {0x1.8p1, 0x1.77ffffffffffp5, 0x1.78c3e2c2fb433p5},
+                {0x1.8p1, 0x1.77ffffffffffep5, 0x1.78c3e2c2fb441p5},
+                {0x1.8p1, 0x1.7ffffffffffffp5, 0x1.80bfd017f10a6p5},
+                {0x1.8p1, 0x1.87fffffffff5p5, 0x1.88bbe7dc8d9ap5},
+                {0x1.8p1, 0x1.88p5, 0x1.88bbe7dc8da5p5},
+                {0x1.8p1, 0x1.8ffffffffffe8p5, 0x1.90b8278768b67p5},
+                {0x1.8p1, 0x1.9p5, 0x1.90b8278768b8p5},
+                {0x1.8p1, 0x1.97fffffffff2bp5, 0x1.98b48cc1ce669p5},
+                {0x1.8p1, 0x1.97fffffffff3p5, 0x1.98b48cc1ce66dp5},
+                {0x1.8p1, 0x1.9ffffffffff34p5, 0x1.a0b11562e5efcp5},
+                {0x1.8p1, 0x1.ap5, 0x1.a0b11562e5fc8p5},
+                {0x1.8p1, 0x1.a7fffffffffdp5, 0x1.a8adbf6b63874p5},
+                {0x1.8p1, 0x1.a8p5, 0x1.a8adbf6b638a4p5},
+                {0x1.8p1, 0x1.affffffffffd8p5, 0x1.b0aa8901b442cp5},
+                {0x1.8p1, 0x1.affffffffffe8p5, 0x1.b0aa8901b443dp5},
+                {0x1.8p1, 0x1.b7ffffffffffp5, 0x1.b8a7706e94761p5},
+                {0x1.8p1, 0x1.b7ffffffffffep5, 0x1.b8a7706e9477p5},
+                {0x1.8p1, 0x1.bfffffffffffep5, 0x1.c0a4741a02dcap5},
+                {0x1.8p1, 0x1.cp5, 0x1.c0a4741a02dcdp5},
+                {0x1.8p1, 0x1.c7fffffffffdp5, 0x1.c8a1928885b75p5},
+                {0x1.8p1, 0x1.c7ffffffffff9p5, 0x1.c8a1928885b9fp5},
+                {0x1.8p1, 0x1.cffffffffff28p5, 0x1.d09eca58b7d2cp5},
+                {0x1.8p1, 0x1.dp5, 0x1.d09eca58b7e04p5},
+                {0x1.8p1, 0x1.d7ffffffffffp5, 0x1.d89c1a4115253p5},
+                {0x1.8p1, 0x1.d8p5, 0x1.d89c1a4115264p5},
+                {0x1.8p1, 0x1.dfffffffffffcp5, 0x1.e099810dfefd1p5},
+                {0x1.8p1, 0x1.e7fffffffffdp5, 0x1.e896fd9ff2afep5},
+                {0x1.8p1, 0x1.e7ffffffffffap5, 0x1.e896fd9ff2b29p5},
+                {0x1.8p1, 0x1.effffffffff98p5, 0x1.f0948ee9ebc7bp5},
+                {0x1.8p1, 0x1.effffffffffcap5, 0x1.f0948ee9ebcadp5},
+                {0x1.8p1, 0x1.f7fffffffff7p5, 0x1.f89233efeda08p5},
+                {0x1.8p1, 0x1.f7fffffffffb2p5, 0x1.f89233efeda4ap5},
+                {0x1.8p1, 0x1.ffffffffffda9p5, 0x1.0047f5e2d7ed7p6},
+                {0x1.8p1, 0x1.03ffffffffedp6, 0x1.0446dac6b5468p6},
+                {0x1.8p1, 0x1.04p6, 0x1.0446dac6b5598p6},
+                {0x1.8p1, 0x1.07fffffffffe8p6, 0x1.0845c83b5eb9bp6},
+                {0x1.8p1, 0x1.07ffffffffff9p6, 0x1.0845c83b5ebadp6},
+                {0x1.8p1, 0x1.0bffffffffe9bp6, 0x1.0c44bdded82bdp6},
+                {0x1.8p1, 0x1.0bffffffffebp6, 0x1.0c44bdded82d1p6},
+                {0x1.8p1, 0x1.0fffffffffed4p6, 0x1.1043bb54e5cc9p6},
+                {0x1.8p1, 0x1.0ffffffffff1fp6, 0x1.1043bb54e5d14p6},
+                {0x1.8p1, 0x1.13ffffffffe9p6, 0x1.1442c046a0ea6p6},
+                {0x1.8p1, 0x1.13fffffffff5ap6, 0x1.1442c046a0f7p6},
+                {0x1.8p1, 0x1.17fffffffffa8p6, 0x1.1841cc62174cbp6},
+                {0x1.8p1, 0x1.17fffffffffb8p6, 0x1.1841cc62174dap6},
+                {0x1.8p1, 0x1.1bffffffffffp6, 0x1.1c40df59f1a57p6},
+                {0x1.8p1, 0x1.1cp6, 0x1.1c40df59f1a67p6},
+                {0x1.8p1, 0x1.1fffffffffffap6, 0x1.203ff8e522535p6},
+                {0x1.8p1, 0x1.1ffffffffffffp6, 0x1.203ff8e52253bp6},
+                {0x1.8p1, 0x1.23fffffffffdp6, 0x1.243f18be9a334p6},
+                {0x1.8p1, 0x1.23ffffffffffbp6, 0x1.243f18be9a36p6},
+                {0x1.8p1, 0x1.27fffffffffe8p6, 0x1.283e3ea503c63p6},
+                {0x1.8p1, 0x1.27ffffffffff8p6, 0x1.283e3ea503c74p6},
+                {0x1.8p1, 0x1.2bffffffffdfp6, 0x1.2c3d6a5a83932p6},
+                {0x1.8p1, 0x1.2bffffffffe1p6, 0x1.2c3d6a5a83953p6},
+                {0x1.8p1, 0x1.2fffffffffffcp6, 0x1.303c9ba47e6d4p6},
+                {0x1.8p1, 0x1.3p6, 0x1.303c9ba47e6d8p6},
+                {0x1.8p1, 0x1.33fffffffffdp6, 0x1.343bd24b62468p6},
+                {0x1.8p1, 0x1.33fffffffffffp6, 0x1.343bd24b62498p6},
+                {0x1.8p1, 0x1.37ffffffffff8p6, 0x1.383b0e1a75c0ap6},
+                {0x1.8p1, 0x1.37fffffffffffp6, 0x1.383b0e1a75c12p6},
+                {0x1.8p1, 0x1.3bffffffffffp6, 0x1.3c3a4edfa9748p6},
+                {0x1.8p1, 0x1.3bffffffffffep6, 0x1.3c3a4edfa9756p6},
+                {0x1.8p1, 0x1.3fffffffffd4dp6, 0x1.4039946b6d79fp6},
+                {0x1.8p1, 0x1.3ffffffffffffp6, 0x1.4039946b6da51p6},
+                {0x1.8p1, 0x1.43fffffffff9p6, 0x1.4438de908abeap6},
+                {0x1.8p1, 0x1.43fffffffffbp6, 0x1.4438de908ac0bp6},
+                {0x1.8p1, 0x1.47ffffffffd08p6, 0x1.48382d23fccedp6},
+                {0x1.8p1, 0x1.47fffffffffa2p6, 0x1.48382d23fcf87p6},
+                {0x1.8p1, 0x1.4bffffffffcebp6, 0x1.4c377ffcd212fp6},
+                {0x1.8p1, 0x1.4bffffffffcfp6, 0x1.4c377ffcd2133p6},
+                {0x1.8p1, 0x1.4ffffffffff44p6, 0x1.5036d6f40ad53p6},
+                {0x1.8p1, 0x1.4ffffffffff9bp6, 0x1.5036d6f40adaap6},
+                {0x1.8p1, 0x1.53ffffffffedp6, 0x1.543631e47c1e1p6},
+                {0x1.8p1, 0x1.54p6, 0x1.543631e47c311p6},
+                {0x1.8p1, 0x1.57ffffffffd78p6, 0x1.583590aab542dp6},
+                {0x1.8p1, 0x1.58p6, 0x1.583590aab56b5p6},
+                {0x1.8p1, 0x1.5bffffffffc7p6, 0x1.5c34f324e60eep6},
+                {0x1.8p1, 0x1.5bffffffffc9p6, 0x1.5c34f324e610fp6},
+                {0x1.8p1, 0x1.5fffffffffffdp6, 0x1.60345932c760dp6},
+                {0x1.8p1, 0x1.5fffffffffffep6, 0x1.60345932c760dp6},
+                {0x1.8p1, 0x1.63fffffffff79p6, 0x1.6433c2b58421fp6},
+                {0x1.8p1, 0x1.63fffffffff9p6, 0x1.6433c2b584235p6},
+                {0x1.8p1, 0x1.67ffffffffda8p6, 0x1.68332f8fa63a6p6},
+                {0x1.8p1, 0x1.67fffffffff4dp6, 0x1.68332f8fa654bp6},
+                {0x1.8p1, 0x1.6bfffffffffep6, 0x1.6c329fa502ccfp6},
+                {0x1.8p1, 0x1.6cp6, 0x1.6c329fa502cefp6},
+                {0x1.8p1, 0x1.6fffffffffff8p6, 0x1.703212daa75f3p6},
+                {0x1.8p1, 0x1.6ffffffffffffp6, 0x1.703212daa75fbp6},
+                {0x1.8p1, 0x1.73fffffffffap6, 0x1.74318916ca409p6},
+                {0x1.8p1, 0x1.74p6, 0x1.74318916ca46ap6},
+                {0x1.8p1, 0x1.77ffffffffffp6, 0x1.78310240ba47p6},
+                {0x1.8p1, 0x1.78p6, 0x1.78310240ba481p6},
+                {0x1.8p1, 0x1.7bfffffffffep6, 0x1.7c307e40cff7fp6},
+                {0x1.8p1, 0x1.7bfffffffffe4p6, 0x1.7c307e40cff83p6},
+                {0x1.8p1, 0x1.7fffffffffff7p6, 0x1.802ffd005ff07p6},
+                {0x1.8p1, 0x1.7fffffffffff9p6, 0x1.802ffd005ff0ap6},
+                {0x1.8p1, 0x1.83fffffffffap6, 0x1.842f7e69adc1ep6},
+                {0x1.8p1, 0x1.83fffffffffffp6, 0x1.842f7e69adc7dp6},
+                {0x1.8p1, 0x1.87fffffffffdp6, 0x1.882f0267dfef4p6},
+                {0x1.8p1, 0x1.88p6, 0x1.882f0267dff24p6},
+                {0x1.8p1, 0x1.8bfffffffffep6, 0x1.8c2e88e6f449ap6},
+                {0x1.8p1, 0x1.8bffffffffff6p6, 0x1.8c2e88e6f44b1p6},
+                {0x1.8p1, 0x1.8ffffffffffe8p6, 0x1.902e11d3b5549p6},
+                {0x1.8p1, 0x1.8fffffffffffep6, 0x1.902e11d3b556p6},
+
+                // Test near decision points of the fdlibm algorithm
+                {0x1.0000000000001p501, 0x1.000000000000p501, 0x1.6a09e667f3bcdp501},
+                {0x1.0p501, 0x1.0p499, 0x1.07e0f66afed07p501},
+
+                {0x1.0p500, 0x1.0p450, 0x1.0p500},
+                {0x1.0000000000001p500, 0x1.0p450, 0x1.0000000000001p500},
+
+                {0x1.0p500, 0x1.0p440, 0x1.0p500},
+                {0x1.0000000000001p500, 0x1.0p440, 0x1.0000000000001p500},
+                {0x1.0p500, 0x1.0p439, 0x1.0p500},
+                {0x1.0000000000001p500, 0x1.0p439, 0x1.0000000000001p500},
+
+                {0x1.0p-450, 0x1.0p-500, 0x1.0p-450},
+                {0x1.0000000000001p-450, 0x1.0p-500, 0x1.0000000000001p-450},
+                {0x1.0p-450, 0x1.fffffffffffffp-499, 0x1.0p-450},
+                {0x1.0000000000001p-450, 0x1.fffffffffffffp-499, 0x1.0000000000001p-450},
+
+                {0x1.0p-450, 0x1.0p-500, 0x1.0p-450},
+                {0x1.0000000000001p-450, 0x1.0p-500, 0x1.0000000000001p-450},
+                {0x1.0p-450, 0x1.fffffffffffffp-499, 0x1.0p-450},
+                {0x1.0000000000001p-450, 0x1.fffffffffffffp-499, 0x1.0000000000001p-450},
+
+                {0x1.00000_ffff_0000p500, 0x1.fffffffffffffp499, 0x1.6a09f1b837ccfp500},
+                {0x1.00000_0000_0001p500, 0x1.fffffffffffffp499, 0x1.6a09e667f3bcdp500},
+                {0x1.00000_ffff_ffffp500, 0x1.fffffffffffffp499, 0x1.6a09f1b8431d3p500},
+                {0x1.00001_0000_0000p500, 0x1.fffffffffffffp499, 0x1.6a09f1b8431d5p500},
+
+                // 0x1.0p-1022 is MIN_NORMAL
+                {0x1.0000000000001p-1022, 0x1.0000000000001p-1022, 0x1.6a09e667f3bcep-1022},
+                {0x1.0000000000001p-1022, 0x1.0p-1022, 0x1.6a09e667f3bcdp-1022},
+                {0x1.0000000000001p-1022, 0x0.fffffffffffffp-1022, 0x1.6a09e667f3bcdp-1022},
+                {0x1.0000000000001p-1022, 0x0.0000000000001P-1022, 0x1.0000000000001p-1022},
+                {0x1.0000000000001p-1022, 0.0, 0x1.0000000000001p-1022},
+
+                {0x1.0000000000000p-1022, 0x0.fffffffffffffp-1022, 0x1.6a09e667f3bccp-1022},
+                {0x1.0000000000000p-1021, 0x0.fffffffffffffp-1022, 0x1.1e3779b97f4a8p-1021},
+                {0x1.0000000000000p-1020, 0x0.fffffffffffffp-1022, 0x1.07e0f66afed07p-1020},
+
+                // 0x0.0000000000001P-1022 is MIN_VALUE (smallest nonzero number)
+                {0x0.0000000000001p-1022, 0x0.0000000000001p-1022, 0x0.0000000000001p-1022},
+                {0x0.0000000000002p-1022, 0x0.0000000000001p-1022, 0x0.0000000000002p-1022},
+                {0x0.0000000000003p-1022, 0x0.0000000000002p-1022, 0x0.0000000000004p-1022},
+        };
+
+        for (double[] testCase : testCases) {
+            testHypotCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+    // Initialize shared random number generator
+    private static final java.util.Random random = new Random();
+    // BEGIN Android-added: Shard testAgainstTranslit() to make tests run faster.
+    private static double X = Tests.createRandomDouble(random);
+    private static double Y = Tests.createRandomDouble(random);
+    // END Android-added: Shard testAgainstTranslit() to make tests run faster.
+
+    // BEGIN Android-changed: Shard testAgainstTranslit() to make tests run faster.
+    /**
+     * Test StrictMath.hypot against transliteration port of hypot.
+     *
+    @Test
+    public void testAgainstTranslit() {
+        double x = Tests.createRandomDouble(random);
+        double y = Tests.createRandomDouble(random);
+
+        // Make the increment twice the ulp value in case the random
+        // value is near an exponent threshold.
+        double increment_x = 2.0 * Math.ulp(x);
+        double increment_y = 2.0 * Math.ulp(y);
+
+        // Don't worry about x or y overflowing to infinity if their
+        // exponent is MAX_EXPONENT.
+        for (int i = 0; i < 200; i++, x += increment_x) {
+            for (int j = 0; j < 200; j++, y += increment_y) {
+                testHypotCase(x, y, FdlibmTranslit.hypot(x, y));
+            }
+        }
+    }
+    */
+    @Test
+    public void testAgainstTranslit_shard1() {
+        testAgainstTranslit(0, 50);
+    }
+
+    @Test
+    public void testAgainstTranslit_shard2() {
+        testAgainstTranslit(50, 100);
+    }
+
+    @Test
+    public void testAgainstTranslit_shard3() {
+        testAgainstTranslit(100, 150);
+    }
+
+    @Test
+    public void testAgainstTranslit_shard4() {
+        testAgainstTranslit(150, 200);
+    }
+
+    private void testAgainstTranslit(int fromI, int toI) {
+        // Make the increment twice the ulp value in case the random
+        // value is near an exponent threshold.
+        double increment_x = 2.0 * Math.ulp(X);
+        double increment_y = 2.0 * Math.ulp(Y);
+
+        // Don't worry about x or y overflowing to infinity if their
+        // exponent is MAX_EXPONENT.
+        for (int i = fromI; i < toI; i++, X += increment_x) {
+            for (int j = 0; j < 200; j++, Y += increment_y) {
+                testHypotCase(X, Y, FdlibmTranslit.hypot(X, Y));
+            }
+        }
+    }
+    // END Android-changed: Shard testAgainstTranslit() to make tests run faster.
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/Log10Tests.java b/ojluni/src/test/java/lang/StrictMath/Log10Tests.java
new file mode 100644
index 0000000..daf690b
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/Log10Tests.java
@@ -0,0 +1,712 @@
+/*
+ * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4074599
+ * @summary Tests for StrictMath.log10
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.StrictMath;
+
+import org.testng.annotations.Test;
+
+/**
+ * The tests in ../Math/Log10Tests.java test properties that should hold for any log10
+ * implementation, including the FDLIBM-based one required for StrictMath.log10.  Therefore, the
+ * test cases in ../Math/Log10Tests.java are run against both the Math and StrictMath versions of
+ * log10.  The role of this test is to verify that the FDLIBM log10 algorithm is being used by
+ * running golden file tests on values that may vary from one conforming log10 implementation to
+ * another.
+ */
+
+public class Log10Tests {
+
+    private Log10Tests() {
+    }
+
+    static void testLog10Case(double input, double expected) {
+        Tests.test("StrictMath.log10(double)", input, StrictMath.log10(input), expected);
+    }
+
+    @Test
+    public void testLog10() {
+        double[][] testCases = {
+                {0x1.3fffffffffec1p-297, -0x1.653c6a27ae2f8p6},
+                {0x1.4p-297, -0x1.653c6a27ae2f7p6},
+                {0x1.3fffffffffbe1p-296, -0x1.640828f2a4382p6},
+                {0x1.4p-296, -0x1.640828f2a437dp6},
+                {0x1.3fffffffffd52p-295, -0x1.62d3e7bd9a406p6},
+                {0x1.4p-295, -0x1.62d3e7bd9a403p6},
+                {0x1.3fffffffffa72p-294, -0x1.619fa6889049p6},
+                {0x1.4p-294, -0x1.619fa68890489p6},
+                {0x1.3fffffffff9bbp-293, -0x1.606b655386518p6},
+                {0x1.4p-293, -0x1.606b65538650fp6},
+                {0x1.3fffffffffbe4p-292, -0x1.5f37241e7c59ap6},
+                {0x1.4p-292, -0x1.5f37241e7c595p6},
+                {0x1.3ffffffffff7ep-291, -0x1.5e02e2e97261cp6},
+                {0x1.4p-291, -0x1.5e02e2e97261bp6},
+                {0x1.3fffffffffc9ep-290, -0x1.5ccea1b4686a6p6},
+                {0x1.4p-290, -0x1.5ccea1b4686a1p6},
+                {0x1.3fffffffffec7p-289, -0x1.5b9a607f5e728p6},
+                {0x1.4p-289, -0x1.5b9a607f5e727p6},
+                {0x1.3fffffffffbe7p-288, -0x1.5a661f4a547b2p6},
+                {0x1.4p-288, -0x1.5a661f4a547adp6},
+                {0x1.3fffffffff907p-287, -0x1.5931de154a83cp6},
+                {0x1.4p-287, -0x1.5931de154a833p6},
+                {0x1.3fffffffffd59p-286, -0x1.57fd9ce0408bcp6},
+                {0x1.4p-286, -0x1.57fd9ce0408b9p6},
+                {0x1.3fffffffffecap-285, -0x1.56c95bab3694p6},
+                {0x1.4p-285, -0x1.56c95bab3693fp6},
+                {0x1.3fffffffffbeap-284, -0x1.55951a762c9cap6},
+                {0x1.4p-284, -0x1.55951a762c9c5p6},
+                {0x1.3ffffffffff84p-283, -0x1.5460d94122a4cp6},
+                {0x1.4p-283, -0x1.5460d94122a4bp6},
+                {0x1.3fffffffffca4p-282, -0x1.532c980c18ad6p6},
+                {0x1.4p-282, -0x1.532c980c18ad1p6},
+                {0x1.3fffffffff9c4p-281, -0x1.51f856d70eb6p6},
+                {0x1.4p-281, -0x1.51f856d70eb57p6},
+                {0x1.3fffffffffe16p-280, -0x1.50c415a204bep6},
+                {0x1.4p-280, -0x1.50c415a204bddp6},
+                {0x1.3fffffffffd5ep-279, -0x1.4f8fd46cfac66p6},
+                {0x1.4p-279, -0x1.4f8fd46cfac63p6},
+                {0x1.3fffffffffd5fp-278, -0x1.4e5b9337f0cecp6},
+                {0x1.4p-278, -0x1.4e5b9337f0ce9p6},
+                {0x1.3fffffffffedp-277, -0x1.4d275202e6d7p6},
+                {0x1.4p-277, -0x1.4d275202e6d6fp6},
+                {0x1.3fffffffffbfp-276, -0x1.4bf310cddcdfap6},
+                {0x1.4p-276, -0x1.4bf310cddcdf5p6},
+                {0x1.3ffffffffff8ap-275, -0x1.4abecf98d2e7bp6},
+                {0x1.4p-275, -0x1.4abecf98d2e7bp6},
+                {0x1.3fffffffffd62p-274, -0x1.498a8e63c8f04p6},
+                {0x1.4p-274, -0x1.498a8e63c8f01p6},
+                {0x1.3fffffffff9cap-273, -0x1.48564d2ebef9p6},
+                {0x1.4p-273, -0x1.48564d2ebef87p6},
+                {0x1.3fffffffff6eap-272, -0x1.47220bf9b501ap6},
+                {0x1.4p-272, -0x1.47220bf9b500dp6},
+                {0x1.3fffffffffb3cp-271, -0x1.45edcac4ab09ap6},
+                {0x1.4p-271, -0x1.45edcac4ab093p6},
+                {0x1.3fffffffffd65p-270, -0x1.44b9898fa111cp6},
+                {0x1.4p-270, -0x1.44b9898fa1119p6},
+                {0x1.3fffffffffa85p-269, -0x1.4385485a971a6p6},
+                {0x1.4p-269, -0x1.4385485a9719fp6},
+                {0x1.3ffffffffe2c7p-268, -0x1.425107258d24dp6},
+                {0x1.3fffffffffed7p-268, -0x1.425107258d226p6},
+                {0x1.4p-268, -0x1.425107258d225p6},
+                {0x1.3fffffffff916p-267, -0x1.411cc5f0832b4p6},
+                {0x1.4p-267, -0x1.411cc5f0832abp6},
+                {0x1.3fffffffffd68p-266, -0x1.3fe884bb79334p6},
+                {0x1.4p-266, -0x1.3fe884bb79331p6},
+                {0x1.3fffffffffe21p-265, -0x1.3eb443866f3b9p6},
+                {0x1.4p-265, -0x1.3eb443866f3b7p6},
+                {0x1.3fffffffffedap-264, -0x1.3d8002516543ep6},
+                {0x1.4p-264, -0x1.3d8002516543dp6},
+                {0x1.3fffffffffbfap-263, -0x1.3c4bc11c5b4c9p6},
+                {0x1.4p-263, -0x1.3c4bc11c5b4c3p6},
+                {0x1.3fffffffff862p-262, -0x1.3b177fe751554p6},
+                {0x1.4p-262, -0x1.3b177fe751549p6},
+                {0x1.3fffffffffa8bp-261, -0x1.39e33eb2475d6p6},
+                {0x1.4p-261, -0x1.39e33eb2475cfp6},
+                {0x1.3fffffffffeddp-260, -0x1.38aefd7d3d656p6},
+                {0x1.4p-260, -0x1.38aefd7d3d655p6},
+                {0x1.3fffffffffbfdp-259, -0x1.377abc48336ep6},
+                {0x1.4p-259, -0x1.377abc48336dbp6},
+                {0x1.3ffffffffff97p-258, -0x1.36467b1329762p6},
+                {0x1.4p-258, -0x1.36467b1329761p6},
+                {0x1.3fffffffffedfp-257, -0x1.351239de1f7e8p6},
+                {0x1.4p-257, -0x1.351239de1f7e7p6},
+                {0x1.3fffffffffeep-256, -0x1.33ddf8a91586ep6},
+                {0x1.4p-256, -0x1.33ddf8a91586dp6},
+                {0x1.3fffffffffcp-255, -0x1.32a9b7740b8f8p6},
+                {0x1.4p-255, -0x1.32a9b7740b8f3p6},
+                {0x1.3fffffffffd71p-254, -0x1.3175763f0197cp6},
+                {0x1.4p-254, -0x1.3175763f01979p6},
+                {0x1.3fffffffff588p-253, -0x1.30413509f7a0ep6},
+                {0x1.4p-253, -0x1.30413509f79ffp6},
+                {0x1.3fffffffff7b1p-252, -0x1.2f0cf3d4eda9p6},
+                {0x1.4p-252, -0x1.2f0cf3d4eda85p6},
+                {0x1.3fffffffffc03p-251, -0x1.2dd8b29fe3b1p6},
+                {0x1.4p-251, -0x1.2dd8b29fe3b0bp6},
+                {0x1.3fffffffff86bp-250, -0x1.2ca4716ad9b9cp6},
+                {0x1.4p-250, -0x1.2ca4716ad9b91p6},
+                {0x1.3fffffffffcbdp-249, -0x1.2b703035cfc1cp6},
+                {0x1.4p-249, -0x1.2b703035cfc17p6},
+                {0x1.3fffffffffee6p-248, -0x1.2a3bef00c5c9ep6},
+                {0x1.4p-248, -0x1.2a3bef00c5c9dp6},
+                {0x1.3fffffffffc06p-247, -0x1.2907adcbbbd28p6},
+                {0x1.4p-247, -0x1.2907adcbbbd23p6},
+                {0x1.3fffffffffd77p-246, -0x1.27d36c96b1dacp6},
+                {0x1.4p-246, -0x1.27d36c96b1da9p6},
+                {0x1.3fffffffffd78p-245, -0x1.269f2b61a7e32p6},
+                {0x1.4p-245, -0x1.269f2b61a7e2fp6},
+                {0x1.3ffffffffea0bp-244, -0x1.256aea2c9ded3p6},
+                {0x1.3fffffffffee9p-244, -0x1.256aea2c9deb6p6},
+                {0x1.4p-244, -0x1.256aea2c9deb5p6},
+                {0x1.3fffffffffe32p-243, -0x1.2436a8f793f3ep6},
+                {0x1.4p-243, -0x1.2436a8f793f3bp6},
+                {0x1.3ffffffffffa3p-242, -0x1.230267c289fc2p6},
+                {0x1.4p-242, -0x1.230267c289fc1p6},
+                {0x1.3fffffffff591p-241, -0x1.21ce268d80056p6},
+                {0x1.4p-241, -0x1.21ce268d80047p6},
+                {0x1.3fffffffff9e3p-240, -0x1.2099e558760d6p6},
+                {0x1.4p-240, -0x1.2099e558760cdp6},
+                {0x1.3fffffffffc0cp-239, -0x1.1f65a4236c158p6},
+                {0x1.4p-239, -0x1.1f65a4236c153p6},
+                {0x1.3fffffffffd7dp-238, -0x1.1e3162ee621dcp6},
+                {0x1.4p-238, -0x1.1e3162ee621d9p6},
+                {0x1.3fffffffffd7ep-237, -0x1.1cfd21b958262p6},
+                {0x1.4p-237, -0x1.1cfd21b95825fp6},
+                {0x1.3fffffffffeefp-236, -0x1.1bc8e0844e2e6p6},
+                {0x1.4p-236, -0x1.1bc8e0844e2e5p6},
+                {0x1.3fffffffffc0fp-235, -0x1.1a949f4f4437p6},
+                {0x1.4p-235, -0x1.1a949f4f4436bp6},
+                {0x1.3ffffffffffa9p-234, -0x1.19605e1a3a3f1p6},
+                {0x1.4p-234, -0x1.19605e1a3a3f1p6},
+                {0x1.3ffffffffffaap-233, -0x1.182c1ce530478p6},
+                {0x1.4p-233, -0x1.182c1ce530477p6},
+                {0x1.3fffffffff2b7p-232, -0x1.16f7dbb02651p6},
+                {0x1.4p-232, -0x1.16f7dbb0264fdp6},
+                {0x1.3fffffffffef3p-231, -0x1.15c39a7b1c584p6},
+                {0x1.4p-231, -0x1.15c39a7b1c583p6},
+                {0x1.3fffffffff932p-230, -0x1.148f594612612p6},
+                {0x1.4p-230, -0x1.148f594612609p6},
+                {0x1.3fffffffffd84p-229, -0x1.135b181108692p6},
+                {0x1.4p-229, -0x1.135b18110868fp6},
+                {0x1.3fffffffffaa4p-228, -0x1.1226d6dbfe71cp6},
+                {0x1.4p-228, -0x1.1226d6dbfe715p6},
+                {0x1.3fffffffffef6p-227, -0x1.10f295a6f479cp6},
+                {0x1.4p-227, -0x1.10f295a6f479bp6},
+                {0x1.3fffffffffd86p-226, -0x1.0fbe5471ea824p6},
+                {0x1.4p-226, -0x1.0fbe5471ea821p6},
+                {0x1.3fffffffffd87p-225, -0x1.0e8a133ce08aap6},
+                {0x1.4p-225, -0x1.0e8a133ce08a7p6},
+                {0x1.3fffffffffef8p-224, -0x1.0d55d207d692ep6},
+                {0x1.4p-224, -0x1.0d55d207d692dp6},
+                {0x1.3fffffffffef9p-223, -0x1.0c2190d2cc9b4p6},
+                {0x1.4p-223, -0x1.0c2190d2cc9b3p6},
+                {0x1.3fffffffff42fp-222, -0x1.0aed4f9dc2a4ap6},
+                {0x1.4p-222, -0x1.0aed4f9dc2a39p6},
+                {0x1.3fffffffff658p-221, -0x1.09b90e68b8accp6},
+                {0x1.4p-221, -0x1.09b90e68b8abfp6},
+                {0x1.3fffffffffaaap-220, -0x1.0884cd33aeb4cp6},
+                {0x1.4p-220, -0x1.0884cd33aeb45p6},
+                {0x1.3fffffffffefcp-219, -0x1.07508bfea4bccp6},
+                {0x1.4p-219, -0x1.07508bfea4bcbp6},
+                {0x1.3fffffffffc1cp-218, -0x1.061c4ac99ac56p6},
+                {0x1.4p-218, -0x1.061c4ac99ac51p6},
+                {0x1.3fffffffffd8dp-217, -0x1.04e8099490cdap6},
+                {0x1.4p-217, -0x1.04e8099490cd7p6},
+                {0x1.3fffffffffaadp-216, -0x1.03b3c85f86d65p6},
+                {0x1.3fffffffffefep-216, -0x1.03b3c85f86d5ep6},
+                {0x1.4p-216, -0x1.03b3c85f86d5dp6},
+                {0x1.3ffffffffdbbdp-215, -0x1.027f872a7ce16p6},
+                {0x1.3fffffffffeffp-215, -0x1.027f872a7cde4p6},
+                {0x1.4p-215, -0x1.027f872a7cde3p6},
+                {0x1.3fffffffffc1fp-214, -0x1.014b45f572e6ep6},
+                {0x1.4p-214, -0x1.014b45f572e69p6},
+                {0x1.3ffffffffffb9p-213, -0x1.001704c068efp6},
+                {0x1.4p-213, -0x1.001704c068eefp6},
+                {0x1.3fffffffffdbfp-212, -0x1.fdc58716bdefp5},
+                {0x1.4p-212, -0x1.fdc58716bdeeap5},
+                {0x1.3ffffffffff3p-211, -0x1.fb5d04aca9ff8p5},
+                {0x1.4p-211, -0x1.fb5d04aca9ff6p5},
+                {0x1.3ffffffffffe9p-210, -0x1.f8f4824296102p5},
+                {0x1.4p-210, -0x1.f8f4824296102p5},
+                {0x1.3fffffffffd09p-209, -0x1.f68bffd882216p5},
+                {0x1.4p-209, -0x1.f68bffd88220ep5},
+                {0x1.3fffffffffdc2p-208, -0x1.f4237d6e6e32p5},
+                {0x1.4p-208, -0x1.f4237d6e6e31ap5},
+                {0x1.3fffffffff23fp-207, -0x1.f1bafb045a44cp5},
+                {0x1.3fffffffffe7bp-207, -0x1.f1bafb045a42ap5},
+                {0x1.4p-207, -0x1.f1bafb045a426p5},
+                {0x1.3ffffffffffecp-206, -0x1.ef52789a46532p5},
+                {0x1.4p-206, -0x1.ef52789a46532p5},
+                {0x1.3fffffffffdc4p-205, -0x1.ece9f63032644p5},
+                {0x1.4p-205, -0x1.ece9f6303263ep5},
+                {0x1.3ffffffffe211p-204, -0x1.ea8173c61e79ep5},
+                {0x1.3ffffffffff35p-204, -0x1.ea8173c61e74cp5},
+                {0x1.4p-204, -0x1.ea8173c61e74ap5},
+                {0x1.3ffffffffec25p-203, -0x1.e818f15c0a88ep5},
+                {0x1.3fffffffffe7ep-203, -0x1.e818f15c0a85ap5},
+                {0x1.4p-203, -0x1.e818f15c0a856p5},
+                {0x1.3ffffffffdcadp-202, -0x1.e5b06ef1f69c5p5},
+                {0x1.3fffffffffedbp-202, -0x1.e5b06ef1f6966p5},
+                {0x1.4p-202, -0x1.e5b06ef1f6962p5},
+                {0x1.3fffffffffd0fp-201, -0x1.e347ec87e2a76p5},
+                {0x1.4p-201, -0x1.e347ec87e2a6ep5},
+                {0x1.3fffffffffe8p-200, -0x1.e0df6a1dceb7ep5},
+                {0x1.4p-200, -0x1.e0df6a1dceb7ap5},
+                {0x1.3ffffffffff39p-199, -0x1.de76e7b3bac88p5},
+                {0x1.4p-199, -0x1.de76e7b3bac86p5},
+                {0x1.3fffffffffff2p-198, -0x1.dc0e6549a6d92p5},
+                {0x1.4p-198, -0x1.dc0e6549a6d92p5},
+                {0x1.3ffffffffff97p-197, -0x1.d9a5e2df92eap5},
+                {0x1.4p-197, -0x1.d9a5e2df92e9ep5},
+                {0x1.3fffffffffdcbp-196, -0x1.d73d60757efbp5},
+                {0x1.4p-196, -0x1.d73d60757efaap5},
+                {0x1.3ffffffffff3cp-195, -0x1.d4d4de0b6b0b8p5},
+                {0x1.4p-195, -0x1.d4d4de0b6b0b6p5},
+                {0x1.3fffffffffee1p-194, -0x1.d26c5ba1571c6p5},
+                {0x1.4p-194, -0x1.d26c5ba1571c2p5},
+                {0x1.3ffffffffff9ap-193, -0x1.d003d937432dp5},
+                {0x1.4p-193, -0x1.d003d937432cep5},
+                {0x1.3fffffffffdcep-192, -0x1.cd9b56cd2f3ep5},
+                {0x1.4p-192, -0x1.cd9b56cd2f3dap5},
+                {0x1.3fffffffffe87p-191, -0x1.cb32d4631b4eap5},
+                {0x1.4p-191, -0x1.cb32d4631b4e6p5},
+                {0x1.3fffffffffff8p-190, -0x1.c8ca51f9075f2p5},
+                {0x1.4p-190, -0x1.c8ca51f9075f2p5},
+                {0x1.3fffffffffff9p-189, -0x1.c661cf8ef36fep5},
+                {0x1.4p-189, -0x1.c661cf8ef36fep5},
+                {0x1.3fffffffffdd1p-188, -0x1.c3f94d24df81p5},
+                {0x1.4p-188, -0x1.c3f94d24df80ap5},
+                {0x1.3fffffffffe8ap-187, -0x1.c190cabacb91ap5},
+                {0x1.4p-187, -0x1.c190cabacb916p5},
+                {0x1.3ffffffffff43p-186, -0x1.bf284850b7a24p5},
+                {0x1.4p-186, -0x1.bf284850b7a22p5},
+                {0x1.3fffffffffffcp-185, -0x1.bcbfc5e6a3b2ep5},
+                {0x1.4p-185, -0x1.bcbfc5e6a3b2ep5},
+                {0x1.3ffffffffffa1p-184, -0x1.ba57437c8fc3cp5},
+                {0x1.4p-184, -0x1.ba57437c8fc3ap5},
+                {0x1.3fffffffffd79p-183, -0x1.b7eec1127bd4ep5},
+                {0x1.4p-183, -0x1.b7eec1127bd46p5},
+                {0x1.3fffffffffe32p-182, -0x1.b5863ea867e58p5},
+                {0x1.4p-182, -0x1.b5863ea867e52p5},
+                {0x1.3ffffffffe4a7p-181, -0x1.b31dbc3e53faap5},
+                {0x1.3ffffffffffffp-181, -0x1.b31dbc3e53f5ep5},
+                {0x1.4p-181, -0x1.b31dbc3e53f5ep5},
+                {0x1.3fffffffffdd7p-180, -0x1.b0b539d44007p5},
+                {0x1.4p-180, -0x1.b0b539d44006ap5},
+                {0x1.3fffffffffa9bp-179, -0x1.ae4cb76a2c185p5},
+                {0x1.3fffffffffe9p-179, -0x1.ae4cb76a2c17ap5},
+                {0x1.4p-179, -0x1.ae4cb76a2c177p5},
+                {0x1.3ffffffffe3f1p-178, -0x1.abe43500182d1p5},
+                {0x1.3ffffffffff49p-178, -0x1.abe4350018284p5},
+                {0x1.4p-178, -0x1.abe4350018283p5},
+                {0x1.3fffffffffc69p-177, -0x1.a97bb29604398p5},
+                {0x1.4p-177, -0x1.a97bb2960438fp5},
+                {0x1.3fffffffffddap-176, -0x1.a713302bf04ap5},
+                {0x1.4p-176, -0x1.a713302bf049bp5},
+                {0x1.3fffffffffe93p-175, -0x1.a4aaadc1dc5aap5},
+                {0x1.4p-175, -0x1.a4aaadc1dc5a7p5},
+                {0x1.3fffffffff481p-174, -0x1.a2422b57c86d3p5},
+                {0x1.3fffffffffe38p-174, -0x1.a2422b57c86b8p5},
+                {0x1.4p-174, -0x1.a2422b57c86b3p5},
+                {0x1.3fffffffffef1p-173, -0x1.9fd9a8edb47c2p5},
+                {0x1.4p-173, -0x1.9fd9a8edb47bfp5},
+                {0x1.3ffffffffffaap-172, -0x1.9d712683a08ccp5},
+                {0x1.4p-172, -0x1.9d712683a08cbp5},
+                {0x1.3fffffffffddep-171, -0x1.9b08a4198c9dcp5},
+                {0x1.4p-171, -0x1.9b08a4198c9d7p5},
+                {0x1.3ffffffffff4fp-170, -0x1.98a021af78ae4p5},
+                {0x1.4p-170, -0x1.98a021af78ae3p5},
+                {0x1.3fffffffffd27p-169, -0x1.96379f4564bf6p5},
+                {0x1.4p-169, -0x1.96379f4564befp5},
+                {0x1.3fffffffffdep-168, -0x1.93cf1cdb50dp5},
+                {0x1.4p-168, -0x1.93cf1cdb50cfbp5},
+                {0x1.3fffffffffe99p-167, -0x1.91669a713ce0ap5},
+                {0x1.4p-167, -0x1.91669a713ce07p5},
+                {0x1.3ffffffffff52p-166, -0x1.8efe180728f14p5},
+                {0x1.4p-166, -0x1.8efe180728f13p5},
+                {0x1.3fffffffffc72p-165, -0x1.8c95959d15028p5},
+                {0x1.4p-165, -0x1.8c95959d1501fp5},
+                {0x1.3ffffffffffbp-164, -0x1.8a2d13330112cp5},
+                {0x1.4p-164, -0x1.8a2d13330112bp5},
+                {0x1.3fffffffffd88p-163, -0x1.87c490c8ed23ep5},
+                {0x1.4p-163, -0x1.87c490c8ed237p5},
+                {0x1.3fffffffffe9dp-162, -0x1.855c0e5ed9346p5},
+                {0x1.4p-162, -0x1.855c0e5ed9343p5},
+                {0x1.3fffffffffefap-161, -0x1.82f38bf4c5452p5},
+                {0x1.4p-161, -0x1.82f38bf4c544fp5},
+                {0x1.3fffffffffd2ep-160, -0x1.808b098ab1562p5},
+                {0x1.4p-160, -0x1.808b098ab155bp5},
+                {0x1.3fffffffffe9fp-159, -0x1.7e2287209d66ap5},
+                {0x1.4p-159, -0x1.7e2287209d667p5},
+                {0x1.3ffffffffff58p-158, -0x1.7bba04b689774p5},
+                {0x1.4p-158, -0x1.7bba04b689773p5},
+                {0x1.3fffffffff099p-157, -0x1.7951824c758aap5},
+                {0x1.3ffffffffff59p-157, -0x1.7951824c7588p5},
+                {0x1.4p-157, -0x1.7951824c7587fp5},
+                {0x1.3fffffffffd31p-156, -0x1.76e8ffe261992p5},
+                {0x1.4p-156, -0x1.76e8ffe26198bp5},
+                {0x1.3fffffffffdeap-155, -0x1.74807d784da9cp5},
+                {0x1.4p-155, -0x1.74807d784da97p5},
+                {0x1.3fffffffffea3p-154, -0x1.7217fb0e39ba6p5},
+                {0x1.4p-154, -0x1.7217fb0e39ba3p5},
+                {0x1.3fffffffffc7bp-153, -0x1.6faf78a425cb8p5},
+                {0x1.3ffffffffff5cp-153, -0x1.6faf78a425cbp5},
+                {0x1.4p-153, -0x1.6faf78a425cafp5},
+                {0x1.3ffffffffffb9p-152, -0x1.6d46f63a11dbcp5},
+                {0x1.4p-152, -0x1.6d46f63a11dbbp5},
+                {0x1.3fffffffffa54p-151, -0x1.6ade73cffded6p5},
+                {0x1.4p-151, -0x1.6ade73cffdec7p5},
+                {0x1.3fffffffffbc5p-150, -0x1.6875f165e9fdfp5},
+                {0x1.3fffffffffea6p-150, -0x1.6875f165e9fd6p5},
+                {0x1.4p-150, -0x1.6875f165e9fd3p5},
+                {0x1.3ffffffffff5fp-149, -0x1.660d6efbd60ep5},
+                {0x1.4p-149, -0x1.660d6efbd60dfp5},
+                {0x1.3fffffffffdefp-148, -0x1.63a4ec91c21fp5},
+                {0x1.4p-148, -0x1.63a4ec91c21ebp5},
+                {0x1.3fffffffffea8p-147, -0x1.613c6a27ae2fap5},
+                {0x1.4p-147, -0x1.613c6a27ae2f7p5},
+                {0x1.3ffffffffff61p-146, -0x1.5ed3e7bd9a404p5},
+                {0x1.4p-146, -0x1.5ed3e7bd9a403p5},
+                {0x1.3ffffffffff62p-145, -0x1.5c6b65538651p5},
+                {0x1.4p-145, -0x1.5c6b65538650fp5},
+                {0x1.3ffffffffffbfp-144, -0x1.5a02e2e97261cp5},
+                {0x1.4p-144, -0x1.5a02e2e97261bp5},
+                {0x1.3fffffffffcdfp-143, -0x1.579a607f5e73p5},
+                {0x1.4p-143, -0x1.579a607f5e727p5},
+                {0x1.3fffffffffd98p-142, -0x1.5531de154a83ap5},
+                {0x1.4p-142, -0x1.5531de154a833p5},
+                {0x1.3fffffffffe51p-141, -0x1.52c95bab36944p5},
+                {0x1.4p-141, -0x1.52c95bab3693fp5},
+                {0x1.3ffffffffffc2p-140, -0x1.5060d94122a4cp5},
+                {0x1.4p-140, -0x1.5060d94122a4bp5},
+                {0x1.3fffffffffdf6p-139, -0x1.4df856d70eb5cp5},
+                {0x1.4p-139, -0x1.4df856d70eb57p5},
+                {0x1.3fffffffffeafp-138, -0x1.4b8fd46cfac66p5},
+                {0x1.4p-138, -0x1.4b8fd46cfac63p5},
+                {0x1.3ffffffffff68p-137, -0x1.49275202e6d7p5},
+                {0x1.4p-137, -0x1.49275202e6d6fp5},
+                {0x1.3ffffffffffc5p-136, -0x1.46becf98d2e7bp5},
+                {0x1.4p-136, -0x1.46becf98d2e7bp5},
+                {0x1.3fffffffffdf9p-135, -0x1.44564d2ebef8cp5},
+                {0x1.4p-135, -0x1.44564d2ebef87p5},
+                {0x1.3fffffffffeb2p-134, -0x1.41edcac4ab096p5},
+                {0x1.4p-134, -0x1.41edcac4ab093p5},
+                {0x1.3ffffffffff6bp-133, -0x1.3f85485a971ap5},
+                {0x1.4p-133, -0x1.3f85485a9719fp5},
+                {0x1.3ffffffffe699p-132, -0x1.3d1cc5f0832f2p5},
+                {0x1.3ffffffffff1p-132, -0x1.3d1cc5f0832aep5},
+                {0x1.4p-132, -0x1.3d1cc5f0832abp5},
+                {0x1.3ffffffffffc9p-131, -0x1.3ab443866f3b8p5},
+                {0x1.4p-131, -0x1.3ab443866f3b7p5},
+                {0x1.3fffffffffda1p-130, -0x1.384bc11c5b4cap5},
+                {0x1.4p-130, -0x1.384bc11c5b4c3p5},
+                {0x1.3ffffffffed15p-129, -0x1.35e33eb247604p5},
+                {0x1.3ffffffffff6ep-129, -0x1.35e33eb2475dp5},
+                {0x1.4p-129, -0x1.35e33eb2475cfp5},
+                {0x1.3ffffffffdd9dp-128, -0x1.337abc483373bp5},
+                {0x1.3fffffffffd46p-128, -0x1.337abc48336e2p5},
+                {0x1.4p-128, -0x1.337abc48336dbp5},
+                {0x1.3fffffffffdffp-127, -0x1.311239de1f7ecp5},
+                {0x1.4p-127, -0x1.311239de1f7e7p5},
+                {0x1.3fffffffff391p-126, -0x1.2ea9b7740b916p5},
+                {0x1.3ffffffffff7p-126, -0x1.2ea9b7740b8f4p5},
+                {0x1.4p-126, -0x1.2ea9b7740b8f3p5},
+                {0x1.3ffffffffff71p-125, -0x1.2c413509f7ap5},
+                {0x1.4p-125, -0x1.2c413509f79ffp5},
+                {0x1.3fffffffffc91p-124, -0x1.29d8b29fe3b14p5},
+                {0x1.4p-124, -0x1.29d8b29fe3b0bp5},
+                {0x1.3fffffffffd4ap-123, -0x1.27703035cfc1ep5},
+                {0x1.4p-123, -0x1.27703035cfc17p5},
+                {0x1.3fffffffffe03p-122, -0x1.2507adcbbbd28p5},
+                {0x1.4p-122, -0x1.2507adcbbbd23p5},
+                {0x1.3fffffffffebcp-121, -0x1.229f2b61a7e32p5},
+                {0x1.4p-121, -0x1.229f2b61a7e2fp5},
+                {0x1.3ffffffffff19p-120, -0x1.2036a8f793f3ep5},
+                {0x1.4p-120, -0x1.2036a8f793f3bp5},
+                {0x1.3fffffffffd4dp-119, -0x1.1dce268d8004ep5},
+                {0x1.4p-119, -0x1.1dce268d80047p5},
+                {0x1.3fffffffffebep-118, -0x1.1b65a4236c156p5},
+                {0x1.4p-118, -0x1.1b65a4236c153p5},
+                {0x1.3ffffffffff77p-117, -0x1.18fd21b95826p5},
+                {0x1.4p-117, -0x1.18fd21b95825fp5},
+                {0x1.3ffffffffffd4p-116, -0x1.16949f4f4436bp5},
+                {0x1.4p-116, -0x1.16949f4f4436bp5},
+                {0x1.3fffffffffe08p-115, -0x1.142c1ce53047cp5},
+                {0x1.4p-115, -0x1.142c1ce530477p5},
+                {0x1.3fffffffffe09p-114, -0x1.11c39a7b1c588p5},
+                {0x1.4p-114, -0x1.11c39a7b1c583p5},
+                {0x1.3fffffffffec2p-113, -0x1.0f5b181108692p5},
+                {0x1.4p-113, -0x1.0f5b18110868fp5},
+                {0x1.3ffffffffff7bp-112, -0x1.0cf295a6f479cp5},
+                {0x1.4p-112, -0x1.0cf295a6f479bp5},
+                {0x1.3ffffffffffd8p-111, -0x1.0a8a133ce08a8p5},
+                {0x1.4p-111, -0x1.0a8a133ce08a7p5},
+                {0x1.3fffffffffa73p-110, -0x1.082190d2cc9c2p5},
+                {0x1.4p-110, -0x1.082190d2cc9b3p5},
+                {0x1.3fffffffffec5p-109, -0x1.05b90e68b8ac2p5},
+                {0x1.4p-109, -0x1.05b90e68b8abfp5},
+                {0x1.3ffffffffedddp-108, -0x1.03508bfea4bfep5},
+                {0x1.3ffffffffff7ep-108, -0x1.03508bfea4bccp5},
+                {0x1.4p-108, -0x1.03508bfea4bcbp5},
+                {0x1.3ffffffffde65p-107, -0x1.00e8099490d35p5},
+                {0x1.3fffffffffe0ep-107, -0x1.00e8099490cdcp5},
+                {0x1.4p-107, -0x1.00e8099490cd7p5},
+                {0x1.3ffffffffed3dp-106, -0x1.fcff0e54f9c2fp4},
+                {0x1.3fffffffffe82p-106, -0x1.fcff0e54f9bcep4},
+                {0x1.4p-106, -0x1.fcff0e54f9bc6p4},
+                {0x1.3fffffffffff3p-105, -0x1.f82e0980d1ddep4},
+                {0x1.4p-105, -0x1.f82e0980d1ddep4},
+                {0x1.3ffffffffff98p-104, -0x1.f35d04aca9ff8p4},
+                {0x1.4p-104, -0x1.f35d04aca9ff6p4},
+                {0x1.3ffffffffe3b7p-103, -0x1.ee8bffd8822abp4},
+                {0x1.3ffffffffffc7p-103, -0x1.ee8bffd88221p4},
+                {0x1.4p-103, -0x1.ee8bffd88220ep4},
+                {0x1.3fffffffffdcdp-102, -0x1.e9bafb045a432p4},
+                {0x1.4p-102, -0x1.e9bafb045a426p4},
+                {0x1.3ffffffffff3ep-101, -0x1.e4e9f63032642p4},
+                {0x1.4p-101, -0x1.e4e9f6303263ep4},
+                {0x1.3ffffffffe301p-100, -0x1.e018f15c0a8f8p4},
+                {0x1.3fffffffffff7p-100, -0x1.e018f15c0a856p4},
+                {0x1.4p-100, -0x1.e018f15c0a856p4},
+                {0x1.3fffffffffd73p-99, -0x1.db47ec87e2a7cp4},
+                {0x1.4p-99, -0x1.db47ec87e2a6ep4},
+                {0x1.3ffffffffdd9dp-98, -0x1.d676e7b3bad46p4},
+                {0x1.3fffffffffee4p-98, -0x1.d676e7b3bac8cp4},
+                {0x1.4p-98, -0x1.d676e7b3bac86p4},
+                {0x1.3ffffffffff9dp-97, -0x1.d1a5e2df92eap4},
+                {0x1.4p-97, -0x1.d1a5e2df92e9ep4},
+                {0x1.3fffffffffffap-96, -0x1.ccd4de0b6b0b6p4},
+                {0x1.4p-96, -0x1.ccd4de0b6b0b6p4},
+                {0x1.3ffffffffffcdp-95, -0x1.c803d937432dp4},
+                {0x1.4p-95, -0x1.c803d937432cep4},
+                {0x1.3ffffffffffcep-94, -0x1.c332d4631b4e8p4},
+                {0x1.4p-94, -0x1.c332d4631b4e6p4},
+                {0x1.3fffffffffe8cp-93, -0x1.be61cf8ef3706p4},
+                {0x1.4p-93, -0x1.be61cf8ef36fep4},
+                {0x1.3fffffffff983p-92, -0x1.b990cabacb93ap4},
+                {0x1.3ffffffffff45p-92, -0x1.b990cabacb91ap4},
+                {0x1.4p-92, -0x1.b990cabacb916p4},
+                {0x1.3fffffffffffep-91, -0x1.b4bfc5e6a3b2ep4},
+                {0x1.4p-91, -0x1.b4bfc5e6a3b2ep4},
+                {0x1.3fffffffffdd6p-90, -0x1.afeec1127bd52p4},
+                {0x1.4p-90, -0x1.afeec1127bd46p4},
+                {0x1.3fffffffffeebp-89, -0x1.ab1dbc3e53f64p4},
+                {0x1.4p-89, -0x1.ab1dbc3e53f5ep4},
+                {0x1.3ffffffffffa4p-88, -0x1.a64cb76a2c178p4},
+                {0x1.4p-88, -0x1.a64cb76a2c177p4},
+                {0x1.3fffffffffa9bp-87, -0x1.a17bb296043acp4},
+                {0x1.3fffffffffd7cp-87, -0x1.a17bb2960439cp4},
+                {0x1.4p-87, -0x1.a17bb2960438fp4},
+                {0x1.3fffffffffe91p-86, -0x1.9caaadc1dc5aep4},
+                {0x1.3ffffffffffc5p-86, -0x1.9caaadc1dc5a8p4},
+                {0x1.3fffffffffe36p-85, -0x1.97d9a8edb47c8p4},
+                {0x1.3ffffffffffa7p-84, -0x1.9308a4198c9d8p4},
+                {0x1.3ffffffffff7ap-83, -0x1.8e379f4564bf2p4},
+                {0x1.3ffffffffffd7p-82, -0x1.89669a713ce08p4},
+                {0x1.3fffffffffe95p-81, -0x1.8495959d15026p4},
+                {0x1.3ffffffffff4ep-80, -0x1.7fc490c8ed23ap4},
+                {0x1.3ffffffffeafbp-79, -0x1.7af38bf4c54c3p4},
+                {0x1.3ffffffffffd9p-79, -0x1.7af38bf4c544fp4},
+                {0x1.3fffffffffe3bp-78, -0x1.762287209d67p4},
+                {0x1.3ffffffffde65p-77, -0x1.7151824c7593ap4},
+                {0x1.3fffffffffef4p-77, -0x1.7151824c75884p4},
+                {0x1.3ffffffffffadp-76, -0x1.6c807d784da98p4},
+                {0x1.3fffffffffb8bp-75, -0x1.67af78a425cc7p4},
+                {0x1.3ffffffffffaep-75, -0x1.67af78a425cbp4},
+                {0x1.3ffffffffffddp-74, -0x1.62de73cffdec8p4},
+                {0x1.3fffffffffe3fp-73, -0x1.5e0d6efbd60e8p4},
+                {0x1.3ffffffffff54p-72, -0x1.593c6a27ae2fap4},
+                {0x1.3ffffffffffb1p-71, -0x1.546b65538651p4},
+                {0x1.3fffffffff571p-70, -0x1.4f9a607f5e762p4},
+                {0x1.3fffffffffde5p-70, -0x1.4f9a607f5e732p4},
+                {0x1.3fffffffffe9ep-69, -0x1.4ac95bab36946p4},
+                {0x1.3ffffffffffb3p-68, -0x1.45f856d70eb58p4},
+                {0x1.3ffffffffe1d7p-67, -0x1.41275202e6e16p4},
+                {0x1.3ffffffffffb4p-67, -0x1.41275202e6d7p4},
+                {0x1.3fffffffffe44p-66, -0x1.3c564d2ebef9p4},
+                {0x1.3fffffffffd5fp-65, -0x1.3785485a971aep4},
+                {0x1.3fffffffffaadp-64, -0x1.32b443866f3d5p4},
+                {0x1.3fffffffffefep-64, -0x1.32b443866f3bcp4},
+                {0x1.3ffffffffeb35p-63, -0x1.2de33eb247643p4},
+                {0x1.3ffffffffffb7p-63, -0x1.2de33eb2475dp4},
+                {0x1.3ffffffffffe6p-62, -0x1.291239de1f7e8p4},
+                {0x1.3fffffffffdecp-61, -0x1.24413509f7a0ap4},
+                {0x1.3ffffffffff5dp-60, -0x1.1f703035cfc1ap4},
+                {0x1.3ffffffffffbap-59, -0x1.1a9f2b61a7e3p4},
+                {0x1.3fffffffffd92p-58, -0x1.15ce268d80054p4},
+                {0x1.3ffffffffff03p-57, -0x1.10fd21b958264p4},
+                {0x1.3ffffffffe6e9p-56, -0x1.0c2c1ce530503p4},
+                {0x1.3ffffffffffbcp-56, -0x1.0c2c1ce530478p4},
+                {0x1.3ffffffffe2c7p-55, -0x1.075b181108731p4},
+                {0x1.3ffffffffff61p-55, -0x1.075b181108692p4},
+                {0x1.3ffffffffffecp-54, -0x1.028a133ce08a8p4},
+                {0x1.3fffffffff14fp-53, -0x1.fb721cd171621p3},
+                {0x1.3fffffffffff8p-53, -0x1.fb721cd17157ep3},
+                {0x1.3ffffffffdd9dp-52, -0x1.f1d0132921b2dp3},
+                {0x1.3ffffffffffe2p-52, -0x1.f1d01329219bp3},
+                {0x1.3ffffffffebebp-51, -0x1.e82e0980d1ebdp3},
+                {0x1.3fffffffffe2dp-51, -0x1.e82e0980d1df2p3},
+                {0x1.3ffffffffff7p-50, -0x1.de8bffd882214p3},
+                {0x1.3fffffffffaadp-49, -0x1.d4e9f6303267ap3},
+                {0x1.3ffffffffffcdp-49, -0x1.d4e9f6303264p3},
+                {0x1.3fffffffffd77p-48, -0x1.cb47ec87e2a8ap3},
+                {0x1.3fffffffffda5p-48, -0x1.cb47ec87e2a89p3},
+                {0x1.3ffffffffff16p-47, -0x1.c1a5e2df92ea8p3},
+                {0x1.3fffffffff983p-46, -0x1.b803d93743316p3},
+                {0x1.3ffffffffffcfp-46, -0x1.b803d937432dp3},
+                {0x1.3ffffffffffa2p-45, -0x1.ae61cf8ef3702p3},
+                {0x1.3fffffffffbc5p-44, -0x1.a4bfc5e6a3b5ep3},
+                {0x1.3ffffffffffffp-44, -0x1.a4bfc5e6a3b2ep3},
+                {0x1.3fffffffffdd7p-43, -0x1.9b1dbc3e53f76p3},
+                {0x1.3fffffffffebep-42, -0x1.917bb2960439cp3},
+                {0x1.3ffffffffe3f1p-41, -0x1.87d9a8edb48f7p3},
+                {0x1.3ffffffffff77p-41, -0x1.87d9a8edb47c4p3},
+                {0x1.3fffffffff23fp-40, -0x1.7e379f4564c87p3},
+                {0x1.3ffffffffffbdp-40, -0x1.7e379f4564bf2p3},
+                {0x1.3fffffffffe36p-39, -0x1.7495959d15032p3},
+                {0x1.3ffffffffecdbp-38, -0x1.6af38bf4c5523p3},
+                {0x1.3ffffffffffa7p-38, -0x1.6af38bf4c5452p3},
+                {0x1.3ffffffffffd6p-37, -0x1.6151824c7588p3},
+                {0x1.3ffffffffffeep-36, -0x1.57af78a425cafp3},
+                {0x1.3ffffffffdcadp-35, -0x1.4e0d6efbd6268p3},
+                {0x1.3ffffffffffefp-35, -0x1.4e0d6efbd60ep3},
+                {0x1.3fffffffffe68p-34, -0x1.446b65538652p3},
+                {0x1.3ffffffffeafbp-33, -0x1.3ac95bab36a28p3},
+                {0x1.3ffffffffffd9p-33, -0x1.3ac95bab3694p3},
+                {0x1.3ffffffffffdap-32, -0x1.31275202e6d7p3},
+                {0x1.3fffffffffcb5p-31, -0x1.2785485a971c4p3},
+                {0x1.3ffffffffffc4p-31, -0x1.2785485a971a2p3},
+                {0x1.3fffffffffec7p-30, -0x1.1de33eb2475dcp3},
+                {0x1.3ffffffffffaep-29, -0x1.14413509f7a02p3},
+                {0x1.3ffffffffd9a3p-28, -0x1.0a9f2b61a7fd9p3},
+                {0x1.3ffffffffffddp-28, -0x1.0a9f2b61a7e3p3},
+                {0x1.3fffffffff32fp-27, -0x1.00fd21b9582edp3},
+                {0x1.3fffffffffe6dp-27, -0x1.00fd21b95827p3},
+                {0x1.3ffffffffffe4p-26, -0x1.eeb6302210d2p2},
+                {0x1.3ffffffffeb35p-25, -0x1.db721cd17174dp2},
+                {0x1.3fffffffffffcp-25, -0x1.db721cd17157ep2},
+                {0x1.3ffffffffde65p-24, -0x1.c82e0980d20cap2},
+                {0x1.3fffffffffeafp-24, -0x1.c82e0980d1dfcp2},
+                {0x1.3ffffffffed3dp-23, -0x1.b4e9f630327ep2},
+                {0x1.3ffffffffff7fp-23, -0x1.b4e9f6303264ap2},
+                {0x1.3ffffffffffdcp-22, -0x1.a1a5e2df92ea2p2},
+                {0x1.3ffffffffe91bp-21, -0x1.8e61cf8ef38fbp2},
+                {0x1.3ffffffffffffp-21, -0x1.8e61cf8ef36fep2},
+                {0x1.3fffffffffeb2p-20, -0x1.7b1dbc3e53f7bp2},
+                {0x1.3ffffffffe3b7p-19, -0x1.67d9a8edb4a33p2},
+                {0x1.3ffffffffff3dp-19, -0x1.67d9a8edb47dp2},
+                {0x1.3ffffffffe6e9p-18, -0x1.5495959d1524dp2},
+                {0x1.3fffffffffff6p-18, -0x1.5495959d1502p2},
+                {0x1.3ffffffffdb5bp-17, -0x1.4151824c75badp2},
+                {0x1.3ffffffffffebp-17, -0x1.4151824c7588p2},
+                {0x1.3ffffffffe301p-16, -0x1.2e0d6efbd6364p2},
+                {0x1.3ffffffffff11p-16, -0x1.2e0d6efbd60f3p2},
+                {0x1.3fffffffff14fp-15, -0x1.1ac95bab36a85p2},
+                {0x1.3ffffffffff57p-15, -0x1.1ac95bab3694ep2},
+                {0x1.3fffffffff481p-14, -0x1.0785485a9729fp2},
+                {0x1.3fffffffffff9p-14, -0x1.0785485a971ap2},
+                {0x1.3fffffffff571p-13, -0x1.e8826a13ef5d4p1},
+                {0x1.3fffffffffff1p-13, -0x1.e8826a13ef4p1},
+                {0x1.3fffffffffc7bp-12, -0x1.c1fa4372b055ap1},
+                {0x1.3ffffffffffcfp-12, -0x1.c1fa4372b04c6p1},
+                {0x1.3fffffffff189p-11, -0x1.9b721cd171802p1},
+                {0x1.3fffffffffffep-11, -0x1.9b721cd17157ep1},
+                {0x1.3ffffffffe211p-10, -0x1.74e9f63032b72p1},
+                {0x1.3fffffffffff3p-10, -0x1.74e9f6303264p1},
+                {0x1.3fffffffffbc5p-9, -0x1.4e61cf8ef37bbp1},
+                {0x1.3fffffffffff4p-9, -0x1.4e61cf8ef37p1},
+                {0x1.3fffffffff391p-8, -0x1.27d9a8edb49e8p1},
+                {0x1.3ffffffffffe9p-8, -0x1.27d9a8edb47c2p1},
+                {0x1.3fffffffffaadp-7, -0x1.0151824c7596cp1},
+                {0x1.3ffffffffffeap-7, -0x1.0151824c75882p1},
+                {0x1.3fffffffffc7bp-6, -0x1.b592b7566d3b6p0},
+                {0x1.3fffffffffff2p-6, -0x1.b592b7566d282p0},
+                {0x1.3fffffffffda5p-5, -0x1.68826a13ef4dp0},
+                {0x1.3fffffffffff6p-5, -0x1.68826a13ef402p0},
+                {0x1.3fffffffffb8bp-4, -0x1.1b721cd17170ap0},
+                {0x1.3ffffffffffffp-4, -0x1.1b721cd17157ep0},
+                {0x1.3fffffffffcb5p-3, -0x1.9cc39f1de7047p-1},
+                {0x1.3fffffffffff2p-3, -0x1.9cc39f1de6e06p-1},
+                {0x1.3fffffffffc7bp-2, -0x1.02a30498eb36fp-1},
+                {0x1.4p-2, -0x1.02a30498eb0fep-1},
+                {0x1.3fffffffffda5p-1, -0x1.a209a84fbd684p-3},
+                {0x1.3fffffffffffcp-1, -0x1.a209a84fbd002p-3},
+                {0x1.3fffffffffff3p0, 0x1.8cf18388647c5p-4},
+                {0x1.3fffffffffffdp0, 0x1.8cf18388647fbp-4},
+                {0x1.3ffffffffff7bp1, 0x1.977d95ec10b4ap-2},
+                {0x1.3fffffffffffcp1, 0x1.977d95ec10bfcp-2},
+                {0x1.3ffffffffff2bp2, 0x1.65df657b0426dp-1},
+                {0x1.3fffffffffff3p2, 0x1.65df657b042f8p-1},
+                {0x1.3fffffffffc83p4, 0x1.4d104d427dd4ap0},
+                {0x1.3fffffffffff1p4, 0x1.4d104d427de7ap0},
+                {0x1.4p4, 0x1.4d104d427de8p0},
+                {0x1.3ffffffffff2bp5, 0x1.9a209a84fbcb6p0},
+                {0x1.4p5, 0x1.9a209a84fbdp0},
+                {0x1.3fffffffffd23p6, 0x1.e730e7c779a81p0},
+                {0x1.3fffffffffffep6, 0x1.e730e7c779b7ep0},
+                {0x1.4p6, 0x1.e730e7c779b7fp0},
+                {0x1.3ffffffffece3p7, 0x1.1a209a84fb9aep1},
+                {0x1.4p7, 0x1.1a209a84fbdp1},
+                {0x1.3fffffffffeb3p8, 0x1.40a8c1263ac06p1},
+                {0x1.3ffffffffff71p8, 0x1.40a8c1263ac26p1},
+                {0x1.4p8, 0x1.40a8c1263ac3fp1},
+                {0x1.3fffffffffe3bp9, 0x1.6730e7c779b31p1},
+                {0x1.3fffffffffffcp9, 0x1.6730e7c779b7ep1},
+                {0x1.4p9, 0x1.6730e7c779b7fp1},
+                {0x1.3fffffffff657p10, 0x1.8db90e68b8912p1},
+                {0x1.3ffffffffff67p10, 0x1.8db90e68b8aa4p1},
+                {0x1.4p10, 0x1.8db90e68b8abfp1},
+                {0x1.3fffffffff8ffp11, 0x1.b4413509f78c8p1},
+                {0x1.3ffffffffffecp11, 0x1.b4413509f79fcp1},
+                {0x1.4p11, 0x1.b4413509f79ffp1},
+                {0x1.3fffffffffd23p12, 0x1.dac95bab368cp1},
+                {0x1.3ffffffffff5dp12, 0x1.dac95bab36922p1},
+                {0x1.4p12, 0x1.dac95bab3693fp1},
+                {0x1.3fffffffffe13p13, 0x1.00a8c1263ac15p2},
+                {0x1.3fffffffffee2p13, 0x1.00a8c1263ac26p2},
+                {0x1.4p13, 0x1.00a8c1263ac3fp2},
+                {0x1.3fffffffff193p14, 0x1.13ecd476da29fp2},
+                {0x1.3ffffffffffc9p14, 0x1.13ecd476da3dap2},
+                {0x1.4p14, 0x1.13ecd476da3dfp2},
+                {0x1.3fffffffff5b7p15, 0x1.2730e7c779a9bp2},
+                {0x1.3ffffffffff1dp15, 0x1.2730e7c779b6cp2},
+                {0x1.4p15, 0x1.2730e7c779b7fp2},
+                {0x1.3ffffffffec2fp16, 0x1.3a74fb1819167p2},
+                {0x1.3ffffffffffedp16, 0x1.3a74fb181931ep2},
+                {0x1.4p16, 0x1.3a74fb181931fp2},
+                {0x1.3fffffffffb07p17, 0x1.4db90e68b8a51p2},
+                {0x1.3fffffffffecep17, 0x1.4db90e68b8aa4p2},
+                {0x1.4p17, 0x1.4db90e68b8abfp2},
+                {0x1.3ffffffffff2bp18, 0x1.60fd21b95824dp2},
+                {0x1.3ffffffffffb5p18, 0x1.60fd21b958258p2},
+                {0x1.4p18, 0x1.60fd21b95825fp2},
+                {0x1.3ffffffffffe4p19, 0x1.74413509f79fcp2},
+                {0x1.4p19, 0x1.74413509f79ffp2},
+                {0x1.3fffffffff6cfp20, 0x1.8785485a970d3p2},
+                {0x1.3ffffffffffd9p20, 0x1.8785485a9719cp2},
+                {0x1.4p20, 0x1.8785485a9719fp2},
+                {0x1.3ffffffffed47p21, 0x1.9ac95bab3679fp2},
+                {0x1.3fffffffffebap21, 0x1.9ac95bab36922p2},
+                {0x1.4p21, 0x1.9ac95bab3693fp2},
+                {0x1.3fffffffff16bp22, 0x1.ae0d6efbd5f9bp2},
+                {0x1.3ffffffffff8ap22, 0x1.ae0d6efbd60d4p2},
+                {0x1.4p22, 0x1.ae0d6efbd60dfp2},
+                {0x1.3ffffffffe667p23, 0x1.c151824c75646p2},
+                {0x1.3fffffffffffep23, 0x1.c151824c7587ep2},
+                {0x1.4p23, 0x1.c151824c7587fp2},
+                {0x1.3fffffffffff3p24, 0x1.d495959d1501ep2},
+                {0x1.4p24, 0x1.d495959d1501fp2},
+                {0x1.3fffffffffadfp25, 0x1.e7d9a8edb474dp2},
+                {0x1.3fffffffffebdp25, 0x1.e7d9a8edb47a2p2},
+                {0x1.4p25, 0x1.e7d9a8edb47bfp2},
+        };
+
+        for (double[] testCase : testCases) {
+            testLog10Case(testCase[0], testCase[1]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/Log1pTests.java b/ojluni/src/test/java/lang/StrictMath/Log1pTests.java
new file mode 100644
index 0000000..aef135b
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/Log1pTests.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4851638
+ * @summary Tests for StrictMath.log1p
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.StrictMath;
+
+import org.testng.annotations.Test;
+
+/**
+ * The tests in ../Math/Log1pTests.java test properties that should hold for any log1p
+ * implementation, including the FDLIBM-based one required for StrictMath.log1p.  Therefore, the
+ * test cases in ../Math/Log1pTests.java are run against both the Math and StrictMath versions of
+ * log1p.  The role of this test is to verify that the FDLIBM log1p algorithm is being used by
+ * running golden file tests on values that may vary from one conforming log1p implementation to
+ * another.
+ */
+
+public class Log1pTests {
+
+    private Log1pTests() {
+    }
+
+    static void testLog1pCase(double input, double expected) {
+        Tests.test("StrictMath.log1p(double)", input, StrictMath.log1p(input), expected);
+    }
+
+    @Test
+    public void testLog1p() {
+        double[][] testCases = {
+                {0x1.fffffffffffffp-54, 0x1.fffffffffffffp-54},
+                {0x1.fffffffffcc48p-15, 0x1.fffc000aa74f3p-15},
+                {0x1.ffffffffff224p-14, 0x1.fff8002aa8ccfp-14},
+                {0x1.ffffffffff90cp-13, 0x1.fff000aaa23bdp-13},
+                {0x1.fffffffffffcep-4, 0x1.e27076e2af2bap-4},
+                {0x1.fffffffffffffp-2, 0x1.9f323ecbf984bp-2},
+                {0x1.ffffffffffffdp-1, 0x1.62e42fefa39eep-1},
+                {0x1.0p1, 0x1.193ea7aad030ap0},
+                {0x1.ffffffffffffbp1, 0x1.9c041f7ed8d31p0},
+                {0x1.fffffffffffffp2, 0x1.193ea7aad030ap1},
+                {0x1.fffffffffffe1p3, 0x1.6aa6bc1fa7f73p1},
+                {0x1.fffffffffffe1p4, 0x1.bf8d8f4d5b8cap1},
+                {0x1.ffffffffffff1p5, 0x1.0b29293942974p2},
+                {0x1.fffffffffff41p6, 0x1.37072a9b5b6b4p2},
+                {0x1.ffffffffffe65p7, 0x1.63241004e8fdep2},
+                {0x1.ffffffffffca1p8, 0x1.8f60adf041b73p2},
+                {0x1.fffffffffffffp9, 0x1.bbad39ebe1ccp2},
+                {0x1.fffffffffffffp10, 0x1.e801c1698ba43p2},
+                {0x1.ffffffffff2dep11, 0x1.0a2d23e3bb54bp3},
+                {0x1.ffffffffff18dp12, 0x1.205a66eeb4f81p3},
+                {0x1.ffffffffffff9p13, 0x1.368829f0af2dcp3},
+                {0x1.fffffffffbc1ep14, 0x1.4cb62cf069217p3},
+                {0x1.ffffffffffff5p16, 0x1.791282ee99d8ep3},
+                {0x1.fffffffffba46p17, 0x1.8f40bded96cd1p3},
+                {0x1.ffffffffffff7p18, 0x1.a56efcec920cbp3},
+                {0x1.ffffffffffff7p19, 0x1.bb9d3deb8c76ap3},
+                {0x1.ffffffffffff9p20, 0x1.d1cb7fea86bcap3},
+                {0x1.ffffffffffff7p24, 0x1.1542457b37d42p4},
+                {0x1.fffffffffffe7p29, 0x1.4cb5ecf0e964fp4},
+                {0x1.ffffffffffff9p30, 0x1.57cd0e704682p4},
+                {0x1.ffffffffffffbp34, 0x1.8429946e1cf5dp4},
+                {0x1.fffffffffffedp35, 0x1.8f40b5ed9912dp4},
+                {0x1.fffffffffffefp39, 0x1.bb9d3beb8c96ap4},
+                {0x1.fffffffffffe1p40, 0x1.c6b45d6b09abap4},
+                {0x1.fffffffffffe3p44, 0x1.f310e368fe17fp4},
+                {0x1.ffffffffffff5p45, 0x1.fe2804e87b34cp4},
+                {0x1.fffffffffffc5p66, 0x1.7386e22edf4a5p5},
+                {0x1.fffffffffff98p90, 0x1.f89c7428bca5fp5},
+                {0x1.a36e2eb1c317dp-14, 0x1.a368d0657ee51p-14},
+                {0x1.0624dd2f18d5cp-10, 0x1.060354f8c2226p-10},
+                {0x1.ffffffffffffdp-1, 0x1.62e42fefa39eep-1},
+                {0x1.8ffffffffffccp6, 0x1.275e2271bba28p2},
+                {0x1.f3fffffffff1p9, 0x1.ba2909ce4f846p2},
+                {0x1.387ffffffffa8p13, 0x1.26bbed6fbd838p3},
+                {0x1.869ffffffffe4p16, 0x1.7069f7a2d94f4p3},
+                {0x1.e847fffffff3ep19, 0x1.ba18abb1dedbcp3},
+                {0x1.312cfffffff23p23, 0x1.01e3b85ec299p4},
+                {0x1.7d783ffffff17p26, 0x1.26bb1bbe0482ap4},
+                {0x1.dcd64ffffffcep29, 0x1.4b927f3304b3ap4},
+                {0x1.2a05f1ffffa3p33, 0x1.7069e2aa317fep4},
+                {0x1.74876e7ffffbep36, 0x1.9541462195ffap4},
+                {0x1.d1a94a1fffddp39, 0x1.ba18a999000a6p4},
+                {0x1.2309ce53ffed2p43, 0x1.def00d106aa4ep4},
+                {0x1.6bcc41e8ffe73p46, 0x1.01e3b843eaa6cp5},
+                {0x1.c6bf52633fe7dp49, 0x1.144f69ff9ffbep5},
+                {0x1.1c37937e07fffp53, 0x1.26bb1bbb55515p5},
+                {0x1.6345785d89f12p56, 0x1.3926cd770aa62p5},
+                {0x1.bc16d674ec76ap59, 0x1.4b927f32bffb6p5},
+                {0x1.158e460913c51p63, 0x1.5dfe30ee75504p5},
+                {0x1.5af1d78b58badp66, 0x1.7069e2aa2aa58p5},
+                {0x1.b1ae4d6e2ecd4p69, 0x1.82d59465dffap5},
+                {0x1.0f0cf064dd066p73, 0x1.95414621954d6p5},
+                {0x1.52d02c7e14a9p76, 0x1.a7acf7dd4aa4cp5},
+                {0x1.a784379d99c19p79, 0x1.ba18a998fff98p5},
+                {0x1.08b2a2c27fb5p83, 0x1.cc845b54b54bap5},
+                {0x1.4adf4b7320322p86, 0x1.def00d106aa42p5},
+                {0x1.9d971e4fe7b91p89, 0x1.f15bbecc1ff6ap5},
+                {0x1.027e72f1f0ea3p93, 0x1.01e3b843eaa63p6},
+                {0x1.431e0fae6d44bp96, 0x1.0b199121c5512p6},
+                {0x1.93e5939a086bcp99, 0x1.144f69ff9ffb4p6},
+                {0x1.f8def8808ac86p102, 0x1.1d8542dd7aa65p6},
+                {0x1.3b8b5b5056dc7p106, 0x1.26bb1bbb55514p6},
+                {0x1.8a6e32246c76cp109, 0x1.2ff0f4992ffb8p6},
+                {0x1.ed09bead86a07p112, 0x1.3926cd770aa41p6},
+                {0x1.3426172c74d33p116, 0x1.425ca654e550ep6},
+                {0x1.812f9cf791f1ep119, 0x1.4b927f32bffb4p6},
+                {0x1.e17b8435758f2p122, 0x1.54c858109aa3ep6},
+                {0x1.2ced32a169cfap126, 0x1.5dfe30ee754fap6},
+                {0x1.78287f49c497cp129, 0x1.673409cc4ffbp6},
+                {0x1.d6329f1c3492ep132, 0x1.7069e2aa2aa3p6},
+                {0x1.25dfa371a14b8p136, 0x1.799fbb88054f2p6},
+                {0x1.6f578c4e09f0ap139, 0x1.82d59465dffa8p6},
+                {0x1.cb2d6f618c4b4p142, 0x1.8c0b6d43baa4cp6},
+                {0x1.1efc659cf77abp146, 0x1.95414621954eap6},
+                {0x1.66bb7f0435c5bp149, 0x1.9e771eff6ffa6p6},
+                {0x1.c06a5ec5428a4p152, 0x1.a7acf7dd4aa36p6},
+                {0x1.18427b3b49fc9p156, 0x1.b0e2d0bb254f6p6},
+                {0x1.5e531a0a1c729p159, 0x1.ba18a998fff9cp6},
+                {0x1.b5e7e08ca3686p162, 0x1.c34e8276daa4p6},
+                {0x1.11b0ec57e6492p166, 0x1.cc845b54b54f2p6},
+                {0x1.561d276ddfd7dp169, 0x1.d5ba34328ff9ap6},
+                {0x1.aba471495757bp172, 0x1.def00d106aa3p6},
+                {0x1.0b46c6cdd6a8ep176, 0x1.e825e5ee454ddp6},
+                {0x1.4e1878814c5f4p179, 0x1.f15bbecc1ff88p6},
+                {0x1.a19e96a19f65ap182, 0x1.fa9197a9faa2ep6},
+                {0x1.05031e2503cfcp186, 0x1.01e3b843eaa71p7},
+                {0x1.4643e5ae441d2p189, 0x1.067ea4b2d7fb6p7},
+                {0x1.97d4df19d5c5dp192, 0x1.0b199121c5516p7},
+                {0x1.fdca16e04ae24p195, 0x1.0fb47d90b2a65p7},
+                {0x1.3e9e4e4c2f2dap199, 0x1.144f69ff9ffc4p7},
+                {0x1.8e45e1df3ac31p202, 0x1.18ea566e8d514p7},
+                {0x1.f1d75a5709306p205, 0x1.1d8542dd7aa63p7},
+                {0x1.372698766608cp209, 0x1.22202f4c67fcp7},
+                {0x1.84f03e93fef5p212, 0x1.26bb1bbb55508p7},
+                {0x1.e62c4e38fdba1p215, 0x1.2b56082a42a4bp7},
+                {0x1.2fdbb0e39f6b8p219, 0x1.2ff0f4992ffb6p7},
+                {0x1.7bd29d1c875a2p222, 0x1.348be1081d50cp7},
+                {0x1.dac74463a76e9p225, 0x1.3926cd770aa42p7},
+                {0x1.28bc8abe48f57p229, 0x1.3dc1b9e5f7fap7},
+                {0x1.72ebad6ddc67ep232, 0x1.425ca654e550ep7},
+                {0x1.cfa698c952a3ap235, 0x1.46f792c3d2a53p7},
+                {0x1.21c81f7dd42b1p239, 0x1.4b927f32bffb6p7},
+                {0x1.6a3a275d4926bp242, 0x1.502d6ba1ad50ap7},
+                {0x1.c4c8b134970ddp245, 0x1.54c858109aa0ep7},
+                {0x1.61bcca711985dp252, 0x1.5dfe30ee75508p7},
+                {0x1.ba2bfd0d5fe2ap255, 0x1.62991d5d62a5cp7},
+                {0x1.59725db2728b7p262, 0x1.6bcef63b3d4fcp7},
+                {0x1.afcef51f0fa33p265, 0x1.7069e2aa2aa5ap7},
+                {0x1.0de1593368f8cp269, 0x1.7504cf1917f95p7},
+                {0x1.5159af804425ep272, 0x1.799fbb88055p7},
+                {0x1.a5b01b605409p275, 0x1.7e3aa7f6f2a3ep7},
+                {0x1.078e111c34e5bp279, 0x1.82d59465dff9fp7},
+                {0x1.497195634225fp282, 0x1.877080d4cd4f4p7},
+                {0x1.9bcdfabc13053p285, 0x1.8c0b6d43baa4ep7},
+                {0x1.0160bcb58c08cp289, 0x1.90a659b2a7fa7p7},
+                {0x1.41b8ebe2eec13p292, 0x1.95414621954f4p7},
+                {0x1.922726dbaa542p295, 0x1.99dc329082a46p7},
+                {0x1.f6b0f09295714p298, 0x1.9e771eff6ffa3p7},
+                {0x1.3a2e965b9d0b2p302, 0x1.a3120b6e5d4eep7},
+                {0x1.88ba3bf284dd1p305, 0x1.a7acf7dd4aa4ep7},
+                {0x1.32d17ed576f35p312, 0x1.b0e2d0bb254ep7},
+                {0x1.7f85de8ad56bep315, 0x1.b57dbd2a12a44p7},
+                {0x1.df67562d87c5cp318, 0x1.ba18a998fff65p7},
+                {0x1.2ba095dc76db7p322, 0x1.beb39607ed4fp7},
+                {0x1.7688bb5394bd3p325, 0x1.c34e8276daa48p7},
+                {0x1.d42aea2878b45p328, 0x1.c7e96ee5c7f87p7},
+                {0x1.249ad2594989p332, 0x1.cc845b54b54a6p7},
+        };
+
+        for (double[] testCase : testCases) {
+            testLog1pCase(testCase[0], testCase[1]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/MultiplicationTests.java b/ojluni/src/test/java/lang/StrictMath/MultiplicationTests.java
index 3489eee..1d09d17 100644
--- a/ojluni/src/test/java/lang/StrictMath/MultiplicationTests.java
+++ b/ojluni/src/test/java/lang/StrictMath/MultiplicationTests.java
@@ -39,10 +39,13 @@
 // Android-added: testng.
 import org.testng.Assert;
 import org.testng.annotations.Test;
+
 import static org.testng.Assert.fail;
 
 public class MultiplicationTests {
-    private MultiplicationTests(){}
+
+    private MultiplicationTests() {
+    }
 
     // BEGIN Android-removed: randomness, main().
     /*
@@ -99,7 +102,7 @@
         };
 
         for (long[] xy : v) {
-            if(!check(xy[0], xy[1])) {
+            if (!check(xy[0], xy[1])) {
                 failures++;
             }
         }
diff --git a/ojluni/src/test/java/lang/StrictMath/PowTests.java b/ojluni/src/test/java/lang/StrictMath/PowTests.java
new file mode 100644
index 0000000..379b40c
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/PowTests.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8136874
+ * @summary Tests for StrictMath.pow
+ * @author Joseph D. Darcy
+ */
+package test.java.lang.StrictMath;
+
+import org.testng.annotations.Test;
+
+/**
+ * The tests in ../Math/PowTests.java test properties that should hold for any pow implementation,
+ * including the FDLIBM-based one required for StrictMath.pow.  Therefore, the test cases in
+ * ../Math/PowTests.java are run against both the Math and StrictMath versions of pow.  The role of
+ * this test is to verify that the FDLIBM pow algorithm is being used by running golden file tests
+ * on values that may vary from one conforming pow implementation to another.
+ */
+
+public class PowTests {
+
+    private PowTests() {
+    }
+
+    private static final double INFINITY = Double.POSITIVE_INFINITY;
+
+    @Test
+    public void testPow() {
+        double[][] testCases = {
+                // Probe near decision points of the fdlibm algorithm
+
+                {0x1.00000_0000_0001p1,  // |x| > 1.0
+                        INFINITY,               // infinity
+                        INFINITY                // 0
+                },
+
+                {0x1.fffffp-1,           // |x| = 0.9999995231628418
+                        0x1.0p31,               // 2^31
+                        0.0                     // 0
+                },
+
+                {0x1.ffffe_ffffffffp-1,  // |x| < 0.9999995231628418
+                        0x1.0p31,               // 2^31
+                        0.0                     // 0
+                },
+
+                {-0x1.ffffe_ffffffffp-1, // |x| < 0.9999995231628418
+                        0x1.0p31,               // 2^31
+                        0.0                     // 0
+                },
+
+                {0x1.fffffp-1,           // |x| = 0.9999995231628418
+                        0x1.0000000000001p31,   // nextUp(2^31)
+                        0.0                     // 0
+                },
+
+                {0x1.fffffp-1,           // |x| = 0.9999995231628418
+                        0x1.0p31 + 1.0,         // 2^31 + 1, odd integer
+                        0.0                     // 0
+                },
+
+                {0x1.fffffp-1,           // |x| = 0.9999995231628418
+                        0x1.0p31 + 2.0,         // 2^31 + 2, even integer
+                        0.0                     // 0
+                },
+
+                {0x1.ffffe_ffffffffp-1,  // |x| < 0.9999995231628418
+                        0x1.0000000000001p31,   // nextUp(2^31)
+                        0.0                     // 0
+                },
+
+                {-0x1.ffffe_ffffffffp-1, // |x| < 0.9999995231628418
+                        0x1.0000000000001p31,   // nextUp(2^31)
+                        Double.NaN              // 0
+                },
+
+                {-0x1.ffffe_ffffffffp-1, // |x| < 0.9999995231628418
+                        0x1.0p31 + 1.0,         // 2^31 + 1, odd integer
+                        -0.0                    // 0
+                },
+
+                {-0x1.ffffe_ffffffffp-1, // |x| < 0.9999995231628418
+                        0x1.0p31 + 2.0,         // 2^31 + 2, even integer
+                        0.0                     // 0
+                },
+
+                {0x1.0000000000001p0,    // nextUp(1)
+                        0x1.0000000000001p31,   // nextUp(2^31)
+                        0x1.00000800002p0
+                },
+
+                {0x1.0000000000001p0,    // nextUp(1)
+                        -0x1.0000000000001p31,  // -nextUp(2^31)
+                        0x1.fffff000004p-1
+                },
+
+                {-0x1.0000000000001p0,   // -nextUp(1)
+                        -0x1.0000000000001p31,  // -nextUp(2^31)
+                        Double.NaN
+                },
+
+                {-0x1.0000000000001p0,   // -nextUp(1)
+                        0x1.0p31 + 1.0,         // 2^31 + 1, odd integer
+                        -0x1.0000080000201p0
+                },
+
+                {-0x1.0000000000001p0,   // -nextUp(1)
+                        0x1.0p31 + 2.0,         // 2^31 + 2, even integer
+                        0x1.0000080000202p0
+                },
+
+                {0x1.00000_ffff_ffffp0,
+                        0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                // Huge y, |y| > 0x1.00000_ffff_ffffp31 ~2**31 is a decision point
+
+                // First y = 0x1.00001_0000_0000p31
+                {0x1.fffff_ffff_ffffp-1,
+                        0x1.00001_0000_0000p31,
+                        0x1.fffff7ffff9p-1
+                },
+
+                {0x1.fffff_ffff_fffep-1,
+                        0x1.00001_0000_0000p31,
+                        0x1.ffffefffff4p-1
+                },
+
+                {0x1.fffff_0000_0000p-1,
+                        0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                //  Cycle through decision points on x values
+
+                {0x1.fffff_0000_0000p-1,
+                        0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {-0x1.fffff_0000_0000p-1,
+                        0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {0x1.ffffe_ffff_ffffp-1,
+                        0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {-0x1.ffffe_ffff_ffffp-1,
+                        0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {0x1.00000_ffff_ffffp0,
+                        0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                {0x1.00001_0000_0000p0,
+                        0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                {-0x1.00000_ffff_ffffp0,
+                        0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                {-0x1.00001_0000_0000p0,
+                        0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                // Now y = -0x1.00001_0000_0000p31
+
+                {0x1.fffff_0000_0000p-1,
+                        -0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                {-0x1.fffff_0000_0000p-1,
+                        0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {0x1.ffffe_ffff_ffffp-1,
+                        -0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                {-0x1.ffffe_ffff_ffffp-1,
+                        -0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                {0x1.00000_ffff_ffffp0,
+                        -0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {0x1.00001_0000_0000p0,
+                        -0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {-0x1.00000_ffff_ffffp0,
+                        -0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {-0x1.00001_0000_0000p0,
+                        -0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                //-----------------------
+
+                {0x1.ffffe_ffff_ffffp-1,
+                        -0x1.00001_0000_0000p31,
+                        INFINITY
+                },
+
+                {0x1.00001_0000_0000p0,
+                        -0x1.00001_0000_0000p31,
+                        0.0
+                },
+
+                {0x1.0000000000002p0, // 1.0000000000000004
+                        0x1.f4add4p30,       // 2.1E9
+                        0x1.00000fa56f1a6p0  // 1.0000009325877754
+                },
+
+                // Verify no early overflow
+                {0x1.0000000000002p0, // 1.0000000000000004
+                        0x1.0642acp31,       // 2.2E9
+                        0x1.000010642b465p0, // 1.0000009769967388
+                },
+
+                // Verify proper overflow
+                {0x1.0000000000002p0,    // 1.0000000000000004
+                        0x1.62e42fefa39fp60,    // 1.59828858065033216E18
+                        0x1.ffffffffffd9fp1023, // 1.7976931348621944E308
+                },
+
+        };
+
+        for (double[] testCase : testCases) {
+            testPowCase(testCase[0], testCase[1], testCase[2]);
+        }
+    }
+
+    private static void testPowCase(double input1, double input2, double expected) {
+        Tests.test("StrictMath.pow(double)", input1, input2,
+                StrictMath.pow(input1, input2), expected);
+    }
+}
diff --git a/ojluni/src/test/java/lang/StrictMath/Tests.java b/ojluni/src/test/java/lang/StrictMath/Tests.java
new file mode 100644
index 0000000..a144edb
--- /dev/null
+++ b/ojluni/src/test/java/lang/StrictMath/Tests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ *
+ *
+ * Shared static test method for StrictMath tests.
+ */
+package test.java.lang.StrictMath;
+
+import org.testng.Assert;
+
+public class Tests {
+
+    private Tests() {
+    }
+
+    static void test(String testName, double input, double result, double expected) {
+        Assert.assertEquals(Double.compare(expected, result), 0,
+                "Failure for " + testName + ":\n" +
+                        "\tFor input " + input + "\t(" + Double.toHexString(input) + ")\n" +
+                        "\texpected  " + expected + "\t(" + Double.toHexString(expected) + ")\n" +
+                        "\tgot       " + result + "\t(" + Double.toHexString(result) + ").");
+    }
+
+    static void test(String testName, double input1, double input2, double result,
+            double expected) {
+        Assert.assertEquals(Double.compare(expected, result), 0,
+                "Failure for " + testName + ":\n" +
+                        "\tFor input " + input1 + "\t(" + Double.toHexString(input1) + "), " +
+                        +input2 + "\t(" + Double.toHexString(input2) + ")\n" +
+                        "\texpected  " + expected + "\t(" + Double.toHexString(expected) + ")\n" +
+                        "\tgot       " + result + "\t(" + Double.toHexString(result) + ").");
+    }
+
+    /**
+     * Returns a double over the normalized range of floating-point values.
+     *
+     * @return a double over the normalized range of floating-point values
+     */
+    static double createRandomDouble(java.util.Random random) {
+        final int EXPONENT_RANGE = Double.MAX_EXPONENT - Double.MIN_EXPONENT + 1;
+
+        int targetExponent = Double.MIN_EXPONENT + random.nextInt(EXPONENT_RANGE + 1);
+        double tmp = random.nextDouble(); // Double in the range of [0.0, 1.0)
+        int tmpExponent = Math.getExponent(tmp);
+        return Math.scalb(tmp, targetExponent - tmpExponent);
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/Chars.java b/ojluni/src/test/java/lang/String/Chars.java
new file mode 100644
index 0000000..1287435
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/Chars.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+    @test
+    @bug 8054307
+    @summary test chars() and codePoints()
+*/
+package test.java.lang.String;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+public class Chars {
+
+    @Test
+    public void testCharsAndCodePoints() {
+        Random r = new Random();
+        for (int i = 0; i < 10; i++) {
+            int n = 100 + r.nextInt(100);
+            char[] cc = new char[n];
+            int[]  ccExp = new int[n];
+            int[]  cpExp = new int[n];
+            // latin1
+            for (int j = 0; j < n; j++) {
+                cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x80));
+            }
+            testChars(cc, ccExp);
+            testCPs(cc, cpExp);
+
+            // bmp without surrogates
+            for (int j = 0; j < n; j++) {
+                cc[j] = (char)(ccExp[j] = cpExp[j] = r.nextInt(0x8000));
+            }
+            testChars(cc, ccExp);
+            testCPs(cc, cpExp);
+
+            // bmp with surrogates
+            int k = 0;
+            for (int j = 0; j < n; j++) {
+                if (j % 9 ==  5 && j + 1 < n) {
+                    int cp = 0x10000 + r.nextInt(2000);
+                    cpExp[k++] = cp;
+                    Character.toChars(cp, cc, j);
+                    ccExp[j] = cc[j];
+                    ccExp[j + 1] = cc[j + 1];
+                    j++;
+                } else {
+                    cc[j] = (char)(ccExp[j] = cpExp[k++] = r.nextInt(0x8000));
+                }
+            }
+            cpExp = Arrays.copyOf(cpExp, k);
+            testChars(cc, ccExp);
+            testCPs(cc, cpExp);
+        }
+    }
+
+    static void testChars(char[] cc, int[] expected) {
+        String str = new String(cc);
+        if (!Arrays.equals(expected, str.chars().toArray())) {
+            throw new RuntimeException("chars/codePoints() failed!");
+        }
+    }
+
+    static void testCPs(char[] cc, int[] expected) {
+        String str = new String(cc);
+        if (!Arrays.equals(expected, str.codePoints().toArray())) {
+            throw new RuntimeException("chars/codePoints() failed!");
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/CharAt.java b/ojluni/src/test/java/lang/String/CompactString/CharAt.java
new file mode 100644
index 0000000..0e260cb
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/CharAt.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import java.util.stream.IntStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.charAt.
+ * @run testng/othervm -XX:+CompactStrings CharAt
+ * @run testng/othervm -XX:-CompactStrings CharAt
+ */
+
+public class CharAt extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_L1, new char[] { 'A' } },
+                new Object[] { STRING_L2, new char[] { 'A', 'B' } },
+                new Object[] { STRING_L4, new char[] { 'A', 'B', 'C', 'D' } },
+                new Object[] { STRING_LLONG,
+                        new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new char[] { '\uFF21' } },
+                new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCharAt(String str, char[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            IntStream
+                                    .range(0, str.length())
+                                    .forEach(
+                                            i -> assertEquals(
+                                                    str.charAt(i),
+                                                    expected[i],
+                                                    String.format(
+                                                            "testing String(%s).charAt(%d), source : %s, ",
+                                                            escapeNonASCIIs(data),
+                                                            i, source)));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/CodePointAt.java b/ojluni/src/test/java/lang/String/CompactString/CodePointAt.java
new file mode 100644
index 0000000..894e13a
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/CodePointAt.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import java.util.stream.IntStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.codePointAt.
+ * @run testng/othervm -XX:+CompactStrings CodePointAt
+ * @run testng/othervm -XX:-CompactStrings CodePointAt
+ */
+
+public class CodePointAt extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_L1, new int[] { 'A' } },
+                new Object[] { STRING_L2, new int[] { 'A', 'B' } },
+                new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } },
+                new Object[] { STRING_LLONG,
+                        new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new int[] { '\uFF21' } },
+                new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } },
+                new Object[] {
+                        STRING_SUPPLEMENTARY,
+                        new int[] { Character.toCodePoint('\uD801', '\uDC00'),
+                                '\uDC00',
+                                Character.toCodePoint('\uD801', '\uDC01'),
+                                '\uDC01', '\uFF21', 'A' }, } };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCodePointAt(String str, int[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            IntStream
+                                    .range(0, str.length())
+                                    .forEach(
+                                            i -> assertEquals(
+                                                    str.codePointAt(i),
+                                                    expected[i],
+                                                    String.format(
+                                                            "testing String(%s).codePointAt(%d), source : %s, ",
+                                                            escapeNonASCIIs(data),
+                                                            i, source)));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/CodePointBefore.java b/ojluni/src/test/java/lang/String/CompactString/CodePointBefore.java
new file mode 100644
index 0000000..740d00c
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/CodePointBefore.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import java.util.stream.IntStream;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.codePointBefore.
+ * @run testng/othervm -XX:+CompactStrings CodePointBefore
+ * @run testng/othervm -XX:-CompactStrings CodePointBefore
+ */
+
+public class CodePointBefore extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_L1, new int[] { 'A' } },
+                new Object[] { STRING_L2, new int[] { 'A', 'B' } },
+                new Object[] { STRING_L4, new int[] { 'A', 'B', 'C', 'D' } },
+                new Object[] { STRING_LLONG,
+                        new int[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new int[] { '\uFF21' } },
+                new Object[] { STRING_U2, new int[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new int[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new int[] { 'A', '\uFF21' } },
+                new Object[] {
+                        STRING_SUPPLEMENTARY,
+                        new int[] { '\uD801', Character.toCodePoint('\uD801', '\uDC00'),
+                                '\uD801', Character.toCodePoint('\uD801', '\uDC01'),
+                                '\uFF21', 'A' }, } };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCodePointBefore(String str, int[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            IntStream
+                                    .range(0, str.length())
+                                    .forEach(
+                                            i -> assertEquals(
+                                                    str.codePointBefore(i + 1),
+                                                    expected[i],
+                                                    String.format(
+                                                            "testing String(%s).codePointBefore(%d), source : %s, ",
+                                                            escapeNonASCIIs(data),
+                                                            i + 1, source)));
+                        });
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/CodePointCount.java b/ojluni/src/test/java/lang/String/CompactString/CodePointCount.java
new file mode 100644
index 0000000..5f24c3b
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/CodePointCount.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.codePointCount.
+ * @run testng/othervm -XX:+CompactStrings CodePointCount
+ * @run testng/othervm -XX:-CompactStrings CodePointCount
+ */
+
+public class CodePointCount extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] { new Object[] { STRING_EMPTY, 0, 0, 0 },
+                new Object[] { STRING_L1, 0, 1, 1 },
+                new Object[] { STRING_L1, 1, 1, 0 },
+                new Object[] { STRING_L2, 0, 2, 2 },
+                new Object[] { STRING_L2, 0, 1, 1 },
+                new Object[] { STRING_L2, 1, 2, 1 },
+                new Object[] { STRING_L4, 0, 4, 4 },
+                new Object[] { STRING_L4, 0, 1, 1 },
+                new Object[] { STRING_L4, 2, 4, 2 },
+                new Object[] { STRING_LLONG, 0, 8, 8 },
+                new Object[] { STRING_LLONG, 0, 5, 5 },
+                new Object[] { STRING_LLONG, 4, 8, 4 },
+                new Object[] { STRING_LLONG, 0, 7, 7 },
+                new Object[] { STRING_U1, 0, 1, 1 },
+                new Object[] { STRING_U2, 0, 2, 2 },
+                new Object[] { STRING_U2, 0, 1, 1 },
+                new Object[] { STRING_U2, 1, 2, 1 },
+                new Object[] { STRING_M12, 0, 2, 2 },
+                new Object[] { STRING_M12, 0, 1, 1 },
+                new Object[] { STRING_M12, 1, 2, 1 },
+                new Object[] { STRING_M11, 0, 2, 2 },
+                new Object[] { STRING_M11, 0, 1, 1 },
+                new Object[] { STRING_M11, 1, 2, 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 1, 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 2, 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 3, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 5, 3 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 6, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 4, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 6, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 4, 1 },};
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCodePointCount(String str, int beginIndex, int endIndex,
+            int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.codePointCount(beginIndex, endIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).codePointCount(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), beginIndex,
+                                            endIndex, source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/CompactString.java b/ojluni/src/test/java/lang/String/CompactString/CompactString.java
new file mode 100644
index 0000000..1c67172
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/CompactString.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.lang.String.CompactString;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.testng.annotations.BeforeClass;
+
+/*
+ * Base class of tests for Compact String.
+ *
+ */
+public class CompactString {
+
+    final Map<String, Map<String, String>> map = new HashMap<>();
+
+    enum StringSources {
+        EMPTY(STRING_EMPTY, BYTE_ARRAY_EMTPY, CHAR_ARRAY_EMPTY,
+                POINT_ARRAY_EMTPY), LDUPLICATE(STRING_LDUPLICATE,
+                BYTE_ARRAY_LDUPLICATE, CHAR_ARRAY_LDUPLICATE,
+                POINT_ARRAY_LDUPLICATE), LLONG(STRING_LLONG, BYTE_ARRAY_LLONG,
+                CHAR_ARRAY_LLONG, POINT_ARRAY_LLONG), L1(STRING_L1,
+                BYTE_ARRAY_L1, CHAR_ARRAY_L1, POINT_ARRAY_L1), L2(STRING_L2,
+                BYTE_ARRAY_L2, CHAR_ARRAY_L2, POINT_ARRAY_L2), L4(STRING_L4,
+                BYTE_ARRAY_L4, CHAR_ARRAY_L4, POINT_ARRAY_L4), UDUPLICATE(
+                STRING_UDUPLICATE, BYTE_ARRAY_UDUPLICATE,
+                CHAR_ARRAY_UDUPLICATE, POINT_ARRAY_UDUPLICATE), U1(STRING_U1,
+                BYTE_ARRAY_U1, CHAR_ARRAY_U1, POINT_ARRAY_U1), U2(STRING_U2,
+                BYTE_ARRAY_U2, CHAR_ARRAY_U2, POINT_ARRAY_U2), MDUPLICATE1(
+                STRING_MDUPLICATE1, BYTE_ARRAY_MDUPLICATE1,
+                CHAR_ARRAY_MDUPLICATE1, POINT_ARRAY_MDUPLICATE1), MDUPLICATE2(
+                STRING_MDUPLICATE2, BYTE_ARRAY_MDUPLICATE2,
+                CHAR_ARRAY_MDUPLICATE2, POINT_ARRAY_MDUPLICATE2), MLONG1(
+                STRING_MLONG1, BYTE_ARRAY_MLONG1, CHAR_ARRAY_MLONG1,
+                POINT_ARRAY_MLONG1), MLONG2(STRING_MLONG2, BYTE_ARRAY_MLONG2,
+                CHAR_ARRAY_MLONG2, POINT_ARRAY_MLONG2), M11(STRING_M11,
+                BYTE_ARRAY_M11, CHAR_ARRAY_M11, POINT_ARRAY_M11), M12(
+                STRING_M12, BYTE_ARRAY_M12, CHAR_ARRAY_M12, POINT_ARRAY_M12), SUPPLEMENTARY(
+                STRING_SUPPLEMENTARY, BYTE_ARRAY_SUPPLEMENTARY,
+                CHAR_ARRAY_SUPPLEMENTARY, POINT_ARRAY_SUPPLEMENTARY), SUPPLEMENTARY_LOWERCASE(
+                STRING_SUPPLEMENTARY_LOWERCASE,
+                BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE,
+                CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE,
+                POINT_ARRAY_SUPPLEMENTARY_LOWERCASE);
+
+        private StringSources(String s, byte[] b, char[] c, int[] i) {
+            str = s;
+            ba = b;
+            ca = c;
+            ia = i;
+        }
+
+        String getString() {
+            return str;
+        }
+
+        byte[] getByteArray() {
+            return ba;
+        }
+
+        char[] getCharArray() {
+            return ca;
+        }
+
+        int[] getIntArray() {
+            return ia;
+        }
+
+        private final String str;
+        private final byte[] ba;
+        private final char[] ca;
+        private final int[] ia;
+    }
+
+    protected static final String DEFAULT_CHARSET_NAME = "UTF-8";
+    protected static final Charset DEFAULT_CHARSET = Charset
+            .forName(DEFAULT_CHARSET_NAME);
+
+    protected static final String STRING_EMPTY = "";
+    protected static final byte[] BYTE_ARRAY_EMTPY = new byte[0];
+    protected static final char[] CHAR_ARRAY_EMPTY = new char[0];
+    protected static final int[] POINT_ARRAY_EMTPY = new int[0];
+
+    protected static final String STRING_LDUPLICATE = "ABABABABAB";
+    protected static final byte[] BYTE_ARRAY_LDUPLICATE = new byte[] { 'A', 'B',
+            'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
+    protected static final char[] CHAR_ARRAY_LDUPLICATE = new char[] { 'A', 'B',
+            'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
+    protected static final int[] POINT_ARRAY_LDUPLICATE = new int[] { 'A', 'B',
+            'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B' };
+
+    protected static final String STRING_LLONG = "ABCDEFGH";
+    protected static final byte[] BYTE_ARRAY_LLONG = new byte[] { 'A', 'B', 'C',
+            'D', 'E', 'F', 'G', 'H' };
+    protected static final char[] CHAR_ARRAY_LLONG = new char[] { 'A', 'B', 'C',
+            'D', 'E', 'F', 'G', 'H' };
+    protected static final int[] POINT_ARRAY_LLONG = new int[] { 'A', 'B', 'C',
+            'D', 'E', 'F', 'G', 'H' };
+
+    protected static final String STRING_L1 = "A";
+    protected static final byte[] BYTE_ARRAY_L1 = new byte[] { 'A' };
+    protected static final char[] CHAR_ARRAY_L1 = new char[] { 'A' };
+    protected static final int[] POINT_ARRAY_L1 = new int[] { 'A' };
+
+    protected static final String STRING_L2 = "AB";
+    protected static final byte[] BYTE_ARRAY_L2 = new byte[] { 'A', 'B' };
+    protected static final char[] CHAR_ARRAY_L2 = new char[] { 'A', 'B' };
+    protected static final int[] POINT_ARRAY_L2 = new int[] { 'A', 'B' };
+
+    protected static final String STRING_L4 = "ABCD";
+    protected static final byte[] BYTE_ARRAY_L4 = new byte[] { 'A', 'B', 'C', 'D' };
+    protected static final char[] CHAR_ARRAY_L4 = new char[] { 'A', 'B', 'C', 'D' };
+    protected static final int[] POINT_ARRAY_L4 = new int[] { 'A', 'B', 'C', 'D' };
+
+    /*
+     * Because right now ASCII is the default encoding parameter for source code
+     * in JDK build environment, so we escape them. same as below.
+     */
+    protected static final String STRING_UDUPLICATE = "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22";
+    protected static final byte[] BYTE_ARRAY_UDUPLICATE = getBytes(STRING_UDUPLICATE);
+    protected static final char[] CHAR_ARRAY_UDUPLICATE = new char[] { '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22' };
+    protected static final int[] POINT_ARRAY_UDUPLICATE = new int[] { '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22', '\uFF21', '\uFF22', '\uFF21',
+            '\uFF22', '\uFF21', '\uFF22' };
+
+    protected static final String STRING_U1 = "\uFF21";
+    protected static final byte[] BYTE_ARRAY_U1 = getBytes(STRING_U1);
+    protected static final char[] CHAR_ARRAY_U1 = new char[] { '\uFF21' };
+    protected static final int[] POINT_ARRAY_U1 = new int[] { '\uFF21' };
+
+    protected static final String STRING_U2 = "\uFF21\uFF22";
+    protected static final byte[] BYTE_ARRAY_U2 = getBytes(STRING_U2);
+    protected static final char[] CHAR_ARRAY_U2 = new char[] { '\uFF21', '\uFF22' };
+    protected static final int[] POINT_ARRAY_U2 = new int[] { '\uFF21', '\uFF22' };
+
+    protected static final String STRING_MDUPLICATE1 = "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A";
+    protected static final byte[] BYTE_ARRAY_MDUPLICATE1 = getBytes(STRING_MDUPLICATE1);
+    protected static final char[] CHAR_ARRAY_MDUPLICATE1 = new char[] { '\uFF21',
+            'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' };
+    protected static final int[] POINT_ARRAY_MDUPLICATE1 = new int[] { '\uFF21',
+            'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A' };
+
+    protected static final String STRING_MDUPLICATE2 = "A\uFF21A\uFF21A\uFF21A\uFF21A\uFF21";
+    protected static final byte[] BYTE_ARRAY_MDUPLICATE2 = getBytes(STRING_MDUPLICATE2);
+    protected static final char[] CHAR_ARRAY_MDUPLICATE2 = new char[] { 'A',
+            '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A',
+            '\uFF21' };
+    protected static final int[] POINT_ARRAY_MDUPLICATE2 = new int[] { 'A',
+            '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A', '\uFF21', 'A',
+            '\uFF21' };
+
+    protected static final String STRING_MLONG1 = "A\uFF21B\uFF22C\uFF23D\uFF24E\uFF25F\uFF26G\uFF27H\uFF28";
+    protected static final byte[] BYTE_ARRAY_MLONG1 = getBytes(STRING_MLONG1);
+    protected static final char[] CHAR_ARRAY_MLONG1 = new char[] { 'A', '\uFF21',
+            'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F',
+            '\uFF26', 'G', '\uFF27', 'H', '\uFF28' };
+    protected static final int[] POINT_ARRAY_MLONG1 = new int[] { 'A', '\uFF21',
+            'B', '\uFF22', 'C', '\uFF23', 'D', '\uFF24', 'E', '\uFF25', 'F',
+            '\uFF26', 'G', '\uFF27', 'H', '\uFF28' };
+
+    protected static final String STRING_MLONG2 = "\uFF21A\uFF22B\uFF23C\uFF24D\uFF25E\uFF26F\uFF27G\uFF28H";
+    protected static final byte[] BYTE_ARRAY_MLONG2 = getBytes(STRING_MLONG2);
+    protected static final char[] CHAR_ARRAY_MLONG2 = new char[] { '\uFF21', 'A',
+            '\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E',
+            '\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' };
+    protected static final int[] POINT_ARRAY_MLONG2 = new int[] { '\uFF21', 'A',
+            '\uFF22', 'B', '\uFF23', 'C', '\uFF24', 'D', '\uFF25', 'E',
+            '\uFF26', 'F', '\uFF27', 'G', '\uFF28', 'H' };
+
+    protected static final String STRING_M11 = "A\uFF21";
+    protected static final byte[] BYTE_ARRAY_M11 = getBytes(STRING_M11);
+    protected static final char[] CHAR_ARRAY_M11 = new char[] { 'A', '\uFF21' };
+    protected static final int[] POINT_ARRAY_M11 = new int[] { 'A', '\uFF21' };
+
+    protected static final String STRING_M12 = "\uFF21A";
+    protected static final byte[] BYTE_ARRAY_M12 = getBytes(STRING_M12);
+    protected static final char[] CHAR_ARRAY_M12 = new char[] { '\uFF21', 'A' };
+    protected static final int[] POINT_ARRAY_M12 = new int[] { '\uFF21', 'A' };
+
+    protected static final String STRING_SUPPLEMENTARY = "\uD801\uDC00\uD801\uDC01\uFF21A";
+    protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY = getBytes(STRING_SUPPLEMENTARY);
+    protected static final char[] CHAR_ARRAY_SUPPLEMENTARY = new char[] {
+            '\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' };
+    protected static final int[] POINT_ARRAY_SUPPLEMENTARY = new int[] {
+            '\uD801', '\uDC00', '\uD801', '\uDC01', '\uFF21', 'A' };
+
+    protected static final String STRING_SUPPLEMENTARY_LOWERCASE = "\uD801\uDC28\uD801\uDC29\uFF41a";
+    protected static final byte[] BYTE_ARRAY_SUPPLEMENTARY_LOWERCASE = getBytes(STRING_SUPPLEMENTARY_LOWERCASE);
+    protected static final char[] CHAR_ARRAY_SUPPLEMENTARY_LOWERCASE = new char[] {
+            '\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' };
+    protected static final int[] POINT_ARRAY_SUPPLEMENTARY_LOWERCASE = new int[] {
+            '\uD801', '\uDC28', '\uD801', '\uDC29', '\uFF41', 'a' };
+
+    protected static final String SRC_BYTE_ARRAY_WITH_CHARSETNAME = "source from byte array with charset name";
+    protected static final String SRC_BYTE_ARRAY_WITH_CHARSET = "source from byte array with charset";
+    protected static final String SRC_CHAR_ARRAY = "source from char array";
+    protected static final String SRC_POINT_ARRAY = "source from code point array";
+    protected static final String SRC_STRING = "source from String";
+    protected static final String SRC_STRINGBUFFER = "source from StringBuffer";
+    protected static final String SRC_STRINGBUILDER = "source from StringBuilder";
+    protected static final String SRC_COPYVALUEOF = "source from copyValueOf from char array";
+    protected static final String SRC_VALUEOF = "source from valueOf from char array";
+
+    static {
+        System.out
+                .println(String
+                        .format("====== The platform's default charset is \"%s\", we're using \"%s\" for testing.",
+                                Charset.defaultCharset().name(),
+                                DEFAULT_CHARSET_NAME));
+    }
+
+    private static byte[] getBytes(String str) {
+        byte[] res = null;
+        try {
+            res = str.getBytes(DEFAULT_CHARSET_NAME);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            throw new RuntimeException("caught UnsupportedEncodingException!!!", e);
+        }
+        return res;
+    }
+
+    private void setUpOneString(String content, byte[] ba, char[] ca, int[] cpa)
+            throws UnsupportedEncodingException {
+        final Map<String, String> m = new HashMap<>();
+        m.put(SRC_BYTE_ARRAY_WITH_CHARSETNAME, new String(ba,
+                DEFAULT_CHARSET_NAME));
+        m.put(SRC_BYTE_ARRAY_WITH_CHARSET, new String(ba, DEFAULT_CHARSET));
+        m.put(SRC_CHAR_ARRAY, new String(ca));
+        m.put(SRC_POINT_ARRAY, new String(cpa, 0, cpa.length));
+        m.put(SRC_STRING, new String(content));
+        m.put(SRC_STRINGBUFFER, new String(new StringBuffer(content)));
+        m.put(SRC_STRINGBUILDER, new String(new StringBuilder(content)));
+        m.put(SRC_COPYVALUEOF, String.copyValueOf(ca));
+        m.put(SRC_VALUEOF, String.valueOf(ca));
+        map.put(content, m);
+    }
+
+    /*
+     * Set up the test data, use 9 ways to construct one String.
+     *
+     * @throws UnsupportedEncodingException
+     *         If the named charset is not supported in setUpOneString(xxx).
+     */
+    @BeforeClass
+    public void setUp() throws UnsupportedEncodingException {
+        for (StringSources src : StringSources.values()) {
+            setUpOneString(src.getString(), src.getByteArray(),
+                    src.getCharArray(), src.getIntArray());
+        }
+    }
+
+    /*
+     * Escape non-ASCII characters since not all systems support them.
+     */
+    protected String escapeNonASCIIs(String str) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < str.length(); i++) {
+            char c = str.charAt(i);
+            if (c > 0x7F) {
+                sb.append("\\u").append(Integer.toHexString((int) c));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /*
+     * Escape non-ASCII characters since not all systems support them.
+     */
+    protected String escapeNonASCII(char c) {
+        StringBuilder sb = new StringBuilder();
+        if (c > 0x7F) {
+            sb.append("\\u").append(Integer.toHexString((int) c));
+        } else {
+            sb.append(c);
+        }
+        return sb.toString();
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/CompareTo.java b/ojluni/src/test/java/lang/String/CompactString/CompareTo.java
new file mode 100644
index 0000000..8121789
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/CompareTo.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559 8137326
+ * @summary Tests Compact String. Verifies the compareTo method for String,
+ * StringBuilder and StringBuffer.
+ * @run testng/othervm -XX:+CompactStrings CompareTo
+ * @run testng/othervm -XX:-CompactStrings CompareTo
+ */
+
+public class CompareTo extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_EMPTY, "\uFF21", -1 },
+                new Object[] { STRING_L1, "AB", -1 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "a", -32 },
+                new Object[] { STRING_L1, "\uFF21", -65248 },
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "Ab", -32 },
+                new Object[] { STRING_L2, "AA", 1 },
+                new Object[] { STRING_L2, "\uFF21", -65248 },
+                new Object[] { STRING_L2, "A\uFF21", -65247 },
+                new Object[] { STRING_L4, "ABC", 1 },
+                new Object[] { STRING_L4, "AB", 2 },
+                new Object[] { STRING_L4, "ABcD", -32 },
+                new Object[] { STRING_L4, "ABCD\uFF21\uFF21", -2 },
+                new Object[] { STRING_L4, "ABCD\uFF21", -1 },
+                new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 },
+                new Object[] { STRING_LLONG, "AB", 6 },
+                new Object[] { STRING_LLONG, "ABCD", 4 },
+                new Object[] { STRING_LLONG, "ABCDEFGH\uFF21\uFF21", -2 },
+                new Object[] { STRING_U1, "\uFF21", 0 },
+                new Object[] { STRING_U1, "\uFF22", -1 },
+                new Object[] { STRING_U1, "\uFF21\uFF22", -1 },
+                new Object[] { STRING_U1, "A", 65248 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
+                new Object[] { STRING_U2, "\uFF22", -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF21", 1 },
+                new Object[] { STRING_U2, "A", 65248 },
+                new Object[] { STRING_M12, "\uFF21A", 0 },
+                new Object[] { STRING_M12, "A\uFF21", 65248 },
+                new Object[] { STRING_M12, "\uFF21\uFF21", -65248 },
+                new Object[] { STRING_M11, "A\uFF21", 0 },
+                new Object[] { STRING_M11, "\uFF21A", -65248 },
+                new Object[] { STRING_M11, "AA", 65248 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCompareTo(String str, String anotherString, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.compareTo(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).compareTo(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+
+    // BEGIN Android-removed: compareTo() for StringBuilder and StringBuffer not yet ported.
+    /*
+     * Runs the same test with StringBuilder
+    *
+    @Test(dataProvider = "provider")
+    public void testStringBuilder(String str, String anotherString, int expected) {
+        StringBuilder another = new StringBuilder(anotherString);
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            StringBuilder sb = new StringBuilder(data);
+                            assertEquals(
+                                    sb.compareTo(another),
+                                    expected,
+                                    String.format(
+                                            "testing StringBuilder(%s).compareTo(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+
+    /*
+     * Runs the same test with StringBuffer
+    *
+    @Test(dataProvider = "provider")
+    public void testStringBuffer(String str, String anotherString, int expected) {
+        StringBuffer another = new StringBuffer(anotherString);
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            StringBuffer sb = new StringBuffer(data);
+                            assertEquals(
+                                    sb.compareTo(another),
+                                    expected,
+                                    String.format(
+                                            "testing StringBuffer(%s).compareTo(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+     */
+    // END Android-removed: compareTo() for StringBuilder and StringBuffer not yet ported.
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/CompareToIgnoreCase.java b/ojluni/src/test/java/lang/String/CompactString/CompareToIgnoreCase.java
new file mode 100644
index 0000000..1304252
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/CompareToIgnoreCase.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.compareToIgnoreCase.
+ * @run testng/othervm -XX:+CompactStrings CompareToIgnoreCase
+ * @run testng/othervm -XX:-CompactStrings CompareToIgnoreCase
+ */
+
+public class CompareToIgnoreCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_L1, "a", 0 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "\uFF21", -65248 },
+                new Object[] { STRING_L1, "B", -1 },
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "aB", 0 },
+                new Object[] { STRING_L2, "\uFF21", -65248 },
+                new Object[] { STRING_L2, "A\uFF21", -65247 },
+                new Object[] { STRING_L4, "ABCD", 0 },
+                new Object[] { STRING_L4, "abcd", 0 },
+                new Object[] { STRING_L4, "ABc\uFF21", -65245 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0 },
+                new Object[] { STRING_LLONG, "abcdefgh", 0 },
+                new Object[] { STRING_LLONG, "ABCDEFG\uFF21", -65241 },
+                new Object[] { STRING_LLONG, "abcdefg\uFF21", -65241 },
+                new Object[] { STRING_U1, "\uFF41", 0 },
+                new Object[] { STRING_U1,
+                        "\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -7 },
+                new Object[] { STRING_U1, "A", 65248 },
+                new Object[] { STRING_U2, "\uFF41", 1 },
+                new Object[] { STRING_U2, "\uFF41\uFF42", 0 },
+                new Object[] { STRING_U2,
+                        "\uFF41\uFF42\uFF43\uFF44\uFF45\uFF46\uFF47\uFF48", -6 },
+                new Object[] { STRING_M12, "\uFF41a", 0 },
+                new Object[] { STRING_M12, "\uFF41\uFF42", -65249 },
+                new Object[] { STRING_M11, "a\uFF41", 0 },
+                new Object[] { STRING_M11, "a\uFF42", -1 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testCompareToIgnoreCase(String str, String anotherString,
+            int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.compareToIgnoreCase(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).compareToIgnoreCase(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Concat.java b/ojluni/src/test/java/lang/String/CompactString/Concat.java
new file mode 100644
index 0000000..b3f4dae
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Concat.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.concat.
+ * @run testng/othervm -XX:+CompactStrings Concat
+ * @run testng/othervm -XX:-CompactStrings Concat
+ */
+
+public class Concat extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, "ABC", "ABC" },
+                new Object[] { STRING_EMPTY,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_EMPTY,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_L1,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "AABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_L1,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_L2,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_L2,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "AB\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_L4,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABCDABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_L4,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "ABCD\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_LLONG,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "ABCDEFGHABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_LLONG,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "ABCDEFGH\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_U1,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "\uFF21ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_U1,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_U2,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "\uFF21\uFF22ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_U2,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21\uFF22\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_M12,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "\uFF21AABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_M12,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "\uFF21A\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" },
+                new Object[] { STRING_M11,
+                        "ABC".concat("\uFF21\uFF22\uFF23").concat("DEF"),
+                        "A\uFF21ABC\uFF21\uFF22\uFF23DEF" },
+                new Object[] {
+                        STRING_M11,
+                        "\uFF21\uFF22\uFF23".concat("ABC").concat(
+                                "\uFF24\uFF25\uFF26"),
+                        "A\uFF21\uFF21\uFF22\uFF23ABC\uFF24\uFF25\uFF26" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testConcat(String str, String anotherString, String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.concat(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).concat(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Contains.java b/ojluni/src/test/java/lang/String/CompactString/Contains.java
new file mode 100644
index 0000000..a0315e1
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Contains.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.contains.
+ * @run testng/othervm -XX:+CompactStrings Contains
+ * @run testng/othervm -XX:-CompactStrings Contains
+ */
+
+public class Contains extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_EMPTY, "A", false },
+                new Object[] { STRING_EMPTY, "\uFF21", false },
+                new Object[] { STRING_L1, "", true },
+                new Object[] { STRING_L1, "A", true },
+                new Object[] { STRING_L1, "\uFF21", false },
+                new Object[] { STRING_L2, "", true },
+                new Object[] { STRING_L2, "A", true },
+                new Object[] { STRING_L2, "AB", true },
+                new Object[] { STRING_L2, "B", true },
+                new Object[] { STRING_L2, "ABC", false },
+                new Object[] { STRING_L2, "ab", false },
+                new Object[] { STRING_L4, "ABCD", true },
+                new Object[] { STRING_L4, "BC", true },
+                new Object[] { STRING_LLONG, "ABCDEFGH", true },
+                new Object[] { STRING_LLONG, "BCDEFGH", true },
+                new Object[] { STRING_LLONG, "EF", true },
+                new Object[] { STRING_U1, "", true },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U1, "a", false },
+                new Object[] { STRING_U1, "\uFF21B", false },
+                new Object[] { STRING_U2, "", true },
+                new Object[] { STRING_U2, "\uFF21\uFF22", true },
+                new Object[] { STRING_U2, "a", false },
+                new Object[] { STRING_U2, "\uFF21B", false },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M12, "\uFF21", true },
+                new Object[] { STRING_M12, "A", true },
+                new Object[] { STRING_M12, "A\uFF21", false },
+                new Object[] { STRING_M11, "A\uFF21", true },
+                new Object[] { STRING_M11, "Ab", false }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testContains(String str, String anotherString, boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.contains(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).contains(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/EndsWith.java b/ojluni/src/test/java/lang/String/CompactString/EndsWith.java
new file mode 100644
index 0000000..39744cc
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/EndsWith.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.endsWith.
+ * @run testng/othervm -XX:+CompactStrings EndsWith
+ * @run testng/othervm -XX:-CompactStrings EndsWith
+ */
+
+public class EndsWith extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] { new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_EMPTY, "A", false },
+                new Object[] { STRING_L1, "A", true },
+                new Object[] { STRING_L1, "", true },
+                new Object[] { STRING_L1, " ", false },
+                new Object[] { STRING_L2, "AB", true },
+                new Object[] { STRING_L2, "B", true },
+                new Object[] { STRING_L2, "", true },
+                new Object[] { STRING_L2, "A", false },
+                new Object[] { STRING_L4, "ABCD", true },
+                new Object[] { STRING_L4, "CD", true },
+                new Object[] { STRING_L4, "D", true },
+                new Object[] { STRING_L4, "", true },
+                new Object[] { STRING_L4, "BC", false },
+                new Object[] { STRING_LLONG, "ABCDEFGH", true },
+                new Object[] { STRING_LLONG, "EFGH", true },
+                new Object[] { STRING_LLONG, "", true },
+                new Object[] { STRING_LLONG, "CDEF", false },
+                new Object[] { STRING_LLONG, "\uFF28", false },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U1, "", true },
+                new Object[] { STRING_U1, "\uFF22", false },
+                new Object[] { STRING_U1, "B", false },
+                new Object[] { STRING_U2, "\uFF21\uFF22", true },
+                new Object[] { STRING_U2, "\uFF22", true },
+                new Object[] { STRING_U2, "", true },
+                new Object[] { STRING_U2, "\uFF21", false },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M12, "A", true },
+                new Object[] { STRING_M12, "", true },
+                new Object[] { STRING_M12, "AA", false },
+                new Object[] { STRING_M11, "A\uFF21", true },
+                new Object[] { STRING_M11, "\uFF21", true },
+                new Object[] { STRING_M11, "", true },
+                new Object[] { STRING_M11, "\uFF21\uFF21", false }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testEndsWith(String str, String suffix, boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.endsWith(suffix),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).endsWith(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(suffix), source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Equals.java b/ojluni/src/test/java/lang/String/CompactString/Equals.java
new file mode 100644
index 0000000..5270769
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Equals.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.equals.
+ * @run testng/othervm -XX:+CompactStrings Equals
+ * @run testng/othervm -XX:-CompactStrings Equals
+ */
+
+public class Equals extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_EMPTY, "A", false },
+                new Object[] { STRING_EMPTY, new StringBuffer(""), false },
+                new Object[] { STRING_L1, "A", true },
+                new Object[] { STRING_L1, "", false },
+                new Object[] { STRING_L1, new StringBuffer("A"), false },
+                new Object[] { STRING_L2, "AB", true },
+                new Object[] { STRING_L2, "", false },
+                new Object[] { STRING_L2, new StringBuilder("AB"), false },
+                new Object[] { STRING_L4, "ABCD", true },
+                new Object[] { STRING_L4, "abc", false },
+                new Object[] { STRING_L4, "", false },
+                new Object[] { STRING_LLONG, "ABCDEFGH", true },
+                new Object[] { STRING_LLONG, "ABCDEFG", false },
+                new Object[] { STRING_LLONG, new StringBuilder("ABCDEFGH"),
+                        false },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U1, "", false },
+                new Object[] { STRING_U2, "\uFF21\uFF22", true },
+                new Object[] { STRING_U2, "\uFF21", false },
+                new Object[] { STRING_U2, "", false },
+                new Object[] { STRING_U2, new StringBuilder("\uFF21\uFF22"),
+                        false },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M12, "A\uFF21", false },
+                new Object[] { STRING_M11, "A\uFF21", true },
+                new Object[] { STRING_M11, new StringBuilder("\uFF21A"), false }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testEquals(String str, Object obj, boolean expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.equals(obj), expected, String.format(
+                            "testing String(%s).equals(%s), source : %s, ",
+                            escapeNonASCIIs(data),
+                            escapeNonASCIIs(obj.toString()), source));
+                });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/EqualsIgnoreCase.java b/ojluni/src/test/java/lang/String/CompactString/EqualsIgnoreCase.java
new file mode 100644
index 0000000..8e7b5cf
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/EqualsIgnoreCase.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.equalsIgnoreCase.
+ * @run testng/othervm -XX:+CompactStrings EqualsIgnoreCase
+ * @run testng/othervm -XX:-CompactStrings EqualsIgnoreCase
+ */
+
+public class EqualsIgnoreCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, "", true },
+                new Object[] { STRING_L1, "a", true },
+                new Object[] { STRING_L2, "aB", true },
+                new Object[] { STRING_L4, "AbCd", true },
+                new Object[] { STRING_LLONG, "aBcDeFgH", true },
+                new Object[] { STRING_U1, "\uFF41", true },
+                new Object[] { STRING_U1, "\uFF21", true },
+                new Object[] { STRING_U2, "\uFF41\uFF42", true },
+                new Object[] { STRING_U2, "\uFF41\uFF22", true },
+                new Object[] { STRING_U2, "\uFF21\uFF42", true },
+                new Object[] { STRING_M12, "\uFF41a", true },
+                new Object[] { STRING_M12, "\uFF21A", true },
+                new Object[] { STRING_M11, "a\uFF41", true },
+                new Object[] { STRING_M11, "A\uFF21", true },
+
+        };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testEqualsIgnoreCase(String str, String anotherString,
+            boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.equalsIgnoreCase(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).equalsIgnoreCase(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/GetChars.java b/ojluni/src/test/java/lang/String/CompactString/GetChars.java
new file mode 100644
index 0000000..76036d1
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/GetChars.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import java.util.Arrays;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.getChars.
+ * @run testng/othervm -XX:+CompactStrings GetChars
+ * @run testng/othervm -XX:-CompactStrings GetChars
+ */
+
+public class GetChars extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, 0, STRING_EMPTY.length(),
+                        new char[STRING_EMPTY.length()], 0, CHAR_ARRAY_EMPTY },
+                new Object[] { STRING_L1, 0, STRING_L1.length(),
+                        new char[STRING_L1.length()], 0, CHAR_ARRAY_L1 },
+                new Object[] { STRING_L2, 0, STRING_L2.length(),
+                        new char[STRING_L2.length()], 0, CHAR_ARRAY_L2 },
+                new Object[] { STRING_L4, 0, STRING_L4.length(),
+                        new char[STRING_L4.length()], 0, CHAR_ARRAY_L4 },
+                new Object[] { STRING_LLONG, 0, STRING_LLONG.length(),
+                        new char[STRING_LLONG.length()], 0, CHAR_ARRAY_LLONG },
+                new Object[] { STRING_U1, 0, STRING_U1.length(),
+                        new char[STRING_U1.length()], 0, CHAR_ARRAY_U1 },
+                new Object[] { STRING_U2, 0, STRING_U2.length(),
+                        new char[STRING_U2.length()], 0, CHAR_ARRAY_U2 },
+                new Object[] { STRING_M12, 0, STRING_M12.length(),
+                        new char[STRING_M12.length()], 0, CHAR_ARRAY_M12 },
+                new Object[] { STRING_M11, 0, STRING_M11.length(),
+                        new char[STRING_M11.length()], 0, CHAR_ARRAY_M11 },
+                new Object[] { STRING_UDUPLICATE, 0,
+                        STRING_UDUPLICATE.length(),
+                        new char[STRING_UDUPLICATE.length()], 0,
+                        CHAR_ARRAY_UDUPLICATE },
+                new Object[] { STRING_MDUPLICATE1, 0,
+                        STRING_MDUPLICATE1.length(),
+                        new char[STRING_MDUPLICATE1.length()], 0,
+                        CHAR_ARRAY_MDUPLICATE1 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testGetChars(String str, int srcBegin, int srcEnd, char[] dst,
+            int dstBegin, char[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            data.getChars(srcBegin, srcEnd, dst, dstBegin);
+                            assertTrue(
+                                    Arrays.equals(dst, expected),
+                                    String.format(
+                                            "testing String(%s).getChars(%d, %d, %s, %d), source : %s, ",
+                                            escapeNonASCIIs(data), srcBegin,
+                                            srcEnd, escapeNonASCIIs(Arrays
+                                                    .toString(dst)), dstBegin,
+                                            source));
+                        });
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/IndexOf.java b/ojluni/src/test/java/lang/String/CompactString/IndexOf.java
new file mode 100644
index 0000000..849d499
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/IndexOf.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.indexOf.
+ * @run testng/othervm -XX:+CompactStrings IndexOf
+ * @run testng/othervm -XX:-CompactStrings IndexOf
+ */
+
+public class IndexOf extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, (int) 'A', -1 },
+                new Object[] { STRING_L1, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'B', 1 },
+                new Object[] { STRING_L4, (int) 'A', 0 },
+                new Object[] { STRING_L4, (int) 'D', 3 },
+                new Object[] { STRING_L4, (int) 'E', -1 },
+                new Object[] { STRING_LLONG, (int) 'A', 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 7 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0 },
+                new Object[] { STRING_U1, (int) 'A', -1 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0 },
+                new Object[] { STRING_M12, (int) 'A', 1 },
+                new Object[] { STRING_M11, (int) 'A', 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 0 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1 },
+                new Object[] { STRING_SUPPLEMENTARY, 'A', 5 },
+                new Object[] { STRING_SUPPLEMENTARY, '\uFF21', 4 },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        Character.toCodePoint('\uD801', '\uDC00'), 0 },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        Character.toCodePoint('\uD801', '\uDC01'), 2 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testIndexOf(String str, int ch, int expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.indexOf(ch), expected, String.format(
+                            "testing String(%s).indexOf(%d), source : %s, ",
+                            escapeNonASCIIs(data), ch, source));
+                });
+    }
+
+    @DataProvider
+    public Object[][] provider2() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, (int) 'A', 0, -1 },
+                new Object[] { STRING_L1, (int) 'A', 0, 0 },
+                new Object[] { STRING_L1, (int) 'A', 1, -1 },
+                new Object[] { STRING_L1, (int) 'B', 0, -1 },
+                new Object[] { STRING_L2, (int) 'A', 0, 0 },
+                new Object[] { STRING_L2, (int) 'A', 1, -1 },
+                new Object[] { STRING_L2, (int) 'B', 0, 1 },
+                new Object[] { STRING_L2, (int) 'B', 1, 1 },
+                new Object[] { STRING_L4, (int) 'A', 0, 0 },
+                new Object[] { STRING_L4, (int) 'D', 2, 3 },
+                new Object[] { STRING_L4, (int) 'B', 2, -1 },
+                new Object[] { STRING_LLONG, (int) 'A', 0, 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 5, 7 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U1, (int) 'A', 0, -1 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 0, 1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_M12, (int) 'A', 1, 1 },
+                new Object[] { STRING_M11, (int) 'A', 0, 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1, 1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 1, 2 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 1, 1 }, };
+    }
+
+    @Test(dataProvider = "provider2")
+    public void testIndexOf(String str, int ch, int fromIndex, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.indexOf(ch, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).indexOf(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), ch,
+                                            fromIndex, source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider3() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "AB", -1 },
+                new Object[] { STRING_L2, "A", 0 },
+                new Object[] { STRING_L2, "B", 1 },
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "AC", -1 },
+                new Object[] { STRING_L2, "ABC", -1 },
+                new Object[] { STRING_L4, "ABCD", 0 },
+                new Object[] { STRING_L4, "D", 3 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0 },
+                new Object[] { STRING_LLONG, "EFGH", 4 },
+                new Object[] { STRING_LLONG, "EFGHI", -1 },
+                new Object[] { STRING_U1, "\uFF21", 0 },
+                new Object[] { STRING_U1, "\uFF21A", -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
+                new Object[] { STRING_U2, "\uFF22", 1 },
+                new Object[] { STRING_U2, "A\uFF22", -1 },
+                new Object[] { STRING_M12, "\uFF21A", 0 },
+                new Object[] { STRING_M12, "A", 1 },
+                new Object[] { STRING_M12, "\uFF21\uFF21", -1 },
+                new Object[] { STRING_M11, "A\uFF21", 0 },
+                new Object[] { STRING_M11, "\uFF21", 1 },
+                new Object[] { STRING_M11, "A", 0 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0 },
+                new Object[] { STRING_UDUPLICATE,
+                        "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21", 1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21",
+                        -1 }, };
+    }
+
+    @Test(dataProvider = "provider3")
+    public void testIndexOf(String str, String anotherString, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.indexOf(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).indexOf(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider4() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", 0, -1 },
+                new Object[] { STRING_L1, "A", 0, 0 },
+                new Object[] { STRING_L1, "A", 1, -1 },
+                new Object[] { STRING_L1, "AB", 0, -1 },
+                new Object[] { STRING_L2, "A", 0, 0 },
+                new Object[] { STRING_L2, "B", 0, 1 },
+                new Object[] { STRING_L2, "AB", 0, 0 },
+                new Object[] { STRING_L2, "AB", 1, -1 },
+                new Object[] { STRING_L4, "ABCD", 0, 0 },
+                new Object[] { STRING_L4, "BC", 0, 1 },
+                new Object[] { STRING_L4, "A", 0, 0 },
+                new Object[] { STRING_L4, "CD", 0, 2 },
+                new Object[] { STRING_L4, "A", 2, -1 },
+                new Object[] { STRING_L4, "ABCDE", 0, -1 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 },
+                new Object[] { STRING_LLONG, "DEFGH", 0, 3 },
+                new Object[] { STRING_LLONG, "A", 0, 0 },
+                new Object[] { STRING_LLONG, "GHI", 0, -1 },
+                new Object[] { STRING_U1, "\uFF21", 0, 0 },
+                new Object[] { STRING_U1, "\uFF21A", 0, -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 },
+                new Object[] { STRING_U2, "\uFF22", 0, 1 },
+                new Object[] { STRING_U2, "\uFF21", 1, -1 },
+                new Object[] { STRING_M12, "\uFF21A", 0, 0 },
+                new Object[] { STRING_M12, "A", 1, 1 },
+                new Object[] { STRING_M12, "\uFF21A", 1, -1 },
+                new Object[] { STRING_M12, "\uFF21", 0, 0 },
+                new Object[] { STRING_M11, "A\uFF21", 0, 0 },
+                new Object[] { STRING_M11, "\uFF21", 1, 1 },
+                new Object[] { STRING_M11, "A\uFF21", 1, -1 },
+                new Object[] { STRING_M11, "A\uFF21A", 0, -1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0, 0 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        1, -1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        1, 1 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22",
+                        4, 4 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22",
+                        7, -1 }, };
+    }
+
+    @Test(dataProvider = "provider4")
+    public void testIndexOf(String str, String anotherString, int fromIndex,
+            int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.indexOf(anotherString, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).indexOf(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            fromIndex, source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Intern.java b/ojluni/src/test/java/lang/String/CompactString/Intern.java
new file mode 100644
index 0000000..4eb9c7d
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Intern.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.intern.
+ * @run testng/othervm -XX:+CompactStrings Intern
+ * @run testng/othervm -XX:-CompactStrings Intern
+ */
+
+public class Intern extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "" },
+                new Object[] { STRING_L1, "A" },
+                new Object[] { STRING_LLONG, "ABCDEFGH" },
+                new Object[] { STRING_U1, "\uFF21" },
+                new Object[] { STRING_U2, "\uFF21\uFF22" },
+                new Object[] { STRING_M12, "\uFF21A" },
+                new Object[] { STRING_M11, "A\uFF21" },
+                new Object[] { STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testIntern(String str, String expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertTrue(data.intern() == expected, String.format(
+                            "testing String(%s).intern(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/LastIndexOf.java b/ojluni/src/test/java/lang/String/CompactString/LastIndexOf.java
new file mode 100644
index 0000000..ad20fad
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/LastIndexOf.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.lastIndexOf.
+ * @run testng/othervm -XX:+CompactStrings LastIndexOf
+ * @run testng/othervm -XX:-CompactStrings LastIndexOf
+ */
+
+public class LastIndexOf extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, (int) 'A', -1 },
+                new Object[] { STRING_L1, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'A', 0 },
+                new Object[] { STRING_L2, (int) 'B', 1 },
+                new Object[] { STRING_L4, (int) 'A', 0 },
+                new Object[] { STRING_L4, (int) 'D', 3 },
+                new Object[] { STRING_LLONG, (int) 'A', 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 7 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0 },
+                new Object[] { STRING_U1, (int) 'B', -1 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0 },
+                new Object[] { STRING_M12, (int) 'A', 1 },
+                new Object[] { STRING_M11, (int) 'A', 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 9 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 8 },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        Character.toCodePoint('\uD801', '\uDC01'), 2 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testLastIndexOf(String str, int ch, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(ch),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%d), source : %s, ",
+                                            escapeNonASCIIs(data), ch, source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider2() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, (int) 'A', 0, -1 },
+                new Object[] { STRING_L1, (int) 'A', 0, 0 },
+                new Object[] { STRING_L1, (int) 'A', 1, 0 },
+                new Object[] { STRING_L2, (int) 'A', 0, 0 },
+                new Object[] { STRING_L2, (int) 'B', 1, 1 },
+                new Object[] { STRING_L2, (int) 'B', 2, 1 },
+                new Object[] { STRING_L4, (int) 'A', 0, 0 },
+                new Object[] { STRING_L4, (int) 'C', 2, 2 },
+                new Object[] { STRING_L4, (int) 'C', 1, -1 },
+                new Object[] { STRING_LLONG, (int) 'A', 0, 0 },
+                new Object[] { STRING_LLONG, (int) 'H', 7, 7 },
+                new Object[] { STRING_LLONG, (int) 'H', 6, -1 },
+                new Object[] { STRING_U1, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U1, (int) '\uFF21', 7, 0 },
+                new Object[] { STRING_U2, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_U2, (int) '\uFF22', 0, -1 },
+                new Object[] { STRING_M12, (int) '\uFF21', 0, 0 },
+                new Object[] { STRING_M12, (int) 'A', 1, 1 },
+                new Object[] { STRING_M12, (int) 'A', 0, -1 },
+                new Object[] { STRING_M11, (int) 'A', 0, 0 },
+                new Object[] { STRING_M11, (int) '\uFF21', 1, 1 },
+                new Object[] { STRING_M11, (int) '\uFF21', 0, -1 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 5, 4 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF21', 6, 6 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 5, 5 },
+                new Object[] { STRING_UDUPLICATE, (int) '\uFF22', 6, 5 }, };
+    }
+
+    @Test(dataProvider = "provider2")
+    public void testLastIndexOf(String str, int ch, int fromIndex, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(ch, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), ch,
+                                            fromIndex, source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider3() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", -1 },
+                new Object[] { STRING_L1, "A", 0 },
+                new Object[] { STRING_L1, "AB", -1 },
+
+                new Object[] { STRING_L2, "AB", 0 },
+                new Object[] { STRING_L2, "B", 1 },
+                new Object[] { STRING_L4, "ABCD", 0 },
+                new Object[] { STRING_L4, "B", 1 },
+                new Object[] { STRING_LLONG, "ABCD", 0 },
+                new Object[] { STRING_LLONG, "GH", 6 },
+                new Object[] { STRING_U1, "\uFF21", 0 },
+                new Object[] { STRING_U1, "\uFF22", -1 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0 },
+                new Object[] { STRING_U2, "\uFF22", 1 },
+                new Object[] { STRING_M12, "\uFF21A", 0 },
+                new Object[] { STRING_M12, "A", 1 },
+                new Object[] { STRING_M11, "A\uFF21", 0 },
+                new Object[] { STRING_M11, "\uFF21", 1 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21\uFF22", 6 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 8 }, };
+    }
+
+    @Test(dataProvider = "provider3")
+    public void testLastIndexOf(String str, String anotherString, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(anotherString),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider4() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "A", 0, -1 },
+                new Object[] { STRING_L2, "AB", 0, 0 },
+
+                new Object[] { STRING_L1, "AB", -1, -1 },
+
+                new Object[] { STRING_L2, "B", 1, 1 },
+                new Object[] { STRING_L2, "B", 0, -1 },
+                new Object[] { STRING_L4, "ABC", 3, 0 },
+                new Object[] { STRING_L4, "ABC", 0, 0 },
+                new Object[] { STRING_L4, "ABC", 1, 0 },
+                new Object[] { STRING_L4, "BC", 1, 1 },
+                new Object[] { STRING_L4, "BC", 0, -1 },
+                new Object[] { STRING_LLONG, "ABCDEFGH", 0, 0 },
+                new Object[] { STRING_LLONG, "EFGH", 7, 4 },
+                new Object[] { STRING_LLONG, "EFGH", 3, -1 },
+                new Object[] { STRING_U1, "\uFF21", 0, 0 },
+                new Object[] { STRING_U1, "\uFF21", 7, 0 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 0, 0 },
+                new Object[] { STRING_U2, "\uFF21\uFF22", 1, 0 },
+                new Object[] { STRING_M12, "\uFF21A", 0, 0 },
+                new Object[] { STRING_M12, "A", 1, 1 },
+                new Object[] { STRING_M12, "A", 0, -1 },
+                new Object[] { STRING_M11, "A\uFF21", 0, 0 },
+                new Object[] { STRING_M11, "A\uFF21", 1, 0 },
+                new Object[] { STRING_M11, "\uFF21", 0, -1 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        9, 0 },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0, 0 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", 6, 6 },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22\uFF21", 6, 6 }, };
+    }
+
+    @Test(dataProvider = "provider4")
+    public void testLastIndexOf(String str, String anotherString,
+            int fromIndex, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.lastIndexOf(anotherString, fromIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).lastIndexOf(%s, %d), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(anotherString),
+                                            fromIndex, source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Length.java b/ojluni/src/test/java/lang/String/CompactString/Length.java
new file mode 100644
index 0000000..c69c983
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Length.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.length.
+ * @run testng/othervm -XX:+CompactStrings Length
+ * @run testng/othervm -XX:-CompactStrings Length
+ */
+
+public class Length extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_EMPTY, 0 }, new Object[] { STRING_L1, 1 },
+                new Object[] { STRING_L2, 2 },
+                new Object[] { STRING_LLONG, 8 },
+                new Object[] { STRING_U1, 1 }, new Object[] { STRING_U2, 2 },
+                new Object[] { STRING_M12, 2 }, new Object[] { STRING_M11, 2 },
+                new Object[] { STRING_UDUPLICATE, 10 },
+                new Object[] { STRING_SUPPLEMENTARY, 6 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testLength(String str, int expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.length(), expected, String.format(
+                            "testing String(%s).length(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Numbers.java b/ojluni/src/test/java/lang/String/CompactString/Numbers.java
new file mode 100644
index 0000000..94c066c
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Numbers.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is testing
+ *          Integer/Long's methods related to String.
+ * @run testng/othervm -XX:+CompactStrings Numbers
+ * @run testng/othervm -XX:-CompactStrings Numbers
+ */
+
+public class Numbers {
+
+    /*
+     * Data provider for testIntegerLong
+     *
+     * @return input parameter for testIntegerLong
+     */
+    @DataProvider
+    public Object[][] numbers() {
+        return new Object[][] {
+                { Integer.toBinaryString(Integer.MAX_VALUE),
+                        "1111111111111111111111111111111" },
+                { Integer.toBinaryString(Integer.MIN_VALUE),
+                        "10000000000000000000000000000000" },
+                { Integer.toBinaryString(7), "111" },
+                { Integer.toBinaryString(0), "0" },
+                { Integer.toOctalString(Integer.MAX_VALUE), "17777777777" },
+                { Integer.toOctalString(Integer.MIN_VALUE), "20000000000" },
+                { Integer.toOctalString(9), "11" },
+                { Integer.toOctalString(0), "0" },
+                { Integer.toHexString(Integer.MAX_VALUE), "7fffffff" },
+                { Integer.toHexString(Integer.MIN_VALUE), "80000000" },
+                { Integer.toHexString(17), "11" },
+                { Integer.toHexString(0), "0" },
+                { Integer.toString(Integer.MAX_VALUE, 2),
+                        "1111111111111111111111111111111" },
+                { Integer.toString(Integer.MIN_VALUE, 2),
+                        "-10000000000000000000000000000000" },
+                { Integer.toString(7, 2), "111" },
+                { Integer.toString(0, 2), "0" },
+                { Integer.toString(Integer.MAX_VALUE, 8), "17777777777" },
+                { Integer.toString(Integer.MIN_VALUE, 8), "-20000000000" },
+                { Integer.toString(9, 8), "11" },
+                { Integer.toString(Integer.MAX_VALUE, 16), "7fffffff" },
+                { Integer.toString(Integer.MIN_VALUE, 16), "-80000000" },
+                { Integer.toString(17, 16), "11" },
+                { Long.toBinaryString(Long.MAX_VALUE),
+                        "111111111111111111111111111111111111111111111111111111111111111" },
+                { Long.toBinaryString(Long.MIN_VALUE),
+                        "1000000000000000000000000000000000000000000000000000000000000000" },
+                { Long.toOctalString(Long.MAX_VALUE), "777777777777777777777" },
+                { Long.toOctalString(Long.MIN_VALUE), "1000000000000000000000" },
+                { Long.toHexString(Long.MAX_VALUE), "7fffffffffffffff" },
+                { Long.toHexString(Long.MIN_VALUE), "8000000000000000" },
+                { Long.toString(Long.MAX_VALUE, 2),
+                        "111111111111111111111111111111111111111111111111111111111111111" },
+                { Long.toString(Long.MIN_VALUE, 2),
+                        "-1000000000000000000000000000000000000000000000000000000000000000" },
+                { Long.toString(Long.MAX_VALUE, 8), "777777777777777777777" },
+                { Long.toString(Long.MIN_VALUE, 8), "-1000000000000000000000" },
+                { Long.toString(Long.MAX_VALUE, 16), "7fffffffffffffff" },
+                { Long.toString(Long.MIN_VALUE, 16), "-8000000000000000" } };
+    }
+
+    /*
+     * test Integer/Long's methods related to String.
+     *
+     * @param res
+     *            real result
+     * @param expected
+     *            expected result
+     */
+    @Test(dataProvider = "numbers")
+    public void testIntegerLong(String res, String expected) {
+        assertEquals(res, expected);
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/OffsetByCodePoints.java b/ojluni/src/test/java/lang/String/CompactString/OffsetByCodePoints.java
new file mode 100644
index 0000000..ba022fd
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/OffsetByCodePoints.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.offsetByCodePoints.
+ * @run testng/othervm -XX:+CompactStrings OffsetByCodePoints
+ * @run testng/othervm -XX:-CompactStrings OffsetByCodePoints
+ */
+
+public class OffsetByCodePoints extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+        new Object[] { STRING_SUPPLEMENTARY, 0, 1, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 0, 3, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 1, 2 },
+                new Object[] { STRING_SUPPLEMENTARY, 1, 3, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 1, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 2, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 2, 3, 6 },
+                new Object[] { STRING_SUPPLEMENTARY, 3, 1, 4 },
+                new Object[] { STRING_SUPPLEMENTARY, 3, 2, 5 },
+                new Object[] { STRING_SUPPLEMENTARY, 3, 3, 6 }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testOffsetByCodePoints(String str, int index,
+            int codePointOffset, int expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.offsetByCodePoints(index,
+                                            codePointOffset),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).offsetByCodePoints(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), index,
+                                            codePointOffset, source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/RegionMatches.java b/ojluni/src/test/java/lang/String/CompactString/RegionMatches.java
new file mode 100644
index 0000000..a9e0a30
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/RegionMatches.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.regionMatches.
+ * @run testng/othervm -XX:+CompactStrings RegionMatches
+ * @run testng/othervm -XX:-CompactStrings RegionMatches
+ */
+
+public class RegionMatches extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true },
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false },
+                new Object[] { STRING_EMPTY, true, 0, "A", 0, 0, true },
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 0, true },
+                new Object[] { STRING_EMPTY, true, 0, "", 0, 1, false },
+                new Object[] { STRING_L1, false, 0, "a", 0, 1, false },
+                new Object[] { STRING_L1, false, 0, "BA", 1, 1, true },
+                new Object[] { STRING_L1, false, 0, "Ba", 1, 1, false },
+                new Object[] { STRING_L1, true, 0, "a", 0, 1, true },
+                new Object[] { STRING_L1, true, 0, "BA", 1, 1, true },
+                new Object[] { STRING_L1, true, 0, "Ba", 1, 1, true },
+                new Object[] { STRING_L2, true, 1, "b", 0, 1, true },
+                new Object[] { STRING_L2, true, 1, "B", 0, 1, true },
+                new Object[] { STRING_L2, true, 0, "xaBc", 1, 2, true },
+                new Object[] { STRING_L2, false, 0, "AB", 0, 2, true },
+                new Object[] { STRING_L2, false, 0, "Ab", 0, 2, false },
+                new Object[] { STRING_L2, false, 1, "BAB", 2, 1, true },
+                new Object[] { STRING_LLONG, true, 1, "bCdEF", 0, 5, true },
+                new Object[] { STRING_LLONG, false, 2, "CDEFG", 0, 5, true },
+                new Object[] { STRING_LLONG, true, 2, "CDEFg", 0, 5, true },
+                new Object[] { STRING_U1, true, 0, "\uFF41", 0, 1, true },
+                new Object[] { STRING_U1, false, 0, "\uFF41", 0, 1, false },
+                new Object[] { STRING_MDUPLICATE1, true, 0, "\uFF41a\uFF41", 0,
+                        3, true },
+                new Object[] { STRING_MDUPLICATE1, false, 0, "\uFF21a\uFF21",
+                        0, 3, false },
+                new Object[] { STRING_SUPPLEMENTARY, true, 1, "\uDC00\uD801",
+                        0, 2, true },
+                new Object[] { STRING_SUPPLEMENTARY, true, 4, "\uFF21", 0, 1,
+                        true },
+                new Object[] { STRING_SUPPLEMENTARY, true, 5, "A", 0, 1, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 0,
+                        "\uD801\uDC28\uD801\uDC29", 0, 4, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1,
+                        "\uDC28\uD801", 0, 2, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 1,
+                        "\uDC00\uD801", 0, 2, false },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, true, 4,
+                        "\uFF21", 0, 1, true },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4,
+                        "\uFF21", 0, 1, false },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, false, 4,
+                        "\uFF41", 0, 1, true }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testRegionMatches(String str, boolean ignoreCase, int toffset,
+            String other, int ooffset, int len, boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.regionMatches(ignoreCase, toffset,
+                                            other, ooffset, len),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).regionMatches(%b, %d, %s, %d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), ignoreCase,
+                                            toffset, escapeNonASCIIs(other),
+                                            ooffset, len, source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Replace.java b/ojluni/src/test/java/lang/String/CompactString/Replace.java
new file mode 100644
index 0000000..5b901d1
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Replace.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.replace.
+ * @run testng/othervm -XX:+CompactStrings Replace
+ * @run testng/othervm -XX:-CompactStrings Replace
+ */
+
+public class Replace extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_L1, 'A', 'B', "B" },
+                new Object[] { STRING_L1, 'A', 'A', "A" },
+                new Object[] { STRING_L1, 'A', '\uFF21', "\uFF21" },
+                new Object[] { STRING_L2, 'A', 'B', "BB" },
+                new Object[] { STRING_L2, 'B', 'A', "AA" },
+                new Object[] { STRING_L2, 'C', 'A', "AB" },
+                new Object[] { STRING_L2, 'B', '\uFF21', "A\uFF21" },
+                new Object[] { STRING_U1, '\uFF21', 'A', "A" },
+                new Object[] { STRING_U1, '\uFF22', 'A', "\uFF21" },
+                new Object[] { STRING_U2, '\uFF22', 'A', "\uFF21A" },
+                new Object[] { STRING_M12, 'A', '\uFF21', "\uFF21\uFF21" },
+                new Object[] { STRING_M11, '\uFF21', 'A', "AA" },
+                new Object[] { STRING_UDUPLICATE, '\uFF21', 'A',
+                        "A\uFF22A\uFF22A\uFF22A\uFF22A\uFF22" },
+                new Object[] { STRING_MDUPLICATE1, '\uFF21', 'A', "AAAAAAAAAA" },
+                new Object[] { STRING_MDUPLICATE1, 'A', '\uFF21',
+                        "\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testReplace(String str, char oldChar, char newChar,
+            String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.replace(oldChar, newChar),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).replace(%s, %s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCII(oldChar),
+                                            escapeNonASCII(newChar), source));
+                        });
+    }
+
+    @DataProvider
+    public Object[][] provider2() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "", "ABC", "ABC" },
+                new Object[] { STRING_EMPTY, "", "", "" },
+                new Object[] { STRING_L1, "A", "B", "B" },
+                new Object[] { STRING_L1, "A", "A", "A" },
+                new Object[] { STRING_L2, "B", "\uFF21", "A\uFF21" },
+                new Object[] { STRING_LLONG, "BCD", "\uFF21", "A\uFF21EFGH" },
+                new Object[] { STRING_U1, "\uFF21", "A", "A" },
+                new Object[] { STRING_U1, "\uFF21", "A\uFF21", "A\uFF21" },
+                new Object[] { STRING_U2, "\uFF21", "A", "A\uFF22" },
+                new Object[] { STRING_U2, "\uFF22", "A", "\uFF21A" },
+                new Object[] { STRING_UDUPLICATE, "\uFF21\uFF22", "AB",
+                        "ABABABABAB" },
+                new Object[] { STRING_MDUPLICATE1, "\uFF21", "A", "AAAAAAAAAA" },
+                new Object[] { STRING_MDUPLICATE1, "A", "\uFF21",
+                        "\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21\uFF21" }, };
+    }
+
+    @Test(dataProvider = "provider2")
+    public void testReplace(String str, CharSequence target,
+            CharSequence replacement, String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.replace(target, replacement),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).replace(%s, %s), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(target.toString()),
+                                            escapeNonASCIIs(replacement
+                                                    .toString()), source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Split.java b/ojluni/src/test/java/lang/String/CompactString/Split.java
new file mode 100644
index 0000000..3b999d6
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Split.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.lang.String.CompactString;
+
+import java.util.Arrays;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.split.
+ * @run testng/othervm -XX:+CompactStrings Split
+ * @run testng/othervm -XX:-CompactStrings Split
+ */
+
+public class Split extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_L1, "", 0, new String[] { "A" } },
+                new Object[] { STRING_L1, "", 1, new String[] { "A" } },
+                new Object[] { STRING_L1, "", 2, new String[] { "A", "" } },
+                new Object[] { STRING_L1, "A", 0, new String[] {} },
+                new Object[] { STRING_L2, "A", 0, new String[] { "", "B" } },
+                new Object[] { STRING_L2, "B", 0, new String[] { "A" } },
+                new Object[] { STRING_LLONG, "D", 0,
+                        new String[] { "ABC", "EFGH" } },
+                new Object[] { STRING_LLONG, "[D]", 0,
+                        new String[] { "ABC", "EFGH" } },
+                new Object[] { STRING_LLONG, "CD", 0,
+                        new String[] { "AB", "EFGH" } },
+                new Object[] { STRING_LLONG, "DC", 0,
+                        new String[] { "ABCDEFGH" } },
+                new Object[] { STRING_LLONG, "[CF]", 0,
+                        new String[] { "AB", "DE", "GH" } },
+                new Object[] { STRING_LLONG, "[CF]", 1,
+                        new String[] { "ABCDEFGH" } },
+                new Object[] { STRING_LLONG, "[CF]", 2,
+                        new String[] { "AB", "DEFGH" } },
+                new Object[] { STRING_LLONG, "[FC]", 0,
+                        new String[] { "AB", "DE", "GH" } },
+                new Object[] { STRING_LLONG, "[FC]", 1,
+                        new String[] { "ABCDEFGH" } },
+                new Object[] { STRING_LLONG, "[FC]", 2,
+                        new String[] { "AB", "DEFGH" } },
+                new Object[] { STRING_U1, "", 0, new String[] { "\uFF21" } },
+                new Object[] { STRING_U1, "", 1, new String[] { "\uFF21" } },
+                new Object[] { STRING_U1, "", 2, new String[] { "\uFF21", "" } },
+                new Object[] { STRING_U1, "\uFF21", 0, new String[] {} },
+                new Object[] { STRING_M12, "\uFF21", 0,
+                        new String[] { "", "A" } },
+                new Object[] { STRING_M12, "A", 0, new String[] { "\uFF21" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21",
+                        0,
+                        new String[] { "", "\uFF22", "\uFF22", "\uFF22",
+                                "\uFF22", "\uFF22" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21",
+                        2,
+                        new String[] { "",
+                                "\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF21",
+                        4,
+                        new String[] { "", "\uFF22", "\uFF22",
+                                "\uFF22\uFF21\uFF22\uFF21\uFF22" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF22",
+                        0,
+                        new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21",
+                                "\uFF21" } },
+                new Object[] {
+                        STRING_UDUPLICATE,
+                        "\uFF22",
+                        3,
+                        new String[] { "\uFF21", "\uFF21",
+                                "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22" } },
+
+                new Object[] { STRING_MDUPLICATE1, "\uFF21", 0,
+                        new String[] { "", "A", "A", "A", "A", "A" } },
+                new Object[] { STRING_MDUPLICATE1, "\uFF21", 3,
+                        new String[] { "", "A", "A\uFF21A\uFF21A\uFF21A" } },
+                new Object[] {
+                        STRING_MDUPLICATE1,
+                        "A",
+                        0,
+                        new String[] { "\uFF21", "\uFF21", "\uFF21", "\uFF21",
+                                "\uFF21" } },
+                new Object[] {
+                        STRING_MDUPLICATE1,
+                        "A",
+                        4,
+                        new String[] { "\uFF21", "\uFF21", "\uFF21",
+                                "\uFF21A\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "\uDC01", 0,
+                        new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "\uD801\uDC01", 0,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 0,
+                        new String[] { "\uD801\uDC00", "", "A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 1,
+                        new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uD801\uDC01\uFF21]", 2,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 0,
+                        new String[] { "\uD801\uDC00", "", "A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 1,
+                        new String[] { "\uD801\uDC00\uD801\uDC01\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY, "[\uFF21\uD801\uDC01]", 2,
+                        new String[] { "\uD801\uDC00", "\uFF21A" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uDC01", 0,
+                        new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE, "\uD801\uDC29",
+                        0, new String[] { "\uD801\uDC28", "\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uD801\uDC29\uFF41]", 0,
+                        new String[] { "\uD801\uDC28", "", "a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uD801\uDC29\uFF41]", 1,
+                        new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uD801\uDC29\uFF41]", 2,
+                        new String[] { "\uD801\uDC28", "\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uFF41\uD801\uDC29]", 0,
+                        new String[] { "\uD801\uDC28", "", "a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uFF41\uD801\uDC29]", 1,
+                        new String[] { "\uD801\uDC28\uD801\uDC29\uFF41a" } },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "[\uFF41\uD801\uDC29]", 2,
+                        new String[] { "\uD801\uDC28", "\uFF41a" } }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testSplit(String str, String regex, int limit, String[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertTrue(
+                                    Arrays.equals(data.split(regex, limit),
+                                            expected),
+                                    String.format(
+                                            "testing String(%s).split(%s, %d), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(regex), limit,
+                                            source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/StartsWith.java b/ojluni/src/test/java/lang/String/CompactString/StartsWith.java
new file mode 100644
index 0000000..33cb445
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/StartsWith.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.startsWith.
+ * @run testng/othervm -XX:+CompactStrings StartsWith
+ * @run testng/othervm -XX:-CompactStrings StartsWith
+ */
+
+public class StartsWith extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] {STRING_EMPTY, "", 0, true},
+                new Object[] {STRING_EMPTY, "A", 0, false},
+                new Object[] {STRING_EMPTY, "", 0, true},
+                new Object[] {STRING_EMPTY, "", -1, false},
+                new Object[] {STRING_L1, "A", 0, true},
+                new Object[] {STRING_L1, "A", -1, false},
+                new Object[] {STRING_L1, "A", 1, false},
+                new Object[] {STRING_L2, "B", 1, true},
+                new Object[] {STRING_L2, "B", 0, false},
+                new Object[] {STRING_L2, "A", 0, true},
+                new Object[] {STRING_L2, "AB", 1, false},
+                new Object[] {STRING_L4, "ABC", 0, true},
+                new Object[] {STRING_LLONG, "ABCDEFGH", 0, true},
+                new Object[] {STRING_LLONG, "ABCDE", 0, true},
+                new Object[] {STRING_LLONG, "CDE", 0, false},
+                new Object[] {STRING_LLONG, "FG", 5, true},
+                new Object[] {STRING_U1, "\uFF21", 0, true},
+                new Object[] {STRING_U1, "", 1, true},
+                new Object[] {STRING_U1, "\uFF21", 0, true},
+                new Object[] {STRING_U1, "A", 0, false},
+                new Object[] {STRING_U2, "\uFF21\uFF22", 0, true},
+                new Object[] {STRING_U2, "\uFF21", 0, true},
+                new Object[] {STRING_U2, "\uFF22", 0, false},
+                new Object[] {STRING_U2, "", 0, true},
+                new Object[] {STRING_M12, "\uFF21", 0, true},
+                new Object[] {STRING_M12, "\uFF21A", 0, true},
+                new Object[] {STRING_M12, "A", 0, false},
+                new Object[] {STRING_M12, "\uFF21A", 0, true},
+                new Object[] {STRING_M12, "A", 1, true},
+                new Object[] {STRING_M11, "A", 0, true},
+                new Object[] {STRING_M11, "A\uFF21", 0, true},
+                new Object[] {STRING_M11, "A\uFF21", 0, true},
+                new Object[] {STRING_M11, "\uFF21", 1, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22",
+                        0, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 0, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 2, true},
+                new Object[] {STRING_UDUPLICATE,
+                        "\uFF21\uFF22\uFF21\uFF22\uFF21\uFF22", 5, false},
+                new Object[] {STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A", 0, true},
+                new Object[] {STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21", 0, true},
+                new Object[] {STRING_MDUPLICATE1, "A\uFF21A\uFF21A\uFF21A", 1, true},
+                new Object[] {STRING_SUPPLEMENTARY, "\uDC01\uFF21", 3, true},
+        };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testStartsWith(String str, String prefix, int toffset,
+            boolean expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.startsWith(prefix, toffset),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).startsWith(%s, %d), source : %s, ",
+                                            escapeNonASCIIs(data),
+                                            escapeNonASCIIs(prefix), toffset,
+                                            source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/SubString.java b/ojluni/src/test/java/lang/String/CompactString/SubString.java
new file mode 100644
index 0000000..1a741c5
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/SubString.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.subString.
+ * @run testng/othervm -XX:+CompactStrings SubString
+ * @run testng/othervm -XX:-CompactStrings SubString
+ */
+
+public class SubString extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, 0, 0, "" },
+                new Object[] { STRING_L1, 0, 1, "A" },
+                new Object[] { STRING_L1, 1, 1, "" },
+                new Object[] { STRING_L2, 0, 2, "AB" },
+                new Object[] { STRING_L2, 1, 2, "B" },
+                new Object[] { STRING_LLONG, 0, 8, "ABCDEFGH" },
+                new Object[] { STRING_LLONG, 7, 8, "H" },
+                new Object[] { STRING_LLONG, 8, 8, "" },
+                new Object[] { STRING_LLONG, 3, 7, "DEFG" },
+                new Object[] { STRING_U1, 0, 1, "\uFF21" },
+                new Object[] { STRING_U1, 1, 1, "" },
+                new Object[] { STRING_U1, 0, 0, "" },
+                new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" },
+                new Object[] { STRING_U2, 1, 2, "\uFF22" },
+                new Object[] { STRING_U2, 2, 2, "" },
+                new Object[] { STRING_U2, 0, 2, "\uFF21\uFF22" },
+                new Object[] { STRING_U2, 1, 2, "\uFF22" },
+                new Object[] { STRING_M12, 1, 2, "A" },
+                new Object[] { STRING_M11, 0, 1, "A" },
+                new Object[] { STRING_M11, 1, 2, "\uFF21" },
+                new Object[] { STRING_UDUPLICATE, 1, 5,
+                        "\uFF22\uFF21\uFF22\uFF21" },
+                new Object[] { STRING_MDUPLICATE1, 9, 10, "A" },
+                new Object[] { STRING_MDUPLICATE1, 7, 8, "A" }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testSubstring(String str, int beginIndex, int endIndex,
+            String expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertEquals(
+                                    data.substring(beginIndex, endIndex),
+                                    expected,
+                                    String.format(
+                                            "testing String(%s).substring(%d, %d), source : %s, ",
+                                            escapeNonASCIIs(data), beginIndex,
+                                            endIndex, source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/ToCharArray.java b/ojluni/src/test/java/lang/String/CompactString/ToCharArray.java
new file mode 100644
index 0000000..4f083ae
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/ToCharArray.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import java.util.Arrays;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.toCharArray.
+ * @run testng/othervm -XX:+CompactStrings ToCharArray
+ * @run testng/othervm -XX:-CompactStrings ToCharArray
+ */
+
+public class ToCharArray extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, new char[] {} },
+                new Object[] { STRING_L1, new char[] { 'A' } },
+                new Object[] { STRING_L2, new char[] { 'A', 'B' } },
+                new Object[] { STRING_LLONG,
+                        new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' } },
+                new Object[] { STRING_U1, new char[] { '\uFF21' } },
+                new Object[] { STRING_U2, new char[] { '\uFF21', '\uFF22' } },
+                new Object[] { STRING_M12, new char[] { '\uFF21', 'A' } },
+                new Object[] { STRING_M11, new char[] { 'A', '\uFF21' } }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testToCharArray(String str, char[] expected) {
+        map.get(str)
+                .forEach(
+                        (source, data) -> {
+                            assertTrue(
+                                    Arrays.equals(data.toCharArray(), expected),
+                                    String.format(
+                                            "testing String(%s).toCharArray(), source : %s, ",
+                                            escapeNonASCIIs(data), source));
+                        });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/ToLowerCase.java b/ojluni/src/test/java/lang/String/CompactString/ToLowerCase.java
new file mode 100644
index 0000000..2be3aca
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/ToLowerCase.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.toLowerCase.
+ * @run testng/othervm -XX:+CompactStrings ToLowerCase
+ * @run testng/othervm -XX:-CompactStrings ToLowerCase
+ */
+
+public class ToLowerCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+                new Object[] { STRING_EMPTY, "" },
+                new Object[] { STRING_L1, "a" },
+                new Object[] { STRING_L2, "ab" },
+                new Object[] { STRING_U1, "\uFF41" },
+                new Object[] { STRING_MDUPLICATE1,
+                        "\uFF41a\uFF41a\uFF41a\uFF41a\uFF41a" },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        "\uD801\uDC28\uD801\uDC29\uFF41a" },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "\uD801\uDC28\uD801\uDC29\uFF41a" },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        STRING_SUPPLEMENTARY_LOWERCASE } };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testToLowerCase(String str, String expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.toLowerCase(), expected, String.format(
+                            "testing String(%s).toLowerCase(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/ToUpperCase.java b/ojluni/src/test/java/lang/String/CompactString/ToUpperCase.java
new file mode 100644
index 0000000..d27ab22
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/ToUpperCase.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.toUpperCase.
+ * @run testng/othervm -XX:+CompactStrings ToUpperCase
+ * @run testng/othervm -XX:-CompactStrings ToUpperCase
+ */
+
+public class ToUpperCase extends CompactString {
+
+    @DataProvider
+    public Object[][] provider() {
+        return new Object[][] {
+
+                new Object[] { STRING_EMPTY, "" },
+                new Object[] { STRING_L1, "A" },
+                new Object[] { STRING_L2, "AB" },
+                new Object[] { STRING_U1, "\uFF21" },
+                new Object[] { STRING_MDUPLICATE1,
+                        "\uFF21A\uFF21A\uFF21A\uFF21A\uFF21A" },
+                new Object[] { STRING_SUPPLEMENTARY,
+                        "\uD801\uDC00\uD801\uDC01\uFF21A" },
+
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        "\uD801\uDC00\uD801\uDC01\uFF21A" },
+                new Object[] { STRING_SUPPLEMENTARY_LOWERCASE,
+                        STRING_SUPPLEMENTARY }, };
+    }
+
+    @Test(dataProvider = "provider")
+    public void testToUpperCase(String str, String expected) {
+        map.get(str).forEach(
+                (source, data) -> {
+                    assertEquals(data.toUpperCase(), expected, String.format(
+                            "testing String(%s).toUpperCase(), source : %s, ",
+                            escapeNonASCIIs(data), source));
+                });
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/Trim.java b/ojluni/src/test/java/lang/String/CompactString/Trim.java
new file mode 100644
index 0000000..8467382
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/Trim.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.trim.
+ * @run testng/othervm -XX:+CompactStrings Trim
+ * @run testng/othervm -XX:-CompactStrings Trim
+ */
+
+public class Trim {
+
+    /*
+     * Data provider for testTrim
+     *
+     * @return input parameter for testTrim
+     */
+    @DataProvider
+    public Object[][] trims() {
+        return new Object[][] {
+                { " \t \t".trim(), "" },
+                { "\t \t ".trim(), "" },
+                { "\t A B C\t ".trim(), "A B C" },
+                { " \t A B C \t".trim(), "A B C" },
+                { "\t \uFF21 \uFF22 \uFF23\t ".trim(), "\uFF21 \uFF22 \uFF23" },
+                { " \t \uFF21 \uFF22 \uFF23 \t".trim(), "\uFF21 \uFF22 \uFF23" },
+                { " \t \uFF41 \uFF42 \uFF43 \t".trim(), "\uFF41 \uFF42 \uFF43" },
+                { " \t A\uFF21 B\uFF22 C\uFF23 \t".trim(),
+                        "A\uFF21 B\uFF22 C\uFF23" } };
+    }
+
+    /*
+     * test trim().
+     *
+     * @param res
+     *            real result
+     * @param expected
+     *            expected result
+     */
+    @Test(dataProvider = "trims")
+    public void testTrim(String res, String expected) {
+        assertEquals(res, expected);
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/String/CompactString/ValueOf.java b/ojluni/src/test/java/lang/String/CompactString/ValueOf.java
new file mode 100644
index 0000000..dad0829
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/CompactString/ValueOf.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.CompactString;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8077559
+ * @summary Tests Compact String. This one is for String.valueOf.
+ *          valueOf(char[] data) is not tested here.
+ * @run testng/othervm -XX:+CompactStrings ValueOf
+ * @run testng/othervm -XX:-CompactStrings ValueOf
+ */
+
+public class ValueOf {
+
+    /*
+     * Data provider for testValueOf
+     *
+     * @return input parameter for testValueOf
+     */
+    @DataProvider
+    public Object[][] valueOfs() {
+        return new Object[][] { { String.valueOf(true), "true" },
+                { String.valueOf(false), "false" },
+                { String.valueOf(1.0f), "1.0" },
+                { String.valueOf(0.0f), "0.0" },
+                { String.valueOf(Float.MAX_VALUE), "3.4028235E38" },
+                { String.valueOf(Float.MIN_VALUE), "1.4E-45" },
+                { String.valueOf(1.0d), "1.0" },
+                { String.valueOf(0.0d), "0.0" },
+                { String.valueOf(Double.MAX_VALUE), "1.7976931348623157E308" },
+                { String.valueOf(Double.MIN_VALUE), "4.9E-324" },
+                { String.valueOf(1), "1" }, { String.valueOf(0), "0" },
+                { String.valueOf(Integer.MAX_VALUE), "2147483647" },
+                { String.valueOf(Integer.MIN_VALUE), "-2147483648" },
+                { String.valueOf(1L), "1" }, { String.valueOf(0L), "0" },
+                { String.valueOf(Long.MAX_VALUE), "9223372036854775807" },
+                { String.valueOf(Long.MIN_VALUE), "-9223372036854775808" } };
+    }
+
+    /*
+     * test String.valueOf(xxx).
+     *
+     * @param res
+     *            real result
+     * @param expected
+     *            expected result
+     */
+    @Test(dataProvider = "valueOfs")
+    public void testValueOf(String res, String expected) {
+        assertEquals(res, expected);
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/String/IsBlank.java b/ojluni/src/test/java/lang/String/IsBlank.java
new file mode 100644
index 0000000..8d5e9d9
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/IsBlank.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String;
+
+// Android-added: support for wrapper to avoid d8 backporting of String.isBlank (b/191859202).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import java.util.stream.IntStream;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @test
+ * @summary Basic isBlank functionality
+ * @bug 8200436
+ * @run main/othervm IsBlank
+ */
+
+public class IsBlank {
+    /*
+     * Test with strings
+     */
+    @Test
+    public void testIsBlank() {
+        test("", true);
+        test(" ", true);
+        test(" \t", true);
+        test("  \u1680", true);
+        test("   abc   ", false);
+        test("   abc\u2022", false);
+    }
+
+    /*
+     * Test full whitespace range
+     */
+    @Test
+    void testWhitespace() {
+        StringBuilder sb = new StringBuilder(64);
+        IntStream.range(1, 0xFFFF).filter(c -> Character.isWhitespace(c))
+                .forEach(c -> sb.append((char)c));
+        String whiteSpace = sb.toString();
+
+        test(whiteSpace, true);
+        test(whiteSpace + "abc" + whiteSpace, false);
+    }
+
+    /*
+     * Raise an exception if the two inputs are not equivalent.
+     */
+    static void test(String input, boolean expected) {
+        // Android-changed: use wrapper to avoid d8 backporting (b/191859202).
+        // assertEquals(input.isBlank(), expected,
+        assertEquals(String_isBlank(input), expected,
+            String.format("Failed test, Input: %s, Expected: %b%n", input, expected));
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of String.isBlank (b/191859202).
+    private static boolean String_isBlank(String input) {
+        try {
+            MethodType isBlankType = MethodType.methodType(boolean.class);
+            MethodHandle isBlank =
+                    MethodHandles.lookup().findVirtual(String.class, "isBlank", isBlankType);
+            return (boolean) isBlank.invokeExact(input);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/Lines.java b/ojluni/src/test/java/lang/String/Lines.java
new file mode 100644
index 0000000..b8395d8
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/Lines.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Basic lines functionality
+ * @bug 8200380
+ * @run main/othervm Lines
+ */
+package test.java.lang.String;
+
+import java.util.Iterator;
+import java.util.stream.Stream;
+import java.io.BufferedReader;
+import java.io.StringReader;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.fail;
+
+public class Lines {
+    /*
+     * Test with strings
+     */
+    @Test
+    public void testLines() {
+        testString("");
+        testString(" ");
+        testString("\n");
+        testString("\n\n\n");
+        testString("\r\r\r");
+        testString("\r\n\r\n\r\n");
+        testString("\n\r\r\n");
+        testString("abc\ndef\nghi\n");
+        testString("abc\ndef\nghi");
+        testString("abc\rdef\rghi\r");
+        testString("abc\rdef\rghi");
+        testString("abc\r\ndef\r\nghi\r\n");
+        testString("abc\r\ndef\r\nghi");
+
+        testString("\2022");
+        testString("\2022\n");
+        testString("\2022\n\2022\n\2022\n");
+        testString("\2022\r\2022\r\2022\r");
+        testString("\2022\r\n\2022\r\n\2022\r\n");
+        testString("\2022\n\2022\r\2022\r\n");
+        testString("abc\2022\ndef\2022\nghi\2022\n");
+        testString("abc\2022\ndef\2022\nghi\2022");
+        testString("abc\2022\rdef\2022\rghi\2022\r");
+        testString("abc\2022\rdef\2022\rghi\2022");
+        testString("abc\2022\r\ndef\2022\r\nghi\2022\r\n");
+        testString("abc\2022\r\ndef\2022\r\nghi\2022");
+        testString("\2022\n\n\n");
+    }
+
+    static void testString(String string) {
+        Stream<String> lines = string.lines();
+        Stream<String> brLines = new BufferedReader(new StringReader(string)).lines();
+
+        Iterator<String> iterator = lines.iterator();
+        Iterator<String> brIterator = brLines.iterator();
+        int count = 0;
+
+        while (iterator.hasNext() && brIterator.hasNext()) {
+            count++;
+            String line = iterator.next();
+            String brLine = brIterator.next();
+
+            if (!line.equals(brLine)) {
+                String replace = string.replaceAll("\n", "\\n").replaceAll("\r", "\\r");
+                fail(String.format("Mismatch at line %d of \"%s\"%n", count, replace));
+            }
+        }
+
+        if (iterator.hasNext() || brIterator.hasNext()) {
+            fail(String.format("Mismatch after line %d of \"%s\"%n", count, string));
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/LiteralReplace.java b/ojluni/src/test/java/lang/String/LiteralReplace.java
new file mode 100644
index 0000000..062b7cf
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/LiteralReplace.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.lang.String;
+
+/* @test
+ * @bug 8058779 8054307
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run testng LiteralReplace
+ * @summary Basic tests of String.replace(CharSequence, CharSequence)
+ * @key randomness
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.Random;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.fail;
+
+public class LiteralReplace {
+
+    @Test(dataProvider="sourceTargetReplacementExpected")
+    public void testExpected(String source, String target,
+             String replacement, String expected)
+    {
+        String canonical = canonicalReplace(source, target, replacement);
+        if (!canonical.equals(expected)) {
+            fail("Canonical: " + canonical + " != " + expected);
+        }
+        test0(source, target, replacement, expected);
+    }
+
+    @Test(dataProvider="sourceTargetReplacement")
+    public void testCanonical(String source, String target,
+            String replacement)
+    {
+        String canonical = canonicalReplace(source, target, replacement);
+        test0(source, target, replacement, canonical);
+    }
+
+    private void test0(String source, String target, String replacement,
+            String expected)
+    {
+        String result = source.replace(target, replacement);
+        if (!result.equals(expected)) {
+            fail(result + " != " + expected);
+        }
+    }
+
+    @Test(dataProvider="sourceTargetReplacementWithNull",
+            expectedExceptions = {NullPointerException.class})
+    public void testNPE(String source, String target, String replacement) {
+        source.replace(target, replacement);
+    }
+
+
+    @DataProvider
+    public static Object[][] sourceTargetReplacementExpected() {
+        return new Object[][] {
+            {"aaa", "aa", "b", "ba"},
+            {"abcdefgh", "def", "DEF", "abcDEFgh"},
+            {"abcdefgh", "123", "DEF", "abcdefgh"},
+            {"abcdefgh", "abcdefghi", "DEF", "abcdefgh"},
+            {"abcdefghabc", "abc", "DEF", "DEFdefghDEF"},
+            {"abcdefghdef", "def", "", "abcgh"},
+            {"abcdefgh", "", "_", "_a_b_c_d_e_f_g_h_"},
+            {"", "", "", ""},
+            {"", "a", "b", ""},
+            {"", "", "abc", "abc"},
+            {"abcdefgh", "abcdefgh", "abcdefgh", "abcdefgh"},
+            {"abcdefgh", "abcdefgh", "abcdefghi", "abcdefghi"},
+            {"abcdefgh", "abcdefgh", "", ""},
+            {"abcdabcd", "abcd", "", ""},
+            {"aaaaaaaaa", "aa", "_X_", "_X__X__X__X_a"},
+            {"aaaaaaaaa", "aa", "aaa", "aaaaaaaaaaaaa"},
+            {"aaaaaaaaa", "aa", "aa", "aaaaaaaaa"},
+            {"a.c.e.g.", ".", "-", "a-c-e-g-"},
+            {"abcdefgh", "[a-h]", "X", "abcdefgh"},
+            {"aa+", "a+", "", "a"},
+            {"^abc$", "abc", "x", "^x$"},
+
+            // more with non-latin1 characters
+            {"\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00",
+             "\u4e01",
+             "\u4e01\u4e00"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08",
+             "\u4e03\u4e04\u4e05",
+             "\u4e10\u4e11\u4e12",
+             "\u4e00\u4e01\u4e02\u4e10\u4e11\u4e12\u4e06\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08",
+             "ABC",
+             "\u4e10\u4e11\u4e12",
+             "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08",
+             "\u4e02\u4e03",
+             "\u4e12\u4e13",
+             "\u4e00\u4e01\u4e12\u4e13\u4e04\u4e12\u4e13\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e02\u4e03\u4e07\u4e08",
+             "\u4e02\u4e03",
+             "ab",
+             "\u4e00\u4e01ab\u4e04ab\u4e07\u4e08"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07",
+             "",
+             "_",
+             "_\u4e00_\u4e01_\u4e02_\u4e03_\u4e04_\u4e05_\u4e06_\u4e07_"},
+            {"^\u4e00\u4e01\u4e02$",
+             "\u4e00\u4e01\u4e02",
+             "\u4e03",
+             "^\u4e03$"},
+
+            {"", "\u4e00", "\u4e01", ""},
+            {"", "", "\u4e00\u4e01\u4e02", "\u4e00\u4e01\u4e02"},
+
+            {"^\u4e00\u4e01\u4e02$",
+             "\u4e00\u4e01\u4e02",
+             "X",
+             "^X$"},
+
+            {"abcdefgh",
+             "def",
+             "\u4e01",
+             "abc\u4e01gh"},
+
+            {"abcdefgh",
+             "def",
+             "\u4e01\u4e02",
+             "abc\u4e01\u4e02gh"},
+
+            {"abcdefabcgh",
+             "abc",
+             "\u4e01\u4e02",
+             "\u4e01\u4e02def\u4e01\u4e02gh"},
+
+            {"abcdefabcghabc",
+             "abc",
+             "\u4e01\u4e02",
+             "\u4e01\u4e02def\u4e01\u4e02gh\u4e01\u4e02"},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "abcd",
+             "abcd"},
+
+            {"\u4e00\u4e01",
+             "\u4e00\u4e01",
+             "abcdefg",
+             "abcdefg"},
+
+            {"\u4e00\u4e01xyz",
+             "\u4e00\u4e01",
+             "abcdefg",
+             "abcdefgxyz"},
+
+            {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00"},
+
+            {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00",
+             "\u4e00\u4e00",
+             "\u4e00\u4e00\u4e00\u4e00"},
+
+            {"\u4e00.\u4e01.\u4e02.\u4e03.\u4e04.",
+             ".",
+             "-",
+             "\u4e00-\u4e01-\u4e02-\u4e03-\u4e04-"},
+
+            {"\u4e00\u4e00\u4e00\u4e00\u4e00\u4e00",
+             "\u4e00",
+             "",
+             ""},
+
+            {"\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05",
+             "",
+             ""},
+        };
+    }
+
+    @DataProvider
+    public static Iterator<Object[]> sourceTargetReplacement() {
+        ArrayList<Object[]> list = new ArrayList<>();
+        for (int maxSrcLen = 1; maxSrcLen <= (1 << 10); maxSrcLen <<= 1) {
+            for (int maxTrgLen = 1; maxTrgLen <= (1 << 10); maxTrgLen <<= 1) {
+                for (int maxPrlLen = 1; maxPrlLen <= (1 << 10); maxPrlLen <<= 1) {
+                    list.add(makeArray(makeRandomString(maxSrcLen),
+                                       makeRandomString(maxTrgLen),
+                                       makeRandomString(maxPrlLen)));
+
+                    String source = makeRandomString(maxSrcLen);
+                    list.add(makeArray(source,
+                                       mekeRandomSubstring(source, maxTrgLen),
+                                       makeRandomString(maxPrlLen)));
+                }
+            }
+        }
+        return list.iterator();
+    }
+
+    @DataProvider
+    public static Iterator<Object[]> sourceTargetReplacementWithNull() {
+        ArrayList<Object[]> list = new ArrayList<>();
+        Object[] arr = {null, "", "a", "b", "string", "str", "ababstrstr"};
+        for (int i = 0; i < arr.length; ++i) {
+            for (int j = 0; j < arr.length; ++j) {
+                for (int k = 0; k < arr.length; ++k) {
+                    if (arr[i] != null && (arr[j] == null || arr[k] == null)) {
+                        list.add(makeArray(arr[i], arr[j], arr[k]));
+                    }
+                }
+            }
+        }
+        return list.iterator();
+    }
+
+    // utilities
+
+    /**
+     * How the String.replace(CharSequence, CharSequence) used to be implemented
+     */
+    private static String canonicalReplace(String source, String target, String replacement) {
+        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
+                source).replaceAll(Matcher.quoteReplacement(replacement.toString()));
+    }
+
+    private static final Random random = new Random();
+
+    private static final char[] CHARS = ("qwertyuiop[]12345678" +
+        "90-=\\`asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+|QWERTYUIOP{" +
+        "}ASDFGHJKL:\"ZXCVBNM<>?\n\r\t\u0444\u044B\u0432\u0430").toCharArray();
+
+    private static String makeRandomString(int maxLen) {
+        int len = random.nextInt(maxLen);
+        char[] buf = new char[len];
+        for (int i = 0; i < len; ++i) {
+            buf[i] = CHARS[random.nextInt(CHARS.length)];
+        }
+        return new String(buf);
+    }
+
+    private static String mekeRandomSubstring(String source, int maxLen) {
+        if (source.isEmpty()) {
+            return source;
+        }
+        int pos = random.nextInt(source.length());
+        int len = Integer.min(source.length() - pos,
+                              random.nextInt(maxLen));
+        return source.substring(pos, pos + len);
+    }
+
+    private static Object[] makeArray(Object... array) {
+         return array;
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/Split.java b/ojluni/src/test/java/lang/String/Split.java
new file mode 100644
index 0000000..60a66aa
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/Split.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String;
+
+/**
+ * @test
+ * @bug 6840246 6559590
+ * @summary test String.split()
+ * @key randomness
+ */
+import java.util.Arrays;
+import java.util.Random;
+import java.util.regex.*;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+// Android-changed: migrate to testng
+public class Split {
+
+    private static final String SOURCE = "0123456789";
+    private static final String FAST_PATH_SOURCE = "0123456789abcdefgABCDEFG";
+    private static Random R;
+
+    @BeforeClass
+    public static void setUp() {
+        R = new Random();
+    }
+
+    @Test
+    public void testSplit_byDigit() {
+        for (int limit=-2; limit<3; limit++) {
+            for (int x=0; x<10; x++) {
+                String[] result = SOURCE.split(Integer.toString(x), limit);
+                int expectedLength = limit < 1 ? 2 : limit;
+
+                if ((limit == 0) && (x == 9)) {
+                    // expected dropping of ""
+                    if (result.length != 1)
+                        throw new RuntimeException("String.split failure 1");
+                    if (!result[0].equals("012345678")) {
+                        throw new RuntimeException("String.split failure 2");
+                    }
+                } else {
+                    if (result.length != expectedLength) {
+                        throw new RuntimeException("String.split failure 3");
+                    }
+                    if (!result[0].equals(SOURCE.substring(0,x))) {
+                        if (limit != 1) {
+                            throw new RuntimeException(
+                                "String.split failure 4");
+                        } else {
+                            if (!result[0].equals(SOURCE.substring(0,10))) {
+                                throw new RuntimeException(
+                                    "String.split failure 10");
+                            }
+                        }
+                    }
+                    if (expectedLength > 1) { // Check segment 2
+                        if (!result[1].equals(SOURCE.substring(x+1,10)))
+                            throw new RuntimeException("String.split failure 5");
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testSplit_noMatch() {
+        for (int limit=-2; limit<3; limit++) {
+            String[] result = SOURCE.split("e", limit);
+            if (result.length != 1)
+                throw new RuntimeException("String.split failure 6");
+            if (!result[0].equals(SOURCE))
+                throw new RuntimeException("String.split failure 7");
+        }
+    }
+
+    // Check the case for limit == 0, source = "";
+    // split() now returns 0-length for empty source "" see #6559590
+    @Test
+    public void testSplit_zeroLimit_emptySource() {
+        String source = "";
+        String[] result = source.split("e", 0);
+        if (result.length != 1)
+            throw new RuntimeException("String.split failure 8");
+        if (!result[0].equals(source))
+            throw new RuntimeException("String.split failure 9");
+    }
+
+    /**
+     * Tests fastpath of {@link java.lang.String#split(String, int)}.
+     *
+     * This test is disabled and just provides explanation of testSplitFastPath_shard*
+     * test functions family. Originally, this test was running around 50 seconds and
+     * was doing the following:
+     *
+     * <pre>
+     * for (boolean doEscape: new boolean[] {false, true}) {
+     *     for (int cp = 0; cp < 0x11000; cp++) {
+     *         ...
+     *     }
+     * }
+     * </pre>
+     *
+     * To make it faster it was sharded into five shards:
+     *
+     * 1) First shard tests {@code doEscape = false} and {@code cp = [0, 0x11000)}, i.e. full range.
+     *    It was accounted for ~10% of all time (~5s), so the whole range goes in single shard.
+     * 2-5) These four shards test {@code doEscape = true} and {@code cp} split in four equal
+     *      intervals.
+     *
+     * There is also {@link #getShardRange(int)} helper function which returns shard range.
+     */
+    @Test(enabled = false)
+    public void testSplit_fastPath() {
+    }
+
+    @Test
+    public void testSplit_fastPath_shard1_noEscape() {
+        testSplit_fastPath_(FAST_PATH_SOURCE, R, false, 0, 0x11000);
+    }
+
+    @Test
+    public void testSplit_fastPath_shard2() {
+        int[] shardRange = getShardRange(0);
+        testSplit_fastPath_(FAST_PATH_SOURCE, R, true, shardRange[0], shardRange[1]);
+    }
+
+    @Test
+    public void testSplit_fastPath_shard3() {
+        int[] shardRange = getShardRange(1);
+        testSplit_fastPath_(FAST_PATH_SOURCE, R, true, shardRange[0], shardRange[1]);
+    }
+
+    @Test
+    public void testSplit_fastPath_shard4() {
+        int[] shardRange = getShardRange(2);
+        testSplit_fastPath_(FAST_PATH_SOURCE, R, true, shardRange[0], shardRange[1]);
+    }
+
+    @Test
+    public void testSplit_fastPath_shard5() {
+        int[] shardRange = getShardRange(3);
+        testSplit_fastPath_(FAST_PATH_SOURCE, R, true, shardRange[0], shardRange[1]);
+    }
+
+    /**
+     * Calculates shard range, i.e. [start, end) by shard index,
+     * assuming there are 4 shards in total; and the whole range spans from 0 to 0x11000.
+     *
+     * @param shardIndex index of the
+     * @return int[] of size 2: [start, end).
+     */
+    private static int[] getShardRange(int shardIndex) {
+        final int SHARD_LENGTH = 0x11000;
+        final int SHARD_COUNT = 4;
+        int shardLength = SHARD_LENGTH / SHARD_COUNT;
+        int shardStart = shardIndex * shardLength;
+        int shardEnd = (shardIndex + 1) * shardLength - 1;
+        return new int[]{ shardStart, shardEnd };
+    }
+
+    private void testSplit_fastPath_(String source, Random r, boolean doEscape, int cpFrom, int cpTo) {
+        for (int cp = cpFrom; cp < cpTo; cp++) {
+            Pattern p = null;
+            String regex = new String(Character.toChars(cp));
+            if (doEscape)
+                regex = "\\" + regex;
+            try {
+                p = Pattern.compile(regex);
+            } catch (PatternSyntaxException pse) {
+                // illegal syntax
+                try {
+                    "abc".split(regex);
+                } catch (PatternSyntaxException pse0) {
+                    continue;
+                }
+                throw new RuntimeException("String.split failure 11");
+            }
+            int off = r.nextInt(source.length());
+            String[] srcStrs = new String[] {
+                "",
+                source,
+                regex + source,
+                source + regex,
+                source.substring(0, 3)
+                    + regex + source.substring(3, 9)
+                    + regex + source.substring(9, 15)
+                    + regex + source.substring(15),
+                source.substring(0, off) + regex + source.substring(off)
+            };
+            for (String src: srcStrs) {
+                for (int limit=-2; limit<3; limit++) {
+                    if (!Arrays.equals(src.split(regex, limit),
+                        p.split(src, limit)))
+                        throw new RuntimeException("String.split failure 12");
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/StringRepeat.java b/ojluni/src/test/java/lang/String/StringRepeat.java
new file mode 100644
index 0000000..23c0560
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/StringRepeat.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary This exercises String#repeat patterns and limits.
+ * @run main/othervm -Xmx4G StringRepeat
+ */
+package test.java.lang.String;
+
+// Android-added: support for wrapper to avoid d8 backporting of String.isBlank (b/191859202).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class StringRepeat {
+    /*
+     * Varitions of repeat count.
+     */
+    static int[] REPEATS = {
+        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+        32, 64, 128, 256, 512, 1024, 64 * 1024, 1024 * 1024,
+        16 * 1024 * 1024
+    };
+
+    /*
+     * Varitions of Strings.
+     */
+    static String[] STRINGS = new String[] {
+            "", "\0",  " ", "a", "$", "\u2022",
+            "ab", "abc", "abcd", "abcde",
+            "The quick brown fox jumps over the lazy dog."
+    };
+
+    /*
+     * Repeat String function tests.
+     */
+    @Test
+    public void test1() {
+        for (int repeat : REPEATS) {
+            for (String string : STRINGS) {
+                long limit = (long)string.length() * (long)repeat;
+
+                // Android-changed: lowered max length limit
+                // if ((long)(Integer.MAX_VALUE >> 1) <= limit) {
+                if ((long)(Integer.MAX_VALUE >> 5) <= limit) {
+                    break;
+                }
+
+                // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+                // verify(string.repeat(repeat), string, repeat);
+                verify(String_repeat(string, repeat), string, repeat);
+            }
+        }
+    }
+
+    /*
+     * Repeat String exception tests.
+     */
+    @Test
+    public void test2() {
+        try {
+            // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+            // "abc".repeat(-1);
+            String_repeat("abc", -1);
+            throw new RuntimeException("No exception for negative repeat count");
+        } catch (IllegalArgumentException ex) {
+            // Correct
+        }
+
+        try {
+            // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+            // "abc".repeat(Integer.MAX_VALUE - 1);
+            String_repeat("abc", Integer.MAX_VALUE - 1);
+            throw new RuntimeException("No exception for large repeat count");
+        } catch (OutOfMemoryError ex) {
+            // Correct
+        }
+    }
+
+    // Android-added: more tests
+    @Test
+    public void testEdgeCases() {
+        // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+        // Assert.assertThrows(IllegalArgumentException.class, () -> "a".repeat(-1));
+        // Assert.assertThrows(IllegalArgumentException.class, () -> "\u03B1".repeat(-1));
+        // Assert.assertThrows(OutOfMemoryError.class, () -> "\u03B1\u03B2".repeat(Integer.MAX_VALUE));
+        Assert.assertThrows(IllegalArgumentException.class, () -> String_repeat("a", -1));
+        Assert.assertThrows(IllegalArgumentException.class, () -> String_repeat("\u03B1", -1));
+        Assert.assertThrows(OutOfMemoryError.class,
+                            () -> String_repeat("\u03B1\u03B2", Integer.MAX_VALUE));
+    }
+
+    @Test
+    public void testCompressed() {
+        // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+        // Assert.assertEquals("a".repeat(0), "");
+        // Assert.assertEquals("a".repeat(1), "a");
+        // Assert.assertEquals("a".repeat(5), "aaaaa");
+        Assert.assertEquals(String_repeat("a", 0), "");
+        Assert.assertEquals(String_repeat("a", 1), "a");
+        Assert.assertEquals(String_repeat("a", 5), "aaaaa");
+
+        // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+        // Assert.assertEquals("abc".repeat(0), "");
+        // Assert.assertEquals("abc".repeat(1), "abc");
+        // Assert.assertEquals("abc".repeat(5), "abcabcabcabcabc");
+        Assert.assertEquals(String_repeat("abc", 0), "");
+        Assert.assertEquals(String_repeat("abc", 1), "abc");
+        Assert.assertEquals(String_repeat("abc", 5), "abcabcabcabcabc");
+    }
+
+    @Test
+    public void testUncompressed() {
+        // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+        // Assert.assertEquals("\u2022".repeat(0), "");
+        // Assert.assertEquals("\u2022".repeat(1), "\u2022");
+        // Assert.assertEquals("\u2022".repeat(5), "\u2022\u2022\u2022\u2022\u2022");
+        Assert.assertEquals(String_repeat("\u2022", 0), "");
+        Assert.assertEquals(String_repeat("\u2022", 1), "\u2022");
+        Assert.assertEquals(String_repeat("\u2022", 5), "\u2022\u2022\u2022\u2022\u2022");
+
+        // Android-changed: call wrappered repeat() to avoid d8 backport (b/191859202).
+        // Assert.assertEquals("\u03B1\u03B2\u03B3".repeat(0), "");
+        // Assert.assertEquals("\u03B1\u03B2\u03B3".repeat(1), "αβγ");
+        // Assert.assertEquals("\u03B1\u03B2\u03B3".repeat(5), "αβγαβγαβγαβγαβγ");
+        Assert.assertEquals(String_repeat("\u03B1\u03B2\u03B3", 0), "");
+        Assert.assertEquals(String_repeat("\u03B1\u03B2\u03B3", 1), "αβγ");
+        Assert.assertEquals(String_repeat("\u03B1\u03B2\u03B3", 5), "αβγαβγαβγαβγαβγ");
+    }
+
+    static String truncate(String string) {
+        if (string.length() < 80) {
+            return string;
+        }
+        return string.substring(0, 80) + "...";
+    }
+
+    /*
+     * Verify string repeat patterns.
+     */
+    static void verify(String result, String string, int repeat) {
+        if (string.isEmpty() || repeat == 0) {
+            if (!result.isEmpty()) {
+                String message = String.format("\"%s\".repeat(%d)%n", truncate(string), repeat) +
+                        String.format("Result \"%s\"%n", truncate(result)) +
+                        String.format("Result expected to be empty, found string of length %d%n", result.length());
+                Assert.fail(message);
+            }
+        } else {
+            int expected = 0;
+            int count = 0;
+            for (int offset = result.indexOf(string, expected);
+                 0 <= offset;
+                 offset = result.indexOf(string, expected)) {
+                count++;
+                if (offset != expected) {
+                    String message = String.format("\"%s\".repeat(%d)%n", truncate(string), repeat) +
+                            String.format("Result \"%s\"%n", truncate(result)) +
+                            String.format("Repeat expected at %d, found at = %d%n", expected, offset);
+                    Assert.fail(message);
+                }
+                expected += string.length();
+            }
+            if (count != repeat) {
+                String message = String.format("\"%s\".repeat(%d)%n", truncate(string), repeat) +
+                        String.format("Result \"%s\"%n", truncate(result)) +
+                        String.format("Repeat count expected to be %d, found %d%n", repeat, count);
+                Assert.fail(message);
+            }
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of String.isBlank (b/191859202).
+    private static String String_repeat(String input, int count) {
+        try {
+            MethodType type = MethodType.methodType(String.class, int.class);
+            MethodHandle repeat = MethodHandles.lookup().findVirtual(String.class, "repeat", type);
+            return (String) repeat.invokeExact(input, count);
+        } catch (IllegalArgumentException | OutOfMemoryError expected) {
+            throw expected;
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/Strip.java b/ojluni/src/test/java/lang/String/Strip.java
new file mode 100644
index 0000000..8d5a6b6
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/Strip.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String;
+
+// Android-added: support for wrapper to avoid d8 backporting of String.isBlank (b/191859202).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @summary Basic strip, stripLeading, stripTrailing functionality
+ * @bug 8200377
+ * @run main/othervm Strip
+ */
+
+public class Strip {
+
+    /*
+     * Test basic stripping routines
+     */
+    @Test
+    public void testStrip() {
+        // Android-changed: call wrappered string methods to avoid d8 backport (b/191859202).
+        // equal("   abc   ".strip(), "abc");
+        // equal("   abc   ".stripLeading(), "abc   ");
+        // equal("   abc   ".stripTrailing(), "   abc");
+        // equal("   abc\u2022   ".strip(), "abc\u2022");
+        // equal("   abc\u2022   ".stripLeading(), "abc\u2022   ");
+        // equal("   abc\u2022   ".stripTrailing(), "   abc\u2022");
+        // equal("".strip(), "");
+        // equal("".stripLeading(), "");
+        // equal("".stripTrailing(), "");
+        // equal("\b".strip(), "\b");
+        // equal("\b".stripLeading(), "\b");
+        // equal("\b".stripTrailing(), "\b");
+        equal(String_strip("   abc   "), "abc");
+        equal(String_stripLeading("   abc   "), "abc   ");
+        equal(String_stripTrailing("   abc   "), "   abc");
+        equal(String_strip("   abc\u2022   "), "abc\u2022");
+        equal(String_stripLeading("   abc\u2022   "), "abc\u2022   ");
+        equal(String_stripTrailing("   abc\u2022   "), "   abc\u2022");
+        equal(String_strip(""), "");
+        equal(String_stripLeading(""), "");
+        equal(String_stripTrailing(""), "");
+        equal(String_strip("\b"), "\b");
+        equal(String_stripLeading("\b"), "\b");
+        equal(String_stripTrailing("\b"), "\b");
+    }
+
+    /*
+     * Test full whitespace range
+     */
+    @Test
+    public void testWhitespace() {
+        StringBuilder sb = new StringBuilder(64);
+        IntStream.range(1, 0xFFFF).filter(c -> Character.isWhitespace(c))
+                .forEach(c -> sb.append((char)c));
+        String whiteSpace = sb.toString();
+
+        String testString = whiteSpace + "abc" + whiteSpace;
+        // Android-changed: call wrappered string methods to avoid d8 backport (b/191859202).
+        // equal(testString.strip(), "abc");
+        // equal(testString.stripLeading(), "abc"  + whiteSpace);
+        // equal(testString.stripTrailing(), whiteSpace + "abc");
+        equal(String_strip(testString), "abc");
+        equal(String_stripLeading(testString), "abc"  + whiteSpace);
+        equal(String_stripTrailing(testString), whiteSpace + "abc");
+    }
+
+    /*
+     * Report difference in result.
+     */
+    static void report(String message, String inputTag, String input,
+                       String outputTag, String output) {
+        System.err.println(message);
+        System.err.println();
+        System.err.println(inputTag);
+        System.err.println(input.codePoints()
+                .mapToObj(c -> (Integer)c)
+                .collect(Collectors.toList()));
+        System.err.println();
+        System.err.println(outputTag);
+        System.err.println(output.codePoints()
+                .mapToObj(c -> (Integer)c)
+                .collect(Collectors.toList()));
+        throw new RuntimeException();
+    }
+
+    /*
+     * Raise an exception if the two inputs are not equivalent.
+     */
+    static void equal(String input, String expected) {
+        if (input == null || expected == null || !expected.equals(input)) {
+            report("Failed equal", "Input:", input, "Expected:", expected);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of String strip methods (b/191859202).
+    private static String String_stripCommon(String method, String input) {
+        try {
+            MethodType type = MethodType.methodType(String.class);
+            MethodHandle strip = MethodHandles.lookup().findVirtual(String.class, method, type);
+            return (String) strip.invokeExact(input);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of String.strip()(b/191859202).
+    private static String String_strip(String input) {
+        return String_stripCommon("strip", input);
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of String.stripLeading() (b/191859202).
+    private static String String_stripLeading(String input) {
+        return String_stripCommon("stripLeading", input);
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of String.stripTrailing() (b/191859202).
+    private static String String_stripTrailing(String input) {
+        return String_stripCommon("stripTrailing", input);
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/concat/CompactStringsInitialCoder.java b/ojluni/src/test/java/lang/String/concat/CompactStringsInitialCoder.java
new file mode 100644
index 0000000..b32e4e6
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/CompactStringsInitialCoder.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.concat;
+
+/**
+ * @test
+ * @summary StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings
+ * @bug 8148869
+ *
+ * @compile -XDstringConcat=indy CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:+CompactStrings   CompactStringsInitialCoder
+ *
+ * @compile -XDstringConcat=indyWithConstants CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:+CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:+CompactStrings   CompactStringsInitialCoder
+ *
+ * @compile -XDstringConcat=indy CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:-CompactStrings   CompactStringsInitialCoder
+ *
+ * @compile -XDstringConcat=indyWithConstants CompactStringsInitialCoder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                           -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                     -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT               -XX:-CompactStrings   CompactStringsInitialCoder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT           -XX:-CompactStrings   CompactStringsInitialCoder
+*/
+import java.lang.StringBuilder;
+
+import org.testng.annotations.Test;
+
+public class CompactStringsInitialCoder {
+
+    static String strEmpty   = "";
+    static String strLatin1  = "\u0042";
+    static String strUTF16   = "\u4242";
+    static char   charLatin1 = '\u0042';
+    static char   charUTF16  = '\u4242';
+
+    @Test
+    public void testCompactStringsInitialCoder() {
+        test("\u0042", "" + '\u0042');
+        test("\u4242", "" + '\u4242');
+
+        test("\u0042", "" + charLatin1);
+        test("\u4242", "" + charUTF16);
+
+        test("\u0042", strEmpty + '\u0042');
+        test("\u4242", strEmpty + '\u4242');
+
+        test("\u0042\u0042", strLatin1 + '\u0042');
+        test("\u0042\u4242", strLatin1 + '\u4242');
+        test("\u4242\u0042", strUTF16  + '\u0042');
+        test("\u4242\u4242", strUTF16  + '\u4242');
+
+        test("\u0042\u0042", "\u0042" + charLatin1);
+        test("\u0042\u4242", "\u0042" + charUTF16);
+        test("\u4242\u0042", "\u4242" + charLatin1);
+        test("\u4242\u4242", "\u4242" + charUTF16);
+
+        test("\u0042\u0042", "" + charLatin1 + charLatin1);
+        test("\u0042\u4242", "" + charLatin1 + charUTF16);
+        test("\u4242\u0042", "" + charUTF16  + charLatin1);
+        test("\u4242\u4242", "" + charUTF16  + charUTF16);
+    }
+
+    public static void test(String expected, String actual) {
+       if (!expected.equals(actual)) {
+           StringBuilder sb = new StringBuilder();
+           sb.append("Expected = ");
+           sb.append(expected);
+           sb.append(", actual = ");
+           sb.append(actual);
+           throw new IllegalStateException(sb.toString());
+       }
+    }
+
+
+}
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcat.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcat.java
new file mode 100644
index 0000000..2e25db3
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcat.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.concat;
+
+/**
+ * @test
+ * @summary test implicit String concatenations
+ *
+ * @compile ImplicitStringConcat.java
+ * @run main/othervm -Xverify:all ImplicitStringConcat
+ *
+ * @compile -XDstringConcat=inline ImplicitStringConcat.java
+ * @run main/othervm -Xverify:all ImplicitStringConcat
+ *
+ * @compile -XDstringConcat=indy ImplicitStringConcat.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcat
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ *
+ * @compile -XDstringConcat=indyWithConstants ImplicitStringConcat.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcat
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcat
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcat
+*/
+import java.lang.StringBuilder;
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcat {
+
+    static boolean b = true;
+    static byte by = 42;
+    static short sh = 42;
+    static char ch = 'a';
+    static int i = 42;
+    static float fl = 42.0f;
+    static long l = 42;
+    static double d = 42.0d;
+    static String s = "foo";
+    static String sNull = null;
+    static Object o = "bar";
+    static Object oNull = null;
+    static CharSequence cs = "bar";
+    static char[] chars = new char[] {'a'};
+
+    static MyClass myCl = new MyClass();
+    static MyClassNull myClNull = new MyClassNull();
+    static Object  myCl2 = new MyClass();
+    static Object[] myArr = new Object[] { myCl };
+    static final Object[] s_myArr = new Object[] { myCl };
+
+    static StringBuffer sb = new StringBuffer("a");
+
+    @Test
+    public void testImplicitStringConcat() {
+
+        test("footrue", s + b);
+        test("foo42",   s + by);
+        test("foo42",   s + sh);
+        test("fooa",    s + ch);
+        test("foo42",   s + i);
+        test("foo42",   s + l);
+        test("foo42.0", s + fl);
+        test("foo42.0", s + d);
+        test("foofoo",  s + s);
+        test("foonull", s + sNull);
+        test("foobar",  s + o);
+        test("foonull", s + oNull);
+        test("foobar",  s + cs);
+
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append("foo");
+            sb.append(myArr.toString());
+            test(sb.toString(), s + myArr);
+        }
+
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append("foo");
+            sb.append(s_myArr.toString());
+            test(sb.toString(), s + s_myArr);
+        }
+
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append("foo[C@");
+            sb.append(Integer.toHexString(System.identityHashCode(chars)));
+            test(sb.toString(), s + chars);
+        }
+
+        test("fooa",    s + ImplicitStringConcat.sb);
+        test("foonull", s + null);
+        test("fooMyClass", s + myCl);
+        test("foonull",    s + myClNull);
+        test("fooMyClass", s + myCl2);
+
+        s = "foo";  s += b;     test("footrue", s);
+        s = "foo";  s += by;    test("foo42", s);
+        s = "foo";  s += sh;    test("foo42", s);
+        s = "foo";  s += ch;    test("fooa", s);
+        s = "foo";  s += i;     test("foo42", s);
+        s = "foo";  s += l;     test("foo42", s);
+        s = "foo";  s += fl;    test("foo42.0", s);
+        s = "foo";  s += d;     test("foo42.0", s);
+        s = "foo";  s += s;     test("foofoo", s);
+        s = "foo";  s += sNull; test("foonull", s);
+        s = "foo";  s += o;     test("foobar", s);
+        s = "foo";  s += oNull; test("foonull", s);
+        s = "foo";  s += cs;    test("foobar", s);
+
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.append("foo[C@");
+            sb.append(Integer.toHexString(System.identityHashCode(chars)));
+            s = "foo";
+            s += chars;
+            test(sb.toString(), s);
+        }
+
+        s = "foo";  s += ImplicitStringConcat.sb;    test("fooa", s);
+        s = "foo";  s += null;  test("foonull", s);
+        s = "foo";  s += myCl;  test("fooMyClass", s);
+        s = "foo";  s += myCl2; test("fooMyClass", s);
+    }
+
+    public static void test(String expected, String actual) {
+       // Fingers crossed: String concat should work.
+       if (!expected.equals(actual)) {
+           StringBuilder sb = new StringBuilder();
+           sb.append("Expected = ");
+           sb.append(expected);
+           sb.append(", actual = ");
+           sb.append(actual);
+           throw new IllegalStateException(sb.toString());
+       }
+    }
+
+    static class MyClass {
+        public String toString() {
+            return "MyClass";
+        }
+    }
+
+    static class MyClassNull {
+        public String toString() {
+            return null;
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatArgCount.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatArgCount.java
new file mode 100644
index 0000000..1115763
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatArgCount.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.concat;
+
+/**
+ * @test
+ * @summary Test multiple number of arguments to concatenate.
+ *
+ * @compile ImplicitStringConcatArgCount.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatArgCount
+ *
+ * @compile -XDallowStringFolding=false -XDstringConcat=inline ImplicitStringConcatArgCount.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatArgCount
+ *
+ * @compile -XDallowStringFolding=false -XDstringConcat=indy ImplicitStringConcatArgCount.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatArgCount
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ *
+ * @compile -XDallowStringFolding=false -XDstringConcat=indyWithConstants ImplicitStringConcatArgCount.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatArgCount
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatArgCount
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatArgCount
+*/
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcatArgCount {
+    static final String s = "f";
+    static final String s1 = "o";
+    static String s2 = "o";
+    static int i = 7;
+
+    @Test
+    public static void testImplicitStringConcatArgCount() {
+        test("fo",          s + s1);
+        test("foo",         s + s1 + s2);
+        test("foo7",        s + s1 + s2 + i);
+        test("foo77",       s + s1 + s2 + i + i);
+        test("foo777",      s + s1 + s2 + i + i + i);
+        test("foo7777",     s + s1 + s2 + i + i + i + i);
+        test("foo77777",    s + s1 + s2 + i + i + i + i + i);
+        test("foo777777",   s + s1 + s2 + i + i + i + i + i + i);
+        test("foo7777777",  s + s1 + s2 + i + i + i + i + i + i + i);
+        test("foo77777777", s + s1 + s2 + i + i + i + i + i + i + i + i);
+    }
+
+    public static void test(String expected, String actual) {
+       if (!expected.equals(actual)) {
+           StringBuilder sb = new StringBuilder();
+           sb.append("Expected = ");
+           sb.append(expected);
+           sb.append(", actual = ");
+           sb.append(actual);
+           throw new IllegalStateException(sb.toString());
+       }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatAssignLHS.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatAssignLHS.java
new file mode 100644
index 0000000..1309bb7
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatAssignLHS.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary "+=" applied to String operands can provoke side effects
+ * @bug 8204322
+ *
+ * @compile ImplicitStringConcatAssignLHS.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
+ *
+ * @compile -XDstringConcat=inline ImplicitStringConcatAssignLHS.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
+ *
+ * @compile -XDstringConcat=indy ImplicitStringConcatAssignLHS.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatAssignLHS
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ *
+ * @compile -XDstringConcat=indyWithConstants ImplicitStringConcatAssignLHS.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatAssignLHS
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatAssignLHS
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatAssignLHS
+*/
+package test.java.lang.String.concat;
+
+import java.lang.StringBuilder;
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcatAssignLHS {
+
+    static final int ARR_SIZE = 10; // enough padding to capture ill offsets
+
+    static int x;
+
+    @Test
+    public void testImplicitStringConcatAssignLHS() {
+        {
+          x = 0;
+            Object[] arr = new Object[ARR_SIZE];
+            arr[x++] += "foo";
+            check(1, "plain-plain Object[]");
+        }
+
+        {
+          x = 0;
+            getObjArray()[x++] += "foo";
+            check(2, "method-plain Object[]");
+        }
+
+        {
+          x = 0;
+            getObjArray()[getIndex()] += "foo";
+            check(2, "method-method Object[]");
+        }
+
+        {
+            x = 0;
+            String[] arr = new String[ARR_SIZE];
+            arr[x++] += "foo";
+            check(1, "plain-plain String[]");
+    }
+
+        {
+            x = 0;
+            getStringArray()[x++] += "foo";
+            check(2, "method-plain String[]");
+        }
+
+        {
+            x = 0;
+            getStringArray()[getIndex()] += "foo";
+            check(2, "method-method String[]");
+        }
+
+        {
+            x = 0;
+            CharSequence[] arr = new CharSequence[ARR_SIZE];
+            arr[x++] += "foo";
+            check(1, "plain-plain CharSequence[]");
+        }
+
+        {
+            x = 0;
+            getCharSequenceArray()[x++] += "foo";
+            check(2, "method-plain CharSequence[]");
+        }
+
+        {
+            x = 0;
+            getCharSequenceArray()[getIndex()] += "foo";
+            check(2, "method-method CharSequence[]");
+        }
+
+        {
+            x = 0;
+            new MyClass().s += "foo";
+            check(1, "MyClass::new (String)");
+        }
+
+        {
+            x = 0;
+            getMyClass().s += "foo";
+            check(1, "method MyClass::new (String)");
+        }
+
+        {
+            x = 0;
+            new MyClass().o += "foo";
+            check(1, "MyClass::new (object)");
+        }
+
+        {
+            x = 0;
+            getMyClass().o += "foo";
+            check(1, "method MyClass::new (object)");
+        }
+    }
+
+    public static void check(int expected, String label) {
+        if (x != expected) {
+           StringBuilder sb = new StringBuilder();
+           sb.append(label);
+           sb.append(": ");
+           sb.append("Expected = ");
+           sb.append(expected);
+           sb.append("actual = ");
+           sb.append(x);
+           throw new IllegalStateException(sb.toString());
+        }
+    }
+
+    public static int getIndex() {
+       return x++;
+    }
+
+    public static class MyClass {
+        Object o;
+        String s;
+
+        public MyClass() {
+       x++;
+        }
+    }
+
+    public static MyClass getMyClass() {
+        return new MyClass();
+}
+
+    public static Object[] getObjArray() {
+        x++;
+        return new Object[ARR_SIZE];
+    }
+
+    public static String[] getStringArray() {
+        x++;
+        return new String[ARR_SIZE];
+    }
+
+    public static CharSequence[] getCharSequenceArray() {
+        x++;
+        return new String[ARR_SIZE];
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatBoundaries.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatBoundaries.java
new file mode 100644
index 0000000..512c498
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatBoundaries.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.concat;
+
+/**
+ * @test
+ * @summary Test the boundary values for concatenation arguments.
+ *
+ * @compile ImplicitStringConcatBoundaries.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
+ *
+ * @compile -XDstringConcat=inline ImplicitStringConcatBoundaries.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
+ *
+ * @compile -XDstringConcat=indy ImplicitStringConcatBoundaries.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatBoundaries
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ *
+ * @compile -XDstringConcat=indyWithConstants ImplicitStringConcatBoundaries.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatBoundaries
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatBoundaries
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatBoundaries
+
+*/
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcatBoundaries {
+
+    public static final boolean BOOL_TRUE_1         = true;
+    public static       boolean BOOL_TRUE_2         = true;
+    public static final boolean BOOL_FALSE_1        = false;
+    public static       boolean BOOL_FALSE_2        = false;
+
+    public static final byte    BYTE_MIN_1          = Byte.MIN_VALUE;
+    public static       byte    BYTE_MIN_2          = Byte.MIN_VALUE;
+    public static final byte    BYTE_MAX_1          = Byte.MAX_VALUE;
+    public static       byte    BYTE_MAX_2          = Byte.MAX_VALUE;
+
+    public static final short   SHORT_MIN_1         = Short.MIN_VALUE;
+    public static       short   SHORT_MIN_2         = Short.MIN_VALUE;
+    public static final short   SHORT_MAX_1         = Short.MAX_VALUE;
+    public static       short   SHORT_MAX_2         = Short.MAX_VALUE;
+
+    public static final char    CHAR_MIN_1          = Character.MIN_VALUE;
+    public static       char    CHAR_MIN_2          = Character.MIN_VALUE;
+    public static final char    CHAR_MAX_1          = Character.MAX_VALUE;
+    public static       char    CHAR_MAX_2          = Character.MAX_VALUE;
+
+    public static final int     INT_MIN_1           = Integer.MIN_VALUE;
+    public static       int     INT_MIN_2           = Integer.MIN_VALUE;
+    public static final int     INT_MAX_1           = Integer.MAX_VALUE;
+    public static       int     INT_MAX_2           = Integer.MAX_VALUE;
+
+    public static final float   FLOAT_MIN_EXP_1     = Float.MIN_EXPONENT;
+    public static       float   FLOAT_MIN_EXP_2     = Float.MIN_EXPONENT;
+    public static final float   FLOAT_MIN_NORM_1    = Float.MIN_NORMAL;
+    public static       float   FLOAT_MIN_NORM_2    = Float.MIN_NORMAL;
+    public static final float   FLOAT_MIN_1         = Float.MIN_VALUE;
+    public static       float   FLOAT_MIN_2         = Float.MIN_VALUE;
+    public static final float   FLOAT_MAX_1         = Float.MAX_VALUE;
+    public static       float   FLOAT_MAX_2         = Float.MAX_VALUE;
+
+    public static final long    LONG_MIN_1          = Long.MIN_VALUE;
+    public static       long    LONG_MIN_2          = Long.MIN_VALUE;
+    public static final long    LONG_MAX_1          = Long.MAX_VALUE;
+    public static       long    LONG_MAX_2          = Long.MAX_VALUE;
+
+    public static final double  DOUBLE_MIN_EXP_1    = Double.MIN_EXPONENT;
+    public static       double  DOUBLE_MIN_EXP_2    = Double.MIN_EXPONENT;
+    public static final double  DOUBLE_MIN_NORM_1   = Double.MIN_NORMAL;
+    public static       double  DOUBLE_MIN_NORM_2   = Double.MIN_NORMAL;
+    public static final double  DOUBLE_MIN_1        = Double.MIN_VALUE;
+    public static       double  DOUBLE_MIN_2        = Double.MIN_VALUE;
+    public static final double  DOUBLE_MAX_1        = Double.MAX_VALUE;
+    public static       double  DOUBLE_MAX_2        = Double.MAX_VALUE;
+
+    @Test
+    public void testImplicitStringConcatBoundaries() {
+        test("foofalse",                    "foo" + BOOL_FALSE_1);
+        test("foofalse",                    "foo" + BOOL_FALSE_2);
+        test("footrue",                     "foo" + BOOL_TRUE_1);
+        test("footrue",                     "foo" + BOOL_TRUE_2);
+
+        test("foo127",                      "foo" + BYTE_MAX_1);
+        test("foo127",                      "foo" + BYTE_MAX_2);
+        test("foo-128",                     "foo" + BYTE_MIN_1);
+        test("foo-128",                     "foo" + BYTE_MIN_2);
+
+        test("foo32767",                    "foo" + SHORT_MAX_1);
+        test("foo32767",                    "foo" + SHORT_MAX_2);
+        test("foo-32768",                   "foo" + SHORT_MIN_1);
+        test("foo-32768",                   "foo" + SHORT_MIN_2);
+
+        test("foo\u0000",                   "foo" + CHAR_MIN_1);
+        test("foo\u0000",                   "foo" + CHAR_MIN_2);
+        test("foo\uFFFF",                   "foo" + CHAR_MAX_1);
+        test("foo\uFFFF",                   "foo" + CHAR_MAX_2);
+
+        test("foo2147483647",               "foo" + INT_MAX_1);
+        test("foo2147483647",               "foo" + INT_MAX_2);
+        test("foo-2147483648",              "foo" + INT_MIN_1);
+        test("foo-2147483648",              "foo" + INT_MIN_2);
+
+        test("foo1.17549435E-38",           "foo" + FLOAT_MIN_NORM_1);
+        test("foo1.17549435E-38",           "foo" + FLOAT_MIN_NORM_2);
+        test("foo-126.0",                   "foo" + FLOAT_MIN_EXP_1);
+        test("foo-126.0",                   "foo" + FLOAT_MIN_EXP_2);
+        test("foo1.4E-45",                  "foo" + FLOAT_MIN_1);
+        test("foo1.4E-45",                  "foo" + FLOAT_MIN_2);
+        test("foo3.4028235E38",             "foo" + FLOAT_MAX_1);
+        test("foo3.4028235E38",             "foo" + FLOAT_MAX_2);
+
+        test("foo-9223372036854775808",     "foo" + LONG_MIN_1);
+        test("foo-9223372036854775808",     "foo" + LONG_MIN_2);
+        test("foo9223372036854775807",      "foo" + LONG_MAX_1);
+        test("foo9223372036854775807",      "foo" + LONG_MAX_2);
+
+        test("foo2.2250738585072014E-308",  "foo" + DOUBLE_MIN_NORM_1);
+        test("foo2.2250738585072014E-308",  "foo" + DOUBLE_MIN_NORM_2);
+        test("foo-1022.0",                  "foo" + DOUBLE_MIN_EXP_1);
+        test("foo-1022.0",                  "foo" + DOUBLE_MIN_EXP_2);
+        test("foo4.9E-324",                 "foo" + DOUBLE_MIN_1);
+        test("foo4.9E-324",                 "foo" + DOUBLE_MIN_2);
+        test("foo1.7976931348623157E308",   "foo" + DOUBLE_MAX_1);
+        test("foo1.7976931348623157E308",   "foo" + DOUBLE_MAX_2);
+    }
+
+    public static void test(String expected, String actual) {
+       if (!expected.equals(actual)) {
+           StringBuilder sb = new StringBuilder();
+           sb.append("Expected = ");
+           sb.append(expected);
+           sb.append(", actual = ");
+           sb.append(actual);
+           throw new IllegalStateException(sb.toString());
+       }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatMany.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatMany.java
new file mode 100644
index 0000000..8a209f3
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatMany.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Test implicit String concatenations with lots of arguments.
+ *
+ * @compile ImplicitStringConcatMany.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatMany
+ *
+ * @compile -XDstringConcat=inline ImplicitStringConcatMany.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatMany
+ *
+ * @compile -XDstringConcat=indy ImplicitStringConcatMany.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatMany
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ *
+ * @compile -XDstringConcat=indyWithConstants ImplicitStringConcatMany.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatMany
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatMany
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatMany
+*/
+package test.java.lang.String.concat;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcatMany {
+
+    static String s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
+    static String s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
+    static String s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
+    static String s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
+    static String s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
+    static String s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
+    static String s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
+    static String s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
+    static String s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
+    static String s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
+
+    static String s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
+    static String s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
+    static String s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
+    static String s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
+    static String s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
+    static String s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
+    static String s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
+    static String s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
+    static String s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
+    static String s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
+
+    static String s200, s201, s202, s203, s204, s205, s206, s207, s208, s209;
+    static String s210, s211, s212, s213, s214, s215, s216, s217, s218, s219;
+    static String s220, s221, s222, s223, s224, s225, s226, s227, s228, s229;
+    static String s230, s231, s232, s233, s234, s235, s236, s237, s238, s239;
+    static String s240, s241, s242, s243, s244, s245, s246, s247, s248, s249;
+    static String s250, s251, s252, s253, s254, s255, s256, s257, s258, s259;
+    static String s260, s261, s262, s263, s264, s265, s266, s267, s268, s269;
+    static String s270, s271, s272, s273, s274, s275, s276, s277, s278, s279;
+    static String s280, s281, s282, s283, s284, s285, s286, s287, s288, s289;
+    static String s290, s291, s292, s293, s294, s295, s296, s297, s298, s299;
+
+    static {
+        for (Field f : ImplicitStringConcatMany.class.getDeclaredFields()) {
+            if (Modifier.isStatic(f.getModifiers())) {
+                String name = f.getName();
+                // Android-added: jacoco injects static fields and crashes (b/203822631).
+                if (f.getType() != String.class || !isConcatStringFieldName(name)) {
+                    continue;
+                }
+                try {
+                    f.set(null, name);
+                } catch (IllegalAccessException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        }
+    }
+
+
+    // Android-added: jacoco injects static fields and crashes (b/203822631).
+    static boolean isConcatStringFieldName(String name) {
+        // String fields in the test are named 's[0-9]{3}'
+        return (name.length() == 4 &&
+                name.charAt(0) == 's' &&
+                Character.isDigit(name.charAt(1)) &&
+                Character.isDigit(name.charAt(2)) &&
+                Character.isDigit(name.charAt(3)));
+    }
+
+    @Test
+    public void testImplicitStringConcatMany() {
+        String res =
+            s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
+            s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
+            s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
+            s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
+            s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
+            s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
+            s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
+            s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
+            s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
+            s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
+
+            s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
+            s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
+            s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
+            s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
+            s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
+            s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
+            s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
+            s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
+            s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
+            s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199 +
+
+            s200 + s201 + s202 + s203 + s204 + s205 + s206 + s207 + s208 + s209 +
+            s210 + s211 + s212 + s213 + s214 + s215 + s216 + s217 + s218 + s219 +
+            s220 + s221 + s222 + s223 + s224 + s225 + s226 + s227 + s228 + s229 +
+            s230 + s231 + s232 + s233 + s234 + s235 + s236 + s237 + s238 + s239 +
+            s240 + s241 + s242 + s243 + s244 + s245 + s246 + s247 + s248 + s249 +
+            s250 + s251 + s252 + s253 + s254 + s255 + s256 + s257 + s258 + s259 +
+            s260 + s261 + s262 + s263 + s264 + s265 + s266 + s267 + s268 + s269 +
+            s270 + s271 + s272 + s273 + s274 + s275 + s276 + s277 + s278 + s279 +
+            s280 + s281 + s282 + s283 + s284 + s285 + s286 + s287 + s288 + s289 +
+            s290 + s291 + s292 + s293 + s294 + s295 + s296 + s297 + s298 + s299;
+
+       StringBuilder sb = new StringBuilder();
+       for (int c = 0; c < 300; c++) {
+            sb.append(String.format("s%03d", c));
+       }
+       test(sb.toString(), res);
+    }
+
+    public static void test(String expected, String actual) {
+       // Fingers crossed: String concat should work.
+       if (!expected.equals(actual)) {
+          throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
+       }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatManyLongs.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatManyLongs.java
new file mode 100644
index 0000000..256a081
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatManyLongs.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Test implicit String concatenations with lots of arguments (two-slot version)
+ *
+ * @compile ImplicitStringConcatManyLongs.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
+ *
+ * @compile -XDstringConcat=inline ImplicitStringConcatManyLongs.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
+ *
+ * @compile -XDstringConcat=indy ImplicitStringConcatManyLongs.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatManyLongs
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ *
+ * @compile -XDstringConcat=indyWithConstants ImplicitStringConcatManyLongs.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatManyLongs
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatManyLongs
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatManyLongs
+*/
+package test.java.lang.String.concat;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcatManyLongs {
+
+    static long s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
+    static long s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
+    static long s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
+    static long s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
+    static long s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
+    static long s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
+    static long s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
+    static long s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
+    static long s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
+    static long s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
+
+    static long s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
+    static long s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
+    static long s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
+    static long s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
+    static long s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
+    static long s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
+    static long s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
+    static long s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
+    static long s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
+    static long s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
+
+    static long s200, s201, s202, s203, s204, s205, s206, s207, s208, s209;
+    static long s210, s211, s212, s213, s214, s215, s216, s217, s218, s219;
+    static long s220, s221, s222, s223, s224, s225, s226, s227, s228, s229;
+    static long s230, s231, s232, s233, s234, s235, s236, s237, s238, s239;
+    static long s240, s241, s242, s243, s244, s245, s246, s247, s248, s249;
+    static long s250, s251, s252, s253, s254, s255, s256, s257, s258, s259;
+    static long s260, s261, s262, s263, s264, s265, s266, s267, s268, s269;
+    static long s270, s271, s272, s273, s274, s275, s276, s277, s278, s279;
+    static long s280, s281, s282, s283, s284, s285, s286, s287, s288, s289;
+    static long s290, s291, s292, s293, s294, s295, s296, s297, s298, s299;
+
+    static {
+        for (Field f : ImplicitStringConcatManyLongs.class.getDeclaredFields()) {
+            if (Modifier.isStatic(f.getModifiers())) {
+                String name = f.getName();
+                try {
+                    f.set(null, Long.valueOf(name.substring(1)));
+                } catch (IllegalAccessException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testImplicitStringConcatManyLongs() {
+        String res = "" +
+            s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
+            s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
+            s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
+            s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
+            s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
+            s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
+            s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
+            s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
+            s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
+            s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
+
+            s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
+            s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
+            s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
+            s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
+            s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
+            s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
+            s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
+            s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
+            s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
+            s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199 +
+
+            s200 + s201 + s202 + s203 + s204 + s205 + s206 + s207 + s208 + s209 +
+            s210 + s211 + s212 + s213 + s214 + s215 + s216 + s217 + s218 + s219 +
+            s220 + s221 + s222 + s223 + s224 + s225 + s226 + s227 + s228 + s229 +
+            s230 + s231 + s232 + s233 + s234 + s235 + s236 + s237 + s238 + s239 +
+            s240 + s241 + s242 + s243 + s244 + s245 + s246 + s247 + s248 + s249 +
+            s250 + s251 + s252 + s253 + s254 + s255 + s256 + s257 + s258 + s259 +
+            s260 + s261 + s262 + s263 + s264 + s265 + s266 + s267 + s268 + s269 +
+            s270 + s271 + s272 + s273 + s274 + s275 + s276 + s277 + s278 + s279 +
+            s280 + s281 + s282 + s283 + s284 + s285 + s286 + s287 + s288 + s289 +
+            s290 + s291 + s292 + s293 + s294 + s295 + s296 + s297 + s298 + s299;
+
+       StringBuilder sb = new StringBuilder();
+       for (int c = 0; c < 300; c++) {
+            sb.append(c);
+       }
+       test(sb.toString(), res);
+    }
+
+    public static void test(String expected, String actual) {
+       // Fingers crossed: String concat should work.
+       if (!expected.equals(actual)) {
+          throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
+       }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatOrder.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatOrder.java
new file mode 100644
index 0000000..5d69b59
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatOrder.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Test implicit string concat calls argument conversions in the right order
+ * @bug 8200118
+ *
+ * @compile ImplicitStringConcatOrder.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatOrder
+ *
+ * @compile -XDstringConcat=inline ImplicitStringConcatOrder.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatOrder
+ *
+ * @compile -XDstringConcat=indy ImplicitStringConcatOrder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatOrder
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ *
+ * @compile -XDstringConcat=indyWithConstants ImplicitStringConcatOrder.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatOrder
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatOrder
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatOrder
+*/
+package test.java.lang.String.concat;
+
+import java.lang.StringBuilder;
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcatOrder {
+
+    static MyClass c = new MyClass();
+
+    @Test
+    public void testImplicitStringConcatOrder() {
+        test("foo123bar",    "foo" + c + c + c + "bar");
+        test("bazxyz456abc", "baz" + ("xyz" + c + c) + c + "abc");
+        test("caf7eba89be",  "caf" + c + ("eba" + c + c) + "be");
+    }
+
+    public static void test(String expected, String actual) {
+       if (!expected.equals(actual)) {
+           StringBuilder sb = new StringBuilder();
+           sb.append("Expected = ");
+           sb.append(expected);
+           sb.append(", actual = ");
+           sb.append(actual);
+           throw new IllegalStateException(sb.toString());
+       }
+    }
+
+    static class MyClass {
+        int x;
+        public String toString() {
+            return String.valueOf(++x);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatShapes.java b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatShapes.java
new file mode 100644
index 0000000..4256ee2
--- /dev/null
+++ b/ojluni/src/test/java/lang/String/concat/ImplicitStringConcatShapes.java
@@ -0,0 +1,5936 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.String.concat;
+
+/**
+ * @test
+ * @summary Test implicit String concatenations, multiple shapes.
+ *
+ * @compile ImplicitStringConcatShapes.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatShapes
+ *
+ * @compile -XDstringConcat=inline ImplicitStringConcatShapes.java
+ * @run main/othervm -Xverify:all ImplicitStringConcatShapes
+ *
+ * @compile -XDstringConcat=indy ImplicitStringConcatShapes.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatShapes
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ *
+ * @compile -XDstringConcat=indyWithConstants ImplicitStringConcatShapes.java
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              ImplicitStringConcatShapes
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  ImplicitStringConcatShapes
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED                                                        -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT                                                  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT                                              -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ *
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  -Djava.lang.invoke.stringConcat.debug=true  -Djava.lang.invoke.stringConcat.cache=true  ImplicitStringConcatShapes
+*/
+
+import org.testng.annotations.Test;
+
+public class ImplicitStringConcatShapes {
+    public static void test(String expected, String actual) {
+        // Fingers crossed: String concat should work.
+        if (!expected.equals(actual)) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("Expected = ");
+            sb.append(expected);
+            sb.append(", actual = ");
+            sb.append(actual);
+            throw new IllegalStateException(sb.toString());
+        }
+    }
+
+    static class MyClass {
+        private final int i;
+
+        public MyClass(int i) {
+            this.i = i;
+        }
+
+        public String toString() {
+            return new StringBuilder("C(").append(i).append(")").toString();
+        }
+    }
+
+    static class MyClassNullToString {
+        public String toString() {
+            return null;
+        }
+    }
+
+    @Test
+    public void testImplicitStringConcatShapes() {
+        run();
+    }
+    static final boolean sf_bl = true;
+    static final byte sf_b = 80;
+    static final byte sf_bM = -41;
+    static final char sf_c = 'C';
+    static final short sf_s = 5500;
+    static final short sf_sM = -8400;
+    static final int sf_i = 75000000;
+    static final int sf_iM = -2000000;
+    static final Integer sf_I = 1000000;
+    static final Integer sf_IN = null;
+    static final float sf_f = 17.0f;
+    static final float sf_fM = -42.0f;
+    static final long sf_l = -194313216L;
+    static final long sf_lM = -1705032704L;
+    static final double sf_d = 12.0d;
+    static final double sf_dM = -84.0d;
+    static final Object sf_o = new MyClass(87);
+    static final Object sf_oN = null;
+    static final Object sf_oNtS = new MyClassNullToString();
+    static final String sf_str = "75";
+    static final String sf_strU = "\u04511";
+    static final String sf_strU1 = "\u000151";
+    static final String sf_strU2 = "\u000292";
+    static final int[] sf_iAN = null;
+    static final Object[] sf_oAN = null;
+    static  boolean s_bl = true;
+    static  byte s_b = 25;
+    static  byte s_bM = -43;
+    static  char s_c = 'T';
+    static  short s_s = 3900;
+    static  short s_sM = -2900;
+    static  int s_i = 97000000;
+    static  int s_iM = -1000000;
+    static  Integer s_I = 25000000;
+    static  Integer s_IN = null;
+    static  float s_f = 55.0f;
+    static  float s_fM = -52.0f;
+    static  long s_l = 935228928L;
+    static  long s_lM = -1410065408L;
+    static  double s_d = 8.0d;
+    static  double s_dM = -96.0d;
+    static  Object s_o = new MyClass(82);
+    static  Object s_oN = null;
+    static  Object s_oNtS = new MyClassNullToString();
+    static  String s_str = "18";
+    static  String s_strU = "\u045180";
+    static  String s_strU1 = "\u000112";
+    static  String s_strU2 = "\u000291";
+    static  int[] s_iAN = null;
+    static  Object[] s_oAN = null;
+     final boolean f_bl = false;
+     final byte f_b = 44;
+     final byte f_bM = -54;
+     final char f_c = 'I';
+     final short f_s = 8000;
+     final short f_sM = -9900;
+     final int f_i = 58000000;
+     final int f_iM = -55000000;
+     final Integer f_I = 94000000;
+     final Integer f_IN = null;
+     final float f_f = 94.0f;
+     final float f_fM = -87.0f;
+     final long f_l = 1460392448L;
+     final long f_lM = -820130816L;
+     final double f_d = 83.0d;
+     final double f_dM = -99.0d;
+     final Object f_o = new MyClass(70);
+     final Object f_oN = null;
+     final Object f_oNtS = new MyClassNullToString();
+     final String f_str = "19";
+     final String f_strU = "\u045176";
+     final String f_strU1 = "\u000121";
+     final String f_strU2 = "\u000218";
+     final int[] f_iAN = null;
+     final Object[] f_oAN = null;
+
+    public void run() {
+        run0();
+        run1();
+        run2();
+        run3();
+        run4();
+        run5();
+    }
+
+    public void run0() {
+        test("-96.0", "" + s_dM);
+        test("null", "" + s_oNtS);
+        test("\u045176", "" + f_strU);
+        test("92", "" + sf_strU2);
+        test("51", "" + sf_strU1);
+        test("null", "" + s_iAN);
+        test("-54", "" + f_bM);
+        test("-87.0", "" + f_fM);
+        test("null", "" + s_oAN);
+        test("19", "" + f_str);
+        test("-41", "" + sf_bM);
+        test("null", "" + sf_IN);
+        test("T", "" + s_c);
+        test("-42.0", "" + sf_fM);
+        test("25", "" + s_b);
+        test("null", "" + f_oN);
+        test("-1410065408", "" + s_lM);
+        test("8.0", "" + s_d);
+        test("55.0", "" + s_f);
+        test("97000000", "" + s_i);
+        test("-9900", "" + f_sM);
+        test("935228928", "" + s_l);
+        test("-8400", "" + sf_sM);
+        test("C(82)", "" + s_o);
+        test("null", "" + sf_oNtS);
+        test("true", "" + s_bl);
+        test("3900", "" + s_s);
+        test("null", "" + sf_oN);
+        test("94000000", "" + f_I);
+        test("null", "" + f_IN);
+        test("true", "" + sf_bl);
+        test("5500", "" + sf_s);
+        test("-2900", "" + s_sM);
+        test("-194313216", "" + sf_l);
+        test("12", "" + s_strU1);
+        test("C(87)", "" + sf_o);
+        test("91", "" + s_strU2);
+        test("21", "" + f_strU1);
+        test("18", "" + f_strU2);
+        test("null", "" + f_iAN);
+        test("null", "" + s_oN);
+        test("\u045180", "" + s_strU);
+        test("C", "" + sf_c);
+        test("75", "" + sf_str);
+        test("-43", "" + s_bM);
+        test("80", "" + sf_b);
+        test("null", "" + s_IN);
+        test("-52.0", "" + s_fM);
+        test("75000000", "" + sf_i);
+        test("44", "" + f_b);
+        test("-1705032704", "" + sf_lM);
+        test("null", "" + f_oAN);
+        test("83.0", "" + f_d);
+        test("I", "" + f_c);
+        test("94.0", "" + f_f);
+        test("12.0", "" + sf_d);
+        test("-99.0", "" + f_dM);
+        test("17.0", "" + sf_f);
+        test("-84.0", "" + sf_dM);
+        test("58000000", "" + f_i);
+        test("-55000000", "" + f_iM);
+        test("1460392448", "" + f_l);
+        test("C(70)", "" + f_o);
+        test("\u04511", "" + sf_strU);
+        test("8000", "" + f_s);
+        test("18", "" + s_str);
+        test("-1000000", "" + s_iM);
+        test("1000000", "" + sf_I);
+        test("null", "" + f_oNtS);
+        test("false", "" + f_bl);
+        test("null", "" + sf_iAN);
+        test("-2000000", "" + sf_iM);
+        test("-820130816", "" + f_lM);
+        test("null", "" + sf_oAN);
+        test("25000000", "" + s_I);
+        test("-96.0-96.0", "" + s_dM + s_dM);
+        test("-96.0null", "" + s_dM + s_oNtS);
+        test("-96.0\u045176", "" + s_dM + f_strU);
+        test("-96.092", "" + s_dM + sf_strU2);
+        test("-96.051", "" + s_dM + sf_strU1);
+        test("-96.0null", "" + s_dM + s_iAN);
+        test("-96.0-54", "" + s_dM + f_bM);
+        test("-96.0-87.0", "" + s_dM + f_fM);
+        test("-96.0null", "" + s_dM + s_oAN);
+        test("-96.019", "" + s_dM + f_str);
+        test("-96.0-41", "" + s_dM + sf_bM);
+        test("-96.0null", "" + s_dM + sf_IN);
+        test("-96.0T", "" + s_dM + s_c);
+        test("-96.0-42.0", "" + s_dM + sf_fM);
+        test("-96.025", "" + s_dM + s_b);
+        test("-96.0null", "" + s_dM + f_oN);
+        test("-96.0-1410065408", "" + s_dM + s_lM);
+        test("-96.08.0", "" + s_dM + s_d);
+        test("-96.055.0", "" + s_dM + s_f);
+        test("-96.097000000", "" + s_dM + s_i);
+        test("-96.0-9900", "" + s_dM + f_sM);
+        test("-96.0935228928", "" + s_dM + s_l);
+        test("-96.0-8400", "" + s_dM + sf_sM);
+        test("-96.0C(82)", "" + s_dM + s_o);
+        test("-96.0null", "" + s_dM + sf_oNtS);
+        test("-96.0true", "" + s_dM + s_bl);
+        test("-96.03900", "" + s_dM + s_s);
+        test("-96.0null", "" + s_dM + sf_oN);
+        test("-96.094000000", "" + s_dM + f_I);
+        test("-96.0null", "" + s_dM + f_IN);
+        test("-96.0true", "" + s_dM + sf_bl);
+        test("-96.05500", "" + s_dM + sf_s);
+        test("-96.0-2900", "" + s_dM + s_sM);
+        test("-96.0-194313216", "" + s_dM + sf_l);
+        test("-96.012", "" + s_dM + s_strU1);
+        test("-96.0C(87)", "" + s_dM + sf_o);
+        test("-96.091", "" + s_dM + s_strU2);
+        test("-96.021", "" + s_dM + f_strU1);
+        test("-96.018", "" + s_dM + f_strU2);
+        test("-96.0null", "" + s_dM + f_iAN);
+        test("-96.0null", "" + s_dM + s_oN);
+        test("-96.0\u045180", "" + s_dM + s_strU);
+        test("-96.0C", "" + s_dM + sf_c);
+        test("-96.075", "" + s_dM + sf_str);
+        test("-96.0-43", "" + s_dM + s_bM);
+        test("-96.080", "" + s_dM + sf_b);
+        test("-96.0null", "" + s_dM + s_IN);
+        test("-96.0-52.0", "" + s_dM + s_fM);
+        test("-96.075000000", "" + s_dM + sf_i);
+        test("-96.044", "" + s_dM + f_b);
+        test("-96.0-1705032704", "" + s_dM + sf_lM);
+        test("-96.0null", "" + s_dM + f_oAN);
+        test("-96.083.0", "" + s_dM + f_d);
+        test("-96.0I", "" + s_dM + f_c);
+        test("-96.094.0", "" + s_dM + f_f);
+        test("-96.012.0", "" + s_dM + sf_d);
+        test("-96.0-99.0", "" + s_dM + f_dM);
+        test("-96.017.0", "" + s_dM + sf_f);
+        test("-96.0-84.0", "" + s_dM + sf_dM);
+        test("-96.058000000", "" + s_dM + f_i);
+        test("-96.0-55000000", "" + s_dM + f_iM);
+        test("-96.01460392448", "" + s_dM + f_l);
+        test("-96.0C(70)", "" + s_dM + f_o);
+        test("-96.0\u04511", "" + s_dM + sf_strU);
+        test("-96.08000", "" + s_dM + f_s);
+        test("-96.018", "" + s_dM + s_str);
+        test("-96.0-1000000", "" + s_dM + s_iM);
+        test("-96.01000000", "" + s_dM + sf_I);
+        test("-96.0null", "" + s_dM + f_oNtS);
+        test("-96.0false", "" + s_dM + f_bl);
+        test("-96.0null", "" + s_dM + sf_iAN);
+        test("-96.0-2000000", "" + s_dM + sf_iM);
+        test("-96.0-820130816", "" + s_dM + f_lM);
+        test("-96.0null", "" + s_dM + sf_oAN);
+        test("-96.025000000", "" + s_dM + s_I);
+        test("null-96.0", "" + s_oNtS + s_dM);
+        test("nullnull", "" + s_oNtS + s_oNtS);
+        test("null\u045176", "" + s_oNtS + f_strU);
+        test("null92", "" + s_oNtS + sf_strU2);
+        test("null51", "" + s_oNtS + sf_strU1);
+        test("nullnull", "" + s_oNtS + s_iAN);
+        test("null-54", "" + s_oNtS + f_bM);
+        test("null-87.0", "" + s_oNtS + f_fM);
+        test("nullnull", "" + s_oNtS + s_oAN);
+        test("null19", "" + s_oNtS + f_str);
+        test("null-41", "" + s_oNtS + sf_bM);
+        test("nullnull", "" + s_oNtS + sf_IN);
+        test("nullT", "" + s_oNtS + s_c);
+        test("null-42.0", "" + s_oNtS + sf_fM);
+        test("null25", "" + s_oNtS + s_b);
+        test("nullnull", "" + s_oNtS + f_oN);
+        test("null-1410065408", "" + s_oNtS + s_lM);
+        test("null8.0", "" + s_oNtS + s_d);
+        test("null55.0", "" + s_oNtS + s_f);
+        test("null97000000", "" + s_oNtS + s_i);
+        test("null-9900", "" + s_oNtS + f_sM);
+        test("null935228928", "" + s_oNtS + s_l);
+        test("null-8400", "" + s_oNtS + sf_sM);
+        test("nullC(82)", "" + s_oNtS + s_o);
+        test("nullnull", "" + s_oNtS + sf_oNtS);
+        test("nulltrue", "" + s_oNtS + s_bl);
+        test("null3900", "" + s_oNtS + s_s);
+        test("nullnull", "" + s_oNtS + sf_oN);
+        test("null94000000", "" + s_oNtS + f_I);
+        test("nullnull", "" + s_oNtS + f_IN);
+        test("nulltrue", "" + s_oNtS + sf_bl);
+        test("null5500", "" + s_oNtS + sf_s);
+        test("null-2900", "" + s_oNtS + s_sM);
+        test("null-194313216", "" + s_oNtS + sf_l);
+        test("null12", "" + s_oNtS + s_strU1);
+        test("nullC(87)", "" + s_oNtS + sf_o);
+        test("null91", "" + s_oNtS + s_strU2);
+        test("null21", "" + s_oNtS + f_strU1);
+        test("null18", "" + s_oNtS + f_strU2);
+        test("nullnull", "" + s_oNtS + f_iAN);
+        test("nullnull", "" + s_oNtS + s_oN);
+        test("null\u045180", "" + s_oNtS + s_strU);
+        test("nullC", "" + s_oNtS + sf_c);
+        test("null75", "" + s_oNtS + sf_str);
+        test("null-43", "" + s_oNtS + s_bM);
+        test("null80", "" + s_oNtS + sf_b);
+        test("nullnull", "" + s_oNtS + s_IN);
+        test("null-52.0", "" + s_oNtS + s_fM);
+        test("null75000000", "" + s_oNtS + sf_i);
+        test("null44", "" + s_oNtS + f_b);
+        test("null-1705032704", "" + s_oNtS + sf_lM);
+        test("nullnull", "" + s_oNtS + f_oAN);
+        test("null83.0", "" + s_oNtS + f_d);
+        test("nullI", "" + s_oNtS + f_c);
+        test("null94.0", "" + s_oNtS + f_f);
+        test("null12.0", "" + s_oNtS + sf_d);
+        test("null-99.0", "" + s_oNtS + f_dM);
+        test("null17.0", "" + s_oNtS + sf_f);
+        test("null-84.0", "" + s_oNtS + sf_dM);
+        test("null58000000", "" + s_oNtS + f_i);
+        test("null-55000000", "" + s_oNtS + f_iM);
+        test("null1460392448", "" + s_oNtS + f_l);
+        test("nullC(70)", "" + s_oNtS + f_o);
+        test("null\u04511", "" + s_oNtS + sf_strU);
+        test("null8000", "" + s_oNtS + f_s);
+        test("null18", "" + s_oNtS + s_str);
+        test("null-1000000", "" + s_oNtS + s_iM);
+        test("null1000000", "" + s_oNtS + sf_I);
+        test("nullnull", "" + s_oNtS + f_oNtS);
+        test("nullfalse", "" + s_oNtS + f_bl);
+        test("nullnull", "" + s_oNtS + sf_iAN);
+        test("null-2000000", "" + s_oNtS + sf_iM);
+        test("null-820130816", "" + s_oNtS + f_lM);
+        test("nullnull", "" + s_oNtS + sf_oAN);
+        test("null25000000", "" + s_oNtS + s_I);
+        test("\u045176-96.0", "" + f_strU + s_dM);
+        test("\u045176null", "" + f_strU + s_oNtS);
+        test("\u045176\u045176", "" + f_strU + f_strU);
+        test("\u04517692", "" + f_strU + sf_strU2);
+        test("\u04517651", "" + f_strU + sf_strU1);
+        test("\u045176null", "" + f_strU + s_iAN);
+        test("\u045176-54", "" + f_strU + f_bM);
+        test("\u045176-87.0", "" + f_strU + f_fM);
+        test("\u045176null", "" + f_strU + s_oAN);
+        test("\u04517619", "" + f_strU + f_str);
+        test("\u045176-41", "" + f_strU + sf_bM);
+        test("\u045176null", "" + f_strU + sf_IN);
+        test("\u045176T", "" + f_strU + s_c);
+        test("\u045176-42.0", "" + f_strU + sf_fM);
+        test("\u04517625", "" + f_strU + s_b);
+        test("\u045176null", "" + f_strU + f_oN);
+        test("\u045176-1410065408", "" + f_strU + s_lM);
+        test("\u0451768.0", "" + f_strU + s_d);
+        test("\u04517655.0", "" + f_strU + s_f);
+        test("\u04517697000000", "" + f_strU + s_i);
+        test("\u045176-9900", "" + f_strU + f_sM);
+        test("\u045176935228928", "" + f_strU + s_l);
+        test("\u045176-8400", "" + f_strU + sf_sM);
+        test("\u045176C(82)", "" + f_strU + s_o);
+        test("\u045176null", "" + f_strU + sf_oNtS);
+        test("\u045176true", "" + f_strU + s_bl);
+        test("\u0451763900", "" + f_strU + s_s);
+        test("\u045176null", "" + f_strU + sf_oN);
+        test("\u04517694000000", "" + f_strU + f_I);
+        test("\u045176null", "" + f_strU + f_IN);
+        test("\u045176true", "" + f_strU + sf_bl);
+        test("\u0451765500", "" + f_strU + sf_s);
+        test("\u045176-2900", "" + f_strU + s_sM);
+        test("\u045176-194313216", "" + f_strU + sf_l);
+        test("\u04517612", "" + f_strU + s_strU1);
+        test("\u045176C(87)", "" + f_strU + sf_o);
+        test("\u04517691", "" + f_strU + s_strU2);
+        test("\u04517621", "" + f_strU + f_strU1);
+        test("\u04517618", "" + f_strU + f_strU2);
+        test("\u045176null", "" + f_strU + f_iAN);
+        test("\u045176null", "" + f_strU + s_oN);
+        test("\u045176\u045180", "" + f_strU + s_strU);
+        test("\u045176C", "" + f_strU + sf_c);
+        test("\u04517675", "" + f_strU + sf_str);
+        test("\u045176-43", "" + f_strU + s_bM);
+        test("\u04517680", "" + f_strU + sf_b);
+        test("\u045176null", "" + f_strU + s_IN);
+        test("\u045176-52.0", "" + f_strU + s_fM);
+        test("\u04517675000000", "" + f_strU + sf_i);
+        test("\u04517644", "" + f_strU + f_b);
+        test("\u045176-1705032704", "" + f_strU + sf_lM);
+        test("\u045176null", "" + f_strU + f_oAN);
+        test("\u04517683.0", "" + f_strU + f_d);
+        test("\u045176I", "" + f_strU + f_c);
+        test("\u04517694.0", "" + f_strU + f_f);
+        test("\u04517612.0", "" + f_strU + sf_d);
+        test("\u045176-99.0", "" + f_strU + f_dM);
+        test("\u04517617.0", "" + f_strU + sf_f);
+        test("\u045176-84.0", "" + f_strU + sf_dM);
+        test("\u04517658000000", "" + f_strU + f_i);
+        test("\u045176-55000000", "" + f_strU + f_iM);
+        test("\u0451761460392448", "" + f_strU + f_l);
+        test("\u045176C(70)", "" + f_strU + f_o);
+        test("\u045176\u04511", "" + f_strU + sf_strU);
+        test("\u0451768000", "" + f_strU + f_s);
+        test("\u04517618", "" + f_strU + s_str);
+        test("\u045176-1000000", "" + f_strU + s_iM);
+        test("\u0451761000000", "" + f_strU + sf_I);
+        test("\u045176null", "" + f_strU + f_oNtS);
+        test("\u045176false", "" + f_strU + f_bl);
+        test("\u045176null", "" + f_strU + sf_iAN);
+        test("\u045176-2000000", "" + f_strU + sf_iM);
+        test("\u045176-820130816", "" + f_strU + f_lM);
+        test("\u045176null", "" + f_strU + sf_oAN);
+        test("\u04517625000000", "" + f_strU + s_I);
+        test("92-96.0", "" + sf_strU2 + s_dM);
+        test("92null", "" + sf_strU2 + s_oNtS);
+        test("92\u045176", "" + sf_strU2 + f_strU);
+        test("9292", "" + sf_strU2 + sf_strU2);
+        test("9251", "" + sf_strU2 + sf_strU1);
+        test("92null", "" + sf_strU2 + s_iAN);
+        test("92-54", "" + sf_strU2 + f_bM);
+        test("92-87.0", "" + sf_strU2 + f_fM);
+        test("92null", "" + sf_strU2 + s_oAN);
+        test("9219", "" + sf_strU2 + f_str);
+        test("92-41", "" + sf_strU2 + sf_bM);
+        test("92null", "" + sf_strU2 + sf_IN);
+        test("92T", "" + sf_strU2 + s_c);
+        test("92-42.0", "" + sf_strU2 + sf_fM);
+        test("9225", "" + sf_strU2 + s_b);
+        test("92null", "" + sf_strU2 + f_oN);
+        test("92-1410065408", "" + sf_strU2 + s_lM);
+        test("928.0", "" + sf_strU2 + s_d);
+        test("9255.0", "" + sf_strU2 + s_f);
+        test("9297000000", "" + sf_strU2 + s_i);
+        test("92-9900", "" + sf_strU2 + f_sM);
+        test("92935228928", "" + sf_strU2 + s_l);
+        test("92-8400", "" + sf_strU2 + sf_sM);
+        test("92C(82)", "" + sf_strU2 + s_o);
+        test("92null", "" + sf_strU2 + sf_oNtS);
+        test("92true", "" + sf_strU2 + s_bl);
+        test("923900", "" + sf_strU2 + s_s);
+        test("92null", "" + sf_strU2 + sf_oN);
+        test("9294000000", "" + sf_strU2 + f_I);
+        test("92null", "" + sf_strU2 + f_IN);
+        test("92true", "" + sf_strU2 + sf_bl);
+        test("925500", "" + sf_strU2 + sf_s);
+        test("92-2900", "" + sf_strU2 + s_sM);
+        test("92-194313216", "" + sf_strU2 + sf_l);
+        test("9212", "" + sf_strU2 + s_strU1);
+        test("92C(87)", "" + sf_strU2 + sf_o);
+        test("9291", "" + sf_strU2 + s_strU2);
+        test("9221", "" + sf_strU2 + f_strU1);
+        test("9218", "" + sf_strU2 + f_strU2);
+        test("92null", "" + sf_strU2 + f_iAN);
+        test("92null", "" + sf_strU2 + s_oN);
+        test("92\u045180", "" + sf_strU2 + s_strU);
+        test("92C", "" + sf_strU2 + sf_c);
+        test("9275", "" + sf_strU2 + sf_str);
+        test("92-43", "" + sf_strU2 + s_bM);
+        test("9280", "" + sf_strU2 + sf_b);
+        test("92null", "" + sf_strU2 + s_IN);
+        test("92-52.0", "" + sf_strU2 + s_fM);
+        test("9275000000", "" + sf_strU2 + sf_i);
+        test("9244", "" + sf_strU2 + f_b);
+        test("92-1705032704", "" + sf_strU2 + sf_lM);
+        test("92null", "" + sf_strU2 + f_oAN);
+        test("9283.0", "" + sf_strU2 + f_d);
+        test("92I", "" + sf_strU2 + f_c);
+        test("9294.0", "" + sf_strU2 + f_f);
+        test("9212.0", "" + sf_strU2 + sf_d);
+        test("92-99.0", "" + sf_strU2 + f_dM);
+        test("9217.0", "" + sf_strU2 + sf_f);
+        test("92-84.0", "" + sf_strU2 + sf_dM);
+        test("9258000000", "" + sf_strU2 + f_i);
+        test("92-55000000", "" + sf_strU2 + f_iM);
+        test("921460392448", "" + sf_strU2 + f_l);
+        test("92C(70)", "" + sf_strU2 + f_o);
+        test("92\u04511", "" + sf_strU2 + sf_strU);
+        test("928000", "" + sf_strU2 + f_s);
+        test("9218", "" + sf_strU2 + s_str);
+        test("92-1000000", "" + sf_strU2 + s_iM);
+        test("921000000", "" + sf_strU2 + sf_I);
+        test("92null", "" + sf_strU2 + f_oNtS);
+        test("92false", "" + sf_strU2 + f_bl);
+        test("92null", "" + sf_strU2 + sf_iAN);
+        test("92-2000000", "" + sf_strU2 + sf_iM);
+        test("92-820130816", "" + sf_strU2 + f_lM);
+        test("92null", "" + sf_strU2 + sf_oAN);
+        test("9225000000", "" + sf_strU2 + s_I);
+        test("51-96.0", "" + sf_strU1 + s_dM);
+        test("51null", "" + sf_strU1 + s_oNtS);
+        test("51\u045176", "" + sf_strU1 + f_strU);
+        test("5192", "" + sf_strU1 + sf_strU2);
+        test("5151", "" + sf_strU1 + sf_strU1);
+        test("51null", "" + sf_strU1 + s_iAN);
+        test("51-54", "" + sf_strU1 + f_bM);
+        test("51-87.0", "" + sf_strU1 + f_fM);
+        test("51null", "" + sf_strU1 + s_oAN);
+        test("5119", "" + sf_strU1 + f_str);
+        test("51-41", "" + sf_strU1 + sf_bM);
+        test("51null", "" + sf_strU1 + sf_IN);
+        test("51T", "" + sf_strU1 + s_c);
+        test("51-42.0", "" + sf_strU1 + sf_fM);
+        test("5125", "" + sf_strU1 + s_b);
+        test("51null", "" + sf_strU1 + f_oN);
+        test("51-1410065408", "" + sf_strU1 + s_lM);
+        test("518.0", "" + sf_strU1 + s_d);
+        test("5155.0", "" + sf_strU1 + s_f);
+        test("5197000000", "" + sf_strU1 + s_i);
+        test("51-9900", "" + sf_strU1 + f_sM);
+        test("51935228928", "" + sf_strU1 + s_l);
+        test("51-8400", "" + sf_strU1 + sf_sM);
+        test("51C(82)", "" + sf_strU1 + s_o);
+        test("51null", "" + sf_strU1 + sf_oNtS);
+        test("51true", "" + sf_strU1 + s_bl);
+        test("513900", "" + sf_strU1 + s_s);
+        test("51null", "" + sf_strU1 + sf_oN);
+        test("5194000000", "" + sf_strU1 + f_I);
+        test("51null", "" + sf_strU1 + f_IN);
+        test("51true", "" + sf_strU1 + sf_bl);
+        test("515500", "" + sf_strU1 + sf_s);
+        test("51-2900", "" + sf_strU1 + s_sM);
+        test("51-194313216", "" + sf_strU1 + sf_l);
+        test("5112", "" + sf_strU1 + s_strU1);
+        test("51C(87)", "" + sf_strU1 + sf_o);
+        test("5191", "" + sf_strU1 + s_strU2);
+        test("5121", "" + sf_strU1 + f_strU1);
+        test("5118", "" + sf_strU1 + f_strU2);
+        test("51null", "" + sf_strU1 + f_iAN);
+        test("51null", "" + sf_strU1 + s_oN);
+        test("51\u045180", "" + sf_strU1 + s_strU);
+        test("51C", "" + sf_strU1 + sf_c);
+        test("5175", "" + sf_strU1 + sf_str);
+        test("51-43", "" + sf_strU1 + s_bM);
+        test("5180", "" + sf_strU1 + sf_b);
+        test("51null", "" + sf_strU1 + s_IN);
+        test("51-52.0", "" + sf_strU1 + s_fM);
+        test("5175000000", "" + sf_strU1 + sf_i);
+        test("5144", "" + sf_strU1 + f_b);
+        test("51-1705032704", "" + sf_strU1 + sf_lM);
+        test("51null", "" + sf_strU1 + f_oAN);
+        test("5183.0", "" + sf_strU1 + f_d);
+        test("51I", "" + sf_strU1 + f_c);
+        test("5194.0", "" + sf_strU1 + f_f);
+        test("5112.0", "" + sf_strU1 + sf_d);
+        test("51-99.0", "" + sf_strU1 + f_dM);
+        test("5117.0", "" + sf_strU1 + sf_f);
+        test("51-84.0", "" + sf_strU1 + sf_dM);
+        test("5158000000", "" + sf_strU1 + f_i);
+        test("51-55000000", "" + sf_strU1 + f_iM);
+        test("511460392448", "" + sf_strU1 + f_l);
+        test("51C(70)", "" + sf_strU1 + f_o);
+        test("51\u04511", "" + sf_strU1 + sf_strU);
+        test("518000", "" + sf_strU1 + f_s);
+        test("5118", "" + sf_strU1 + s_str);
+        test("51-1000000", "" + sf_strU1 + s_iM);
+        test("511000000", "" + sf_strU1 + sf_I);
+        test("51null", "" + sf_strU1 + f_oNtS);
+        test("51false", "" + sf_strU1 + f_bl);
+        test("51null", "" + sf_strU1 + sf_iAN);
+        test("51-2000000", "" + sf_strU1 + sf_iM);
+        test("51-820130816", "" + sf_strU1 + f_lM);
+        test("51null", "" + sf_strU1 + sf_oAN);
+        test("5125000000", "" + sf_strU1 + s_I);
+        test("null-96.0", "" + s_iAN + s_dM);
+        test("nullnull", "" + s_iAN + s_oNtS);
+        test("null\u045176", "" + s_iAN + f_strU);
+        test("null92", "" + s_iAN + sf_strU2);
+        test("null51", "" + s_iAN + sf_strU1);
+        test("nullnull", "" + s_iAN + s_iAN);
+        test("null-54", "" + s_iAN + f_bM);
+        test("null-87.0", "" + s_iAN + f_fM);
+        test("nullnull", "" + s_iAN + s_oAN);
+        test("null19", "" + s_iAN + f_str);
+        test("null-41", "" + s_iAN + sf_bM);
+        test("nullnull", "" + s_iAN + sf_IN);
+        test("nullT", "" + s_iAN + s_c);
+        test("null-42.0", "" + s_iAN + sf_fM);
+        test("null25", "" + s_iAN + s_b);
+        test("nullnull", "" + s_iAN + f_oN);
+        test("null-1410065408", "" + s_iAN + s_lM);
+        test("null8.0", "" + s_iAN + s_d);
+        test("null55.0", "" + s_iAN + s_f);
+        test("null97000000", "" + s_iAN + s_i);
+        test("null-9900", "" + s_iAN + f_sM);
+        test("null935228928", "" + s_iAN + s_l);
+        test("null-8400", "" + s_iAN + sf_sM);
+        test("nullC(82)", "" + s_iAN + s_o);
+        test("nullnull", "" + s_iAN + sf_oNtS);
+        test("nulltrue", "" + s_iAN + s_bl);
+        test("null3900", "" + s_iAN + s_s);
+        test("nullnull", "" + s_iAN + sf_oN);
+        test("null94000000", "" + s_iAN + f_I);
+        test("nullnull", "" + s_iAN + f_IN);
+        test("nulltrue", "" + s_iAN + sf_bl);
+        test("null5500", "" + s_iAN + sf_s);
+        test("null-2900", "" + s_iAN + s_sM);
+        test("null-194313216", "" + s_iAN + sf_l);
+        test("null12", "" + s_iAN + s_strU1);
+        test("nullC(87)", "" + s_iAN + sf_o);
+        test("null91", "" + s_iAN + s_strU2);
+        test("null21", "" + s_iAN + f_strU1);
+        test("null18", "" + s_iAN + f_strU2);
+        test("nullnull", "" + s_iAN + f_iAN);
+        test("nullnull", "" + s_iAN + s_oN);
+        test("null\u045180", "" + s_iAN + s_strU);
+        test("nullC", "" + s_iAN + sf_c);
+        test("null75", "" + s_iAN + sf_str);
+        test("null-43", "" + s_iAN + s_bM);
+        test("null80", "" + s_iAN + sf_b);
+        test("nullnull", "" + s_iAN + s_IN);
+        test("null-52.0", "" + s_iAN + s_fM);
+        test("null75000000", "" + s_iAN + sf_i);
+        test("null44", "" + s_iAN + f_b);
+        test("null-1705032704", "" + s_iAN + sf_lM);
+        test("nullnull", "" + s_iAN + f_oAN);
+        test("null83.0", "" + s_iAN + f_d);
+        test("nullI", "" + s_iAN + f_c);
+        test("null94.0", "" + s_iAN + f_f);
+        test("null12.0", "" + s_iAN + sf_d);
+        test("null-99.0", "" + s_iAN + f_dM);
+        test("null17.0", "" + s_iAN + sf_f);
+        test("null-84.0", "" + s_iAN + sf_dM);
+        test("null58000000", "" + s_iAN + f_i);
+        test("null-55000000", "" + s_iAN + f_iM);
+        test("null1460392448", "" + s_iAN + f_l);
+        test("nullC(70)", "" + s_iAN + f_o);
+        test("null\u04511", "" + s_iAN + sf_strU);
+        test("null8000", "" + s_iAN + f_s);
+        test("null18", "" + s_iAN + s_str);
+        test("null-1000000", "" + s_iAN + s_iM);
+        test("null1000000", "" + s_iAN + sf_I);
+        test("nullnull", "" + s_iAN + f_oNtS);
+        test("nullfalse", "" + s_iAN + f_bl);
+        test("nullnull", "" + s_iAN + sf_iAN);
+        test("null-2000000", "" + s_iAN + sf_iM);
+        test("null-820130816", "" + s_iAN + f_lM);
+        test("nullnull", "" + s_iAN + sf_oAN);
+        test("null25000000", "" + s_iAN + s_I);
+        test("-54-96.0", "" + f_bM + s_dM);
+        test("-54null", "" + f_bM + s_oNtS);
+        test("-54\u045176", "" + f_bM + f_strU);
+        test("-5492", "" + f_bM + sf_strU2);
+        test("-5451", "" + f_bM + sf_strU1);
+        test("-54null", "" + f_bM + s_iAN);
+        test("-54-54", "" + f_bM + f_bM);
+        test("-54-87.0", "" + f_bM + f_fM);
+        test("-54null", "" + f_bM + s_oAN);
+        test("-5419", "" + f_bM + f_str);
+        test("-54-41", "" + f_bM + sf_bM);
+        test("-54null", "" + f_bM + sf_IN);
+        test("-54T", "" + f_bM + s_c);
+        test("-54-42.0", "" + f_bM + sf_fM);
+        test("-5425", "" + f_bM + s_b);
+        test("-54null", "" + f_bM + f_oN);
+        test("-54-1410065408", "" + f_bM + s_lM);
+        test("-548.0", "" + f_bM + s_d);
+        test("-5455.0", "" + f_bM + s_f);
+        test("-5497000000", "" + f_bM + s_i);
+        test("-54-9900", "" + f_bM + f_sM);
+        test("-54935228928", "" + f_bM + s_l);
+        test("-54-8400", "" + f_bM + sf_sM);
+        test("-54C(82)", "" + f_bM + s_o);
+        test("-54null", "" + f_bM + sf_oNtS);
+        test("-54true", "" + f_bM + s_bl);
+        test("-543900", "" + f_bM + s_s);
+        test("-54null", "" + f_bM + sf_oN);
+        test("-5494000000", "" + f_bM + f_I);
+        test("-54null", "" + f_bM + f_IN);
+        test("-54true", "" + f_bM + sf_bl);
+        test("-545500", "" + f_bM + sf_s);
+        test("-54-2900", "" + f_bM + s_sM);
+        test("-54-194313216", "" + f_bM + sf_l);
+        test("-5412", "" + f_bM + s_strU1);
+        test("-54C(87)", "" + f_bM + sf_o);
+        test("-5491", "" + f_bM + s_strU2);
+        test("-5421", "" + f_bM + f_strU1);
+        test("-5418", "" + f_bM + f_strU2);
+        test("-54null", "" + f_bM + f_iAN);
+        test("-54null", "" + f_bM + s_oN);
+        test("-54\u045180", "" + f_bM + s_strU);
+        test("-54C", "" + f_bM + sf_c);
+        test("-5475", "" + f_bM + sf_str);
+        test("-54-43", "" + f_bM + s_bM);
+        test("-5480", "" + f_bM + sf_b);
+        test("-54null", "" + f_bM + s_IN);
+        test("-54-52.0", "" + f_bM + s_fM);
+        test("-5475000000", "" + f_bM + sf_i);
+        test("-5444", "" + f_bM + f_b);
+        test("-54-1705032704", "" + f_bM + sf_lM);
+        test("-54null", "" + f_bM + f_oAN);
+        test("-5483.0", "" + f_bM + f_d);
+        test("-54I", "" + f_bM + f_c);
+        test("-5494.0", "" + f_bM + f_f);
+        test("-5412.0", "" + f_bM + sf_d);
+        test("-54-99.0", "" + f_bM + f_dM);
+        test("-5417.0", "" + f_bM + sf_f);
+        test("-54-84.0", "" + f_bM + sf_dM);
+        test("-5458000000", "" + f_bM + f_i);
+        test("-54-55000000", "" + f_bM + f_iM);
+        test("-541460392448", "" + f_bM + f_l);
+        test("-54C(70)", "" + f_bM + f_o);
+        test("-54\u04511", "" + f_bM + sf_strU);
+        test("-548000", "" + f_bM + f_s);
+        test("-5418", "" + f_bM + s_str);
+        test("-54-1000000", "" + f_bM + s_iM);
+        test("-541000000", "" + f_bM + sf_I);
+        test("-54null", "" + f_bM + f_oNtS);
+        test("-54false", "" + f_bM + f_bl);
+        test("-54null", "" + f_bM + sf_iAN);
+        test("-54-2000000", "" + f_bM + sf_iM);
+        test("-54-820130816", "" + f_bM + f_lM);
+        test("-54null", "" + f_bM + sf_oAN);
+        test("-5425000000", "" + f_bM + s_I);
+        test("-87.0-96.0", "" + f_fM + s_dM);
+        test("-87.0null", "" + f_fM + s_oNtS);
+        test("-87.0\u045176", "" + f_fM + f_strU);
+        test("-87.092", "" + f_fM + sf_strU2);
+        test("-87.051", "" + f_fM + sf_strU1);
+        test("-87.0null", "" + f_fM + s_iAN);
+        test("-87.0-54", "" + f_fM + f_bM);
+        test("-87.0-87.0", "" + f_fM + f_fM);
+        test("-87.0null", "" + f_fM + s_oAN);
+        test("-87.019", "" + f_fM + f_str);
+        test("-87.0-41", "" + f_fM + sf_bM);
+        test("-87.0null", "" + f_fM + sf_IN);
+        test("-87.0T", "" + f_fM + s_c);
+        test("-87.0-42.0", "" + f_fM + sf_fM);
+        test("-87.025", "" + f_fM + s_b);
+        test("-87.0null", "" + f_fM + f_oN);
+        test("-87.0-1410065408", "" + f_fM + s_lM);
+        test("-87.08.0", "" + f_fM + s_d);
+        test("-87.055.0", "" + f_fM + s_f);
+        test("-87.097000000", "" + f_fM + s_i);
+        test("-87.0-9900", "" + f_fM + f_sM);
+        test("-87.0935228928", "" + f_fM + s_l);
+        test("-87.0-8400", "" + f_fM + sf_sM);
+        test("-87.0C(82)", "" + f_fM + s_o);
+        test("-87.0null", "" + f_fM + sf_oNtS);
+        test("-87.0true", "" + f_fM + s_bl);
+        test("-87.03900", "" + f_fM + s_s);
+        test("-87.0null", "" + f_fM + sf_oN);
+        test("-87.094000000", "" + f_fM + f_I);
+        test("-87.0null", "" + f_fM + f_IN);
+        test("-87.0true", "" + f_fM + sf_bl);
+        test("-87.05500", "" + f_fM + sf_s);
+        test("-87.0-2900", "" + f_fM + s_sM);
+        test("-87.0-194313216", "" + f_fM + sf_l);
+        test("-87.012", "" + f_fM + s_strU1);
+        test("-87.0C(87)", "" + f_fM + sf_o);
+        test("-87.091", "" + f_fM + s_strU2);
+        test("-87.021", "" + f_fM + f_strU1);
+        test("-87.018", "" + f_fM + f_strU2);
+        test("-87.0null", "" + f_fM + f_iAN);
+        test("-87.0null", "" + f_fM + s_oN);
+        test("-87.0\u045180", "" + f_fM + s_strU);
+        test("-87.0C", "" + f_fM + sf_c);
+        test("-87.075", "" + f_fM + sf_str);
+        test("-87.0-43", "" + f_fM + s_bM);
+        test("-87.080", "" + f_fM + sf_b);
+        test("-87.0null", "" + f_fM + s_IN);
+        test("-87.0-52.0", "" + f_fM + s_fM);
+        test("-87.075000000", "" + f_fM + sf_i);
+        test("-87.044", "" + f_fM + f_b);
+        test("-87.0-1705032704", "" + f_fM + sf_lM);
+        test("-87.0null", "" + f_fM + f_oAN);
+        test("-87.083.0", "" + f_fM + f_d);
+        test("-87.0I", "" + f_fM + f_c);
+        test("-87.094.0", "" + f_fM + f_f);
+        test("-87.012.0", "" + f_fM + sf_d);
+        test("-87.0-99.0", "" + f_fM + f_dM);
+        test("-87.017.0", "" + f_fM + sf_f);
+        test("-87.0-84.0", "" + f_fM + sf_dM);
+        test("-87.058000000", "" + f_fM + f_i);
+        test("-87.0-55000000", "" + f_fM + f_iM);
+        test("-87.01460392448", "" + f_fM + f_l);
+        test("-87.0C(70)", "" + f_fM + f_o);
+        test("-87.0\u04511", "" + f_fM + sf_strU);
+        test("-87.08000", "" + f_fM + f_s);
+        test("-87.018", "" + f_fM + s_str);
+        test("-87.0-1000000", "" + f_fM + s_iM);
+        test("-87.01000000", "" + f_fM + sf_I);
+        test("-87.0null", "" + f_fM + f_oNtS);
+        test("-87.0false", "" + f_fM + f_bl);
+        test("-87.0null", "" + f_fM + sf_iAN);
+        test("-87.0-2000000", "" + f_fM + sf_iM);
+        test("-87.0-820130816", "" + f_fM + f_lM);
+        test("-87.0null", "" + f_fM + sf_oAN);
+        test("-87.025000000", "" + f_fM + s_I);
+        test("null-96.0", "" + s_oAN + s_dM);
+        test("nullnull", "" + s_oAN + s_oNtS);
+        test("null\u045176", "" + s_oAN + f_strU);
+        test("null92", "" + s_oAN + sf_strU2);
+        test("null51", "" + s_oAN + sf_strU1);
+        test("nullnull", "" + s_oAN + s_iAN);
+        test("null-54", "" + s_oAN + f_bM);
+        test("null-87.0", "" + s_oAN + f_fM);
+        test("nullnull", "" + s_oAN + s_oAN);
+        test("null19", "" + s_oAN + f_str);
+        test("null-41", "" + s_oAN + sf_bM);
+        test("nullnull", "" + s_oAN + sf_IN);
+        test("nullT", "" + s_oAN + s_c);
+        test("null-42.0", "" + s_oAN + sf_fM);
+        test("null25", "" + s_oAN + s_b);
+        test("nullnull", "" + s_oAN + f_oN);
+        test("null-1410065408", "" + s_oAN + s_lM);
+        test("null8.0", "" + s_oAN + s_d);
+        test("null55.0", "" + s_oAN + s_f);
+        test("null97000000", "" + s_oAN + s_i);
+        test("null-9900", "" + s_oAN + f_sM);
+        test("null935228928", "" + s_oAN + s_l);
+        test("null-8400", "" + s_oAN + sf_sM);
+        test("nullC(82)", "" + s_oAN + s_o);
+        test("nullnull", "" + s_oAN + sf_oNtS);
+        test("nulltrue", "" + s_oAN + s_bl);
+        test("null3900", "" + s_oAN + s_s);
+        test("nullnull", "" + s_oAN + sf_oN);
+        test("null94000000", "" + s_oAN + f_I);
+        test("nullnull", "" + s_oAN + f_IN);
+        test("nulltrue", "" + s_oAN + sf_bl);
+        test("null5500", "" + s_oAN + sf_s);
+        test("null-2900", "" + s_oAN + s_sM);
+        test("null-194313216", "" + s_oAN + sf_l);
+        test("null12", "" + s_oAN + s_strU1);
+        test("nullC(87)", "" + s_oAN + sf_o);
+        test("null91", "" + s_oAN + s_strU2);
+        test("null21", "" + s_oAN + f_strU1);
+        test("null18", "" + s_oAN + f_strU2);
+        test("nullnull", "" + s_oAN + f_iAN);
+        test("nullnull", "" + s_oAN + s_oN);
+        test("null\u045180", "" + s_oAN + s_strU);
+        test("nullC", "" + s_oAN + sf_c);
+        test("null75", "" + s_oAN + sf_str);
+        test("null-43", "" + s_oAN + s_bM);
+        test("null80", "" + s_oAN + sf_b);
+        test("nullnull", "" + s_oAN + s_IN);
+        test("null-52.0", "" + s_oAN + s_fM);
+        test("null75000000", "" + s_oAN + sf_i);
+        test("null44", "" + s_oAN + f_b);
+        test("null-1705032704", "" + s_oAN + sf_lM);
+        test("nullnull", "" + s_oAN + f_oAN);
+        test("null83.0", "" + s_oAN + f_d);
+        test("nullI", "" + s_oAN + f_c);
+        test("null94.0", "" + s_oAN + f_f);
+        test("null12.0", "" + s_oAN + sf_d);
+        test("null-99.0", "" + s_oAN + f_dM);
+        test("null17.0", "" + s_oAN + sf_f);
+        test("null-84.0", "" + s_oAN + sf_dM);
+        test("null58000000", "" + s_oAN + f_i);
+        test("null-55000000", "" + s_oAN + f_iM);
+        test("null1460392448", "" + s_oAN + f_l);
+        test("nullC(70)", "" + s_oAN + f_o);
+        test("null\u04511", "" + s_oAN + sf_strU);
+        test("null8000", "" + s_oAN + f_s);
+        test("null18", "" + s_oAN + s_str);
+        test("null-1000000", "" + s_oAN + s_iM);
+        test("null1000000", "" + s_oAN + sf_I);
+        test("nullnull", "" + s_oAN + f_oNtS);
+        test("nullfalse", "" + s_oAN + f_bl);
+        test("nullnull", "" + s_oAN + sf_iAN);
+        test("null-2000000", "" + s_oAN + sf_iM);
+        test("null-820130816", "" + s_oAN + f_lM);
+        test("nullnull", "" + s_oAN + sf_oAN);
+        test("null25000000", "" + s_oAN + s_I);
+        test("19-96.0", "" + f_str + s_dM);
+        test("19null", "" + f_str + s_oNtS);
+        test("19\u045176", "" + f_str + f_strU);
+        test("1992", "" + f_str + sf_strU2);
+        test("1951", "" + f_str + sf_strU1);
+        test("19null", "" + f_str + s_iAN);
+        test("19-54", "" + f_str + f_bM);
+        test("19-87.0", "" + f_str + f_fM);
+        test("19null", "" + f_str + s_oAN);
+        test("1919", "" + f_str + f_str);
+        test("19-41", "" + f_str + sf_bM);
+        test("19null", "" + f_str + sf_IN);
+        test("19T", "" + f_str + s_c);
+        test("19-42.0", "" + f_str + sf_fM);
+        test("1925", "" + f_str + s_b);
+        test("19null", "" + f_str + f_oN);
+        test("19-1410065408", "" + f_str + s_lM);
+        test("198.0", "" + f_str + s_d);
+        test("1955.0", "" + f_str + s_f);
+        test("1997000000", "" + f_str + s_i);
+        test("19-9900", "" + f_str + f_sM);
+        test("19935228928", "" + f_str + s_l);
+        test("19-8400", "" + f_str + sf_sM);
+        test("19C(82)", "" + f_str + s_o);
+        test("19null", "" + f_str + sf_oNtS);
+        test("19true", "" + f_str + s_bl);
+        test("193900", "" + f_str + s_s);
+        test("19null", "" + f_str + sf_oN);
+        test("1994000000", "" + f_str + f_I);
+        test("19null", "" + f_str + f_IN);
+        test("19true", "" + f_str + sf_bl);
+        test("195500", "" + f_str + sf_s);
+        test("19-2900", "" + f_str + s_sM);
+        test("19-194313216", "" + f_str + sf_l);
+        test("1912", "" + f_str + s_strU1);
+        test("19C(87)", "" + f_str + sf_o);
+        test("1991", "" + f_str + s_strU2);
+        test("1921", "" + f_str + f_strU1);
+        test("1918", "" + f_str + f_strU2);
+        test("19null", "" + f_str + f_iAN);
+        test("19null", "" + f_str + s_oN);
+        test("19\u045180", "" + f_str + s_strU);
+        test("19C", "" + f_str + sf_c);
+        test("1975", "" + f_str + sf_str);
+        test("19-43", "" + f_str + s_bM);
+        test("1980", "" + f_str + sf_b);
+        test("19null", "" + f_str + s_IN);
+        test("19-52.0", "" + f_str + s_fM);
+        test("1975000000", "" + f_str + sf_i);
+        test("1944", "" + f_str + f_b);
+        test("19-1705032704", "" + f_str + sf_lM);
+        test("19null", "" + f_str + f_oAN);
+        test("1983.0", "" + f_str + f_d);
+        test("19I", "" + f_str + f_c);
+        test("1994.0", "" + f_str + f_f);
+        test("1912.0", "" + f_str + sf_d);
+        test("19-99.0", "" + f_str + f_dM);
+        test("1917.0", "" + f_str + sf_f);
+        test("19-84.0", "" + f_str + sf_dM);
+        test("1958000000", "" + f_str + f_i);
+        test("19-55000000", "" + f_str + f_iM);
+        test("191460392448", "" + f_str + f_l);
+        test("19C(70)", "" + f_str + f_o);
+        test("19\u04511", "" + f_str + sf_strU);
+        test("198000", "" + f_str + f_s);
+        test("1918", "" + f_str + s_str);
+        test("19-1000000", "" + f_str + s_iM);
+        test("191000000", "" + f_str + sf_I);
+        test("19null", "" + f_str + f_oNtS);
+        test("19false", "" + f_str + f_bl);
+        test("19null", "" + f_str + sf_iAN);
+        test("19-2000000", "" + f_str + sf_iM);
+        test("19-820130816", "" + f_str + f_lM);
+        test("19null", "" + f_str + sf_oAN);
+        test("1925000000", "" + f_str + s_I);
+        test("-41-96.0", "" + sf_bM + s_dM);
+        test("-41null", "" + sf_bM + s_oNtS);
+        test("-41\u045176", "" + sf_bM + f_strU);
+        test("-4192", "" + sf_bM + sf_strU2);
+        test("-4151", "" + sf_bM + sf_strU1);
+        test("-41null", "" + sf_bM + s_iAN);
+        test("-41-54", "" + sf_bM + f_bM);
+        test("-41-87.0", "" + sf_bM + f_fM);
+        test("-41null", "" + sf_bM + s_oAN);
+        test("-4119", "" + sf_bM + f_str);
+        test("-41-41", "" + sf_bM + sf_bM);
+        test("-41null", "" + sf_bM + sf_IN);
+        test("-41T", "" + sf_bM + s_c);
+        test("-41-42.0", "" + sf_bM + sf_fM);
+        test("-4125", "" + sf_bM + s_b);
+        test("-41null", "" + sf_bM + f_oN);
+        test("-41-1410065408", "" + sf_bM + s_lM);
+        test("-418.0", "" + sf_bM + s_d);
+        test("-4155.0", "" + sf_bM + s_f);
+        test("-4197000000", "" + sf_bM + s_i);
+        test("-41-9900", "" + sf_bM + f_sM);
+        test("-41935228928", "" + sf_bM + s_l);
+        test("-41-8400", "" + sf_bM + sf_sM);
+        test("-41C(82)", "" + sf_bM + s_o);
+        test("-41null", "" + sf_bM + sf_oNtS);
+        test("-41true", "" + sf_bM + s_bl);
+        test("-413900", "" + sf_bM + s_s);
+        test("-41null", "" + sf_bM + sf_oN);
+        test("-4194000000", "" + sf_bM + f_I);
+        test("-41null", "" + sf_bM + f_IN);
+        test("-41true", "" + sf_bM + sf_bl);
+        test("-415500", "" + sf_bM + sf_s);
+        test("-41-2900", "" + sf_bM + s_sM);
+        test("-41-194313216", "" + sf_bM + sf_l);
+        test("-4112", "" + sf_bM + s_strU1);
+        test("-41C(87)", "" + sf_bM + sf_o);
+        test("-4191", "" + sf_bM + s_strU2);
+        test("-4121", "" + sf_bM + f_strU1);
+        test("-4118", "" + sf_bM + f_strU2);
+        test("-41null", "" + sf_bM + f_iAN);
+        test("-41null", "" + sf_bM + s_oN);
+        test("-41\u045180", "" + sf_bM + s_strU);
+        test("-41C", "" + sf_bM + sf_c);
+        test("-4175", "" + sf_bM + sf_str);
+        test("-41-43", "" + sf_bM + s_bM);
+        test("-4180", "" + sf_bM + sf_b);
+        test("-41null", "" + sf_bM + s_IN);
+        test("-41-52.0", "" + sf_bM + s_fM);
+        test("-4175000000", "" + sf_bM + sf_i);
+        test("-4144", "" + sf_bM + f_b);
+        test("-41-1705032704", "" + sf_bM + sf_lM);
+        test("-41null", "" + sf_bM + f_oAN);
+        test("-4183.0", "" + sf_bM + f_d);
+        test("-41I", "" + sf_bM + f_c);
+        test("-4194.0", "" + sf_bM + f_f);
+        test("-4112.0", "" + sf_bM + sf_d);
+        test("-41-99.0", "" + sf_bM + f_dM);
+        test("-4117.0", "" + sf_bM + sf_f);
+        test("-41-84.0", "" + sf_bM + sf_dM);
+        test("-4158000000", "" + sf_bM + f_i);
+        test("-41-55000000", "" + sf_bM + f_iM);
+        test("-411460392448", "" + sf_bM + f_l);
+        test("-41C(70)", "" + sf_bM + f_o);
+        test("-41\u04511", "" + sf_bM + sf_strU);
+        test("-418000", "" + sf_bM + f_s);
+        test("-4118", "" + sf_bM + s_str);
+        test("-41-1000000", "" + sf_bM + s_iM);
+        test("-411000000", "" + sf_bM + sf_I);
+        test("-41null", "" + sf_bM + f_oNtS);
+        test("-41false", "" + sf_bM + f_bl);
+        test("-41null", "" + sf_bM + sf_iAN);
+        test("-41-2000000", "" + sf_bM + sf_iM);
+        test("-41-820130816", "" + sf_bM + f_lM);
+        test("-41null", "" + sf_bM + sf_oAN);
+        test("-4125000000", "" + sf_bM + s_I);
+        test("null-96.0", "" + sf_IN + s_dM);
+        test("nullnull", "" + sf_IN + s_oNtS);
+        test("null\u045176", "" + sf_IN + f_strU);
+        test("null92", "" + sf_IN + sf_strU2);
+        test("null51", "" + sf_IN + sf_strU1);
+        test("nullnull", "" + sf_IN + s_iAN);
+        test("null-54", "" + sf_IN + f_bM);
+        test("null-87.0", "" + sf_IN + f_fM);
+        test("nullnull", "" + sf_IN + s_oAN);
+        test("null19", "" + sf_IN + f_str);
+        test("null-41", "" + sf_IN + sf_bM);
+        test("nullnull", "" + sf_IN + sf_IN);
+        test("nullT", "" + sf_IN + s_c);
+        test("null-42.0", "" + sf_IN + sf_fM);
+        test("null25", "" + sf_IN + s_b);
+        test("nullnull", "" + sf_IN + f_oN);
+        test("null-1410065408", "" + sf_IN + s_lM);
+        test("null8.0", "" + sf_IN + s_d);
+        test("null55.0", "" + sf_IN + s_f);
+        test("null97000000", "" + sf_IN + s_i);
+        test("null-9900", "" + sf_IN + f_sM);
+        test("null935228928", "" + sf_IN + s_l);
+        test("null-8400", "" + sf_IN + sf_sM);
+        test("nullC(82)", "" + sf_IN + s_o);
+        test("nullnull", "" + sf_IN + sf_oNtS);
+        test("nulltrue", "" + sf_IN + s_bl);
+        test("null3900", "" + sf_IN + s_s);
+        test("nullnull", "" + sf_IN + sf_oN);
+        test("null94000000", "" + sf_IN + f_I);
+        test("nullnull", "" + sf_IN + f_IN);
+        test("nulltrue", "" + sf_IN + sf_bl);
+        test("null5500", "" + sf_IN + sf_s);
+        test("null-2900", "" + sf_IN + s_sM);
+        test("null-194313216", "" + sf_IN + sf_l);
+        test("null12", "" + sf_IN + s_strU1);
+        test("nullC(87)", "" + sf_IN + sf_o);
+        test("null91", "" + sf_IN + s_strU2);
+        test("null21", "" + sf_IN + f_strU1);
+        test("null18", "" + sf_IN + f_strU2);
+        test("nullnull", "" + sf_IN + f_iAN);
+        test("nullnull", "" + sf_IN + s_oN);
+        test("null\u045180", "" + sf_IN + s_strU);
+        test("nullC", "" + sf_IN + sf_c);
+        test("null75", "" + sf_IN + sf_str);
+        test("null-43", "" + sf_IN + s_bM);
+        test("null80", "" + sf_IN + sf_b);
+        test("nullnull", "" + sf_IN + s_IN);
+        test("null-52.0", "" + sf_IN + s_fM);
+        test("null75000000", "" + sf_IN + sf_i);
+        test("null44", "" + sf_IN + f_b);
+        test("null-1705032704", "" + sf_IN + sf_lM);
+        test("nullnull", "" + sf_IN + f_oAN);
+        test("null83.0", "" + sf_IN + f_d);
+        test("nullI", "" + sf_IN + f_c);
+        test("null94.0", "" + sf_IN + f_f);
+        test("null12.0", "" + sf_IN + sf_d);
+        test("null-99.0", "" + sf_IN + f_dM);
+        test("null17.0", "" + sf_IN + sf_f);
+        test("null-84.0", "" + sf_IN + sf_dM);
+        test("null58000000", "" + sf_IN + f_i);
+        test("null-55000000", "" + sf_IN + f_iM);
+        test("null1460392448", "" + sf_IN + f_l);
+        test("nullC(70)", "" + sf_IN + f_o);
+        test("null\u04511", "" + sf_IN + sf_strU);
+        test("null8000", "" + sf_IN + f_s);
+        test("null18", "" + sf_IN + s_str);
+        test("null-1000000", "" + sf_IN + s_iM);
+        test("null1000000", "" + sf_IN + sf_I);
+        test("nullnull", "" + sf_IN + f_oNtS);
+        test("nullfalse", "" + sf_IN + f_bl);
+        test("nullnull", "" + sf_IN + sf_iAN);
+        test("null-2000000", "" + sf_IN + sf_iM);
+        test("null-820130816", "" + sf_IN + f_lM);
+        test("nullnull", "" + sf_IN + sf_oAN);
+        test("null25000000", "" + sf_IN + s_I);
+        test("T-96.0", "" + s_c + s_dM);
+        test("Tnull", "" + s_c + s_oNtS);
+        test("T\u045176", "" + s_c + f_strU);
+        test("T92", "" + s_c + sf_strU2);
+        test("T51", "" + s_c + sf_strU1);
+        test("Tnull", "" + s_c + s_iAN);
+        test("T-54", "" + s_c + f_bM);
+        test("T-87.0", "" + s_c + f_fM);
+        test("Tnull", "" + s_c + s_oAN);
+        test("T19", "" + s_c + f_str);
+        test("T-41", "" + s_c + sf_bM);
+        test("Tnull", "" + s_c + sf_IN);
+        test("TT", "" + s_c + s_c);
+        test("T-42.0", "" + s_c + sf_fM);
+        test("T25", "" + s_c + s_b);
+        test("Tnull", "" + s_c + f_oN);
+        test("T-1410065408", "" + s_c + s_lM);
+        test("T8.0", "" + s_c + s_d);
+        test("T55.0", "" + s_c + s_f);
+        test("T97000000", "" + s_c + s_i);
+        test("T-9900", "" + s_c + f_sM);
+        test("T935228928", "" + s_c + s_l);
+        test("T-8400", "" + s_c + sf_sM);
+        test("TC(82)", "" + s_c + s_o);
+        test("Tnull", "" + s_c + sf_oNtS);
+    }
+
+    public void run1() {
+        test("Ttrue", "" + s_c + s_bl);
+        test("T3900", "" + s_c + s_s);
+        test("Tnull", "" + s_c + sf_oN);
+        test("T94000000", "" + s_c + f_I);
+        test("Tnull", "" + s_c + f_IN);
+        test("Ttrue", "" + s_c + sf_bl);
+        test("T5500", "" + s_c + sf_s);
+        test("T-2900", "" + s_c + s_sM);
+        test("T-194313216", "" + s_c + sf_l);
+        test("T12", "" + s_c + s_strU1);
+        test("TC(87)", "" + s_c + sf_o);
+        test("T91", "" + s_c + s_strU2);
+        test("T21", "" + s_c + f_strU1);
+        test("T18", "" + s_c + f_strU2);
+        test("Tnull", "" + s_c + f_iAN);
+        test("Tnull", "" + s_c + s_oN);
+        test("T\u045180", "" + s_c + s_strU);
+        test("TC", "" + s_c + sf_c);
+        test("T75", "" + s_c + sf_str);
+        test("T-43", "" + s_c + s_bM);
+        test("T80", "" + s_c + sf_b);
+        test("Tnull", "" + s_c + s_IN);
+        test("T-52.0", "" + s_c + s_fM);
+        test("T75000000", "" + s_c + sf_i);
+        test("T44", "" + s_c + f_b);
+        test("T-1705032704", "" + s_c + sf_lM);
+        test("Tnull", "" + s_c + f_oAN);
+        test("T83.0", "" + s_c + f_d);
+        test("TI", "" + s_c + f_c);
+        test("T94.0", "" + s_c + f_f);
+        test("T12.0", "" + s_c + sf_d);
+        test("T-99.0", "" + s_c + f_dM);
+        test("T17.0", "" + s_c + sf_f);
+        test("T-84.0", "" + s_c + sf_dM);
+        test("T58000000", "" + s_c + f_i);
+        test("T-55000000", "" + s_c + f_iM);
+        test("T1460392448", "" + s_c + f_l);
+        test("TC(70)", "" + s_c + f_o);
+        test("T\u04511", "" + s_c + sf_strU);
+        test("T8000", "" + s_c + f_s);
+        test("T18", "" + s_c + s_str);
+        test("T-1000000", "" + s_c + s_iM);
+        test("T1000000", "" + s_c + sf_I);
+        test("Tnull", "" + s_c + f_oNtS);
+        test("Tfalse", "" + s_c + f_bl);
+        test("Tnull", "" + s_c + sf_iAN);
+        test("T-2000000", "" + s_c + sf_iM);
+        test("T-820130816", "" + s_c + f_lM);
+        test("Tnull", "" + s_c + sf_oAN);
+        test("T25000000", "" + s_c + s_I);
+        test("-42.0-96.0", "" + sf_fM + s_dM);
+        test("-42.0null", "" + sf_fM + s_oNtS);
+        test("-42.0\u045176", "" + sf_fM + f_strU);
+        test("-42.092", "" + sf_fM + sf_strU2);
+        test("-42.051", "" + sf_fM + sf_strU1);
+        test("-42.0null", "" + sf_fM + s_iAN);
+        test("-42.0-54", "" + sf_fM + f_bM);
+        test("-42.0-87.0", "" + sf_fM + f_fM);
+        test("-42.0null", "" + sf_fM + s_oAN);
+        test("-42.019", "" + sf_fM + f_str);
+        test("-42.0-41", "" + sf_fM + sf_bM);
+        test("-42.0null", "" + sf_fM + sf_IN);
+        test("-42.0T", "" + sf_fM + s_c);
+        test("-42.0-42.0", "" + sf_fM + sf_fM);
+        test("-42.025", "" + sf_fM + s_b);
+        test("-42.0null", "" + sf_fM + f_oN);
+        test("-42.0-1410065408", "" + sf_fM + s_lM);
+        test("-42.08.0", "" + sf_fM + s_d);
+        test("-42.055.0", "" + sf_fM + s_f);
+        test("-42.097000000", "" + sf_fM + s_i);
+        test("-42.0-9900", "" + sf_fM + f_sM);
+        test("-42.0935228928", "" + sf_fM + s_l);
+        test("-42.0-8400", "" + sf_fM + sf_sM);
+        test("-42.0C(82)", "" + sf_fM + s_o);
+        test("-42.0null", "" + sf_fM + sf_oNtS);
+        test("-42.0true", "" + sf_fM + s_bl);
+        test("-42.03900", "" + sf_fM + s_s);
+        test("-42.0null", "" + sf_fM + sf_oN);
+        test("-42.094000000", "" + sf_fM + f_I);
+        test("-42.0null", "" + sf_fM + f_IN);
+        test("-42.0true", "" + sf_fM + sf_bl);
+        test("-42.05500", "" + sf_fM + sf_s);
+        test("-42.0-2900", "" + sf_fM + s_sM);
+        test("-42.0-194313216", "" + sf_fM + sf_l);
+        test("-42.012", "" + sf_fM + s_strU1);
+        test("-42.0C(87)", "" + sf_fM + sf_o);
+        test("-42.091", "" + sf_fM + s_strU2);
+        test("-42.021", "" + sf_fM + f_strU1);
+        test("-42.018", "" + sf_fM + f_strU2);
+        test("-42.0null", "" + sf_fM + f_iAN);
+        test("-42.0null", "" + sf_fM + s_oN);
+        test("-42.0\u045180", "" + sf_fM + s_strU);
+        test("-42.0C", "" + sf_fM + sf_c);
+        test("-42.075", "" + sf_fM + sf_str);
+        test("-42.0-43", "" + sf_fM + s_bM);
+        test("-42.080", "" + sf_fM + sf_b);
+        test("-42.0null", "" + sf_fM + s_IN);
+        test("-42.0-52.0", "" + sf_fM + s_fM);
+        test("-42.075000000", "" + sf_fM + sf_i);
+        test("-42.044", "" + sf_fM + f_b);
+        test("-42.0-1705032704", "" + sf_fM + sf_lM);
+        test("-42.0null", "" + sf_fM + f_oAN);
+        test("-42.083.0", "" + sf_fM + f_d);
+        test("-42.0I", "" + sf_fM + f_c);
+        test("-42.094.0", "" + sf_fM + f_f);
+        test("-42.012.0", "" + sf_fM + sf_d);
+        test("-42.0-99.0", "" + sf_fM + f_dM);
+        test("-42.017.0", "" + sf_fM + sf_f);
+        test("-42.0-84.0", "" + sf_fM + sf_dM);
+        test("-42.058000000", "" + sf_fM + f_i);
+        test("-42.0-55000000", "" + sf_fM + f_iM);
+        test("-42.01460392448", "" + sf_fM + f_l);
+        test("-42.0C(70)", "" + sf_fM + f_o);
+        test("-42.0\u04511", "" + sf_fM + sf_strU);
+        test("-42.08000", "" + sf_fM + f_s);
+        test("-42.018", "" + sf_fM + s_str);
+        test("-42.0-1000000", "" + sf_fM + s_iM);
+        test("-42.01000000", "" + sf_fM + sf_I);
+        test("-42.0null", "" + sf_fM + f_oNtS);
+        test("-42.0false", "" + sf_fM + f_bl);
+        test("-42.0null", "" + sf_fM + sf_iAN);
+        test("-42.0-2000000", "" + sf_fM + sf_iM);
+        test("-42.0-820130816", "" + sf_fM + f_lM);
+        test("-42.0null", "" + sf_fM + sf_oAN);
+        test("-42.025000000", "" + sf_fM + s_I);
+        test("25-96.0", "" + s_b + s_dM);
+        test("25null", "" + s_b + s_oNtS);
+        test("25\u045176", "" + s_b + f_strU);
+        test("2592", "" + s_b + sf_strU2);
+        test("2551", "" + s_b + sf_strU1);
+        test("25null", "" + s_b + s_iAN);
+        test("25-54", "" + s_b + f_bM);
+        test("25-87.0", "" + s_b + f_fM);
+        test("25null", "" + s_b + s_oAN);
+        test("2519", "" + s_b + f_str);
+        test("25-41", "" + s_b + sf_bM);
+        test("25null", "" + s_b + sf_IN);
+        test("25T", "" + s_b + s_c);
+        test("25-42.0", "" + s_b + sf_fM);
+        test("2525", "" + s_b + s_b);
+        test("25null", "" + s_b + f_oN);
+        test("25-1410065408", "" + s_b + s_lM);
+        test("258.0", "" + s_b + s_d);
+        test("2555.0", "" + s_b + s_f);
+        test("2597000000", "" + s_b + s_i);
+        test("25-9900", "" + s_b + f_sM);
+        test("25935228928", "" + s_b + s_l);
+        test("25-8400", "" + s_b + sf_sM);
+        test("25C(82)", "" + s_b + s_o);
+        test("25null", "" + s_b + sf_oNtS);
+        test("25true", "" + s_b + s_bl);
+        test("253900", "" + s_b + s_s);
+        test("25null", "" + s_b + sf_oN);
+        test("2594000000", "" + s_b + f_I);
+        test("25null", "" + s_b + f_IN);
+        test("25true", "" + s_b + sf_bl);
+        test("255500", "" + s_b + sf_s);
+        test("25-2900", "" + s_b + s_sM);
+        test("25-194313216", "" + s_b + sf_l);
+        test("2512", "" + s_b + s_strU1);
+        test("25C(87)", "" + s_b + sf_o);
+        test("2591", "" + s_b + s_strU2);
+        test("2521", "" + s_b + f_strU1);
+        test("2518", "" + s_b + f_strU2);
+        test("25null", "" + s_b + f_iAN);
+        test("25null", "" + s_b + s_oN);
+        test("25\u045180", "" + s_b + s_strU);
+        test("25C", "" + s_b + sf_c);
+        test("2575", "" + s_b + sf_str);
+        test("25-43", "" + s_b + s_bM);
+        test("2580", "" + s_b + sf_b);
+        test("25null", "" + s_b + s_IN);
+        test("25-52.0", "" + s_b + s_fM);
+        test("2575000000", "" + s_b + sf_i);
+        test("2544", "" + s_b + f_b);
+        test("25-1705032704", "" + s_b + sf_lM);
+        test("25null", "" + s_b + f_oAN);
+        test("2583.0", "" + s_b + f_d);
+        test("25I", "" + s_b + f_c);
+        test("2594.0", "" + s_b + f_f);
+        test("2512.0", "" + s_b + sf_d);
+        test("25-99.0", "" + s_b + f_dM);
+        test("2517.0", "" + s_b + sf_f);
+        test("25-84.0", "" + s_b + sf_dM);
+        test("2558000000", "" + s_b + f_i);
+        test("25-55000000", "" + s_b + f_iM);
+        test("251460392448", "" + s_b + f_l);
+        test("25C(70)", "" + s_b + f_o);
+        test("25\u04511", "" + s_b + sf_strU);
+        test("258000", "" + s_b + f_s);
+        test("2518", "" + s_b + s_str);
+        test("25-1000000", "" + s_b + s_iM);
+        test("251000000", "" + s_b + sf_I);
+        test("25null", "" + s_b + f_oNtS);
+        test("25false", "" + s_b + f_bl);
+        test("25null", "" + s_b + sf_iAN);
+        test("25-2000000", "" + s_b + sf_iM);
+        test("25-820130816", "" + s_b + f_lM);
+        test("25null", "" + s_b + sf_oAN);
+        test("2525000000", "" + s_b + s_I);
+        test("null-96.0", "" + f_oN + s_dM);
+        test("nullnull", "" + f_oN + s_oNtS);
+        test("null\u045176", "" + f_oN + f_strU);
+        test("null92", "" + f_oN + sf_strU2);
+        test("null51", "" + f_oN + sf_strU1);
+        test("nullnull", "" + f_oN + s_iAN);
+        test("null-54", "" + f_oN + f_bM);
+        test("null-87.0", "" + f_oN + f_fM);
+        test("nullnull", "" + f_oN + s_oAN);
+        test("null19", "" + f_oN + f_str);
+        test("null-41", "" + f_oN + sf_bM);
+        test("nullnull", "" + f_oN + sf_IN);
+        test("nullT", "" + f_oN + s_c);
+        test("null-42.0", "" + f_oN + sf_fM);
+        test("null25", "" + f_oN + s_b);
+        test("nullnull", "" + f_oN + f_oN);
+        test("null-1410065408", "" + f_oN + s_lM);
+        test("null8.0", "" + f_oN + s_d);
+        test("null55.0", "" + f_oN + s_f);
+        test("null97000000", "" + f_oN + s_i);
+        test("null-9900", "" + f_oN + f_sM);
+        test("null935228928", "" + f_oN + s_l);
+        test("null-8400", "" + f_oN + sf_sM);
+        test("nullC(82)", "" + f_oN + s_o);
+        test("nullnull", "" + f_oN + sf_oNtS);
+        test("nulltrue", "" + f_oN + s_bl);
+        test("null3900", "" + f_oN + s_s);
+        test("nullnull", "" + f_oN + sf_oN);
+        test("null94000000", "" + f_oN + f_I);
+        test("nullnull", "" + f_oN + f_IN);
+        test("nulltrue", "" + f_oN + sf_bl);
+        test("null5500", "" + f_oN + sf_s);
+        test("null-2900", "" + f_oN + s_sM);
+        test("null-194313216", "" + f_oN + sf_l);
+        test("null12", "" + f_oN + s_strU1);
+        test("nullC(87)", "" + f_oN + sf_o);
+        test("null91", "" + f_oN + s_strU2);
+        test("null21", "" + f_oN + f_strU1);
+        test("null18", "" + f_oN + f_strU2);
+        test("nullnull", "" + f_oN + f_iAN);
+        test("nullnull", "" + f_oN + s_oN);
+        test("null\u045180", "" + f_oN + s_strU);
+        test("nullC", "" + f_oN + sf_c);
+        test("null75", "" + f_oN + sf_str);
+        test("null-43", "" + f_oN + s_bM);
+        test("null80", "" + f_oN + sf_b);
+        test("nullnull", "" + f_oN + s_IN);
+        test("null-52.0", "" + f_oN + s_fM);
+        test("null75000000", "" + f_oN + sf_i);
+        test("null44", "" + f_oN + f_b);
+        test("null-1705032704", "" + f_oN + sf_lM);
+        test("nullnull", "" + f_oN + f_oAN);
+        test("null83.0", "" + f_oN + f_d);
+        test("nullI", "" + f_oN + f_c);
+        test("null94.0", "" + f_oN + f_f);
+        test("null12.0", "" + f_oN + sf_d);
+        test("null-99.0", "" + f_oN + f_dM);
+        test("null17.0", "" + f_oN + sf_f);
+        test("null-84.0", "" + f_oN + sf_dM);
+        test("null58000000", "" + f_oN + f_i);
+        test("null-55000000", "" + f_oN + f_iM);
+        test("null1460392448", "" + f_oN + f_l);
+        test("nullC(70)", "" + f_oN + f_o);
+        test("null\u04511", "" + f_oN + sf_strU);
+        test("null8000", "" + f_oN + f_s);
+        test("null18", "" + f_oN + s_str);
+        test("null-1000000", "" + f_oN + s_iM);
+        test("null1000000", "" + f_oN + sf_I);
+        test("nullnull", "" + f_oN + f_oNtS);
+        test("nullfalse", "" + f_oN + f_bl);
+        test("nullnull", "" + f_oN + sf_iAN);
+        test("null-2000000", "" + f_oN + sf_iM);
+        test("null-820130816", "" + f_oN + f_lM);
+        test("nullnull", "" + f_oN + sf_oAN);
+        test("null25000000", "" + f_oN + s_I);
+        test("-1410065408-96.0", "" + s_lM + s_dM);
+        test("-1410065408null", "" + s_lM + s_oNtS);
+        test("-1410065408\u045176", "" + s_lM + f_strU);
+        test("-141006540892", "" + s_lM + sf_strU2);
+        test("-141006540851", "" + s_lM + sf_strU1);
+        test("-1410065408null", "" + s_lM + s_iAN);
+        test("-1410065408-54", "" + s_lM + f_bM);
+        test("-1410065408-87.0", "" + s_lM + f_fM);
+        test("-1410065408null", "" + s_lM + s_oAN);
+        test("-141006540819", "" + s_lM + f_str);
+        test("-1410065408-41", "" + s_lM + sf_bM);
+        test("-1410065408null", "" + s_lM + sf_IN);
+        test("-1410065408T", "" + s_lM + s_c);
+        test("-1410065408-42.0", "" + s_lM + sf_fM);
+        test("-141006540825", "" + s_lM + s_b);
+        test("-1410065408null", "" + s_lM + f_oN);
+        test("-1410065408-1410065408", "" + s_lM + s_lM);
+        test("-14100654088.0", "" + s_lM + s_d);
+        test("-141006540855.0", "" + s_lM + s_f);
+        test("-141006540897000000", "" + s_lM + s_i);
+        test("-1410065408-9900", "" + s_lM + f_sM);
+        test("-1410065408935228928", "" + s_lM + s_l);
+        test("-1410065408-8400", "" + s_lM + sf_sM);
+        test("-1410065408C(82)", "" + s_lM + s_o);
+        test("-1410065408null", "" + s_lM + sf_oNtS);
+        test("-1410065408true", "" + s_lM + s_bl);
+        test("-14100654083900", "" + s_lM + s_s);
+        test("-1410065408null", "" + s_lM + sf_oN);
+        test("-141006540894000000", "" + s_lM + f_I);
+        test("-1410065408null", "" + s_lM + f_IN);
+        test("-1410065408true", "" + s_lM + sf_bl);
+        test("-14100654085500", "" + s_lM + sf_s);
+        test("-1410065408-2900", "" + s_lM + s_sM);
+        test("-1410065408-194313216", "" + s_lM + sf_l);
+        test("-141006540812", "" + s_lM + s_strU1);
+        test("-1410065408C(87)", "" + s_lM + sf_o);
+        test("-141006540891", "" + s_lM + s_strU2);
+        test("-141006540821", "" + s_lM + f_strU1);
+        test("-141006540818", "" + s_lM + f_strU2);
+        test("-1410065408null", "" + s_lM + f_iAN);
+        test("-1410065408null", "" + s_lM + s_oN);
+        test("-1410065408\u045180", "" + s_lM + s_strU);
+        test("-1410065408C", "" + s_lM + sf_c);
+        test("-141006540875", "" + s_lM + sf_str);
+        test("-1410065408-43", "" + s_lM + s_bM);
+        test("-141006540880", "" + s_lM + sf_b);
+        test("-1410065408null", "" + s_lM + s_IN);
+        test("-1410065408-52.0", "" + s_lM + s_fM);
+        test("-141006540875000000", "" + s_lM + sf_i);
+        test("-141006540844", "" + s_lM + f_b);
+        test("-1410065408-1705032704", "" + s_lM + sf_lM);
+        test("-1410065408null", "" + s_lM + f_oAN);
+        test("-141006540883.0", "" + s_lM + f_d);
+        test("-1410065408I", "" + s_lM + f_c);
+        test("-141006540894.0", "" + s_lM + f_f);
+        test("-141006540812.0", "" + s_lM + sf_d);
+        test("-1410065408-99.0", "" + s_lM + f_dM);
+        test("-141006540817.0", "" + s_lM + sf_f);
+        test("-1410065408-84.0", "" + s_lM + sf_dM);
+        test("-141006540858000000", "" + s_lM + f_i);
+        test("-1410065408-55000000", "" + s_lM + f_iM);
+        test("-14100654081460392448", "" + s_lM + f_l);
+        test("-1410065408C(70)", "" + s_lM + f_o);
+        test("-1410065408\u04511", "" + s_lM + sf_strU);
+        test("-14100654088000", "" + s_lM + f_s);
+        test("-141006540818", "" + s_lM + s_str);
+        test("-1410065408-1000000", "" + s_lM + s_iM);
+        test("-14100654081000000", "" + s_lM + sf_I);
+        test("-1410065408null", "" + s_lM + f_oNtS);
+        test("-1410065408false", "" + s_lM + f_bl);
+        test("-1410065408null", "" + s_lM + sf_iAN);
+        test("-1410065408-2000000", "" + s_lM + sf_iM);
+        test("-1410065408-820130816", "" + s_lM + f_lM);
+        test("-1410065408null", "" + s_lM + sf_oAN);
+        test("-141006540825000000", "" + s_lM + s_I);
+        test("8.0-96.0", "" + s_d + s_dM);
+        test("8.0null", "" + s_d + s_oNtS);
+        test("8.0\u045176", "" + s_d + f_strU);
+        test("8.092", "" + s_d + sf_strU2);
+        test("8.051", "" + s_d + sf_strU1);
+        test("8.0null", "" + s_d + s_iAN);
+        test("8.0-54", "" + s_d + f_bM);
+        test("8.0-87.0", "" + s_d + f_fM);
+        test("8.0null", "" + s_d + s_oAN);
+        test("8.019", "" + s_d + f_str);
+        test("8.0-41", "" + s_d + sf_bM);
+        test("8.0null", "" + s_d + sf_IN);
+        test("8.0T", "" + s_d + s_c);
+        test("8.0-42.0", "" + s_d + sf_fM);
+        test("8.025", "" + s_d + s_b);
+        test("8.0null", "" + s_d + f_oN);
+        test("8.0-1410065408", "" + s_d + s_lM);
+        test("8.08.0", "" + s_d + s_d);
+        test("8.055.0", "" + s_d + s_f);
+        test("8.097000000", "" + s_d + s_i);
+        test("8.0-9900", "" + s_d + f_sM);
+        test("8.0935228928", "" + s_d + s_l);
+        test("8.0-8400", "" + s_d + sf_sM);
+        test("8.0C(82)", "" + s_d + s_o);
+        test("8.0null", "" + s_d + sf_oNtS);
+        test("8.0true", "" + s_d + s_bl);
+        test("8.03900", "" + s_d + s_s);
+        test("8.0null", "" + s_d + sf_oN);
+        test("8.094000000", "" + s_d + f_I);
+        test("8.0null", "" + s_d + f_IN);
+        test("8.0true", "" + s_d + sf_bl);
+        test("8.05500", "" + s_d + sf_s);
+        test("8.0-2900", "" + s_d + s_sM);
+        test("8.0-194313216", "" + s_d + sf_l);
+        test("8.012", "" + s_d + s_strU1);
+        test("8.0C(87)", "" + s_d + sf_o);
+        test("8.091", "" + s_d + s_strU2);
+        test("8.021", "" + s_d + f_strU1);
+        test("8.018", "" + s_d + f_strU2);
+        test("8.0null", "" + s_d + f_iAN);
+        test("8.0null", "" + s_d + s_oN);
+        test("8.0\u045180", "" + s_d + s_strU);
+        test("8.0C", "" + s_d + sf_c);
+        test("8.075", "" + s_d + sf_str);
+        test("8.0-43", "" + s_d + s_bM);
+        test("8.080", "" + s_d + sf_b);
+        test("8.0null", "" + s_d + s_IN);
+        test("8.0-52.0", "" + s_d + s_fM);
+        test("8.075000000", "" + s_d + sf_i);
+        test("8.044", "" + s_d + f_b);
+        test("8.0-1705032704", "" + s_d + sf_lM);
+        test("8.0null", "" + s_d + f_oAN);
+        test("8.083.0", "" + s_d + f_d);
+        test("8.0I", "" + s_d + f_c);
+        test("8.094.0", "" + s_d + f_f);
+        test("8.012.0", "" + s_d + sf_d);
+        test("8.0-99.0", "" + s_d + f_dM);
+        test("8.017.0", "" + s_d + sf_f);
+        test("8.0-84.0", "" + s_d + sf_dM);
+        test("8.058000000", "" + s_d + f_i);
+        test("8.0-55000000", "" + s_d + f_iM);
+        test("8.01460392448", "" + s_d + f_l);
+        test("8.0C(70)", "" + s_d + f_o);
+        test("8.0\u04511", "" + s_d + sf_strU);
+        test("8.08000", "" + s_d + f_s);
+        test("8.018", "" + s_d + s_str);
+        test("8.0-1000000", "" + s_d + s_iM);
+        test("8.01000000", "" + s_d + sf_I);
+        test("8.0null", "" + s_d + f_oNtS);
+        test("8.0false", "" + s_d + f_bl);
+        test("8.0null", "" + s_d + sf_iAN);
+        test("8.0-2000000", "" + s_d + sf_iM);
+        test("8.0-820130816", "" + s_d + f_lM);
+        test("8.0null", "" + s_d + sf_oAN);
+        test("8.025000000", "" + s_d + s_I);
+        test("55.0-96.0", "" + s_f + s_dM);
+        test("55.0null", "" + s_f + s_oNtS);
+        test("55.0\u045176", "" + s_f + f_strU);
+        test("55.092", "" + s_f + sf_strU2);
+        test("55.051", "" + s_f + sf_strU1);
+        test("55.0null", "" + s_f + s_iAN);
+        test("55.0-54", "" + s_f + f_bM);
+        test("55.0-87.0", "" + s_f + f_fM);
+        test("55.0null", "" + s_f + s_oAN);
+        test("55.019", "" + s_f + f_str);
+        test("55.0-41", "" + s_f + sf_bM);
+        test("55.0null", "" + s_f + sf_IN);
+        test("55.0T", "" + s_f + s_c);
+        test("55.0-42.0", "" + s_f + sf_fM);
+        test("55.025", "" + s_f + s_b);
+        test("55.0null", "" + s_f + f_oN);
+        test("55.0-1410065408", "" + s_f + s_lM);
+        test("55.08.0", "" + s_f + s_d);
+        test("55.055.0", "" + s_f + s_f);
+        test("55.097000000", "" + s_f + s_i);
+        test("55.0-9900", "" + s_f + f_sM);
+        test("55.0935228928", "" + s_f + s_l);
+        test("55.0-8400", "" + s_f + sf_sM);
+        test("55.0C(82)", "" + s_f + s_o);
+        test("55.0null", "" + s_f + sf_oNtS);
+        test("55.0true", "" + s_f + s_bl);
+        test("55.03900", "" + s_f + s_s);
+        test("55.0null", "" + s_f + sf_oN);
+        test("55.094000000", "" + s_f + f_I);
+        test("55.0null", "" + s_f + f_IN);
+        test("55.0true", "" + s_f + sf_bl);
+        test("55.05500", "" + s_f + sf_s);
+        test("55.0-2900", "" + s_f + s_sM);
+        test("55.0-194313216", "" + s_f + sf_l);
+        test("55.012", "" + s_f + s_strU1);
+        test("55.0C(87)", "" + s_f + sf_o);
+        test("55.091", "" + s_f + s_strU2);
+        test("55.021", "" + s_f + f_strU1);
+        test("55.018", "" + s_f + f_strU2);
+        test("55.0null", "" + s_f + f_iAN);
+        test("55.0null", "" + s_f + s_oN);
+        test("55.0\u045180", "" + s_f + s_strU);
+        test("55.0C", "" + s_f + sf_c);
+        test("55.075", "" + s_f + sf_str);
+        test("55.0-43", "" + s_f + s_bM);
+        test("55.080", "" + s_f + sf_b);
+        test("55.0null", "" + s_f + s_IN);
+        test("55.0-52.0", "" + s_f + s_fM);
+        test("55.075000000", "" + s_f + sf_i);
+        test("55.044", "" + s_f + f_b);
+        test("55.0-1705032704", "" + s_f + sf_lM);
+        test("55.0null", "" + s_f + f_oAN);
+        test("55.083.0", "" + s_f + f_d);
+        test("55.0I", "" + s_f + f_c);
+        test("55.094.0", "" + s_f + f_f);
+        test("55.012.0", "" + s_f + sf_d);
+        test("55.0-99.0", "" + s_f + f_dM);
+        test("55.017.0", "" + s_f + sf_f);
+        test("55.0-84.0", "" + s_f + sf_dM);
+        test("55.058000000", "" + s_f + f_i);
+        test("55.0-55000000", "" + s_f + f_iM);
+        test("55.01460392448", "" + s_f + f_l);
+        test("55.0C(70)", "" + s_f + f_o);
+        test("55.0\u04511", "" + s_f + sf_strU);
+        test("55.08000", "" + s_f + f_s);
+        test("55.018", "" + s_f + s_str);
+        test("55.0-1000000", "" + s_f + s_iM);
+        test("55.01000000", "" + s_f + sf_I);
+        test("55.0null", "" + s_f + f_oNtS);
+        test("55.0false", "" + s_f + f_bl);
+        test("55.0null", "" + s_f + sf_iAN);
+        test("55.0-2000000", "" + s_f + sf_iM);
+        test("55.0-820130816", "" + s_f + f_lM);
+        test("55.0null", "" + s_f + sf_oAN);
+        test("55.025000000", "" + s_f + s_I);
+        test("97000000-96.0", "" + s_i + s_dM);
+        test("97000000null", "" + s_i + s_oNtS);
+        test("97000000\u045176", "" + s_i + f_strU);
+        test("9700000092", "" + s_i + sf_strU2);
+        test("9700000051", "" + s_i + sf_strU1);
+        test("97000000null", "" + s_i + s_iAN);
+        test("97000000-54", "" + s_i + f_bM);
+        test("97000000-87.0", "" + s_i + f_fM);
+        test("97000000null", "" + s_i + s_oAN);
+        test("9700000019", "" + s_i + f_str);
+        test("97000000-41", "" + s_i + sf_bM);
+        test("97000000null", "" + s_i + sf_IN);
+        test("97000000T", "" + s_i + s_c);
+        test("97000000-42.0", "" + s_i + sf_fM);
+        test("9700000025", "" + s_i + s_b);
+        test("97000000null", "" + s_i + f_oN);
+        test("97000000-1410065408", "" + s_i + s_lM);
+        test("970000008.0", "" + s_i + s_d);
+        test("9700000055.0", "" + s_i + s_f);
+        test("9700000097000000", "" + s_i + s_i);
+        test("97000000-9900", "" + s_i + f_sM);
+        test("97000000935228928", "" + s_i + s_l);
+        test("97000000-8400", "" + s_i + sf_sM);
+        test("97000000C(82)", "" + s_i + s_o);
+        test("97000000null", "" + s_i + sf_oNtS);
+        test("97000000true", "" + s_i + s_bl);
+        test("970000003900", "" + s_i + s_s);
+        test("97000000null", "" + s_i + sf_oN);
+        test("9700000094000000", "" + s_i + f_I);
+        test("97000000null", "" + s_i + f_IN);
+        test("97000000true", "" + s_i + sf_bl);
+        test("970000005500", "" + s_i + sf_s);
+        test("97000000-2900", "" + s_i + s_sM);
+        test("97000000-194313216", "" + s_i + sf_l);
+        test("9700000012", "" + s_i + s_strU1);
+        test("97000000C(87)", "" + s_i + sf_o);
+        test("9700000091", "" + s_i + s_strU2);
+        test("9700000021", "" + s_i + f_strU1);
+        test("9700000018", "" + s_i + f_strU2);
+        test("97000000null", "" + s_i + f_iAN);
+        test("97000000null", "" + s_i + s_oN);
+        test("97000000\u045180", "" + s_i + s_strU);
+        test("97000000C", "" + s_i + sf_c);
+        test("9700000075", "" + s_i + sf_str);
+        test("97000000-43", "" + s_i + s_bM);
+        test("9700000080", "" + s_i + sf_b);
+        test("97000000null", "" + s_i + s_IN);
+        test("97000000-52.0", "" + s_i + s_fM);
+        test("9700000075000000", "" + s_i + sf_i);
+        test("9700000044", "" + s_i + f_b);
+        test("97000000-1705032704", "" + s_i + sf_lM);
+        test("97000000null", "" + s_i + f_oAN);
+        test("9700000083.0", "" + s_i + f_d);
+        test("97000000I", "" + s_i + f_c);
+        test("9700000094.0", "" + s_i + f_f);
+        test("9700000012.0", "" + s_i + sf_d);
+        test("97000000-99.0", "" + s_i + f_dM);
+        test("9700000017.0", "" + s_i + sf_f);
+        test("97000000-84.0", "" + s_i + sf_dM);
+        test("9700000058000000", "" + s_i + f_i);
+        test("97000000-55000000", "" + s_i + f_iM);
+        test("970000001460392448", "" + s_i + f_l);
+        test("97000000C(70)", "" + s_i + f_o);
+        test("97000000\u04511", "" + s_i + sf_strU);
+        test("970000008000", "" + s_i + f_s);
+        test("9700000018", "" + s_i + s_str);
+        test("97000000-1000000", "" + s_i + s_iM);
+        test("970000001000000", "" + s_i + sf_I);
+        test("97000000null", "" + s_i + f_oNtS);
+        test("97000000false", "" + s_i + f_bl);
+        test("97000000null", "" + s_i + sf_iAN);
+        test("97000000-2000000", "" + s_i + sf_iM);
+        test("97000000-820130816", "" + s_i + f_lM);
+        test("97000000null", "" + s_i + sf_oAN);
+        test("9700000025000000", "" + s_i + s_I);
+        test("-9900-96.0", "" + f_sM + s_dM);
+        test("-9900null", "" + f_sM + s_oNtS);
+        test("-9900\u045176", "" + f_sM + f_strU);
+        test("-990092", "" + f_sM + sf_strU2);
+        test("-990051", "" + f_sM + sf_strU1);
+        test("-9900null", "" + f_sM + s_iAN);
+        test("-9900-54", "" + f_sM + f_bM);
+        test("-9900-87.0", "" + f_sM + f_fM);
+        test("-9900null", "" + f_sM + s_oAN);
+        test("-990019", "" + f_sM + f_str);
+        test("-9900-41", "" + f_sM + sf_bM);
+        test("-9900null", "" + f_sM + sf_IN);
+        test("-9900T", "" + f_sM + s_c);
+        test("-9900-42.0", "" + f_sM + sf_fM);
+        test("-990025", "" + f_sM + s_b);
+        test("-9900null", "" + f_sM + f_oN);
+        test("-9900-1410065408", "" + f_sM + s_lM);
+        test("-99008.0", "" + f_sM + s_d);
+        test("-990055.0", "" + f_sM + s_f);
+        test("-990097000000", "" + f_sM + s_i);
+        test("-9900-9900", "" + f_sM + f_sM);
+        test("-9900935228928", "" + f_sM + s_l);
+        test("-9900-8400", "" + f_sM + sf_sM);
+        test("-9900C(82)", "" + f_sM + s_o);
+        test("-9900null", "" + f_sM + sf_oNtS);
+        test("-9900true", "" + f_sM + s_bl);
+        test("-99003900", "" + f_sM + s_s);
+        test("-9900null", "" + f_sM + sf_oN);
+        test("-990094000000", "" + f_sM + f_I);
+        test("-9900null", "" + f_sM + f_IN);
+        test("-9900true", "" + f_sM + sf_bl);
+        test("-99005500", "" + f_sM + sf_s);
+        test("-9900-2900", "" + f_sM + s_sM);
+        test("-9900-194313216", "" + f_sM + sf_l);
+        test("-990012", "" + f_sM + s_strU1);
+        test("-9900C(87)", "" + f_sM + sf_o);
+        test("-990091", "" + f_sM + s_strU2);
+        test("-990021", "" + f_sM + f_strU1);
+        test("-990018", "" + f_sM + f_strU2);
+        test("-9900null", "" + f_sM + f_iAN);
+        test("-9900null", "" + f_sM + s_oN);
+        test("-9900\u045180", "" + f_sM + s_strU);
+        test("-9900C", "" + f_sM + sf_c);
+        test("-990075", "" + f_sM + sf_str);
+        test("-9900-43", "" + f_sM + s_bM);
+        test("-990080", "" + f_sM + sf_b);
+        test("-9900null", "" + f_sM + s_IN);
+        test("-9900-52.0", "" + f_sM + s_fM);
+        test("-990075000000", "" + f_sM + sf_i);
+        test("-990044", "" + f_sM + f_b);
+        test("-9900-1705032704", "" + f_sM + sf_lM);
+        test("-9900null", "" + f_sM + f_oAN);
+        test("-990083.0", "" + f_sM + f_d);
+        test("-9900I", "" + f_sM + f_c);
+        test("-990094.0", "" + f_sM + f_f);
+        test("-990012.0", "" + f_sM + sf_d);
+        test("-9900-99.0", "" + f_sM + f_dM);
+        test("-990017.0", "" + f_sM + sf_f);
+        test("-9900-84.0", "" + f_sM + sf_dM);
+        test("-990058000000", "" + f_sM + f_i);
+        test("-9900-55000000", "" + f_sM + f_iM);
+        test("-99001460392448", "" + f_sM + f_l);
+        test("-9900C(70)", "" + f_sM + f_o);
+        test("-9900\u04511", "" + f_sM + sf_strU);
+        test("-99008000", "" + f_sM + f_s);
+        test("-990018", "" + f_sM + s_str);
+        test("-9900-1000000", "" + f_sM + s_iM);
+        test("-99001000000", "" + f_sM + sf_I);
+        test("-9900null", "" + f_sM + f_oNtS);
+        test("-9900false", "" + f_sM + f_bl);
+        test("-9900null", "" + f_sM + sf_iAN);
+        test("-9900-2000000", "" + f_sM + sf_iM);
+        test("-9900-820130816", "" + f_sM + f_lM);
+        test("-9900null", "" + f_sM + sf_oAN);
+        test("-990025000000", "" + f_sM + s_I);
+        test("935228928-96.0", "" + s_l + s_dM);
+        test("935228928null", "" + s_l + s_oNtS);
+        test("935228928\u045176", "" + s_l + f_strU);
+        test("93522892892", "" + s_l + sf_strU2);
+        test("93522892851", "" + s_l + sf_strU1);
+        test("935228928null", "" + s_l + s_iAN);
+        test("935228928-54", "" + s_l + f_bM);
+        test("935228928-87.0", "" + s_l + f_fM);
+        test("935228928null", "" + s_l + s_oAN);
+        test("93522892819", "" + s_l + f_str);
+        test("935228928-41", "" + s_l + sf_bM);
+        test("935228928null", "" + s_l + sf_IN);
+        test("935228928T", "" + s_l + s_c);
+        test("935228928-42.0", "" + s_l + sf_fM);
+        test("93522892825", "" + s_l + s_b);
+        test("935228928null", "" + s_l + f_oN);
+        test("935228928-1410065408", "" + s_l + s_lM);
+        test("9352289288.0", "" + s_l + s_d);
+        test("93522892855.0", "" + s_l + s_f);
+        test("93522892897000000", "" + s_l + s_i);
+        test("935228928-9900", "" + s_l + f_sM);
+        test("935228928935228928", "" + s_l + s_l);
+        test("935228928-8400", "" + s_l + sf_sM);
+        test("935228928C(82)", "" + s_l + s_o);
+        test("935228928null", "" + s_l + sf_oNtS);
+        test("935228928true", "" + s_l + s_bl);
+        test("9352289283900", "" + s_l + s_s);
+        test("935228928null", "" + s_l + sf_oN);
+        test("93522892894000000", "" + s_l + f_I);
+        test("935228928null", "" + s_l + f_IN);
+        test("935228928true", "" + s_l + sf_bl);
+        test("9352289285500", "" + s_l + sf_s);
+        test("935228928-2900", "" + s_l + s_sM);
+        test("935228928-194313216", "" + s_l + sf_l);
+        test("93522892812", "" + s_l + s_strU1);
+        test("935228928C(87)", "" + s_l + sf_o);
+        test("93522892891", "" + s_l + s_strU2);
+        test("93522892821", "" + s_l + f_strU1);
+        test("93522892818", "" + s_l + f_strU2);
+        test("935228928null", "" + s_l + f_iAN);
+        test("935228928null", "" + s_l + s_oN);
+        test("935228928\u045180", "" + s_l + s_strU);
+        test("935228928C", "" + s_l + sf_c);
+        test("93522892875", "" + s_l + sf_str);
+        test("935228928-43", "" + s_l + s_bM);
+        test("93522892880", "" + s_l + sf_b);
+        test("935228928null", "" + s_l + s_IN);
+        test("935228928-52.0", "" + s_l + s_fM);
+        test("93522892875000000", "" + s_l + sf_i);
+        test("93522892844", "" + s_l + f_b);
+        test("935228928-1705032704", "" + s_l + sf_lM);
+        test("935228928null", "" + s_l + f_oAN);
+        test("93522892883.0", "" + s_l + f_d);
+        test("935228928I", "" + s_l + f_c);
+        test("93522892894.0", "" + s_l + f_f);
+        test("93522892812.0", "" + s_l + sf_d);
+        test("935228928-99.0", "" + s_l + f_dM);
+        test("93522892817.0", "" + s_l + sf_f);
+        test("935228928-84.0", "" + s_l + sf_dM);
+        test("93522892858000000", "" + s_l + f_i);
+        test("935228928-55000000", "" + s_l + f_iM);
+        test("9352289281460392448", "" + s_l + f_l);
+        test("935228928C(70)", "" + s_l + f_o);
+        test("935228928\u04511", "" + s_l + sf_strU);
+        test("9352289288000", "" + s_l + f_s);
+        test("93522892818", "" + s_l + s_str);
+        test("935228928-1000000", "" + s_l + s_iM);
+        test("9352289281000000", "" + s_l + sf_I);
+        test("935228928null", "" + s_l + f_oNtS);
+        test("935228928false", "" + s_l + f_bl);
+        test("935228928null", "" + s_l + sf_iAN);
+        test("935228928-2000000", "" + s_l + sf_iM);
+        test("935228928-820130816", "" + s_l + f_lM);
+        test("935228928null", "" + s_l + sf_oAN);
+        test("93522892825000000", "" + s_l + s_I);
+        test("-8400-96.0", "" + sf_sM + s_dM);
+        test("-8400null", "" + sf_sM + s_oNtS);
+        test("-8400\u045176", "" + sf_sM + f_strU);
+        test("-840092", "" + sf_sM + sf_strU2);
+        test("-840051", "" + sf_sM + sf_strU1);
+        test("-8400null", "" + sf_sM + s_iAN);
+        test("-8400-54", "" + sf_sM + f_bM);
+        test("-8400-87.0", "" + sf_sM + f_fM);
+        test("-8400null", "" + sf_sM + s_oAN);
+        test("-840019", "" + sf_sM + f_str);
+        test("-8400-41", "" + sf_sM + sf_bM);
+        test("-8400null", "" + sf_sM + sf_IN);
+        test("-8400T", "" + sf_sM + s_c);
+        test("-8400-42.0", "" + sf_sM + sf_fM);
+        test("-840025", "" + sf_sM + s_b);
+        test("-8400null", "" + sf_sM + f_oN);
+        test("-8400-1410065408", "" + sf_sM + s_lM);
+        test("-84008.0", "" + sf_sM + s_d);
+        test("-840055.0", "" + sf_sM + s_f);
+        test("-840097000000", "" + sf_sM + s_i);
+        test("-8400-9900", "" + sf_sM + f_sM);
+        test("-8400935228928", "" + sf_sM + s_l);
+        test("-8400-8400", "" + sf_sM + sf_sM);
+        test("-8400C(82)", "" + sf_sM + s_o);
+        test("-8400null", "" + sf_sM + sf_oNtS);
+        test("-8400true", "" + sf_sM + s_bl);
+        test("-84003900", "" + sf_sM + s_s);
+        test("-8400null", "" + sf_sM + sf_oN);
+        test("-840094000000", "" + sf_sM + f_I);
+        test("-8400null", "" + sf_sM + f_IN);
+        test("-8400true", "" + sf_sM + sf_bl);
+        test("-84005500", "" + sf_sM + sf_s);
+        test("-8400-2900", "" + sf_sM + s_sM);
+        test("-8400-194313216", "" + sf_sM + sf_l);
+        test("-840012", "" + sf_sM + s_strU1);
+        test("-8400C(87)", "" + sf_sM + sf_o);
+        test("-840091", "" + sf_sM + s_strU2);
+        test("-840021", "" + sf_sM + f_strU1);
+        test("-840018", "" + sf_sM + f_strU2);
+        test("-8400null", "" + sf_sM + f_iAN);
+        test("-8400null", "" + sf_sM + s_oN);
+        test("-8400\u045180", "" + sf_sM + s_strU);
+        test("-8400C", "" + sf_sM + sf_c);
+        test("-840075", "" + sf_sM + sf_str);
+        test("-8400-43", "" + sf_sM + s_bM);
+        test("-840080", "" + sf_sM + sf_b);
+        test("-8400null", "" + sf_sM + s_IN);
+        test("-8400-52.0", "" + sf_sM + s_fM);
+        test("-840075000000", "" + sf_sM + sf_i);
+        test("-840044", "" + sf_sM + f_b);
+        test("-8400-1705032704", "" + sf_sM + sf_lM);
+        test("-8400null", "" + sf_sM + f_oAN);
+        test("-840083.0", "" + sf_sM + f_d);
+        test("-8400I", "" + sf_sM + f_c);
+        test("-840094.0", "" + sf_sM + f_f);
+        test("-840012.0", "" + sf_sM + sf_d);
+        test("-8400-99.0", "" + sf_sM + f_dM);
+        test("-840017.0", "" + sf_sM + sf_f);
+        test("-8400-84.0", "" + sf_sM + sf_dM);
+        test("-840058000000", "" + sf_sM + f_i);
+        test("-8400-55000000", "" + sf_sM + f_iM);
+        test("-84001460392448", "" + sf_sM + f_l);
+        test("-8400C(70)", "" + sf_sM + f_o);
+        test("-8400\u04511", "" + sf_sM + sf_strU);
+        test("-84008000", "" + sf_sM + f_s);
+        test("-840018", "" + sf_sM + s_str);
+        test("-8400-1000000", "" + sf_sM + s_iM);
+        test("-84001000000", "" + sf_sM + sf_I);
+        test("-8400null", "" + sf_sM + f_oNtS);
+        test("-8400false", "" + sf_sM + f_bl);
+        test("-8400null", "" + sf_sM + sf_iAN);
+        test("-8400-2000000", "" + sf_sM + sf_iM);
+        test("-8400-820130816", "" + sf_sM + f_lM);
+        test("-8400null", "" + sf_sM + sf_oAN);
+        test("-840025000000", "" + sf_sM + s_I);
+        test("C(82)-96.0", "" + s_o + s_dM);
+        test("C(82)null", "" + s_o + s_oNtS);
+        test("C(82)\u045176", "" + s_o + f_strU);
+        test("C(82)92", "" + s_o + sf_strU2);
+        test("C(82)51", "" + s_o + sf_strU1);
+        test("C(82)null", "" + s_o + s_iAN);
+        test("C(82)-54", "" + s_o + f_bM);
+        test("C(82)-87.0", "" + s_o + f_fM);
+        test("C(82)null", "" + s_o + s_oAN);
+        test("C(82)19", "" + s_o + f_str);
+        test("C(82)-41", "" + s_o + sf_bM);
+        test("C(82)null", "" + s_o + sf_IN);
+        test("C(82)T", "" + s_o + s_c);
+        test("C(82)-42.0", "" + s_o + sf_fM);
+        test("C(82)25", "" + s_o + s_b);
+        test("C(82)null", "" + s_o + f_oN);
+        test("C(82)-1410065408", "" + s_o + s_lM);
+        test("C(82)8.0", "" + s_o + s_d);
+        test("C(82)55.0", "" + s_o + s_f);
+        test("C(82)97000000", "" + s_o + s_i);
+        test("C(82)-9900", "" + s_o + f_sM);
+        test("C(82)935228928", "" + s_o + s_l);
+        test("C(82)-8400", "" + s_o + sf_sM);
+        test("C(82)C(82)", "" + s_o + s_o);
+        test("C(82)null", "" + s_o + sf_oNtS);
+        test("C(82)true", "" + s_o + s_bl);
+        test("C(82)3900", "" + s_o + s_s);
+        test("C(82)null", "" + s_o + sf_oN);
+        test("C(82)94000000", "" + s_o + f_I);
+        test("C(82)null", "" + s_o + f_IN);
+        test("C(82)true", "" + s_o + sf_bl);
+        test("C(82)5500", "" + s_o + sf_s);
+        test("C(82)-2900", "" + s_o + s_sM);
+        test("C(82)-194313216", "" + s_o + sf_l);
+        test("C(82)12", "" + s_o + s_strU1);
+        test("C(82)C(87)", "" + s_o + sf_o);
+        test("C(82)91", "" + s_o + s_strU2);
+        test("C(82)21", "" + s_o + f_strU1);
+        test("C(82)18", "" + s_o + f_strU2);
+        test("C(82)null", "" + s_o + f_iAN);
+        test("C(82)null", "" + s_o + s_oN);
+        test("C(82)\u045180", "" + s_o + s_strU);
+        test("C(82)C", "" + s_o + sf_c);
+        test("C(82)75", "" + s_o + sf_str);
+        test("C(82)-43", "" + s_o + s_bM);
+        test("C(82)80", "" + s_o + sf_b);
+        test("C(82)null", "" + s_o + s_IN);
+        test("C(82)-52.0", "" + s_o + s_fM);
+        test("C(82)75000000", "" + s_o + sf_i);
+        test("C(82)44", "" + s_o + f_b);
+        test("C(82)-1705032704", "" + s_o + sf_lM);
+        test("C(82)null", "" + s_o + f_oAN);
+        test("C(82)83.0", "" + s_o + f_d);
+        test("C(82)I", "" + s_o + f_c);
+        test("C(82)94.0", "" + s_o + f_f);
+        test("C(82)12.0", "" + s_o + sf_d);
+        test("C(82)-99.0", "" + s_o + f_dM);
+        test("C(82)17.0", "" + s_o + sf_f);
+        test("C(82)-84.0", "" + s_o + sf_dM);
+        test("C(82)58000000", "" + s_o + f_i);
+        test("C(82)-55000000", "" + s_o + f_iM);
+        test("C(82)1460392448", "" + s_o + f_l);
+        test("C(82)C(70)", "" + s_o + f_o);
+        test("C(82)\u04511", "" + s_o + sf_strU);
+        test("C(82)8000", "" + s_o + f_s);
+        test("C(82)18", "" + s_o + s_str);
+        test("C(82)-1000000", "" + s_o + s_iM);
+        test("C(82)1000000", "" + s_o + sf_I);
+        test("C(82)null", "" + s_o + f_oNtS);
+        test("C(82)false", "" + s_o + f_bl);
+        test("C(82)null", "" + s_o + sf_iAN);
+        test("C(82)-2000000", "" + s_o + sf_iM);
+        test("C(82)-820130816", "" + s_o + f_lM);
+        test("C(82)null", "" + s_o + sf_oAN);
+        test("C(82)25000000", "" + s_o + s_I);
+        test("null-96.0", "" + sf_oNtS + s_dM);
+        test("nullnull", "" + sf_oNtS + s_oNtS);
+        test("null\u045176", "" + sf_oNtS + f_strU);
+        test("null92", "" + sf_oNtS + sf_strU2);
+        test("null51", "" + sf_oNtS + sf_strU1);
+        test("nullnull", "" + sf_oNtS + s_iAN);
+        test("null-54", "" + sf_oNtS + f_bM);
+        test("null-87.0", "" + sf_oNtS + f_fM);
+        test("nullnull", "" + sf_oNtS + s_oAN);
+        test("null19", "" + sf_oNtS + f_str);
+        test("null-41", "" + sf_oNtS + sf_bM);
+        test("nullnull", "" + sf_oNtS + sf_IN);
+        test("nullT", "" + sf_oNtS + s_c);
+        test("null-42.0", "" + sf_oNtS + sf_fM);
+        test("null25", "" + sf_oNtS + s_b);
+        test("nullnull", "" + sf_oNtS + f_oN);
+        test("null-1410065408", "" + sf_oNtS + s_lM);
+        test("null8.0", "" + sf_oNtS + s_d);
+        test("null55.0", "" + sf_oNtS + s_f);
+        test("null97000000", "" + sf_oNtS + s_i);
+        test("null-9900", "" + sf_oNtS + f_sM);
+        test("null935228928", "" + sf_oNtS + s_l);
+        test("null-8400", "" + sf_oNtS + sf_sM);
+        test("nullC(82)", "" + sf_oNtS + s_o);
+        test("nullnull", "" + sf_oNtS + sf_oNtS);
+        test("nulltrue", "" + sf_oNtS + s_bl);
+        test("null3900", "" + sf_oNtS + s_s);
+        test("nullnull", "" + sf_oNtS + sf_oN);
+        test("null94000000", "" + sf_oNtS + f_I);
+        test("nullnull", "" + sf_oNtS + f_IN);
+        test("nulltrue", "" + sf_oNtS + sf_bl);
+        test("null5500", "" + sf_oNtS + sf_s);
+        test("null-2900", "" + sf_oNtS + s_sM);
+        test("null-194313216", "" + sf_oNtS + sf_l);
+        test("null12", "" + sf_oNtS + s_strU1);
+        test("nullC(87)", "" + sf_oNtS + sf_o);
+        test("null91", "" + sf_oNtS + s_strU2);
+        test("null21", "" + sf_oNtS + f_strU1);
+        test("null18", "" + sf_oNtS + f_strU2);
+        test("nullnull", "" + sf_oNtS + f_iAN);
+        test("nullnull", "" + sf_oNtS + s_oN);
+        test("null\u045180", "" + sf_oNtS + s_strU);
+        test("nullC", "" + sf_oNtS + sf_c);
+        test("null75", "" + sf_oNtS + sf_str);
+        test("null-43", "" + sf_oNtS + s_bM);
+        test("null80", "" + sf_oNtS + sf_b);
+        test("nullnull", "" + sf_oNtS + s_IN);
+        test("null-52.0", "" + sf_oNtS + s_fM);
+        test("null75000000", "" + sf_oNtS + sf_i);
+        test("null44", "" + sf_oNtS + f_b);
+        test("null-1705032704", "" + sf_oNtS + sf_lM);
+        test("nullnull", "" + sf_oNtS + f_oAN);
+        test("null83.0", "" + sf_oNtS + f_d);
+        test("nullI", "" + sf_oNtS + f_c);
+        test("null94.0", "" + sf_oNtS + f_f);
+        test("null12.0", "" + sf_oNtS + sf_d);
+        test("null-99.0", "" + sf_oNtS + f_dM);
+        test("null17.0", "" + sf_oNtS + sf_f);
+        test("null-84.0", "" + sf_oNtS + sf_dM);
+        test("null58000000", "" + sf_oNtS + f_i);
+        test("null-55000000", "" + sf_oNtS + f_iM);
+        test("null1460392448", "" + sf_oNtS + f_l);
+        test("nullC(70)", "" + sf_oNtS + f_o);
+        test("null\u04511", "" + sf_oNtS + sf_strU);
+        test("null8000", "" + sf_oNtS + f_s);
+        test("null18", "" + sf_oNtS + s_str);
+        test("null-1000000", "" + sf_oNtS + s_iM);
+        test("null1000000", "" + sf_oNtS + sf_I);
+        test("nullnull", "" + sf_oNtS + f_oNtS);
+        test("nullfalse", "" + sf_oNtS + f_bl);
+        test("nullnull", "" + sf_oNtS + sf_iAN);
+        test("null-2000000", "" + sf_oNtS + sf_iM);
+        test("null-820130816", "" + sf_oNtS + f_lM);
+        test("nullnull", "" + sf_oNtS + sf_oAN);
+        test("null25000000", "" + sf_oNtS + s_I);
+        test("true-96.0", "" + s_bl + s_dM);
+        test("truenull", "" + s_bl + s_oNtS);
+        test("true\u045176", "" + s_bl + f_strU);
+        test("true92", "" + s_bl + sf_strU2);
+        test("true51", "" + s_bl + sf_strU1);
+        test("truenull", "" + s_bl + s_iAN);
+        test("true-54", "" + s_bl + f_bM);
+        test("true-87.0", "" + s_bl + f_fM);
+        test("truenull", "" + s_bl + s_oAN);
+        test("true19", "" + s_bl + f_str);
+        test("true-41", "" + s_bl + sf_bM);
+        test("truenull", "" + s_bl + sf_IN);
+        test("trueT", "" + s_bl + s_c);
+        test("true-42.0", "" + s_bl + sf_fM);
+        test("true25", "" + s_bl + s_b);
+        test("truenull", "" + s_bl + f_oN);
+        test("true-1410065408", "" + s_bl + s_lM);
+        test("true8.0", "" + s_bl + s_d);
+        test("true55.0", "" + s_bl + s_f);
+        test("true97000000", "" + s_bl + s_i);
+        test("true-9900", "" + s_bl + f_sM);
+        test("true935228928", "" + s_bl + s_l);
+        test("true-8400", "" + s_bl + sf_sM);
+        test("trueC(82)", "" + s_bl + s_o);
+        test("truenull", "" + s_bl + sf_oNtS);
+        test("truetrue", "" + s_bl + s_bl);
+        test("true3900", "" + s_bl + s_s);
+        test("truenull", "" + s_bl + sf_oN);
+        test("true94000000", "" + s_bl + f_I);
+        test("truenull", "" + s_bl + f_IN);
+        test("truetrue", "" + s_bl + sf_bl);
+        test("true5500", "" + s_bl + sf_s);
+        test("true-2900", "" + s_bl + s_sM);
+        test("true-194313216", "" + s_bl + sf_l);
+        test("true12", "" + s_bl + s_strU1);
+        test("trueC(87)", "" + s_bl + sf_o);
+        test("true91", "" + s_bl + s_strU2);
+        test("true21", "" + s_bl + f_strU1);
+        test("true18", "" + s_bl + f_strU2);
+        test("truenull", "" + s_bl + f_iAN);
+        test("truenull", "" + s_bl + s_oN);
+        test("true\u045180", "" + s_bl + s_strU);
+        test("trueC", "" + s_bl + sf_c);
+        test("true75", "" + s_bl + sf_str);
+        test("true-43", "" + s_bl + s_bM);
+        test("true80", "" + s_bl + sf_b);
+        test("truenull", "" + s_bl + s_IN);
+        test("true-52.0", "" + s_bl + s_fM);
+        test("true75000000", "" + s_bl + sf_i);
+        test("true44", "" + s_bl + f_b);
+    }
+
+    public void run2() {
+        test("true-1705032704", "" + s_bl + sf_lM);
+        test("truenull", "" + s_bl + f_oAN);
+        test("true83.0", "" + s_bl + f_d);
+        test("trueI", "" + s_bl + f_c);
+        test("true94.0", "" + s_bl + f_f);
+        test("true12.0", "" + s_bl + sf_d);
+        test("true-99.0", "" + s_bl + f_dM);
+        test("true17.0", "" + s_bl + sf_f);
+        test("true-84.0", "" + s_bl + sf_dM);
+        test("true58000000", "" + s_bl + f_i);
+        test("true-55000000", "" + s_bl + f_iM);
+        test("true1460392448", "" + s_bl + f_l);
+        test("trueC(70)", "" + s_bl + f_o);
+        test("true\u04511", "" + s_bl + sf_strU);
+        test("true8000", "" + s_bl + f_s);
+        test("true18", "" + s_bl + s_str);
+        test("true-1000000", "" + s_bl + s_iM);
+        test("true1000000", "" + s_bl + sf_I);
+        test("truenull", "" + s_bl + f_oNtS);
+        test("truefalse", "" + s_bl + f_bl);
+        test("truenull", "" + s_bl + sf_iAN);
+        test("true-2000000", "" + s_bl + sf_iM);
+        test("true-820130816", "" + s_bl + f_lM);
+        test("truenull", "" + s_bl + sf_oAN);
+        test("true25000000", "" + s_bl + s_I);
+        test("3900-96.0", "" + s_s + s_dM);
+        test("3900null", "" + s_s + s_oNtS);
+        test("3900\u045176", "" + s_s + f_strU);
+        test("390092", "" + s_s + sf_strU2);
+        test("390051", "" + s_s + sf_strU1);
+        test("3900null", "" + s_s + s_iAN);
+        test("3900-54", "" + s_s + f_bM);
+        test("3900-87.0", "" + s_s + f_fM);
+        test("3900null", "" + s_s + s_oAN);
+        test("390019", "" + s_s + f_str);
+        test("3900-41", "" + s_s + sf_bM);
+        test("3900null", "" + s_s + sf_IN);
+        test("3900T", "" + s_s + s_c);
+        test("3900-42.0", "" + s_s + sf_fM);
+        test("390025", "" + s_s + s_b);
+        test("3900null", "" + s_s + f_oN);
+        test("3900-1410065408", "" + s_s + s_lM);
+        test("39008.0", "" + s_s + s_d);
+        test("390055.0", "" + s_s + s_f);
+        test("390097000000", "" + s_s + s_i);
+        test("3900-9900", "" + s_s + f_sM);
+        test("3900935228928", "" + s_s + s_l);
+        test("3900-8400", "" + s_s + sf_sM);
+        test("3900C(82)", "" + s_s + s_o);
+        test("3900null", "" + s_s + sf_oNtS);
+        test("3900true", "" + s_s + s_bl);
+        test("39003900", "" + s_s + s_s);
+        test("3900null", "" + s_s + sf_oN);
+        test("390094000000", "" + s_s + f_I);
+        test("3900null", "" + s_s + f_IN);
+        test("3900true", "" + s_s + sf_bl);
+        test("39005500", "" + s_s + sf_s);
+        test("3900-2900", "" + s_s + s_sM);
+        test("3900-194313216", "" + s_s + sf_l);
+        test("390012", "" + s_s + s_strU1);
+        test("3900C(87)", "" + s_s + sf_o);
+        test("390091", "" + s_s + s_strU2);
+        test("390021", "" + s_s + f_strU1);
+        test("390018", "" + s_s + f_strU2);
+        test("3900null", "" + s_s + f_iAN);
+        test("3900null", "" + s_s + s_oN);
+        test("3900\u045180", "" + s_s + s_strU);
+        test("3900C", "" + s_s + sf_c);
+        test("390075", "" + s_s + sf_str);
+        test("3900-43", "" + s_s + s_bM);
+        test("390080", "" + s_s + sf_b);
+        test("3900null", "" + s_s + s_IN);
+        test("3900-52.0", "" + s_s + s_fM);
+        test("390075000000", "" + s_s + sf_i);
+        test("390044", "" + s_s + f_b);
+        test("3900-1705032704", "" + s_s + sf_lM);
+        test("3900null", "" + s_s + f_oAN);
+        test("390083.0", "" + s_s + f_d);
+        test("3900I", "" + s_s + f_c);
+        test("390094.0", "" + s_s + f_f);
+        test("390012.0", "" + s_s + sf_d);
+        test("3900-99.0", "" + s_s + f_dM);
+        test("390017.0", "" + s_s + sf_f);
+        test("3900-84.0", "" + s_s + sf_dM);
+        test("390058000000", "" + s_s + f_i);
+        test("3900-55000000", "" + s_s + f_iM);
+        test("39001460392448", "" + s_s + f_l);
+        test("3900C(70)", "" + s_s + f_o);
+        test("3900\u04511", "" + s_s + sf_strU);
+        test("39008000", "" + s_s + f_s);
+        test("390018", "" + s_s + s_str);
+        test("3900-1000000", "" + s_s + s_iM);
+        test("39001000000", "" + s_s + sf_I);
+        test("3900null", "" + s_s + f_oNtS);
+        test("3900false", "" + s_s + f_bl);
+        test("3900null", "" + s_s + sf_iAN);
+        test("3900-2000000", "" + s_s + sf_iM);
+        test("3900-820130816", "" + s_s + f_lM);
+        test("3900null", "" + s_s + sf_oAN);
+        test("390025000000", "" + s_s + s_I);
+        test("null-96.0", "" + sf_oN + s_dM);
+        test("nullnull", "" + sf_oN + s_oNtS);
+        test("null\u045176", "" + sf_oN + f_strU);
+        test("null92", "" + sf_oN + sf_strU2);
+        test("null51", "" + sf_oN + sf_strU1);
+        test("nullnull", "" + sf_oN + s_iAN);
+        test("null-54", "" + sf_oN + f_bM);
+        test("null-87.0", "" + sf_oN + f_fM);
+        test("nullnull", "" + sf_oN + s_oAN);
+        test("null19", "" + sf_oN + f_str);
+        test("null-41", "" + sf_oN + sf_bM);
+        test("nullnull", "" + sf_oN + sf_IN);
+        test("nullT", "" + sf_oN + s_c);
+        test("null-42.0", "" + sf_oN + sf_fM);
+        test("null25", "" + sf_oN + s_b);
+        test("nullnull", "" + sf_oN + f_oN);
+        test("null-1410065408", "" + sf_oN + s_lM);
+        test("null8.0", "" + sf_oN + s_d);
+        test("null55.0", "" + sf_oN + s_f);
+        test("null97000000", "" + sf_oN + s_i);
+        test("null-9900", "" + sf_oN + f_sM);
+        test("null935228928", "" + sf_oN + s_l);
+        test("null-8400", "" + sf_oN + sf_sM);
+        test("nullC(82)", "" + sf_oN + s_o);
+        test("nullnull", "" + sf_oN + sf_oNtS);
+        test("nulltrue", "" + sf_oN + s_bl);
+        test("null3900", "" + sf_oN + s_s);
+        test("nullnull", "" + sf_oN + sf_oN);
+        test("null94000000", "" + sf_oN + f_I);
+        test("nullnull", "" + sf_oN + f_IN);
+        test("nulltrue", "" + sf_oN + sf_bl);
+        test("null5500", "" + sf_oN + sf_s);
+        test("null-2900", "" + sf_oN + s_sM);
+        test("null-194313216", "" + sf_oN + sf_l);
+        test("null12", "" + sf_oN + s_strU1);
+        test("nullC(87)", "" + sf_oN + sf_o);
+        test("null91", "" + sf_oN + s_strU2);
+        test("null21", "" + sf_oN + f_strU1);
+        test("null18", "" + sf_oN + f_strU2);
+        test("nullnull", "" + sf_oN + f_iAN);
+        test("nullnull", "" + sf_oN + s_oN);
+        test("null\u045180", "" + sf_oN + s_strU);
+        test("nullC", "" + sf_oN + sf_c);
+        test("null75", "" + sf_oN + sf_str);
+        test("null-43", "" + sf_oN + s_bM);
+        test("null80", "" + sf_oN + sf_b);
+        test("nullnull", "" + sf_oN + s_IN);
+        test("null-52.0", "" + sf_oN + s_fM);
+        test("null75000000", "" + sf_oN + sf_i);
+        test("null44", "" + sf_oN + f_b);
+        test("null-1705032704", "" + sf_oN + sf_lM);
+        test("nullnull", "" + sf_oN + f_oAN);
+        test("null83.0", "" + sf_oN + f_d);
+        test("nullI", "" + sf_oN + f_c);
+        test("null94.0", "" + sf_oN + f_f);
+        test("null12.0", "" + sf_oN + sf_d);
+        test("null-99.0", "" + sf_oN + f_dM);
+        test("null17.0", "" + sf_oN + sf_f);
+        test("null-84.0", "" + sf_oN + sf_dM);
+        test("null58000000", "" + sf_oN + f_i);
+        test("null-55000000", "" + sf_oN + f_iM);
+        test("null1460392448", "" + sf_oN + f_l);
+        test("nullC(70)", "" + sf_oN + f_o);
+        test("null\u04511", "" + sf_oN + sf_strU);
+        test("null8000", "" + sf_oN + f_s);
+        test("null18", "" + sf_oN + s_str);
+        test("null-1000000", "" + sf_oN + s_iM);
+        test("null1000000", "" + sf_oN + sf_I);
+        test("nullnull", "" + sf_oN + f_oNtS);
+        test("nullfalse", "" + sf_oN + f_bl);
+        test("nullnull", "" + sf_oN + sf_iAN);
+        test("null-2000000", "" + sf_oN + sf_iM);
+        test("null-820130816", "" + sf_oN + f_lM);
+        test("nullnull", "" + sf_oN + sf_oAN);
+        test("null25000000", "" + sf_oN + s_I);
+        test("94000000-96.0", "" + f_I + s_dM);
+        test("94000000null", "" + f_I + s_oNtS);
+        test("94000000\u045176", "" + f_I + f_strU);
+        test("9400000092", "" + f_I + sf_strU2);
+        test("9400000051", "" + f_I + sf_strU1);
+        test("94000000null", "" + f_I + s_iAN);
+        test("94000000-54", "" + f_I + f_bM);
+        test("94000000-87.0", "" + f_I + f_fM);
+        test("94000000null", "" + f_I + s_oAN);
+        test("9400000019", "" + f_I + f_str);
+        test("94000000-41", "" + f_I + sf_bM);
+        test("94000000null", "" + f_I + sf_IN);
+        test("94000000T", "" + f_I + s_c);
+        test("94000000-42.0", "" + f_I + sf_fM);
+        test("9400000025", "" + f_I + s_b);
+        test("94000000null", "" + f_I + f_oN);
+        test("94000000-1410065408", "" + f_I + s_lM);
+        test("940000008.0", "" + f_I + s_d);
+        test("9400000055.0", "" + f_I + s_f);
+        test("9400000097000000", "" + f_I + s_i);
+        test("94000000-9900", "" + f_I + f_sM);
+        test("94000000935228928", "" + f_I + s_l);
+        test("94000000-8400", "" + f_I + sf_sM);
+        test("94000000C(82)", "" + f_I + s_o);
+        test("94000000null", "" + f_I + sf_oNtS);
+        test("94000000true", "" + f_I + s_bl);
+        test("940000003900", "" + f_I + s_s);
+        test("94000000null", "" + f_I + sf_oN);
+        test("9400000094000000", "" + f_I + f_I);
+        test("94000000null", "" + f_I + f_IN);
+        test("94000000true", "" + f_I + sf_bl);
+        test("940000005500", "" + f_I + sf_s);
+        test("94000000-2900", "" + f_I + s_sM);
+        test("94000000-194313216", "" + f_I + sf_l);
+        test("9400000012", "" + f_I + s_strU1);
+        test("94000000C(87)", "" + f_I + sf_o);
+        test("9400000091", "" + f_I + s_strU2);
+        test("9400000021", "" + f_I + f_strU1);
+        test("9400000018", "" + f_I + f_strU2);
+        test("94000000null", "" + f_I + f_iAN);
+        test("94000000null", "" + f_I + s_oN);
+        test("94000000\u045180", "" + f_I + s_strU);
+        test("94000000C", "" + f_I + sf_c);
+        test("9400000075", "" + f_I + sf_str);
+        test("94000000-43", "" + f_I + s_bM);
+        test("9400000080", "" + f_I + sf_b);
+        test("94000000null", "" + f_I + s_IN);
+        test("94000000-52.0", "" + f_I + s_fM);
+        test("9400000075000000", "" + f_I + sf_i);
+        test("9400000044", "" + f_I + f_b);
+        test("94000000-1705032704", "" + f_I + sf_lM);
+        test("94000000null", "" + f_I + f_oAN);
+        test("9400000083.0", "" + f_I + f_d);
+        test("94000000I", "" + f_I + f_c);
+        test("9400000094.0", "" + f_I + f_f);
+        test("9400000012.0", "" + f_I + sf_d);
+        test("94000000-99.0", "" + f_I + f_dM);
+        test("9400000017.0", "" + f_I + sf_f);
+        test("94000000-84.0", "" + f_I + sf_dM);
+        test("9400000058000000", "" + f_I + f_i);
+        test("94000000-55000000", "" + f_I + f_iM);
+        test("940000001460392448", "" + f_I + f_l);
+        test("94000000C(70)", "" + f_I + f_o);
+        test("94000000\u04511", "" + f_I + sf_strU);
+        test("940000008000", "" + f_I + f_s);
+        test("9400000018", "" + f_I + s_str);
+        test("94000000-1000000", "" + f_I + s_iM);
+        test("940000001000000", "" + f_I + sf_I);
+        test("94000000null", "" + f_I + f_oNtS);
+        test("94000000false", "" + f_I + f_bl);
+        test("94000000null", "" + f_I + sf_iAN);
+        test("94000000-2000000", "" + f_I + sf_iM);
+        test("94000000-820130816", "" + f_I + f_lM);
+        test("94000000null", "" + f_I + sf_oAN);
+        test("9400000025000000", "" + f_I + s_I);
+        test("null-96.0", "" + f_IN + s_dM);
+        test("nullnull", "" + f_IN + s_oNtS);
+        test("null\u045176", "" + f_IN + f_strU);
+        test("null92", "" + f_IN + sf_strU2);
+        test("null51", "" + f_IN + sf_strU1);
+        test("nullnull", "" + f_IN + s_iAN);
+        test("null-54", "" + f_IN + f_bM);
+        test("null-87.0", "" + f_IN + f_fM);
+        test("nullnull", "" + f_IN + s_oAN);
+        test("null19", "" + f_IN + f_str);
+        test("null-41", "" + f_IN + sf_bM);
+        test("nullnull", "" + f_IN + sf_IN);
+        test("nullT", "" + f_IN + s_c);
+        test("null-42.0", "" + f_IN + sf_fM);
+        test("null25", "" + f_IN + s_b);
+        test("nullnull", "" + f_IN + f_oN);
+        test("null-1410065408", "" + f_IN + s_lM);
+        test("null8.0", "" + f_IN + s_d);
+        test("null55.0", "" + f_IN + s_f);
+        test("null97000000", "" + f_IN + s_i);
+        test("null-9900", "" + f_IN + f_sM);
+        test("null935228928", "" + f_IN + s_l);
+        test("null-8400", "" + f_IN + sf_sM);
+        test("nullC(82)", "" + f_IN + s_o);
+        test("nullnull", "" + f_IN + sf_oNtS);
+        test("nulltrue", "" + f_IN + s_bl);
+        test("null3900", "" + f_IN + s_s);
+        test("nullnull", "" + f_IN + sf_oN);
+        test("null94000000", "" + f_IN + f_I);
+        test("nullnull", "" + f_IN + f_IN);
+        test("nulltrue", "" + f_IN + sf_bl);
+        test("null5500", "" + f_IN + sf_s);
+        test("null-2900", "" + f_IN + s_sM);
+        test("null-194313216", "" + f_IN + sf_l);
+        test("null12", "" + f_IN + s_strU1);
+        test("nullC(87)", "" + f_IN + sf_o);
+        test("null91", "" + f_IN + s_strU2);
+        test("null21", "" + f_IN + f_strU1);
+        test("null18", "" + f_IN + f_strU2);
+        test("nullnull", "" + f_IN + f_iAN);
+        test("nullnull", "" + f_IN + s_oN);
+        test("null\u045180", "" + f_IN + s_strU);
+        test("nullC", "" + f_IN + sf_c);
+        test("null75", "" + f_IN + sf_str);
+        test("null-43", "" + f_IN + s_bM);
+        test("null80", "" + f_IN + sf_b);
+        test("nullnull", "" + f_IN + s_IN);
+        test("null-52.0", "" + f_IN + s_fM);
+        test("null75000000", "" + f_IN + sf_i);
+        test("null44", "" + f_IN + f_b);
+        test("null-1705032704", "" + f_IN + sf_lM);
+        test("nullnull", "" + f_IN + f_oAN);
+        test("null83.0", "" + f_IN + f_d);
+        test("nullI", "" + f_IN + f_c);
+        test("null94.0", "" + f_IN + f_f);
+        test("null12.0", "" + f_IN + sf_d);
+        test("null-99.0", "" + f_IN + f_dM);
+        test("null17.0", "" + f_IN + sf_f);
+        test("null-84.0", "" + f_IN + sf_dM);
+        test("null58000000", "" + f_IN + f_i);
+        test("null-55000000", "" + f_IN + f_iM);
+        test("null1460392448", "" + f_IN + f_l);
+        test("nullC(70)", "" + f_IN + f_o);
+        test("null\u04511", "" + f_IN + sf_strU);
+        test("null8000", "" + f_IN + f_s);
+        test("null18", "" + f_IN + s_str);
+        test("null-1000000", "" + f_IN + s_iM);
+        test("null1000000", "" + f_IN + sf_I);
+        test("nullnull", "" + f_IN + f_oNtS);
+        test("nullfalse", "" + f_IN + f_bl);
+        test("nullnull", "" + f_IN + sf_iAN);
+        test("null-2000000", "" + f_IN + sf_iM);
+        test("null-820130816", "" + f_IN + f_lM);
+        test("nullnull", "" + f_IN + sf_oAN);
+        test("null25000000", "" + f_IN + s_I);
+        test("true-96.0", "" + sf_bl + s_dM);
+        test("truenull", "" + sf_bl + s_oNtS);
+        test("true\u045176", "" + sf_bl + f_strU);
+        test("true92", "" + sf_bl + sf_strU2);
+        test("true51", "" + sf_bl + sf_strU1);
+        test("truenull", "" + sf_bl + s_iAN);
+        test("true-54", "" + sf_bl + f_bM);
+        test("true-87.0", "" + sf_bl + f_fM);
+        test("truenull", "" + sf_bl + s_oAN);
+        test("true19", "" + sf_bl + f_str);
+        test("true-41", "" + sf_bl + sf_bM);
+        test("truenull", "" + sf_bl + sf_IN);
+        test("trueT", "" + sf_bl + s_c);
+        test("true-42.0", "" + sf_bl + sf_fM);
+        test("true25", "" + sf_bl + s_b);
+        test("truenull", "" + sf_bl + f_oN);
+        test("true-1410065408", "" + sf_bl + s_lM);
+        test("true8.0", "" + sf_bl + s_d);
+        test("true55.0", "" + sf_bl + s_f);
+        test("true97000000", "" + sf_bl + s_i);
+        test("true-9900", "" + sf_bl + f_sM);
+        test("true935228928", "" + sf_bl + s_l);
+        test("true-8400", "" + sf_bl + sf_sM);
+        test("trueC(82)", "" + sf_bl + s_o);
+        test("truenull", "" + sf_bl + sf_oNtS);
+        test("truetrue", "" + sf_bl + s_bl);
+        test("true3900", "" + sf_bl + s_s);
+        test("truenull", "" + sf_bl + sf_oN);
+        test("true94000000", "" + sf_bl + f_I);
+        test("truenull", "" + sf_bl + f_IN);
+        test("truetrue", "" + sf_bl + sf_bl);
+        test("true5500", "" + sf_bl + sf_s);
+        test("true-2900", "" + sf_bl + s_sM);
+        test("true-194313216", "" + sf_bl + sf_l);
+        test("true12", "" + sf_bl + s_strU1);
+        test("trueC(87)", "" + sf_bl + sf_o);
+        test("true91", "" + sf_bl + s_strU2);
+        test("true21", "" + sf_bl + f_strU1);
+        test("true18", "" + sf_bl + f_strU2);
+        test("truenull", "" + sf_bl + f_iAN);
+        test("truenull", "" + sf_bl + s_oN);
+        test("true\u045180", "" + sf_bl + s_strU);
+        test("trueC", "" + sf_bl + sf_c);
+        test("true75", "" + sf_bl + sf_str);
+        test("true-43", "" + sf_bl + s_bM);
+        test("true80", "" + sf_bl + sf_b);
+        test("truenull", "" + sf_bl + s_IN);
+        test("true-52.0", "" + sf_bl + s_fM);
+        test("true75000000", "" + sf_bl + sf_i);
+        test("true44", "" + sf_bl + f_b);
+        test("true-1705032704", "" + sf_bl + sf_lM);
+        test("truenull", "" + sf_bl + f_oAN);
+        test("true83.0", "" + sf_bl + f_d);
+        test("trueI", "" + sf_bl + f_c);
+        test("true94.0", "" + sf_bl + f_f);
+        test("true12.0", "" + sf_bl + sf_d);
+        test("true-99.0", "" + sf_bl + f_dM);
+        test("true17.0", "" + sf_bl + sf_f);
+        test("true-84.0", "" + sf_bl + sf_dM);
+        test("true58000000", "" + sf_bl + f_i);
+        test("true-55000000", "" + sf_bl + f_iM);
+        test("true1460392448", "" + sf_bl + f_l);
+        test("trueC(70)", "" + sf_bl + f_o);
+        test("true\u04511", "" + sf_bl + sf_strU);
+        test("true8000", "" + sf_bl + f_s);
+        test("true18", "" + sf_bl + s_str);
+        test("true-1000000", "" + sf_bl + s_iM);
+        test("true1000000", "" + sf_bl + sf_I);
+        test("truenull", "" + sf_bl + f_oNtS);
+        test("truefalse", "" + sf_bl + f_bl);
+        test("truenull", "" + sf_bl + sf_iAN);
+        test("true-2000000", "" + sf_bl + sf_iM);
+        test("true-820130816", "" + sf_bl + f_lM);
+        test("truenull", "" + sf_bl + sf_oAN);
+        test("true25000000", "" + sf_bl + s_I);
+        test("5500-96.0", "" + sf_s + s_dM);
+        test("5500null", "" + sf_s + s_oNtS);
+        test("5500\u045176", "" + sf_s + f_strU);
+        test("550092", "" + sf_s + sf_strU2);
+        test("550051", "" + sf_s + sf_strU1);
+        test("5500null", "" + sf_s + s_iAN);
+        test("5500-54", "" + sf_s + f_bM);
+        test("5500-87.0", "" + sf_s + f_fM);
+        test("5500null", "" + sf_s + s_oAN);
+        test("550019", "" + sf_s + f_str);
+        test("5500-41", "" + sf_s + sf_bM);
+        test("5500null", "" + sf_s + sf_IN);
+        test("5500T", "" + sf_s + s_c);
+        test("5500-42.0", "" + sf_s + sf_fM);
+        test("550025", "" + sf_s + s_b);
+        test("5500null", "" + sf_s + f_oN);
+        test("5500-1410065408", "" + sf_s + s_lM);
+        test("55008.0", "" + sf_s + s_d);
+        test("550055.0", "" + sf_s + s_f);
+        test("550097000000", "" + sf_s + s_i);
+        test("5500-9900", "" + sf_s + f_sM);
+        test("5500935228928", "" + sf_s + s_l);
+        test("5500-8400", "" + sf_s + sf_sM);
+        test("5500C(82)", "" + sf_s + s_o);
+        test("5500null", "" + sf_s + sf_oNtS);
+        test("5500true", "" + sf_s + s_bl);
+        test("55003900", "" + sf_s + s_s);
+        test("5500null", "" + sf_s + sf_oN);
+        test("550094000000", "" + sf_s + f_I);
+        test("5500null", "" + sf_s + f_IN);
+        test("5500true", "" + sf_s + sf_bl);
+        test("55005500", "" + sf_s + sf_s);
+        test("5500-2900", "" + sf_s + s_sM);
+        test("5500-194313216", "" + sf_s + sf_l);
+        test("550012", "" + sf_s + s_strU1);
+        test("5500C(87)", "" + sf_s + sf_o);
+        test("550091", "" + sf_s + s_strU2);
+        test("550021", "" + sf_s + f_strU1);
+        test("550018", "" + sf_s + f_strU2);
+        test("5500null", "" + sf_s + f_iAN);
+        test("5500null", "" + sf_s + s_oN);
+        test("5500\u045180", "" + sf_s + s_strU);
+        test("5500C", "" + sf_s + sf_c);
+        test("550075", "" + sf_s + sf_str);
+        test("5500-43", "" + sf_s + s_bM);
+        test("550080", "" + sf_s + sf_b);
+        test("5500null", "" + sf_s + s_IN);
+        test("5500-52.0", "" + sf_s + s_fM);
+        test("550075000000", "" + sf_s + sf_i);
+        test("550044", "" + sf_s + f_b);
+        test("5500-1705032704", "" + sf_s + sf_lM);
+        test("5500null", "" + sf_s + f_oAN);
+        test("550083.0", "" + sf_s + f_d);
+        test("5500I", "" + sf_s + f_c);
+        test("550094.0", "" + sf_s + f_f);
+        test("550012.0", "" + sf_s + sf_d);
+        test("5500-99.0", "" + sf_s + f_dM);
+        test("550017.0", "" + sf_s + sf_f);
+        test("5500-84.0", "" + sf_s + sf_dM);
+        test("550058000000", "" + sf_s + f_i);
+        test("5500-55000000", "" + sf_s + f_iM);
+        test("55001460392448", "" + sf_s + f_l);
+        test("5500C(70)", "" + sf_s + f_o);
+        test("5500\u04511", "" + sf_s + sf_strU);
+        test("55008000", "" + sf_s + f_s);
+        test("550018", "" + sf_s + s_str);
+        test("5500-1000000", "" + sf_s + s_iM);
+        test("55001000000", "" + sf_s + sf_I);
+        test("5500null", "" + sf_s + f_oNtS);
+        test("5500false", "" + sf_s + f_bl);
+        test("5500null", "" + sf_s + sf_iAN);
+        test("5500-2000000", "" + sf_s + sf_iM);
+        test("5500-820130816", "" + sf_s + f_lM);
+        test("5500null", "" + sf_s + sf_oAN);
+        test("550025000000", "" + sf_s + s_I);
+        test("-2900-96.0", "" + s_sM + s_dM);
+        test("-2900null", "" + s_sM + s_oNtS);
+        test("-2900\u045176", "" + s_sM + f_strU);
+        test("-290092", "" + s_sM + sf_strU2);
+        test("-290051", "" + s_sM + sf_strU1);
+        test("-2900null", "" + s_sM + s_iAN);
+        test("-2900-54", "" + s_sM + f_bM);
+        test("-2900-87.0", "" + s_sM + f_fM);
+        test("-2900null", "" + s_sM + s_oAN);
+        test("-290019", "" + s_sM + f_str);
+        test("-2900-41", "" + s_sM + sf_bM);
+        test("-2900null", "" + s_sM + sf_IN);
+        test("-2900T", "" + s_sM + s_c);
+        test("-2900-42.0", "" + s_sM + sf_fM);
+        test("-290025", "" + s_sM + s_b);
+        test("-2900null", "" + s_sM + f_oN);
+        test("-2900-1410065408", "" + s_sM + s_lM);
+        test("-29008.0", "" + s_sM + s_d);
+        test("-290055.0", "" + s_sM + s_f);
+        test("-290097000000", "" + s_sM + s_i);
+        test("-2900-9900", "" + s_sM + f_sM);
+        test("-2900935228928", "" + s_sM + s_l);
+        test("-2900-8400", "" + s_sM + sf_sM);
+        test("-2900C(82)", "" + s_sM + s_o);
+        test("-2900null", "" + s_sM + sf_oNtS);
+        test("-2900true", "" + s_sM + s_bl);
+        test("-29003900", "" + s_sM + s_s);
+        test("-2900null", "" + s_sM + sf_oN);
+        test("-290094000000", "" + s_sM + f_I);
+        test("-2900null", "" + s_sM + f_IN);
+        test("-2900true", "" + s_sM + sf_bl);
+        test("-29005500", "" + s_sM + sf_s);
+        test("-2900-2900", "" + s_sM + s_sM);
+        test("-2900-194313216", "" + s_sM + sf_l);
+        test("-290012", "" + s_sM + s_strU1);
+        test("-2900C(87)", "" + s_sM + sf_o);
+        test("-290091", "" + s_sM + s_strU2);
+        test("-290021", "" + s_sM + f_strU1);
+        test("-290018", "" + s_sM + f_strU2);
+        test("-2900null", "" + s_sM + f_iAN);
+        test("-2900null", "" + s_sM + s_oN);
+        test("-2900\u045180", "" + s_sM + s_strU);
+        test("-2900C", "" + s_sM + sf_c);
+        test("-290075", "" + s_sM + sf_str);
+        test("-2900-43", "" + s_sM + s_bM);
+        test("-290080", "" + s_sM + sf_b);
+        test("-2900null", "" + s_sM + s_IN);
+        test("-2900-52.0", "" + s_sM + s_fM);
+        test("-290075000000", "" + s_sM + sf_i);
+        test("-290044", "" + s_sM + f_b);
+        test("-2900-1705032704", "" + s_sM + sf_lM);
+        test("-2900null", "" + s_sM + f_oAN);
+        test("-290083.0", "" + s_sM + f_d);
+        test("-2900I", "" + s_sM + f_c);
+        test("-290094.0", "" + s_sM + f_f);
+        test("-290012.0", "" + s_sM + sf_d);
+        test("-2900-99.0", "" + s_sM + f_dM);
+        test("-290017.0", "" + s_sM + sf_f);
+        test("-2900-84.0", "" + s_sM + sf_dM);
+        test("-290058000000", "" + s_sM + f_i);
+        test("-2900-55000000", "" + s_sM + f_iM);
+        test("-29001460392448", "" + s_sM + f_l);
+        test("-2900C(70)", "" + s_sM + f_o);
+        test("-2900\u04511", "" + s_sM + sf_strU);
+        test("-29008000", "" + s_sM + f_s);
+        test("-290018", "" + s_sM + s_str);
+        test("-2900-1000000", "" + s_sM + s_iM);
+        test("-29001000000", "" + s_sM + sf_I);
+        test("-2900null", "" + s_sM + f_oNtS);
+        test("-2900false", "" + s_sM + f_bl);
+        test("-2900null", "" + s_sM + sf_iAN);
+        test("-2900-2000000", "" + s_sM + sf_iM);
+        test("-2900-820130816", "" + s_sM + f_lM);
+        test("-2900null", "" + s_sM + sf_oAN);
+        test("-290025000000", "" + s_sM + s_I);
+        test("-194313216-96.0", "" + sf_l + s_dM);
+        test("-194313216null", "" + sf_l + s_oNtS);
+        test("-194313216\u045176", "" + sf_l + f_strU);
+        test("-19431321692", "" + sf_l + sf_strU2);
+        test("-19431321651", "" + sf_l + sf_strU1);
+        test("-194313216null", "" + sf_l + s_iAN);
+        test("-194313216-54", "" + sf_l + f_bM);
+        test("-194313216-87.0", "" + sf_l + f_fM);
+        test("-194313216null", "" + sf_l + s_oAN);
+        test("-19431321619", "" + sf_l + f_str);
+        test("-194313216-41", "" + sf_l + sf_bM);
+        test("-194313216null", "" + sf_l + sf_IN);
+        test("-194313216T", "" + sf_l + s_c);
+        test("-194313216-42.0", "" + sf_l + sf_fM);
+        test("-19431321625", "" + sf_l + s_b);
+        test("-194313216null", "" + sf_l + f_oN);
+        test("-194313216-1410065408", "" + sf_l + s_lM);
+        test("-1943132168.0", "" + sf_l + s_d);
+        test("-19431321655.0", "" + sf_l + s_f);
+        test("-19431321697000000", "" + sf_l + s_i);
+        test("-194313216-9900", "" + sf_l + f_sM);
+        test("-194313216935228928", "" + sf_l + s_l);
+        test("-194313216-8400", "" + sf_l + sf_sM);
+        test("-194313216C(82)", "" + sf_l + s_o);
+        test("-194313216null", "" + sf_l + sf_oNtS);
+        test("-194313216true", "" + sf_l + s_bl);
+        test("-1943132163900", "" + sf_l + s_s);
+        test("-194313216null", "" + sf_l + sf_oN);
+        test("-19431321694000000", "" + sf_l + f_I);
+        test("-194313216null", "" + sf_l + f_IN);
+        test("-194313216true", "" + sf_l + sf_bl);
+        test("-1943132165500", "" + sf_l + sf_s);
+        test("-194313216-2900", "" + sf_l + s_sM);
+        test("-194313216-194313216", "" + sf_l + sf_l);
+        test("-19431321612", "" + sf_l + s_strU1);
+        test("-194313216C(87)", "" + sf_l + sf_o);
+        test("-19431321691", "" + sf_l + s_strU2);
+        test("-19431321621", "" + sf_l + f_strU1);
+        test("-19431321618", "" + sf_l + f_strU2);
+        test("-194313216null", "" + sf_l + f_iAN);
+        test("-194313216null", "" + sf_l + s_oN);
+        test("-194313216\u045180", "" + sf_l + s_strU);
+        test("-194313216C", "" + sf_l + sf_c);
+        test("-19431321675", "" + sf_l + sf_str);
+        test("-194313216-43", "" + sf_l + s_bM);
+        test("-19431321680", "" + sf_l + sf_b);
+        test("-194313216null", "" + sf_l + s_IN);
+        test("-194313216-52.0", "" + sf_l + s_fM);
+        test("-19431321675000000", "" + sf_l + sf_i);
+        test("-19431321644", "" + sf_l + f_b);
+        test("-194313216-1705032704", "" + sf_l + sf_lM);
+        test("-194313216null", "" + sf_l + f_oAN);
+        test("-19431321683.0", "" + sf_l + f_d);
+        test("-194313216I", "" + sf_l + f_c);
+        test("-19431321694.0", "" + sf_l + f_f);
+        test("-19431321612.0", "" + sf_l + sf_d);
+        test("-194313216-99.0", "" + sf_l + f_dM);
+        test("-19431321617.0", "" + sf_l + sf_f);
+        test("-194313216-84.0", "" + sf_l + sf_dM);
+        test("-19431321658000000", "" + sf_l + f_i);
+        test("-194313216-55000000", "" + sf_l + f_iM);
+        test("-1943132161460392448", "" + sf_l + f_l);
+        test("-194313216C(70)", "" + sf_l + f_o);
+        test("-194313216\u04511", "" + sf_l + sf_strU);
+        test("-1943132168000", "" + sf_l + f_s);
+        test("-19431321618", "" + sf_l + s_str);
+        test("-194313216-1000000", "" + sf_l + s_iM);
+        test("-1943132161000000", "" + sf_l + sf_I);
+        test("-194313216null", "" + sf_l + f_oNtS);
+        test("-194313216false", "" + sf_l + f_bl);
+        test("-194313216null", "" + sf_l + sf_iAN);
+        test("-194313216-2000000", "" + sf_l + sf_iM);
+        test("-194313216-820130816", "" + sf_l + f_lM);
+        test("-194313216null", "" + sf_l + sf_oAN);
+        test("-19431321625000000", "" + sf_l + s_I);
+        test("12-96.0", "" + s_strU1 + s_dM);
+        test("12null", "" + s_strU1 + s_oNtS);
+        test("12\u045176", "" + s_strU1 + f_strU);
+        test("1292", "" + s_strU1 + sf_strU2);
+        test("1251", "" + s_strU1 + sf_strU1);
+        test("12null", "" + s_strU1 + s_iAN);
+        test("12-54", "" + s_strU1 + f_bM);
+        test("12-87.0", "" + s_strU1 + f_fM);
+        test("12null", "" + s_strU1 + s_oAN);
+        test("1219", "" + s_strU1 + f_str);
+        test("12-41", "" + s_strU1 + sf_bM);
+        test("12null", "" + s_strU1 + sf_IN);
+        test("12T", "" + s_strU1 + s_c);
+        test("12-42.0", "" + s_strU1 + sf_fM);
+        test("1225", "" + s_strU1 + s_b);
+        test("12null", "" + s_strU1 + f_oN);
+        test("12-1410065408", "" + s_strU1 + s_lM);
+        test("128.0", "" + s_strU1 + s_d);
+        test("1255.0", "" + s_strU1 + s_f);
+        test("1297000000", "" + s_strU1 + s_i);
+        test("12-9900", "" + s_strU1 + f_sM);
+        test("12935228928", "" + s_strU1 + s_l);
+        test("12-8400", "" + s_strU1 + sf_sM);
+        test("12C(82)", "" + s_strU1 + s_o);
+        test("12null", "" + s_strU1 + sf_oNtS);
+        test("12true", "" + s_strU1 + s_bl);
+        test("123900", "" + s_strU1 + s_s);
+        test("12null", "" + s_strU1 + sf_oN);
+        test("1294000000", "" + s_strU1 + f_I);
+        test("12null", "" + s_strU1 + f_IN);
+        test("12true", "" + s_strU1 + sf_bl);
+        test("125500", "" + s_strU1 + sf_s);
+        test("12-2900", "" + s_strU1 + s_sM);
+        test("12-194313216", "" + s_strU1 + sf_l);
+        test("1212", "" + s_strU1 + s_strU1);
+        test("12C(87)", "" + s_strU1 + sf_o);
+        test("1291", "" + s_strU1 + s_strU2);
+        test("1221", "" + s_strU1 + f_strU1);
+        test("1218", "" + s_strU1 + f_strU2);
+        test("12null", "" + s_strU1 + f_iAN);
+        test("12null", "" + s_strU1 + s_oN);
+        test("12\u045180", "" + s_strU1 + s_strU);
+        test("12C", "" + s_strU1 + sf_c);
+        test("1275", "" + s_strU1 + sf_str);
+        test("12-43", "" + s_strU1 + s_bM);
+        test("1280", "" + s_strU1 + sf_b);
+        test("12null", "" + s_strU1 + s_IN);
+        test("12-52.0", "" + s_strU1 + s_fM);
+        test("1275000000", "" + s_strU1 + sf_i);
+        test("1244", "" + s_strU1 + f_b);
+        test("12-1705032704", "" + s_strU1 + sf_lM);
+        test("12null", "" + s_strU1 + f_oAN);
+        test("1283.0", "" + s_strU1 + f_d);
+        test("12I", "" + s_strU1 + f_c);
+        test("1294.0", "" + s_strU1 + f_f);
+        test("1212.0", "" + s_strU1 + sf_d);
+        test("12-99.0", "" + s_strU1 + f_dM);
+        test("1217.0", "" + s_strU1 + sf_f);
+        test("12-84.0", "" + s_strU1 + sf_dM);
+        test("1258000000", "" + s_strU1 + f_i);
+        test("12-55000000", "" + s_strU1 + f_iM);
+        test("121460392448", "" + s_strU1 + f_l);
+        test("12C(70)", "" + s_strU1 + f_o);
+        test("12\u04511", "" + s_strU1 + sf_strU);
+        test("128000", "" + s_strU1 + f_s);
+        test("1218", "" + s_strU1 + s_str);
+        test("12-1000000", "" + s_strU1 + s_iM);
+        test("121000000", "" + s_strU1 + sf_I);
+        test("12null", "" + s_strU1 + f_oNtS);
+        test("12false", "" + s_strU1 + f_bl);
+        test("12null", "" + s_strU1 + sf_iAN);
+        test("12-2000000", "" + s_strU1 + sf_iM);
+        test("12-820130816", "" + s_strU1 + f_lM);
+        test("12null", "" + s_strU1 + sf_oAN);
+        test("1225000000", "" + s_strU1 + s_I);
+        test("C(87)-96.0", "" + sf_o + s_dM);
+        test("C(87)null", "" + sf_o + s_oNtS);
+        test("C(87)\u045176", "" + sf_o + f_strU);
+        test("C(87)92", "" + sf_o + sf_strU2);
+        test("C(87)51", "" + sf_o + sf_strU1);
+        test("C(87)null", "" + sf_o + s_iAN);
+        test("C(87)-54", "" + sf_o + f_bM);
+        test("C(87)-87.0", "" + sf_o + f_fM);
+        test("C(87)null", "" + sf_o + s_oAN);
+        test("C(87)19", "" + sf_o + f_str);
+        test("C(87)-41", "" + sf_o + sf_bM);
+        test("C(87)null", "" + sf_o + sf_IN);
+        test("C(87)T", "" + sf_o + s_c);
+        test("C(87)-42.0", "" + sf_o + sf_fM);
+        test("C(87)25", "" + sf_o + s_b);
+        test("C(87)null", "" + sf_o + f_oN);
+        test("C(87)-1410065408", "" + sf_o + s_lM);
+        test("C(87)8.0", "" + sf_o + s_d);
+        test("C(87)55.0", "" + sf_o + s_f);
+        test("C(87)97000000", "" + sf_o + s_i);
+        test("C(87)-9900", "" + sf_o + f_sM);
+        test("C(87)935228928", "" + sf_o + s_l);
+        test("C(87)-8400", "" + sf_o + sf_sM);
+        test("C(87)C(82)", "" + sf_o + s_o);
+        test("C(87)null", "" + sf_o + sf_oNtS);
+        test("C(87)true", "" + sf_o + s_bl);
+        test("C(87)3900", "" + sf_o + s_s);
+        test("C(87)null", "" + sf_o + sf_oN);
+        test("C(87)94000000", "" + sf_o + f_I);
+        test("C(87)null", "" + sf_o + f_IN);
+        test("C(87)true", "" + sf_o + sf_bl);
+        test("C(87)5500", "" + sf_o + sf_s);
+        test("C(87)-2900", "" + sf_o + s_sM);
+        test("C(87)-194313216", "" + sf_o + sf_l);
+        test("C(87)12", "" + sf_o + s_strU1);
+        test("C(87)C(87)", "" + sf_o + sf_o);
+        test("C(87)91", "" + sf_o + s_strU2);
+        test("C(87)21", "" + sf_o + f_strU1);
+        test("C(87)18", "" + sf_o + f_strU2);
+        test("C(87)null", "" + sf_o + f_iAN);
+        test("C(87)null", "" + sf_o + s_oN);
+        test("C(87)\u045180", "" + sf_o + s_strU);
+        test("C(87)C", "" + sf_o + sf_c);
+        test("C(87)75", "" + sf_o + sf_str);
+        test("C(87)-43", "" + sf_o + s_bM);
+        test("C(87)80", "" + sf_o + sf_b);
+        test("C(87)null", "" + sf_o + s_IN);
+        test("C(87)-52.0", "" + sf_o + s_fM);
+        test("C(87)75000000", "" + sf_o + sf_i);
+        test("C(87)44", "" + sf_o + f_b);
+        test("C(87)-1705032704", "" + sf_o + sf_lM);
+        test("C(87)null", "" + sf_o + f_oAN);
+        test("C(87)83.0", "" + sf_o + f_d);
+        test("C(87)I", "" + sf_o + f_c);
+        test("C(87)94.0", "" + sf_o + f_f);
+        test("C(87)12.0", "" + sf_o + sf_d);
+        test("C(87)-99.0", "" + sf_o + f_dM);
+        test("C(87)17.0", "" + sf_o + sf_f);
+        test("C(87)-84.0", "" + sf_o + sf_dM);
+        test("C(87)58000000", "" + sf_o + f_i);
+        test("C(87)-55000000", "" + sf_o + f_iM);
+        test("C(87)1460392448", "" + sf_o + f_l);
+        test("C(87)C(70)", "" + sf_o + f_o);
+        test("C(87)\u04511", "" + sf_o + sf_strU);
+        test("C(87)8000", "" + sf_o + f_s);
+        test("C(87)18", "" + sf_o + s_str);
+        test("C(87)-1000000", "" + sf_o + s_iM);
+        test("C(87)1000000", "" + sf_o + sf_I);
+        test("C(87)null", "" + sf_o + f_oNtS);
+        test("C(87)false", "" + sf_o + f_bl);
+        test("C(87)null", "" + sf_o + sf_iAN);
+        test("C(87)-2000000", "" + sf_o + sf_iM);
+        test("C(87)-820130816", "" + sf_o + f_lM);
+        test("C(87)null", "" + sf_o + sf_oAN);
+        test("C(87)25000000", "" + sf_o + s_I);
+        test("91-96.0", "" + s_strU2 + s_dM);
+        test("91null", "" + s_strU2 + s_oNtS);
+        test("91\u045176", "" + s_strU2 + f_strU);
+        test("9192", "" + s_strU2 + sf_strU2);
+        test("9151", "" + s_strU2 + sf_strU1);
+        test("91null", "" + s_strU2 + s_iAN);
+        test("91-54", "" + s_strU2 + f_bM);
+        test("91-87.0", "" + s_strU2 + f_fM);
+        test("91null", "" + s_strU2 + s_oAN);
+        test("9119", "" + s_strU2 + f_str);
+        test("91-41", "" + s_strU2 + sf_bM);
+        test("91null", "" + s_strU2 + sf_IN);
+        test("91T", "" + s_strU2 + s_c);
+        test("91-42.0", "" + s_strU2 + sf_fM);
+        test("9125", "" + s_strU2 + s_b);
+        test("91null", "" + s_strU2 + f_oN);
+        test("91-1410065408", "" + s_strU2 + s_lM);
+        test("918.0", "" + s_strU2 + s_d);
+        test("9155.0", "" + s_strU2 + s_f);
+        test("9197000000", "" + s_strU2 + s_i);
+        test("91-9900", "" + s_strU2 + f_sM);
+        test("91935228928", "" + s_strU2 + s_l);
+        test("91-8400", "" + s_strU2 + sf_sM);
+        test("91C(82)", "" + s_strU2 + s_o);
+        test("91null", "" + s_strU2 + sf_oNtS);
+        test("91true", "" + s_strU2 + s_bl);
+        test("913900", "" + s_strU2 + s_s);
+        test("91null", "" + s_strU2 + sf_oN);
+        test("9194000000", "" + s_strU2 + f_I);
+        test("91null", "" + s_strU2 + f_IN);
+        test("91true", "" + s_strU2 + sf_bl);
+        test("915500", "" + s_strU2 + sf_s);
+        test("91-2900", "" + s_strU2 + s_sM);
+        test("91-194313216", "" + s_strU2 + sf_l);
+        test("9112", "" + s_strU2 + s_strU1);
+        test("91C(87)", "" + s_strU2 + sf_o);
+        test("9191", "" + s_strU2 + s_strU2);
+        test("9121", "" + s_strU2 + f_strU1);
+        test("9118", "" + s_strU2 + f_strU2);
+        test("91null", "" + s_strU2 + f_iAN);
+        test("91null", "" + s_strU2 + s_oN);
+        test("91\u045180", "" + s_strU2 + s_strU);
+        test("91C", "" + s_strU2 + sf_c);
+        test("9175", "" + s_strU2 + sf_str);
+        test("91-43", "" + s_strU2 + s_bM);
+        test("9180", "" + s_strU2 + sf_b);
+        test("91null", "" + s_strU2 + s_IN);
+        test("91-52.0", "" + s_strU2 + s_fM);
+        test("9175000000", "" + s_strU2 + sf_i);
+        test("9144", "" + s_strU2 + f_b);
+        test("91-1705032704", "" + s_strU2 + sf_lM);
+        test("91null", "" + s_strU2 + f_oAN);
+        test("9183.0", "" + s_strU2 + f_d);
+        test("91I", "" + s_strU2 + f_c);
+        test("9194.0", "" + s_strU2 + f_f);
+        test("9112.0", "" + s_strU2 + sf_d);
+        test("91-99.0", "" + s_strU2 + f_dM);
+        test("9117.0", "" + s_strU2 + sf_f);
+        test("91-84.0", "" + s_strU2 + sf_dM);
+        test("9158000000", "" + s_strU2 + f_i);
+        test("91-55000000", "" + s_strU2 + f_iM);
+        test("911460392448", "" + s_strU2 + f_l);
+        test("91C(70)", "" + s_strU2 + f_o);
+        test("91\u04511", "" + s_strU2 + sf_strU);
+        test("918000", "" + s_strU2 + f_s);
+        test("9118", "" + s_strU2 + s_str);
+        test("91-1000000", "" + s_strU2 + s_iM);
+        test("911000000", "" + s_strU2 + sf_I);
+        test("91null", "" + s_strU2 + f_oNtS);
+        test("91false", "" + s_strU2 + f_bl);
+        test("91null", "" + s_strU2 + sf_iAN);
+        test("91-2000000", "" + s_strU2 + sf_iM);
+        test("91-820130816", "" + s_strU2 + f_lM);
+        test("91null", "" + s_strU2 + sf_oAN);
+        test("9125000000", "" + s_strU2 + s_I);
+        test("21-96.0", "" + f_strU1 + s_dM);
+        test("21null", "" + f_strU1 + s_oNtS);
+        test("21\u045176", "" + f_strU1 + f_strU);
+        test("2192", "" + f_strU1 + sf_strU2);
+        test("2151", "" + f_strU1 + sf_strU1);
+        test("21null", "" + f_strU1 + s_iAN);
+        test("21-54", "" + f_strU1 + f_bM);
+        test("21-87.0", "" + f_strU1 + f_fM);
+        test("21null", "" + f_strU1 + s_oAN);
+        test("2119", "" + f_strU1 + f_str);
+        test("21-41", "" + f_strU1 + sf_bM);
+        test("21null", "" + f_strU1 + sf_IN);
+        test("21T", "" + f_strU1 + s_c);
+        test("21-42.0", "" + f_strU1 + sf_fM);
+        test("2125", "" + f_strU1 + s_b);
+        test("21null", "" + f_strU1 + f_oN);
+        test("21-1410065408", "" + f_strU1 + s_lM);
+        test("218.0", "" + f_strU1 + s_d);
+        test("2155.0", "" + f_strU1 + s_f);
+        test("2197000000", "" + f_strU1 + s_i);
+        test("21-9900", "" + f_strU1 + f_sM);
+        test("21935228928", "" + f_strU1 + s_l);
+        test("21-8400", "" + f_strU1 + sf_sM);
+        test("21C(82)", "" + f_strU1 + s_o);
+        test("21null", "" + f_strU1 + sf_oNtS);
+        test("21true", "" + f_strU1 + s_bl);
+        test("213900", "" + f_strU1 + s_s);
+        test("21null", "" + f_strU1 + sf_oN);
+        test("2194000000", "" + f_strU1 + f_I);
+        test("21null", "" + f_strU1 + f_IN);
+        test("21true", "" + f_strU1 + sf_bl);
+        test("215500", "" + f_strU1 + sf_s);
+        test("21-2900", "" + f_strU1 + s_sM);
+        test("21-194313216", "" + f_strU1 + sf_l);
+        test("2112", "" + f_strU1 + s_strU1);
+        test("21C(87)", "" + f_strU1 + sf_o);
+        test("2191", "" + f_strU1 + s_strU2);
+        test("2121", "" + f_strU1 + f_strU1);
+        test("2118", "" + f_strU1 + f_strU2);
+        test("21null", "" + f_strU1 + f_iAN);
+        test("21null", "" + f_strU1 + s_oN);
+        test("21\u045180", "" + f_strU1 + s_strU);
+        test("21C", "" + f_strU1 + sf_c);
+        test("2175", "" + f_strU1 + sf_str);
+        test("21-43", "" + f_strU1 + s_bM);
+        test("2180", "" + f_strU1 + sf_b);
+        test("21null", "" + f_strU1 + s_IN);
+        test("21-52.0", "" + f_strU1 + s_fM);
+        test("2175000000", "" + f_strU1 + sf_i);
+        test("2144", "" + f_strU1 + f_b);
+        test("21-1705032704", "" + f_strU1 + sf_lM);
+        test("21null", "" + f_strU1 + f_oAN);
+        test("2183.0", "" + f_strU1 + f_d);
+        test("21I", "" + f_strU1 + f_c);
+        test("2194.0", "" + f_strU1 + f_f);
+        test("2112.0", "" + f_strU1 + sf_d);
+        test("21-99.0", "" + f_strU1 + f_dM);
+        test("2117.0", "" + f_strU1 + sf_f);
+        test("21-84.0", "" + f_strU1 + sf_dM);
+        test("2158000000", "" + f_strU1 + f_i);
+        test("21-55000000", "" + f_strU1 + f_iM);
+        test("211460392448", "" + f_strU1 + f_l);
+        test("21C(70)", "" + f_strU1 + f_o);
+        test("21\u04511", "" + f_strU1 + sf_strU);
+        test("218000", "" + f_strU1 + f_s);
+        test("2118", "" + f_strU1 + s_str);
+        test("21-1000000", "" + f_strU1 + s_iM);
+        test("211000000", "" + f_strU1 + sf_I);
+        test("21null", "" + f_strU1 + f_oNtS);
+        test("21false", "" + f_strU1 + f_bl);
+        test("21null", "" + f_strU1 + sf_iAN);
+        test("21-2000000", "" + f_strU1 + sf_iM);
+        test("21-820130816", "" + f_strU1 + f_lM);
+        test("21null", "" + f_strU1 + sf_oAN);
+        test("2125000000", "" + f_strU1 + s_I);
+        test("18-96.0", "" + f_strU2 + s_dM);
+        test("18null", "" + f_strU2 + s_oNtS);
+        test("18\u045176", "" + f_strU2 + f_strU);
+        test("1892", "" + f_strU2 + sf_strU2);
+        test("1851", "" + f_strU2 + sf_strU1);
+        test("18null", "" + f_strU2 + s_iAN);
+        test("18-54", "" + f_strU2 + f_bM);
+        test("18-87.0", "" + f_strU2 + f_fM);
+        test("18null", "" + f_strU2 + s_oAN);
+        test("1819", "" + f_strU2 + f_str);
+        test("18-41", "" + f_strU2 + sf_bM);
+        test("18null", "" + f_strU2 + sf_IN);
+        test("18T", "" + f_strU2 + s_c);
+        test("18-42.0", "" + f_strU2 + sf_fM);
+        test("1825", "" + f_strU2 + s_b);
+        test("18null", "" + f_strU2 + f_oN);
+        test("18-1410065408", "" + f_strU2 + s_lM);
+        test("188.0", "" + f_strU2 + s_d);
+        test("1855.0", "" + f_strU2 + s_f);
+        test("1897000000", "" + f_strU2 + s_i);
+        test("18-9900", "" + f_strU2 + f_sM);
+        test("18935228928", "" + f_strU2 + s_l);
+        test("18-8400", "" + f_strU2 + sf_sM);
+        test("18C(82)", "" + f_strU2 + s_o);
+        test("18null", "" + f_strU2 + sf_oNtS);
+        test("18true", "" + f_strU2 + s_bl);
+        test("183900", "" + f_strU2 + s_s);
+        test("18null", "" + f_strU2 + sf_oN);
+        test("1894000000", "" + f_strU2 + f_I);
+        test("18null", "" + f_strU2 + f_IN);
+        test("18true", "" + f_strU2 + sf_bl);
+        test("185500", "" + f_strU2 + sf_s);
+        test("18-2900", "" + f_strU2 + s_sM);
+        test("18-194313216", "" + f_strU2 + sf_l);
+        test("1812", "" + f_strU2 + s_strU1);
+        test("18C(87)", "" + f_strU2 + sf_o);
+        test("1891", "" + f_strU2 + s_strU2);
+        test("1821", "" + f_strU2 + f_strU1);
+        test("1818", "" + f_strU2 + f_strU2);
+        test("18null", "" + f_strU2 + f_iAN);
+        test("18null", "" + f_strU2 + s_oN);
+        test("18\u045180", "" + f_strU2 + s_strU);
+        test("18C", "" + f_strU2 + sf_c);
+        test("1875", "" + f_strU2 + sf_str);
+        test("18-43", "" + f_strU2 + s_bM);
+        test("1880", "" + f_strU2 + sf_b);
+        test("18null", "" + f_strU2 + s_IN);
+        test("18-52.0", "" + f_strU2 + s_fM);
+        test("1875000000", "" + f_strU2 + sf_i);
+        test("1844", "" + f_strU2 + f_b);
+        test("18-1705032704", "" + f_strU2 + sf_lM);
+        test("18null", "" + f_strU2 + f_oAN);
+        test("1883.0", "" + f_strU2 + f_d);
+        test("18I", "" + f_strU2 + f_c);
+        test("1894.0", "" + f_strU2 + f_f);
+        test("1812.0", "" + f_strU2 + sf_d);
+        test("18-99.0", "" + f_strU2 + f_dM);
+        test("1817.0", "" + f_strU2 + sf_f);
+        test("18-84.0", "" + f_strU2 + sf_dM);
+        test("1858000000", "" + f_strU2 + f_i);
+        test("18-55000000", "" + f_strU2 + f_iM);
+        test("181460392448", "" + f_strU2 + f_l);
+        test("18C(70)", "" + f_strU2 + f_o);
+        test("18\u04511", "" + f_strU2 + sf_strU);
+        test("188000", "" + f_strU2 + f_s);
+        test("1818", "" + f_strU2 + s_str);
+        test("18-1000000", "" + f_strU2 + s_iM);
+        test("181000000", "" + f_strU2 + sf_I);
+        test("18null", "" + f_strU2 + f_oNtS);
+        test("18false", "" + f_strU2 + f_bl);
+        test("18null", "" + f_strU2 + sf_iAN);
+        test("18-2000000", "" + f_strU2 + sf_iM);
+        test("18-820130816", "" + f_strU2 + f_lM);
+        test("18null", "" + f_strU2 + sf_oAN);
+        test("1825000000", "" + f_strU2 + s_I);
+    }
+
+    public void run3() {
+        test("null-96.0", "" + f_iAN + s_dM);
+        test("nullnull", "" + f_iAN + s_oNtS);
+        test("null\u045176", "" + f_iAN + f_strU);
+        test("null92", "" + f_iAN + sf_strU2);
+        test("null51", "" + f_iAN + sf_strU1);
+        test("nullnull", "" + f_iAN + s_iAN);
+        test("null-54", "" + f_iAN + f_bM);
+        test("null-87.0", "" + f_iAN + f_fM);
+        test("nullnull", "" + f_iAN + s_oAN);
+        test("null19", "" + f_iAN + f_str);
+        test("null-41", "" + f_iAN + sf_bM);
+        test("nullnull", "" + f_iAN + sf_IN);
+        test("nullT", "" + f_iAN + s_c);
+        test("null-42.0", "" + f_iAN + sf_fM);
+        test("null25", "" + f_iAN + s_b);
+        test("nullnull", "" + f_iAN + f_oN);
+        test("null-1410065408", "" + f_iAN + s_lM);
+        test("null8.0", "" + f_iAN + s_d);
+        test("null55.0", "" + f_iAN + s_f);
+        test("null97000000", "" + f_iAN + s_i);
+        test("null-9900", "" + f_iAN + f_sM);
+        test("null935228928", "" + f_iAN + s_l);
+        test("null-8400", "" + f_iAN + sf_sM);
+        test("nullC(82)", "" + f_iAN + s_o);
+        test("nullnull", "" + f_iAN + sf_oNtS);
+        test("nulltrue", "" + f_iAN + s_bl);
+        test("null3900", "" + f_iAN + s_s);
+        test("nullnull", "" + f_iAN + sf_oN);
+        test("null94000000", "" + f_iAN + f_I);
+        test("nullnull", "" + f_iAN + f_IN);
+        test("nulltrue", "" + f_iAN + sf_bl);
+        test("null5500", "" + f_iAN + sf_s);
+        test("null-2900", "" + f_iAN + s_sM);
+        test("null-194313216", "" + f_iAN + sf_l);
+        test("null12", "" + f_iAN + s_strU1);
+        test("nullC(87)", "" + f_iAN + sf_o);
+        test("null91", "" + f_iAN + s_strU2);
+        test("null21", "" + f_iAN + f_strU1);
+        test("null18", "" + f_iAN + f_strU2);
+        test("nullnull", "" + f_iAN + f_iAN);
+        test("nullnull", "" + f_iAN + s_oN);
+        test("null\u045180", "" + f_iAN + s_strU);
+        test("nullC", "" + f_iAN + sf_c);
+        test("null75", "" + f_iAN + sf_str);
+        test("null-43", "" + f_iAN + s_bM);
+        test("null80", "" + f_iAN + sf_b);
+        test("nullnull", "" + f_iAN + s_IN);
+        test("null-52.0", "" + f_iAN + s_fM);
+        test("null75000000", "" + f_iAN + sf_i);
+        test("null44", "" + f_iAN + f_b);
+        test("null-1705032704", "" + f_iAN + sf_lM);
+        test("nullnull", "" + f_iAN + f_oAN);
+        test("null83.0", "" + f_iAN + f_d);
+        test("nullI", "" + f_iAN + f_c);
+        test("null94.0", "" + f_iAN + f_f);
+        test("null12.0", "" + f_iAN + sf_d);
+        test("null-99.0", "" + f_iAN + f_dM);
+        test("null17.0", "" + f_iAN + sf_f);
+        test("null-84.0", "" + f_iAN + sf_dM);
+        test("null58000000", "" + f_iAN + f_i);
+        test("null-55000000", "" + f_iAN + f_iM);
+        test("null1460392448", "" + f_iAN + f_l);
+        test("nullC(70)", "" + f_iAN + f_o);
+        test("null\u04511", "" + f_iAN + sf_strU);
+        test("null8000", "" + f_iAN + f_s);
+        test("null18", "" + f_iAN + s_str);
+        test("null-1000000", "" + f_iAN + s_iM);
+        test("null1000000", "" + f_iAN + sf_I);
+        test("nullnull", "" + f_iAN + f_oNtS);
+        test("nullfalse", "" + f_iAN + f_bl);
+        test("nullnull", "" + f_iAN + sf_iAN);
+        test("null-2000000", "" + f_iAN + sf_iM);
+        test("null-820130816", "" + f_iAN + f_lM);
+        test("nullnull", "" + f_iAN + sf_oAN);
+        test("null25000000", "" + f_iAN + s_I);
+        test("null-96.0", "" + s_oN + s_dM);
+        test("nullnull", "" + s_oN + s_oNtS);
+        test("null\u045176", "" + s_oN + f_strU);
+        test("null92", "" + s_oN + sf_strU2);
+        test("null51", "" + s_oN + sf_strU1);
+        test("nullnull", "" + s_oN + s_iAN);
+        test("null-54", "" + s_oN + f_bM);
+        test("null-87.0", "" + s_oN + f_fM);
+        test("nullnull", "" + s_oN + s_oAN);
+        test("null19", "" + s_oN + f_str);
+        test("null-41", "" + s_oN + sf_bM);
+        test("nullnull", "" + s_oN + sf_IN);
+        test("nullT", "" + s_oN + s_c);
+        test("null-42.0", "" + s_oN + sf_fM);
+        test("null25", "" + s_oN + s_b);
+        test("nullnull", "" + s_oN + f_oN);
+        test("null-1410065408", "" + s_oN + s_lM);
+        test("null8.0", "" + s_oN + s_d);
+        test("null55.0", "" + s_oN + s_f);
+        test("null97000000", "" + s_oN + s_i);
+        test("null-9900", "" + s_oN + f_sM);
+        test("null935228928", "" + s_oN + s_l);
+        test("null-8400", "" + s_oN + sf_sM);
+        test("nullC(82)", "" + s_oN + s_o);
+        test("nullnull", "" + s_oN + sf_oNtS);
+        test("nulltrue", "" + s_oN + s_bl);
+        test("null3900", "" + s_oN + s_s);
+        test("nullnull", "" + s_oN + sf_oN);
+        test("null94000000", "" + s_oN + f_I);
+        test("nullnull", "" + s_oN + f_IN);
+        test("nulltrue", "" + s_oN + sf_bl);
+        test("null5500", "" + s_oN + sf_s);
+        test("null-2900", "" + s_oN + s_sM);
+        test("null-194313216", "" + s_oN + sf_l);
+        test("null12", "" + s_oN + s_strU1);
+        test("nullC(87)", "" + s_oN + sf_o);
+        test("null91", "" + s_oN + s_strU2);
+        test("null21", "" + s_oN + f_strU1);
+        test("null18", "" + s_oN + f_strU2);
+        test("nullnull", "" + s_oN + f_iAN);
+        test("nullnull", "" + s_oN + s_oN);
+        test("null\u045180", "" + s_oN + s_strU);
+        test("nullC", "" + s_oN + sf_c);
+        test("null75", "" + s_oN + sf_str);
+        test("null-43", "" + s_oN + s_bM);
+        test("null80", "" + s_oN + sf_b);
+        test("nullnull", "" + s_oN + s_IN);
+        test("null-52.0", "" + s_oN + s_fM);
+        test("null75000000", "" + s_oN + sf_i);
+        test("null44", "" + s_oN + f_b);
+        test("null-1705032704", "" + s_oN + sf_lM);
+        test("nullnull", "" + s_oN + f_oAN);
+        test("null83.0", "" + s_oN + f_d);
+        test("nullI", "" + s_oN + f_c);
+        test("null94.0", "" + s_oN + f_f);
+        test("null12.0", "" + s_oN + sf_d);
+        test("null-99.0", "" + s_oN + f_dM);
+        test("null17.0", "" + s_oN + sf_f);
+        test("null-84.0", "" + s_oN + sf_dM);
+        test("null58000000", "" + s_oN + f_i);
+        test("null-55000000", "" + s_oN + f_iM);
+        test("null1460392448", "" + s_oN + f_l);
+        test("nullC(70)", "" + s_oN + f_o);
+        test("null\u04511", "" + s_oN + sf_strU);
+        test("null8000", "" + s_oN + f_s);
+        test("null18", "" + s_oN + s_str);
+        test("null-1000000", "" + s_oN + s_iM);
+        test("null1000000", "" + s_oN + sf_I);
+        test("nullnull", "" + s_oN + f_oNtS);
+        test("nullfalse", "" + s_oN + f_bl);
+        test("nullnull", "" + s_oN + sf_iAN);
+        test("null-2000000", "" + s_oN + sf_iM);
+        test("null-820130816", "" + s_oN + f_lM);
+        test("nullnull", "" + s_oN + sf_oAN);
+        test("null25000000", "" + s_oN + s_I);
+        test("\u045180-96.0", "" + s_strU + s_dM);
+        test("\u045180null", "" + s_strU + s_oNtS);
+        test("\u045180\u045176", "" + s_strU + f_strU);
+        test("\u04518092", "" + s_strU + sf_strU2);
+        test("\u04518051", "" + s_strU + sf_strU1);
+        test("\u045180null", "" + s_strU + s_iAN);
+        test("\u045180-54", "" + s_strU + f_bM);
+        test("\u045180-87.0", "" + s_strU + f_fM);
+        test("\u045180null", "" + s_strU + s_oAN);
+        test("\u04518019", "" + s_strU + f_str);
+        test("\u045180-41", "" + s_strU + sf_bM);
+        test("\u045180null", "" + s_strU + sf_IN);
+        test("\u045180T", "" + s_strU + s_c);
+        test("\u045180-42.0", "" + s_strU + sf_fM);
+        test("\u04518025", "" + s_strU + s_b);
+        test("\u045180null", "" + s_strU + f_oN);
+        test("\u045180-1410065408", "" + s_strU + s_lM);
+        test("\u0451808.0", "" + s_strU + s_d);
+        test("\u04518055.0", "" + s_strU + s_f);
+        test("\u04518097000000", "" + s_strU + s_i);
+        test("\u045180-9900", "" + s_strU + f_sM);
+        test("\u045180935228928", "" + s_strU + s_l);
+        test("\u045180-8400", "" + s_strU + sf_sM);
+        test("\u045180C(82)", "" + s_strU + s_o);
+        test("\u045180null", "" + s_strU + sf_oNtS);
+        test("\u045180true", "" + s_strU + s_bl);
+        test("\u0451803900", "" + s_strU + s_s);
+        test("\u045180null", "" + s_strU + sf_oN);
+        test("\u04518094000000", "" + s_strU + f_I);
+        test("\u045180null", "" + s_strU + f_IN);
+        test("\u045180true", "" + s_strU + sf_bl);
+        test("\u0451805500", "" + s_strU + sf_s);
+        test("\u045180-2900", "" + s_strU + s_sM);
+        test("\u045180-194313216", "" + s_strU + sf_l);
+        test("\u04518012", "" + s_strU + s_strU1);
+        test("\u045180C(87)", "" + s_strU + sf_o);
+        test("\u04518091", "" + s_strU + s_strU2);
+        test("\u04518021", "" + s_strU + f_strU1);
+        test("\u04518018", "" + s_strU + f_strU2);
+        test("\u045180null", "" + s_strU + f_iAN);
+        test("\u045180null", "" + s_strU + s_oN);
+        test("\u045180\u045180", "" + s_strU + s_strU);
+        test("\u045180C", "" + s_strU + sf_c);
+        test("\u04518075", "" + s_strU + sf_str);
+        test("\u045180-43", "" + s_strU + s_bM);
+        test("\u04518080", "" + s_strU + sf_b);
+        test("\u045180null", "" + s_strU + s_IN);
+        test("\u045180-52.0", "" + s_strU + s_fM);
+        test("\u04518075000000", "" + s_strU + sf_i);
+        test("\u04518044", "" + s_strU + f_b);
+        test("\u045180-1705032704", "" + s_strU + sf_lM);
+        test("\u045180null", "" + s_strU + f_oAN);
+        test("\u04518083.0", "" + s_strU + f_d);
+        test("\u045180I", "" + s_strU + f_c);
+        test("\u04518094.0", "" + s_strU + f_f);
+        test("\u04518012.0", "" + s_strU + sf_d);
+        test("\u045180-99.0", "" + s_strU + f_dM);
+        test("\u04518017.0", "" + s_strU + sf_f);
+        test("\u045180-84.0", "" + s_strU + sf_dM);
+        test("\u04518058000000", "" + s_strU + f_i);
+        test("\u045180-55000000", "" + s_strU + f_iM);
+        test("\u0451801460392448", "" + s_strU + f_l);
+        test("\u045180C(70)", "" + s_strU + f_o);
+        test("\u045180\u04511", "" + s_strU + sf_strU);
+        test("\u0451808000", "" + s_strU + f_s);
+        test("\u04518018", "" + s_strU + s_str);
+        test("\u045180-1000000", "" + s_strU + s_iM);
+        test("\u0451801000000", "" + s_strU + sf_I);
+        test("\u045180null", "" + s_strU + f_oNtS);
+        test("\u045180false", "" + s_strU + f_bl);
+        test("\u045180null", "" + s_strU + sf_iAN);
+        test("\u045180-2000000", "" + s_strU + sf_iM);
+        test("\u045180-820130816", "" + s_strU + f_lM);
+        test("\u045180null", "" + s_strU + sf_oAN);
+        test("\u04518025000000", "" + s_strU + s_I);
+        test("C-96.0", "" + sf_c + s_dM);
+        test("Cnull", "" + sf_c + s_oNtS);
+        test("C\u045176", "" + sf_c + f_strU);
+        test("C92", "" + sf_c + sf_strU2);
+        test("C51", "" + sf_c + sf_strU1);
+        test("Cnull", "" + sf_c + s_iAN);
+        test("C-54", "" + sf_c + f_bM);
+        test("C-87.0", "" + sf_c + f_fM);
+        test("Cnull", "" + sf_c + s_oAN);
+        test("C19", "" + sf_c + f_str);
+        test("C-41", "" + sf_c + sf_bM);
+        test("Cnull", "" + sf_c + sf_IN);
+        test("CT", "" + sf_c + s_c);
+        test("C-42.0", "" + sf_c + sf_fM);
+        test("C25", "" + sf_c + s_b);
+        test("Cnull", "" + sf_c + f_oN);
+        test("C-1410065408", "" + sf_c + s_lM);
+        test("C8.0", "" + sf_c + s_d);
+        test("C55.0", "" + sf_c + s_f);
+        test("C97000000", "" + sf_c + s_i);
+        test("C-9900", "" + sf_c + f_sM);
+        test("C935228928", "" + sf_c + s_l);
+        test("C-8400", "" + sf_c + sf_sM);
+        test("CC(82)", "" + sf_c + s_o);
+        test("Cnull", "" + sf_c + sf_oNtS);
+        test("Ctrue", "" + sf_c + s_bl);
+        test("C3900", "" + sf_c + s_s);
+        test("Cnull", "" + sf_c + sf_oN);
+        test("C94000000", "" + sf_c + f_I);
+        test("Cnull", "" + sf_c + f_IN);
+        test("Ctrue", "" + sf_c + sf_bl);
+        test("C5500", "" + sf_c + sf_s);
+        test("C-2900", "" + sf_c + s_sM);
+        test("C-194313216", "" + sf_c + sf_l);
+        test("C12", "" + sf_c + s_strU1);
+        test("CC(87)", "" + sf_c + sf_o);
+        test("C91", "" + sf_c + s_strU2);
+        test("C21", "" + sf_c + f_strU1);
+        test("C18", "" + sf_c + f_strU2);
+        test("Cnull", "" + sf_c + f_iAN);
+        test("Cnull", "" + sf_c + s_oN);
+        test("C\u045180", "" + sf_c + s_strU);
+        test("CC", "" + sf_c + sf_c);
+        test("C75", "" + sf_c + sf_str);
+        test("C-43", "" + sf_c + s_bM);
+        test("C80", "" + sf_c + sf_b);
+        test("Cnull", "" + sf_c + s_IN);
+        test("C-52.0", "" + sf_c + s_fM);
+        test("C75000000", "" + sf_c + sf_i);
+        test("C44", "" + sf_c + f_b);
+        test("C-1705032704", "" + sf_c + sf_lM);
+        test("Cnull", "" + sf_c + f_oAN);
+        test("C83.0", "" + sf_c + f_d);
+        test("CI", "" + sf_c + f_c);
+        test("C94.0", "" + sf_c + f_f);
+        test("C12.0", "" + sf_c + sf_d);
+        test("C-99.0", "" + sf_c + f_dM);
+        test("C17.0", "" + sf_c + sf_f);
+        test("C-84.0", "" + sf_c + sf_dM);
+        test("C58000000", "" + sf_c + f_i);
+        test("C-55000000", "" + sf_c + f_iM);
+        test("C1460392448", "" + sf_c + f_l);
+        test("CC(70)", "" + sf_c + f_o);
+        test("C\u04511", "" + sf_c + sf_strU);
+        test("C8000", "" + sf_c + f_s);
+        test("C18", "" + sf_c + s_str);
+        test("C-1000000", "" + sf_c + s_iM);
+        test("C1000000", "" + sf_c + sf_I);
+        test("Cnull", "" + sf_c + f_oNtS);
+        test("Cfalse", "" + sf_c + f_bl);
+        test("Cnull", "" + sf_c + sf_iAN);
+        test("C-2000000", "" + sf_c + sf_iM);
+        test("C-820130816", "" + sf_c + f_lM);
+        test("Cnull", "" + sf_c + sf_oAN);
+        test("C25000000", "" + sf_c + s_I);
+        test("75-96.0", "" + sf_str + s_dM);
+        test("75null", "" + sf_str + s_oNtS);
+        test("75\u045176", "" + sf_str + f_strU);
+        test("7592", "" + sf_str + sf_strU2);
+        test("7551", "" + sf_str + sf_strU1);
+        test("75null", "" + sf_str + s_iAN);
+        test("75-54", "" + sf_str + f_bM);
+        test("75-87.0", "" + sf_str + f_fM);
+        test("75null", "" + sf_str + s_oAN);
+        test("7519", "" + sf_str + f_str);
+        test("75-41", "" + sf_str + sf_bM);
+        test("75null", "" + sf_str + sf_IN);
+        test("75T", "" + sf_str + s_c);
+        test("75-42.0", "" + sf_str + sf_fM);
+        test("7525", "" + sf_str + s_b);
+        test("75null", "" + sf_str + f_oN);
+        test("75-1410065408", "" + sf_str + s_lM);
+        test("758.0", "" + sf_str + s_d);
+        test("7555.0", "" + sf_str + s_f);
+        test("7597000000", "" + sf_str + s_i);
+        test("75-9900", "" + sf_str + f_sM);
+        test("75935228928", "" + sf_str + s_l);
+        test("75-8400", "" + sf_str + sf_sM);
+        test("75C(82)", "" + sf_str + s_o);
+        test("75null", "" + sf_str + sf_oNtS);
+        test("75true", "" + sf_str + s_bl);
+        test("753900", "" + sf_str + s_s);
+        test("75null", "" + sf_str + sf_oN);
+        test("7594000000", "" + sf_str + f_I);
+        test("75null", "" + sf_str + f_IN);
+        test("75true", "" + sf_str + sf_bl);
+        test("755500", "" + sf_str + sf_s);
+        test("75-2900", "" + sf_str + s_sM);
+        test("75-194313216", "" + sf_str + sf_l);
+        test("7512", "" + sf_str + s_strU1);
+        test("75C(87)", "" + sf_str + sf_o);
+        test("7591", "" + sf_str + s_strU2);
+        test("7521", "" + sf_str + f_strU1);
+        test("7518", "" + sf_str + f_strU2);
+        test("75null", "" + sf_str + f_iAN);
+        test("75null", "" + sf_str + s_oN);
+        test("75\u045180", "" + sf_str + s_strU);
+        test("75C", "" + sf_str + sf_c);
+        test("7575", "" + sf_str + sf_str);
+        test("75-43", "" + sf_str + s_bM);
+        test("7580", "" + sf_str + sf_b);
+        test("75null", "" + sf_str + s_IN);
+        test("75-52.0", "" + sf_str + s_fM);
+        test("7575000000", "" + sf_str + sf_i);
+        test("7544", "" + sf_str + f_b);
+        test("75-1705032704", "" + sf_str + sf_lM);
+        test("75null", "" + sf_str + f_oAN);
+        test("7583.0", "" + sf_str + f_d);
+        test("75I", "" + sf_str + f_c);
+        test("7594.0", "" + sf_str + f_f);
+        test("7512.0", "" + sf_str + sf_d);
+        test("75-99.0", "" + sf_str + f_dM);
+        test("7517.0", "" + sf_str + sf_f);
+        test("75-84.0", "" + sf_str + sf_dM);
+        test("7558000000", "" + sf_str + f_i);
+        test("75-55000000", "" + sf_str + f_iM);
+        test("751460392448", "" + sf_str + f_l);
+        test("75C(70)", "" + sf_str + f_o);
+        test("75\u04511", "" + sf_str + sf_strU);
+        test("758000", "" + sf_str + f_s);
+        test("7518", "" + sf_str + s_str);
+        test("75-1000000", "" + sf_str + s_iM);
+        test("751000000", "" + sf_str + sf_I);
+        test("75null", "" + sf_str + f_oNtS);
+        test("75false", "" + sf_str + f_bl);
+        test("75null", "" + sf_str + sf_iAN);
+        test("75-2000000", "" + sf_str + sf_iM);
+        test("75-820130816", "" + sf_str + f_lM);
+        test("75null", "" + sf_str + sf_oAN);
+        test("7525000000", "" + sf_str + s_I);
+        test("-43-96.0", "" + s_bM + s_dM);
+        test("-43null", "" + s_bM + s_oNtS);
+        test("-43\u045176", "" + s_bM + f_strU);
+        test("-4392", "" + s_bM + sf_strU2);
+        test("-4351", "" + s_bM + sf_strU1);
+        test("-43null", "" + s_bM + s_iAN);
+        test("-43-54", "" + s_bM + f_bM);
+        test("-43-87.0", "" + s_bM + f_fM);
+        test("-43null", "" + s_bM + s_oAN);
+        test("-4319", "" + s_bM + f_str);
+        test("-43-41", "" + s_bM + sf_bM);
+        test("-43null", "" + s_bM + sf_IN);
+        test("-43T", "" + s_bM + s_c);
+        test("-43-42.0", "" + s_bM + sf_fM);
+        test("-4325", "" + s_bM + s_b);
+        test("-43null", "" + s_bM + f_oN);
+        test("-43-1410065408", "" + s_bM + s_lM);
+        test("-438.0", "" + s_bM + s_d);
+        test("-4355.0", "" + s_bM + s_f);
+        test("-4397000000", "" + s_bM + s_i);
+        test("-43-9900", "" + s_bM + f_sM);
+        test("-43935228928", "" + s_bM + s_l);
+        test("-43-8400", "" + s_bM + sf_sM);
+        test("-43C(82)", "" + s_bM + s_o);
+        test("-43null", "" + s_bM + sf_oNtS);
+        test("-43true", "" + s_bM + s_bl);
+        test("-433900", "" + s_bM + s_s);
+        test("-43null", "" + s_bM + sf_oN);
+        test("-4394000000", "" + s_bM + f_I);
+        test("-43null", "" + s_bM + f_IN);
+        test("-43true", "" + s_bM + sf_bl);
+        test("-435500", "" + s_bM + sf_s);
+        test("-43-2900", "" + s_bM + s_sM);
+        test("-43-194313216", "" + s_bM + sf_l);
+        test("-4312", "" + s_bM + s_strU1);
+        test("-43C(87)", "" + s_bM + sf_o);
+        test("-4391", "" + s_bM + s_strU2);
+        test("-4321", "" + s_bM + f_strU1);
+        test("-4318", "" + s_bM + f_strU2);
+        test("-43null", "" + s_bM + f_iAN);
+        test("-43null", "" + s_bM + s_oN);
+        test("-43\u045180", "" + s_bM + s_strU);
+        test("-43C", "" + s_bM + sf_c);
+        test("-4375", "" + s_bM + sf_str);
+        test("-43-43", "" + s_bM + s_bM);
+        test("-4380", "" + s_bM + sf_b);
+        test("-43null", "" + s_bM + s_IN);
+        test("-43-52.0", "" + s_bM + s_fM);
+        test("-4375000000", "" + s_bM + sf_i);
+        test("-4344", "" + s_bM + f_b);
+        test("-43-1705032704", "" + s_bM + sf_lM);
+        test("-43null", "" + s_bM + f_oAN);
+        test("-4383.0", "" + s_bM + f_d);
+        test("-43I", "" + s_bM + f_c);
+        test("-4394.0", "" + s_bM + f_f);
+        test("-4312.0", "" + s_bM + sf_d);
+        test("-43-99.0", "" + s_bM + f_dM);
+        test("-4317.0", "" + s_bM + sf_f);
+        test("-43-84.0", "" + s_bM + sf_dM);
+        test("-4358000000", "" + s_bM + f_i);
+        test("-43-55000000", "" + s_bM + f_iM);
+        test("-431460392448", "" + s_bM + f_l);
+        test("-43C(70)", "" + s_bM + f_o);
+        test("-43\u04511", "" + s_bM + sf_strU);
+        test("-438000", "" + s_bM + f_s);
+        test("-4318", "" + s_bM + s_str);
+        test("-43-1000000", "" + s_bM + s_iM);
+        test("-431000000", "" + s_bM + sf_I);
+        test("-43null", "" + s_bM + f_oNtS);
+        test("-43false", "" + s_bM + f_bl);
+        test("-43null", "" + s_bM + sf_iAN);
+        test("-43-2000000", "" + s_bM + sf_iM);
+        test("-43-820130816", "" + s_bM + f_lM);
+        test("-43null", "" + s_bM + sf_oAN);
+        test("-4325000000", "" + s_bM + s_I);
+        test("80-96.0", "" + sf_b + s_dM);
+        test("80null", "" + sf_b + s_oNtS);
+        test("80\u045176", "" + sf_b + f_strU);
+        test("8092", "" + sf_b + sf_strU2);
+        test("8051", "" + sf_b + sf_strU1);
+        test("80null", "" + sf_b + s_iAN);
+        test("80-54", "" + sf_b + f_bM);
+        test("80-87.0", "" + sf_b + f_fM);
+        test("80null", "" + sf_b + s_oAN);
+        test("8019", "" + sf_b + f_str);
+        test("80-41", "" + sf_b + sf_bM);
+        test("80null", "" + sf_b + sf_IN);
+        test("80T", "" + sf_b + s_c);
+        test("80-42.0", "" + sf_b + sf_fM);
+        test("8025", "" + sf_b + s_b);
+        test("80null", "" + sf_b + f_oN);
+        test("80-1410065408", "" + sf_b + s_lM);
+        test("808.0", "" + sf_b + s_d);
+        test("8055.0", "" + sf_b + s_f);
+        test("8097000000", "" + sf_b + s_i);
+        test("80-9900", "" + sf_b + f_sM);
+        test("80935228928", "" + sf_b + s_l);
+        test("80-8400", "" + sf_b + sf_sM);
+        test("80C(82)", "" + sf_b + s_o);
+        test("80null", "" + sf_b + sf_oNtS);
+        test("80true", "" + sf_b + s_bl);
+        test("803900", "" + sf_b + s_s);
+        test("80null", "" + sf_b + sf_oN);
+        test("8094000000", "" + sf_b + f_I);
+        test("80null", "" + sf_b + f_IN);
+        test("80true", "" + sf_b + sf_bl);
+        test("805500", "" + sf_b + sf_s);
+        test("80-2900", "" + sf_b + s_sM);
+        test("80-194313216", "" + sf_b + sf_l);
+        test("8012", "" + sf_b + s_strU1);
+        test("80C(87)", "" + sf_b + sf_o);
+        test("8091", "" + sf_b + s_strU2);
+        test("8021", "" + sf_b + f_strU1);
+        test("8018", "" + sf_b + f_strU2);
+        test("80null", "" + sf_b + f_iAN);
+        test("80null", "" + sf_b + s_oN);
+        test("80\u045180", "" + sf_b + s_strU);
+        test("80C", "" + sf_b + sf_c);
+        test("8075", "" + sf_b + sf_str);
+        test("80-43", "" + sf_b + s_bM);
+        test("8080", "" + sf_b + sf_b);
+        test("80null", "" + sf_b + s_IN);
+        test("80-52.0", "" + sf_b + s_fM);
+        test("8075000000", "" + sf_b + sf_i);
+        test("8044", "" + sf_b + f_b);
+        test("80-1705032704", "" + sf_b + sf_lM);
+        test("80null", "" + sf_b + f_oAN);
+        test("8083.0", "" + sf_b + f_d);
+        test("80I", "" + sf_b + f_c);
+        test("8094.0", "" + sf_b + f_f);
+        test("8012.0", "" + sf_b + sf_d);
+        test("80-99.0", "" + sf_b + f_dM);
+        test("8017.0", "" + sf_b + sf_f);
+        test("80-84.0", "" + sf_b + sf_dM);
+        test("8058000000", "" + sf_b + f_i);
+        test("80-55000000", "" + sf_b + f_iM);
+        test("801460392448", "" + sf_b + f_l);
+        test("80C(70)", "" + sf_b + f_o);
+        test("80\u04511", "" + sf_b + sf_strU);
+        test("808000", "" + sf_b + f_s);
+        test("8018", "" + sf_b + s_str);
+        test("80-1000000", "" + sf_b + s_iM);
+        test("801000000", "" + sf_b + sf_I);
+        test("80null", "" + sf_b + f_oNtS);
+        test("80false", "" + sf_b + f_bl);
+        test("80null", "" + sf_b + sf_iAN);
+        test("80-2000000", "" + sf_b + sf_iM);
+        test("80-820130816", "" + sf_b + f_lM);
+        test("80null", "" + sf_b + sf_oAN);
+        test("8025000000", "" + sf_b + s_I);
+        test("null-96.0", "" + s_IN + s_dM);
+        test("nullnull", "" + s_IN + s_oNtS);
+        test("null\u045176", "" + s_IN + f_strU);
+        test("null92", "" + s_IN + sf_strU2);
+        test("null51", "" + s_IN + sf_strU1);
+        test("nullnull", "" + s_IN + s_iAN);
+        test("null-54", "" + s_IN + f_bM);
+        test("null-87.0", "" + s_IN + f_fM);
+        test("nullnull", "" + s_IN + s_oAN);
+        test("null19", "" + s_IN + f_str);
+        test("null-41", "" + s_IN + sf_bM);
+        test("nullnull", "" + s_IN + sf_IN);
+        test("nullT", "" + s_IN + s_c);
+        test("null-42.0", "" + s_IN + sf_fM);
+        test("null25", "" + s_IN + s_b);
+        test("nullnull", "" + s_IN + f_oN);
+        test("null-1410065408", "" + s_IN + s_lM);
+        test("null8.0", "" + s_IN + s_d);
+        test("null55.0", "" + s_IN + s_f);
+        test("null97000000", "" + s_IN + s_i);
+        test("null-9900", "" + s_IN + f_sM);
+        test("null935228928", "" + s_IN + s_l);
+        test("null-8400", "" + s_IN + sf_sM);
+        test("nullC(82)", "" + s_IN + s_o);
+        test("nullnull", "" + s_IN + sf_oNtS);
+        test("nulltrue", "" + s_IN + s_bl);
+        test("null3900", "" + s_IN + s_s);
+        test("nullnull", "" + s_IN + sf_oN);
+        test("null94000000", "" + s_IN + f_I);
+        test("nullnull", "" + s_IN + f_IN);
+        test("nulltrue", "" + s_IN + sf_bl);
+        test("null5500", "" + s_IN + sf_s);
+        test("null-2900", "" + s_IN + s_sM);
+        test("null-194313216", "" + s_IN + sf_l);
+        test("null12", "" + s_IN + s_strU1);
+        test("nullC(87)", "" + s_IN + sf_o);
+        test("null91", "" + s_IN + s_strU2);
+        test("null21", "" + s_IN + f_strU1);
+        test("null18", "" + s_IN + f_strU2);
+        test("nullnull", "" + s_IN + f_iAN);
+        test("nullnull", "" + s_IN + s_oN);
+        test("null\u045180", "" + s_IN + s_strU);
+        test("nullC", "" + s_IN + sf_c);
+        test("null75", "" + s_IN + sf_str);
+        test("null-43", "" + s_IN + s_bM);
+        test("null80", "" + s_IN + sf_b);
+        test("nullnull", "" + s_IN + s_IN);
+        test("null-52.0", "" + s_IN + s_fM);
+        test("null75000000", "" + s_IN + sf_i);
+        test("null44", "" + s_IN + f_b);
+        test("null-1705032704", "" + s_IN + sf_lM);
+        test("nullnull", "" + s_IN + f_oAN);
+        test("null83.0", "" + s_IN + f_d);
+        test("nullI", "" + s_IN + f_c);
+        test("null94.0", "" + s_IN + f_f);
+        test("null12.0", "" + s_IN + sf_d);
+        test("null-99.0", "" + s_IN + f_dM);
+        test("null17.0", "" + s_IN + sf_f);
+        test("null-84.0", "" + s_IN + sf_dM);
+        test("null58000000", "" + s_IN + f_i);
+        test("null-55000000", "" + s_IN + f_iM);
+        test("null1460392448", "" + s_IN + f_l);
+        test("nullC(70)", "" + s_IN + f_o);
+        test("null\u04511", "" + s_IN + sf_strU);
+        test("null8000", "" + s_IN + f_s);
+        test("null18", "" + s_IN + s_str);
+        test("null-1000000", "" + s_IN + s_iM);
+        test("null1000000", "" + s_IN + sf_I);
+        test("nullnull", "" + s_IN + f_oNtS);
+        test("nullfalse", "" + s_IN + f_bl);
+        test("nullnull", "" + s_IN + sf_iAN);
+        test("null-2000000", "" + s_IN + sf_iM);
+        test("null-820130816", "" + s_IN + f_lM);
+        test("nullnull", "" + s_IN + sf_oAN);
+        test("null25000000", "" + s_IN + s_I);
+        test("-52.0-96.0", "" + s_fM + s_dM);
+        test("-52.0null", "" + s_fM + s_oNtS);
+        test("-52.0\u045176", "" + s_fM + f_strU);
+        test("-52.092", "" + s_fM + sf_strU2);
+        test("-52.051", "" + s_fM + sf_strU1);
+        test("-52.0null", "" + s_fM + s_iAN);
+        test("-52.0-54", "" + s_fM + f_bM);
+        test("-52.0-87.0", "" + s_fM + f_fM);
+        test("-52.0null", "" + s_fM + s_oAN);
+        test("-52.019", "" + s_fM + f_str);
+        test("-52.0-41", "" + s_fM + sf_bM);
+        test("-52.0null", "" + s_fM + sf_IN);
+        test("-52.0T", "" + s_fM + s_c);
+        test("-52.0-42.0", "" + s_fM + sf_fM);
+        test("-52.025", "" + s_fM + s_b);
+        test("-52.0null", "" + s_fM + f_oN);
+        test("-52.0-1410065408", "" + s_fM + s_lM);
+        test("-52.08.0", "" + s_fM + s_d);
+        test("-52.055.0", "" + s_fM + s_f);
+        test("-52.097000000", "" + s_fM + s_i);
+        test("-52.0-9900", "" + s_fM + f_sM);
+        test("-52.0935228928", "" + s_fM + s_l);
+        test("-52.0-8400", "" + s_fM + sf_sM);
+        test("-52.0C(82)", "" + s_fM + s_o);
+        test("-52.0null", "" + s_fM + sf_oNtS);
+        test("-52.0true", "" + s_fM + s_bl);
+        test("-52.03900", "" + s_fM + s_s);
+        test("-52.0null", "" + s_fM + sf_oN);
+        test("-52.094000000", "" + s_fM + f_I);
+        test("-52.0null", "" + s_fM + f_IN);
+        test("-52.0true", "" + s_fM + sf_bl);
+        test("-52.05500", "" + s_fM + sf_s);
+        test("-52.0-2900", "" + s_fM + s_sM);
+        test("-52.0-194313216", "" + s_fM + sf_l);
+        test("-52.012", "" + s_fM + s_strU1);
+        test("-52.0C(87)", "" + s_fM + sf_o);
+        test("-52.091", "" + s_fM + s_strU2);
+        test("-52.021", "" + s_fM + f_strU1);
+        test("-52.018", "" + s_fM + f_strU2);
+        test("-52.0null", "" + s_fM + f_iAN);
+        test("-52.0null", "" + s_fM + s_oN);
+        test("-52.0\u045180", "" + s_fM + s_strU);
+        test("-52.0C", "" + s_fM + sf_c);
+        test("-52.075", "" + s_fM + sf_str);
+        test("-52.0-43", "" + s_fM + s_bM);
+        test("-52.080", "" + s_fM + sf_b);
+        test("-52.0null", "" + s_fM + s_IN);
+        test("-52.0-52.0", "" + s_fM + s_fM);
+        test("-52.075000000", "" + s_fM + sf_i);
+        test("-52.044", "" + s_fM + f_b);
+        test("-52.0-1705032704", "" + s_fM + sf_lM);
+        test("-52.0null", "" + s_fM + f_oAN);
+        test("-52.083.0", "" + s_fM + f_d);
+        test("-52.0I", "" + s_fM + f_c);
+        test("-52.094.0", "" + s_fM + f_f);
+        test("-52.012.0", "" + s_fM + sf_d);
+        test("-52.0-99.0", "" + s_fM + f_dM);
+        test("-52.017.0", "" + s_fM + sf_f);
+        test("-52.0-84.0", "" + s_fM + sf_dM);
+        test("-52.058000000", "" + s_fM + f_i);
+        test("-52.0-55000000", "" + s_fM + f_iM);
+        test("-52.01460392448", "" + s_fM + f_l);
+        test("-52.0C(70)", "" + s_fM + f_o);
+        test("-52.0\u04511", "" + s_fM + sf_strU);
+        test("-52.08000", "" + s_fM + f_s);
+        test("-52.018", "" + s_fM + s_str);
+        test("-52.0-1000000", "" + s_fM + s_iM);
+        test("-52.01000000", "" + s_fM + sf_I);
+        test("-52.0null", "" + s_fM + f_oNtS);
+        test("-52.0false", "" + s_fM + f_bl);
+        test("-52.0null", "" + s_fM + sf_iAN);
+        test("-52.0-2000000", "" + s_fM + sf_iM);
+        test("-52.0-820130816", "" + s_fM + f_lM);
+        test("-52.0null", "" + s_fM + sf_oAN);
+        test("-52.025000000", "" + s_fM + s_I);
+        test("75000000-96.0", "" + sf_i + s_dM);
+        test("75000000null", "" + sf_i + s_oNtS);
+        test("75000000\u045176", "" + sf_i + f_strU);
+        test("7500000092", "" + sf_i + sf_strU2);
+        test("7500000051", "" + sf_i + sf_strU1);
+        test("75000000null", "" + sf_i + s_iAN);
+        test("75000000-54", "" + sf_i + f_bM);
+        test("75000000-87.0", "" + sf_i + f_fM);
+        test("75000000null", "" + sf_i + s_oAN);
+        test("7500000019", "" + sf_i + f_str);
+        test("75000000-41", "" + sf_i + sf_bM);
+        test("75000000null", "" + sf_i + sf_IN);
+        test("75000000T", "" + sf_i + s_c);
+        test("75000000-42.0", "" + sf_i + sf_fM);
+        test("7500000025", "" + sf_i + s_b);
+        test("75000000null", "" + sf_i + f_oN);
+        test("75000000-1410065408", "" + sf_i + s_lM);
+        test("750000008.0", "" + sf_i + s_d);
+        test("7500000055.0", "" + sf_i + s_f);
+        test("7500000097000000", "" + sf_i + s_i);
+        test("75000000-9900", "" + sf_i + f_sM);
+        test("75000000935228928", "" + sf_i + s_l);
+        test("75000000-8400", "" + sf_i + sf_sM);
+        test("75000000C(82)", "" + sf_i + s_o);
+        test("75000000null", "" + sf_i + sf_oNtS);
+        test("75000000true", "" + sf_i + s_bl);
+        test("750000003900", "" + sf_i + s_s);
+        test("75000000null", "" + sf_i + sf_oN);
+        test("7500000094000000", "" + sf_i + f_I);
+        test("75000000null", "" + sf_i + f_IN);
+        test("75000000true", "" + sf_i + sf_bl);
+        test("750000005500", "" + sf_i + sf_s);
+        test("75000000-2900", "" + sf_i + s_sM);
+        test("75000000-194313216", "" + sf_i + sf_l);
+        test("7500000012", "" + sf_i + s_strU1);
+        test("75000000C(87)", "" + sf_i + sf_o);
+        test("7500000091", "" + sf_i + s_strU2);
+        test("7500000021", "" + sf_i + f_strU1);
+        test("7500000018", "" + sf_i + f_strU2);
+        test("75000000null", "" + sf_i + f_iAN);
+        test("75000000null", "" + sf_i + s_oN);
+        test("75000000\u045180", "" + sf_i + s_strU);
+        test("75000000C", "" + sf_i + sf_c);
+        test("7500000075", "" + sf_i + sf_str);
+        test("75000000-43", "" + sf_i + s_bM);
+        test("7500000080", "" + sf_i + sf_b);
+        test("75000000null", "" + sf_i + s_IN);
+        test("75000000-52.0", "" + sf_i + s_fM);
+        test("7500000075000000", "" + sf_i + sf_i);
+        test("7500000044", "" + sf_i + f_b);
+        test("75000000-1705032704", "" + sf_i + sf_lM);
+        test("75000000null", "" + sf_i + f_oAN);
+        test("7500000083.0", "" + sf_i + f_d);
+        test("75000000I", "" + sf_i + f_c);
+        test("7500000094.0", "" + sf_i + f_f);
+        test("7500000012.0", "" + sf_i + sf_d);
+        test("75000000-99.0", "" + sf_i + f_dM);
+        test("7500000017.0", "" + sf_i + sf_f);
+        test("75000000-84.0", "" + sf_i + sf_dM);
+        test("7500000058000000", "" + sf_i + f_i);
+        test("75000000-55000000", "" + sf_i + f_iM);
+        test("750000001460392448", "" + sf_i + f_l);
+        test("75000000C(70)", "" + sf_i + f_o);
+        test("75000000\u04511", "" + sf_i + sf_strU);
+        test("750000008000", "" + sf_i + f_s);
+        test("7500000018", "" + sf_i + s_str);
+        test("75000000-1000000", "" + sf_i + s_iM);
+        test("750000001000000", "" + sf_i + sf_I);
+        test("75000000null", "" + sf_i + f_oNtS);
+        test("75000000false", "" + sf_i + f_bl);
+        test("75000000null", "" + sf_i + sf_iAN);
+        test("75000000-2000000", "" + sf_i + sf_iM);
+        test("75000000-820130816", "" + sf_i + f_lM);
+        test("75000000null", "" + sf_i + sf_oAN);
+        test("7500000025000000", "" + sf_i + s_I);
+        test("44-96.0", "" + f_b + s_dM);
+        test("44null", "" + f_b + s_oNtS);
+        test("44\u045176", "" + f_b + f_strU);
+        test("4492", "" + f_b + sf_strU2);
+        test("4451", "" + f_b + sf_strU1);
+        test("44null", "" + f_b + s_iAN);
+        test("44-54", "" + f_b + f_bM);
+        test("44-87.0", "" + f_b + f_fM);
+        test("44null", "" + f_b + s_oAN);
+        test("4419", "" + f_b + f_str);
+        test("44-41", "" + f_b + sf_bM);
+        test("44null", "" + f_b + sf_IN);
+        test("44T", "" + f_b + s_c);
+        test("44-42.0", "" + f_b + sf_fM);
+        test("4425", "" + f_b + s_b);
+        test("44null", "" + f_b + f_oN);
+        test("44-1410065408", "" + f_b + s_lM);
+        test("448.0", "" + f_b + s_d);
+        test("4455.0", "" + f_b + s_f);
+        test("4497000000", "" + f_b + s_i);
+        test("44-9900", "" + f_b + f_sM);
+        test("44935228928", "" + f_b + s_l);
+        test("44-8400", "" + f_b + sf_sM);
+        test("44C(82)", "" + f_b + s_o);
+        test("44null", "" + f_b + sf_oNtS);
+        test("44true", "" + f_b + s_bl);
+        test("443900", "" + f_b + s_s);
+        test("44null", "" + f_b + sf_oN);
+        test("4494000000", "" + f_b + f_I);
+        test("44null", "" + f_b + f_IN);
+        test("44true", "" + f_b + sf_bl);
+        test("445500", "" + f_b + sf_s);
+        test("44-2900", "" + f_b + s_sM);
+        test("44-194313216", "" + f_b + sf_l);
+        test("4412", "" + f_b + s_strU1);
+        test("44C(87)", "" + f_b + sf_o);
+        test("4491", "" + f_b + s_strU2);
+        test("4421", "" + f_b + f_strU1);
+        test("4418", "" + f_b + f_strU2);
+        test("44null", "" + f_b + f_iAN);
+        test("44null", "" + f_b + s_oN);
+        test("44\u045180", "" + f_b + s_strU);
+        test("44C", "" + f_b + sf_c);
+        test("4475", "" + f_b + sf_str);
+        test("44-43", "" + f_b + s_bM);
+        test("4480", "" + f_b + sf_b);
+        test("44null", "" + f_b + s_IN);
+        test("44-52.0", "" + f_b + s_fM);
+        test("4475000000", "" + f_b + sf_i);
+        test("4444", "" + f_b + f_b);
+        test("44-1705032704", "" + f_b + sf_lM);
+        test("44null", "" + f_b + f_oAN);
+        test("4483.0", "" + f_b + f_d);
+        test("44I", "" + f_b + f_c);
+        test("4494.0", "" + f_b + f_f);
+        test("4412.0", "" + f_b + sf_d);
+        test("44-99.0", "" + f_b + f_dM);
+        test("4417.0", "" + f_b + sf_f);
+        test("44-84.0", "" + f_b + sf_dM);
+        test("4458000000", "" + f_b + f_i);
+        test("44-55000000", "" + f_b + f_iM);
+        test("441460392448", "" + f_b + f_l);
+        test("44C(70)", "" + f_b + f_o);
+        test("44\u04511", "" + f_b + sf_strU);
+        test("448000", "" + f_b + f_s);
+        test("4418", "" + f_b + s_str);
+        test("44-1000000", "" + f_b + s_iM);
+        test("441000000", "" + f_b + sf_I);
+        test("44null", "" + f_b + f_oNtS);
+        test("44false", "" + f_b + f_bl);
+        test("44null", "" + f_b + sf_iAN);
+        test("44-2000000", "" + f_b + sf_iM);
+        test("44-820130816", "" + f_b + f_lM);
+        test("44null", "" + f_b + sf_oAN);
+        test("4425000000", "" + f_b + s_I);
+        test("-1705032704-96.0", "" + sf_lM + s_dM);
+        test("-1705032704null", "" + sf_lM + s_oNtS);
+        test("-1705032704\u045176", "" + sf_lM + f_strU);
+        test("-170503270492", "" + sf_lM + sf_strU2);
+        test("-170503270451", "" + sf_lM + sf_strU1);
+        test("-1705032704null", "" + sf_lM + s_iAN);
+        test("-1705032704-54", "" + sf_lM + f_bM);
+        test("-1705032704-87.0", "" + sf_lM + f_fM);
+        test("-1705032704null", "" + sf_lM + s_oAN);
+        test("-170503270419", "" + sf_lM + f_str);
+        test("-1705032704-41", "" + sf_lM + sf_bM);
+        test("-1705032704null", "" + sf_lM + sf_IN);
+        test("-1705032704T", "" + sf_lM + s_c);
+        test("-1705032704-42.0", "" + sf_lM + sf_fM);
+        test("-170503270425", "" + sf_lM + s_b);
+        test("-1705032704null", "" + sf_lM + f_oN);
+        test("-1705032704-1410065408", "" + sf_lM + s_lM);
+        test("-17050327048.0", "" + sf_lM + s_d);
+        test("-170503270455.0", "" + sf_lM + s_f);
+        test("-170503270497000000", "" + sf_lM + s_i);
+        test("-1705032704-9900", "" + sf_lM + f_sM);
+        test("-1705032704935228928", "" + sf_lM + s_l);
+        test("-1705032704-8400", "" + sf_lM + sf_sM);
+        test("-1705032704C(82)", "" + sf_lM + s_o);
+        test("-1705032704null", "" + sf_lM + sf_oNtS);
+        test("-1705032704true", "" + sf_lM + s_bl);
+        test("-17050327043900", "" + sf_lM + s_s);
+        test("-1705032704null", "" + sf_lM + sf_oN);
+        test("-170503270494000000", "" + sf_lM + f_I);
+        test("-1705032704null", "" + sf_lM + f_IN);
+        test("-1705032704true", "" + sf_lM + sf_bl);
+        test("-17050327045500", "" + sf_lM + sf_s);
+        test("-1705032704-2900", "" + sf_lM + s_sM);
+        test("-1705032704-194313216", "" + sf_lM + sf_l);
+        test("-170503270412", "" + sf_lM + s_strU1);
+        test("-1705032704C(87)", "" + sf_lM + sf_o);
+        test("-170503270491", "" + sf_lM + s_strU2);
+        test("-170503270421", "" + sf_lM + f_strU1);
+        test("-170503270418", "" + sf_lM + f_strU2);
+        test("-1705032704null", "" + sf_lM + f_iAN);
+        test("-1705032704null", "" + sf_lM + s_oN);
+        test("-1705032704\u045180", "" + sf_lM + s_strU);
+        test("-1705032704C", "" + sf_lM + sf_c);
+        test("-170503270475", "" + sf_lM + sf_str);
+        test("-1705032704-43", "" + sf_lM + s_bM);
+        test("-170503270480", "" + sf_lM + sf_b);
+        test("-1705032704null", "" + sf_lM + s_IN);
+        test("-1705032704-52.0", "" + sf_lM + s_fM);
+        test("-170503270475000000", "" + sf_lM + sf_i);
+        test("-170503270444", "" + sf_lM + f_b);
+        test("-1705032704-1705032704", "" + sf_lM + sf_lM);
+        test("-1705032704null", "" + sf_lM + f_oAN);
+        test("-170503270483.0", "" + sf_lM + f_d);
+        test("-1705032704I", "" + sf_lM + f_c);
+        test("-170503270494.0", "" + sf_lM + f_f);
+        test("-170503270412.0", "" + sf_lM + sf_d);
+        test("-1705032704-99.0", "" + sf_lM + f_dM);
+        test("-170503270417.0", "" + sf_lM + sf_f);
+        test("-1705032704-84.0", "" + sf_lM + sf_dM);
+        test("-170503270458000000", "" + sf_lM + f_i);
+        test("-1705032704-55000000", "" + sf_lM + f_iM);
+        test("-17050327041460392448", "" + sf_lM + f_l);
+        test("-1705032704C(70)", "" + sf_lM + f_o);
+        test("-1705032704\u04511", "" + sf_lM + sf_strU);
+        test("-17050327048000", "" + sf_lM + f_s);
+        test("-170503270418", "" + sf_lM + s_str);
+        test("-1705032704-1000000", "" + sf_lM + s_iM);
+        test("-17050327041000000", "" + sf_lM + sf_I);
+        test("-1705032704null", "" + sf_lM + f_oNtS);
+        test("-1705032704false", "" + sf_lM + f_bl);
+        test("-1705032704null", "" + sf_lM + sf_iAN);
+        test("-1705032704-2000000", "" + sf_lM + sf_iM);
+        test("-1705032704-820130816", "" + sf_lM + f_lM);
+        test("-1705032704null", "" + sf_lM + sf_oAN);
+        test("-170503270425000000", "" + sf_lM + s_I);
+        test("null-96.0", "" + f_oAN + s_dM);
+        test("nullnull", "" + f_oAN + s_oNtS);
+        test("null\u045176", "" + f_oAN + f_strU);
+        test("null92", "" + f_oAN + sf_strU2);
+        test("null51", "" + f_oAN + sf_strU1);
+        test("nullnull", "" + f_oAN + s_iAN);
+        test("null-54", "" + f_oAN + f_bM);
+        test("null-87.0", "" + f_oAN + f_fM);
+        test("nullnull", "" + f_oAN + s_oAN);
+        test("null19", "" + f_oAN + f_str);
+        test("null-41", "" + f_oAN + sf_bM);
+        test("nullnull", "" + f_oAN + sf_IN);
+        test("nullT", "" + f_oAN + s_c);
+        test("null-42.0", "" + f_oAN + sf_fM);
+        test("null25", "" + f_oAN + s_b);
+        test("nullnull", "" + f_oAN + f_oN);
+        test("null-1410065408", "" + f_oAN + s_lM);
+        test("null8.0", "" + f_oAN + s_d);
+        test("null55.0", "" + f_oAN + s_f);
+        test("null97000000", "" + f_oAN + s_i);
+        test("null-9900", "" + f_oAN + f_sM);
+        test("null935228928", "" + f_oAN + s_l);
+        test("null-8400", "" + f_oAN + sf_sM);
+        test("nullC(82)", "" + f_oAN + s_o);
+        test("nullnull", "" + f_oAN + sf_oNtS);
+        test("nulltrue", "" + f_oAN + s_bl);
+        test("null3900", "" + f_oAN + s_s);
+        test("nullnull", "" + f_oAN + sf_oN);
+        test("null94000000", "" + f_oAN + f_I);
+        test("nullnull", "" + f_oAN + f_IN);
+        test("nulltrue", "" + f_oAN + sf_bl);
+        test("null5500", "" + f_oAN + sf_s);
+        test("null-2900", "" + f_oAN + s_sM);
+        test("null-194313216", "" + f_oAN + sf_l);
+        test("null12", "" + f_oAN + s_strU1);
+        test("nullC(87)", "" + f_oAN + sf_o);
+        test("null91", "" + f_oAN + s_strU2);
+        test("null21", "" + f_oAN + f_strU1);
+        test("null18", "" + f_oAN + f_strU2);
+        test("nullnull", "" + f_oAN + f_iAN);
+        test("nullnull", "" + f_oAN + s_oN);
+        test("null\u045180", "" + f_oAN + s_strU);
+        test("nullC", "" + f_oAN + sf_c);
+        test("null75", "" + f_oAN + sf_str);
+        test("null-43", "" + f_oAN + s_bM);
+        test("null80", "" + f_oAN + sf_b);
+        test("nullnull", "" + f_oAN + s_IN);
+        test("null-52.0", "" + f_oAN + s_fM);
+        test("null75000000", "" + f_oAN + sf_i);
+        test("null44", "" + f_oAN + f_b);
+        test("null-1705032704", "" + f_oAN + sf_lM);
+        test("nullnull", "" + f_oAN + f_oAN);
+        test("null83.0", "" + f_oAN + f_d);
+        test("nullI", "" + f_oAN + f_c);
+        test("null94.0", "" + f_oAN + f_f);
+        test("null12.0", "" + f_oAN + sf_d);
+        test("null-99.0", "" + f_oAN + f_dM);
+        test("null17.0", "" + f_oAN + sf_f);
+        test("null-84.0", "" + f_oAN + sf_dM);
+        test("null58000000", "" + f_oAN + f_i);
+        test("null-55000000", "" + f_oAN + f_iM);
+        test("null1460392448", "" + f_oAN + f_l);
+        test("nullC(70)", "" + f_oAN + f_o);
+        test("null\u04511", "" + f_oAN + sf_strU);
+        test("null8000", "" + f_oAN + f_s);
+        test("null18", "" + f_oAN + s_str);
+        test("null-1000000", "" + f_oAN + s_iM);
+        test("null1000000", "" + f_oAN + sf_I);
+        test("nullnull", "" + f_oAN + f_oNtS);
+        test("nullfalse", "" + f_oAN + f_bl);
+        test("nullnull", "" + f_oAN + sf_iAN);
+        test("null-2000000", "" + f_oAN + sf_iM);
+        test("null-820130816", "" + f_oAN + f_lM);
+        test("nullnull", "" + f_oAN + sf_oAN);
+        test("null25000000", "" + f_oAN + s_I);
+        test("83.0-96.0", "" + f_d + s_dM);
+        test("83.0null", "" + f_d + s_oNtS);
+        test("83.0\u045176", "" + f_d + f_strU);
+        test("83.092", "" + f_d + sf_strU2);
+        test("83.051", "" + f_d + sf_strU1);
+        test("83.0null", "" + f_d + s_iAN);
+        test("83.0-54", "" + f_d + f_bM);
+        test("83.0-87.0", "" + f_d + f_fM);
+        test("83.0null", "" + f_d + s_oAN);
+        test("83.019", "" + f_d + f_str);
+        test("83.0-41", "" + f_d + sf_bM);
+        test("83.0null", "" + f_d + sf_IN);
+        test("83.0T", "" + f_d + s_c);
+        test("83.0-42.0", "" + f_d + sf_fM);
+        test("83.025", "" + f_d + s_b);
+        test("83.0null", "" + f_d + f_oN);
+        test("83.0-1410065408", "" + f_d + s_lM);
+        test("83.08.0", "" + f_d + s_d);
+        test("83.055.0", "" + f_d + s_f);
+        test("83.097000000", "" + f_d + s_i);
+        test("83.0-9900", "" + f_d + f_sM);
+        test("83.0935228928", "" + f_d + s_l);
+        test("83.0-8400", "" + f_d + sf_sM);
+        test("83.0C(82)", "" + f_d + s_o);
+        test("83.0null", "" + f_d + sf_oNtS);
+    }
+
+    public void run4() {
+        test("83.0true", "" + f_d + s_bl);
+        test("83.03900", "" + f_d + s_s);
+        test("83.0null", "" + f_d + sf_oN);
+        test("83.094000000", "" + f_d + f_I);
+        test("83.0null", "" + f_d + f_IN);
+        test("83.0true", "" + f_d + sf_bl);
+        test("83.05500", "" + f_d + sf_s);
+        test("83.0-2900", "" + f_d + s_sM);
+        test("83.0-194313216", "" + f_d + sf_l);
+        test("83.012", "" + f_d + s_strU1);
+        test("83.0C(87)", "" + f_d + sf_o);
+        test("83.091", "" + f_d + s_strU2);
+        test("83.021", "" + f_d + f_strU1);
+        test("83.018", "" + f_d + f_strU2);
+        test("83.0null", "" + f_d + f_iAN);
+        test("83.0null", "" + f_d + s_oN);
+        test("83.0\u045180", "" + f_d + s_strU);
+        test("83.0C", "" + f_d + sf_c);
+        test("83.075", "" + f_d + sf_str);
+        test("83.0-43", "" + f_d + s_bM);
+        test("83.080", "" + f_d + sf_b);
+        test("83.0null", "" + f_d + s_IN);
+        test("83.0-52.0", "" + f_d + s_fM);
+        test("83.075000000", "" + f_d + sf_i);
+        test("83.044", "" + f_d + f_b);
+        test("83.0-1705032704", "" + f_d + sf_lM);
+        test("83.0null", "" + f_d + f_oAN);
+        test("83.083.0", "" + f_d + f_d);
+        test("83.0I", "" + f_d + f_c);
+        test("83.094.0", "" + f_d + f_f);
+        test("83.012.0", "" + f_d + sf_d);
+        test("83.0-99.0", "" + f_d + f_dM);
+        test("83.017.0", "" + f_d + sf_f);
+        test("83.0-84.0", "" + f_d + sf_dM);
+        test("83.058000000", "" + f_d + f_i);
+        test("83.0-55000000", "" + f_d + f_iM);
+        test("83.01460392448", "" + f_d + f_l);
+        test("83.0C(70)", "" + f_d + f_o);
+        test("83.0\u04511", "" + f_d + sf_strU);
+        test("83.08000", "" + f_d + f_s);
+        test("83.018", "" + f_d + s_str);
+        test("83.0-1000000", "" + f_d + s_iM);
+        test("83.01000000", "" + f_d + sf_I);
+        test("83.0null", "" + f_d + f_oNtS);
+        test("83.0false", "" + f_d + f_bl);
+        test("83.0null", "" + f_d + sf_iAN);
+        test("83.0-2000000", "" + f_d + sf_iM);
+        test("83.0-820130816", "" + f_d + f_lM);
+        test("83.0null", "" + f_d + sf_oAN);
+        test("83.025000000", "" + f_d + s_I);
+        test("I-96.0", "" + f_c + s_dM);
+        test("Inull", "" + f_c + s_oNtS);
+        test("I\u045176", "" + f_c + f_strU);
+        test("I92", "" + f_c + sf_strU2);
+        test("I51", "" + f_c + sf_strU1);
+        test("Inull", "" + f_c + s_iAN);
+        test("I-54", "" + f_c + f_bM);
+        test("I-87.0", "" + f_c + f_fM);
+        test("Inull", "" + f_c + s_oAN);
+        test("I19", "" + f_c + f_str);
+        test("I-41", "" + f_c + sf_bM);
+        test("Inull", "" + f_c + sf_IN);
+        test("IT", "" + f_c + s_c);
+        test("I-42.0", "" + f_c + sf_fM);
+        test("I25", "" + f_c + s_b);
+        test("Inull", "" + f_c + f_oN);
+        test("I-1410065408", "" + f_c + s_lM);
+        test("I8.0", "" + f_c + s_d);
+        test("I55.0", "" + f_c + s_f);
+        test("I97000000", "" + f_c + s_i);
+        test("I-9900", "" + f_c + f_sM);
+        test("I935228928", "" + f_c + s_l);
+        test("I-8400", "" + f_c + sf_sM);
+        test("IC(82)", "" + f_c + s_o);
+        test("Inull", "" + f_c + sf_oNtS);
+        test("Itrue", "" + f_c + s_bl);
+        test("I3900", "" + f_c + s_s);
+        test("Inull", "" + f_c + sf_oN);
+        test("I94000000", "" + f_c + f_I);
+        test("Inull", "" + f_c + f_IN);
+        test("Itrue", "" + f_c + sf_bl);
+        test("I5500", "" + f_c + sf_s);
+        test("I-2900", "" + f_c + s_sM);
+        test("I-194313216", "" + f_c + sf_l);
+        test("I12", "" + f_c + s_strU1);
+        test("IC(87)", "" + f_c + sf_o);
+        test("I91", "" + f_c + s_strU2);
+        test("I21", "" + f_c + f_strU1);
+        test("I18", "" + f_c + f_strU2);
+        test("Inull", "" + f_c + f_iAN);
+        test("Inull", "" + f_c + s_oN);
+        test("I\u045180", "" + f_c + s_strU);
+        test("IC", "" + f_c + sf_c);
+        test("I75", "" + f_c + sf_str);
+        test("I-43", "" + f_c + s_bM);
+        test("I80", "" + f_c + sf_b);
+        test("Inull", "" + f_c + s_IN);
+        test("I-52.0", "" + f_c + s_fM);
+        test("I75000000", "" + f_c + sf_i);
+        test("I44", "" + f_c + f_b);
+        test("I-1705032704", "" + f_c + sf_lM);
+        test("Inull", "" + f_c + f_oAN);
+        test("I83.0", "" + f_c + f_d);
+        test("II", "" + f_c + f_c);
+        test("I94.0", "" + f_c + f_f);
+        test("I12.0", "" + f_c + sf_d);
+        test("I-99.0", "" + f_c + f_dM);
+        test("I17.0", "" + f_c + sf_f);
+        test("I-84.0", "" + f_c + sf_dM);
+        test("I58000000", "" + f_c + f_i);
+        test("I-55000000", "" + f_c + f_iM);
+        test("I1460392448", "" + f_c + f_l);
+        test("IC(70)", "" + f_c + f_o);
+        test("I\u04511", "" + f_c + sf_strU);
+        test("I8000", "" + f_c + f_s);
+        test("I18", "" + f_c + s_str);
+        test("I-1000000", "" + f_c + s_iM);
+        test("I1000000", "" + f_c + sf_I);
+        test("Inull", "" + f_c + f_oNtS);
+        test("Ifalse", "" + f_c + f_bl);
+        test("Inull", "" + f_c + sf_iAN);
+        test("I-2000000", "" + f_c + sf_iM);
+        test("I-820130816", "" + f_c + f_lM);
+        test("Inull", "" + f_c + sf_oAN);
+        test("I25000000", "" + f_c + s_I);
+        test("94.0-96.0", "" + f_f + s_dM);
+        test("94.0null", "" + f_f + s_oNtS);
+        test("94.0\u045176", "" + f_f + f_strU);
+        test("94.092", "" + f_f + sf_strU2);
+        test("94.051", "" + f_f + sf_strU1);
+        test("94.0null", "" + f_f + s_iAN);
+        test("94.0-54", "" + f_f + f_bM);
+        test("94.0-87.0", "" + f_f + f_fM);
+        test("94.0null", "" + f_f + s_oAN);
+        test("94.019", "" + f_f + f_str);
+        test("94.0-41", "" + f_f + sf_bM);
+        test("94.0null", "" + f_f + sf_IN);
+        test("94.0T", "" + f_f + s_c);
+        test("94.0-42.0", "" + f_f + sf_fM);
+        test("94.025", "" + f_f + s_b);
+        test("94.0null", "" + f_f + f_oN);
+        test("94.0-1410065408", "" + f_f + s_lM);
+        test("94.08.0", "" + f_f + s_d);
+        test("94.055.0", "" + f_f + s_f);
+        test("94.097000000", "" + f_f + s_i);
+        test("94.0-9900", "" + f_f + f_sM);
+        test("94.0935228928", "" + f_f + s_l);
+        test("94.0-8400", "" + f_f + sf_sM);
+        test("94.0C(82)", "" + f_f + s_o);
+        test("94.0null", "" + f_f + sf_oNtS);
+        test("94.0true", "" + f_f + s_bl);
+        test("94.03900", "" + f_f + s_s);
+        test("94.0null", "" + f_f + sf_oN);
+        test("94.094000000", "" + f_f + f_I);
+        test("94.0null", "" + f_f + f_IN);
+        test("94.0true", "" + f_f + sf_bl);
+        test("94.05500", "" + f_f + sf_s);
+        test("94.0-2900", "" + f_f + s_sM);
+        test("94.0-194313216", "" + f_f + sf_l);
+        test("94.012", "" + f_f + s_strU1);
+        test("94.0C(87)", "" + f_f + sf_o);
+        test("94.091", "" + f_f + s_strU2);
+        test("94.021", "" + f_f + f_strU1);
+        test("94.018", "" + f_f + f_strU2);
+        test("94.0null", "" + f_f + f_iAN);
+        test("94.0null", "" + f_f + s_oN);
+        test("94.0\u045180", "" + f_f + s_strU);
+        test("94.0C", "" + f_f + sf_c);
+        test("94.075", "" + f_f + sf_str);
+        test("94.0-43", "" + f_f + s_bM);
+        test("94.080", "" + f_f + sf_b);
+        test("94.0null", "" + f_f + s_IN);
+        test("94.0-52.0", "" + f_f + s_fM);
+        test("94.075000000", "" + f_f + sf_i);
+        test("94.044", "" + f_f + f_b);
+        test("94.0-1705032704", "" + f_f + sf_lM);
+        test("94.0null", "" + f_f + f_oAN);
+        test("94.083.0", "" + f_f + f_d);
+        test("94.0I", "" + f_f + f_c);
+        test("94.094.0", "" + f_f + f_f);
+        test("94.012.0", "" + f_f + sf_d);
+        test("94.0-99.0", "" + f_f + f_dM);
+        test("94.017.0", "" + f_f + sf_f);
+        test("94.0-84.0", "" + f_f + sf_dM);
+        test("94.058000000", "" + f_f + f_i);
+        test("94.0-55000000", "" + f_f + f_iM);
+        test("94.01460392448", "" + f_f + f_l);
+        test("94.0C(70)", "" + f_f + f_o);
+        test("94.0\u04511", "" + f_f + sf_strU);
+        test("94.08000", "" + f_f + f_s);
+        test("94.018", "" + f_f + s_str);
+        test("94.0-1000000", "" + f_f + s_iM);
+        test("94.01000000", "" + f_f + sf_I);
+        test("94.0null", "" + f_f + f_oNtS);
+        test("94.0false", "" + f_f + f_bl);
+        test("94.0null", "" + f_f + sf_iAN);
+        test("94.0-2000000", "" + f_f + sf_iM);
+        test("94.0-820130816", "" + f_f + f_lM);
+        test("94.0null", "" + f_f + sf_oAN);
+        test("94.025000000", "" + f_f + s_I);
+        test("12.0-96.0", "" + sf_d + s_dM);
+        test("12.0null", "" + sf_d + s_oNtS);
+        test("12.0\u045176", "" + sf_d + f_strU);
+        test("12.092", "" + sf_d + sf_strU2);
+        test("12.051", "" + sf_d + sf_strU1);
+        test("12.0null", "" + sf_d + s_iAN);
+        test("12.0-54", "" + sf_d + f_bM);
+        test("12.0-87.0", "" + sf_d + f_fM);
+        test("12.0null", "" + sf_d + s_oAN);
+        test("12.019", "" + sf_d + f_str);
+        test("12.0-41", "" + sf_d + sf_bM);
+        test("12.0null", "" + sf_d + sf_IN);
+        test("12.0T", "" + sf_d + s_c);
+        test("12.0-42.0", "" + sf_d + sf_fM);
+        test("12.025", "" + sf_d + s_b);
+        test("12.0null", "" + sf_d + f_oN);
+        test("12.0-1410065408", "" + sf_d + s_lM);
+        test("12.08.0", "" + sf_d + s_d);
+        test("12.055.0", "" + sf_d + s_f);
+        test("12.097000000", "" + sf_d + s_i);
+        test("12.0-9900", "" + sf_d + f_sM);
+        test("12.0935228928", "" + sf_d + s_l);
+        test("12.0-8400", "" + sf_d + sf_sM);
+        test("12.0C(82)", "" + sf_d + s_o);
+        test("12.0null", "" + sf_d + sf_oNtS);
+        test("12.0true", "" + sf_d + s_bl);
+        test("12.03900", "" + sf_d + s_s);
+        test("12.0null", "" + sf_d + sf_oN);
+        test("12.094000000", "" + sf_d + f_I);
+        test("12.0null", "" + sf_d + f_IN);
+        test("12.0true", "" + sf_d + sf_bl);
+        test("12.05500", "" + sf_d + sf_s);
+        test("12.0-2900", "" + sf_d + s_sM);
+        test("12.0-194313216", "" + sf_d + sf_l);
+        test("12.012", "" + sf_d + s_strU1);
+        test("12.0C(87)", "" + sf_d + sf_o);
+        test("12.091", "" + sf_d + s_strU2);
+        test("12.021", "" + sf_d + f_strU1);
+        test("12.018", "" + sf_d + f_strU2);
+        test("12.0null", "" + sf_d + f_iAN);
+        test("12.0null", "" + sf_d + s_oN);
+        test("12.0\u045180", "" + sf_d + s_strU);
+        test("12.0C", "" + sf_d + sf_c);
+        test("12.075", "" + sf_d + sf_str);
+        test("12.0-43", "" + sf_d + s_bM);
+        test("12.080", "" + sf_d + sf_b);
+        test("12.0null", "" + sf_d + s_IN);
+        test("12.0-52.0", "" + sf_d + s_fM);
+        test("12.075000000", "" + sf_d + sf_i);
+        test("12.044", "" + sf_d + f_b);
+        test("12.0-1705032704", "" + sf_d + sf_lM);
+        test("12.0null", "" + sf_d + f_oAN);
+        test("12.083.0", "" + sf_d + f_d);
+        test("12.0I", "" + sf_d + f_c);
+        test("12.094.0", "" + sf_d + f_f);
+        test("12.012.0", "" + sf_d + sf_d);
+        test("12.0-99.0", "" + sf_d + f_dM);
+        test("12.017.0", "" + sf_d + sf_f);
+        test("12.0-84.0", "" + sf_d + sf_dM);
+        test("12.058000000", "" + sf_d + f_i);
+        test("12.0-55000000", "" + sf_d + f_iM);
+        test("12.01460392448", "" + sf_d + f_l);
+        test("12.0C(70)", "" + sf_d + f_o);
+        test("12.0\u04511", "" + sf_d + sf_strU);
+        test("12.08000", "" + sf_d + f_s);
+        test("12.018", "" + sf_d + s_str);
+        test("12.0-1000000", "" + sf_d + s_iM);
+        test("12.01000000", "" + sf_d + sf_I);
+        test("12.0null", "" + sf_d + f_oNtS);
+        test("12.0false", "" + sf_d + f_bl);
+        test("12.0null", "" + sf_d + sf_iAN);
+        test("12.0-2000000", "" + sf_d + sf_iM);
+        test("12.0-820130816", "" + sf_d + f_lM);
+        test("12.0null", "" + sf_d + sf_oAN);
+        test("12.025000000", "" + sf_d + s_I);
+        test("-99.0-96.0", "" + f_dM + s_dM);
+        test("-99.0null", "" + f_dM + s_oNtS);
+        test("-99.0\u045176", "" + f_dM + f_strU);
+        test("-99.092", "" + f_dM + sf_strU2);
+        test("-99.051", "" + f_dM + sf_strU1);
+        test("-99.0null", "" + f_dM + s_iAN);
+        test("-99.0-54", "" + f_dM + f_bM);
+        test("-99.0-87.0", "" + f_dM + f_fM);
+        test("-99.0null", "" + f_dM + s_oAN);
+        test("-99.019", "" + f_dM + f_str);
+        test("-99.0-41", "" + f_dM + sf_bM);
+        test("-99.0null", "" + f_dM + sf_IN);
+        test("-99.0T", "" + f_dM + s_c);
+        test("-99.0-42.0", "" + f_dM + sf_fM);
+        test("-99.025", "" + f_dM + s_b);
+        test("-99.0null", "" + f_dM + f_oN);
+        test("-99.0-1410065408", "" + f_dM + s_lM);
+        test("-99.08.0", "" + f_dM + s_d);
+        test("-99.055.0", "" + f_dM + s_f);
+        test("-99.097000000", "" + f_dM + s_i);
+        test("-99.0-9900", "" + f_dM + f_sM);
+        test("-99.0935228928", "" + f_dM + s_l);
+        test("-99.0-8400", "" + f_dM + sf_sM);
+        test("-99.0C(82)", "" + f_dM + s_o);
+        test("-99.0null", "" + f_dM + sf_oNtS);
+        test("-99.0true", "" + f_dM + s_bl);
+        test("-99.03900", "" + f_dM + s_s);
+        test("-99.0null", "" + f_dM + sf_oN);
+        test("-99.094000000", "" + f_dM + f_I);
+        test("-99.0null", "" + f_dM + f_IN);
+        test("-99.0true", "" + f_dM + sf_bl);
+        test("-99.05500", "" + f_dM + sf_s);
+        test("-99.0-2900", "" + f_dM + s_sM);
+        test("-99.0-194313216", "" + f_dM + sf_l);
+        test("-99.012", "" + f_dM + s_strU1);
+        test("-99.0C(87)", "" + f_dM + sf_o);
+        test("-99.091", "" + f_dM + s_strU2);
+        test("-99.021", "" + f_dM + f_strU1);
+        test("-99.018", "" + f_dM + f_strU2);
+        test("-99.0null", "" + f_dM + f_iAN);
+        test("-99.0null", "" + f_dM + s_oN);
+        test("-99.0\u045180", "" + f_dM + s_strU);
+        test("-99.0C", "" + f_dM + sf_c);
+        test("-99.075", "" + f_dM + sf_str);
+        test("-99.0-43", "" + f_dM + s_bM);
+        test("-99.080", "" + f_dM + sf_b);
+        test("-99.0null", "" + f_dM + s_IN);
+        test("-99.0-52.0", "" + f_dM + s_fM);
+        test("-99.075000000", "" + f_dM + sf_i);
+        test("-99.044", "" + f_dM + f_b);
+        test("-99.0-1705032704", "" + f_dM + sf_lM);
+        test("-99.0null", "" + f_dM + f_oAN);
+        test("-99.083.0", "" + f_dM + f_d);
+        test("-99.0I", "" + f_dM + f_c);
+        test("-99.094.0", "" + f_dM + f_f);
+        test("-99.012.0", "" + f_dM + sf_d);
+        test("-99.0-99.0", "" + f_dM + f_dM);
+        test("-99.017.0", "" + f_dM + sf_f);
+        test("-99.0-84.0", "" + f_dM + sf_dM);
+        test("-99.058000000", "" + f_dM + f_i);
+        test("-99.0-55000000", "" + f_dM + f_iM);
+        test("-99.01460392448", "" + f_dM + f_l);
+        test("-99.0C(70)", "" + f_dM + f_o);
+        test("-99.0\u04511", "" + f_dM + sf_strU);
+        test("-99.08000", "" + f_dM + f_s);
+        test("-99.018", "" + f_dM + s_str);
+        test("-99.0-1000000", "" + f_dM + s_iM);
+        test("-99.01000000", "" + f_dM + sf_I);
+        test("-99.0null", "" + f_dM + f_oNtS);
+        test("-99.0false", "" + f_dM + f_bl);
+        test("-99.0null", "" + f_dM + sf_iAN);
+        test("-99.0-2000000", "" + f_dM + sf_iM);
+        test("-99.0-820130816", "" + f_dM + f_lM);
+        test("-99.0null", "" + f_dM + sf_oAN);
+        test("-99.025000000", "" + f_dM + s_I);
+        test("17.0-96.0", "" + sf_f + s_dM);
+        test("17.0null", "" + sf_f + s_oNtS);
+        test("17.0\u045176", "" + sf_f + f_strU);
+        test("17.092", "" + sf_f + sf_strU2);
+        test("17.051", "" + sf_f + sf_strU1);
+        test("17.0null", "" + sf_f + s_iAN);
+        test("17.0-54", "" + sf_f + f_bM);
+        test("17.0-87.0", "" + sf_f + f_fM);
+        test("17.0null", "" + sf_f + s_oAN);
+        test("17.019", "" + sf_f + f_str);
+        test("17.0-41", "" + sf_f + sf_bM);
+        test("17.0null", "" + sf_f + sf_IN);
+        test("17.0T", "" + sf_f + s_c);
+        test("17.0-42.0", "" + sf_f + sf_fM);
+        test("17.025", "" + sf_f + s_b);
+        test("17.0null", "" + sf_f + f_oN);
+        test("17.0-1410065408", "" + sf_f + s_lM);
+        test("17.08.0", "" + sf_f + s_d);
+        test("17.055.0", "" + sf_f + s_f);
+        test("17.097000000", "" + sf_f + s_i);
+        test("17.0-9900", "" + sf_f + f_sM);
+        test("17.0935228928", "" + sf_f + s_l);
+        test("17.0-8400", "" + sf_f + sf_sM);
+        test("17.0C(82)", "" + sf_f + s_o);
+        test("17.0null", "" + sf_f + sf_oNtS);
+        test("17.0true", "" + sf_f + s_bl);
+        test("17.03900", "" + sf_f + s_s);
+        test("17.0null", "" + sf_f + sf_oN);
+        test("17.094000000", "" + sf_f + f_I);
+        test("17.0null", "" + sf_f + f_IN);
+        test("17.0true", "" + sf_f + sf_bl);
+        test("17.05500", "" + sf_f + sf_s);
+        test("17.0-2900", "" + sf_f + s_sM);
+        test("17.0-194313216", "" + sf_f + sf_l);
+        test("17.012", "" + sf_f + s_strU1);
+        test("17.0C(87)", "" + sf_f + sf_o);
+        test("17.091", "" + sf_f + s_strU2);
+        test("17.021", "" + sf_f + f_strU1);
+        test("17.018", "" + sf_f + f_strU2);
+        test("17.0null", "" + sf_f + f_iAN);
+        test("17.0null", "" + sf_f + s_oN);
+        test("17.0\u045180", "" + sf_f + s_strU);
+        test("17.0C", "" + sf_f + sf_c);
+        test("17.075", "" + sf_f + sf_str);
+        test("17.0-43", "" + sf_f + s_bM);
+        test("17.080", "" + sf_f + sf_b);
+        test("17.0null", "" + sf_f + s_IN);
+        test("17.0-52.0", "" + sf_f + s_fM);
+        test("17.075000000", "" + sf_f + sf_i);
+        test("17.044", "" + sf_f + f_b);
+        test("17.0-1705032704", "" + sf_f + sf_lM);
+        test("17.0null", "" + sf_f + f_oAN);
+        test("17.083.0", "" + sf_f + f_d);
+        test("17.0I", "" + sf_f + f_c);
+        test("17.094.0", "" + sf_f + f_f);
+        test("17.012.0", "" + sf_f + sf_d);
+        test("17.0-99.0", "" + sf_f + f_dM);
+        test("17.017.0", "" + sf_f + sf_f);
+        test("17.0-84.0", "" + sf_f + sf_dM);
+        test("17.058000000", "" + sf_f + f_i);
+        test("17.0-55000000", "" + sf_f + f_iM);
+        test("17.01460392448", "" + sf_f + f_l);
+        test("17.0C(70)", "" + sf_f + f_o);
+        test("17.0\u04511", "" + sf_f + sf_strU);
+        test("17.08000", "" + sf_f + f_s);
+        test("17.018", "" + sf_f + s_str);
+        test("17.0-1000000", "" + sf_f + s_iM);
+        test("17.01000000", "" + sf_f + sf_I);
+        test("17.0null", "" + sf_f + f_oNtS);
+        test("17.0false", "" + sf_f + f_bl);
+        test("17.0null", "" + sf_f + sf_iAN);
+        test("17.0-2000000", "" + sf_f + sf_iM);
+        test("17.0-820130816", "" + sf_f + f_lM);
+        test("17.0null", "" + sf_f + sf_oAN);
+        test("17.025000000", "" + sf_f + s_I);
+        test("-84.0-96.0", "" + sf_dM + s_dM);
+        test("-84.0null", "" + sf_dM + s_oNtS);
+        test("-84.0\u045176", "" + sf_dM + f_strU);
+        test("-84.092", "" + sf_dM + sf_strU2);
+        test("-84.051", "" + sf_dM + sf_strU1);
+        test("-84.0null", "" + sf_dM + s_iAN);
+        test("-84.0-54", "" + sf_dM + f_bM);
+        test("-84.0-87.0", "" + sf_dM + f_fM);
+        test("-84.0null", "" + sf_dM + s_oAN);
+        test("-84.019", "" + sf_dM + f_str);
+        test("-84.0-41", "" + sf_dM + sf_bM);
+        test("-84.0null", "" + sf_dM + sf_IN);
+        test("-84.0T", "" + sf_dM + s_c);
+        test("-84.0-42.0", "" + sf_dM + sf_fM);
+        test("-84.025", "" + sf_dM + s_b);
+        test("-84.0null", "" + sf_dM + f_oN);
+        test("-84.0-1410065408", "" + sf_dM + s_lM);
+        test("-84.08.0", "" + sf_dM + s_d);
+        test("-84.055.0", "" + sf_dM + s_f);
+        test("-84.097000000", "" + sf_dM + s_i);
+        test("-84.0-9900", "" + sf_dM + f_sM);
+        test("-84.0935228928", "" + sf_dM + s_l);
+        test("-84.0-8400", "" + sf_dM + sf_sM);
+        test("-84.0C(82)", "" + sf_dM + s_o);
+        test("-84.0null", "" + sf_dM + sf_oNtS);
+        test("-84.0true", "" + sf_dM + s_bl);
+        test("-84.03900", "" + sf_dM + s_s);
+        test("-84.0null", "" + sf_dM + sf_oN);
+        test("-84.094000000", "" + sf_dM + f_I);
+        test("-84.0null", "" + sf_dM + f_IN);
+        test("-84.0true", "" + sf_dM + sf_bl);
+        test("-84.05500", "" + sf_dM + sf_s);
+        test("-84.0-2900", "" + sf_dM + s_sM);
+        test("-84.0-194313216", "" + sf_dM + sf_l);
+        test("-84.012", "" + sf_dM + s_strU1);
+        test("-84.0C(87)", "" + sf_dM + sf_o);
+        test("-84.091", "" + sf_dM + s_strU2);
+        test("-84.021", "" + sf_dM + f_strU1);
+        test("-84.018", "" + sf_dM + f_strU2);
+        test("-84.0null", "" + sf_dM + f_iAN);
+        test("-84.0null", "" + sf_dM + s_oN);
+        test("-84.0\u045180", "" + sf_dM + s_strU);
+        test("-84.0C", "" + sf_dM + sf_c);
+        test("-84.075", "" + sf_dM + sf_str);
+        test("-84.0-43", "" + sf_dM + s_bM);
+        test("-84.080", "" + sf_dM + sf_b);
+        test("-84.0null", "" + sf_dM + s_IN);
+        test("-84.0-52.0", "" + sf_dM + s_fM);
+        test("-84.075000000", "" + sf_dM + sf_i);
+        test("-84.044", "" + sf_dM + f_b);
+        test("-84.0-1705032704", "" + sf_dM + sf_lM);
+        test("-84.0null", "" + sf_dM + f_oAN);
+        test("-84.083.0", "" + sf_dM + f_d);
+        test("-84.0I", "" + sf_dM + f_c);
+        test("-84.094.0", "" + sf_dM + f_f);
+        test("-84.012.0", "" + sf_dM + sf_d);
+        test("-84.0-99.0", "" + sf_dM + f_dM);
+        test("-84.017.0", "" + sf_dM + sf_f);
+        test("-84.0-84.0", "" + sf_dM + sf_dM);
+        test("-84.058000000", "" + sf_dM + f_i);
+        test("-84.0-55000000", "" + sf_dM + f_iM);
+        test("-84.01460392448", "" + sf_dM + f_l);
+        test("-84.0C(70)", "" + sf_dM + f_o);
+        test("-84.0\u04511", "" + sf_dM + sf_strU);
+        test("-84.08000", "" + sf_dM + f_s);
+        test("-84.018", "" + sf_dM + s_str);
+        test("-84.0-1000000", "" + sf_dM + s_iM);
+        test("-84.01000000", "" + sf_dM + sf_I);
+        test("-84.0null", "" + sf_dM + f_oNtS);
+        test("-84.0false", "" + sf_dM + f_bl);
+        test("-84.0null", "" + sf_dM + sf_iAN);
+        test("-84.0-2000000", "" + sf_dM + sf_iM);
+        test("-84.0-820130816", "" + sf_dM + f_lM);
+        test("-84.0null", "" + sf_dM + sf_oAN);
+        test("-84.025000000", "" + sf_dM + s_I);
+        test("58000000-96.0", "" + f_i + s_dM);
+        test("58000000null", "" + f_i + s_oNtS);
+        test("58000000\u045176", "" + f_i + f_strU);
+        test("5800000092", "" + f_i + sf_strU2);
+        test("5800000051", "" + f_i + sf_strU1);
+        test("58000000null", "" + f_i + s_iAN);
+        test("58000000-54", "" + f_i + f_bM);
+        test("58000000-87.0", "" + f_i + f_fM);
+        test("58000000null", "" + f_i + s_oAN);
+        test("5800000019", "" + f_i + f_str);
+        test("58000000-41", "" + f_i + sf_bM);
+        test("58000000null", "" + f_i + sf_IN);
+        test("58000000T", "" + f_i + s_c);
+        test("58000000-42.0", "" + f_i + sf_fM);
+        test("5800000025", "" + f_i + s_b);
+        test("58000000null", "" + f_i + f_oN);
+        test("58000000-1410065408", "" + f_i + s_lM);
+        test("580000008.0", "" + f_i + s_d);
+        test("5800000055.0", "" + f_i + s_f);
+        test("5800000097000000", "" + f_i + s_i);
+        test("58000000-9900", "" + f_i + f_sM);
+        test("58000000935228928", "" + f_i + s_l);
+        test("58000000-8400", "" + f_i + sf_sM);
+        test("58000000C(82)", "" + f_i + s_o);
+        test("58000000null", "" + f_i + sf_oNtS);
+        test("58000000true", "" + f_i + s_bl);
+        test("580000003900", "" + f_i + s_s);
+        test("58000000null", "" + f_i + sf_oN);
+        test("5800000094000000", "" + f_i + f_I);
+        test("58000000null", "" + f_i + f_IN);
+        test("58000000true", "" + f_i + sf_bl);
+        test("580000005500", "" + f_i + sf_s);
+        test("58000000-2900", "" + f_i + s_sM);
+        test("58000000-194313216", "" + f_i + sf_l);
+        test("5800000012", "" + f_i + s_strU1);
+        test("58000000C(87)", "" + f_i + sf_o);
+        test("5800000091", "" + f_i + s_strU2);
+        test("5800000021", "" + f_i + f_strU1);
+        test("5800000018", "" + f_i + f_strU2);
+        test("58000000null", "" + f_i + f_iAN);
+        test("58000000null", "" + f_i + s_oN);
+        test("58000000\u045180", "" + f_i + s_strU);
+        test("58000000C", "" + f_i + sf_c);
+        test("5800000075", "" + f_i + sf_str);
+        test("58000000-43", "" + f_i + s_bM);
+        test("5800000080", "" + f_i + sf_b);
+        test("58000000null", "" + f_i + s_IN);
+        test("58000000-52.0", "" + f_i + s_fM);
+        test("5800000075000000", "" + f_i + sf_i);
+        test("5800000044", "" + f_i + f_b);
+        test("58000000-1705032704", "" + f_i + sf_lM);
+        test("58000000null", "" + f_i + f_oAN);
+        test("5800000083.0", "" + f_i + f_d);
+        test("58000000I", "" + f_i + f_c);
+        test("5800000094.0", "" + f_i + f_f);
+        test("5800000012.0", "" + f_i + sf_d);
+        test("58000000-99.0", "" + f_i + f_dM);
+        test("5800000017.0", "" + f_i + sf_f);
+        test("58000000-84.0", "" + f_i + sf_dM);
+        test("5800000058000000", "" + f_i + f_i);
+        test("58000000-55000000", "" + f_i + f_iM);
+        test("580000001460392448", "" + f_i + f_l);
+        test("58000000C(70)", "" + f_i + f_o);
+        test("58000000\u04511", "" + f_i + sf_strU);
+        test("580000008000", "" + f_i + f_s);
+        test("5800000018", "" + f_i + s_str);
+        test("58000000-1000000", "" + f_i + s_iM);
+        test("580000001000000", "" + f_i + sf_I);
+        test("58000000null", "" + f_i + f_oNtS);
+        test("58000000false", "" + f_i + f_bl);
+        test("58000000null", "" + f_i + sf_iAN);
+        test("58000000-2000000", "" + f_i + sf_iM);
+        test("58000000-820130816", "" + f_i + f_lM);
+        test("58000000null", "" + f_i + sf_oAN);
+        test("5800000025000000", "" + f_i + s_I);
+        test("-55000000-96.0", "" + f_iM + s_dM);
+        test("-55000000null", "" + f_iM + s_oNtS);
+        test("-55000000\u045176", "" + f_iM + f_strU);
+        test("-5500000092", "" + f_iM + sf_strU2);
+        test("-5500000051", "" + f_iM + sf_strU1);
+        test("-55000000null", "" + f_iM + s_iAN);
+        test("-55000000-54", "" + f_iM + f_bM);
+        test("-55000000-87.0", "" + f_iM + f_fM);
+        test("-55000000null", "" + f_iM + s_oAN);
+        test("-5500000019", "" + f_iM + f_str);
+        test("-55000000-41", "" + f_iM + sf_bM);
+        test("-55000000null", "" + f_iM + sf_IN);
+        test("-55000000T", "" + f_iM + s_c);
+        test("-55000000-42.0", "" + f_iM + sf_fM);
+        test("-5500000025", "" + f_iM + s_b);
+        test("-55000000null", "" + f_iM + f_oN);
+        test("-55000000-1410065408", "" + f_iM + s_lM);
+        test("-550000008.0", "" + f_iM + s_d);
+        test("-5500000055.0", "" + f_iM + s_f);
+        test("-5500000097000000", "" + f_iM + s_i);
+        test("-55000000-9900", "" + f_iM + f_sM);
+        test("-55000000935228928", "" + f_iM + s_l);
+        test("-55000000-8400", "" + f_iM + sf_sM);
+        test("-55000000C(82)", "" + f_iM + s_o);
+        test("-55000000null", "" + f_iM + sf_oNtS);
+        test("-55000000true", "" + f_iM + s_bl);
+        test("-550000003900", "" + f_iM + s_s);
+        test("-55000000null", "" + f_iM + sf_oN);
+        test("-5500000094000000", "" + f_iM + f_I);
+        test("-55000000null", "" + f_iM + f_IN);
+        test("-55000000true", "" + f_iM + sf_bl);
+        test("-550000005500", "" + f_iM + sf_s);
+        test("-55000000-2900", "" + f_iM + s_sM);
+        test("-55000000-194313216", "" + f_iM + sf_l);
+        test("-5500000012", "" + f_iM + s_strU1);
+        test("-55000000C(87)", "" + f_iM + sf_o);
+        test("-5500000091", "" + f_iM + s_strU2);
+        test("-5500000021", "" + f_iM + f_strU1);
+        test("-5500000018", "" + f_iM + f_strU2);
+        test("-55000000null", "" + f_iM + f_iAN);
+        test("-55000000null", "" + f_iM + s_oN);
+        test("-55000000\u045180", "" + f_iM + s_strU);
+        test("-55000000C", "" + f_iM + sf_c);
+        test("-5500000075", "" + f_iM + sf_str);
+        test("-55000000-43", "" + f_iM + s_bM);
+        test("-5500000080", "" + f_iM + sf_b);
+        test("-55000000null", "" + f_iM + s_IN);
+        test("-55000000-52.0", "" + f_iM + s_fM);
+        test("-5500000075000000", "" + f_iM + sf_i);
+        test("-5500000044", "" + f_iM + f_b);
+        test("-55000000-1705032704", "" + f_iM + sf_lM);
+        test("-55000000null", "" + f_iM + f_oAN);
+        test("-5500000083.0", "" + f_iM + f_d);
+        test("-55000000I", "" + f_iM + f_c);
+        test("-5500000094.0", "" + f_iM + f_f);
+        test("-5500000012.0", "" + f_iM + sf_d);
+        test("-55000000-99.0", "" + f_iM + f_dM);
+        test("-5500000017.0", "" + f_iM + sf_f);
+        test("-55000000-84.0", "" + f_iM + sf_dM);
+        test("-5500000058000000", "" + f_iM + f_i);
+        test("-55000000-55000000", "" + f_iM + f_iM);
+        test("-550000001460392448", "" + f_iM + f_l);
+        test("-55000000C(70)", "" + f_iM + f_o);
+        test("-55000000\u04511", "" + f_iM + sf_strU);
+        test("-550000008000", "" + f_iM + f_s);
+        test("-5500000018", "" + f_iM + s_str);
+        test("-55000000-1000000", "" + f_iM + s_iM);
+        test("-550000001000000", "" + f_iM + sf_I);
+        test("-55000000null", "" + f_iM + f_oNtS);
+        test("-55000000false", "" + f_iM + f_bl);
+        test("-55000000null", "" + f_iM + sf_iAN);
+        test("-55000000-2000000", "" + f_iM + sf_iM);
+        test("-55000000-820130816", "" + f_iM + f_lM);
+        test("-55000000null", "" + f_iM + sf_oAN);
+        test("-5500000025000000", "" + f_iM + s_I);
+        test("1460392448-96.0", "" + f_l + s_dM);
+        test("1460392448null", "" + f_l + s_oNtS);
+        test("1460392448\u045176", "" + f_l + f_strU);
+        test("146039244892", "" + f_l + sf_strU2);
+        test("146039244851", "" + f_l + sf_strU1);
+        test("1460392448null", "" + f_l + s_iAN);
+        test("1460392448-54", "" + f_l + f_bM);
+        test("1460392448-87.0", "" + f_l + f_fM);
+        test("1460392448null", "" + f_l + s_oAN);
+        test("146039244819", "" + f_l + f_str);
+        test("1460392448-41", "" + f_l + sf_bM);
+        test("1460392448null", "" + f_l + sf_IN);
+        test("1460392448T", "" + f_l + s_c);
+        test("1460392448-42.0", "" + f_l + sf_fM);
+        test("146039244825", "" + f_l + s_b);
+        test("1460392448null", "" + f_l + f_oN);
+        test("1460392448-1410065408", "" + f_l + s_lM);
+        test("14603924488.0", "" + f_l + s_d);
+        test("146039244855.0", "" + f_l + s_f);
+        test("146039244897000000", "" + f_l + s_i);
+        test("1460392448-9900", "" + f_l + f_sM);
+        test("1460392448935228928", "" + f_l + s_l);
+        test("1460392448-8400", "" + f_l + sf_sM);
+        test("1460392448C(82)", "" + f_l + s_o);
+        test("1460392448null", "" + f_l + sf_oNtS);
+        test("1460392448true", "" + f_l + s_bl);
+        test("14603924483900", "" + f_l + s_s);
+        test("1460392448null", "" + f_l + sf_oN);
+        test("146039244894000000", "" + f_l + f_I);
+        test("1460392448null", "" + f_l + f_IN);
+        test("1460392448true", "" + f_l + sf_bl);
+        test("14603924485500", "" + f_l + sf_s);
+        test("1460392448-2900", "" + f_l + s_sM);
+        test("1460392448-194313216", "" + f_l + sf_l);
+        test("146039244812", "" + f_l + s_strU1);
+        test("1460392448C(87)", "" + f_l + sf_o);
+        test("146039244891", "" + f_l + s_strU2);
+        test("146039244821", "" + f_l + f_strU1);
+        test("146039244818", "" + f_l + f_strU2);
+        test("1460392448null", "" + f_l + f_iAN);
+        test("1460392448null", "" + f_l + s_oN);
+        test("1460392448\u045180", "" + f_l + s_strU);
+        test("1460392448C", "" + f_l + sf_c);
+        test("146039244875", "" + f_l + sf_str);
+        test("1460392448-43", "" + f_l + s_bM);
+        test("146039244880", "" + f_l + sf_b);
+        test("1460392448null", "" + f_l + s_IN);
+        test("1460392448-52.0", "" + f_l + s_fM);
+        test("146039244875000000", "" + f_l + sf_i);
+        test("146039244844", "" + f_l + f_b);
+        test("1460392448-1705032704", "" + f_l + sf_lM);
+        test("1460392448null", "" + f_l + f_oAN);
+        test("146039244883.0", "" + f_l + f_d);
+        test("1460392448I", "" + f_l + f_c);
+        test("146039244894.0", "" + f_l + f_f);
+        test("146039244812.0", "" + f_l + sf_d);
+        test("1460392448-99.0", "" + f_l + f_dM);
+        test("146039244817.0", "" + f_l + sf_f);
+        test("1460392448-84.0", "" + f_l + sf_dM);
+        test("146039244858000000", "" + f_l + f_i);
+        test("1460392448-55000000", "" + f_l + f_iM);
+        test("14603924481460392448", "" + f_l + f_l);
+        test("1460392448C(70)", "" + f_l + f_o);
+        test("1460392448\u04511", "" + f_l + sf_strU);
+        test("14603924488000", "" + f_l + f_s);
+        test("146039244818", "" + f_l + s_str);
+        test("1460392448-1000000", "" + f_l + s_iM);
+        test("14603924481000000", "" + f_l + sf_I);
+        test("1460392448null", "" + f_l + f_oNtS);
+        test("1460392448false", "" + f_l + f_bl);
+        test("1460392448null", "" + f_l + sf_iAN);
+        test("1460392448-2000000", "" + f_l + sf_iM);
+        test("1460392448-820130816", "" + f_l + f_lM);
+        test("1460392448null", "" + f_l + sf_oAN);
+        test("146039244825000000", "" + f_l + s_I);
+        test("C(70)-96.0", "" + f_o + s_dM);
+        test("C(70)null", "" + f_o + s_oNtS);
+        test("C(70)\u045176", "" + f_o + f_strU);
+        test("C(70)92", "" + f_o + sf_strU2);
+        test("C(70)51", "" + f_o + sf_strU1);
+        test("C(70)null", "" + f_o + s_iAN);
+        test("C(70)-54", "" + f_o + f_bM);
+        test("C(70)-87.0", "" + f_o + f_fM);
+        test("C(70)null", "" + f_o + s_oAN);
+        test("C(70)19", "" + f_o + f_str);
+        test("C(70)-41", "" + f_o + sf_bM);
+        test("C(70)null", "" + f_o + sf_IN);
+        test("C(70)T", "" + f_o + s_c);
+        test("C(70)-42.0", "" + f_o + sf_fM);
+        test("C(70)25", "" + f_o + s_b);
+        test("C(70)null", "" + f_o + f_oN);
+        test("C(70)-1410065408", "" + f_o + s_lM);
+        test("C(70)8.0", "" + f_o + s_d);
+        test("C(70)55.0", "" + f_o + s_f);
+        test("C(70)97000000", "" + f_o + s_i);
+        test("C(70)-9900", "" + f_o + f_sM);
+        test("C(70)935228928", "" + f_o + s_l);
+        test("C(70)-8400", "" + f_o + sf_sM);
+        test("C(70)C(82)", "" + f_o + s_o);
+        test("C(70)null", "" + f_o + sf_oNtS);
+        test("C(70)true", "" + f_o + s_bl);
+        test("C(70)3900", "" + f_o + s_s);
+        test("C(70)null", "" + f_o + sf_oN);
+        test("C(70)94000000", "" + f_o + f_I);
+        test("C(70)null", "" + f_o + f_IN);
+        test("C(70)true", "" + f_o + sf_bl);
+        test("C(70)5500", "" + f_o + sf_s);
+        test("C(70)-2900", "" + f_o + s_sM);
+        test("C(70)-194313216", "" + f_o + sf_l);
+        test("C(70)12", "" + f_o + s_strU1);
+        test("C(70)C(87)", "" + f_o + sf_o);
+        test("C(70)91", "" + f_o + s_strU2);
+        test("C(70)21", "" + f_o + f_strU1);
+        test("C(70)18", "" + f_o + f_strU2);
+        test("C(70)null", "" + f_o + f_iAN);
+        test("C(70)null", "" + f_o + s_oN);
+        test("C(70)\u045180", "" + f_o + s_strU);
+        test("C(70)C", "" + f_o + sf_c);
+        test("C(70)75", "" + f_o + sf_str);
+        test("C(70)-43", "" + f_o + s_bM);
+        test("C(70)80", "" + f_o + sf_b);
+        test("C(70)null", "" + f_o + s_IN);
+        test("C(70)-52.0", "" + f_o + s_fM);
+        test("C(70)75000000", "" + f_o + sf_i);
+        test("C(70)44", "" + f_o + f_b);
+        test("C(70)-1705032704", "" + f_o + sf_lM);
+        test("C(70)null", "" + f_o + f_oAN);
+        test("C(70)83.0", "" + f_o + f_d);
+        test("C(70)I", "" + f_o + f_c);
+        test("C(70)94.0", "" + f_o + f_f);
+        test("C(70)12.0", "" + f_o + sf_d);
+        test("C(70)-99.0", "" + f_o + f_dM);
+        test("C(70)17.0", "" + f_o + sf_f);
+        test("C(70)-84.0", "" + f_o + sf_dM);
+        test("C(70)58000000", "" + f_o + f_i);
+        test("C(70)-55000000", "" + f_o + f_iM);
+        test("C(70)1460392448", "" + f_o + f_l);
+        test("C(70)C(70)", "" + f_o + f_o);
+        test("C(70)\u04511", "" + f_o + sf_strU);
+        test("C(70)8000", "" + f_o + f_s);
+        test("C(70)18", "" + f_o + s_str);
+        test("C(70)-1000000", "" + f_o + s_iM);
+        test("C(70)1000000", "" + f_o + sf_I);
+        test("C(70)null", "" + f_o + f_oNtS);
+        test("C(70)false", "" + f_o + f_bl);
+        test("C(70)null", "" + f_o + sf_iAN);
+        test("C(70)-2000000", "" + f_o + sf_iM);
+        test("C(70)-820130816", "" + f_o + f_lM);
+        test("C(70)null", "" + f_o + sf_oAN);
+        test("C(70)25000000", "" + f_o + s_I);
+        test("\u04511-96.0", "" + sf_strU + s_dM);
+        test("\u04511null", "" + sf_strU + s_oNtS);
+        test("\u04511\u045176", "" + sf_strU + f_strU);
+        test("\u0451192", "" + sf_strU + sf_strU2);
+        test("\u0451151", "" + sf_strU + sf_strU1);
+        test("\u04511null", "" + sf_strU + s_iAN);
+        test("\u04511-54", "" + sf_strU + f_bM);
+        test("\u04511-87.0", "" + sf_strU + f_fM);
+        test("\u04511null", "" + sf_strU + s_oAN);
+        test("\u0451119", "" + sf_strU + f_str);
+        test("\u04511-41", "" + sf_strU + sf_bM);
+        test("\u04511null", "" + sf_strU + sf_IN);
+        test("\u04511T", "" + sf_strU + s_c);
+        test("\u04511-42.0", "" + sf_strU + sf_fM);
+        test("\u0451125", "" + sf_strU + s_b);
+        test("\u04511null", "" + sf_strU + f_oN);
+        test("\u04511-1410065408", "" + sf_strU + s_lM);
+        test("\u045118.0", "" + sf_strU + s_d);
+        test("\u0451155.0", "" + sf_strU + s_f);
+        test("\u0451197000000", "" + sf_strU + s_i);
+        test("\u04511-9900", "" + sf_strU + f_sM);
+        test("\u04511935228928", "" + sf_strU + s_l);
+        test("\u04511-8400", "" + sf_strU + sf_sM);
+        test("\u04511C(82)", "" + sf_strU + s_o);
+        test("\u04511null", "" + sf_strU + sf_oNtS);
+        test("\u04511true", "" + sf_strU + s_bl);
+        test("\u045113900", "" + sf_strU + s_s);
+        test("\u04511null", "" + sf_strU + sf_oN);
+        test("\u0451194000000", "" + sf_strU + f_I);
+        test("\u04511null", "" + sf_strU + f_IN);
+        test("\u04511true", "" + sf_strU + sf_bl);
+        test("\u045115500", "" + sf_strU + sf_s);
+        test("\u04511-2900", "" + sf_strU + s_sM);
+        test("\u04511-194313216", "" + sf_strU + sf_l);
+        test("\u0451112", "" + sf_strU + s_strU1);
+        test("\u04511C(87)", "" + sf_strU + sf_o);
+        test("\u0451191", "" + sf_strU + s_strU2);
+        test("\u0451121", "" + sf_strU + f_strU1);
+        test("\u0451118", "" + sf_strU + f_strU2);
+        test("\u04511null", "" + sf_strU + f_iAN);
+        test("\u04511null", "" + sf_strU + s_oN);
+        test("\u04511\u045180", "" + sf_strU + s_strU);
+        test("\u04511C", "" + sf_strU + sf_c);
+        test("\u0451175", "" + sf_strU + sf_str);
+        test("\u04511-43", "" + sf_strU + s_bM);
+        test("\u0451180", "" + sf_strU + sf_b);
+        test("\u04511null", "" + sf_strU + s_IN);
+        test("\u04511-52.0", "" + sf_strU + s_fM);
+        test("\u0451175000000", "" + sf_strU + sf_i);
+        test("\u0451144", "" + sf_strU + f_b);
+        test("\u04511-1705032704", "" + sf_strU + sf_lM);
+        test("\u04511null", "" + sf_strU + f_oAN);
+        test("\u0451183.0", "" + sf_strU + f_d);
+        test("\u04511I", "" + sf_strU + f_c);
+        test("\u0451194.0", "" + sf_strU + f_f);
+        test("\u0451112.0", "" + sf_strU + sf_d);
+        test("\u04511-99.0", "" + sf_strU + f_dM);
+        test("\u0451117.0", "" + sf_strU + sf_f);
+        test("\u04511-84.0", "" + sf_strU + sf_dM);
+        test("\u0451158000000", "" + sf_strU + f_i);
+        test("\u04511-55000000", "" + sf_strU + f_iM);
+        test("\u045111460392448", "" + sf_strU + f_l);
+        test("\u04511C(70)", "" + sf_strU + f_o);
+        test("\u04511\u04511", "" + sf_strU + sf_strU);
+        test("\u045118000", "" + sf_strU + f_s);
+        test("\u0451118", "" + sf_strU + s_str);
+        test("\u04511-1000000", "" + sf_strU + s_iM);
+        test("\u045111000000", "" + sf_strU + sf_I);
+        test("\u04511null", "" + sf_strU + f_oNtS);
+        test("\u04511false", "" + sf_strU + f_bl);
+        test("\u04511null", "" + sf_strU + sf_iAN);
+        test("\u04511-2000000", "" + sf_strU + sf_iM);
+        test("\u04511-820130816", "" + sf_strU + f_lM);
+        test("\u04511null", "" + sf_strU + sf_oAN);
+        test("\u0451125000000", "" + sf_strU + s_I);
+        test("8000-96.0", "" + f_s + s_dM);
+        test("8000null", "" + f_s + s_oNtS);
+        test("8000\u045176", "" + f_s + f_strU);
+        test("800092", "" + f_s + sf_strU2);
+        test("800051", "" + f_s + sf_strU1);
+        test("8000null", "" + f_s + s_iAN);
+        test("8000-54", "" + f_s + f_bM);
+        test("8000-87.0", "" + f_s + f_fM);
+        test("8000null", "" + f_s + s_oAN);
+        test("800019", "" + f_s + f_str);
+        test("8000-41", "" + f_s + sf_bM);
+        test("8000null", "" + f_s + sf_IN);
+        test("8000T", "" + f_s + s_c);
+        test("8000-42.0", "" + f_s + sf_fM);
+        test("800025", "" + f_s + s_b);
+        test("8000null", "" + f_s + f_oN);
+        test("8000-1410065408", "" + f_s + s_lM);
+        test("80008.0", "" + f_s + s_d);
+        test("800055.0", "" + f_s + s_f);
+        test("800097000000", "" + f_s + s_i);
+        test("8000-9900", "" + f_s + f_sM);
+        test("8000935228928", "" + f_s + s_l);
+        test("8000-8400", "" + f_s + sf_sM);
+        test("8000C(82)", "" + f_s + s_o);
+        test("8000null", "" + f_s + sf_oNtS);
+        test("8000true", "" + f_s + s_bl);
+        test("80003900", "" + f_s + s_s);
+        test("8000null", "" + f_s + sf_oN);
+        test("800094000000", "" + f_s + f_I);
+        test("8000null", "" + f_s + f_IN);
+        test("8000true", "" + f_s + sf_bl);
+        test("80005500", "" + f_s + sf_s);
+        test("8000-2900", "" + f_s + s_sM);
+        test("8000-194313216", "" + f_s + sf_l);
+        test("800012", "" + f_s + s_strU1);
+        test("8000C(87)", "" + f_s + sf_o);
+        test("800091", "" + f_s + s_strU2);
+        test("800021", "" + f_s + f_strU1);
+        test("800018", "" + f_s + f_strU2);
+        test("8000null", "" + f_s + f_iAN);
+        test("8000null", "" + f_s + s_oN);
+        test("8000\u045180", "" + f_s + s_strU);
+        test("8000C", "" + f_s + sf_c);
+        test("800075", "" + f_s + sf_str);
+        test("8000-43", "" + f_s + s_bM);
+        test("800080", "" + f_s + sf_b);
+        test("8000null", "" + f_s + s_IN);
+        test("8000-52.0", "" + f_s + s_fM);
+        test("800075000000", "" + f_s + sf_i);
+        test("800044", "" + f_s + f_b);
+        test("8000-1705032704", "" + f_s + sf_lM);
+        test("8000null", "" + f_s + f_oAN);
+        test("800083.0", "" + f_s + f_d);
+        test("8000I", "" + f_s + f_c);
+        test("800094.0", "" + f_s + f_f);
+        test("800012.0", "" + f_s + sf_d);
+        test("8000-99.0", "" + f_s + f_dM);
+        test("800017.0", "" + f_s + sf_f);
+        test("8000-84.0", "" + f_s + sf_dM);
+        test("800058000000", "" + f_s + f_i);
+        test("8000-55000000", "" + f_s + f_iM);
+        test("80001460392448", "" + f_s + f_l);
+        test("8000C(70)", "" + f_s + f_o);
+        test("8000\u04511", "" + f_s + sf_strU);
+        test("80008000", "" + f_s + f_s);
+        test("800018", "" + f_s + s_str);
+        test("8000-1000000", "" + f_s + s_iM);
+        test("80001000000", "" + f_s + sf_I);
+        test("8000null", "" + f_s + f_oNtS);
+        test("8000false", "" + f_s + f_bl);
+        test("8000null", "" + f_s + sf_iAN);
+        test("8000-2000000", "" + f_s + sf_iM);
+        test("8000-820130816", "" + f_s + f_lM);
+        test("8000null", "" + f_s + sf_oAN);
+        test("800025000000", "" + f_s + s_I);
+        test("18-96.0", "" + s_str + s_dM);
+        test("18null", "" + s_str + s_oNtS);
+        test("18\u045176", "" + s_str + f_strU);
+        test("1892", "" + s_str + sf_strU2);
+        test("1851", "" + s_str + sf_strU1);
+        test("18null", "" + s_str + s_iAN);
+        test("18-54", "" + s_str + f_bM);
+        test("18-87.0", "" + s_str + f_fM);
+        test("18null", "" + s_str + s_oAN);
+        test("1819", "" + s_str + f_str);
+        test("18-41", "" + s_str + sf_bM);
+        test("18null", "" + s_str + sf_IN);
+        test("18T", "" + s_str + s_c);
+        test("18-42.0", "" + s_str + sf_fM);
+        test("1825", "" + s_str + s_b);
+        test("18null", "" + s_str + f_oN);
+        test("18-1410065408", "" + s_str + s_lM);
+        test("188.0", "" + s_str + s_d);
+        test("1855.0", "" + s_str + s_f);
+        test("1897000000", "" + s_str + s_i);
+        test("18-9900", "" + s_str + f_sM);
+        test("18935228928", "" + s_str + s_l);
+        test("18-8400", "" + s_str + sf_sM);
+        test("18C(82)", "" + s_str + s_o);
+        test("18null", "" + s_str + sf_oNtS);
+        test("18true", "" + s_str + s_bl);
+        test("183900", "" + s_str + s_s);
+        test("18null", "" + s_str + sf_oN);
+        test("1894000000", "" + s_str + f_I);
+        test("18null", "" + s_str + f_IN);
+        test("18true", "" + s_str + sf_bl);
+        test("185500", "" + s_str + sf_s);
+        test("18-2900", "" + s_str + s_sM);
+        test("18-194313216", "" + s_str + sf_l);
+        test("1812", "" + s_str + s_strU1);
+        test("18C(87)", "" + s_str + sf_o);
+        test("1891", "" + s_str + s_strU2);
+        test("1821", "" + s_str + f_strU1);
+        test("1818", "" + s_str + f_strU2);
+        test("18null", "" + s_str + f_iAN);
+        test("18null", "" + s_str + s_oN);
+        test("18\u045180", "" + s_str + s_strU);
+        test("18C", "" + s_str + sf_c);
+        test("1875", "" + s_str + sf_str);
+        test("18-43", "" + s_str + s_bM);
+        test("1880", "" + s_str + sf_b);
+        test("18null", "" + s_str + s_IN);
+        test("18-52.0", "" + s_str + s_fM);
+        test("1875000000", "" + s_str + sf_i);
+        test("1844", "" + s_str + f_b);
+    }
+
+    public void run5() {
+        test("18-1705032704", "" + s_str + sf_lM);
+        test("18null", "" + s_str + f_oAN);
+        test("1883.0", "" + s_str + f_d);
+        test("18I", "" + s_str + f_c);
+        test("1894.0", "" + s_str + f_f);
+        test("1812.0", "" + s_str + sf_d);
+        test("18-99.0", "" + s_str + f_dM);
+        test("1817.0", "" + s_str + sf_f);
+        test("18-84.0", "" + s_str + sf_dM);
+        test("1858000000", "" + s_str + f_i);
+        test("18-55000000", "" + s_str + f_iM);
+        test("181460392448", "" + s_str + f_l);
+        test("18C(70)", "" + s_str + f_o);
+        test("18\u04511", "" + s_str + sf_strU);
+        test("188000", "" + s_str + f_s);
+        test("1818", "" + s_str + s_str);
+        test("18-1000000", "" + s_str + s_iM);
+        test("181000000", "" + s_str + sf_I);
+        test("18null", "" + s_str + f_oNtS);
+        test("18false", "" + s_str + f_bl);
+        test("18null", "" + s_str + sf_iAN);
+        test("18-2000000", "" + s_str + sf_iM);
+        test("18-820130816", "" + s_str + f_lM);
+        test("18null", "" + s_str + sf_oAN);
+        test("1825000000", "" + s_str + s_I);
+        test("-1000000-96.0", "" + s_iM + s_dM);
+        test("-1000000null", "" + s_iM + s_oNtS);
+        test("-1000000\u045176", "" + s_iM + f_strU);
+        test("-100000092", "" + s_iM + sf_strU2);
+        test("-100000051", "" + s_iM + sf_strU1);
+        test("-1000000null", "" + s_iM + s_iAN);
+        test("-1000000-54", "" + s_iM + f_bM);
+        test("-1000000-87.0", "" + s_iM + f_fM);
+        test("-1000000null", "" + s_iM + s_oAN);
+        test("-100000019", "" + s_iM + f_str);
+        test("-1000000-41", "" + s_iM + sf_bM);
+        test("-1000000null", "" + s_iM + sf_IN);
+        test("-1000000T", "" + s_iM + s_c);
+        test("-1000000-42.0", "" + s_iM + sf_fM);
+        test("-100000025", "" + s_iM + s_b);
+        test("-1000000null", "" + s_iM + f_oN);
+        test("-1000000-1410065408", "" + s_iM + s_lM);
+        test("-10000008.0", "" + s_iM + s_d);
+        test("-100000055.0", "" + s_iM + s_f);
+        test("-100000097000000", "" + s_iM + s_i);
+        test("-1000000-9900", "" + s_iM + f_sM);
+        test("-1000000935228928", "" + s_iM + s_l);
+        test("-1000000-8400", "" + s_iM + sf_sM);
+        test("-1000000C(82)", "" + s_iM + s_o);
+        test("-1000000null", "" + s_iM + sf_oNtS);
+        test("-1000000true", "" + s_iM + s_bl);
+        test("-10000003900", "" + s_iM + s_s);
+        test("-1000000null", "" + s_iM + sf_oN);
+        test("-100000094000000", "" + s_iM + f_I);
+        test("-1000000null", "" + s_iM + f_IN);
+        test("-1000000true", "" + s_iM + sf_bl);
+        test("-10000005500", "" + s_iM + sf_s);
+        test("-1000000-2900", "" + s_iM + s_sM);
+        test("-1000000-194313216", "" + s_iM + sf_l);
+        test("-100000012", "" + s_iM + s_strU1);
+        test("-1000000C(87)", "" + s_iM + sf_o);
+        test("-100000091", "" + s_iM + s_strU2);
+        test("-100000021", "" + s_iM + f_strU1);
+        test("-100000018", "" + s_iM + f_strU2);
+        test("-1000000null", "" + s_iM + f_iAN);
+        test("-1000000null", "" + s_iM + s_oN);
+        test("-1000000\u045180", "" + s_iM + s_strU);
+        test("-1000000C", "" + s_iM + sf_c);
+        test("-100000075", "" + s_iM + sf_str);
+        test("-1000000-43", "" + s_iM + s_bM);
+        test("-100000080", "" + s_iM + sf_b);
+        test("-1000000null", "" + s_iM + s_IN);
+        test("-1000000-52.0", "" + s_iM + s_fM);
+        test("-100000075000000", "" + s_iM + sf_i);
+        test("-100000044", "" + s_iM + f_b);
+        test("-1000000-1705032704", "" + s_iM + sf_lM);
+        test("-1000000null", "" + s_iM + f_oAN);
+        test("-100000083.0", "" + s_iM + f_d);
+        test("-1000000I", "" + s_iM + f_c);
+        test("-100000094.0", "" + s_iM + f_f);
+        test("-100000012.0", "" + s_iM + sf_d);
+        test("-1000000-99.0", "" + s_iM + f_dM);
+        test("-100000017.0", "" + s_iM + sf_f);
+        test("-1000000-84.0", "" + s_iM + sf_dM);
+        test("-100000058000000", "" + s_iM + f_i);
+        test("-1000000-55000000", "" + s_iM + f_iM);
+        test("-10000001460392448", "" + s_iM + f_l);
+        test("-1000000C(70)", "" + s_iM + f_o);
+        test("-1000000\u04511", "" + s_iM + sf_strU);
+        test("-10000008000", "" + s_iM + f_s);
+        test("-100000018", "" + s_iM + s_str);
+        test("-1000000-1000000", "" + s_iM + s_iM);
+        test("-10000001000000", "" + s_iM + sf_I);
+        test("-1000000null", "" + s_iM + f_oNtS);
+        test("-1000000false", "" + s_iM + f_bl);
+        test("-1000000null", "" + s_iM + sf_iAN);
+        test("-1000000-2000000", "" + s_iM + sf_iM);
+        test("-1000000-820130816", "" + s_iM + f_lM);
+        test("-1000000null", "" + s_iM + sf_oAN);
+        test("-100000025000000", "" + s_iM + s_I);
+        test("1000000-96.0", "" + sf_I + s_dM);
+        test("1000000null", "" + sf_I + s_oNtS);
+        test("1000000\u045176", "" + sf_I + f_strU);
+        test("100000092", "" + sf_I + sf_strU2);
+        test("100000051", "" + sf_I + sf_strU1);
+        test("1000000null", "" + sf_I + s_iAN);
+        test("1000000-54", "" + sf_I + f_bM);
+        test("1000000-87.0", "" + sf_I + f_fM);
+        test("1000000null", "" + sf_I + s_oAN);
+        test("100000019", "" + sf_I + f_str);
+        test("1000000-41", "" + sf_I + sf_bM);
+        test("1000000null", "" + sf_I + sf_IN);
+        test("1000000T", "" + sf_I + s_c);
+        test("1000000-42.0", "" + sf_I + sf_fM);
+        test("100000025", "" + sf_I + s_b);
+        test("1000000null", "" + sf_I + f_oN);
+        test("1000000-1410065408", "" + sf_I + s_lM);
+        test("10000008.0", "" + sf_I + s_d);
+        test("100000055.0", "" + sf_I + s_f);
+        test("100000097000000", "" + sf_I + s_i);
+        test("1000000-9900", "" + sf_I + f_sM);
+        test("1000000935228928", "" + sf_I + s_l);
+        test("1000000-8400", "" + sf_I + sf_sM);
+        test("1000000C(82)", "" + sf_I + s_o);
+        test("1000000null", "" + sf_I + sf_oNtS);
+        test("1000000true", "" + sf_I + s_bl);
+        test("10000003900", "" + sf_I + s_s);
+        test("1000000null", "" + sf_I + sf_oN);
+        test("100000094000000", "" + sf_I + f_I);
+        test("1000000null", "" + sf_I + f_IN);
+        test("1000000true", "" + sf_I + sf_bl);
+        test("10000005500", "" + sf_I + sf_s);
+        test("1000000-2900", "" + sf_I + s_sM);
+        test("1000000-194313216", "" + sf_I + sf_l);
+        test("100000012", "" + sf_I + s_strU1);
+        test("1000000C(87)", "" + sf_I + sf_o);
+        test("100000091", "" + sf_I + s_strU2);
+        test("100000021", "" + sf_I + f_strU1);
+        test("100000018", "" + sf_I + f_strU2);
+        test("1000000null", "" + sf_I + f_iAN);
+        test("1000000null", "" + sf_I + s_oN);
+        test("1000000\u045180", "" + sf_I + s_strU);
+        test("1000000C", "" + sf_I + sf_c);
+        test("100000075", "" + sf_I + sf_str);
+        test("1000000-43", "" + sf_I + s_bM);
+        test("100000080", "" + sf_I + sf_b);
+        test("1000000null", "" + sf_I + s_IN);
+        test("1000000-52.0", "" + sf_I + s_fM);
+        test("100000075000000", "" + sf_I + sf_i);
+        test("100000044", "" + sf_I + f_b);
+        test("1000000-1705032704", "" + sf_I + sf_lM);
+        test("1000000null", "" + sf_I + f_oAN);
+        test("100000083.0", "" + sf_I + f_d);
+        test("1000000I", "" + sf_I + f_c);
+        test("100000094.0", "" + sf_I + f_f);
+        test("100000012.0", "" + sf_I + sf_d);
+        test("1000000-99.0", "" + sf_I + f_dM);
+        test("100000017.0", "" + sf_I + sf_f);
+        test("1000000-84.0", "" + sf_I + sf_dM);
+        test("100000058000000", "" + sf_I + f_i);
+        test("1000000-55000000", "" + sf_I + f_iM);
+        test("10000001460392448", "" + sf_I + f_l);
+        test("1000000C(70)", "" + sf_I + f_o);
+        test("1000000\u04511", "" + sf_I + sf_strU);
+        test("10000008000", "" + sf_I + f_s);
+        test("100000018", "" + sf_I + s_str);
+        test("1000000-1000000", "" + sf_I + s_iM);
+        test("10000001000000", "" + sf_I + sf_I);
+        test("1000000null", "" + sf_I + f_oNtS);
+        test("1000000false", "" + sf_I + f_bl);
+        test("1000000null", "" + sf_I + sf_iAN);
+        test("1000000-2000000", "" + sf_I + sf_iM);
+        test("1000000-820130816", "" + sf_I + f_lM);
+        test("1000000null", "" + sf_I + sf_oAN);
+        test("100000025000000", "" + sf_I + s_I);
+        test("null-96.0", "" + f_oNtS + s_dM);
+        test("nullnull", "" + f_oNtS + s_oNtS);
+        test("null\u045176", "" + f_oNtS + f_strU);
+        test("null92", "" + f_oNtS + sf_strU2);
+        test("null51", "" + f_oNtS + sf_strU1);
+        test("nullnull", "" + f_oNtS + s_iAN);
+        test("null-54", "" + f_oNtS + f_bM);
+        test("null-87.0", "" + f_oNtS + f_fM);
+        test("nullnull", "" + f_oNtS + s_oAN);
+        test("null19", "" + f_oNtS + f_str);
+        test("null-41", "" + f_oNtS + sf_bM);
+        test("nullnull", "" + f_oNtS + sf_IN);
+        test("nullT", "" + f_oNtS + s_c);
+        test("null-42.0", "" + f_oNtS + sf_fM);
+        test("null25", "" + f_oNtS + s_b);
+        test("nullnull", "" + f_oNtS + f_oN);
+        test("null-1410065408", "" + f_oNtS + s_lM);
+        test("null8.0", "" + f_oNtS + s_d);
+        test("null55.0", "" + f_oNtS + s_f);
+        test("null97000000", "" + f_oNtS + s_i);
+        test("null-9900", "" + f_oNtS + f_sM);
+        test("null935228928", "" + f_oNtS + s_l);
+        test("null-8400", "" + f_oNtS + sf_sM);
+        test("nullC(82)", "" + f_oNtS + s_o);
+        test("nullnull", "" + f_oNtS + sf_oNtS);
+        test("nulltrue", "" + f_oNtS + s_bl);
+        test("null3900", "" + f_oNtS + s_s);
+        test("nullnull", "" + f_oNtS + sf_oN);
+        test("null94000000", "" + f_oNtS + f_I);
+        test("nullnull", "" + f_oNtS + f_IN);
+        test("nulltrue", "" + f_oNtS + sf_bl);
+        test("null5500", "" + f_oNtS + sf_s);
+        test("null-2900", "" + f_oNtS + s_sM);
+        test("null-194313216", "" + f_oNtS + sf_l);
+        test("null12", "" + f_oNtS + s_strU1);
+        test("nullC(87)", "" + f_oNtS + sf_o);
+        test("null91", "" + f_oNtS + s_strU2);
+        test("null21", "" + f_oNtS + f_strU1);
+        test("null18", "" + f_oNtS + f_strU2);
+        test("nullnull", "" + f_oNtS + f_iAN);
+        test("nullnull", "" + f_oNtS + s_oN);
+        test("null\u045180", "" + f_oNtS + s_strU);
+        test("nullC", "" + f_oNtS + sf_c);
+        test("null75", "" + f_oNtS + sf_str);
+        test("null-43", "" + f_oNtS + s_bM);
+        test("null80", "" + f_oNtS + sf_b);
+        test("nullnull", "" + f_oNtS + s_IN);
+        test("null-52.0", "" + f_oNtS + s_fM);
+        test("null75000000", "" + f_oNtS + sf_i);
+        test("null44", "" + f_oNtS + f_b);
+        test("null-1705032704", "" + f_oNtS + sf_lM);
+        test("nullnull", "" + f_oNtS + f_oAN);
+        test("null83.0", "" + f_oNtS + f_d);
+        test("nullI", "" + f_oNtS + f_c);
+        test("null94.0", "" + f_oNtS + f_f);
+        test("null12.0", "" + f_oNtS + sf_d);
+        test("null-99.0", "" + f_oNtS + f_dM);
+        test("null17.0", "" + f_oNtS + sf_f);
+        test("null-84.0", "" + f_oNtS + sf_dM);
+        test("null58000000", "" + f_oNtS + f_i);
+        test("null-55000000", "" + f_oNtS + f_iM);
+        test("null1460392448", "" + f_oNtS + f_l);
+        test("nullC(70)", "" + f_oNtS + f_o);
+        test("null\u04511", "" + f_oNtS + sf_strU);
+        test("null8000", "" + f_oNtS + f_s);
+        test("null18", "" + f_oNtS + s_str);
+        test("null-1000000", "" + f_oNtS + s_iM);
+        test("null1000000", "" + f_oNtS + sf_I);
+        test("nullnull", "" + f_oNtS + f_oNtS);
+        test("nullfalse", "" + f_oNtS + f_bl);
+        test("nullnull", "" + f_oNtS + sf_iAN);
+        test("null-2000000", "" + f_oNtS + sf_iM);
+        test("null-820130816", "" + f_oNtS + f_lM);
+        test("nullnull", "" + f_oNtS + sf_oAN);
+        test("null25000000", "" + f_oNtS + s_I);
+        test("false-96.0", "" + f_bl + s_dM);
+        test("falsenull", "" + f_bl + s_oNtS);
+        test("false\u045176", "" + f_bl + f_strU);
+        test("false92", "" + f_bl + sf_strU2);
+        test("false51", "" + f_bl + sf_strU1);
+        test("falsenull", "" + f_bl + s_iAN);
+        test("false-54", "" + f_bl + f_bM);
+        test("false-87.0", "" + f_bl + f_fM);
+        test("falsenull", "" + f_bl + s_oAN);
+        test("false19", "" + f_bl + f_str);
+        test("false-41", "" + f_bl + sf_bM);
+        test("falsenull", "" + f_bl + sf_IN);
+        test("falseT", "" + f_bl + s_c);
+        test("false-42.0", "" + f_bl + sf_fM);
+        test("false25", "" + f_bl + s_b);
+        test("falsenull", "" + f_bl + f_oN);
+        test("false-1410065408", "" + f_bl + s_lM);
+        test("false8.0", "" + f_bl + s_d);
+        test("false55.0", "" + f_bl + s_f);
+        test("false97000000", "" + f_bl + s_i);
+        test("false-9900", "" + f_bl + f_sM);
+        test("false935228928", "" + f_bl + s_l);
+        test("false-8400", "" + f_bl + sf_sM);
+        test("falseC(82)", "" + f_bl + s_o);
+        test("falsenull", "" + f_bl + sf_oNtS);
+        test("falsetrue", "" + f_bl + s_bl);
+        test("false3900", "" + f_bl + s_s);
+        test("falsenull", "" + f_bl + sf_oN);
+        test("false94000000", "" + f_bl + f_I);
+        test("falsenull", "" + f_bl + f_IN);
+        test("falsetrue", "" + f_bl + sf_bl);
+        test("false5500", "" + f_bl + sf_s);
+        test("false-2900", "" + f_bl + s_sM);
+        test("false-194313216", "" + f_bl + sf_l);
+        test("false12", "" + f_bl + s_strU1);
+        test("falseC(87)", "" + f_bl + sf_o);
+        test("false91", "" + f_bl + s_strU2);
+        test("false21", "" + f_bl + f_strU1);
+        test("false18", "" + f_bl + f_strU2);
+        test("falsenull", "" + f_bl + f_iAN);
+        test("falsenull", "" + f_bl + s_oN);
+        test("false\u045180", "" + f_bl + s_strU);
+        test("falseC", "" + f_bl + sf_c);
+        test("false75", "" + f_bl + sf_str);
+        test("false-43", "" + f_bl + s_bM);
+        test("false80", "" + f_bl + sf_b);
+        test("falsenull", "" + f_bl + s_IN);
+        test("false-52.0", "" + f_bl + s_fM);
+        test("false75000000", "" + f_bl + sf_i);
+        test("false44", "" + f_bl + f_b);
+        test("false-1705032704", "" + f_bl + sf_lM);
+        test("falsenull", "" + f_bl + f_oAN);
+        test("false83.0", "" + f_bl + f_d);
+        test("falseI", "" + f_bl + f_c);
+        test("false94.0", "" + f_bl + f_f);
+        test("false12.0", "" + f_bl + sf_d);
+        test("false-99.0", "" + f_bl + f_dM);
+        test("false17.0", "" + f_bl + sf_f);
+        test("false-84.0", "" + f_bl + sf_dM);
+        test("false58000000", "" + f_bl + f_i);
+        test("false-55000000", "" + f_bl + f_iM);
+        test("false1460392448", "" + f_bl + f_l);
+        test("falseC(70)", "" + f_bl + f_o);
+        test("false\u04511", "" + f_bl + sf_strU);
+        test("false8000", "" + f_bl + f_s);
+        test("false18", "" + f_bl + s_str);
+        test("false-1000000", "" + f_bl + s_iM);
+        test("false1000000", "" + f_bl + sf_I);
+        test("falsenull", "" + f_bl + f_oNtS);
+        test("falsefalse", "" + f_bl + f_bl);
+        test("falsenull", "" + f_bl + sf_iAN);
+        test("false-2000000", "" + f_bl + sf_iM);
+        test("false-820130816", "" + f_bl + f_lM);
+        test("falsenull", "" + f_bl + sf_oAN);
+        test("false25000000", "" + f_bl + s_I);
+        test("null-96.0", "" + sf_iAN + s_dM);
+        test("nullnull", "" + sf_iAN + s_oNtS);
+        test("null\u045176", "" + sf_iAN + f_strU);
+        test("null92", "" + sf_iAN + sf_strU2);
+        test("null51", "" + sf_iAN + sf_strU1);
+        test("nullnull", "" + sf_iAN + s_iAN);
+        test("null-54", "" + sf_iAN + f_bM);
+        test("null-87.0", "" + sf_iAN + f_fM);
+        test("nullnull", "" + sf_iAN + s_oAN);
+        test("null19", "" + sf_iAN + f_str);
+        test("null-41", "" + sf_iAN + sf_bM);
+        test("nullnull", "" + sf_iAN + sf_IN);
+        test("nullT", "" + sf_iAN + s_c);
+        test("null-42.0", "" + sf_iAN + sf_fM);
+        test("null25", "" + sf_iAN + s_b);
+        test("nullnull", "" + sf_iAN + f_oN);
+        test("null-1410065408", "" + sf_iAN + s_lM);
+        test("null8.0", "" + sf_iAN + s_d);
+        test("null55.0", "" + sf_iAN + s_f);
+        test("null97000000", "" + sf_iAN + s_i);
+        test("null-9900", "" + sf_iAN + f_sM);
+        test("null935228928", "" + sf_iAN + s_l);
+        test("null-8400", "" + sf_iAN + sf_sM);
+        test("nullC(82)", "" + sf_iAN + s_o);
+        test("nullnull", "" + sf_iAN + sf_oNtS);
+        test("nulltrue", "" + sf_iAN + s_bl);
+        test("null3900", "" + sf_iAN + s_s);
+        test("nullnull", "" + sf_iAN + sf_oN);
+        test("null94000000", "" + sf_iAN + f_I);
+        test("nullnull", "" + sf_iAN + f_IN);
+        test("nulltrue", "" + sf_iAN + sf_bl);
+        test("null5500", "" + sf_iAN + sf_s);
+        test("null-2900", "" + sf_iAN + s_sM);
+        test("null-194313216", "" + sf_iAN + sf_l);
+        test("null12", "" + sf_iAN + s_strU1);
+        test("nullC(87)", "" + sf_iAN + sf_o);
+        test("null91", "" + sf_iAN + s_strU2);
+        test("null21", "" + sf_iAN + f_strU1);
+        test("null18", "" + sf_iAN + f_strU2);
+        test("nullnull", "" + sf_iAN + f_iAN);
+        test("nullnull", "" + sf_iAN + s_oN);
+        test("null\u045180", "" + sf_iAN + s_strU);
+        test("nullC", "" + sf_iAN + sf_c);
+        test("null75", "" + sf_iAN + sf_str);
+        test("null-43", "" + sf_iAN + s_bM);
+        test("null80", "" + sf_iAN + sf_b);
+        test("nullnull", "" + sf_iAN + s_IN);
+        test("null-52.0", "" + sf_iAN + s_fM);
+        test("null75000000", "" + sf_iAN + sf_i);
+        test("null44", "" + sf_iAN + f_b);
+        test("null-1705032704", "" + sf_iAN + sf_lM);
+        test("nullnull", "" + sf_iAN + f_oAN);
+        test("null83.0", "" + sf_iAN + f_d);
+        test("nullI", "" + sf_iAN + f_c);
+        test("null94.0", "" + sf_iAN + f_f);
+        test("null12.0", "" + sf_iAN + sf_d);
+        test("null-99.0", "" + sf_iAN + f_dM);
+        test("null17.0", "" + sf_iAN + sf_f);
+        test("null-84.0", "" + sf_iAN + sf_dM);
+        test("null58000000", "" + sf_iAN + f_i);
+        test("null-55000000", "" + sf_iAN + f_iM);
+        test("null1460392448", "" + sf_iAN + f_l);
+        test("nullC(70)", "" + sf_iAN + f_o);
+        test("null\u04511", "" + sf_iAN + sf_strU);
+        test("null8000", "" + sf_iAN + f_s);
+        test("null18", "" + sf_iAN + s_str);
+        test("null-1000000", "" + sf_iAN + s_iM);
+        test("null1000000", "" + sf_iAN + sf_I);
+        test("nullnull", "" + sf_iAN + f_oNtS);
+        test("nullfalse", "" + sf_iAN + f_bl);
+        test("nullnull", "" + sf_iAN + sf_iAN);
+        test("null-2000000", "" + sf_iAN + sf_iM);
+        test("null-820130816", "" + sf_iAN + f_lM);
+        test("nullnull", "" + sf_iAN + sf_oAN);
+        test("null25000000", "" + sf_iAN + s_I);
+        test("-2000000-96.0", "" + sf_iM + s_dM);
+        test("-2000000null", "" + sf_iM + s_oNtS);
+        test("-2000000\u045176", "" + sf_iM + f_strU);
+        test("-200000092", "" + sf_iM + sf_strU2);
+        test("-200000051", "" + sf_iM + sf_strU1);
+        test("-2000000null", "" + sf_iM + s_iAN);
+        test("-2000000-54", "" + sf_iM + f_bM);
+        test("-2000000-87.0", "" + sf_iM + f_fM);
+        test("-2000000null", "" + sf_iM + s_oAN);
+        test("-200000019", "" + sf_iM + f_str);
+        test("-2000000-41", "" + sf_iM + sf_bM);
+        test("-2000000null", "" + sf_iM + sf_IN);
+        test("-2000000T", "" + sf_iM + s_c);
+        test("-2000000-42.0", "" + sf_iM + sf_fM);
+        test("-200000025", "" + sf_iM + s_b);
+        test("-2000000null", "" + sf_iM + f_oN);
+        test("-2000000-1410065408", "" + sf_iM + s_lM);
+        test("-20000008.0", "" + sf_iM + s_d);
+        test("-200000055.0", "" + sf_iM + s_f);
+        test("-200000097000000", "" + sf_iM + s_i);
+        test("-2000000-9900", "" + sf_iM + f_sM);
+        test("-2000000935228928", "" + sf_iM + s_l);
+        test("-2000000-8400", "" + sf_iM + sf_sM);
+        test("-2000000C(82)", "" + sf_iM + s_o);
+        test("-2000000null", "" + sf_iM + sf_oNtS);
+        test("-2000000true", "" + sf_iM + s_bl);
+        test("-20000003900", "" + sf_iM + s_s);
+        test("-2000000null", "" + sf_iM + sf_oN);
+        test("-200000094000000", "" + sf_iM + f_I);
+        test("-2000000null", "" + sf_iM + f_IN);
+        test("-2000000true", "" + sf_iM + sf_bl);
+        test("-20000005500", "" + sf_iM + sf_s);
+        test("-2000000-2900", "" + sf_iM + s_sM);
+        test("-2000000-194313216", "" + sf_iM + sf_l);
+        test("-200000012", "" + sf_iM + s_strU1);
+        test("-2000000C(87)", "" + sf_iM + sf_o);
+        test("-200000091", "" + sf_iM + s_strU2);
+        test("-200000021", "" + sf_iM + f_strU1);
+        test("-200000018", "" + sf_iM + f_strU2);
+        test("-2000000null", "" + sf_iM + f_iAN);
+        test("-2000000null", "" + sf_iM + s_oN);
+        test("-2000000\u045180", "" + sf_iM + s_strU);
+        test("-2000000C", "" + sf_iM + sf_c);
+        test("-200000075", "" + sf_iM + sf_str);
+        test("-2000000-43", "" + sf_iM + s_bM);
+        test("-200000080", "" + sf_iM + sf_b);
+        test("-2000000null", "" + sf_iM + s_IN);
+        test("-2000000-52.0", "" + sf_iM + s_fM);
+        test("-200000075000000", "" + sf_iM + sf_i);
+        test("-200000044", "" + sf_iM + f_b);
+        test("-2000000-1705032704", "" + sf_iM + sf_lM);
+        test("-2000000null", "" + sf_iM + f_oAN);
+        test("-200000083.0", "" + sf_iM + f_d);
+        test("-2000000I", "" + sf_iM + f_c);
+        test("-200000094.0", "" + sf_iM + f_f);
+        test("-200000012.0", "" + sf_iM + sf_d);
+        test("-2000000-99.0", "" + sf_iM + f_dM);
+        test("-200000017.0", "" + sf_iM + sf_f);
+        test("-2000000-84.0", "" + sf_iM + sf_dM);
+        test("-200000058000000", "" + sf_iM + f_i);
+        test("-2000000-55000000", "" + sf_iM + f_iM);
+        test("-20000001460392448", "" + sf_iM + f_l);
+        test("-2000000C(70)", "" + sf_iM + f_o);
+        test("-2000000\u04511", "" + sf_iM + sf_strU);
+        test("-20000008000", "" + sf_iM + f_s);
+        test("-200000018", "" + sf_iM + s_str);
+        test("-2000000-1000000", "" + sf_iM + s_iM);
+        test("-20000001000000", "" + sf_iM + sf_I);
+        test("-2000000null", "" + sf_iM + f_oNtS);
+        test("-2000000false", "" + sf_iM + f_bl);
+        test("-2000000null", "" + sf_iM + sf_iAN);
+        test("-2000000-2000000", "" + sf_iM + sf_iM);
+        test("-2000000-820130816", "" + sf_iM + f_lM);
+        test("-2000000null", "" + sf_iM + sf_oAN);
+        test("-200000025000000", "" + sf_iM + s_I);
+        test("-820130816-96.0", "" + f_lM + s_dM);
+        test("-820130816null", "" + f_lM + s_oNtS);
+        test("-820130816\u045176", "" + f_lM + f_strU);
+        test("-82013081692", "" + f_lM + sf_strU2);
+        test("-82013081651", "" + f_lM + sf_strU1);
+        test("-820130816null", "" + f_lM + s_iAN);
+        test("-820130816-54", "" + f_lM + f_bM);
+        test("-820130816-87.0", "" + f_lM + f_fM);
+        test("-820130816null", "" + f_lM + s_oAN);
+        test("-82013081619", "" + f_lM + f_str);
+        test("-820130816-41", "" + f_lM + sf_bM);
+        test("-820130816null", "" + f_lM + sf_IN);
+        test("-820130816T", "" + f_lM + s_c);
+        test("-820130816-42.0", "" + f_lM + sf_fM);
+        test("-82013081625", "" + f_lM + s_b);
+        test("-820130816null", "" + f_lM + f_oN);
+        test("-820130816-1410065408", "" + f_lM + s_lM);
+        test("-8201308168.0", "" + f_lM + s_d);
+        test("-82013081655.0", "" + f_lM + s_f);
+        test("-82013081697000000", "" + f_lM + s_i);
+        test("-820130816-9900", "" + f_lM + f_sM);
+        test("-820130816935228928", "" + f_lM + s_l);
+        test("-820130816-8400", "" + f_lM + sf_sM);
+        test("-820130816C(82)", "" + f_lM + s_o);
+        test("-820130816null", "" + f_lM + sf_oNtS);
+        test("-820130816true", "" + f_lM + s_bl);
+        test("-8201308163900", "" + f_lM + s_s);
+        test("-820130816null", "" + f_lM + sf_oN);
+        test("-82013081694000000", "" + f_lM + f_I);
+        test("-820130816null", "" + f_lM + f_IN);
+        test("-820130816true", "" + f_lM + sf_bl);
+        test("-8201308165500", "" + f_lM + sf_s);
+        test("-820130816-2900", "" + f_lM + s_sM);
+        test("-820130816-194313216", "" + f_lM + sf_l);
+        test("-82013081612", "" + f_lM + s_strU1);
+        test("-820130816C(87)", "" + f_lM + sf_o);
+        test("-82013081691", "" + f_lM + s_strU2);
+        test("-82013081621", "" + f_lM + f_strU1);
+        test("-82013081618", "" + f_lM + f_strU2);
+        test("-820130816null", "" + f_lM + f_iAN);
+        test("-820130816null", "" + f_lM + s_oN);
+        test("-820130816\u045180", "" + f_lM + s_strU);
+        test("-820130816C", "" + f_lM + sf_c);
+        test("-82013081675", "" + f_lM + sf_str);
+        test("-820130816-43", "" + f_lM + s_bM);
+        test("-82013081680", "" + f_lM + sf_b);
+        test("-820130816null", "" + f_lM + s_IN);
+        test("-820130816-52.0", "" + f_lM + s_fM);
+        test("-82013081675000000", "" + f_lM + sf_i);
+        test("-82013081644", "" + f_lM + f_b);
+        test("-820130816-1705032704", "" + f_lM + sf_lM);
+        test("-820130816null", "" + f_lM + f_oAN);
+        test("-82013081683.0", "" + f_lM + f_d);
+        test("-820130816I", "" + f_lM + f_c);
+        test("-82013081694.0", "" + f_lM + f_f);
+        test("-82013081612.0", "" + f_lM + sf_d);
+        test("-820130816-99.0", "" + f_lM + f_dM);
+        test("-82013081617.0", "" + f_lM + sf_f);
+        test("-820130816-84.0", "" + f_lM + sf_dM);
+        test("-82013081658000000", "" + f_lM + f_i);
+        test("-820130816-55000000", "" + f_lM + f_iM);
+        test("-8201308161460392448", "" + f_lM + f_l);
+        test("-820130816C(70)", "" + f_lM + f_o);
+        test("-820130816\u04511", "" + f_lM + sf_strU);
+        test("-8201308168000", "" + f_lM + f_s);
+        test("-82013081618", "" + f_lM + s_str);
+        test("-820130816-1000000", "" + f_lM + s_iM);
+        test("-8201308161000000", "" + f_lM + sf_I);
+        test("-820130816null", "" + f_lM + f_oNtS);
+        test("-820130816false", "" + f_lM + f_bl);
+        test("-820130816null", "" + f_lM + sf_iAN);
+        test("-820130816-2000000", "" + f_lM + sf_iM);
+        test("-820130816-820130816", "" + f_lM + f_lM);
+        test("-820130816null", "" + f_lM + sf_oAN);
+        test("-82013081625000000", "" + f_lM + s_I);
+        test("null-96.0", "" + sf_oAN + s_dM);
+        test("nullnull", "" + sf_oAN + s_oNtS);
+        test("null\u045176", "" + sf_oAN + f_strU);
+        test("null92", "" + sf_oAN + sf_strU2);
+        test("null51", "" + sf_oAN + sf_strU1);
+        test("nullnull", "" + sf_oAN + s_iAN);
+        test("null-54", "" + sf_oAN + f_bM);
+        test("null-87.0", "" + sf_oAN + f_fM);
+        test("nullnull", "" + sf_oAN + s_oAN);
+        test("null19", "" + sf_oAN + f_str);
+        test("null-41", "" + sf_oAN + sf_bM);
+        test("nullnull", "" + sf_oAN + sf_IN);
+        test("nullT", "" + sf_oAN + s_c);
+        test("null-42.0", "" + sf_oAN + sf_fM);
+        test("null25", "" + sf_oAN + s_b);
+        test("nullnull", "" + sf_oAN + f_oN);
+        test("null-1410065408", "" + sf_oAN + s_lM);
+        test("null8.0", "" + sf_oAN + s_d);
+        test("null55.0", "" + sf_oAN + s_f);
+        test("null97000000", "" + sf_oAN + s_i);
+        test("null-9900", "" + sf_oAN + f_sM);
+        test("null935228928", "" + sf_oAN + s_l);
+        test("null-8400", "" + sf_oAN + sf_sM);
+        test("nullC(82)", "" + sf_oAN + s_o);
+        test("nullnull", "" + sf_oAN + sf_oNtS);
+        test("nulltrue", "" + sf_oAN + s_bl);
+        test("null3900", "" + sf_oAN + s_s);
+        test("nullnull", "" + sf_oAN + sf_oN);
+        test("null94000000", "" + sf_oAN + f_I);
+        test("nullnull", "" + sf_oAN + f_IN);
+        test("nulltrue", "" + sf_oAN + sf_bl);
+        test("null5500", "" + sf_oAN + sf_s);
+        test("null-2900", "" + sf_oAN + s_sM);
+        test("null-194313216", "" + sf_oAN + sf_l);
+        test("null12", "" + sf_oAN + s_strU1);
+        test("nullC(87)", "" + sf_oAN + sf_o);
+        test("null91", "" + sf_oAN + s_strU2);
+        test("null21", "" + sf_oAN + f_strU1);
+        test("null18", "" + sf_oAN + f_strU2);
+        test("nullnull", "" + sf_oAN + f_iAN);
+        test("nullnull", "" + sf_oAN + s_oN);
+        test("null\u045180", "" + sf_oAN + s_strU);
+        test("nullC", "" + sf_oAN + sf_c);
+        test("null75", "" + sf_oAN + sf_str);
+        test("null-43", "" + sf_oAN + s_bM);
+        test("null80", "" + sf_oAN + sf_b);
+        test("nullnull", "" + sf_oAN + s_IN);
+        test("null-52.0", "" + sf_oAN + s_fM);
+        test("null75000000", "" + sf_oAN + sf_i);
+        test("null44", "" + sf_oAN + f_b);
+        test("null-1705032704", "" + sf_oAN + sf_lM);
+        test("nullnull", "" + sf_oAN + f_oAN);
+        test("null83.0", "" + sf_oAN + f_d);
+        test("nullI", "" + sf_oAN + f_c);
+        test("null94.0", "" + sf_oAN + f_f);
+        test("null12.0", "" + sf_oAN + sf_d);
+        test("null-99.0", "" + sf_oAN + f_dM);
+        test("null17.0", "" + sf_oAN + sf_f);
+        test("null-84.0", "" + sf_oAN + sf_dM);
+        test("null58000000", "" + sf_oAN + f_i);
+        test("null-55000000", "" + sf_oAN + f_iM);
+        test("null1460392448", "" + sf_oAN + f_l);
+        test("nullC(70)", "" + sf_oAN + f_o);
+        test("null\u04511", "" + sf_oAN + sf_strU);
+        test("null8000", "" + sf_oAN + f_s);
+        test("null18", "" + sf_oAN + s_str);
+        test("null-1000000", "" + sf_oAN + s_iM);
+        test("null1000000", "" + sf_oAN + sf_I);
+        test("nullnull", "" + sf_oAN + f_oNtS);
+        test("nullfalse", "" + sf_oAN + f_bl);
+        test("nullnull", "" + sf_oAN + sf_iAN);
+        test("null-2000000", "" + sf_oAN + sf_iM);
+        test("null-820130816", "" + sf_oAN + f_lM);
+        test("nullnull", "" + sf_oAN + sf_oAN);
+        test("null25000000", "" + sf_oAN + s_I);
+        test("25000000-96.0", "" + s_I + s_dM);
+        test("25000000null", "" + s_I + s_oNtS);
+        test("25000000\u045176", "" + s_I + f_strU);
+        test("2500000092", "" + s_I + sf_strU2);
+        test("2500000051", "" + s_I + sf_strU1);
+        test("25000000null", "" + s_I + s_iAN);
+        test("25000000-54", "" + s_I + f_bM);
+        test("25000000-87.0", "" + s_I + f_fM);
+        test("25000000null", "" + s_I + s_oAN);
+        test("2500000019", "" + s_I + f_str);
+        test("25000000-41", "" + s_I + sf_bM);
+        test("25000000null", "" + s_I + sf_IN);
+        test("25000000T", "" + s_I + s_c);
+        test("25000000-42.0", "" + s_I + sf_fM);
+        test("2500000025", "" + s_I + s_b);
+        test("25000000null", "" + s_I + f_oN);
+        test("25000000-1410065408", "" + s_I + s_lM);
+        test("250000008.0", "" + s_I + s_d);
+        test("2500000055.0", "" + s_I + s_f);
+        test("2500000097000000", "" + s_I + s_i);
+        test("25000000-9900", "" + s_I + f_sM);
+        test("25000000935228928", "" + s_I + s_l);
+        test("25000000-8400", "" + s_I + sf_sM);
+        test("25000000C(82)", "" + s_I + s_o);
+        test("25000000null", "" + s_I + sf_oNtS);
+        test("25000000true", "" + s_I + s_bl);
+        test("250000003900", "" + s_I + s_s);
+        test("25000000null", "" + s_I + sf_oN);
+        test("2500000094000000", "" + s_I + f_I);
+        test("25000000null", "" + s_I + f_IN);
+        test("25000000true", "" + s_I + sf_bl);
+        test("250000005500", "" + s_I + sf_s);
+        test("25000000-2900", "" + s_I + s_sM);
+        test("25000000-194313216", "" + s_I + sf_l);
+        test("2500000012", "" + s_I + s_strU1);
+        test("25000000C(87)", "" + s_I + sf_o);
+        test("2500000091", "" + s_I + s_strU2);
+        test("2500000021", "" + s_I + f_strU1);
+        test("2500000018", "" + s_I + f_strU2);
+        test("25000000null", "" + s_I + f_iAN);
+        test("25000000null", "" + s_I + s_oN);
+        test("25000000\u045180", "" + s_I + s_strU);
+        test("25000000C", "" + s_I + sf_c);
+        test("2500000075", "" + s_I + sf_str);
+        test("25000000-43", "" + s_I + s_bM);
+        test("2500000080", "" + s_I + sf_b);
+        test("25000000null", "" + s_I + s_IN);
+        test("25000000-52.0", "" + s_I + s_fM);
+        test("2500000075000000", "" + s_I + sf_i);
+        test("2500000044", "" + s_I + f_b);
+        test("25000000-1705032704", "" + s_I + sf_lM);
+        test("25000000null", "" + s_I + f_oAN);
+        test("2500000083.0", "" + s_I + f_d);
+        test("25000000I", "" + s_I + f_c);
+        test("2500000094.0", "" + s_I + f_f);
+        test("2500000012.0", "" + s_I + sf_d);
+        test("25000000-99.0", "" + s_I + f_dM);
+        test("2500000017.0", "" + s_I + sf_f);
+        test("25000000-84.0", "" + s_I + sf_dM);
+        test("2500000058000000", "" + s_I + f_i);
+        test("25000000-55000000", "" + s_I + f_iM);
+        test("250000001460392448", "" + s_I + f_l);
+        test("25000000C(70)", "" + s_I + f_o);
+        test("25000000\u04511", "" + s_I + sf_strU);
+        test("250000008000", "" + s_I + f_s);
+        test("2500000018", "" + s_I + s_str);
+        test("25000000-1000000", "" + s_I + s_iM);
+        test("250000001000000", "" + s_I + sf_I);
+        test("25000000null", "" + s_I + f_oNtS);
+        test("25000000false", "" + s_I + f_bl);
+        test("25000000null", "" + s_I + sf_iAN);
+        test("25000000-2000000", "" + s_I + sf_iM);
+        test("25000000-820130816", "" + s_I + f_lM);
+        test("25000000null", "" + s_I + sf_oAN);
+        test("2500000025000000", "" + s_I + s_I);
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/Thread/ITLConstructor.java b/ojluni/src/test/java/lang/Thread/ITLConstructor.java
new file mode 100644
index 0000000..97040f9
--- /dev/null
+++ b/ojluni/src/test/java/lang/Thread/ITLConstructor.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Basic test for Thread(ThreadGroup,Runnable,String,long,boolean)
+ */
+package test.java.lang.Thread;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ITLConstructor {
+
+    static InheritableThreadLocal<Integer> n = new InheritableThreadLocal<>() {
+        protected Integer initialValue() {
+            return 0;
+        }
+
+        protected Integer childValue(Integer parentValue) {
+            return parentValue + 1;
+        }
+    };
+
+    static final int CHILD_THREAD_COUNT = 10;
+
+    @Test
+    public static void testInheritableThreadLocal_inherit() throws Exception {
+        test(true);
+    }
+
+    @Test
+    public static void testInheritableThreadLocal_notInherit() throws Exception {
+        test(false);
+    }
+
+    static void test(boolean inherit) throws Exception {
+        // concurrent access to separate indexes is ok
+        int[] x = new int[CHILD_THREAD_COUNT];
+        Thread child = new Thread(Thread.currentThread().getThreadGroup(),
+                new AnotherRunnable(0, x, inherit),
+                "ITLConstructor-thread-" + (0),
+                0,
+                inherit);
+        child.start();
+        child.join(); // waits for *all* threads to complete
+
+        // Check results
+        for (int i = 0; i < CHILD_THREAD_COUNT; i++) {
+            int expectedValue = 1;
+            if (inherit) {
+                expectedValue = i + 1;
+            }
+
+            Assert.assertEquals(x[i], expectedValue, "Got x[" + i + "] = " + x[i]
+                        + ", expected: " + expectedValue);
+        }
+    }
+
+    static class AnotherRunnable implements Runnable {
+
+        final int threadId;
+        final int[] x;
+        final boolean inherit;
+
+        AnotherRunnable(int threadId, int[] x, boolean inherit) {
+            this.threadId = threadId;
+            this.x = x;
+            this.inherit = inherit;
+        }
+
+        public void run() {
+            int itlValue = n.get();
+
+            if (threadId < CHILD_THREAD_COUNT - 1) {
+                Thread child = new Thread(Thread.currentThread().getThreadGroup(),
+                        new AnotherRunnable(threadId + 1, x, inherit),
+                        "ITLConstructor-thread-" + (threadId + 1),
+                        0,
+                        inherit);
+                child.start();
+                try {
+                    child.join();
+                } catch (InterruptedException e) {
+                    throw (new RuntimeException("Interrupted", e));
+                }
+            }
+
+            x[threadId] = itlValue + 1;
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/ArrayConstructorTest.java b/ojluni/src/test/java/lang/invoke/ArrayConstructorTest.java
new file mode 100644
index 0000000..ff81bb6
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/ArrayConstructorTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8155106
+ * @run testng/othervm -ea -esa test.java.lang.invoke.ArrayConstructorTest
+ */
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+
+public class ArrayConstructorTest {
+
+    static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    @Test
+    public static void testFindConstructorArray() {
+        boolean caught = false;
+        try {
+            MethodHandle h = LOOKUP.findConstructor(Object[].class, methodType(void.class));
+        } catch (NoSuchMethodException nsme) {
+            assertEquals("no constructor for array class: [Ljava.lang.Object;", nsme.getMessage());
+            caught = true;
+        } catch (Exception e) {
+            throw new AssertionError("unexpected exception: " + e);
+        }
+        assertTrue(caught);
+    }
+
+    @DataProvider
+    static Object[][] arrayConstructorNegative() {
+        return new Object[][]{
+                {String.class, IllegalArgumentException.class, "not an array class: java.lang.String"},
+                {null, NullPointerException.class, null}
+        };
+    }
+
+    @Test(dataProvider = "arrayConstructorNegative")
+    public static void testArrayConstructorNegative(Class<?> clazz, Class<?> exceptionClass, String message) {
+        boolean caught = false;
+        try {
+            MethodHandle h = MethodHandles.arrayConstructor(clazz);
+        } catch (Exception e) {
+            assertEquals(exceptionClass, e.getClass());
+            if (message != null) {
+                assertEquals(message, e.getMessage());
+            }
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public static void testArrayConstructor() throws Throwable {
+        MethodHandle h = MethodHandles.arrayConstructor(String[].class);
+        assertEquals(methodType(String[].class, int.class), h.type());
+        String[] a = (String[]) h.invoke(17);
+        assertEquals(17, a.length);
+    }
+
+    @Test(expectedExceptions = {NegativeArraySizeException.class})
+    public static void testArrayConstructorNegativeIndex() throws Throwable {
+        MethodHandle h = MethodHandles.arrayConstructor(String[].class);
+        assertEquals(methodType(String[].class, int.class), h.type());
+        h.invoke(-1); // throws exception
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/ArrayLengthTest.java b/ojluni/src/test/java/lang/invoke/ArrayLengthTest.java
new file mode 100644
index 0000000..2d4bfbe
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/ArrayLengthTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @run testng/othervm -ea -esa test.java.lang.invoke.ArrayLengthTest
+ */
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+public class ArrayLengthTest {
+
+    @DataProvider
+    Object[][] arrayClasses() {
+        return new Object[][] {
+                {int[].class},
+                {long[].class},
+                {float[].class},
+                {double[].class},
+                {boolean[].class},
+                {byte[].class},
+                {short[].class},
+                {char[].class},
+                {Object[].class},
+                {StringBuffer[].class}
+        };
+    }
+
+    @Test(dataProvider = "arrayClasses")
+    public void testArrayLength(Class<?> arrayClass) throws Throwable {
+        MethodHandle arrayLength = MethodHandles.arrayLength(arrayClass);
+        assertEquals(int.class, arrayLength.type().returnType());
+        assertEquals(arrayClass, arrayLength.type().parameterType(0));
+        Object array = MethodHandles.arrayConstructor(arrayClass).invoke(10);
+        assertEquals(10, arrayLength.invoke(array));
+    }
+
+    @Test(dataProvider = "arrayClasses", expectedExceptions = NullPointerException.class)
+    public void testArrayLengthInvokeNPE(Class<?> arrayClass) throws Throwable {
+        MethodHandle arrayLength = MethodHandles.arrayLength(arrayClass);
+        arrayLength.invoke(null);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testArrayLengthNoArray() {
+        MethodHandles.arrayLength(String.class);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testArrayLengthNPE() {
+        MethodHandles.arrayLength(null);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullReference() throws Throwable {
+        MethodHandle arrayLength = MethodHandles.arrayLength(String[].class);
+        int len = (int)arrayLength.invokeExact((String[])null);
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/ConstantIdentityMHTest.java b/ojluni/src/test/java/lang/invoke/ConstantIdentityMHTest.java
new file mode 100644
index 0000000..a80e30e
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/ConstantIdentityMHTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @run testng/othervm -ea -esa test.java.lang.invoke.ConstantIdentityMHTest
+ */
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.List;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.*;
+
+public class ConstantIdentityMHTest {
+
+    @DataProvider(name = "testZeroData")
+    private Object[][] testZeroData() {
+       return new Object[][] {
+           {void.class, "()void"},
+           {int.class, "()int"},
+           {byte.class, "()byte"},
+           {short.class, "()short"},
+           {long.class, "()long"},
+           {float.class, "()float"},
+           {double.class, "()double"},
+           {boolean.class, "()boolean"},
+           {char.class, "()char"},
+           {Integer.class, "()Integer"}
+       };
+    }
+
+    @Test(dataProvider = "testZeroData")
+    public void testZero(Class<?> expectedtype, String expected) throws Throwable {
+        assertEquals(MethodHandles.zero(expectedtype).type().toString(), expected);
+    }
+
+    @Test
+    @ExpectedExceptions(NullPointerException.class)
+    public void testZeroNPE() {
+        MethodHandle mh = MethodHandles.zero(null);
+    }
+
+    @Test
+    void testEmpty() throws Throwable {
+        MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class));
+        assertEquals("xy", (String)cat.invoke("x","y"));
+        MethodHandle mhEmpty = MethodHandles.empty(cat.type());
+        assertEquals(null, (String)mhEmpty.invoke("x","y"));
+    }
+
+    @Test
+    @ExpectedExceptions(NullPointerException.class)
+    void testEmptyNPE() {
+        MethodHandle lenEmptyMH = MethodHandles.empty(null);
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/CountedLoopIterationCountsTest.java b/ojluni/src/test/java/lang/invoke/CountedLoopIterationCountsTest.java
new file mode 100644
index 0000000..8520808
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/CountedLoopIterationCountsTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8164102
+ * @run main/othervm -ea -esa test.java.lang.invoke.CountedLoopIterationCountsTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+public class CountedLoopIterationCountsTest {
+
+    public static void main(String[] args) throws Throwable {
+        run(1, -10, 0);
+        run(1, 0, 0);
+        run(Integer.MAX_VALUE - 1, Integer.MIN_VALUE + 10, 0);
+        run(Integer.MIN_VALUE, Integer.MIN_VALUE + 4, 4);
+        run(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1, 1);
+        run(Integer.MAX_VALUE - 1, 0, 0);
+        run(Integer.MAX_VALUE - 1, 10, 0);
+        run(Integer.MAX_VALUE - 1, -10, 0);
+        run(Integer.MAX_VALUE, Integer.MIN_VALUE + 10, 0);
+        run(Integer.MAX_VALUE - 1, Integer.MAX_VALUE, 1);
+        run(Integer.MAX_VALUE, Integer.MAX_VALUE, 0);
+
+        if (failed) {
+            throw new AssertionError("one or more tests failed");
+        }
+    }
+
+    static boolean failed = false;
+
+    private static void run(int start, int end, int expectedIterations) throws Throwable {
+        System.out.println("run from " + start + " to " + end);
+        MethodHandle loop = MethodHandles.countedLoop(
+                MethodHandles.constant(int.class, start), // iterate from given start (inclusive) ...
+                MethodHandles.constant(int.class, end),   // ... to given end (exclusive)
+                MH_m1,                                    // initialise loop variable to -1
+                MH_step);                                 // increment loop counter by one in each iteration
+        // The loop variable's value, and hence the loop result, will be "number of iterations" minus one.
+        int r = (int) loop.invoke();
+        if (r + 1 != expectedIterations) {
+            System.out.println("expected " + expectedIterations + " iterations, but got " + r);
+            failed = true;
+        }
+    }
+
+    static int step(int stepCount, int counter) {
+        return stepCount + 1;
+    }
+
+    static final MethodHandle MH_m1;
+    static final MethodHandle MH_step;
+    static {
+        try {
+            MH_m1 = MethodHandles.constant(int.class, -1);
+            MH_step = MethodHandles.lookup().findStatic(CountedLoopIterationCountsTest.class, "step",
+                    MethodType.methodType(int.class, int.class, int.class));
+        } catch (Throwable t) {
+            throw new ExceptionInInitializerError(t);
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/DropArgumentsTest.java b/ojluni/src/test/java/lang/invoke/DropArgumentsTest.java
new file mode 100644
index 0000000..be65b39
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/DropArgumentsTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug  8158169
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @run testng test.java.lang.invoke.DropArgumentsTest
+ */
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Collections;
+import java.util.List;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.*;
+
+public class DropArgumentsTest {
+
+    @Test
+    public void testDropArgumentsToMatch() throws Throwable {
+        MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class));
+        MethodType bigType = cat.type().insertParameterTypes(0, String.class, String.class, int.class);
+        MethodHandle d0 = MethodHandles.dropArgumentsToMatch(cat, 0, bigType.parameterList(), 3);
+        assertEquals("xy",(String)d0.invokeExact("m", "n", 1, "x", "y"));
+        MethodHandle d1 = MethodHandles.dropArgumentsToMatch(cat, 0, bigType.parameterList(), 0);
+        assertEquals("mn",(String)d1.invokeExact("m", "n", 1, "x", "y"));
+        MethodHandle d2 = MethodHandles.dropArgumentsToMatch(cat, 1, bigType.parameterList(), 4);
+        assertEquals("xy",(String)d2.invokeExact("x", "b", "c", 1, "a", "y"));
+
+    }
+
+    @DataProvider(name = "dropArgumentsToMatchNPEData")
+    private Object[][] dropArgumentsToMatchNPEData()
+            throws NoSuchMethodException, IllegalAccessException {
+        MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class));
+        return new Object[][] {
+                { (MethodHandle) null, 0, cat.type().parameterList(), 0 },
+                { cat, 0, null, 0 }
+        };
+    }
+
+    @Test(dataProvider = "dropArgumentsToMatchNPEData")
+    @ExpectedExceptions(NullPointerException.class)
+    public void dropArgumentsToMatchNPE(MethodHandle target, int pos, List<Class<?>> valueType, int skip) {
+        MethodHandles.dropArgumentsToMatch(target, pos, valueType , skip);
+    }
+
+    @DataProvider(name = "dropArgumentsToMatchIAEData")
+    private Object[][] dropArgumentsToMatchIAEData()
+        throws NoSuchMethodException, IllegalAccessException {
+        MethodHandle cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class));
+        MethodType bigType = cat.type().insertParameterTypes(0, String.class, String.class, int.class);
+        return new Object[][] {
+            {cat, -1, bigType.parameterList(), 0},
+            {cat, 0, bigType.parameterList(), -1},
+            {cat, 3, bigType.parameterList(), 0},
+            {cat, 0, bigType.parameterList(), 6},
+            {cat, 0, bigType.parameterList(), 2}
+        };
+    }
+
+    @Test(dataProvider = "dropArgumentsToMatchIAEData")
+    @ExpectedExceptions(IllegalArgumentException.class)
+    public void dropArgumentsToMatchIAE(MethodHandle target, int pos, List<Class<?>> valueType, int skip) {
+        MethodHandles.dropArgumentsToMatch(target, pos, valueType , skip);
+    }
+
+    @Test
+    @ExpectedExceptions(IllegalArgumentException.class)
+    public void dropArgumentsToMatchTestWithVoid() throws Throwable {
+        MethodHandle cat = lookup().findVirtual(String.class, "concat",
+                                   MethodType.methodType(String.class, String.class));
+        MethodType bigTypewithVoid = cat.type().insertParameterTypes(0, void.class, String.class, int.class);
+        MethodHandle handle2 = MethodHandles.dropArgumentsToMatch(cat, 0, bigTypewithVoid.parameterList(), 1);
+    }
+
+    public static class MethodSet {
+
+        static void mVoid() {
+
+        }
+
+        static void mVoid(int t) {
+
+        }
+    }
+
+    @Test
+    public void dropArgumentsToMatchPosSkipRange() throws Throwable {
+        // newTypes.size() == 1, pos == 1   &&   target.paramSize() == 0, skip == 0
+        MethodHandle mh1 = MethodHandles.lookup().findStatic(MethodSet.class, "mVoid",
+                                                             MethodType.methodType(void.class));
+        MethodHandle handle1 = dropArgumentsToMatch(mh1, 0, Collections.singletonList(int.class), 1);
+        assertEquals(1, handle1.type().parameterList().size());
+
+        // newTypes.size() == 1, pos == 0   &&   target.paramSize() == 1, skip == 1
+        MethodHandle mh2 = MethodHandles.lookup().findStatic(MethodSet.class, "mVoid",
+                                                             MethodType.methodType(void.class, int.class));
+        MethodHandle handle2 = dropArgumentsToMatch(mh2, 1, Collections.singletonList(int.class), 0);
+        assertEquals(2, handle2.type().parameterList().size());
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/ExplicitCastArgumentsTest.java b/ojluni/src/test/java/lang/invoke/ExplicitCastArgumentsTest.java
new file mode 100644
index 0000000..2584e45
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/ExplicitCastArgumentsTest.java
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package name for grouping tests.
+package test.java.lang.invoke;
+
+import sun.invoke.util.Wrapper;
+import test.java.lang.invoke.lib.Helper;
+
+import java.io.File;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+// Android-added: for @Test annotating test methods.
+import org.testng.*;
+import org.testng.annotations.*;
+
+/*
+ * @test
+ * @bug 8060483 8066746
+ * @key randomness
+ * @library /lib/testlibrary /java/lang/invoke/common
+ * @modules java.base/sun.invoke.util
+ * @summary unit tests for MethodHandles.explicitCastArguments()
+ * @run main ExplicitCastArgumentsTest
+ */
+
+/**
+ * Tests for MethodHandles.explicitCastArguments().
+ */
+public class ExplicitCastArgumentsTest {
+
+    private static final boolean VERBOSE = Helper.IS_VERBOSE;
+    private static final Class<?> THIS_CLASS = ExplicitCastArgumentsTest.class;
+    private static final Random RNG = Helper.RNG;
+    private static final Map<Wrapper, Object> RANDOM_VALUES = new HashMap<>(9);
+
+    static {
+        RANDOM_VALUES.put(Wrapper.BOOLEAN, RNG.nextBoolean());
+        RANDOM_VALUES.put(Wrapper.BYTE, (byte) RNG.nextInt());
+        RANDOM_VALUES.put(Wrapper.SHORT, (short) RNG.nextInt());
+        RANDOM_VALUES.put(Wrapper.CHAR, (char) RNG.nextInt());
+        RANDOM_VALUES.put(Wrapper.INT, RNG.nextInt());
+        RANDOM_VALUES.put(Wrapper.LONG, RNG.nextLong());
+        RANDOM_VALUES.put(Wrapper.FLOAT, RNG.nextFloat());
+        RANDOM_VALUES.put(Wrapper.DOUBLE, RNG.nextDouble());
+        RANDOM_VALUES.put(Wrapper.OBJECT, new Object());
+    }
+
+    public static void main(String[] args) throws Throwable {
+        testVarargsCollector();
+        testNullRef2Prim();
+        testRef2Prim();
+        testPrim2Ref();
+        testPrim2Prim();
+        testNonBCPRef2NonBCPRef();
+        testBCPRef2BCPRef();
+        testNonBCPRef2BCPRef();
+        testReturnAny2Void();
+        testReturnVoid2Any();
+        testMultipleArgs();
+        System.out.println("TEST PASSED");
+    }
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample method used in {@link #testVarargsCollector} test to form a method
+     * handle.
+     *
+     * @param args - any args
+     * @return - returns args
+     */
+    public static String[] f(String... args) {
+        return args;
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests that MHs.explicitCastArguments does incorrect type checks for
+     * VarargsCollector. Bug 8066746.
+     *
+     * @throws java.lang.Throwable
+     */
+    public static void testVarargsCollector() throws Throwable {
+        MethodType mt = MethodType.methodType(String[].class, String[].class);
+        MethodHandle mh = MethodHandles.publicLookup()
+                .findStatic(THIS_CLASS, "f", mt);
+        mh = MethodHandles.explicitCastArguments(mh,
+                MethodType.methodType(Object.class, Object.class));
+        mh.invokeWithArguments((Object) (new String[]{"str1", "str2"}));
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests that null wrapper reference is successfully converted to primitive
+     * types. Converted result should be zero for a primitive. Bug 8060483.
+     */
+    public static void testNullRef2Prim() {
+        for (Wrapper from : Wrapper.values()) {
+            for (Wrapper to : Wrapper.values()) {
+                if (from == Wrapper.VOID || to == Wrapper.VOID) {
+                    continue;
+                }
+                // MHs.eCA javadoc:
+                //    If T0 is a reference and T1 a primitive, and if the reference
+                //    is null at runtime, a zero value is introduced.
+                for (TestConversionMode mode : TestConversionMode.values()) {
+                    testConversion(mode, from.wrapperType(),
+                            to.primitiveType(), null, to.zero(), false, null);
+                }
+            }
+        }
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests that non-null wrapper reference is successfully converted to
+     * primitive types.
+     */
+    public static void testRef2Prim() {
+        for (Wrapper from : Wrapper.values()) {
+            for (Wrapper to : Wrapper.values()) {
+                if (from == Wrapper.VOID || to == Wrapper.VOID
+                        || to == Wrapper.OBJECT) {
+                    continue;
+                }
+                Object value = RANDOM_VALUES.get(from);
+                for (TestConversionMode mode : TestConversionMode.values()) {
+                    if (from != Wrapper.OBJECT) {
+                        Object convValue = to.wrap(value);
+                        testConversion(mode, from.wrapperType(),
+                                to.primitiveType(), value, convValue, false, null);
+                    } else {
+                        testConversion(mode, from.wrapperType(),
+                                to.primitiveType(), value, null,
+                                true, ClassCastException.class);
+                    }
+                }
+            }
+        }
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests that primitive is successfully converted to wrapper reference
+     * types, to the Number type (if possible) and to the Object type.
+     */
+    public static void testPrim2Ref() {
+        for (Wrapper from : Wrapper.values()) {
+            for (Wrapper to : Wrapper.values()) {
+                if (from == Wrapper.VOID || from == Wrapper.OBJECT
+                        || to == Wrapper.VOID || to == Wrapper.OBJECT) {
+                    continue;
+                }
+                Object value = RANDOM_VALUES.get(from);
+                for (TestConversionMode mode : TestConversionMode.values()) {
+                    if (from == to) {
+                        testConversion(mode, from.primitiveType(),
+                                to.wrapperType(), value, value, false, null);
+                    } else {
+                        testConversion(mode, from.primitiveType(),
+                                to.wrapperType(), value, null, true, ClassCastException.class);
+                    }
+                    if (from != Wrapper.BOOLEAN && from != Wrapper.CHAR) {
+                        testConversion(mode, from.primitiveType(),
+                                Number.class, value, value, false, null);
+                    } else {
+                        testConversion(mode, from.primitiveType(),
+                                Number.class, value, null,
+                                true, ClassCastException.class);
+                    }
+                    testConversion(mode, from.primitiveType(),
+                            Object.class, value, value, false, null);
+                }
+            }
+        }
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests that primitive is successfully converted to other primitive type.
+     */
+    public static void testPrim2Prim() {
+        for (Wrapper from : Wrapper.values()) {
+            for (Wrapper to : Wrapper.values()) {
+                if (from == Wrapper.VOID || to == Wrapper.VOID
+                        || from == Wrapper.OBJECT || to == Wrapper.OBJECT) {
+                    continue;
+                }
+                Object value = RANDOM_VALUES.get(from);
+                Object convValue = to.wrap(value);
+                for (TestConversionMode mode : TestConversionMode.values()) {
+                    testConversion(mode, from.primitiveType(),
+                            to.primitiveType(), value, convValue, false, null);
+                }
+            }
+        }
+    }
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample interface for {@link #testNonBCPRef2Ref} test.
+     */
+    public static interface TestInterface {}
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample class for {@link #testNonBCPRef2Ref} test.
+     */
+    public static class TestSuperClass implements TestInterface {}
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample class for {@link #testNonBCPRef2Ref} test.
+     */
+    public static class TestSubClass1 extends TestSuperClass {}
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample class for {@link #testNonBCPRef2Ref} test.
+     */
+    public static class TestSubClass2 extends TestSuperClass {}
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests non-bootclasspath reference to reference conversions.
+     *
+     * @throws java.lang.Throwable
+     */
+    public static void testNonBCPRef2NonBCPRef() throws Throwable {
+        Class testInterface = TestInterface.class;
+        Class testSuperClass = TestSuperClass.class;
+        Class testSubClass1 = TestSubClass1.class;
+        Class testSubClass2 = TestSubClass2.class;
+        Object testSuperObj = new TestSuperClass();
+        Object testObj01 = new TestSubClass1();
+        Object testObj02 = new TestSubClass2();
+        Class[] parents = {testInterface, testSuperClass};
+        Class[] children = {testSubClass1, testSubClass2};
+        Object[] childInst = {testObj01, testObj02};
+        for (TestConversionMode mode : TestConversionMode.values()) {
+            for (Class parent : parents) {
+                for (int j = 0; j < children.length; j++) {
+                    // Android-changed: spelling fix in next comment.
+                    // Child type to parent type non-null conversion, should succeed
+                    testConversion(mode, children[j], parent, childInst[j],
+                            childInst[j], false, null);
+                    // Android-changed: spelling fix in next comment.
+                    // Child type to parent type null conversion, should succeed
+                    testConversion(mode, children[j], parent, null,
+                            null, false, null);
+                    // Parent type to child type non-null conversion with parent
+                    // type instance, should fail
+                    testConversion(mode, parent, children[j], testSuperObj,
+                            null, true, ClassCastException.class);
+                    // Parent type to child type non-null conversion with child
+                    // type instance, should succeed
+                    testConversion(mode, parent, children[j], childInst[j],
+                            childInst[j], false, null);
+                    // Parent type to child type null conversion, should succeed
+                    testConversion(mode, parent, children[j], null,
+                            null, false, null);
+                }
+                // Parent type to child type non-null conversion with sibling
+                // type instance, should fail
+                testConversion(mode, parent, testSubClass1, testObj02,
+                        null, true, ClassCastException.class);
+            }
+            // Sibling type non-null conversion, should fail
+            testConversion(mode, testSubClass1,
+                    testSubClass2, testObj01, null, true,
+                    ClassCastException.class);
+            // Sibling type null conversion, should succeed
+            testConversion(mode, testSubClass1,
+                    testSubClass2, null, null, false, null);
+        }
+    }
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample interface for {@link #testNonBCPRef2BCPRef} test.
+     */
+    public static interface TestSerializableInterface extends Serializable {}
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample class for {@link #testNonBCPRef2BCPRef} test.
+     */
+    public static class TestSerializableClass
+            implements TestSerializableInterface {}
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample class for {@link #testNonBCPRef2BCPRef} test.
+     */
+    public static class TestFileChildClass extends File
+            implements TestSerializableInterface {
+        public TestFileChildClass(String pathname) {
+            super(pathname);
+        }
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests non-bootclasspath reference to bootclasspath reference conversions
+     * and vice-versa.
+     *
+     * @throws java.lang.Throwable
+     */
+    public static void testNonBCPRef2BCPRef() throws Throwable {
+        Class bcpInterface = Serializable.class;
+        Class bcpSuperClass = File.class;
+        Class nonBcpInterface = TestSerializableInterface.class;
+        Class nonBcpSuperSiblingClass = TestSerializableClass.class;
+        Class nonBcpSubClass = TestFileChildClass.class;
+        Object bcpSuperObj = new File(".");
+        Object testSuperSiblingObj = new TestSerializableClass();
+        Object testSubObj = new TestFileChildClass(".");
+        Class[] parents = {bcpInterface, bcpSuperClass};
+        for (TestConversionMode mode : TestConversionMode.values()) {
+            for (Class parent : parents) {
+                // Android-changed: spelling fix in next comment.
+                // Child type to parent type non-null conversion, should succeed
+                testConversion(mode, nonBcpSubClass, parent, testSubObj,
+                        testSubObj, false, null);
+                // Android-changed: spelling fix in next comment.
+                // Child type to parent type null conversion, should succeed
+                testConversion(mode, nonBcpSubClass, parent, null, null,
+                        false, null);
+                // Parent type to child type non-null conversion with parent
+                // type instance, should fail
+                testConversion(mode, parent, nonBcpSubClass, bcpSuperObj, null,
+                        true, ClassCastException.class);
+                // Parent type to child type non-null conversion with child
+                // type instance, should succeed
+                testConversion(mode, parent, nonBcpSubClass, testSubObj,
+                        testSubObj, false, null);
+                // Parent type to child type null conversion, should succeed
+                testConversion(mode, parent, nonBcpSubClass, null, null,
+                        false, null);
+            }
+            // Parent type to child type non-null conversion with
+            // super sibling type instance, should fail
+            testConversion(mode, bcpInterface, nonBcpSubClass,
+                    testSuperSiblingObj, null, true, ClassCastException.class);
+            Class[] siblings = {nonBcpSubClass, bcpSuperClass};
+            for (Class sibling : siblings) {
+                // Non-bcp class to bcp/non-bcp sibling class non-null
+                // conversion with nonBcpSuperSiblingClass instance, should fail
+                testConversion(mode, nonBcpSuperSiblingClass, sibling,
+                        testSuperSiblingObj, null, true, ClassCastException.class);
+                // Non-bcp class to bcp/non-bcp sibling class null conversion,
+                // should succeed
+                testConversion(mode, nonBcpSuperSiblingClass, sibling,
+                        null, null, false, null);
+                // Non-bcp interface to bcp/non-bcp sibling class non-null
+                // conversion with nonBcpSubClass instance, should succeed
+                testConversion(mode, nonBcpInterface, sibling, testSubObj,
+                        testSubObj, false, null);
+                // Non-bcp interface to bcp/non-bcp sibling class
+                // null conversion, should succeed
+                testConversion(mode, nonBcpInterface, sibling, null, null,
+                        false, null);
+                // Non-bcp interface to bcp/non-bcp sibling class non-null
+                // conversion with nonBcpSuperSiblingClass instance, should fail
+                testConversion(mode, nonBcpInterface, sibling,
+                        testSuperSiblingObj, testSubObj,
+                        true, ClassCastException.class);
+            }
+        }
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests bootclasspath reference to reference conversions.
+     */
+    public static void testBCPRef2BCPRef() {
+        Class bcpInterface = CharSequence.class;
+        Class bcpSubClass1 = String.class;
+        Class bcpSubClass2 = StringBuffer.class;
+        Object testObj01 = new String("test");
+        Object testObj02 = new StringBuffer("test");
+        Class[] children = {bcpSubClass1, bcpSubClass2};
+        Object[] childInst = {testObj01, testObj02};
+        for (TestConversionMode mode : TestConversionMode.values()) {
+            for (int i = 0; i < children.length; i++) {
+                // Android-changed: spelling fix in next comment.
+                // Child type to parent type non-null conversion, should succeed
+                testConversion(mode, children[i], bcpInterface, childInst[i],
+                        childInst[i], false, null);
+                // Android-changed: spelling fix in next comment.
+                // Child type to parent type null conversion, should succeed
+                testConversion(mode, children[i], bcpInterface, null,
+                        null, false, null);
+                // Parent type to child type non-null conversion with child
+                // type instance, should succeed
+                testConversion(mode, bcpInterface,
+                        children[i], childInst[i], childInst[i], false, null);
+                // Parent type to child type null conversion, should succeed
+                testConversion(mode, bcpInterface,
+                        children[i], null, null, false, null);
+            }
+            // Sibling type non-null conversion, should fail
+            testConversion(mode, bcpSubClass1,
+                    bcpSubClass2, testObj01, null, true,
+                    ClassCastException.class);
+            // Sibling type null conversion, should succeed
+            testConversion(mode, bcpSubClass1,
+                    bcpSubClass2, null, null, false, null);
+            // Parent type to child type non-null conversion with sibling
+            // type instance, should fail
+            testConversion(mode, bcpInterface, bcpSubClass1, testObj02,
+                    null, true, ClassCastException.class);
+        }
+    }
+
+    // Android-changed: use 'sample' in comment.
+    /**
+     * Sample method used in {@link #testReturnAny2Void} and
+     * {@link #testReturnVoid2Any} tests to form a method handle.
+     */
+    public static void retVoid() {}
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests that non-null any return is successfully converted to non-type
+     * void.
+     */
+    public static void testReturnAny2Void() {
+        for (Wrapper from : Wrapper.values()) {
+            testConversion(TestConversionMode.RETURN_VALUE, from.wrapperType(),
+                    void.class, RANDOM_VALUES.get(from),
+                    null, false, null);
+            testConversion(TestConversionMode.RETURN_VALUE, from.primitiveType(),
+                    void.class, RANDOM_VALUES.get(from),
+                    null, false, null);
+        }
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests that void return is successfully converted to primitive and
+     * reference. Result should be zero for primitives and null for references.
+     */
+    public static void testReturnVoid2Any() {
+        for (Wrapper to : Wrapper.values()) {
+            testConversion(TestConversionMode.RETURN_VALUE, void.class,
+                    to.primitiveType(), null,
+                    to.zero(), false, null);
+            testConversion(TestConversionMode.RETURN_VALUE, void.class,
+                    to.wrapperType(), null,
+                    null, false, null);
+        }
+    }
+
+    private static void checkForWrongMethodTypeException(MethodHandle mh, MethodType mt) {
+        try {
+            MethodHandles.explicitCastArguments(mh, mt);
+            throw new AssertionError("Expected WrongMethodTypeException is not thrown");
+        } catch (WrongMethodTypeException wmte) {
+            if (VERBOSE) {
+                System.out.printf("Expected exception %s: %s\n",
+                        wmte.getClass(), wmte.getMessage());
+            }
+        }
+    }
+
+    // Android-added: @Test annotation with invocationCount as the test is non-deterministic.
+    @Test(invocationCount=10)
+    /**
+     * Tests that MHs.eCA method works correctly with MHs with multiple arguments.
+     * @throws Throwable
+     */
+    public static void testMultipleArgs() throws Throwable {
+        int arity = 1 + RNG.nextInt(Helper.MAX_ARITY / 2 - 2);
+        int arityMinus = RNG.nextInt(arity);
+        int arityPlus = arity + RNG.nextInt(Helper.MAX_ARITY / 2 - arity) + 1;
+        MethodType mType = Helper.randomMethodTypeGenerator(arity);
+        MethodType mTypeNew = Helper.randomMethodTypeGenerator(arity);
+        MethodType mTypeNewMinus = Helper.randomMethodTypeGenerator(arityMinus);
+        MethodType mTypeNewPlus = Helper.randomMethodTypeGenerator(arityPlus);
+        Class<?> rType = mType.returnType();
+        MethodHandle original;
+        if (rType.equals(void.class)) {
+            MethodType mt = MethodType.methodType(void.class);
+            original = MethodHandles.publicLookup()
+                    .findStatic(THIS_CLASS, "retVoid", mt);
+        } else {
+            Object rValue = Helper.castToWrapper(1, rType);
+            original = MethodHandles.constant(rType, rValue);
+        }
+        original = Helper.addTrailingArgs(original, arity, mType.parameterList());
+        MethodHandle target = MethodHandles
+                    .explicitCastArguments(original, mTypeNew);
+        Object[] parList = Helper.randomArgs(mTypeNew.parameterList());
+        for (int i = 0; i < parList.length; i++) {
+            if (parList[i] instanceof String) {
+                parList[i] = null; //getting rid of Stings produced by randomArgs
+            }
+        }
+        target.invokeWithArguments(parList);
+        checkForWrongMethodTypeException(original, mTypeNewMinus);
+        checkForWrongMethodTypeException(original, mTypeNewPlus);
+    }
+
+    /**
+     * Enumeration of test conversion modes.
+     */
+    public enum TestConversionMode {
+        RETURN_VALUE,
+        ARGUMENT;
+    }
+
+    // Android-added: @Test annotation
+    @Test
+    /**
+     * Tests type and value conversion. Comparing with the given expected result.
+     *
+     * @param mode - test conversion mode. See {@link #TestConversionMode}.
+     * @param from - source type.
+     * @param to - destination type.
+     * @param param - value to be converted.
+     * @param expectedResult - expected value after conversion.
+     * @param failureExpected - true if conversion failure expected.
+     * @param expectedException - expected exception class if
+     * {@code failureExpected} is true.
+     */
+    public static void testConversion(TestConversionMode mode,
+            Class<?> from, Class<?> to, Object param,
+            Object expectedResult, boolean failureExpected,
+            Class<? extends Throwable> expectedException) {
+        if (VERBOSE) {
+            System.out.printf("Testing return value conversion: "
+                    + "%-10s => %-10s: %5s: ", from.getSimpleName(),
+                    to.getSimpleName(), param);
+        }
+        MethodHandle original = null;
+        MethodType newType = null;
+        switch (mode) {
+            case RETURN_VALUE:
+                if (from.equals(void.class)) {
+                    MethodType mt = MethodType.methodType(void.class);
+                    try {
+                        original = MethodHandles.publicLookup()
+                                .findStatic(THIS_CLASS, "retVoid", mt);
+                    } catch (NoSuchMethodException | IllegalAccessException ex) {
+                        throw new Error("Unexpected issue", ex);
+                    }
+                } else {
+                    original = MethodHandles.constant(from, param);
+                }
+                newType = original.type().changeReturnType(to);
+                break;
+            case ARGUMENT:
+                if (from.equals(void.class) || to.equals(void.class)) {
+                    throw new Error("Test issue: argument conversion does not"
+                            + " work with non-type void");
+                }
+                original = MethodHandles.identity(to);
+                newType = original.type().changeParameterType(0, from);
+                break;
+            default:
+                // Android-changed: spelling fix in msg.
+                String msg = String.format("Test issue: unknown test"
+                        + " conversion mode %s.", mode.name());
+                throw new Error(msg);
+        }
+        try {
+            MethodHandle target = MethodHandles
+                    .explicitCastArguments(original, newType);
+            Object result;
+            switch (mode) {
+                case RETURN_VALUE:
+                    result = target.invokeWithArguments();
+                    break;
+                case ARGUMENT:
+                    result = target.invokeWithArguments(param);
+                    break;
+                default:
+                    // Android-changed: spelling fix in msg.
+                    String msg = String.format("Test issue: unknown test"
+                            + " conversion mode %s.", mode.name());
+                    throw new Error(msg);
+            }
+            if (!failureExpected
+                    && (expectedResult != null && !expectedResult.equals(result)
+                    || expectedResult == null && result != null)) {
+                String msg = String.format("Conversion result %s is not equal"
+                        + " to the expected result %10s",
+                        result, expectedResult);
+                throw new AssertionError(msg);
+            }
+            if (VERBOSE) {
+                String resultStr;
+                if (result != null) {
+                    resultStr = String.format("Converted value and type are"
+                            + " %10s (%10s)", "'" + result + "'",
+                            result.getClass().getSimpleName());
+                } else {
+                    resultStr = String.format("Converted value is %10s", result);
+                }
+                System.out.println(resultStr);
+            }
+            if (failureExpected) {
+                String msg = String.format("No exception thrown while testing"
+                        + " return value conversion: %10s => %10s;"
+                        + " parameter: %10s",
+                        from, to, param);
+                throw new AssertionError(msg);
+            }
+        } catch (AssertionError e) {
+            throw e; // report test failure
+        } catch (Throwable e) {
+            if (VERBOSE) {
+                System.out.printf("%s: %s\n", e.getClass(), e.getMessage());
+            }
+            if (!failureExpected || !e.getClass().equals(expectedException)) {
+                String msg = String.format("Unexpected exception was thrown"
+                        + " while testing return value conversion:"
+                        + " %s => %s; parameter: %s", from, to, param);
+                throw new AssertionError(msg, e);
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/FilterArgumentsTest.java b/ojluni/src/test/java/lang/invoke/FilterArgumentsTest.java
new file mode 100644
index 0000000..d113af0
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/FilterArgumentsTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8194554
+ * @run testng/othervm test.java.lang.invoke.FilterArgumentsTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.methodType;
+
+import org.testng.annotations.*;
+import static org.testng.Assert.*;
+
+public class FilterArgumentsTest {
+
+    @Test
+    public static void testFilterA_B_C() throws Throwable {
+        FilterTest test = new FilterTest(
+            filterArguments(MH_TEST, 0, MH_FILTER_A, MH_FILTER_B, MH_FILTER_C));
+        test.run(List.of("A", "B", "C"));
+    }
+
+    @Test
+    public static void testFilterA_B() throws Throwable {
+        FilterTest test = new FilterTest(
+            filterArguments(MH_TEST, 0, MH_FILTER_A, MH_FILTER_B));
+        test.run(List.of("A", "B"));
+    }
+
+    @Test
+    public static void testFilterB_C() throws Throwable {
+        FilterTest test = new FilterTest(
+            filterArguments(MH_TEST, 1, MH_FILTER_B, MH_FILTER_C));
+        test.run(List.of("B", "C"));
+    }
+
+    @Test
+    public static void testFilterB() throws Throwable {
+        FilterTest test = new FilterTest(filterArguments(MH_TEST, 1, MH_FILTER_B));
+        test.run(List.of("B"));
+    }
+
+    @Test
+    public static void testFilterC() throws Throwable {
+        FilterTest test = new FilterTest(filterArguments(MH_TEST, 2, MH_FILTER_C));
+        test.run(List.of("C"));
+    }
+
+    static class FilterTest {
+        static List<String> filters = new ArrayList<>();
+
+        final MethodHandle mh;
+        FilterTest(MethodHandle mh) {
+            this.mh = mh;
+        }
+
+        void run(List<String> expected) throws Throwable {
+            filters.clear();
+            assertEquals("x-0-z", (String)mh.invokeExact("x", 0, 'z'));
+            assertEquals(expected, filters);
+        }
+
+        static String filterA(String s) {
+            filters.add("A");
+            return s;
+        }
+
+        static int filterB(int value) {
+            filters.add("B");
+            return value;
+        }
+
+        static char filterC(char c) {
+            filters.add("C");
+            return c;
+        }
+
+        static String test(String s, int i, char c) {
+            return s + "-" + i + "-" + c;
+        }
+    }
+
+    static final MethodHandle MH_TEST;
+    static final MethodHandle MH_FILTER_A;
+    static final MethodHandle MH_FILTER_B;
+    static final MethodHandle MH_FILTER_C;
+    static final Lookup LOOKUP = MethodHandles.lookup();
+
+    static {
+        try {
+            MH_TEST = LOOKUP.findStatic(FilterTest.class, "test",
+                methodType(String.class, String.class, int.class, char.class));
+            MH_FILTER_A = LOOKUP.findStatic(FilterTest.class, "filterA",
+                methodType(String.class, String.class));
+            MH_FILTER_B = LOOKUP.findStatic(FilterTest.class, "filterB",
+                methodType(int.class, int.class));
+            MH_FILTER_C = LOOKUP.findStatic(FilterTest.class, "filterC",
+                methodType(char.class, char.class));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/FoldTest.java b/ojluni/src/test/java/lang/invoke/FoldTest.java
new file mode 100644
index 0000000..1e8e4f5
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/FoldTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @run testng/othervm -ea -esa test.java.lang.invoke.FoldTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the new fold method handle combinator added in JEP 274.
+ */
+public class FoldTest {
+
+    static final Lookup LOOKUP = MethodHandles.lookup();
+
+    @Test
+    public static void testFold0a() throws Throwable {
+        // equivalence to foldArguments(MethodHandle,MethodHandle)
+        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder);
+        assertEquals(Fold.MT_folded1, fold.type());
+        assertEquals(720, (int) fold.invoke(3, 4, 5));
+    }
+
+    @Test
+    public static void testFold1a() throws Throwable {
+        // test foldArguments for folding position 1
+        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1);
+        assertEquals(Fold.MT_folded1, fold.type());
+        assertEquals(540, (int) fold.invoke(3, 4, 5));
+    }
+
+    @Test
+    public static void testFold0b() throws Throwable {
+        // test foldArguments equivalence with multiple types
+        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb);
+        assertEquals(Fold.MT_folded2, fold.type());
+        assertEquals(23, (int) fold.invoke("true", true, 23));
+    }
+
+    @Test
+    public static void testFold1b() throws Throwable {
+        // test folgArguments for folding position 1, with multiple types
+        MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2);
+        assertEquals(Fold.MT_folded3, fold.type());
+        assertEquals(1, (int) fold.invoke(true, true, 1));
+        assertEquals(-1, (int) fold.invoke(true, false, -1));
+    }
+
+    @Test
+    public static void testFoldArgumentsExample() throws Throwable {
+        // test the JavaDoc foldArguments-with-pos example
+        StringWriter swr = new StringWriter();
+        MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr);
+        MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class));
+        assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+        MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace);
+        assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+        assertEquals("jum", swr.toString());
+    }
+
+    static class Fold {
+
+        static int adder(int a, int b, int c) {
+            return a + b + c;
+        }
+
+        static int adder1(int a, int b) {
+            return a + b;
+        }
+
+        static int multer(int x, int q, int r, int s) {
+            return x * q * r * s;
+        }
+
+        static int str(boolean b1, String s, boolean b2, int x) {
+            return b1 && s.equals(String.valueOf(b2)) ? x : -x;
+        }
+
+        static boolean comb(String s, boolean b2) {
+            return !s.equals(b2);
+        }
+
+        static String comb2(boolean b2, int x) {
+            int ib = b2 ? 1 : 0;
+            return ib == x ? "true" : "false";
+        }
+
+        static final Class<Fold> FOLD = Fold.class;
+
+        static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class);
+        static final MethodType MT_adder1 = methodType(int.class, int.class, int.class);
+        static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class);
+        static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class);
+        static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class);
+        static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class);
+
+        static final MethodHandle MH_adder;
+        static final MethodHandle MH_adder1;
+        static final MethodHandle MH_multer;
+        static final MethodHandle MH_str;
+        static final MethodHandle MH_comb;
+        static final MethodHandle MH_comb2;
+
+        static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class);
+        static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class);
+        static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class);
+
+        static {
+            try {
+                MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder);
+                MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1);
+                MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer);
+                MH_str = LOOKUP.findStatic(FOLD, "str", MT_str);
+                MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb);
+                MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/InvokeGenericTest.java b/ojluni/src/test/java/lang/invoke/InvokeGenericTest.java
new file mode 100644
index 0000000..ef201ca
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/InvokeGenericTest.java
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandle.invoke
+ * @compile InvokeGenericTest.java
+ * @run testng/othervm test.java.lang.invoke.InvokeGenericTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import java.lang.reflect.*;
+import java.util.*;
+import org.testng.*;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.*;
+
+/**
+ *
+ * @author jrose
+ */
+@SuppressWarnings("cast")  // various casts help emphasize arguments to invokeExact
+public class InvokeGenericTest {
+    // How much output?
+    static int verbosity = 0;
+    static {
+        String vstr = System.getProperty("test.java.lang.invoke.InvokeGenericTest.verbosity");
+        if (vstr != null)  verbosity = Integer.parseInt(vstr);
+    }
+
+//    public static void main(String... av) throws Throwable {
+//        new InvokeGenericTest().testFirst();
+//    }
+
+    @Test
+    public void testFirst() throws Throwable {
+        verbosity += 9; try {
+            // left blank for debugging
+        } finally { printCounts(); verbosity -= 9; }
+    }
+
+    public InvokeGenericTest() {
+    }
+
+    String testName;
+    static int allPosTests, allNegTests;
+    int posTests, negTests;
+    @AfterMethod
+    public void printCounts() {
+        if (verbosity >= 2 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
+            if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
+            allPosTests += posTests;
+            allNegTests += negTests;
+            posTests = negTests = 0;
+        }
+    }
+    void countTest(boolean positive) {
+        if (positive) ++posTests;
+        else          ++negTests;
+    }
+    void countTest() { countTest(true); }
+    void startTest(String name) {
+        if (testName != null)  printCounts();
+        if (verbosity >= 1)
+            System.out.println("["+name+"]");
+        posTests = negTests = 0;
+        testName = name;
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        calledLog.clear();
+        calledLog.add(null);
+        nextArgVal = INITIAL_ARG_VAL;
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+        int posTests = allPosTests, negTests = allNegTests;
+        if (verbosity >= 2 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
+            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
+        }
+    }
+
+    static List<Object> calledLog = new ArrayList<>();
+    static Object logEntry(String name, Object... args) {
+        return Arrays.asList(name, Arrays.asList(args));
+    }
+    static Object called(String name, Object... args) {
+        Object entry = logEntry(name, args);
+        calledLog.add(entry);
+        return entry;
+    }
+    static void assertCalled(String name, Object... args) {
+        Object expected = logEntry(name, args);
+        Object actual   = calledLog.get(calledLog.size() - 1);
+        if (expected.equals(actual) && verbosity < 9)  return;
+        System.out.println("assertCalled "+name+":");
+        System.out.println("expected:   "+expected);
+        System.out.println("actual:     "+actual);
+        System.out.println("ex. types:  "+getClasses(expected));
+        System.out.println("act. types: "+getClasses(actual));
+        assertEquals("previous method call", expected, actual);
+    }
+    static void printCalled(MethodHandle target, String name, Object... args) {
+        if (verbosity >= 3)
+            System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
+    }
+
+    static Object castToWrapper(Object value, Class<?> dst) {
+        Object wrap = null;
+        if (value instanceof Number)
+            wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
+        if (value instanceof Character)
+            wrap = castToWrapperOrNull((char)(Character)value, dst);
+        if (wrap != null)  return wrap;
+        return dst.cast(value);
+    }
+
+    static Object castToWrapperOrNull(long value, Class<?> dst) {
+        if (dst == int.class || dst == Integer.class)
+            return (int)(value);
+        if (dst == long.class || dst == Long.class)
+            return (long)(value);
+        if (dst == char.class || dst == Character.class)
+            return (char)(value);
+        if (dst == short.class || dst == Short.class)
+            return (short)(value);
+        if (dst == float.class || dst == Float.class)
+            return (float)(value);
+        if (dst == double.class || dst == Double.class)
+            return (double)(value);
+        if (dst == byte.class || dst == Byte.class)
+            return (byte)(value);
+        if (dst == boolean.class || dst == boolean.class)
+            return ((value % 29) & 1) == 0;
+        return null;
+    }
+
+    static final int ONE_MILLION = (1000*1000),  // first int value
+                     TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
+                     INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
+    static long nextArgVal;
+    static long nextArg(boolean moreBits) {
+        long val = nextArgVal++;
+        long sign = -(val & 1); // alternate signs
+        val >>= 1;
+        if (moreBits)
+            // Guarantee some bits in the high word.
+            // In any case keep the decimal representation simple-looking,
+            // with lots of zeroes, so as not to make the printed decimal
+            // strings unnecessarily noisy.
+            val += (val % ONE_MILLION) * TEN_BILLION;
+        return val ^ sign;
+    }
+    static int nextArg() {
+        // Produce a 32-bit result something like ONE_MILLION+(smallint).
+        // Example: 1_000_042.
+        return (int) nextArg(false);
+    }
+    static long nextArg(Class<?> kind) {
+        if (kind == long.class   || kind == Long.class ||
+            kind == double.class || kind == Double.class)
+            // produce a 64-bit result something like
+            // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+            // Example: 10_000_420_001_000_042.
+            return nextArg(true);
+        return (long) nextArg();
+    }
+
+    static Object randomArg(Class<?> param) {
+        Object wrap = castToWrapperOrNull(nextArg(param), param);
+        if (wrap != null) {
+            return wrap;
+        }
+//        import sun.invoke.util.Wrapper;
+//        Wrapper wrap = Wrapper.forBasicType(dst);
+//        if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
+//            wrap = Wrapper.forWrapperType(dst);
+//        if (wrap != Wrapper.OBJECT)
+//            return wrap.wrap(nextArg++);
+        if (param.isInterface()) {
+            for (Class<?> c : param.getClasses()) {
+                if (param.isAssignableFrom(c) && !c.isInterface())
+                    { param = c; break; }
+            }
+        }
+        if (param.isInterface() || param.isAssignableFrom(String.class))
+            return "#"+nextArg();
+        else
+            try {
+                return param.newInstance();
+            } catch (InstantiationException | IllegalAccessException ex) {
+            }
+        return null;  // random class not Object, String, Integer, etc.
+    }
+    static Object[] randomArgs(Class<?>... params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < args.length; i++)
+            args[i] = randomArg(params[i]);
+        return args;
+    }
+    static Object[] randomArgs(int nargs, Class<?> param) {
+        Object[] args = new Object[nargs];
+        for (int i = 0; i < args.length; i++)
+            args[i] = randomArg(param);
+        return args;
+    }
+
+    static final Object ANON_OBJ = new Object();
+    static Object zeroArg(Class<?> param) {
+        Object x = castToWrapperOrNull(0L, param);
+        if (x != null)  return x;
+        if (param.isInterface() || param.isAssignableFrom(String.class))  return "\"\"";
+        if (param == Object.class)  return ANON_OBJ;
+        if (param.getComponentType() != null)  return Array.newInstance(param.getComponentType(), 0);
+        return null;
+    }
+    static Object[] zeroArgs(Class<?>... params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < args.length; i++)
+            args[i] = zeroArg(params[i]);
+        return args;
+    }
+    static Object[] zeroArgs(List<Class<?>> params) {
+        return zeroArgs(params.toArray(new Class<?>[0]));
+    }
+
+    @SafeVarargs @SuppressWarnings("varargs")
+    static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
+        return Arrays.copyOf(a, a.length, atype);
+    }
+    @SafeVarargs @SuppressWarnings("varargs")
+    static <T> T[] cat(T[] a, T... b) {
+        int alen = a.length, blen = b.length;
+        if (blen == 0)  return a;
+        T[] c = Arrays.copyOf(a, alen + blen);
+        System.arraycopy(b, 0, c, alen, blen);
+        return c;
+    }
+    static Integer[] boxAll(int... vx) {
+        Integer[] res = new Integer[vx.length];
+        for (int i = 0; i < res.length; i++) {
+            res[i] = vx[i];
+        }
+        return res;
+    }
+    static Object getClasses(Object x) {
+        if (x == null)  return x;
+        if (x instanceof String)  return x;  // keep the name
+        if (x instanceof List) {
+            // recursively report classes of the list elements
+            Object[] xa = ((List)x).toArray();
+            for (int i = 0; i < xa.length; i++)
+                xa[i] = getClasses(xa[i]);
+            return Arrays.asList(xa);
+        }
+        return x.getClass().getSimpleName();
+    }
+
+    static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
+        return changeArgTypes(target, 0, 999, argType);
+    }
+    static MethodHandle changeArgTypes(MethodHandle target,
+            int beg, int end, Class<?> argType) {
+        MethodType targetType = target.type();
+        end = Math.min(end, targetType.parameterCount());
+        ArrayList<Class<?>> argTypes = new ArrayList<>(targetType.parameterList());
+        Collections.fill(argTypes.subList(beg, end), argType);
+        MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
+        return target.asType(ttype2);
+    }
+
+    // This lookup is good for all members in and under InvokeGenericTest.
+    static final Lookup LOOKUP = MethodHandles.lookup();
+
+    Map<List<Class<?>>, MethodHandle> CALLABLES = new HashMap<>();
+    MethodHandle callable(List<Class<?>> params) {
+        MethodHandle mh = CALLABLES.get(params);
+        if (mh == null) {
+            mh = collector_MH.asType(methodType(Object.class, params));
+            CALLABLES.put(params, mh);
+        }
+        return mh;
+    }
+    MethodHandle callable(Class<?>... params) {
+        return callable(Arrays.asList(params));
+    }
+    private static Object collector(Object... args) {
+        return Arrays.asList(args);
+    }
+    private static final MethodHandle collector_MH;
+    static {
+        try {
+            collector_MH
+                = LOOKUP.findStatic(LOOKUP.lookupClass(),
+                                    "collector",
+                                    methodType(Object.class, Object[].class));
+        } catch (ReflectiveOperationException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Test
+    public void testSimple() throws Throwable {
+        startTest("testSimple");
+        countTest();
+        String[] args = { "one", "two" };
+        MethodHandle mh = callable(Object.class, String.class);
+        Object res; List<?> resl;
+        res = resl = (List<?>) mh.invoke((String)args[0], (Object)args[1]);
+        //System.out.println(res);
+        assertEquals(Arrays.asList(args), res);
+    }
+
+    @Test
+    public void testSimplePrims() throws Throwable {
+        startTest("testSimplePrims");
+        countTest();
+        int[] args = { 1, 2 };
+        MethodHandle mh = callable(Object.class, Object.class);
+        Object res; List<?> resl;
+        res = resl = (List<?>) mh.invoke(args[0], args[1]);
+        //System.out.println(res);
+        assertEquals(Arrays.toString(args), res.toString());
+    }
+
+    @Test
+    public void testAlternateName() throws Throwable {
+        startTest("testAlternateName");
+        countTest();
+        String[] args = { "one", "two" };
+        MethodHandle mh = callable(Object.class, String.class);
+        Object res; List<?> resl;
+        res = resl = (List<?>) mh.invoke((String)args[0], (Object)args[1]);
+        //System.out.println(res);
+        assertEquals(Arrays.asList(args), res);
+    }
+
+    @Test
+    public void testWrongArgumentCount() throws Throwable {
+        startTest("testWrongArgumentCount");
+        for (int i = 0; i <= 10; i++) {
+            testWrongArgumentCount(Collections.<Class<?>>nCopies(i, Integer.class));
+            if (i <= 4) {
+                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, int.class));
+                testWrongArgumentCount(Collections.<Class<?>>nCopies(i, long.class));
+            }
+        }
+    }
+    public void testWrongArgumentCount(List<Class<?>> params) throws Throwable {
+        int max = params.size();
+        for (int i = 0; i < max; i++) {
+            List<Class<?>> params2 = params.subList(0, i);
+            for (int k = 0; k <= 2; k++) {
+                if (k == 1)  params  = methodType(Object.class,  params).generic().parameterList();
+                if (k == 2)  params2 = methodType(Object.class, params2).generic().parameterList();
+                testWrongArgumentCount(params, params2);
+                testWrongArgumentCount(params2, params);
+            }
+        }
+    }
+    public void testWrongArgumentCount(List<Class<?>> expect, List<Class<?>> observe) throws Throwable {
+        countTest(false);
+        if (expect.equals(observe))
+            assert(false);
+        MethodHandle target = callable(expect);
+        Object[] args = zeroArgs(observe);
+        Object junk;
+        try {
+            switch (args.length) {
+            case 0:
+                junk = target.invoke(); break;
+            case 1:
+                junk = target.invoke(args[0]); break;
+            case 2:
+                junk = target.invoke(args[0], args[1]); break;
+            case 3:
+                junk = target.invoke(args[0], args[1], args[2]); break;
+            case 4:
+                junk = target.invoke(args[0], args[1], args[2], args[3]); break;
+            default:
+                junk = target.invokeWithArguments(args); break;
+            }
+        } catch (WrongMethodTypeException ex) {
+            return;
+        } catch (Exception ex) {
+            throw new RuntimeException("wrong exception calling "+target+" on "+Arrays.asList(args), ex);
+        }
+        throw new RuntimeException("bad success calling "+target+" on "+Arrays.asList(args));
+    }
+
+    /** Make a list of all combinations of the given types, with the given arities.
+     *  A void return type is possible iff the first type is void.class.
+     */
+    static List<MethodType> allMethodTypes(int minargc, int maxargc, Class<?>... types) {
+        ArrayList<MethodType> result = new ArrayList<>();
+        if (types.length > 0) {
+            ArrayList<MethodType> argcTypes = new ArrayList<>();
+            // build arity-zero types first
+            for (Class<?> rtype : types) {
+                argcTypes.add(MethodType.methodType(rtype));
+            }
+            if (types[0] == void.class)
+                // void is not an argument type
+                types = Arrays.copyOfRange(types, 1, types.length);
+            for (int argc = 0; argc <= maxargc; argc++) {
+                if (argc >= minargc)
+                    result.addAll(argcTypes);
+                if (argc >= maxargc)
+                    break;
+                ArrayList<MethodType> prevTypes = argcTypes;
+                argcTypes = new ArrayList<>();
+                for (MethodType prevType : prevTypes) {
+                    for (Class<?> ptype : types) {
+                        argcTypes.add(prevType.insertParameterTypes(argc, ptype));
+                    }
+                }
+            }
+        }
+        return Collections.unmodifiableList(result);
+    }
+    static List<MethodType> allMethodTypes(int argc, Class<?>... types) {
+        return allMethodTypes(argc, argc, types);
+    }
+
+    MethodHandle toString_MH;
+
+    @Test
+    public void testReferenceConversions() throws Throwable {
+        startTest("testReferenceConversions");
+        toString_MH = LOOKUP.
+            findVirtual(Object.class, "toString", MethodType.methodType(String.class));
+        Object[] args = { "one", "two" };
+        for (MethodType type : allMethodTypes(2, Object.class, String.class, CharSequence.class)) {
+            testReferenceConversions(type, args);
+        }
+    }
+    public void testReferenceConversions(MethodType type, Object... args) throws Throwable {
+        countTest();
+        int nargs = args.length;
+        List<Object> argList = Arrays.asList(args);
+        String expectString = argList.toString();
+        if (verbosity > 3)  System.out.println("target type: "+type+expectString);
+        MethodHandle mh = callable(type.parameterList());
+        mh = MethodHandles.filterReturnValue(mh, toString_MH);
+        mh = mh.asType(type);
+        Object res = null;
+        if (nargs == 2) {
+            res = mh.invoke((Object)args[0], (Object)args[1]);
+            assertEquals(expectString, res);
+            res = mh.invoke((String)args[0], (Object)args[1]);
+            assertEquals(expectString, res);
+            res = mh.invoke((Object)args[0], (String)args[1]);
+            assertEquals(expectString, res);
+            res = mh.invoke((String)args[0], (String)args[1]);
+            assertEquals(expectString, res);
+            res = mh.invoke((String)args[0], (CharSequence)args[1]);
+            assertEquals(expectString, res);
+            res = mh.invoke((CharSequence)args[0], (Object)args[1]);
+            assertEquals(expectString, res);
+            res = (String) mh.invoke((Object)args[0], (Object)args[1]);
+            assertEquals(expectString, res);
+            res = (String) mh.invoke((String)args[0], (Object)args[1]);
+            assertEquals(expectString, res);
+            res = (CharSequence) mh.invoke((String)args[0], (Object)args[1]);
+            assertEquals(expectString, res);
+        } else {
+            assert(false);  // write this code
+        }
+        //System.out.println(res);
+    }
+
+
+    @Test
+    public void testBoxConversions() throws Throwable {
+        startTest("testBoxConversions");
+        countTest();
+        Object[] args = { 1, 2 };
+        MethodHandle mh = callable(Object.class, int.class);
+        Object res; List<?> resl; int resi;
+        res = resl = (List<?>) mh.invoke((int)args[0], (Object)args[1]);
+        //System.out.println(res);
+        assertEquals(Arrays.asList(args), res);
+        mh = MethodHandles.identity(int.class);
+        mh = MethodHandles.dropArguments(mh, 1, int.class);
+        res = resi = (int) mh.invoke((Object) args[0], (Object) args[1]);
+        assertEquals(args[0], res);
+        res = resi = (int) mh.invoke((int) args[0], (Object) args[1]);
+        assertEquals(args[0], res);
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/InvokeWithArgumentsTest.java b/ojluni/src/test/java/lang/invoke/InvokeWithArgumentsTest.java
new file mode 100644
index 0000000..df3c247
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/InvokeWithArgumentsTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary basic tests for MethodHandle.invokeWithArguments
+ * @run testng test.java.lang.invoke.InvokeWithArgumentsTest
+ */
+
+package test.java.lang.invoke;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.WrongMethodTypeException;
+
+import static java.lang.invoke.MethodType.methodType;
+
+public class InvokeWithArgumentsTest {
+    static final MethodHandles.Lookup L = MethodHandles.lookup();
+
+    static Object[] arity(Object o1, Object o2, Object... a) {
+        return a;
+    }
+
+    @Test
+    public void testArity() throws Throwable {
+        MethodHandle mh = L.findStatic(L.lookupClass(), "arity",
+                                       methodType(Object[].class, Object.class, Object.class, Object[].class));
+
+        try {
+            mh.invokeWithArguments("");
+            Assert.fail("WrongMethodTypeException expected");
+        } catch (WrongMethodTypeException e) {}
+    }
+
+    static Object[] passThrough(String... a) {
+        return a;
+    }
+
+    static Object[] pack(Object o, Object... a) {
+        return a;
+    }
+
+    @Test
+    public void testArrayNoPassThrough() throws Throwable {
+        String[] actual = {"A", "B"};
+
+        MethodHandle mh = L.findStatic(L.lookupClass(), "passThrough",
+                                       methodType(Object[].class, String[].class));
+
+        // Note: the actual array is not preserved, the elements will be
+        // unpacked and then packed into a new array before invoking the method
+        // Android-changed: Cast to Object[] to avoid compilation warning.
+        // String[] expected = (String[]) mh.invokeWithArguments(actual);
+        String[] expected = (String[]) mh.invokeWithArguments((Object[]) actual);
+
+        Assert.assertTrue(actual != expected, "Array should not pass through");
+        Assert.assertEquals(actual, expected, "Array contents should be equal");
+    }
+
+    @Test
+    public void testArrayPack() throws Throwable {
+        String[] actual = new String[]{"A", "B"};
+
+        MethodHandle mh = L.findStatic(L.lookupClass(), "pack",
+                                       methodType(Object[].class, Object.class, Object[].class));
+
+        // Note: since String[] can be cast to Object, the actual String[] array
+        // will cast to Object become the single element of a new Object[] array
+        Object[] expected = (Object[]) mh.invokeWithArguments("", actual);
+
+        Assert.assertEquals(1, expected.length, "Array should contain just one element");
+        Assert.assertTrue(actual == expected[0], "Array should pass through");
+    }
+
+    static void intArray(int... a) {
+    }
+
+    @Test
+    public void testPrimitiveArrayWithNull() throws Throwable {
+        MethodHandle mh = L.findStatic(L.lookupClass(), "intArray",
+                                       methodType(void.class, int[].class));
+        try {
+            mh.invokeWithArguments(null, null);
+            Assert.fail("NullPointerException expected");
+        } catch (NullPointerException e) {}
+    }
+
+    @Test
+    public void testPrimitiveArrayWithRef() throws Throwable {
+        MethodHandle mh = L.findStatic(L.lookupClass(), "intArray",
+                                       methodType(void.class, int[].class));
+        try {
+            mh.invokeWithArguments("A", "B");
+            Assert.fail("ClassCastException expected");
+        } catch (ClassCastException e) {}
+    }
+
+
+    static void numberArray(Number... a) {
+    }
+
+    @Test
+    public void testRefArrayWithCast() throws Throwable {
+        MethodHandle mh = L.findStatic(L.lookupClass(), "numberArray",
+                                       methodType(void.class, Number[].class));
+        // All numbers, should not throw
+        mh.invokeWithArguments(1, 1.0, 1.0F, 1L);
+
+        try {
+            mh.invokeWithArguments("A");
+            Assert.fail("ClassCastException expected");
+        } catch (ClassCastException e) {}
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/JavaDocExamplesTest.java b/ojluni/src/test/java/lang/invoke/JavaDocExamplesTest.java
new file mode 100644
index 0000000..b279ba5
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/JavaDocExamplesTest.java
@@ -0,0 +1,961 @@
+/*
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary example code used in javadoc for java.lang.invoke API
+ * @compile JavaDocExamplesTest.java
+ * @run testng/othervm test.java.lang.invoke.JavaDocExamplesTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.StringWriter;
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+import java.util.*;
+
+import org.testng.*;
+import org.testng.annotations.*;
+
+/**
+ * @author jrose
+ */
+public class JavaDocExamplesTest {
+    /** Wrapper for running the TestNG tests in this module.
+     *  Put TestNG on the classpath!
+     */
+    public static void main(String... ignore) throws Throwable {
+      new JavaDocExamplesTest().run();
+    }
+
+    public void run() throws Throwable {
+      // Android-removed: not used.
+      /*
+        testMisc();
+        testFindStatic();
+        testFindConstructor();
+        testFindVirtual();
+        testFindSpecial();
+        testPermuteArguments();
+        testZero();
+        testDropArguments();
+        testDropArgumentsToMatch();
+        testFilterArguments();
+        testFoldArguments();
+        testFoldArguments2();
+        testMethodHandlesSummary();
+        testAsSpreader();
+        testAsCollector();
+        testAsVarargsCollector();
+        testAsFixedArity();
+        testAsTypeCornerCases();
+        testMutableCallSite();
+      */
+    }
+    // How much output?
+    static final Class<?> THIS_CLASS = JavaDocExamplesTest.class;
+    static int verbosity = Integer.getInteger(THIS_CLASS.getSimpleName()+".verbosity", 0);
+
+
+{}
+private static final Lookup LOOKUP = lookup();
+// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
+//     "concat", methodType(String.class, String.class));
+// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
+//     "hashCode", methodType(int.class));
+
+// form required if ReflectiveOperationException is intercepted:
+    private static final MethodHandle CONCAT_2, HASHCODE_2, ADD_2, SUB_2;
+static {
+  try {
+    Class<?> THIS_CLASS = LOOKUP.lookupClass();
+    CONCAT_2 = LOOKUP.findVirtual(String.class,
+      "concat", methodType(String.class, String.class));
+    HASHCODE_2 = LOOKUP.findVirtual(Object.class,
+      "hashCode", methodType(int.class));
+    ADD_2 = LOOKUP.findStatic(THIS_CLASS, "add", methodType(int.class, int.class, int.class));
+    SUB_2 = LOOKUP.findStatic(THIS_CLASS, "sub", methodType(int.class, int.class, int.class));
+   } catch (ReflectiveOperationException ex) {
+     throw new RuntimeException(ex);
+   }
+}
+    static int add(int x, int y) { return x + y; }
+    static int sub(int x, int y) { return x - y; }
+
+{}
+
+    @Test public void testMisc() throws Throwable {
+// Extra tests, not from javadoc:
+{}
+MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
+  "hashCode", methodType(int.class));
+//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y"));
+//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
+{}
+    }
+
+    @Test public void testFindStatic() throws Throwable {
+{}
+MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
+  "asList", methodType(List.class, Object[].class));
+assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
+{}
+    }
+
+    @Test public void testFindVirtual() throws Throwable {
+{}
+MethodHandle MH_concat = publicLookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,
+  "hashCode", methodType(int.class));
+MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,
+  "hashCode", methodType(int.class));
+assertEquals("xy", (String) MH_concat.invokeExact("x", "y"));
+assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy"));
+// interface method:
+MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
+  "subSequence", methodType(CharSequence.class, int.class, int.class));
+assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
+// constructor "internal method" must be accessed differently:
+MethodType MT_newString = methodType(void.class); //()V for new String()
+try { assertEquals("impossible", lookup()
+        .findVirtual(String.class, "<init>", MT_newString));
+ } catch (NoSuchMethodException ex) { } // OK
+MethodHandle MH_newString = publicLookup()
+  .findConstructor(String.class, MT_newString);
+assertEquals("", (String) MH_newString.invokeExact());
+{}
+    }
+
+    @Test public void testFindConstructor() throws Throwable {
+{}
+MethodHandle MH_newArrayList = publicLookup().findConstructor(
+  ArrayList.class, methodType(void.class, Collection.class));
+Collection orig = Arrays.asList("x", "y");
+Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
+assert(orig != copy);
+assertEquals(orig, copy);
+// a variable-arity constructor:
+MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
+  ProcessBuilder.class, methodType(void.class, String[].class));
+ProcessBuilder pb = (ProcessBuilder)
+  MH_newProcessBuilder.invoke("x", "y", "z");
+assertEquals("[x, y, z]", pb.command().toString());
+{}
+    }
+
+// for testFindSpecial
+{}
+static class Listie extends ArrayList {
+  public String toString() { return "[wee Listie]"; }
+  static Lookup lookup() { return MethodHandles.lookup(); }
+}
+{}
+
+// Android-removed: test fails, needs investigating (b/207844518).
+/*
+    @Test public void testFindSpecial() throws Throwable {
+{}
+// no access to constructor via invokeSpecial:
+MethodHandle MH_newListie = Listie.lookup()
+  .findConstructor(Listie.class, methodType(void.class));
+Listie l = (Listie) MH_newListie.invokeExact();
+try { assertEquals("impossible", Listie.lookup().findSpecial(
+        Listie.class, "<init>", methodType(void.class), Listie.class));
+ } catch (NoSuchMethodException ex) { } // OK
+// access to super and self methods via invokeSpecial:
+MethodHandle MH_super = Listie.lookup().findSpecial(
+  ArrayList.class, "toString" , methodType(String.class), Listie.class);
+MethodHandle MH_this = Listie.lookup().findSpecial(
+  Listie.class, "toString" , methodType(String.class), Listie.class);
+MethodHandle MH_duper = Listie.lookup().findSpecial(
+  Object.class, "toString" , methodType(String.class), Listie.class);
+assertEquals("[]", (String) MH_super.invokeExact(l));
+assertEquals(""+l, (String) MH_this.invokeExact(l));
+assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method
+try { assertEquals("inaccessible", Listie.lookup().findSpecial(
+        String.class, "toString", methodType(String.class), Listie.class));
+ } catch (IllegalAccessException ex) { } // OK
+Listie subl = new Listie() { public String toString() { return "[subclass]"; } };
+assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
+{}
+    }
+*/
+
+    @Test public void testPermuteArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodType intfn1 = methodType(int.class, int.class);
+MethodType intfn2 = methodType(int.class, int.class, int.class);
+MethodHandle sub = SUB_2;// ... {int x, int y => x-y} ...;
+assert(sub.type().equals(intfn2));
+MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
+MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
+assert((int)rsub.invokeExact(1, 100) == 99);
+MethodHandle add = ADD_2;// ... {int x, int y => x+y} ...;
+assert(add.type().equals(intfn2));
+MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
+assert(twice.type().equals(intfn1));
+assert((int)twice.invokeExact(21) == 42);
+            }}
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+            }}
+    }
+
+@Test public void testZero() throws Throwable {
+        {{
+{} /// JAVADOC
+Class<?> type = Double.class;
+MethodHandle mh1 = MethodHandles.explicitCastArguments(MethodHandles.constant(Object.class, null), methodType(type));
+assertEquals("()Double", mh1.type().toString());
+MethodHandle mh2 = MethodHandles.empty(methodType(type));
+assertEquals("()Double", mh2.type().toString());
+        }}
+   }
+
+    @Test public void testDropArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+            }}
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+            }}
+    }
+
+    @Test public void testDropArgumentsToMatch() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle h0= constant(boolean.class, true);
+MethodHandle h1 = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class));
+MethodType bigType = h1.type().insertParameterTypes(1, String.class, int.class);
+MethodHandle h2 = dropArguments(h1, 0, bigType.parameterList());
+if (h1.type().parameterCount() < h2.type().parameterCount()) {
+    h1 = dropArgumentsToMatch(h1, 0, h2.type().parameterList(), 0);  // lengthen h1
+}
+else {
+    h2 = dropArgumentsToMatch(h2, 0, h1.type().parameterList(), 0);    // lengthen h2
+}
+MethodHandle h3 = guardWithTest(h0, h1, h2);
+assertEquals("xy", h3.invoke("x", "y", 1, "a", "b", "c"));
+        }}
+    }
+
+    @Test public void testFilterArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle upcase = lookup().findVirtual(String.class,
+  "toUpperCase", methodType(String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle f0 = filterArguments(cat, 0, upcase);
+assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
+MethodHandle f1 = filterArguments(cat, 1, upcase);
+assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
+MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
+assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
+            }}
+    }
+
+    @Test public void testCollectArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle deepToString = publicLookup()
+  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
+MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
+assertEquals("[strange]", (String) ts1.invokeExact("strange"));
+MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
+assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
+MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
+MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
+assertEquals("[top, [up, down], strange]",
+             (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
+MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
+assertEquals("[top, [up, down], [strange]]",
+             (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
+MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
+assertEquals("[top, [[up, down, strange], charm], bottom]",
+             (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
+            }}
+    }
+
+    @Test public void testFoldArguments() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
+  "println", methodType(void.class, String.class))
+    .bindTo(System.out);
+MethodHandle cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+MethodHandle catTrace = foldArguments(cat, trace);
+// also prints "boo":
+assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+            }}
+    }
+
+    static void assertEquals(Object exp, Object act) {
+        if (verbosity > 0)
+            System.out.println("result: "+act);
+        Assert.assertEquals(exp, act);
+    }
+
+    static void assertTrue(boolean b) {
+        if (verbosity > 0) {
+            System.out.println("result: " + b);
+        }
+        Assert.assertTrue(b);
+    }
+
+    @Test public void testMethodHandlesSummary() throws Throwable {
+        {{
+{} /// JAVADOC
+Object x, y; String s; int i;
+MethodType mt; MethodHandle mh;
+MethodHandles.Lookup lookup = MethodHandles.lookup();
+// mt is (char,char)String
+mt = MethodType.methodType(String.class, char.class, char.class);
+mh = lookup.findVirtual(String.class, "replace", mt);
+s = (String) mh.invokeExact("daddy",'d','n');
+// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
+assertEquals(s, "nanny");
+// weakly typed invocation (using MHs.invoke)
+s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
+assertEquals(s, "savvy");
+// mt is (Object[])List
+mt = MethodType.methodType(java.util.List.class, Object[].class);
+mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
+assert(mh.isVarargsCollector());
+x = mh.invoke("one", "two");
+// invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+assertEquals(x, java.util.Arrays.asList("one","two"));
+// mt is (Object,Object,Object)Object
+mt = MethodType.genericMethodType(3);
+mh = mh.asType(mt);
+x = mh.invokeExact((Object)1, (Object)2, (Object)3);
+// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+assertEquals(x, java.util.Arrays.asList(1,2,3));
+// mt is ()int
+mt = MethodType.methodType(int.class);
+mh = lookup.findVirtual(java.util.List.class, "size", mt);
+i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
+// invokeExact(Ljava/util/List;)I
+assert(i == 3);
+mt = MethodType.methodType(void.class, String.class);
+mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
+mh.invokeExact(System.out, "Hello, world.");
+// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
+{}
+            }}
+    }
+
+    @Test public void testAsSpreader() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle equals = publicLookup()
+  .findVirtual(String.class, "equals", methodType(boolean.class, Object.class));
+assert( (boolean) equals.invokeExact("me", (Object)"me"));
+assert(!(boolean) equals.invokeExact("me", (Object)"thee"));
+// spread both arguments from a 2-array:
+MethodHandle eq2 = equals.asSpreader(Object[].class, 2);
+assert( (boolean) eq2.invokeExact(new Object[]{ "me", "me" }));
+assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" }));
+// try to spread from anything but a 2-array:
+for (int n = 0; n <= 10; n++) {
+  Object[] badArityArgs = (n == 2 ? new Object[0] : new Object[n]);
+  try { assert((boolean) eq2.invokeExact(badArityArgs) && false); }
+  catch (IllegalArgumentException ex) { } // OK
+}
+// spread both arguments from a String array:
+MethodHandle eq2s = equals.asSpreader(String[].class, 2);
+assert( (boolean) eq2s.invokeExact(new String[]{ "me", "me" }));
+assert(!(boolean) eq2s.invokeExact(new String[]{ "me", "thee" }));
+// spread second arguments from a 1-array:
+MethodHandle eq1 = equals.asSpreader(Object[].class, 1);
+assert( (boolean) eq1.invokeExact("me", new Object[]{ "me" }));
+assert(!(boolean) eq1.invokeExact("me", new Object[]{ "thee" }));
+// spread no arguments from a 0-array or null:
+MethodHandle eq0 = equals.asSpreader(Object[].class, 0);
+assert( (boolean) eq0.invokeExact("me", (Object)"me", new Object[0]));
+assert(!(boolean) eq0.invokeExact("me", (Object)"thee", (Object[])null));
+// asSpreader and asCollector are approximate inverses:
+for (int n = 0; n <= 2; n++) {
+    for (Class<?> a : new Class<?>[]{Object[].class, String[].class, CharSequence[].class}) {
+        MethodHandle equals2 = equals.asSpreader(a, n).asCollector(a, n);
+        assert( (boolean) equals2.invokeWithArguments("me", "me"));
+        assert(!(boolean) equals2.invokeWithArguments("me", "thee"));
+    }
+}
+MethodHandle caToString = publicLookup()
+  .findStatic(Arrays.class, "toString", methodType(String.class, char[].class));
+assertEquals("[A, B, C]", (String) caToString.invokeExact("ABC".toCharArray()));
+MethodHandle caString3 = caToString.asCollector(char[].class, 3);
+assertEquals("[A, B, C]", (String) caString3.invokeExact('A', 'B', 'C'));
+MethodHandle caToString2 = caString3.asSpreader(char[].class, 2);
+assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray()));
+            }}
+    }
+
+    @Test public void testAsCollector() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle deepToString = publicLookup()
+  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
+assertEquals("[won]",   (String) deepToString.invokeExact(new Object[]{"won"}));
+MethodHandle ts1 = deepToString.asCollector(Object[].class, 1);
+assertEquals(methodType(String.class, Object.class), ts1.type());
+//assertEquals("[won]", (String) ts1.invokeExact(         new Object[]{"won"})); //FAIL
+assertEquals("[[won]]", (String) ts1.invokeExact((Object) new Object[]{"won"}));
+// arrayType can be a subtype of Object[]
+MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
+assertEquals(methodType(String.class, String.class, String.class), ts2.type());
+assertEquals("[two, too]", (String) ts2.invokeExact("two", "too"));
+MethodHandle ts0 = deepToString.asCollector(Object[].class, 0);
+assertEquals("[]", (String) ts0.invokeExact());
+// collectors can be nested, Lisp-style
+MethodHandle ts22 = deepToString.asCollector(Object[].class, 3).asCollector(String[].class, 2);
+assertEquals("[A, B, [C, D]]", ((String) ts22.invokeExact((Object)'A', (Object)"B", "C", "D")));
+// arrayType can be any primitive array type
+MethodHandle bytesToString = publicLookup()
+  .findStatic(Arrays.class, "toString", methodType(String.class, byte[].class))
+  .asCollector(byte[].class, 3);
+assertEquals("[1, 2, 3]", (String) bytesToString.invokeExact((byte)1, (byte)2, (byte)3));
+MethodHandle longsToString = publicLookup()
+  .findStatic(Arrays.class, "toString", methodType(String.class, long[].class))
+  .asCollector(long[].class, 1);
+assertEquals("[123]", (String) longsToString.invokeExact((long)123));
+            }}
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test public void testAsVarargsCollector() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle deepToString = publicLookup()
+  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
+MethodHandle ts1 = deepToString.asVarargsCollector(Object[].class);
+assertEquals("[won]",   (String) ts1.invokeExact(    new Object[]{"won"}));
+assertEquals("[won]",   (String) ts1.invoke(         new Object[]{"won"}));
+assertEquals("[won]",   (String) ts1.invoke(                      "won" ));
+assertEquals("[[won]]", (String) ts1.invoke((Object) new Object[]{"won"}));
+// findStatic of Arrays.asList(...) produces a variable arity method handle:
+MethodHandle asList = publicLookup()
+  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
+assertEquals(methodType(List.class, Object[].class), asList.type());
+assert(asList.isVarargsCollector());
+assertEquals("[]", asList.invoke().toString());
+assertEquals("[1]", asList.invoke(1).toString());
+assertEquals("[two, too]", asList.invoke("two", "too").toString());
+String[] argv = { "three", "thee", "tee" };
+assertEquals("[three, thee, tee]", asList.invoke(argv).toString());
+assertEquals("[three, thee, tee]", asList.invoke((Object[])argv).toString());
+List ls = (List) asList.invoke((Object)argv);
+assertEquals(1, ls.size());
+assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
+            }}
+    }
+
+    @Test public void testAsFixedArity() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle asListVar = publicLookup()
+  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+  .asVarargsCollector(Object[].class);
+MethodHandle asListFix = asListVar.asFixedArity();
+assertEquals("[1]", asListVar.invoke(1).toString());
+Exception caught = null;
+try { asListFix.invoke((Object)1); }
+catch (Exception ex) { caught = ex; }
+assert(caught instanceof ClassCastException);
+assertEquals("[two, too]", asListVar.invoke("two", "too").toString());
+try { asListFix.invoke("two", "too"); }
+catch (Exception ex) { caught = ex; }
+assert(caught instanceof WrongMethodTypeException);
+Object[] argv = { "three", "thee", "tee" };
+assertEquals("[three, thee, tee]", asListVar.invoke(argv).toString());
+assertEquals("[three, thee, tee]", asListFix.invoke(argv).toString());
+assertEquals(1, ((List) asListVar.invoke((Object)argv)).size());
+assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
+            }}
+    }
+
+    @Test public void testAsTypeCornerCases() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle i2s = publicLookup()
+  .findVirtual(Integer.class, "toString", methodType(String.class));
+i2s = i2s.asType(i2s.type().unwrap());
+MethodHandle l2s = publicLookup()
+  .findVirtual(Long.class, "toString", methodType(String.class));
+l2s = l2s.asType(l2s.type().unwrap());
+
+Exception caught = null;
+try { i2s.asType(methodType(String.class, String.class)); }
+catch (Exception ex) { caught = ex; }
+assert(caught instanceof WrongMethodTypeException);
+
+i2s.asType(methodType(String.class, byte.class));
+i2s.asType(methodType(String.class, Byte.class));
+i2s.asType(methodType(String.class, Character.class));
+i2s.asType(methodType(String.class, Integer.class));
+l2s.asType(methodType(String.class, byte.class));
+l2s.asType(methodType(String.class, Byte.class));
+l2s.asType(methodType(String.class, Character.class));
+l2s.asType(methodType(String.class, Integer.class));
+l2s.asType(methodType(String.class, Long.class));
+
+caught = null;
+try { i2s.asType(methodType(String.class, Long.class)); }
+catch (Exception ex) { caught = ex; }
+assert(caught instanceof WrongMethodTypeException);
+
+MethodHandle i2sGen = i2s.asType(methodType(String.class, Object.class));
+MethodHandle l2sGen = l2s.asType(methodType(String.class, Object.class));
+
+i2sGen.invoke(42);  // int -> Integer -> Object -> Integer -> int
+i2sGen.invoke((byte)4);  // byte -> Byte -> Object -> Byte -> byte -> int
+l2sGen.invoke(42);  // int -> Integer -> Object -> Integer -> int
+l2sGen.invoke((byte)4);  // byte -> Byte -> Object -> Byte -> byte -> int
+l2sGen.invoke(0x420000000L);
+
+caught = null;
+try { i2sGen.invoke(0x420000000L); } // long -> Long -> Object -> Integer CCE
+catch (Exception ex) { caught = ex; }
+assert(caught instanceof ClassCastException);
+
+caught = null;
+try { i2sGen.invoke("asdf"); } // String -> Object -> Integer CCE
+catch (Exception ex) { caught = ex; }
+assert(caught instanceof ClassCastException);
+{}
+            }}
+    }
+
+    @Test public void testMutableCallSite() throws Throwable {
+        {{
+{} /// JAVADOC
+MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
+MethodHandle MH_name = name.dynamicInvoker();
+MethodType MT_str1 = MethodType.methodType(String.class);
+MethodHandle MH_upcase = MethodHandles.lookup()
+    .findVirtual(String.class, "toUpperCase", MT_str1);
+MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
+name.setTarget(MethodHandles.constant(String.class, "Rocky"));
+assertEquals("ROCKY", (String) worker1.invokeExact());
+name.setTarget(MethodHandles.constant(String.class, "Fred"));
+assertEquals("FRED", (String) worker1.invokeExact());
+// (mutation can be continued indefinitely)
+/*
+ * </pre></blockquote>
+ * <p>
+ * The same call site may be used in several places at once.
+ * <blockquote><pre>
+ */
+MethodType MT_str2 = MethodType.methodType(String.class, String.class);
+MethodHandle MH_cat = lookup().findVirtual(String.class,
+  "concat", methodType(String.class, String.class));
+MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?");
+MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
+assertEquals("Fred, dear?", (String) worker2.invokeExact());
+name.setTarget(MethodHandles.constant(String.class, "Wilma"));
+assertEquals("WILMA", (String) worker1.invokeExact());
+assertEquals("Wilma, dear?", (String) worker2.invokeExact());
+{}
+            }}
+    }
+
+// Android-removed: SwitchPoint not supported.
+/*
+    @Test public void testSwitchPoint() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle MH_strcat = MethodHandles.lookup()
+    .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
+SwitchPoint spt = new SwitchPoint();
+assert(!spt.hasBeenInvalidated());
+// the following steps may be repeated to re-use the same switch point:
+MethodHandle worker1 = MH_strcat;
+MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0);
+MethodHandle worker = spt.guardWithTest(worker1, worker2);
+assertEquals("method", (String) worker.invokeExact("met", "hod"));
+SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
+assert(spt.hasBeenInvalidated());
+assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
+{}
+            }}
+    }
+*/
+
+    @Test public void testFoldArguments2() throws Throwable {
+        {{
+{} /// JAVADOC
+// argument-based dispatch for methods of the form boolean x.___(y: String)
+Lookup lookup = publicLookup();
+// first, a tracing hack:
+MethodHandle println = lookup.findVirtual(java.io.PrintStream.class, "println", methodType(void.class, String.class));
+MethodHandle arrayToString = lookup.findStatic(Arrays.class, "toString", methodType(String.class, Object[].class));
+MethodHandle concat = lookup.findVirtual(String.class, "concat", methodType(String.class, String.class));
+MethodHandle arrayToString_DIS = filterReturnValue(arrayToString, concat.bindTo("DIS:"));
+MethodHandle arrayToString_INV = filterReturnValue(arrayToString, concat.bindTo("INV:"));
+MethodHandle printArgs_DIS = filterReturnValue(arrayToString_DIS, println.bindTo(System.out)).asVarargsCollector(Object[].class);
+MethodHandle printArgs_INV = filterReturnValue(arrayToString_INV, println.bindTo(System.out)).asVarargsCollector(Object[].class);
+// metaobject protocol:
+MethodType mtype = methodType(boolean.class, String.class);
+MethodHandle findVirtual = lookup.findVirtual(Lookup.class,
+  "findVirtual", methodType(MethodHandle.class, Class.class, String.class, MethodType.class));
+MethodHandle getClass = lookup.findVirtual(Object.class,
+  "getClass", methodType(Class.class));
+MethodHandle dispatch = findVirtual;
+dispatch = filterArguments(dispatch, 1, getClass);
+dispatch = insertArguments(dispatch, 3, mtype);
+dispatch = dispatch.bindTo(lookup);
+assertEquals(methodType(MethodHandle.class, Object.class, String.class), dispatch.type());
+MethodHandle invoker = invoker(mtype.insertParameterTypes(0, Object.class));
+// wrap tracing around the dispatch and invoke steps:
+dispatch = foldArguments(dispatch, printArgs_DIS.asType(dispatch.type().changeReturnType(void.class)));
+invoker = foldArguments(invoker, printArgs_INV.asType(invoker.type().changeReturnType(void.class)));
+invoker = dropArguments(invoker, 2, String.class);  // ignore selector
+// compose the dispatcher and the invoker:
+MethodHandle invokeDispatched = foldArguments(invoker, dispatch);
+Object x = "football", y = new java.util.Scanner("bar");
+assert( (boolean) invokeDispatched.invokeExact(x, "startsWith", "foo"));
+assert(!(boolean) invokeDispatched.invokeExact(x, "startsWith", "#"));
+assert( (boolean) invokeDispatched.invokeExact(x, "endsWith", "all"));
+assert(!(boolean) invokeDispatched.invokeExact(x, "endsWith", "foo"));
+assert( (boolean) invokeDispatched.invokeExact(y, "hasNext", "[abc]+[rst]"));
+assert(!(boolean) invokeDispatched.invokeExact(y, "hasNext", "[123]+[789]"));
+            }}
+    }
+
+    static int one(int k) { return 1; }
+    static int inc(int i, int acc, int k) { return i + 1; }
+    static int mult(int i, int acc, int k) { return i * acc; }
+    static boolean pred(int i, int acc, int k) { return i < k; }
+    static int fin(int i, int acc, int k) { return acc; }
+
+    @Test public void testLoop() throws Throwable {
+        MethodHandle MH_inc, MH_one, MH_mult, MH_pred, MH_fin;
+        Class<?> I = int.class;
+        MH_inc = LOOKUP.findStatic(THIS_CLASS, "inc", methodType(I, I, I, I));
+        MH_one = LOOKUP.findStatic(THIS_CLASS, "one", methodType(I, I));
+        MH_mult = LOOKUP.findStatic(THIS_CLASS, "mult", methodType(I, I, I, I));
+        MH_pred = LOOKUP.findStatic(THIS_CLASS, "pred", methodType(boolean.class, I, I, I));
+        MH_fin = LOOKUP.findStatic(THIS_CLASS, "fin", methodType(I, I, I, I));
+        {{
+{} /// JAVADOC
+// iterative implementation of the factorial function as a loop handle
+// null initializer for counter, should initialize to 0
+MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+assertEquals(120, loop.invoke(5));
+{}
+        }}
+    }
+
+    static int inc(int i) { return i + 1; } // drop acc, k
+    static int mult(int i, int acc) { return i * acc; } //drop k
+    static boolean cmp(int i, int k) { return i < k; }
+
+    @Test public void testSimplerLoop() throws Throwable {
+        MethodHandle MH_inc, MH_mult, MH_cmp;
+        Class<?> I = int.class;
+        MH_inc = LOOKUP.findStatic(THIS_CLASS, "inc", methodType(I, I));
+        MH_mult = LOOKUP.findStatic(THIS_CLASS, "mult", methodType(I, I, I));
+        MH_cmp = LOOKUP.findStatic(THIS_CLASS, "cmp", methodType(boolean.class, I, I));
+        {{
+{} /// JAVADOC
+// simplified implementation of the factorial function as a loop handle
+// null initializer for counter, should initialize to 0
+MethodHandle MH_one = MethodHandles.constant(int.class, 1);
+MethodHandle MH_pred = MethodHandles.dropArguments(MH_cmp, 1, int.class); // drop acc
+MethodHandle MH_fin = MethodHandles.dropArguments(MethodHandles.identity(int.class), 0, int.class); // drop i
+MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+assertEquals(720, loop.invoke(6));
+{}
+        }}
+    }
+
+    // for testFacLoop
+{}
+static class FacLoop {
+  final int k;
+  FacLoop(int k) { this.k = k; }
+  int inc(int i) { return i + 1; }
+  int mult(int i, int acc) { return i * acc; }
+  boolean pred(int i) { return i < k; }
+  int fin(int i, int acc) { return acc; }
+}
+{}
+
+    // assume MH_inc, MH_mult, and MH_pred are handles to the above methods
+    @Test public void testFacLoop() throws Throwable {
+        MethodHandle MH_FacLoop, MH_inc, MH_mult, MH_pred, MH_fin;
+        Class<?> I = int.class;
+        MH_FacLoop = LOOKUP.findConstructor(FacLoop.class, methodType(void.class, I));
+        MH_inc = LOOKUP.findVirtual(FacLoop.class, "inc", methodType(I, I));
+        MH_mult = LOOKUP.findVirtual(FacLoop.class, "mult", methodType(I, I, I));
+        MH_pred = LOOKUP.findVirtual(FacLoop.class, "pred", methodType(boolean.class, I));
+        MH_fin = LOOKUP.findVirtual(FacLoop.class, "fin", methodType(I, I, I));
+        {{
+{} /// JAVADOC
+// instance-based implementation of the factorial function as a loop handle
+// null initializer for counter, should initialize to 0
+MethodHandle MH_one = MethodHandles.constant(int.class, 1);
+MethodHandle[] instanceClause = new MethodHandle[]{MH_FacLoop};
+MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
+MethodHandle[] accumulatorClause = new MethodHandle[]{MH_one, MH_mult, MH_pred, MH_fin};
+MethodHandle loop = MethodHandles.loop(instanceClause, counterClause, accumulatorClause);
+assertEquals(5040, loop.invoke(7));
+{}
+        }}
+    }
+
+    static List<String> initZip(Iterator<String> a, Iterator<String> b) { return new ArrayList<>(); }
+    static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) { return a.hasNext() && b.hasNext(); }
+    static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+        zip.add(a.next());
+        zip.add(b.next());
+        return zip;
+    }
+
+    @Test public void testWhileLoop() throws Throwable {
+        MethodHandle MH_initZip, MH_zipPred, MH_zipStep;
+        Class<?> IT = Iterator.class;
+        Class<?> L = List.class;
+        MH_initZip = LOOKUP.findStatic(THIS_CLASS, "initZip", methodType(L, IT, IT));
+        MH_zipPred = LOOKUP.findStatic(THIS_CLASS, "zipPred", methodType(boolean.class, L, IT, IT));
+        MH_zipStep = LOOKUP.findStatic(THIS_CLASS, "zipStep", methodType(L, L, IT, IT));
+        {{
+{} /// JAVADOC
+// implement the zip function for lists as a loop handle
+MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep);
+List<String> a = Arrays.asList("a", "b", "c", "d");
+List<String> b = Arrays.asList("e", "f", "g", "h");
+List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
+assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
+{}
+        }}
+    }
+
+    static int zero(int limit) { return 0; }
+    static int step(int i, int limit) { return i + 1; }
+    static boolean pred(int i, int limit) { return i < limit; }
+
+    @Test public void testDoWhileLoop() throws Throwable {
+        MethodHandle MH_zero, MH_step, MH_pred;
+        Class<?> I = int.class;
+        MH_zero = LOOKUP.findStatic(THIS_CLASS, "zero", methodType(I, I));
+        MH_step = LOOKUP.findStatic(THIS_CLASS, "step", methodType(I, I, I));
+        MH_pred = LOOKUP.findStatic(THIS_CLASS, "pred", methodType(boolean.class, I, I));
+        {{
+{} /// JAVADOC
+// int i = 0; while (i < limit) { ++i; } return i; => limit
+MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
+assertEquals(23, loop.invoke(23));
+{}
+        }}
+    }
+
+    static String step(String v, int counter, String start_) { return "na " + v; }  //#0
+    static String step(String v, int counter ) { return "na " + v; } //#1
+    static String step(String v, int counter, int iterations_, String pre, String start_) { return pre + " " + v; } //#2
+    static String step3(String v, int counter, String pre) { return pre + " " + v; } //#3
+
+    @Test public void testCountedLoop() throws Throwable {
+        MethodHandle MH_step;
+        Class<?> S = String.class, I = int.class;
+        // Theme:
+        MH_step = LOOKUP.findStatic(THIS_CLASS, "step", methodType(S, S, I, S));
+        {{
+{} /// JAVADOC
+// String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
+// => a variation on a well known theme
+MethodHandle fit13 = MethodHandles.constant(int.class, 13);
+MethodHandle start = MethodHandles.identity(String.class);
+MethodHandle loop = MethodHandles.countedLoop(fit13, start, MH_step);  // (v, i, _) -> "na " + v
+assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+{}
+        }}
+        // Variation #1:
+        MH_step = LOOKUP.findStatic(THIS_CLASS, "step", methodType(S, S, I));
+        {{
+{} /// JAVADOC
+// String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
+// => a variation on a well known theme
+MethodHandle count = MethodHandles.dropArguments(MethodHandles.identity(int.class), 1, String.class);
+MethodHandle start = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, int.class);
+MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step);  // (v, i) -> "na " + v
+assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "Lambdaman!"));
+{}
+            assertEquals("na na Lambdaman!", loop.invoke(2, "Lambdaman!"));
+            assertEquals("Lambdaman!", loop.invoke(0, "Lambdaman!"));
+            assertEquals("Lambdaman!", loop.invoke(-1, "Lambdaman!"));
+            assertEquals("Lambdaman!", loop.invoke(Integer.MIN_VALUE, "Lambdaman!"));
+        }}
+        // Variation #2:
+        MH_step = LOOKUP.findStatic(THIS_CLASS, "step", methodType(S, S, I, I, S, S));
+        {{
+{} /// JAVADOC
+// String s = "Lambdaman!", t = "na"; for (int i = 0; i < 13; ++i) { s = t + " " + s; } return s;
+// => a variation on a well known theme
+MethodHandle count = MethodHandles.identity(int.class);
+MethodHandle start = MethodHandles.dropArguments(MethodHandles.identity(String.class), 0, int.class, String.class);
+MethodHandle loop = MethodHandles.countedLoop(count, start, MH_step);  // (v, i, _, pre, _) -> pre + " " + v
+assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke(13, "na", "Lambdaman!"));
+{}
+        }}
+        // Variation #3:
+        MH_step = LOOKUP.findStatic(THIS_CLASS, "step3", methodType(S, S, I, S));
+        {{
+{} /// JAVADOC
+// String s = "Lambdaman!", t = "na"; for (int i = 0; i < 13; ++i) { s = t + " " + s; } return s;
+// => a variation on a well known theme
+MethodType loopType = methodType(String.class, String.class, int.class, String.class);
+MethodHandle count = MethodHandles.dropArgumentsToMatch(MethodHandles.identity(int.class),    0, loopType.parameterList(), 1);
+MethodHandle start = MethodHandles.dropArgumentsToMatch(MethodHandles.identity(String.class), 0, loopType.parameterList(), 2);
+MethodHandle body  = MethodHandles.dropArgumentsToMatch(MH_step,                              2, loopType.parameterList(), 0);
+MethodHandle loop = MethodHandles.countedLoop(count, start, body);  // (v, i, pre, _, _) -> pre + " " + v
+assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("na", 13, "Lambdaman!"));
+{}
+        }}
+    }
+
+    static List<String> reverseStep(List<String> r, String e) {
+        r.add(0, e);
+        return r;
+    }
+    static List<String> newArrayList() { return new ArrayList<>(); }
+
+    @Test public void testIteratedLoop() throws Throwable {
+        MethodHandle MH_newArrayList, MH_reverseStep;
+        Class<?> L = List.class, S = String.class;
+        MH_newArrayList = LOOKUP.findStatic(THIS_CLASS, "newArrayList", methodType(L));
+        MH_reverseStep = LOOKUP.findStatic(THIS_CLASS, "reverseStep", methodType(L, L, S));
+        {{
+{} /// JAVADOC
+// reverse a list
+MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
+List<String> list = Arrays.asList("a", "b", "c", "d", "e");
+List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
+assertEquals(reversedList, (List<String>) loop.invoke(list));
+{}
+        }}
+    }
+
+    @Test public void testFoldArguments3() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
+        "println", methodType(void.class, String.class))
+        .bindTo(System.out);
+MethodHandle cat = lookup().findVirtual(String.class,
+        "concat", methodType(String.class, String.class));
+assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
+MethodHandle catTrace = foldArguments(cat, 1, trace);
+// also prints "jum":
+assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
+{}
+        }}
+    }
+
+    @Test public void testAsCollector2() throws Throwable {
+        {{
+{} /// JAVADOC
+StringWriter swr = new StringWriter();
+MethodHandle swWrite = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).bindTo(swr);
+MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
+swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
+assertEquals("BC", swr.toString());
+swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
+assertEquals("BCPQRS", swr.toString());
+swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
+assertEquals("BCPQRSZ", swr.toString());
+{}
+        }}
+    }
+
+    @Test public void testAsSpreader2() throws Throwable {
+        {{
+{} /// JAVADOC
+MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
+MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
+Object[] ints = new Object[]{3, 9, 7, 7};
+Comparator<Integer> cmp = (a, b) -> a - b;
+assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
+assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
+assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
+{}
+        }}
+    }
+
+    /* ---- TEMPLATE ----
+    @Test public void testFoo() throws Throwable {
+        {{
+{} /// JAVADOC
+{}
+            }}
+    }
+    */
+}
diff --git a/ojluni/src/test/java/lang/invoke/LoopCombinatorTest.java b/ojluni/src/test/java/lang/invoke/LoopCombinatorTest.java
new file mode 100644
index 0000000..96d7cd1
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/LoopCombinatorTest.java
@@ -0,0 +1,1383 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @bug 8150635
+ * @bug 8150956
+ * @bug 8150957
+ * @bug 8151179
+ * @bug 8152667
+ * @bug 8153637
+ * @bug 8154751
+ * @bug 8154754
+ * @bug 8167974
+ * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.util.*;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the loop combinators introduced in JEP 274.
+ */
+public class LoopCombinatorTest {
+
+    static final Lookup LOOKUP = MethodHandles.lookup();
+
+    @Test
+    public static void testLoopFac() throws Throwable {
+        MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
+        MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+        MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+        assertEquals(Fac.MT_fac, loop.type());
+        assertEquals(120, loop.invoke(5));
+    }
+
+    @Test
+    public static void testLoopFacNullInit() throws Throwable {
+        // null initializer for counter, should initialize to 0
+        MethodHandle[] counterClause = new MethodHandle[]{null, Fac.MH_inc};
+        MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+        MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+        assertEquals(Fac.MT_fac, loop.type());
+        assertEquals(120, loop.invoke(5));
+    }
+
+    @Test
+    public static void testLoopNullInit() throws Throwable {
+        // null initializer for counter, should initialize to 0, one-clause loop
+        MethodHandle[] counterClause = new MethodHandle[]{null, Loop.MH_inc, Loop.MH_pred, Loop.MH_fin};
+        MethodHandle loop = MethodHandles.loop(counterClause);
+        assertEquals(Loop.MT_loop, loop.type());
+        assertEquals(10, loop.invoke(10));
+    }
+
+    @Test
+    public static void testLoopVoid1() throws Throwable {
+        // construct a post-checked loop that only does one iteration and has a void body and void local state
+        MethodHandle loop = MethodHandles.loop(new MethodHandle[]{Empty.MH_f, Empty.MH_f, Empty.MH_pred, null});
+        assertEquals(MethodType.methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @Test
+    public static void testLoopVoid2() throws Throwable {
+        // construct a post-checked loop that only does one iteration and has a void body and void local state,
+        // initialized implicitly from the step type
+        MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, null});
+        assertEquals(MethodType.methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @Test
+    public static void testLoopVoid3() throws Throwable {
+        // construct a post-checked loop that only does one iteration and has a void body and void local state,
+        // and that has a void finalizer
+        MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_f});
+        assertEquals(MethodType.methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @Test
+    public static void testLoopFacWithVoidState() throws Throwable {
+        // like testLoopFac, but with additional void state that outputs a dot
+        MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc};
+        MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+        MethodHandle[] dotClause = new MethodHandle[]{null, Fac.MH_dot};
+        MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause, dotClause);
+        assertEquals(Fac.MT_fac, loop.type());
+        assertEquals(120, loop.invoke(5));
+    }
+
+    @Test
+    public static void testLoopVoidInt() throws Throwable {
+        // construct a post-checked loop that only does one iteration and has a void body and void local state,
+        // and that returns a constant
+        MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_c});
+        assertEquals(MethodType.methodType(int.class), loop.type());
+        assertEquals(23, loop.invoke());
+    }
+
+    @Test
+    public static void testLoopWithVirtuals() throws Throwable {
+        // construct a loop (to calculate factorial) that uses a mix of static and virtual methods
+        MethodHandle[] counterClause = new MethodHandle[]{null, LoopWithVirtuals.permute(LoopWithVirtuals.MH_inc)};
+        MethodHandle[] accumulatorClause = new MethodHandle[]{
+                // init function must indicate the loop arguments (there is no other means to determine them)
+                MethodHandles.dropArguments(LoopWithVirtuals.MH_one, 0, LoopWithVirtuals.class),
+                LoopWithVirtuals.permute(LoopWithVirtuals.MH_mult),
+                LoopWithVirtuals.permute(LoopWithVirtuals.MH_pred),
+                LoopWithVirtuals.permute(LoopWithVirtuals.MH_fin)
+        };
+        MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+        assertEquals(LoopWithVirtuals.MT_loop, loop.type());
+        assertEquals(120, loop.invoke(new LoopWithVirtuals(), 5));
+    }
+
+    @Test
+    public static void testLoopOmitPred() throws Throwable {
+        // construct a loop to calculate factorial that omits a predicate
+        MethodHandle[] counterClause = new MethodHandle[]{null, Fac.MH_inc, null, Fac.MH_fin};
+        MethodHandle[] accumulatorClause = new MethodHandle[]{Fac.MH_one, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin};
+        MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause);
+        assertEquals(Fac.MT_fac, loop.type());
+        assertEquals(120, loop.invoke(5));
+    }
+
+    @DataProvider
+    static Object[][] negativeTestData() {
+        MethodHandle i0 = MethodHandles.constant(int.class, 0);
+        MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class);
+        MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class);
+        MethodHandle i3 = MethodHandles.dropArguments(i0, 0, int.class, int.class, int.class);
+        List<MethodHandle> inits = Arrays.asList(ii, id, i3);
+        List<Class<?>> ints3 = Arrays.asList(int.class, int.class, int.class);
+        List<Class<?>> ints4 = Arrays.asList(int.class, int.class, int.class, int.class);
+        List<MethodHandle> finis = Arrays.asList(Fac.MH_fin, Fac.MH_inc, Counted.MH_step);
+        List<MethodHandle> preds1 = Arrays.asList(null, null, null);
+        List<MethodHandle> preds2 = Arrays.asList(null, Fac.MH_fin, null);
+        MethodHandle eek = MethodHandles.dropArguments(i0, 0, int.class, int.class, double.class);
+        List<MethodHandle> nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot);
+        List<MethodHandle> nepreds = Arrays.asList(null, Fac.MH_pred, null);
+        List<MethodHandle> nefinis = Arrays.asList(null, Fac.MH_fin, null);
+        List<MethodHandle> lvsteps = Arrays.asList(LoopWithVirtuals.MH_inc, LoopWithVirtuals.MH_mult);
+        List<MethodHandle> lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred);
+        List<MethodHandle> lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin);
+        return new Object[][] {
+                {null, "null or no clauses passed"},
+                {new MethodHandle[][]{}, "null or no clauses passed"},
+                {new MethodHandle[][]{{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}},
+                        "All loop clauses must be represented as MethodHandle arrays with at most 4 elements."},
+                {new MethodHandle[][]{{null, Fac.MH_inc}, null}, "null clauses are not allowed"},
+                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_dot}},
+                        "clause 0: init and step return types must match: int != void"},
+                {new MethodHandle[][]{{ii}, {id}, {i3}},
+                        "found non-effectively identical init parameter type lists: " + inits +
+                                " (common suffix: " + ints3 + ")"},
+                {new MethodHandle[][]{{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc},
+                        {null, Counted.MH_start, null, Counted.MH_step}},
+                        "found non-identical finalizer return types: " + finis + " (return type: int)"},
+                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin},
+                        {null, Fac.MH_dot}}, "no predicate found: " + preds1},
+                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin},
+                        {null, Fac.MH_dot}}, "predicates must have boolean return type: " + preds2},
+                {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin},
+                        {null, Fac.MH_dot}},
+                        "found non-effectively identical parameter type lists:\nstep: " + nesteps +
+                                "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints3 + ")"},
+                {new MethodHandle[][]{{null, LoopWithVirtuals.MH_inc},
+                        {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}},
+                        "found non-effectively identical parameter type lists:\nstep: " + lvsteps +
+                                "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints4 + ")"}
+        };
+    }
+
+    static final MethodHandle MH_loop;
+
+    static {
+        try {
+            MH_loop = LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class));
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    @Test(dataProvider = "negativeTestData")
+    public static void testLoopNegative(MethodHandle[][] clauses, String expectedMessage) throws Throwable {
+        boolean caught = false;
+        try {
+            MH_loop.invokeWithArguments((Object[]) clauses);
+        } catch (IllegalArgumentException iae) {
+            assertEquals(expectedMessage, iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test(dataProvider = "whileLoopTestData")
+    public static void testWhileLoop(MethodHandle MH_zero,
+                                     MethodHandle MH_pred,
+                                     MethodHandle MH_step,
+                                     String messageOrNull) throws Throwable {
+        // int i = 0; while (i < limit) { ++i; } return i; => limit
+        try {
+            MethodHandle loop = MethodHandles.whileLoop(MH_zero, MH_pred, MH_step);
+            assert messageOrNull == null;
+            if (MH_step.type().equals(While.MH_step.type()))
+                assertEquals(While.MT_while, loop.type());
+            assertEquals(MH_step.type().dropParameterTypes(0, 1), loop.type());
+            while (loop.type().parameterCount() > 1)  loop = snip(loop);
+            assertEquals(23, loop.invoke(23));
+        } catch (IllegalArgumentException iae) {
+            assert messageOrNull != null;
+            assertEqualsFIXME(messageOrNull, iae.getMessage());
+        }
+    }
+
+    static void assertEqualsFIXME(String expect, String actual) {
+        if (!expect.equals(actual)) {
+            // just issue a warning
+            System.out.println("*** "+actual+"\n != "+expect);
+        }
+    }
+
+    @DataProvider
+    static Object[][] whileLoopTestData() {
+        MethodHandle
+            zeroI = While.MH_zero,
+            zeroX = snip(zeroI),
+            zeroIB = slap(zeroI, byte.class),
+            predII = While.MH_pred,
+            predIX = snip(predII),
+            predIIB = slap(predII, byte.class),
+            stepII = While.MH_step,
+            stepIX = snip(stepII),
+            stepIIB = slap(stepII, byte.class)
+            ;
+        return new Object[][] {
+            // normal while loop clauses, perhaps with effectively-identical reductions
+            {zeroI, predII, stepII, null},
+            {zeroX, predII, stepII, null},
+            {null, predII, stepII, null},
+            // expanded while loop clauses
+            {zeroIB, predIIB, stepIIB, null},
+            {zeroI, predIIB, stepIIB, null},
+            {null, predIIB, stepIIB, null},
+            {zeroIB, predII, stepIIB, null},
+            {zeroX, predII, stepIIB, null},
+            {null, predII, stepIIB, null},
+            // short step clauses cause errors
+            {zeroI, predII, stepIX, "loop predicate must match: (int,int)boolean != (int)boolean"},
+            {zeroIB, predIX, stepIX, "loop initializer must match: (int,byte)int != ()int"},
+            // bad body type
+            {zeroI, predII, tweak(stepII, -1, char.class), "body function must match: (int,int)char != (char,int,int)char"},
+            {zeroI, predII, tweak(stepII,  0, char.class), "body function must match: (char,int)int != (int,char,int)int"},
+            // bad pred type
+            {zeroI, tweak(predII, -1, char.class), stepII, "loop predicate must match: (int,int)char != (int,int)boolean"},
+            {zeroI, tweak(predII,  0, char.class), stepII, "loop predicate must match: (char,int)boolean != (int,int)boolean"},
+            // bad init type
+            {tweak(zeroI, -1, char.class), predII, stepII, "loop initializer must match: (int)char != (int)int"},
+            {tweak(zeroI,  0, char.class), predII, stepII, "loop initializer must match: (char)int != (int)int"},
+        };
+    }
+
+    // tweak the type of an MH
+    static MethodHandle tweak(MethodHandle mh, int argPos, Class<?> type) {
+        MethodType mt = mh.type();
+        if (argPos == -1)
+            mt = mt.changeReturnType(type);
+        else
+            mt = mt.changeParameterType(argPos, type);
+        return MethodHandles.explicitCastArguments(mh, mt);
+    }
+    // snip off an MH argument, hard-wiring to zero
+    static MethodHandle snip(MethodHandle mh, int argPos) {
+        if (argPos < 0)  return null;  // special case for optional args
+        Class<?> argType = mh.type().parameterType(argPos);
+        Object zero;
+        try {
+            zero = MethodHandles.zero(argType).invoke();
+        } catch (Throwable ex) {
+            throw new AssertionError(ex);
+        }
+        return MethodHandles.insertArguments(mh, argPos, zero);
+    }
+    static MethodHandle snip(MethodHandle mh) {
+        return snip(mh, mh.type().parameterCount()-1);
+    }
+    // slap on an extra type on the end of the MH
+    static MethodHandle slap(MethodHandle mh, Class<?> addType) {
+        return MethodHandles.dropArguments(mh, mh.type().parameterCount(), addType);
+    }
+
+    @Test
+    public static void testWhileLoopNoIteration() throws Throwable {
+        // a while loop that never executes its body because the predicate evaluates to false immediately
+        MethodHandle loop = MethodHandles.whileLoop(While.MH_initString, While.MH_predString, While.MH_stepString);
+        assertEquals(While.MT_string, loop.type());
+        assertEquals("a", loop.invoke());
+    }
+
+    @Test(dataProvider = "whileLoopTestData")
+    public static void testDoWhileLoop(MethodHandle MH_zero,
+                                       MethodHandle MH_pred,
+                                       MethodHandle MH_step,
+                                       String messageOrNull) throws Throwable {
+        // int i = 0; do { ++i; } while (i < limit); return i; => limit
+        try {
+            MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
+            assert messageOrNull == null;
+            if (MH_step.type().equals(While.MH_step.type()))
+                assertEquals(While.MT_while, loop.type());
+            assertEquals(MH_step.type().dropParameterTypes(0, 1), loop.type());
+            while (loop.type().parameterCount() > 1)  loop = snip(loop);
+            assertEquals(23, loop.invoke(23));
+        } catch (IllegalArgumentException iae) {
+            assert messageOrNull != null;
+            if (!messageOrNull.equals(iae.getMessage())) {
+                // just issue a warning
+                System.out.println("*** "+messageOrNull+"\n != "+iae.getMessage());
+            }
+        }
+    }
+
+    @Test
+    public static void testDoWhileBadInit() throws Throwable {
+        boolean caught = false;
+        try {
+            While w = new While();
+            MethodHandle loop = MethodHandles.doWhileLoop(MethodHandles.empty(methodType(char.class)),
+                                                          While.MH_voidBody.bindTo(w),
+                                                          While.MH_voidPred.bindTo(w));
+        } catch (IllegalArgumentException iae) {
+            assertEquals("loop initializer must match: ()char != (int)void", iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public static void testWhileZip() throws Throwable {
+        MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred);
+        assertEquals(While.MT_zip, loop.type());
+        List<String> a = Arrays.asList("a", "b", "c", "d");
+        List<String> b = Arrays.asList("e", "f", "g", "h");
+        List<String> zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
+        assertEquals(zipped, (List<String>) loop.invoke(a.iterator(), b.iterator()));
+    }
+
+    @Test
+    public static void testWhileBadInit() throws Throwable {
+        boolean caught = false;
+        try {
+            While w = new While();
+            MethodHandle loop = MethodHandles.whileLoop(MethodHandles.empty(methodType(void.class, char.class)),
+                                                        While.MH_voidPred.bindTo(w),
+                                                        While.MH_voidBody.bindTo(w));
+        } catch (IllegalArgumentException iae) {
+            assertEquals("loop initializer must match: (char)void != (int)void", iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public static void testWhileVoidInit() throws Throwable {
+        While w = new While();
+        int v = 5;
+        MethodHandle loop = MethodHandles.whileLoop(While.MH_voidInit.bindTo(w), While.MH_voidPred.bindTo(w),
+                While.MH_voidBody.bindTo(w));
+        assertEquals(While.MT_void, loop.type());
+        loop.invoke(v);
+        assertEquals(v, w.i);
+    }
+
+    @Test
+    public static void testDoWhileVoidInit() throws Throwable {
+        While w = new While();
+        int v = 5;
+        MethodHandle loop = MethodHandles.doWhileLoop(While.MH_voidInit.bindTo(w), While.MH_voidBody.bindTo(w),
+                While.MH_voidPred.bindTo(w));
+        assertEquals(While.MT_void, loop.type());
+        loop.invoke(v);
+        assertEquals(v, w.i);
+    }
+
+    @DataProvider
+    static Object[][] nullArgs() {
+        MethodHandle c = MethodHandles.constant(int.class, 1);
+        return new Object[][]{{null, c}, {c, null}};
+    }
+
+    @Test(dataProvider = "nullArgs", expectedExceptions = NullPointerException.class)
+    public static void testWhileNullArgs(MethodHandle pred, MethodHandle body) {
+        MethodHandles.whileLoop(null, pred, body);
+    }
+
+    @Test(dataProvider = "nullArgs", expectedExceptions = NullPointerException.class)
+    public static void testDoWhileNullArgs(MethodHandle body, MethodHandle pred) {
+        MethodHandles.whileLoop(null, body, pred);
+    }
+
+    @Test
+    public static void testCountedLoop() throws Throwable {
+        // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme
+        MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, String.class);
+        MethodHandle loop = MethodHandles.countedLoop(fit13, Counted.MH_start, Counted.MH_step);
+        assertEquals(Counted.MT_counted, loop.type());
+        assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+    }
+
+    @Test
+    public static void testCountedLoopVoidInit() throws Throwable {
+        MethodHandle fit5 = MethodHandles.constant(int.class, 5);
+        for (int i = 0; i < 8; i++) {
+            MethodHandle zero = MethodHandles.zero(void.class);
+            MethodHandle init = fit5;
+            MethodHandle body = Counted.MH_printHello;
+            boolean useNull = (i & 1) != 0, addInitArg = (i & 2) != 0, addBodyArg = (i & 4) != 0;
+            if (useNull)    zero = null;
+            if (addInitArg) init = MethodHandles.dropArguments(init, 0, int.class);
+            if (addBodyArg) body = MethodHandles.dropArguments(body, 1, int.class);
+            System.out.println("testCountedLoopVoidInit i="+i+" : "+Arrays.asList(init, zero, body));
+            MethodHandle loop = MethodHandles.countedLoop(init, zero, body);
+            MethodType expectedType = Counted.MT_countedPrinting;
+            if (addInitArg || addBodyArg)
+                expectedType = expectedType.insertParameterTypes(0, int.class);
+            assertEquals(expectedType, loop.type());
+            if (addInitArg || addBodyArg)
+                loop.invoke(99);
+            else
+                loop.invoke();
+        }
+    }
+
+    @Test
+    public static void testCountedArrayLoop() throws Throwable {
+        // int[] a = new int[]{0}; for (int i = 0; i < 13; ++i) { ++a[0]; } => a[0] == 13
+        MethodHandle fit13 = MethodHandles.dropArguments(MethodHandles.constant(int.class, 13), 0, int[].class);
+        MethodHandle loop = MethodHandles.countedLoop(fit13, null, Counted.MH_stepUpdateArray);
+        assertEquals(Counted.MT_arrayCounted, loop.type());
+        int[] a = new int[]{0};
+        loop.invoke(a);
+        assertEquals(13, a[0]);
+    }
+
+    @Test
+    public static void testCountedPrintingLoop() throws Throwable {
+        MethodHandle fit5 = MethodHandles.constant(int.class, 5);
+        MethodHandle loop = MethodHandles.countedLoop(fit5, null, Counted.MH_printHello);
+        assertEquals(Counted.MT_countedPrinting, loop.type());
+        loop.invoke();
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public static void testCountedLoopNullBody() throws Throwable {
+        MethodHandle h5 = MethodHandles.constant(int.class, 5);
+        MethodHandle h13 = MethodHandles.constant(int.class, 13);
+        MethodHandle loop = MethodHandles.countedLoop(h5, h13, null);
+        assertEquals(methodType(int.class), loop.type());
+        assertEquals(13, loop.invoke());
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public static void testCountedLoopNullIterations() throws Throwable {
+        MethodHandle loop = MethodHandles.countedLoop(null, null, null);
+        assertEquals(methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public static void testCountedLoopNullInitAndBody() throws Throwable {
+        MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null);
+        assertEquals(methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @DataProvider
+    static Object[][] countedLoopBodyParameters() {
+        Class<?> V = String.class, I = int.class, A = List.class;
+        // return types are of these forms:
+        //    {count = int(A...), init = V(A...), body = V(V, I, A...)}
+        return new Object[][] {
+            // body leads determining A...
+            {methodType(I), methodType(V), methodType(V, V, I)},
+            {methodType(I), methodType(V), methodType(V, V, I, A)},
+            {methodType(I,A), methodType(V), methodType(V, V, I, A)},
+            {methodType(I), methodType(V,A), methodType(V, V, I, A)},
+            // body leads, with void V
+            {methodType(I), methodType(void.class), methodType(void.class, I)},
+            {methodType(I), methodType(void.class), methodType(void.class, I, A)},
+            {methodType(I,A), methodType(void.class), methodType(void.class, I, A)},
+            {methodType(I), methodType(void.class,A), methodType(void.class, I, A)},
+            // count leads determining A..., but only if body drops all A...
+            {methodType(I,A), methodType(V), methodType(V, V, I)},
+            {methodType(I,A), methodType(V,A), methodType(V, V, I)},
+            // count leads, with void V
+            {methodType(I,A), methodType(void.class), methodType(void.class, I)},
+            {methodType(I,A), methodType(void.class,A), methodType(void.class, I)},
+        };
+    }
+
+    @Test(dataProvider = "countedLoopBodyParameters")
+    public static void testCountedLoopBodyParameters(MethodType countType, MethodType initType, MethodType bodyType) throws Throwable {
+        MethodHandle loop = MethodHandles.countedLoop(
+                MethodHandles.empty(countType),
+                initType == null ? null : MethodHandles.empty(initType),
+                MethodHandles.empty(bodyType));
+        // The rule:  If body takes the minimum number of parameters, then take what countType offers.
+        // The initType has to just roll with whatever the other two agree on.
+        int innerParams = (bodyType.returnType() == void.class ? 1 : 2);
+        MethodType expectType = bodyType.dropParameterTypes(0, innerParams);
+        if (expectType.parameterCount() == 0)
+            expectType = expectType.insertParameterTypes(0, countType.parameterList());
+        assertEquals(expectType, loop.type());
+    }
+
+    @Test(dataProvider = "countedLoopBodyParameters")
+    public static void testCountedLoopBodyParametersNullInit(MethodType countType, MethodType initType, MethodType bodyType) throws Throwable {
+        testCountedLoopBodyParameters(countType, null, bodyType);
+    }
+
+    @Test
+    public static void testCountedLoopStateInitializedToNull() throws Throwable {
+        MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5),
+                MethodHandles.empty(methodType(String.class)), Counted.MH_stateBody);
+        assertEquals(Counted.MT_bodyDeterminesState, loop.type());
+        assertEquals("sssssnull01234", loop.invoke());
+    }
+
+    @Test
+    public static void testCountedLoopArgsDefinedByIterations() throws Throwable {
+        MethodHandle iterations =
+                MethodHandles.dropArguments(MethodHandles.constant(int.class, 3), 0, String.class);
+        MethodHandle loop = MethodHandles.countedLoop(iterations,
+                MethodHandles.empty(iterations.type().changeReturnType(String.class)), Counted.MH_append);
+        assertEquals(Counted.MT_iterationsDefineArgs, loop.type());
+        assertEquals("hello012", loop.invoke("hello"));
+    }
+
+    @Test
+    public static void testCountedRangeLoop() throws Throwable {
+        // String s = "Lambdaman!"; for (int i = -5; i < 8; ++i) { s = "na " + s; } return s; => a well known theme
+        MethodHandle fitm5 = MethodHandles.dropArguments(Counted.MH_m5, 0, String.class);
+        MethodHandle fit8 = MethodHandles.dropArguments(Counted.MH_8, 0, String.class);
+        MethodHandle loop = MethodHandles.countedLoop(fitm5, fit8, Counted.MH_start, Counted.MH_step);
+        assertEquals(Counted.MT_counted, loop.type());
+        assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!"));
+    }
+
+    @Test
+    public static void testCountedLoopCounterInit() throws Throwable {
+        // int x = 0; for (int i = 0; i < 5; ++i) { x += i; } return x; => 10
+        // (only if counter's first value in body is 0)
+        MethodHandle iter = MethodHandles.constant(int.class, 5);
+        MethodHandle init = MethodHandles.constant(int.class, 0);
+        MethodHandle body = Counted.MH_addCounter;
+        MethodHandle loop = MethodHandles.countedLoop(iter, init, body);
+        assertEquals(Counted.MT_counterInit, loop.type());
+        assertEquals(10, loop.invoke());
+    }
+
+    @Test
+    public static void testCountedLoopEmpty() throws Throwable {
+        // for (int i = 0; i < 5; ++i) { /* empty */ }
+        MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null,
+                MethodHandles.empty(methodType(void.class, int.class)));
+        assertEquals(methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @Test
+    public static void testCountedRangeLoopEmpty() throws Throwable {
+        // for (int i = -5; i < 5; ++i) { /* empty */ }
+        MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, -5),
+                MethodHandles.constant(int.class, 5), null, MethodHandles.empty(methodType(void.class, int.class)));
+        assertEquals(methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @DataProvider
+    static Object[][] countedLoopNegativeData() {
+        // Android-changed: inclusive language renaming local variable to 'zero'.
+        MethodHandle zero = MethodHandles.zero(void.class);
+        MethodHandle one = MethodHandles.constant(int.class, 1);
+        MethodHandle oneString = MethodHandles.dropArguments(one, 0, String.class);
+        MethodHandle oneDouble = MethodHandles.dropArguments(one, 0, double.class);
+        return new Object[][]{
+                {zero, one, zero, zero, String.format("start/end must return int %s, %s", zero, one)},
+                {one, zero, zero, zero, String.format("start/end must return int %s, %s", one, zero)},
+                {oneString, oneDouble, zero, zero,
+                        String.format("start and end parameter types must match: %s != %s", oneString.type(),
+                                oneDouble.type())},
+                {oneString, oneString, zero, zero,
+                        String.format("start/end and init parameter types must match: %s != %s", oneString.type(),
+                                zero.type())},
+                {one, one, null, zero, String.format("actual and expected body signatures must match: %s != %s",
+                        zero.type(), zero.type().appendParameterTypes(int.class))}
+        };
+    }
+
+    @Test(dataProvider = "countedLoopNegativeData")
+    public static void testCountedLoopNegative(MethodHandle start, MethodHandle end, MethodHandle init,
+                                               MethodHandle body, String msg) {
+        if (true)  return;  //%%%FIXME%%%%
+        boolean caught = false;
+        try {
+            MethodHandles.countedLoop(start, end, init, body);
+        } catch (IllegalArgumentException iae) {
+            assertEquals(msg, iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public static void testIterateSum() throws Throwable {
+        // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21
+        MethodHandle loop = MethodHandles.iteratedLoop(Iterate.MH_sumIterator, Iterate.MH_sumInit, Iterate.MH_sumStep);
+        assertEquals(Iterate.MT_sum, loop.type());
+        assertEquals(21, loop.invoke(new Integer[]{1, 2, 3, 4, 5, 6}));
+    }
+
+    @DataProvider
+    static Object[][] iteratorInits() {
+        return new Object[][]{{Iterate.MH_iteratorFromList}, {Iterate.MH_iteratorFromIterable}, {null}};
+    }
+
+    @Test(dataProvider = "iteratorInits")
+    public static void testIterateReverse(MethodHandle iterator) throws Throwable {
+        // this test uses List as its loop state type; don't try to change that
+        if (iterator != null)
+            iterator = iterator.asType(iterator.type().changeParameterType(0, List.class));
+        for (int i = 0; i < 4; i++) {
+            MethodHandle init = Iterate.MH_reverseInit, body = Iterate.MH_reverseStep;
+            boolean snipInit = (i & 1) != 0, snipBody = (i & 2) != 0;
+            if (snipInit)  init = snip(init);
+            if (snipBody)  body = snip(body);
+            if (!snipInit && snipBody && iterator == null) {
+                // Body does not determine (A...), so the default guy just picks Iterable.
+                // If body insisted on (List), the default guy would adjust himself.
+                // Init has no authority to change the (A...), so must patch init.
+                // All according to plan!
+                init = slap(snip(init), Iterable.class);
+            }
+            System.out.println("testIterateReverse i="+i+" : "+Arrays.asList(iterator, init, body));
+            MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, body);
+            MethodType expectedType = Iterate.MT_reverse;
+            if (iterator == null && i >= 2)
+                expectedType = expectedType.changeParameterType(0, Iterable.class);
+            assertEquals(expectedType, loop.type());
+            List<String> list = Arrays.asList("a", "b", "c", "d", "e");
+            List<String> reversedList = Arrays.asList("e", "d", "c", "b", "a");
+            assertEquals(reversedList, (List<String>) loop.invoke(list));
+        }
+    }
+
+    @Test(dataProvider = "iteratorInits")
+    public static void testIterateLength(MethodHandle iterator) throws Throwable {
+        MethodHandle body = Iterate.MH_lengthStep;
+        MethodHandle init = Iterate.MH_lengthInit;
+        MethodType expectedType = Iterate.MT_length;
+        int barity = body.type().parameterCount();
+        Class<?> iteratorSource = iterator == null ? null : iterator.type().parameterType(0);
+        if (iterator != null && iteratorSource != body.type().parameterType(barity-1)) {
+            // adjust body to accept the other type
+            body = body.asType(body.type().changeParameterType(barity-1, iteratorSource));
+            init = init.asType(init.type().changeParameterType(0, iteratorSource));
+            expectedType = expectedType.changeParameterType(0, iteratorSource);
+        }
+        for (;; init = snip(init)) {
+            System.out.println("testIterateLength.init = "+init);
+            MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, body);
+            assertEquals(expectedType, loop.type());
+            List<Double> list = Arrays.asList(23.0, 148.0, 42.0);
+            assertEquals(list.size(), (int) loop.invoke(list));
+            if (init == null)  break;
+        }
+    }
+
+    @Test(dataProvider = "iteratorInits")
+    public static void testIterateMap(MethodHandle iterator) throws Throwable {
+        MethodHandle body = Iterate.MH_mapStep;
+        MethodHandle init = Iterate.MH_mapInit;
+        MethodType expectedType = Iterate.MT_map;
+        int barity = body.type().parameterCount();
+        Class<?> iteratorSource = iterator == null ? null : iterator.type().parameterType(0);
+        if (iterator != null && iteratorSource != body.type().parameterType(barity-1)) {
+            // adjust body to accept the other type
+            body = body.asType(body.type().changeParameterType(barity-1, iteratorSource));
+            init = init.asType(init.type().changeParameterType(0, iteratorSource));
+            expectedType = expectedType.changeParameterType(0, iteratorSource);
+        }
+        for (; init != null; init = snip(init)) {
+            System.out.println("testIterateMap.init = "+init);
+            MethodHandle loop = MethodHandles.iteratedLoop(iterator, init, body);
+            assertEquals(expectedType, loop.type());
+            List<String> list = Arrays.asList("Hello", "world", "!");
+            List<String> upList = Arrays.asList("HELLO", "WORLD", "!");
+            assertEquals(upList, (List<String>) loop.invoke(list));
+        }
+    }
+
+    @Test(dataProvider = "iteratorInits")
+    public static void testIteratePrint(MethodHandle iterator) throws Throwable {
+        MethodHandle body = Iterate.MH_printStep;
+        MethodType expectedType = Iterate.MT_print;
+        int barity = body.type().parameterCount();
+        Class<?> iteratorSource = iterator == null ? null : iterator.type().parameterType(0);
+        if (iterator != null && iteratorSource != body.type().parameterType(barity-1)) {
+            // adjust body to accept the other type
+            body = body.asType(body.type().changeParameterType(barity-1, iteratorSource));
+            expectedType = expectedType.changeParameterType(0, iteratorSource);
+        }
+        MethodHandle loop = MethodHandles.iteratedLoop(iterator, null, body);
+        assertEquals(expectedType, loop.type());
+        loop.invoke(Arrays.asList("hello", "world"));
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public static void testIterateNullBody() {
+        MethodHandles.iteratedLoop(MethodHandles.empty(methodType(Iterator.class, int.class)),
+                MethodHandles.identity(int.class), null);
+    }
+
+    @DataProvider
+    static Object[][] wrongIteratorTypes() {
+        return new Object[][]{{void.class}, {Object.class}, {Iterable.class}};
+    }
+
+    @Test(dataProvider = "wrongIteratorTypes")
+    public static void testIterateVoidIterator(Class<?> it) {
+        boolean caught = false;
+        MethodType v = methodType(it);
+        try {
+            MethodHandles.iteratedLoop(MethodHandles.empty(v), null, MethodHandles.empty(v));
+        } catch(IllegalArgumentException iae) {
+            assertEqualsFIXME("iteratedLoop first argument must have Iterator return type", iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test(dataProvider = "iteratorInits")
+    public static void testIterateVoidInit(MethodHandle iterator) throws Throwable {
+        // this test uses List as its loop state type; don't try to change that
+        if (iterator != null)
+            iterator = iterator.asType(iterator.type().changeParameterType(0, List.class));
+        MethodHandle loop = MethodHandles.iteratedLoop(iterator, Iterate.MH_voidInit, Iterate.MH_printStep);
+        assertEquals(Iterate.MT_print, loop.type());
+        loop.invoke(Arrays.asList("hello", "world"));
+    }
+
+    @DataProvider
+    static Object[][] iterateParameters() {
+        MethodType i = methodType(int.class);
+        MethodType sil_v = methodType(void.class, String.class, int.class, List.class);
+        MethodType isl_i = methodType(int.class, int.class, String.class, List.class);
+        MethodType isli_i = methodType(int.class, int.class, String.class, List.class, int.class);
+        MethodType sl_v = methodType(void.class, String.class, List.class);
+        MethodType sli_v = methodType(void.class, String.class, List.class, int.class);
+        MethodType l_it = methodType(Iterator.class, List.class);
+        MethodType li_i = methodType(int.class, List.class, int.class);
+        MethodType li_it = methodType(Iterator.class, List.class, int.class);
+        MethodType il_it = methodType(Iterator.class, int.class, List.class);
+        MethodType l_i = methodType(int.class, List.class);
+        return new Object[][]{
+                {l_it, null, sl_v, ""},
+                {l_it, l_i, isl_i, ""},
+                {l_it, null, sl_v, ""},
+                {li_it, li_i, isli_i, ""},
+                {null, null, sil_v, "inferred first loop argument must inherit from Iterable: int"},
+                {il_it, null, sil_v, ""},
+                {li_it, null, sli_v, ""},
+                {sl_v, null, sl_v, "iteratedLoop first argument must have Iterator return type"},
+                {li_it, l_it, sl_v,
+                        String.format("iterator and init parameter lists must match: %s != %s", li_it, l_it)},
+                {li_it, li_i, isl_i,
+                        String.format("body types (regard parameter types after index 0, and result type) must match: %s != %s",
+                                isl_i, isl_i.dropParameterTypes(0, 1).appendParameterTypes(int.class))}
+        };
+    }
+
+    @Test(dataProvider = "iterateParameters")
+    public static void testIterateParameters(MethodType it, MethodType in, MethodType bo, String msg) {
+        boolean negative = !msg.isEmpty();
+        MethodHandle iterator = it == null ? null : MethodHandles.empty(it);
+        MethodHandle init = in == null ? null : MethodHandles.empty(in);
+        boolean caught = false;
+        MethodHandle loop = null;
+        try {
+            loop = MethodHandles.iteratedLoop(iterator, init, MethodHandles.empty(bo));
+        } catch (Throwable t) {
+            if (!negative) {
+                throw t;
+            }
+            assertEqualsFIXME(msg, t.getMessage());
+            caught = true;
+        }
+        if (negative) {
+            assertTrue(caught);
+        } else {
+            MethodType lt = loop.type();
+            if (it == null && in == null) {
+                assertEquals(bo.dropParameterTypes(0, 1), lt);
+            } else if (it == null) {
+                if (in.parameterCount() == 0) {
+                    assertEquals(bo.dropParameterTypes(0, in.returnType() == void.class ? 1 : 2), lt);
+                } else {
+                    assertEquals(methodType(bo.returnType(), in.parameterArray()), lt);
+                }
+            } else if (in == null) {
+                assertEquals(methodType(bo.returnType(), it.parameterArray()), lt);
+            } else if (it.parameterCount() > in.parameterCount()) {
+                assertEquals(methodType(bo.returnType(), it.parameterArray()), lt);
+            } else if (it.parameterCount() < in.parameterCount()) {
+                assertEquals(methodType(bo.returnType(), in.parameterArray()), lt);
+            } else {
+                // both it, in present; with equal parameter list lengths
+                assertEquals(it.parameterList(), lt.parameterList());
+                assertEquals(in.parameterList(), lt.parameterList());
+                assertEquals(bo.returnType(), lt.returnType());
+            }
+        }
+    }
+
+    @Test
+    public static void testIteratorSubclass() throws Throwable {
+        MethodHandle loop = MethodHandles.iteratedLoop(MethodHandles.empty(methodType(BogusIterator.class, List.class)),
+                null, MethodHandles.empty(methodType(void.class, String.class, List.class)));
+        assertEquals(methodType(void.class, List.class), loop.type());
+    }
+
+    static class BogusIterator implements Iterator {
+        @Override
+        public boolean hasNext() {
+            return false;
+        }
+        @Override
+        public Object next() {
+            return null;
+        }
+    }
+
+    static class Empty {
+
+        static void f() { }
+
+        static boolean pred() {
+            return false;
+        }
+
+        static int c() {
+            return 23;
+        }
+
+        static final Class<Empty> EMPTY = Empty.class;
+
+        static final MethodType MT_f = methodType(void.class);
+        static final MethodType MT_pred = methodType(boolean.class);
+        static final MethodType MT_c = methodType(int.class);
+
+        static final MethodHandle MH_f;
+        static final MethodHandle MH_pred;
+        static final MethodHandle MH_c;
+
+        static {
+            try {
+                MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f);
+                MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred);
+                MH_c = LOOKUP.findStatic(EMPTY, "c", MT_c);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+    }
+
+    static class Fac {
+
+        static int zero(int k) {
+            return 0;
+        }
+
+        static int one(int k) {
+            return 1;
+        }
+
+        static boolean pred(int i, int acc, int k) {
+            return i < k;
+        }
+
+        static int inc(int i, int acc, int k) {
+            return i + 1;
+        }
+
+        static int mult(int i, int acc, int k) {
+            return i * acc;
+        }
+
+        static void dot(int i, int acc, int k) {
+            System.out.print('.');
+        }
+
+        static int fin(int i, int acc, int k) {
+            return acc;
+        }
+
+        static final Class<Fac> FAC = Fac.class;
+
+        static final MethodType MT_init = methodType(int.class, int.class);
+        static final MethodType MT_fn = methodType(int.class, int.class, int.class, int.class);
+        static final MethodType MT_dot = methodType(void.class, int.class, int.class, int.class);
+        static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
+
+        static final MethodHandle MH_zero;
+        static final MethodHandle MH_one;
+        static final MethodHandle MH_pred;
+        static final MethodHandle MH_inc;
+        static final MethodHandle MH_mult;
+        static final MethodHandle MH_dot;
+        static final MethodHandle MH_fin;
+
+        static final MethodType MT_fac = methodType(int.class, int.class);
+
+        static {
+            try {
+                MH_zero = LOOKUP.findStatic(FAC, "zero", MT_init);
+                MH_one = LOOKUP.findStatic(FAC, "one", MT_init);
+                MH_pred = LOOKUP.findStatic(FAC, "pred", MT_pred);
+                MH_inc = LOOKUP.findStatic(FAC, "inc", MT_fn);
+                MH_mult = LOOKUP.findStatic(FAC, "mult", MT_fn);
+                MH_dot = LOOKUP.findStatic(FAC, "dot", MT_dot);
+                MH_fin = LOOKUP.findStatic(FAC, "fin", MT_fn);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+    }
+
+    static class Loop {
+
+        static int inc(int i, int k) {
+            return i + 1;
+        }
+
+        static boolean pred(int i, int k) {
+            return i < k;
+        }
+
+        static int fin(int i, int k) {
+            return k;
+        }
+
+        static final Class<Loop> LOOP = Loop.class;
+
+        static final MethodType MT_inc = methodType(int.class, int.class, int.class);
+        static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
+        static final MethodType MT_fin = methodType(int.class, int.class, int.class);
+
+        static final MethodHandle MH_inc;
+        static final MethodHandle MH_pred;
+        static final MethodHandle MH_fin;
+
+        static final MethodType MT_loop = methodType(int.class, int.class);
+
+        static {
+            try {
+                MH_inc = LOOKUP.findStatic(LOOP, "inc", MT_inc);
+                MH_pred = LOOKUP.findStatic(LOOP, "pred", MT_pred);
+                MH_fin = LOOKUP.findStatic(LOOP, "fin", MT_fin);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+    }
+
+    static class LoopWithVirtuals {
+
+        static int one(int k) {
+            return 1;
+        }
+
+        int inc(int i, int acc, int k) {
+            return i + 1;
+        }
+
+        int mult(int i, int acc, int k) {
+            return i * acc;
+        }
+
+        boolean pred(int i, int acc, int k) {
+            return i < k;
+        }
+
+        int fin(int i, int acc, int k) {
+            return acc;
+        }
+
+        static final Class<LoopWithVirtuals> LOOP_WITH_VIRTUALS = LoopWithVirtuals.class;
+
+        static final MethodType MT_one = methodType(int.class, int.class);
+        static final MethodType MT_inc = methodType(int.class, int.class, int.class, int.class);
+        static final MethodType MT_mult = methodType(int.class, int.class, int.class, int.class);
+        static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class);
+        static final MethodType MT_fin = methodType(int.class, int.class, int.class, int.class);
+
+        static final MethodHandle MH_one;
+        static final MethodHandle MH_inc;
+        static final MethodHandle MH_mult;
+        static final MethodHandle MH_pred;
+        static final MethodHandle MH_fin;
+
+        static final MethodType MT_loop = methodType(int.class, LOOP_WITH_VIRTUALS, int.class);
+
+        static {
+            try {
+                MH_one = LOOKUP.findStatic(LOOP_WITH_VIRTUALS, "one", MT_one);
+                MH_inc = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "inc", MT_inc);
+                MH_mult = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "mult", MT_mult);
+                MH_pred = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "pred", MT_pred);
+                MH_fin = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "fin", MT_fin);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+        static MethodHandle permute(MethodHandle h) {
+            // The handles representing virtual methods need to be rearranged to match the required order of arguments
+            // (loop-local state comes first, then loop arguments). As the receiver comes first in the signature but is
+            // a loop argument, it must be moved to the appropriate position in the signature.
+            return MethodHandles.permuteArguments(h,
+                    methodType(h.type().returnType(), int.class, int.class, LOOP_WITH_VIRTUALS, int.class), 2, 0, 1, 3);
+        }
+
+    }
+
+    static class While {
+
+        static int zero(int limit) {
+            return 0;
+        }
+
+        static boolean pred(int i, int limit) {
+            return i < limit;
+        }
+
+        static int step(int i, int limit) {
+            return i + 1;
+        }
+
+        static String initString() {
+            return "a";
+        }
+
+        static boolean predString(String s) {
+            return s.length() != 1;
+        }
+
+        static String stepString(String s) {
+            return s + "a";
+        }
+
+        static List<String> zipInitZip(Iterator<String> a, Iterator<String> b) {
+            return new ArrayList<>();
+        }
+
+        static boolean zipPred(List<String> zip, Iterator<String> a, Iterator<String> b) {
+            return a.hasNext() && b.hasNext();
+        }
+
+        static List<String> zipStep(List<String> zip, Iterator<String> a, Iterator<String> b) {
+            zip.add(a.next());
+            zip.add(b.next());
+            return zip;
+        }
+
+        private int i = 0;
+
+        void voidInit(int k) {
+            // empty
+        }
+
+        void voidBody(int k) {
+            ++i;
+        }
+
+        boolean voidPred(int k) {
+            return i < k;
+        }
+
+        static final Class<While> WHILE = While.class;
+
+        static final MethodType MT_zero = methodType(int.class, int.class);
+        static final MethodType MT_pred = methodType(boolean.class, int.class, int.class);
+        static final MethodType MT_fn = methodType(int.class, int.class, int.class);
+        static final MethodType MT_initString = methodType(String.class);
+        static final MethodType MT_predString = methodType(boolean.class, String.class);
+        static final MethodType MT_stepString = methodType(String.class, String.class);
+        static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class);
+        static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class);
+        static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class);
+        static final MethodType MT_voidInit = methodType(void.class, int.class);
+        static final MethodType MT_voidBody = methodType(void.class, int.class);
+        static final MethodType MT_voidPred = methodType(boolean.class, int.class);
+
+        static final MethodHandle MH_zero;
+        static final MethodHandle MH_pred;
+        static final MethodHandle MH_step;
+        static final MethodHandle MH_initString;
+        static final MethodHandle MH_predString;
+        static final MethodHandle MH_stepString;
+        static final MethodHandle MH_zipInitZip;
+        static final MethodHandle MH_zipPred;
+        static final MethodHandle MH_zipStep;
+        static final MethodHandle MH_voidInit;
+        static final MethodHandle MH_voidBody;
+        static final MethodHandle MH_voidPred;
+
+        static final MethodType MT_while = methodType(int.class, int.class);
+        static final MethodType MT_string = methodType(String.class);
+        static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class);
+        static final MethodType MT_void = methodType(void.class, int.class);
+
+        static {
+            try {
+                MH_zero = LOOKUP.findStatic(WHILE, "zero", MT_zero);
+                MH_pred = LOOKUP.findStatic(WHILE, "pred", MT_pred);
+                MH_step = LOOKUP.findStatic(WHILE, "step", MT_fn);
+                MH_initString = LOOKUP.findStatic(WHILE, "initString", MT_initString);
+                MH_predString = LOOKUP.findStatic(WHILE, "predString", MT_predString);
+                MH_stepString = LOOKUP.findStatic(WHILE, "stepString", MT_stepString);
+                MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip);
+                MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred);
+                MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep);
+                MH_voidInit = LOOKUP.findVirtual(WHILE, "voidInit", MT_voidInit);
+                MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody);
+                MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+    }
+
+    static class Counted {
+
+        static String start(String arg) {
+            return arg;
+        }
+
+        static String step(String v, int counter) {
+            return "na " + v;
+        }
+
+        static void stepUpdateArray(int counter, int[] a) {
+            ++a[0];
+        }
+
+        static void printHello(int counter) {
+            System.out.print("hello");
+        }
+
+        static int addCounter(int x, int counter) {
+            return x + counter;
+        }
+
+        static String stateBody(String s, int counter) {
+            return "s" + s + counter;
+        }
+
+        static String append(String localState, int counter, String loopArg) {
+            if (null == localState) {
+                return loopArg + counter;
+            }
+            return localState + counter;
+        }
+
+        static final Class<Counted> COUNTED = Counted.class;
+
+        static final MethodType MT_start = methodType(String.class, String.class);
+        static final MethodType MT_step = methodType(String.class, String.class, int.class);
+        static final MethodType MT_stepUpdateArray = methodType(void.class, int.class, int[].class);
+        static final MethodType MT_printHello = methodType(void.class, int.class);
+        static final MethodType MT_addCounter = methodType(int.class, int.class, int.class);
+        static final MethodType MT_stateBody = methodType(String.class, String.class, int.class);
+        static final MethodType MT_append = methodType(String.class, String.class, int.class, String.class);
+
+        static final MethodHandle MH_13;
+        static final MethodHandle MH_m5;
+        static final MethodHandle MH_8;
+        static final MethodHandle MH_start;
+        static final MethodHandle MH_step;
+        static final MethodHandle MH_stepUpdateArray;
+        static final MethodHandle MH_printHello;
+        static final MethodHandle MH_addCounter;
+        static final MethodHandle MH_stateBody;
+        static final MethodHandle MH_append;
+
+        static final MethodType MT_counted = methodType(String.class, String.class);
+        static final MethodType MT_arrayCounted = methodType(void.class, int[].class);
+        static final MethodType MT_countedPrinting = methodType(void.class);
+        static final MethodType MT_counterInit = methodType(int.class);
+        static final MethodType MT_bodyDeterminesState = methodType(String.class);
+        static final MethodType MT_iterationsDefineArgs = methodType(String.class, String.class);
+
+        static {
+            try {
+                MH_13 = MethodHandles.constant(int.class, 13);
+                MH_m5 = MethodHandles.constant(int.class, -5);
+                MH_8 = MethodHandles.constant(int.class, 8);
+                MH_start = LOOKUP.findStatic(COUNTED, "start", MT_start);
+                MH_step = LOOKUP.findStatic(COUNTED, "step", MT_step);
+                MH_stepUpdateArray = LOOKUP.findStatic(COUNTED, "stepUpdateArray", MT_stepUpdateArray);
+                MH_printHello = LOOKUP.findStatic(COUNTED, "printHello", MT_printHello);
+                MH_addCounter = LOOKUP.findStatic(COUNTED, "addCounter", MT_addCounter);
+                MH_stateBody = LOOKUP.findStatic(COUNTED, "stateBody", MT_stateBody);
+                MH_append = LOOKUP.findStatic(COUNTED, "append", MT_append);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+    }
+
+    static class Iterate {
+
+        static Iterator<Integer> sumIterator(Integer[] a) {
+            return Arrays.asList(a).iterator();
+        }
+
+        static int sumInit(Integer[] a) {
+            return 0;
+        }
+
+        static int sumStep(int s, int e, Integer[] a) {
+            return s + e;
+        }
+
+        static List<String> reverseInit(List<String> l) {
+            return new ArrayList<>();
+        }
+
+        static List<String> reverseStep(List<String> r, String e, List<String> l) {
+            r.add(0, e);
+            return r;
+        }
+
+        static int lengthInit(List<Double> l) {
+            return 0;
+        }
+
+        static int lengthStep(int len, Object o, List<Double> l) {
+            return len + 1;
+        }
+
+        static List<String> mapInit(List<String> l) {
+            return new ArrayList<>();
+        }
+
+        static List<String> mapStep(List<String> r, String e, List<String> l) {
+            r.add(e.toUpperCase());
+            return r;
+        }
+
+        static void printStep(String s, List<String> l) {
+            System.out.print(s);
+        }
+
+        static void voidInit(List<String> l) {
+            // empty
+        }
+
+        static ListIterator<?> iteratorFromList(List<?> l) {
+            return l.listIterator();
+        }
+
+        static Iterator<?> iteratorFromIterable(Iterable<?> l) {
+            return l.iterator();
+        }
+
+        static final Class<Iterate> ITERATE = Iterate.class;
+
+        static final MethodType MT_sumIterator = methodType(Iterator.class, Integer[].class);
+
+        static final MethodType MT_sumInit = methodType(int.class, Integer[].class);
+        static final MethodType MT_reverseInit = methodType(List.class, List.class);
+        static final MethodType MT_lenghInit = methodType(int.class, List.class);
+        static final MethodType MT_mapInit = methodType(List.class, List.class);
+
+        static final MethodType MT_sumStep = methodType(int.class, int.class, int.class, Integer[].class);
+        static final MethodType MT_reverseStep = methodType(List.class, List.class, String.class, List.class);
+        static final MethodType MT_lengthStep = methodType(int.class, int.class, Object.class, List.class);
+        static final MethodType MT_mapStep = methodType(List.class, List.class, String.class, List.class);
+        static final MethodType MT_printStep = methodType(void.class, String.class, List.class);
+
+        static final MethodType MT_voidInit = methodType(void.class, List.class);
+
+        static final MethodType MT_iteratorFromList = methodType(ListIterator.class, List.class);
+        static final MethodType MT_iteratorFromIterable = methodType(Iterator.class, Iterable.class);
+
+        static final MethodHandle MH_sumIterator;
+        static final MethodHandle MH_sumInit;
+        static final MethodHandle MH_sumStep;
+        static final MethodHandle MH_printStep;
+
+        static final MethodHandle MH_reverseInit;
+        static final MethodHandle MH_reverseStep;
+
+        static final MethodHandle MH_lengthInit;
+        static final MethodHandle MH_lengthStep;
+
+        static final MethodHandle MH_mapInit;
+        static final MethodHandle MH_mapStep;
+
+        static final MethodHandle MH_voidInit;
+
+        static final MethodHandle MH_iteratorFromList;
+        static final MethodHandle MH_iteratorFromIterable;
+
+        static final MethodType MT_sum = methodType(int.class, Integer[].class);
+        static final MethodType MT_reverse = methodType(List.class, List.class);
+        static final MethodType MT_length = methodType(int.class, List.class);
+        static final MethodType MT_map = methodType(List.class, List.class);
+        static final MethodType MT_print = methodType(void.class, List.class);
+
+        static {
+            try {
+                MH_sumIterator = LOOKUP.findStatic(ITERATE, "sumIterator", MT_sumIterator);
+                MH_sumInit = LOOKUP.findStatic(ITERATE, "sumInit", MT_sumInit);
+                MH_sumStep = LOOKUP.findStatic(ITERATE, "sumStep", MT_sumStep);
+                MH_reverseInit = LOOKUP.findStatic(ITERATE, "reverseInit", MT_reverseInit);
+                MH_reverseStep = LOOKUP.findStatic(ITERATE, "reverseStep", MT_reverseStep);
+                MH_lengthInit = LOOKUP.findStatic(ITERATE, "lengthInit", MT_lenghInit);
+                MH_lengthStep = LOOKUP.findStatic(ITERATE, "lengthStep", MT_lengthStep);
+                MH_mapInit = LOOKUP.findStatic(ITERATE, "mapInit", MT_mapInit);
+                MH_mapStep = LOOKUP.findStatic(ITERATE, "mapStep", MT_mapStep);
+                MH_printStep = LOOKUP.findStatic(ITERATE, "printStep", MT_printStep);
+                MH_voidInit = LOOKUP.findStatic(ITERATE, "voidInit", MT_voidInit);
+                MH_iteratorFromList = LOOKUP.findStatic(ITERATE, "iteratorFromList", MT_iteratorFromList);
+                MH_iteratorFromIterable = LOOKUP.findStatic(ITERATE, "iteratorFromIterable", MT_iteratorFromIterable);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/MethodHandlesAsCollectorTest.java b/ojluni/src/test/java/lang/invoke/MethodHandlesAsCollectorTest.java
new file mode 100644
index 0000000..56dab7b
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/MethodHandlesAsCollectorTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @library /lib/testlibrary /java/lang/invoke/common
+ * @compile MethodHandlesTest.java MethodHandlesAsCollectorTest.java remote/RemoteExample.java
+ * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions
+ *                                 -XX:-VerifyDependencies
+ *                                 -esa
+ *                                 test.java.lang.invoke.MethodHandlesAsCollectorTest
+ */
+
+package test.java.lang.invoke;
+
+import org.junit.*;
+import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+
+import static org.junit.Assert.*;
+
+public class MethodHandlesAsCollectorTest extends MethodHandlesTest {
+
+    @Test // SLOW
+    public void testAsCollector() throws Throwable {
+        CodeCacheOverflowProcessor.runMHTest(this::testAsCollector0);
+        CodeCacheOverflowProcessor.runMHTest(this::testAsCollector1);
+    }
+
+    // Android-added: suppress errorprone warning, tests run via testAsCollector() above.
+    @SuppressWarnings("JUnit4TestNotRun")
+    public void testAsCollector0() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("asCollector");
+        for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
+            if (verbosity >= 3)
+                System.out.println("asCollector "+argType);
+            for (int nargs = 0; nargs < 50; nargs++) {
+                if (CAN_TEST_LIGHTLY && nargs > 11)  break;
+                for (int pos = 0; pos <= nargs; pos++) {
+                    if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
+                    if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
+                        continue;
+                    testAsCollector(argType, pos, nargs);
+                }
+            }
+        }
+    }
+
+    // Android-added: suppress errorprone warning, tests run via testAsCollector() above.
+    @SuppressWarnings("JUnit4TestNotRun")
+    public void testAsCollector(Class<?> argType, int pos, int nargs) throws Throwable {
+        countTest();
+        // fake up a MH with the same type as the desired adapter:
+        MethodHandle fake = varargsArray(nargs);
+        fake = changeArgTypes(fake, argType);
+        MethodType newType = fake.type();
+        Object[] args = randomArgs(newType.parameterArray());
+        // here is what should happen:
+        Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
+        collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
+        // here is the MH which will witness the collected argument tail:
+        MethodHandle target = varargsArray(pos+1);
+        target = changeArgTypes(target, 0, pos, argType);
+        target = changeArgTypes(target, pos, pos+1, Object[].class);
+        if (verbosity >= 3)
+            System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
+        MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType);
+        Object[] returnValue = (Object[]) result.invokeWithArguments(args);
+        assertArrayEquals(collectedArgs, returnValue);
+    }
+
+    // Android-added: suppress errorprone warning, tests run via testAsCollector() above.
+    @SuppressWarnings("JUnit4TestNotRun")
+    public void testAsCollector1() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("asCollector/pos");
+        for (Class<?> argType : new Class<?>[]{Object.class, Integer.class, int.class}) {
+            if (verbosity >= 3)
+                System.out.println("asCollector/pos "+argType);
+            for (int nargs = 0; nargs < 50; nargs++) {
+                if (CAN_TEST_LIGHTLY && nargs > 11)  break;
+                for (int pos = 0; pos <= nargs; pos++) {
+                    if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2)  continue;
+                    if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
+                        continue;
+                    for (int coll = 1; coll < nargs - pos; ++coll) {
+                        if (coll > 4 && coll != 7 && coll != 11 && coll != 20 && coll < nargs - pos - 4) continue;
+                        testAsCollector(argType, pos, coll, nargs);
+                    }
+                }
+            }
+        }
+    }
+
+    // Android-added: suppress errorprone warning, tests run via testAsCollector() above.
+    @SuppressWarnings("JUnit4TestNotRun")
+    public void testAsCollector(Class<?> argType, int pos, int collect, int nargs) throws Throwable {
+        countTest();
+        // fake up a MH with the same type as the desired adapter:
+        MethodHandle fake = varargsArray(nargs);
+        fake = changeArgTypes(fake, argType);
+        MethodType newType = fake.type();
+        Object[] args = randomArgs(newType.parameterArray());
+        // here is what should happen:
+        // new arg list has "collect" less arguments, but one extra for collected arguments array
+        int collectedLength = nargs-(collect-1);
+        Object[] collectedArgs = new Object[collectedLength];
+        System.arraycopy(args, 0, collectedArgs, 0, pos);
+        collectedArgs[pos] = Arrays.copyOfRange(args, pos, pos+collect);
+        System.arraycopy(args, pos+collect, collectedArgs, pos+1, args.length-(pos+collect));
+        // here is the MH which will witness the collected argument part (not tail!):
+        MethodHandle target = varargsArray(collectedLength);
+        target = changeArgTypes(target, 0, pos, argType);
+        target = changeArgTypes(target, pos, pos+1, Object[].class);
+        target = changeArgTypes(target, pos+1, collectedLength, argType);
+        if (verbosity >= 3)
+            System.out.println("collect "+collect+" from "+Arrays.asList(args)+" ["+pos+".."+(pos+collect)+"[");
+        MethodHandle result = target.asCollector(pos, Object[].class, collect).asType(newType);
+        Object[] returnValue = (Object[]) result.invokeWithArguments(args);
+        assertArrayEquals(collectedArgs, returnValue);
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/MethodHandlesCastFailureTest.java b/ojluni/src/test/java/lang/invoke/MethodHandlesCastFailureTest.java
new file mode 100644
index 0000000..8416a8a
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/MethodHandlesCastFailureTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @library /lib/testlibrary /java/lang/invoke/common
+ * @compile MethodHandlesTest.java MethodHandlesCastFailureTest.java remote/RemoteExample.java
+ * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions
+ *                                 -XX:-VerifyDependencies
+ *                                 -esa
+ *                                 test.java.lang.invoke.MethodHandlesCastFailureTest
+ */
+
+package test.java.lang.invoke;
+
+import org.junit.*;
+import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import static org.junit.Assert.*;
+
+public class MethodHandlesCastFailureTest extends MethodHandlesTest {
+
+    @Test  // SLOW
+    public void testCastFailure() throws Throwable {
+        CodeCacheOverflowProcessor.runMHTest(this::testCastFailure0);
+    }
+
+    // Android-added: @Ignore as this is a helper for testCastFailure().
+    @Ignore
+    public void testCastFailure0() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("testCastFailure");
+        testCastFailure("cast/argument", 11000);
+        if (CAN_TEST_LIGHTLY)  return;
+        testCastFailure("unbox/argument", 11000);
+        testCastFailure("cast/return", 11000);
+        testCastFailure("unbox/return", 11000);
+    }
+
+    static class Surprise {
+        public MethodHandle asMethodHandle() {
+            return VALUE.bindTo(this);
+        }
+        Object value(Object x) {
+            trace("value", x);
+            if (boo != null)  return boo;
+            return x;
+        }
+        Object boo;
+        void boo(Object x) { boo = x; }
+
+        static void trace(String x, Object y) {
+            if (verbosity > 8) System.out.println(x+"="+y);
+        }
+        static Object  refIdentity(Object x)  { trace("ref.x", x); return x; }
+        static Integer boxIdentity(Integer x) { trace("box.x", x); return x; }
+        static int     intIdentity(int x)     { trace("int.x", x); return x; }
+        static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY;
+        static {
+            try {
+                VALUE = PRIVATE.findVirtual(
+                    Surprise.class, "value",
+                        MethodType.methodType(Object.class, Object.class));
+                REF_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "refIdentity",
+                        MethodType.methodType(Object.class, Object.class));
+                BOX_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "boxIdentity",
+                        MethodType.methodType(Integer.class, Integer.class));
+                INT_IDENTITY = PRIVATE.findStatic(
+                    Surprise.class, "intIdentity",
+                        MethodType.methodType(int.class, int.class));
+            } catch (NoSuchMethodException | IllegalAccessException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    // Android-added: @Ignore as this is a helper.
+    @Ignore
+    @SuppressWarnings("ConvertToStringSwitch")
+    void testCastFailure(String mode, int okCount) throws Throwable {
+        countTest(false);
+        if (verbosity > 2)  System.out.println("mode="+mode);
+        Surprise boo = new Surprise();
+        MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
+        if (mode.endsWith("/return")) {
+            if (mode.equals("unbox/return")) {
+                // fail on return to ((Integer)surprise).intValue
+                surprise = surprise.asType(MethodType.methodType(int.class, Object.class));
+                identity = identity.asType(MethodType.methodType(int.class, Object.class));
+            } else if (mode.equals("cast/return")) {
+                // fail on return to (Integer)surprise
+                surprise = surprise.asType(MethodType.methodType(Integer.class, Object.class));
+                identity = identity.asType(MethodType.methodType(Integer.class, Object.class));
+            }
+        } else if (mode.endsWith("/argument")) {
+            MethodHandle callee = null;
+            if (mode.equals("unbox/argument")) {
+                // fail on handing surprise to int argument
+                callee = Surprise.INT_IDENTITY;
+            } else if (mode.equals("cast/argument")) {
+                // fail on handing surprise to Integer argument
+                callee = Surprise.BOX_IDENTITY;
+            }
+            if (callee != null) {
+                callee = callee.asType(MethodType.genericMethodType(1));
+                surprise = MethodHandles.filterArguments(callee, 0, surprise);
+                identity = MethodHandles.filterArguments(callee, 0, identity);
+            }
+        }
+        assertNotSame(mode, surprise, surprise0);
+        identity = identity.asType(MethodType.genericMethodType(1));
+        surprise = surprise.asType(MethodType.genericMethodType(1));
+        Object x = 42;
+        for (int i = 0; i < okCount; i++) {
+            Object y = identity.invokeExact(x);
+            assertEquals(x, y);
+            Object z = surprise.invokeExact(x);
+            assertEquals(x, z);
+        }
+        boo.boo("Boo!");
+        Object y = identity.invokeExact(x);
+        assertEquals(x, y);
+        try {
+            Object z = surprise.invokeExact(x);
+            System.out.println("Failed to throw; got z="+z);
+            assertTrue(false);
+        } catch (ClassCastException ex) {
+            if (verbosity > 2)
+                System.out.println("caught "+ex);
+            if (verbosity > 3)
+                ex.printStackTrace(System.out);
+            assertTrue(true);  // all is well
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java b/ojluni/src/test/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java
new file mode 100644
index 0000000..845b68c
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @library /lib/testlibrary /java/lang/invoke/common
+ * @compile MethodHandlesTest.java MethodHandlesPermuteArgumentsTest.java remote/RemoteExample.java
+ * @run junit/othervm/timeout=2500 -XX:+IgnoreUnrecognizedVMOptions
+ *                                 -XX:-VerifyDependencies
+ *                                 -esa
+ *                                 test.java.lang.invoke.MethodHandlesPermuteArgumentsTest
+ */
+
+
+package test.java.lang.invoke;
+
+import org.junit.*;
+import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+
+import static org.junit.Assert.*;
+
+public class MethodHandlesPermuteArgumentsTest extends MethodHandlesTest {
+
+    @Test // SLOW
+    public void testPermuteArguments() throws Throwable {
+        CodeCacheOverflowProcessor.runMHTest(this::testPermuteArguments0);
+    }
+
+    // Android-added: @Test for test cases.
+    @Test
+    public void testPermuteArguments0() throws Throwable {
+        if (CAN_SKIP_WORKING)  return;
+        startTest("permuteArguments");
+        testPermuteArguments(4, Integer.class, 2, long.class, 6);
+        if (CAN_TEST_LIGHTLY)  return;
+        testPermuteArguments(4, Integer.class, 2, String.class, 0);
+        testPermuteArguments(6, Integer.class, 0, null, 30);
+    }
+
+    // Android-added: @Ignore as this is a test helper.
+    @Ignore
+    public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
+        if (verbosity >= 2)
+            System.out.println("permuteArguments "+max+"*"+type1.getName()
+                    +(t2c==0?"":"/"+t2c+"*"+type2.getName())
+                    +(dilution > 0 ? " with dilution "+dilution : ""));
+        int t2pos = t2c == 0 ? 0 : 1;
+        for (int inargs = t2pos+1; inargs <= max; inargs++) {
+            Class<?>[] types = new Class<?>[inargs];
+            Arrays.fill(types, type1);
+            if (t2c != 0) {
+                // Fill in a middle range with type2:
+                Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2);
+            }
+            Object[] args = randomArgs(types);
+            int numcases = 1;
+            for (int outargs = 0; outargs <= max; outargs++) {
+                if (outargs - inargs >= MAX_ARG_INCREASE)  continue;
+                int casStep = dilution + 1;
+                // Avoid some common factors:
+                while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) ||
+                       (casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0))
+                    casStep++;
+                testPermuteArguments(args, types, outargs, numcases, casStep);
+                numcases *= inargs;
+                if (CAN_TEST_LIGHTLY && outargs < max-2)  continue;
+                if (dilution > 10 && outargs >= 4) {
+                    if (CAN_TEST_LIGHTLY)  continue;
+                    int[] reorder = new int[outargs];
+                    // Do some special patterns, which we probably missed.
+                    // Replication of a single argument or argument pair.
+                    for (int i = 0; i < inargs; i++) {
+                        Arrays.fill(reorder, i);
+                        testPermuteArguments(args, types, reorder);
+                        for (int d = 1; d <= 2; d++) {
+                            if (i + d >= inargs)  continue;
+                            for (int j = 1; j < outargs; j += 2)
+                                reorder[j] += 1;
+                            testPermuteArguments(args, types, reorder);
+                            testPermuteArguments(args, types, reverse(reorder));
+                        }
+                    }
+                    // Repetition of a sequence of 3 or more arguments.
+                    for (int i = 1; i < inargs; i++) {
+                        for (int len = 3; len <= inargs; len++) {
+                            for (int j = 0; j < outargs; j++)
+                                reorder[j] = (i + (j % len)) % inargs;
+                            testPermuteArguments(args, types, reorder);
+                            testPermuteArguments(args, types, reverse(reorder));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Android-added: @Ignore for test helper.
+    @Ignore
+    public void testPermuteArguments(Object[] args, Class<?>[] types,
+                                     int outargs, int numcases, int casStep) throws Throwable {
+        int inargs = args.length;
+        int[] reorder = new int[outargs];
+        for (int cas = 0; cas < numcases; cas += casStep) {
+            for (int i = 0, c = cas; i < outargs; i++) {
+                reorder[i] = c % inargs;
+                c /= inargs;
+            }
+            if (CAN_TEST_LIGHTLY && outargs >= 3 &&
+               (reorder[0] == reorder[1] || reorder[1] == reorder[2]))
+                   continue;
+            testPermuteArguments(args, types, reorder);
+        }
+    }
+
+    static int[] reverse(int[] reorder) {
+        reorder = reorder.clone();
+        for (int i = 0, imax = reorder.length / 2; i < imax; i++) {
+            int j = reorder.length - 1 - i;
+            int tem = reorder[i];
+            reorder[i] = reorder[j];
+            reorder[j] = tem;
+        }
+        return reorder;
+    }
+
+    // Android-added: @Ignore for test helper.
+    @Ignore
+    void testPermuteArguments(Object[] args, Class<?>[] types, int[] reorder) throws Throwable {
+        countTest();
+        if (args == null && types == null) {
+            int max = 0;
+            for (int j : reorder) {
+                if (max < j)  max = j;
+            }
+            args = randomArgs(max+1, Integer.class);
+        }
+        if (args == null) {
+            args = randomArgs(types);
+        }
+        if (types == null) {
+            types = new Class<?>[args.length];
+            for (int i = 0; i < args.length; i++)
+                types[i] = args[i].getClass();
+        }
+        int inargs = args.length, outargs = reorder.length;
+        assertTrue(inargs == types.length);
+        if (verbosity >= 3)
+            System.out.println("permuteArguments "+Arrays.toString(reorder));
+        Object[] permArgs = new Object[outargs];
+        Class<?>[] permTypes = new Class<?>[outargs];
+        for (int i = 0; i < outargs; i++) {
+            permArgs[i] = args[reorder[i]];
+            permTypes[i] = types[reorder[i]];
+        }
+        if (verbosity >= 4) {
+            System.out.println("in args:   "+Arrays.asList(args));
+            System.out.println("out args:  "+Arrays.asList(permArgs));
+            System.out.println("in types:  "+Arrays.asList(types));
+            System.out.println("out types: "+Arrays.asList(permTypes));
+        }
+        MethodType inType  = MethodType.methodType(Object.class, types);
+        MethodType outType = MethodType.methodType(Object.class, permTypes);
+        MethodHandle target = varargsList(outargs).asType(outType);
+        MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
+        if (verbosity >= 5)  System.out.println("newTarget = "+newTarget);
+        Object result = newTarget.invokeWithArguments(args);
+        Object expected = Arrays.asList(permArgs);
+        if (!expected.equals(result)) {
+            System.out.println("*** failed permuteArguments "+Arrays.toString(reorder)+
+                               " types="+Arrays.asList(types));
+            System.out.println("in args:   "+Arrays.asList(args));
+            System.out.println("out args:  "+expected);
+            System.out.println("bad args:  "+result);
+        }
+        assertEquals(expected, result);
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/MethodHandlesTest.java b/ojluni/src/test/java/lang/invoke/MethodHandlesTest.java
new file mode 100644
index 0000000..314d2a2
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/MethodHandlesTest.java
@@ -0,0 +1,948 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.lang.invoke;
+
+import org.junit.*;
+import test.java.lang.invoke.remote.RemoteExample;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author jrose
+ */
+public abstract class MethodHandlesTest {
+
+    static final Class<?> THIS_CLASS = MethodHandlesTest.class;
+    // How much output?
+    static int verbosity = 0;
+
+    static {
+        String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".verbosity");
+        if (vstr == null)
+            vstr = System.getProperty(THIS_CLASS.getName()+".verbosity");
+        if (vstr != null)  verbosity = Integer.parseInt(vstr);
+    }
+
+    // Set this true during development if you want to fast-forward to
+    // a particular new, non-working test.  Tests which are known to
+    // work (or have recently worked) test this flag and return on true.
+    static final boolean CAN_SKIP_WORKING;
+
+    static {
+        String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".CAN_SKIP_WORKING");
+        if (vstr == null)
+            vstr = System.getProperty(THIS_CLASS.getName()+".CAN_SKIP_WORKING");
+        CAN_SKIP_WORKING = Boolean.parseBoolean(vstr);
+    }
+
+    // Set 'true' to do about 15x fewer tests, especially those redundant with RicochetTest.
+    // This might be useful with -Xcomp stress tests that compile all method handles.
+    static boolean CAN_TEST_LIGHTLY = Boolean.getBoolean(THIS_CLASS.getName()+".CAN_TEST_LIGHTLY");
+
+    static final int MAX_ARG_INCREASE = 3;
+
+    String testName;
+    static int allPosTests, allNegTests;
+    int posTests, negTests;
+
+    @After
+    public void printCounts() {
+        if (verbosity >= 2 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
+            if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
+            allPosTests += posTests;
+            allNegTests += negTests;
+            posTests = negTests = 0;
+        }
+    }
+
+    void countTest(boolean positive) {
+        if (positive) ++posTests;
+        else          ++negTests;
+    }
+
+    void countTest() { countTest(true); }
+
+    void startTest(String name) {
+        if (testName != null)  printCounts();
+        if (verbosity >= 1)
+            System.out.println(name);
+        posTests = negTests = 0;
+        testName = name;
+    }
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        calledLog.clear();
+        calledLog.add(null);
+        nextArgVal = INITIAL_ARG_VAL;
+    }
+
+    @AfterClass
+    public static void tearDownClass() throws Exception {
+        int posTests = allPosTests, negTests = allNegTests;
+        if (verbosity >= 0 && (posTests | negTests) != 0) {
+            System.out.println();
+            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
+            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
+        }
+    }
+
+    static List<Object> calledLog = new ArrayList<>();
+
+    static Object logEntry(String name, Object... args) {
+        return Arrays.asList(name, Arrays.asList(args));
+    }
+
+    public static Object called(String name, Object... args) {
+        Object entry = logEntry(name, args);
+        calledLog.add(entry);
+        return entry;
+    }
+
+    static void assertCalled(String name, Object... args) {
+        Object expected = logEntry(name, args);
+        Object actual   = calledLog.get(calledLog.size() - 1);
+        if (expected.equals(actual) && verbosity < 9)  return;
+        System.out.println("assertCalled "+name+":");
+        System.out.println("expected:   "+deepToString(expected));
+        System.out.println("actual:     "+actual);
+        System.out.println("ex. types:  "+getClasses(expected));
+        System.out.println("act. types: "+getClasses(actual));
+        assertEquals("previous method call", expected, actual);
+    }
+
+    static void printCalled(MethodHandle target, String name, Object... args) {
+        if (verbosity >= 3)
+            System.out.println("calling MH="+target+" to "+name+deepToString(args));
+    }
+
+    static String deepToString(Object x) {
+        if (x == null)  return "null";
+        if (x instanceof Collection)
+            x = ((Collection)x).toArray();
+        if (x instanceof Object[]) {
+            Object[] ax = (Object[]) x;
+            ax = Arrays.copyOf(ax, ax.length, Object[].class);
+            for (int i = 0; i < ax.length; i++)
+                ax[i] = deepToString(ax[i]);
+            x = Arrays.deepToString(ax);
+        }
+        if (x.getClass().isArray())
+            try {
+                x = Arrays.class.getMethod("toString", x.getClass()).invoke(null, x);
+            } catch (ReflectiveOperationException ex) { throw new Error(ex); }
+        assert(!(x instanceof Object[]));
+        return x.toString();
+    }
+
+    static Object castToWrapper(Object value, Class<?> dst) {
+        Object wrap = null;
+        if (value instanceof Number)
+            wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
+        if (value instanceof Character)
+            wrap = castToWrapperOrNull((char)(Character)value, dst);
+        if (wrap != null)  return wrap;
+        return dst.cast(value);
+    }
+
+    @SuppressWarnings("cast")  // primitive cast to (long) is part of the pattern
+    static Object castToWrapperOrNull(long value, Class<?> dst) {
+        if (dst == int.class || dst == Integer.class)
+            return (int)(value);
+        if (dst == long.class || dst == Long.class)
+            return (long)(value);
+        if (dst == char.class || dst == Character.class)
+            return (char)(value);
+        if (dst == short.class || dst == Short.class)
+            return (short)(value);
+        if (dst == float.class || dst == Float.class)
+            return (float)(value);
+        if (dst == double.class || dst == Double.class)
+            return (double)(value);
+        if (dst == byte.class || dst == Byte.class)
+            return (byte)(value);
+        if (dst == boolean.class || dst == boolean.class)
+            return ((value % 29) & 1) == 0;
+        return null;
+    }
+
+    static final int ONE_MILLION = (1000*1000),  // first int value
+                     TEN_BILLION = (10*1000*1000*1000),  // scale factor to reach upper 32 bits
+                     INITIAL_ARG_VAL = ONE_MILLION << 1;  // <<1 makes space for sign bit;
+    static long nextArgVal;
+
+    static long nextArg(boolean moreBits) {
+        long val = nextArgVal++;
+        long sign = -(val & 1); // alternate signs
+        val >>= 1;
+        if (moreBits)
+            // Guarantee some bits in the high word.
+            // In any case keep the decimal representation simple-looking,
+            // with lots of zeroes, so as not to make the printed decimal
+            // strings unnecessarily noisy.
+            val += (val % ONE_MILLION) * TEN_BILLION;
+        return val ^ sign;
+    }
+
+    static int nextArg() {
+        // Produce a 32-bit result something like ONE_MILLION+(smallint).
+        // Example: 1_000_042.
+        return (int) nextArg(false);
+    }
+
+    static long nextArg(Class<?> kind) {
+        if (kind == long.class   || kind == Long.class ||
+            kind == double.class || kind == Double.class)
+            // produce a 64-bit result something like
+            // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+            // Example: 10_000_420_001_000_042.
+            return nextArg(true);
+        return (long) nextArg();
+    }
+
+    static Object randomArg(Class<?> param) {
+        Object wrap = castToWrapperOrNull(nextArg(param), param);
+        if (wrap != null) {
+            return wrap;
+        }
+        //import sun.invoke.util.Wrapper;
+        //Wrapper wrap = Wrapper.forBasicType(dst);
+        //if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
+        //   wrap = Wrapper.forWrapperType(dst);
+        //   if (wrap != Wrapper.OBJECT)
+        //       return wrap.wrap(nextArg++);
+        if (param.isInterface()) {
+            for (Class<?> c : param.getClasses()) {
+                if (param.isAssignableFrom(c) && !c.isInterface())
+                    { param = c; break; }
+            }
+        }
+        if (param.isArray()) {
+            Class<?> ctype = param.getComponentType();
+            Object arg = Array.newInstance(ctype, 2);
+            Array.set(arg, 0, randomArg(ctype));
+            return arg;
+        }
+        if (param.isInterface() && param.isAssignableFrom(List.class))
+            return Arrays.asList("#"+nextArg());
+        if (param.isInterface() || param.isAssignableFrom(String.class))
+            return "#"+nextArg();
+        else
+            try {
+                return param.newInstance();
+            } catch (InstantiationException | IllegalAccessException ex) {
+            }
+        return null;  // random class not Object, String, Integer, etc.
+    }
+
+    static Object[] randomArgs(Class<?>... params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < args.length; i++)
+            args[i] = randomArg(params[i]);
+        return args;
+    }
+
+    static Object[] randomArgs(int nargs, Class<?> param) {
+        Object[] args = new Object[nargs];
+        for (int i = 0; i < args.length; i++)
+            args[i] = randomArg(param);
+        return args;
+    }
+
+    static Object[] randomArgs(List<Class<?>> params) {
+        return randomArgs(params.toArray(new Class<?>[params.size()]));
+    }
+
+    @SafeVarargs @SuppressWarnings("varargs")
+    static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
+        return Arrays.copyOf(a, a.length, atype);
+    }
+
+    @SafeVarargs @SuppressWarnings("varargs")
+    static <T> T[] cat(T[] a, T... b) {
+        int alen = a.length, blen = b.length;
+        if (blen == 0)  return a;
+        T[] c = Arrays.copyOf(a, alen + blen);
+        System.arraycopy(b, 0, c, alen, blen);
+        return c;
+    }
+
+    static Integer[] boxAll(int... vx) {
+        Integer[] res = new Integer[vx.length];
+        for (int i = 0; i < res.length; i++) {
+            res[i] = vx[i];
+        }
+        return res;
+    }
+
+    static Object getClasses(Object x) {
+        if (x == null)  return x;
+        if (x instanceof String)  return x;  // keep the name
+        if (x instanceof List) {
+            // recursively report classes of the list elements
+            Object[] xa = ((List)x).toArray();
+            for (int i = 0; i < xa.length; i++)
+                xa[i] = getClasses(xa[i]);
+            return Arrays.asList(xa);
+        }
+        return x.getClass().getSimpleName();
+    }
+
+    /** Return lambda(arg...[arity]) { new Object[]{ arg... } } */
+    static MethodHandle varargsList(int arity) {
+        return ValueConversions.varargsList(arity);
+    }
+
+    /** Return lambda(arg...[arity]) { Arrays.asList(arg...) } */
+    static MethodHandle varargsArray(int arity) {
+        return ValueConversions.varargsArray(arity);
+    }
+
+    static MethodHandle varargsArray(Class<?> arrayType, int arity) {
+        return ValueConversions.varargsArray(arrayType, arity);
+    }
+
+    /** Variation of varargsList, but with the given rtype. */
+    static MethodHandle varargsList(int arity, Class<?> rtype) {
+        MethodHandle list = varargsList(arity);
+        MethodType listType = list.type().changeReturnType(rtype);
+        if (List.class.isAssignableFrom(rtype) || rtype == void.class || rtype == Object.class) {
+            // OK
+        } else if (rtype.isAssignableFrom(String.class)) {
+            if (LIST_TO_STRING == null)
+                try {
+                    LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString",
+                                                        MethodType.methodType(String.class, List.class));
+                } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); }
+            list = MethodHandles.filterReturnValue(list, LIST_TO_STRING);
+        } else if (rtype.isPrimitive()) {
+            if (LIST_TO_INT == null)
+                try {
+                    LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt",
+                                                     MethodType.methodType(int.class, List.class));
+                } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); }
+            list = MethodHandles.filterReturnValue(list, LIST_TO_INT);
+            list = MethodHandles.explicitCastArguments(list, listType);
+        } else {
+            throw new RuntimeException("varargsList: "+rtype);
+        }
+        return list.asType(listType);
+    }
+
+    /** Variation of varargsList, but with the given ptypes and rtype. */
+    static MethodHandle varargsList(List<Class<?>> ptypes, Class<?> rtype) {
+        MethodHandle list = varargsList(ptypes.size(), rtype);
+        return list.asType(MethodType.methodType(rtype, ptypes));
+    }
+
+    private static MethodHandle LIST_TO_STRING, LIST_TO_INT;
+    private static String listToString(List<?> x) { return x.toString(); }
+    private static int listToInt(List<?> x) { return x.toString().hashCode(); }
+
+    static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
+        return changeArgTypes(target, 0, 999, argType);
+    }
+
+    static MethodHandle changeArgTypes(MethodHandle target,
+            int beg, int end, Class<?> argType) {
+        MethodType targetType = target.type();
+        end = Math.min(end, targetType.parameterCount());
+        ArrayList<Class<?>> argTypes = new ArrayList<>(targetType.parameterList());
+        Collections.fill(argTypes.subList(beg, end), argType);
+        MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
+        return target.asType(ttype2);
+    }
+
+    static MethodHandle addTrailingArgs(MethodHandle target, int nargs, Class<?> argClass) {
+        int targetLen = target.type().parameterCount();
+        int extra = (nargs - targetLen);
+        if (extra <= 0)  return target;
+        List<Class<?>> fakeArgs = Collections.<Class<?>>nCopies(extra, argClass);
+        return MethodHandles.dropArguments(target, targetLen, fakeArgs);
+    }
+
+    // This lookup is good for all members in and under MethodHandlesTest.
+    static final Lookup PRIVATE = MethodHandles.lookup();
+    // This lookup is good for package-private members but not private ones.
+    static final Lookup PACKAGE = PackageSibling.lookup();
+    // This lookup is good for public members and protected members of PubExample
+    static final Lookup SUBCLASS = RemoteExample.lookup();
+    // This lookup is good only for public members in exported packages.
+    static final Lookup PUBLIC  = MethodHandles.publicLookup();
+
+    // Subject methods...
+    static class Example implements IntExample {
+        final String name;
+        public Example() { name = "Example#"+nextArg(); }
+        protected Example(String name) { this.name = name; }
+        @SuppressWarnings("LeakingThisInConstructor")
+        protected Example(int x) { this(); called("protected <init>", this, x); }
+        //Example(Void x) { does not exist; lookup elicts NoSuchMethodException }
+        @Override public String toString() { return name; }
+
+        public void            v0()     { called("v0", this); }
+        protected void         pro_v0() { called("pro_v0", this); }
+        void                   pkg_v0() { called("pkg_v0", this); }
+        private void           pri_v0() { called("pri_v0", this); }
+        public static void     s0()     { called("s0"); }
+        protected static void  pro_s0() { called("pro_s0"); }
+        static void            pkg_s0() { called("pkg_s0"); }
+        private static void    pri_s0() { called("pri_s0"); }
+
+        public Object          v1(Object x) { return called("v1", this, x); }
+        public Object          v2(Object x, Object y) { return called("v2", this, x, y); }
+        public Object          v2(Object x, int    y) { return called("v2", this, x, y); }
+        public Object          v2(int    x, Object y) { return called("v2", this, x, y); }
+        public Object          v2(int    x, int    y) { return called("v2", this, x, y); }
+        public static Object   s1(Object x) { return called("s1", x); }
+        public static Object   s2(int x)    { return called("s2", x); }
+        public static Object   s3(long x)   { return called("s3", x); }
+        public static Object   s4(int x, int y) { return called("s4", x, y); }
+        public static Object   s5(long x, int y) { return called("s5", x, y); }
+        public static Object   s6(int x, long y) { return called("s6", x, y); }
+        public static Object   s7(float x, double y) { return called("s7", x, y); }
+
+        // for testing findConstructor:
+        public Example(String x, int y) { this.name = x+y; called("Example.<init>", x, y); }
+        public Example(int x, String y) { this.name = x+y; called("Example.<init>", x, y); }
+        public Example(int x, int    y) { this.name = x+""+y; called("Example.<init>", x, y); }
+        public Example(int x, long   y) { this.name = x+""+y; called("Example.<init>", x, y); }
+        public Example(int x, float  y) { this.name = x+""+y; called("Example.<init>", x, y); }
+        public Example(int x, double y) { this.name = x+""+y; called("Example.<init>", x, y); }
+        public Example(int x, int    y, int z) { this.name = x+""+y+""+z; called("Example.<init>", x, y, z); }
+        public Example(int x, int    y, int z, int a) { this.name = x+""+y+""+z+""+a; called("Example.<init>", x, y, z, a); }
+
+        static final Lookup EXAMPLE = MethodHandles.lookup();  // for testing findSpecial
+    }
+
+    static final Lookup EXAMPLE = Example.EXAMPLE;
+    public static class PubExample extends Example {
+        public PubExample() { this("PubExample"); }
+        protected PubExample(String prefix) { super(prefix+"#"+nextArg()); }
+        protected void         pro_v0() { called("Pub/pro_v0", this); }
+        protected static void  pro_s0() { called("Pub/pro_s0"); }
+    }
+
+    static class SubExample extends Example {
+        @Override public void  v0()     { called("Sub/v0", this); }
+        @Override void         pkg_v0() { called("Sub/pkg_v0", this); }
+        @SuppressWarnings("LeakingThisInConstructor")
+        private      SubExample(int x)  { called("<init>", this, x); }
+        public SubExample() { super("SubExample#"+nextArg()); }
+    }
+
+    public static interface IntExample {
+        public void            v0();
+        public default void    vd() { called("vd", this); }
+        public static class Impl implements IntExample {
+            public void        v0()     { called("Int/v0", this); }
+            final String name;
+            public Impl() { name = "Impl#"+nextArg(); }
+            @Override public String toString() { return name; }
+        }
+    }
+
+    static interface SubIntExample extends IntExample { }
+
+    static final Object[][][] ACCESS_CASES = {
+        { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
+        { { false, PUBLIC }, { false, SUBCLASS }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE
+        { { false, PUBLIC }, { false, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false
+        { { false, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: subclass OK
+        { { true, PUBLIC }, { true, SUBCLASS }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[4]: all true
+    };
+
+    static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
+        Object[][] cases;
+        if (name.contains("pri_") || isSpecial) {
+            cases = ACCESS_CASES[1]; // PRIVATE only
+        } else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) {
+            cases = ACCESS_CASES[2]; // not PUBLIC
+        } else if (name.contains("pro_")) {
+            cases = ACCESS_CASES[3]; // PUBLIC class, protected member
+        } else {
+            assertTrue(name.indexOf('_') < 0 || name.contains("fin_"));
+            boolean pubc = Modifier.isPublic(defc.getModifiers());
+            if (pubc)
+                cases = ACCESS_CASES[4]; // all access levels
+            else
+                cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC
+        }
+        if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE)
+            cases = Arrays.copyOfRange(cases, 0, cases.length-1);
+        return cases;
+    }
+
+    static Object[][] accessCases(Class<?> defc, String name) {
+        return accessCases(defc, name, false);
+    }
+
+    static Lookup maybeMoveIn(Lookup lookup, Class<?> defc) {
+        if (lookup == PUBLIC || lookup == SUBCLASS || lookup == PACKAGE)
+            // external views stay external
+            return lookup;
+        return lookup.in(defc);
+    }
+
+    /** Is findVirtual (etc.) of "&lt;init&lt;" supposed to elicit a NoSuchMethodException? */
+    static final boolean INIT_REF_CAUSES_NSME = true;
+
+    static void assertExceptionClass(Class<? extends Throwable> expected,
+                                     Throwable actual) {
+        if (expected.isInstance(actual))  return;
+        actual.printStackTrace();
+        assertEquals(expected, actual.getClass());
+    }
+
+    static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
+
+    // rough check of name string
+    static void assertNameStringContains(MethodHandle x, String s) {
+        if (!DEBUG_METHOD_HANDLE_NAMES) {
+            // ignore s
+            assertEquals("MethodHandle"+x.type(), x.toString());
+            return;
+        }
+        if (x.toString().contains(s))  return;
+        assertEquals(s, x);
+    }
+
+    public static class HasFields {
+        boolean fZ = false;
+        byte fB = (byte)'B';
+        short fS = (short)'S';
+        char fC = 'C';
+        int fI = 'I';
+        long fJ = 'J';
+        float fF = 'F';
+        double fD = 'D';
+        static boolean sZ = true;
+        static byte sB = 1+(byte)'B';
+        static short sS = 1+(short)'S';
+        static char sC = 1+'C';
+        static int sI = 1+'I';
+        static long sJ = 1+'J';
+        static float sF = 1+'F';
+        static double sD = 1+'D';
+
+        Object fL = 'L';
+        String fR = "R";
+        static Object sL = 'M';
+        static String sR = "S";
+
+        static final Object[][] CASES;
+        static {
+            ArrayList<Object[]> cases = new ArrayList<>();
+            Object types[][] = {
+                {'L',Object.class}, {'R',String.class},
+                {'I',int.class}, {'J',long.class},
+                {'F',float.class}, {'D',double.class},
+                {'Z',boolean.class}, {'B',byte.class},
+                {'S',short.class}, {'C',char.class},
+            };
+            HasFields fields = new HasFields();
+            for (Object[] t : types) {
+                for (int kind = 0; kind <= 1; kind++) {
+                    boolean isStatic = (kind != 0);
+                    char btc = (Character)t[0];
+                    String name = (isStatic ? "s" : "f") + btc;
+                    Class<?> type = (Class<?>) t[1];
+                    Object value;
+                    Field field;
+                        try {
+                        field = HasFields.class.getDeclaredField(name);
+                    } catch (NoSuchFieldException | SecurityException ex) {
+                        throw new InternalError("no field HasFields."+name);
+                    }
+                    try {
+                        value = field.get(fields);
+                    } catch (IllegalArgumentException | IllegalAccessException ex) {
+                        throw new InternalError("cannot fetch field HasFields."+name);
+                    }
+                    if (type == float.class) {
+                        float v = 'F';
+                        if (isStatic)  v++;
+                        assertTrue(value.equals(v));
+                    }
+                    assertTrue(name.equals(field.getName()));
+                    assertTrue(type.equals(field.getType()));
+                    assertTrue(isStatic == (Modifier.isStatic(field.getModifiers())));
+                    cases.add(new Object[]{ field, value });
+                }
+            }
+            cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
+            cases.add(new Object[]{ new Object[]{ true,  HasFields.class, "bogus_sL", Object.class }, Error.class });
+            CASES = cases.toArray(new Object[0][]);
+        }
+    }
+
+    static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10, TEST_BOUND = 0x20, TEST_NPE = 0x40;
+
+    static boolean testModeMatches(int testMode, boolean isStatic) {
+        switch (testMode) {
+        case TEST_FIND_STATIC:          return isStatic;
+        case TEST_FIND_FIELD:           return !isStatic;
+        case TEST_UNREFLECT:            return true;  // unreflect matches both
+        }
+        throw new InternalError("testMode="+testMode);
+    }
+
+    static class Callee {
+        static Object id() { return called("id"); }
+        static Object id(Object x) { return called("id", x); }
+        static Object id(Object x, Object y) { return called("id", x, y); }
+        static Object id(Object x, Object y, Object z) { return called("id", x, y, z); }
+        static Object id(Object... vx) { return called("id", vx); }
+        static MethodHandle ofType(int n) {
+            return ofType(Object.class, n);
+        }
+        static MethodHandle ofType(Class<?> rtype, int n) {
+            if (n == -1)
+                return ofType(MethodType.methodType(rtype, Object[].class));
+            return ofType(MethodType.genericMethodType(n).changeReturnType(rtype));
+        }
+        static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) {
+            return ofType(MethodType.methodType(rtype, ptypes));
+        }
+        static MethodHandle ofType(MethodType type) {
+            Class<?> rtype = type.returnType();
+            String pfx = "";
+            if (rtype != Object.class)
+                pfx = rtype.getSimpleName().substring(0, 1).toLowerCase();
+            String name = pfx+"id";
+            try {
+                return PRIVATE.findStatic(Callee.class, name, type);
+            } catch (NoSuchMethodException | IllegalAccessException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    static Object invokee(Object... args) {
+        return called("invokee", args).hashCode();
+    }
+
+    protected static final String MISSING_ARG = "missingArg";
+    protected static final String MISSING_ARG_2 = "missingArg#2";
+
+    static Object targetIfEquals() {
+        return called("targetIfEquals");
+    }
+
+    static Object fallbackIfNotEquals() {
+        return called("fallbackIfNotEquals");
+    }
+
+    static Object targetIfEquals(Object x) {
+        assertEquals(x, MISSING_ARG);
+        return called("targetIfEquals", x);
+    }
+
+    static Object fallbackIfNotEquals(Object x) {
+        assertFalse(x.toString(), x.equals(MISSING_ARG));
+        return called("fallbackIfNotEquals", x);
+    }
+
+    static Object targetIfEquals(Object x, Object y) {
+        assertEquals(x, y);
+        return called("targetIfEquals", x, y);
+    }
+
+    static Object fallbackIfNotEquals(Object x, Object y) {
+        assertFalse(x.toString(), x.equals(y));
+        return called("fallbackIfNotEquals", x, y);
+    }
+
+    static Object targetIfEquals(Object x, Object y, Object z) {
+        assertEquals(x, y);
+        return called("targetIfEquals", x, y, z);
+    }
+
+    static Object fallbackIfNotEquals(Object x, Object y, Object z) {
+        assertFalse(x.toString(), x.equals(y));
+        return called("fallbackIfNotEquals", x, y, z);
+    }
+
+    static boolean loopIntPred(int a) {
+        if (verbosity >= 5) {
+            System.out.println("int pred " + a + " -> " + (a < 7));
+        }
+        return a < 7;
+    }
+
+    static boolean loopDoublePred(int a, double b) {
+        if (verbosity >= 5) {
+            System.out.println("double pred (a=" + a + ") " + b + " -> " + (b > 0.5));
+        }
+        return b > 0.5;
+    }
+
+    static boolean loopStringPred(int a, double b, String c) {
+        if (verbosity >= 5) {
+            System.out.println("String pred (a=" + a + ",b=" + b + ") " + c + " -> " + (c.length() <= 9));
+        }
+        return c.length() <= 9;
+    }
+
+    static int loopIntStep(int a) {
+        if (verbosity >= 5) {
+            System.out.println("int step " + a + " -> " + (a + 1));
+        }
+        return a + 1;
+    }
+
+    static double loopDoubleStep(int a, double b) {
+        if (verbosity >= 5) {
+            System.out.println("double step (a=" + a + ") " + b + " -> " + (b / 2.0));
+        }
+        return b / 2.0;
+    }
+
+    static String loopStringStep(int a, double b, String c) {
+        if (verbosity >= 5) {
+            System.out.println("String step (a=" + a + ",b=" + b + ") " + c + " -> " + (c + a));
+        }
+        return c + a;
+    }
+
+    static void vtarget(String[] a) {
+        // naught, akin to identity
+    }
+
+    static void vtargetThrow(String[] a) throws Exception {
+        throw new Exception("thrown");
+    }
+
+    static void vcleanupPassThrough(Throwable t, String[] a) {
+        assertNull(t);
+        // naught, akin to identity
+    }
+
+    static void vcleanupAugment(Throwable t, String[] a) {
+        assertNull(t);
+        a[0] = "augmented";
+    }
+
+    static void vcleanupCatch(Throwable t, String[] a) {
+        assertNotNull(t);
+        a[0] = "caught";
+    }
+
+    static void vcleanupThrow(Throwable t, String[] a) throws Exception {
+        assertNotNull(t);
+        throw new Exception("rethrown");
+    }
+}
+// Local abbreviated copy of sun.invoke.util.ValueConversions
+// This guy tests access from outside the same package member, but inside
+// the package itself.
+class ValueConversions {
+    private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
+    private static final Object[] NO_ARGS_ARRAY = {};
+    private static Object[] makeArray(Object... args) { return args; }
+    private static Object[] array() { return NO_ARGS_ARRAY; }
+    private static Object[] array(Object a0)
+                { return makeArray(a0); }
+    private static Object[] array(Object a0, Object a1)
+                { return makeArray(a0, a1); }
+    private static Object[] array(Object a0, Object a1, Object a2)
+                { return makeArray(a0, a1, a2); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
+                { return makeArray(a0, a1, a2, a3); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4)
+                { return makeArray(a0, a1, a2, a3, a4); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5)
+                { return makeArray(a0, a1, a2, a3, a4, a5); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+                                  Object a4, Object a5, Object a6, Object a7,
+                                  Object a8, Object a9)
+                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+
+    static MethodHandle[] makeArrays() {
+        ArrayList<MethodHandle> arrays = new ArrayList<>();
+        MethodHandles.Lookup lookup = IMPL_LOOKUP;
+        for (;;) {
+            int nargs = arrays.size();
+            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
+            String name = "array";
+            MethodHandle array = null;
+            try {
+                array = lookup.findStatic(ValueConversions.class, name, type);
+            } catch (ReflectiveOperationException ex) {
+                // break from loop!
+            }
+            if (array == null)  break;
+            arrays.add(array);
+        }
+        assertTrue(arrays.size() == 11);  // current number of methods
+        return arrays.toArray(new MethodHandle[0]);
+    }
+
+    static final MethodHandle[] ARRAYS = makeArrays();
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns an Object array of them, as if for varargs.
+     */
+    public static MethodHandle varargsArray(int nargs) {
+        if (nargs < ARRAYS.length)
+            return ARRAYS[nargs];
+        return MethodHandles.identity(Object[].class).asCollector(Object[].class, nargs);
+    }
+
+    public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
+        Class<?> elemType = arrayType.getComponentType();
+        MethodType vaType = MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType));
+        MethodHandle mh = varargsArray(nargs);
+        if (arrayType != Object[].class)
+            mh = MethodHandles.filterReturnValue(mh, CHANGE_ARRAY_TYPE.bindTo(arrayType));
+        return mh.asType(vaType);
+    }
+
+    static Object changeArrayType(Class<?> arrayType, Object[] a) {
+        Class<?> elemType = arrayType.getComponentType();
+        if (!elemType.isPrimitive())
+            return Arrays.copyOf(a, a.length, arrayType.asSubclass(Object[].class));
+        Object b = java.lang.reflect.Array.newInstance(elemType, a.length);
+        for (int i = 0; i < a.length; i++)
+            java.lang.reflect.Array.set(b, i, a[i]);
+        return b;
+    }
+
+    private static final MethodHandle CHANGE_ARRAY_TYPE;
+    static {
+        try {
+            CHANGE_ARRAY_TYPE = IMPL_LOOKUP.findStatic(ValueConversions.class, "changeArrayType",
+                                                       MethodType.methodType(Object.class, Class.class, Object[].class));
+        } catch (NoSuchMethodException | IllegalAccessException ex) {
+            Error err = new InternalError("uncaught exception");
+            err.initCause(ex);
+            throw err;
+        }
+    }
+
+    private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
+    private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
+    private static List<Object> list() { return NO_ARGS_LIST; }
+    private static List<Object> list(Object a0)
+                { return makeList(a0); }
+    private static List<Object> list(Object a0, Object a1)
+                { return makeList(a0, a1); }
+    private static List<Object> list(Object a0, Object a1, Object a2)
+                { return makeList(a0, a1, a2); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
+                { return makeList(a0, a1, a2, a3); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4)
+                { return makeList(a0, a1, a2, a3, a4); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5)
+                { return makeList(a0, a1, a2, a3, a4, a5); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7,
+                                     Object a8)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+                                     Object a4, Object a5, Object a6, Object a7,
+                                     Object a8, Object a9)
+                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+
+    static MethodHandle[] makeLists() {
+        ArrayList<MethodHandle> lists = new ArrayList<>();
+        MethodHandles.Lookup lookup = IMPL_LOOKUP;
+        for (;;) {
+            int nargs = lists.size();
+            MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
+            String name = "list";
+            MethodHandle list = null;
+            try {
+                list = lookup.findStatic(ValueConversions.class, name, type);
+            } catch (ReflectiveOperationException ex) {
+                // break from loop!
+            }
+            if (list == null)  break;
+            lists.add(list);
+        }
+        assertTrue(lists.size() == 11);  // current number of methods
+        return lists.toArray(new MethodHandle[0]);
+    }
+
+    static final MethodHandle[] LISTS = makeLists();
+    static final MethodHandle AS_LIST;
+
+    static {
+        try {
+            AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
+        } catch (NoSuchMethodException | IllegalAccessException ex) { throw new RuntimeException(ex); }
+    }
+
+    /** Return a method handle that takes the indicated number of Object
+     *  arguments and returns List.
+     */
+    public static MethodHandle varargsList(int nargs) {
+        if (nargs < LISTS.length)
+            return LISTS[nargs];
+        return AS_LIST.asCollector(Object[].class, nargs);
+    }
+}
+// This guy tests access from outside the same package member, but inside
+// the package itself.
+class PackageSibling {
+    static Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/MethodTypeTest.java b/ojluni/src/test/java/lang/invoke/MethodTypeTest.java
new file mode 100644
index 0000000..c2ae4e0
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/MethodTypeTest.java
@@ -0,0 +1,567 @@
+/*
+ * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodType
+ * @compile MethodTypeTest.java
+ * @run testng/othervm test.java.lang.invoke.MethodTypeTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.IOException;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+
+import java.util.*;
+import org.testng.*;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.*;
+
+/**
+ *
+ * @author jrose
+ */
+public class MethodTypeTest {
+
+    private Class<?> rtype;
+    private Class<?>[] ptypes;
+    private MethodType mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov;
+    private MethodType mt_iSI, mt_ISi, mt_ISI, mt_iSi;
+    private MethodType mt_viO, mt_iO2, mt_OOi, mt_iOi;
+    private MethodType mt_VIO, mt_IO2, mt_OOI, mt_IOI, mt_VIS;
+    private MethodType mt_vOiSzA, mt_OO99;
+    private MethodType[] GALLERY;
+    private Method compareTo;
+
+    @BeforeMethod
+    public void setUp() throws Exception {
+        rtype = void.class;
+        ptypes = new Class<?>[] { int.class, String.class };
+
+        mt_viS = MethodType.methodType(void.class, int.class, String.class);
+        mt_OO = MethodType.methodType(Object.class, Object.class);
+        mt_OO2 = MethodType.methodType(Object.class, Object.class, Object.class);
+        mt_vv = MethodType.methodType(void.class);
+        mt_Vv = MethodType.methodType(Void.class);
+        mt_Ov = MethodType.methodType(Object.class);
+        mt_iSI = MethodType.methodType(int.class, String.class, Integer.class);
+        mt_ISi = MethodType.methodType(Integer.class, String.class, int.class);
+        mt_ISI = MethodType.methodType(Integer.class, String.class, Integer.class);
+        mt_iSi = MethodType.methodType(int.class, String.class, int.class);
+
+        compareTo = String.class.getDeclaredMethod("compareTo", String.class);
+
+        mt_viO = MethodType.methodType(void.class, int.class, Object.class);
+        mt_iO2 = MethodType.methodType(int.class, Object.class, Object.class);
+        mt_OOi = MethodType.methodType(Object.class, Object.class, int.class);
+        mt_iOi = MethodType.methodType(int.class, Object.class, int.class);
+
+        mt_VIO = MethodType.methodType(Void.class, Integer.class, Object.class);
+        mt_IO2 = MethodType.methodType(Integer.class, Object.class, Object.class);
+        mt_OOI = MethodType.methodType(Object.class, Object.class, Integer.class);
+        mt_IOI = MethodType.methodType(Integer.class, Object.class, Integer.class);
+        mt_VIS = MethodType.methodType(Void.class, Integer.class, String.class);
+
+        mt_vOiSzA = MethodType.methodType(void.class, Object.class, int.class, String.class, boolean.class, Object[].class);
+        mt_OO99 = MethodType.genericMethodType(99);
+
+        GALLERY = new MethodType[] {
+            mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov,
+            mt_iSI, mt_ISi, mt_ISI, mt_iSi,
+            mt_viO, mt_iO2, mt_OOi, mt_iOi,
+            mt_VIO, mt_IO2, mt_OOI, mt_IOI,
+            mt_VIS, mt_vOiSzA, mt_OO99
+        };
+    }
+
+    @AfterMethod
+    public void tearDown() throws Exception {
+    }
+
+    /** Make sure the method types are all distinct. */
+    @Test
+    public void testDistinct() {
+        List<MethodType> gallery2 = new ArrayList<>();
+        for (MethodType mt : GALLERY) {
+            assertFalse(mt.toString(), gallery2.contains(mt));
+            gallery2.add(mt);
+        }
+        // check self-equality also:
+        assertEquals(Arrays.asList(GALLERY), gallery2);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_Class_ClassArr() {
+        System.out.println("make (from type array)");
+        MethodType result = MethodType.methodType(rtype, ptypes);
+        assertSame(mt_viS, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_Class_List() {
+        System.out.println("make (from type list)");
+        MethodType result = MethodType.methodType(rtype, Arrays.asList(ptypes));
+        assertSame(mt_viS, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_3args() {
+        System.out.println("make (from type with varargs)");
+        MethodType result = MethodType.methodType(rtype, ptypes[0], ptypes[1]);
+        assertSame(mt_viS, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_Class() {
+        System.out.println("make (from single type)");
+        Class<?> rt = Integer.class;
+        MethodType expResult = MethodType.methodType(rt, new Class<?>[0]);
+        MethodType result = MethodType.methodType(rt);
+        assertSame(expResult, result);
+    }
+
+    @Test
+    public void testMakeGeneric() {
+        System.out.println("makeGeneric");
+        int objectArgCount = 2;
+        MethodType expResult = mt_OO2;
+        MethodType result = MethodType.genericMethodType(objectArgCount);
+        assertSame(expResult, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_MethodType() {
+        System.out.println("make (from rtype, MethodType)");
+        MethodType expResult = mt_iO2;
+        MethodType result = MethodType.methodType(int.class, mt_IO2);
+        assertSame(expResult, result);
+    }
+
+    /**
+     * Test of make method, of class MethodType.
+     */
+    @Test
+    public void testMake_String_ClassLoader() {
+        System.out.println("make (from bytecode signature)");
+        ClassLoader loader = null;
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        String obj = "Ljava/lang/Object;";
+        assertEquals(obj, concat(Object.class));
+        String[] expResults = {
+            "(ILjava/lang/String;)V",
+            concat("(", obj, 2, ")", Object.class),
+            "()V", "()"+obj,
+            concat("(", String.class, Integer.class, ")I"),
+            concat("(", String.class, "I)", Integer.class),
+            concat("(", String.class, Integer.class, ")", Integer.class),
+            concat("(", String.class, "I)I")
+        };
+        for (int i = 0; i < instances.length; i++) {
+            MethodType instance = instances[i];
+            String result = instance.toMethodDescriptorString();
+            assertEquals("#"+i, expResults[i], result);
+            MethodType parsed = MethodType.fromMethodDescriptorString(result, loader);
+            assertSame("--#"+i, instance, parsed);
+        }
+    }
+    private static String concat(Object... parts) {
+        StringBuilder sb = new StringBuilder();
+        Object prevPart = "";
+        for (Object part : parts) {
+            if (part instanceof Class) {
+                part = "L"+((Class)part).getName()+";";
+            }
+            if (part instanceof Integer) {
+                for (int n = (Integer) part; n > 1; n--)
+                    sb.append(prevPart);
+                part = "";
+            }
+            sb.append(part);
+            prevPart = part;
+        }
+        return sb.toString().replace('.', '/');
+    }
+
+    @Test
+    public void testHasPrimitives() {
+        System.out.println("hasPrimitives");
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        boolean[] expResults =   {true,   false,  true,  false, true,   true,   false,  true};
+        for (int i = 0; i < instances.length; i++) {
+            boolean result = instances[i].hasPrimitives();
+            assertEquals("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testHasWrappers() {
+        System.out.println("hasWrappers");
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        boolean[] expResults =   {false,  false,  false, false, true,   true,   true,   false};
+        for (int i = 0; i < instances.length; i++) {
+            System.out.println("  hasWrappers "+instances[i]);
+            boolean result = instances[i].hasWrappers();
+            assertEquals("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testErase() {
+        System.out.println("erase");
+        MethodType[] instances  = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_viO, mt_OO2, mt_vv, mt_Ov, mt_iO2, mt_OOi, mt_OO2, mt_iOi};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].erase();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testGeneric() {
+        System.out.println("generic");
+        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_OO2, mt_OO2, mt_Ov, mt_Ov, mt_OO2, mt_OO2, mt_OO2, mt_OO2};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].generic();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testWrap() {
+        System.out.println("wrap");
+        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_VIS, mt_OO2, mt_Vv, mt_Ov, mt_ISI, mt_ISI, mt_ISI, mt_ISI};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].wrap();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    @Test
+    public void testUnwrap() {
+        System.out.println("unwrap");
+        MethodType[] instances =  {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        MethodType[] expResults = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSi, mt_iSi, mt_iSi, mt_iSi};
+        for (int i = 0; i < instances.length; i++) {
+            MethodType result = instances[i].unwrap();
+            assertSame("#"+i, expResults[i], result);
+        }
+    }
+
+    /**
+     * Test of parameterType method, of class MethodType.
+     */
+    @Test
+    public void testParameterType() {
+        System.out.println("parameterType");
+        for (int num = 0; num < ptypes.length; num++) {
+            MethodType instance = mt_viS;
+            Class<?> expResult = ptypes[num];
+            Class<?> result = instance.parameterType(num);
+            assertSame(expResult, result);
+        }
+    }
+
+    /**
+     * Test of parameterCount method, of class MethodType.
+     */
+    @Test
+    public void testParameterCount() {
+        System.out.println("parameterCount");
+        MethodType instance = mt_viS;
+        int expResult = 2;
+        int result = instance.parameterCount();
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of returnType method, of class MethodType.
+     */
+    @Test
+    public void testReturnType() {
+        System.out.println("returnType");
+        MethodType instance = mt_viS;
+        Class<?> expResult = void.class;
+        Class<?> result = instance.returnType();
+        assertSame(expResult, result);
+    }
+
+    /**
+     * Test of parameterList method, of class MethodType.
+     */
+    @Test
+    public void testParameterList() {
+        System.out.println("parameterList");
+        MethodType instance = mt_viS;
+        List<Class<?>> expResult = Arrays.asList(ptypes);
+        List<Class<?>> result = instance.parameterList();
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of parameterArray method, of class MethodType.
+     */
+    @Test
+    public void testParameterArray() {
+        System.out.println("parameterArray");
+        MethodType instance = mt_viS;
+        Class<?>[] expResult = ptypes;
+        Class<?>[] result = instance.parameterArray();
+        assertEquals(Arrays.asList(expResult), Arrays.asList(result));
+    }
+
+    /**
+     * Test of equals method, of class MethodType.
+     */
+    @Test
+    public void testEquals_Object() {
+        System.out.println("equals");
+        Object x = null;
+        MethodType instance = mt_viS;
+        boolean expResult = false;
+        boolean result = instance.equals(x);
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of equals method, of class MethodType.
+     */
+    @Test
+    public void testEquals_MethodType() {
+        System.out.println("equals");
+        MethodType that = mt_viS;
+        MethodType instance = mt_viS;
+        boolean expResult = true;
+        boolean result = instance.equals(that);
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of hashCode method, of class MethodType.
+     */
+    @Test
+    public void testHashCode() {
+        System.out.println("hashCode");
+        MethodType instance = mt_viS;
+        ArrayList<Class<?>> types = new ArrayList<>();
+        types.add(instance.returnType());
+        types.addAll(instance.parameterList());
+        int expResult = types.hashCode();
+        int result = instance.hashCode();
+        assertEquals(expResult, result);
+    }
+
+    /**
+     * Test of toString method, of class MethodType.
+     */
+    @Test
+    public void testToString() {
+        System.out.println("toString");
+        MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+        //String expResult = "void[int, class java.lang.String]";
+        String[] expResults = {
+            "(int,String)void",
+            "(Object,Object)Object",
+            "()void",
+            "()Object",
+            "(String,Integer)int",
+            "(String,int)Integer",
+            "(String,Integer)Integer",
+            "(String,int)int"
+        };
+        for (int i = 0; i < instances.length; i++) {
+            MethodType instance = instances[i];
+            String result = instance.toString();
+            System.out.println("#"+i+":"+result);
+            assertEquals("#"+i, expResults[i], result);
+        }
+    }
+
+    private static byte[] writeSerial(Object x) throws java.io.IOException {
+        try (java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
+             java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(bout)
+             ) {
+            out.writeObject(x);
+            out.flush();
+            return bout.toByteArray();
+        }
+    }
+    private static Object readSerial(byte[] wire) throws java.io.IOException, ClassNotFoundException {
+        try (java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(wire);
+             java.io.ObjectInputStream in = new java.io.ObjectInputStream(bin)) {
+            return in.readObject();
+        }
+    }
+    private static void testSerializedEquality(Object x) throws java.io.IOException, ClassNotFoundException {
+        if (x instanceof Object[])
+            x = Arrays.asList((Object[]) x);  // has proper equals method
+        byte[] wire = writeSerial(x);
+        Object y = readSerial(wire);
+        assertEquals(x, y);
+    }
+
+    /** Test (de-)serialization. */
+    @Test
+    public void testSerialization() throws Throwable {
+        System.out.println("serialization");
+        for (MethodType mt : GALLERY) {
+            testSerializedEquality(mt);
+        }
+        testSerializedEquality(GALLERY);
+
+        // Make a list of mixed objects:
+        List<Object> stuff = new ArrayList<>();
+        Collections.addAll(stuff, GALLERY);  // copy #1
+        Object[] triples = Arrays.copyOfRange(GALLERY, 0, GALLERY.length/2);
+        Collections.addAll(stuff, triples);  // copy #3 (partial)
+        for (MethodType mt : GALLERY) {
+            Collections.addAll(stuff, mt.parameterArray());
+        }
+        Collections.shuffle(stuff, new Random(292));
+        Collections.addAll(stuff, GALLERY);  // copy #2
+        testSerializedEquality(stuff);
+    }
+
+    /** Test serialization formats. */
+    @Test
+    public void testPortableSerialFormat() throws Throwable {
+        System.out.println("portable serial format");
+        boolean generateData = false;
+        //generateData = true;  // set this true to generate the following input data:
+        Object[][] cases = {
+            { mt_vv, new byte[] {  // ()void
+                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
+                    (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
+                    (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
+                    (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
+                    (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+                } },
+            { mt_OO, new byte[] {  // (Object)Object
+                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
+                    (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62,
+                    (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+                    (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a,
+                    (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+                    (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61, (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab,
+                    (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb, (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02,
+                    (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
+                    (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x03, (byte)0x78,
+                } },
+            { mt_vOiSzA, new byte[] {  // (Object,int,String,boolean,Object[])void
+                    (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+                    (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+                    (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
+                    (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
+                    (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
+                    (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
+                    (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00,
+                    (byte)0x03, (byte)0x69, (byte)0x6e, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+                    (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76,
+                    (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x53,
+                    (byte)0x74, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67, (byte)0xa0, (byte)0xf0, (byte)0xa4,
+                    (byte)0x38, (byte)0x7a, (byte)0x3b, (byte)0xb3, (byte)0x42, (byte)0x02, (byte)0x00, (byte)0x00,
+                    (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x07, (byte)0x62, (byte)0x6f,
+                    (byte)0x6f, (byte)0x6c, (byte)0x65, (byte)0x61, (byte)0x6e, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                    (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x13, (byte)0x5b, (byte)0x4c,
+                    (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+                    (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+                    (byte)0x3b, (byte)0x90, (byte)0xce, (byte)0x58, (byte)0x9f, (byte)0x10, (byte)0x73, (byte)0x29,
+                    (byte)0x6c, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x78,
+                } },
+        };
+        for (Object[] c : cases) {
+            MethodType mt = (MethodType) c[0];
+            System.out.println("deserialize "+mt);
+            byte[] wire = (byte[]) c[1];
+            if (generateData) {
+                System.out.println("<generateData>");
+                wire = writeSerial(mt);
+                final String INDENT = "                ";
+                System.out.print("{  // "+mt);
+                for (int i = 0; i < wire.length; i++) {
+                    if (i % 8 == 0) { System.out.println(); System.out.print(INDENT+"   "); }
+                    String hex = Integer.toHexString(wire[i] & 0xFF);
+                    if (hex.length() == 1)  hex = "0"+hex;
+                    System.out.print(" (byte)0x"+hex+",");
+                }
+                System.out.println();
+                System.out.println(INDENT+"}");
+                System.out.println("</generateData>");
+                System.out.flush();
+            }
+            Object decode;
+            try {
+                decode = readSerial(wire);
+            } catch (IOException | ClassNotFoundException ex) {
+                decode = ex;  // oops!
+            }
+            assertEquals(mt, decode);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/PermuteArgsReturnVoidTest.java b/ojluni/src/test/java/lang/invoke/PermuteArgsReturnVoidTest.java
new file mode 100644
index 0000000..b01a4aa
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/PermuteArgsReturnVoidTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8184119
+ * @summary test permutation when return value is directly derived from an argument
+ * @run testng/othervm test.java.lang.invoke.PermuteArgsReturnVoidTest
+ */
+
+
+package test.java.lang.invoke;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodHandles.dropArguments;
+import static java.lang.invoke.MethodHandles.identity;
+
+public class PermuteArgsReturnVoidTest {
+
+    static String consumeIdentity(String s, int i1, int i2) {
+        return s;
+    }
+
+    static void consumeVoid(String s, int i1, int i2) {
+    }
+
+    @Test
+    public void testReturnOnStack() throws Throwable {
+        MethodHandles.Lookup l = MethodHandles.lookup();
+
+        MethodHandle consumeIdentity = l.findStatic(
+                PermuteArgsReturnVoidTest.class, "consumeIdentity",
+                MethodType.methodType(String.class, String.class, int.class, int.class));
+        MethodHandle consumeVoid = l.findStatic(
+                PermuteArgsReturnVoidTest.class, "consumeVoid",
+                MethodType.methodType(void.class, String.class, int.class, int.class));
+
+        MethodHandle f = MethodHandles.foldArguments(consumeIdentity, consumeVoid);
+
+        MethodHandle p = MethodHandles.permuteArguments(f, MethodType.methodType(String.class, String.class, int.class, int.class), 0, 2, 1);
+
+        String s = (String) p.invoke("IN", 0, 0);
+        Assert.assertEquals(s.getClass(), String.class);
+        Assert.assertEquals(s, "IN");
+    }
+
+    @Test
+    public void testReturnFromArg() throws Throwable {
+        MethodHandles.Lookup l = MethodHandles.lookup();
+
+        MethodHandle consumeIdentity = dropArguments(
+                identity(String.class), 1, int.class, int.class);
+        MethodHandle consumeVoid = l.findStatic(
+                PermuteArgsReturnVoidTest.class, "consumeVoid",
+                MethodType.methodType(void.class, String.class, int.class, int.class));
+
+        MethodHandle f = MethodHandles.foldArguments(consumeIdentity, consumeVoid);
+
+        MethodHandle p = MethodHandles.permuteArguments(f, MethodType.methodType(String.class, String.class, int.class, int.class), 0, 2, 1);
+
+        String s = (String) p.invoke("IN", 0, 0);
+        Assert.assertEquals(s.getClass(), String.class);
+        Assert.assertEquals(s, "IN");
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/PermuteArgsTest.java b/ojluni/src/test/java/lang/invoke/PermuteArgsTest.java
new file mode 100644
index 0000000..e175102
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/PermuteArgsTest.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for method handles which permute their arguments
+ * @library /lib/testlibrary /java/lang/invoke/common
+ * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -ea -esa -DPermuteArgsTest.MAX_ARITY=8 test.java.lang.invoke.PermuteArgsTest
+ */
+
+/* Examples of manual runs:
+ * java -DPermuteArgsTest.{DRY_RUN=true,MAX_ARITY=253} test.java.lang.invoke.PermuteArgsTest
+ * java -DPermuteArgsTest.{VERBOSE=true,MAX_ARITY=5} test.java.lang.invoke.PermuteArgsTest
+ * java test.java.lang.invoke.PermuteArgsTest list3I[2,0,1] listJLJ[2,0,1]
+ */
+
+package test.java.lang.invoke;
+
+import org.testng.annotations.Test;
+import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.lang.invoke.MethodHandles.Lookup;
+import static java.lang.invoke.MethodHandles.lookup;
+import static java.lang.invoke.MethodHandles.permuteArguments;
+import static java.lang.invoke.MethodType.methodType;
+
+public class PermuteArgsTest {
+    private static final Class<?> CLASS = PermuteArgsTest.class;
+    private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 8);
+    private static final boolean DRY_RUN = Boolean.getBoolean(CLASS.getSimpleName()+".DRY_RUN");
+    private static final boolean VERBOSE = Boolean.getBoolean(CLASS.getSimpleName()+".VERBOSE") || DRY_RUN;
+
+    static Object list2I(int x, int y) {
+        return Arrays.asList(x, y);
+    }
+    static Object list3I(int x, int y, int z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object list4I(int w, int x, int y, int z) {
+        return Arrays.asList(w, x, y, z);
+    }
+    static Object list2J(long x, long y) {
+        return Arrays.asList(x, y);
+    }
+    static Object list3J(long x, long y, long z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object list4J(long w, long x, long y, long z) {
+        return Arrays.asList(w, x, y, z);
+    }
+    static Object list2I2J(int w, int x, long y, long z) {
+        return Arrays.asList(w, x, y, z);
+    }
+    static Object list2J2I(long w, long x, int y, int z) {
+        return Arrays.asList(w, x, y, z);
+    }
+    static Object listLJJ(Object x, long y, long z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object listJLJ(long x, Object y, long z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object listJJL(long x, long y, Object z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object listJLL(long x, Object y, Object z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object listLJL(Object x, long y, Object z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object listLLJ(Object x, Object y, long z) {
+        return Arrays.asList(x, y, z);
+    }
+    static Object listJLLJ(long w, Object x, Object y, long z) {
+        return Arrays.asList(w, x, y, z);
+    }
+    static Object listLJJL(Object w, long x, long y, Object z) {
+        return Arrays.asList(w, x, y, z);
+    }
+    static Object listI_etc(int... va) {
+        ArrayList<Object> res = new ArrayList<>();
+        for (int x : va)  res.add(x);
+        return res;
+    }
+    static Object listIJL_etc(int x, long y, Object z, Object... va) {
+        ArrayList<Object> res = new ArrayList<>();
+        res.addAll(Arrays.asList(x, y, z));
+        res.addAll(Arrays.asList(va));
+        return res;
+    }
+
+    public static void main(String argv[]) throws Throwable {
+        if (argv.length > 0) {
+            for (String arg : argv) {
+                // arg ::= name[n,...]
+                int k = arg.indexOf('[');
+                String mhName = arg.substring(0, k).trim();
+                String permString = arg.substring(k);
+                testOnePermutation(mhName, permString);
+            }
+            return;
+        }
+        new PermuteArgsTest().test();
+    }
+
+    static int testCases;
+
+    @Test
+    public void test() throws Throwable {
+        CodeCacheOverflowProcessor.runMHTest(this::test0);
+    }
+
+    public void test0() throws Throwable {
+        testCases = 0;
+        Lookup lookup = lookup();
+        for (Method m : lookup.lookupClass().getDeclaredMethods()) {
+            if (m.getName().startsWith("list") &&
+                Modifier.isStatic(m.getModifiers())) {
+                test(m.getName(), lookup.unreflect(m));
+            }
+        }
+        System.out.println("ran a total of "+testCases+" test cases");
+    }
+
+    static int jump(int i, int min, int max) {
+        if (i >= min && i <= max-1) {
+            // jump faster
+            int len = max-min;
+            if (i < min + len/2)
+                i = min + len/2;
+            else
+                i = max-1;
+        }
+        return i;
+    }
+
+    static void test(String name, MethodHandle mh) throws Throwable {
+        if (VERBOSE)
+            System.out.println("mh = "+name+" : "+mh+" { "
+                               +Arrays.toString(junkArgs(mh.type().parameterArray())));
+        int testCases0 = testCases;
+        if (!mh.isVarargsCollector()) {
+            // normal case
+            testPermutations(mh);
+        } else {
+            // varargs case; add params up to MAX_ARITY
+            MethodType mt = mh.type();
+            int posArgs = mt.parameterCount() - 1;
+            int arity0 = Math.max(3, posArgs);
+            for (int arity = arity0; arity <= MAX_ARITY; arity++) {
+                MethodHandle mh1;
+                try {
+                    mh1 = adjustArity(mh, arity);
+                } catch (IllegalArgumentException ex) {
+                    System.out.println("*** mh = "+name+" : "+mh+"; arity = "+arity+" => "+ex);
+                    ex.printStackTrace(System.out);
+                    break;  // cannot get this arity for this type
+                }
+                test("("+arity+")"+name, mh1);
+                arity = jump(arity, arity0*2, MAX_ARITY);
+            }
+        }
+        if (VERBOSE)
+            System.out.println("ran "+(testCases - testCases0)+" test cases for "+name+" }");
+    }
+
+    static MethodHandle adjustArity(MethodHandle mh, int arity) {
+        MethodType mt = mh.type();
+        int posArgs = mt.parameterCount() - 1;
+        Class<?> reptype = mt.parameterType(posArgs).getComponentType();
+        MethodType mt1 = mt.dropParameterTypes(posArgs, posArgs+1);
+        while (mt1.parameterCount() < arity) {
+            Class<?> pt = reptype;
+            if (pt == Object.class && posArgs > 0)
+                // repeat types cyclically if possible:
+                pt = mt1.parameterType(mt1.parameterCount() - posArgs);
+            mt1 = mt1.appendParameterTypes(pt);
+        }
+        try {
+            return mh.asType(mt1);
+        } catch (WrongMethodTypeException | IllegalArgumentException ex) {
+            throw new IllegalArgumentException("cannot convert to type "+mt1+" from "+mh, ex);
+        }
+    }
+    static MethodHandle findTestMH(String name, int[] perm)
+            throws ReflectiveOperationException {
+        int arity = perm.length;
+        Lookup lookup = lookup();
+        for (Method m : lookup.lookupClass().getDeclaredMethods()) {
+            if (m.getName().equals(name) &&
+                Modifier.isStatic(m.getModifiers())) {
+                MethodHandle mh = lookup.unreflect(m);
+                int mhArity = mh.type().parameterCount();
+                if (mh.isVarargsCollector()) {
+                    if (mhArity-1 <= arity)
+                        return adjustArity(mh, arity);
+                } else if (mhArity == arity) {
+                    return mh;
+                }
+            }
+        }
+        throw new RuntimeException("no such method for arity "+arity+": "+name);
+    }
+
+    static void testPermutations(MethodHandle mh) throws Throwable {
+        HashSet<String> done = new HashSet<>();
+        MethodType mt = mh.type();
+        int[] perm = nullPerm(mt.parameterCount());
+        final int MARGIN = (perm.length <= 10 ? 2 : 0);
+        int testCases0 = testCases;
+        for (int j = 0; j <= 1; j++) {
+            int maxStart = perm.length-1;
+            if (j != 0)  maxStart /= 2;
+            for (int start = 0; start <= maxStart; start++) {
+                int maxOmit = (maxStart - start) / 2;
+                if (start != 0)  maxOmit = 2;
+                if (j != 0)  maxOmit = 1;
+                for (int omit = 0; omit <= maxOmit; omit++) {
+                    int end = perm.length - omit;
+                    if (end - start >= 2) {
+                        //System.out.println("testPermutations"+Arrays.asList(start, end)+(j == 0 ? "" : " (reverse)"));
+                        testPermutations(mh, perm, start, end, done);
+                    }
+                    omit = jump(omit, (start == 0 && j == 0 ? MARGIN : 0), maxOmit);
+                }
+                start = jump(start, (j == 0 ? MARGIN : 0), maxStart);
+            }
+            // do everything in reverse:
+            reverse(perm, 0, perm.length);
+        }
+        switch (perm.length) {
+        case 2: assert(testCases - testCases0 == 2); break;
+        case 3: assert(testCases - testCases0 == 6); break;
+        case 4: assert(testCases - testCases0 == 24); break;
+        case 5: assert(testCases - testCases0 == 120); break;
+        case 6: assert(testCases - testCases0 > 720/3); break;
+        }
+    }
+
+    static void testPermutations(MethodHandle mh, int[] perm, int start, int end,
+                                 Set<String> done) throws Throwable {
+        if (end - start <= 1)  return;
+        for (int j = 0; j <= 1; j++) {
+            testRotations(mh, perm, start, end, done);
+            if (end - start <= 2)  return;
+            reverse(perm, start, end);
+        }
+        if (end - start <= 3)  return;
+        int excess4 = (end - start) - 4;
+        // composed rotations:
+        int start2 = start + 1 + excess4/3;
+        int end2   = end       - excess4/3;
+        end2 = start2 + Math.min(start == 0 ? 4 : 3, end2 - start2);
+        int skips = (perm.length+3)/5;
+        for (int i = start; i < end; i++) {
+            rotate(perm, start, end);
+            if (skips > 1 && ((i-start) + (i-start)/7) % skips != 0)  continue;
+            for (int j = 0; j <= 1; j++) {
+                testPermutations(mh, perm, start2, end2, done);
+                reverse(perm, start, end);
+            }
+        }
+    }
+
+    static void testRotations(MethodHandle mh, int[] perm, int start, int end,
+                              Set<String> done) throws Throwable {
+        Object[] args = junkArgs(mh.type().parameterArray());
+        for (int i = start; i < end; i++) {
+            if (done.add(Arrays.toString(perm)))
+                testOnePermutation(mh, perm, args);
+            rotate(perm, start, end);
+        }
+    }
+
+    static void testOnePermutation(MethodHandle mh, int[] perm, Object[] args)
+            throws Throwable {
+        MethodType mt = mh.type();
+        MethodType pmt = methodType(mt.returnType(),
+                unpermuteArgs(perm, mt.parameterArray(), Class[].class));
+        if (VERBOSE)
+            System.out.println(Arrays.toString(perm));
+        testCases += 1;
+        if (DRY_RUN)
+            return;
+        Object res = permuteArguments(mh, pmt, perm).invokeWithArguments(unpermuteArgs(perm, args));
+        String str = String.valueOf(res);
+        if (!Arrays.toString(args).equals(str)) {
+            System.out.println(Arrays.toString(perm)+" "+str+" *** WRONG ***");
+        }
+    }
+
+    // For reproducing failures:
+    static void testOnePermutation(String mhName, String permString) throws Throwable {
+        String s = permString;
+        s = s.replace('[', ' ').replace(']', ' ').replace(',', ' ');  // easier to trim spaces
+        s = s.trim();
+        int[] perm = new int[s.length()];
+        int arity = 0;
+        while (!s.isEmpty()) {
+            int k = s.indexOf(' ');
+            if (k < 0)  k = s.length();
+            perm[arity++] = Integer.parseInt(s.substring(0, k));
+            s = s.substring(k).trim();
+        }
+        perm = Arrays.copyOf(perm, arity);
+        testOnePermutation(mhName, perm);
+    }
+    static void testOnePermutation(String mhName, int[] perm) throws Throwable {
+        MethodHandle mh = findTestMH(mhName, perm);
+        System.out.println("mh = "+mhName+" : "+mh+" { "
+                           +Arrays.toString(junkArgs(mh.type().parameterArray())));
+        Object[] args = junkArgs(mh.type().parameterArray());
+        testOnePermutation(mh, perm, args);
+        System.out.println("}");
+    }
+
+    static Object[] junkArgs(Class<?>[] ptypes) {
+        Object[] args = new Object[ptypes.length];
+        for (int i = 0; i < ptypes.length; i++) {
+            Class<?> pt = ptypes[i];
+            Object arg;
+            if (pt == Void.class)       arg = null;
+            else if (pt == int.class)   arg = i + 101;
+            else if (pt == long.class)  arg = i + 10_000_000_001L;
+            else                        arg = "#" + (i + 1);
+            args[i] = arg;
+        }
+        return args;
+    }
+
+    static int[] nullPerm(int len) {
+        int[] perm = new int[len];
+        for (int i = 0; i < len; i++)
+            perm[i] = i;
+        return perm;
+    }
+    static void rotate(int[] perm) {
+        rotate(perm, 0, perm.length);
+    }
+    static void rotate(int[] perm, int start, int end) {
+        int x = perm[end-1];
+        for (int j = start; j < end; j++) {
+            int y = perm[j]; perm[j] = x; x = y;
+        }
+    }
+    static void reverse(int[] perm) {
+        reverse(perm, 0, perm.length);
+    }
+    static void reverse(int[] perm, int start, int end) {
+        int mid = start + (end - start)/2;
+        for (int j = start; j < mid; j++) {
+            int k = (end-1) - j;
+            int x = perm[j]; perm[j] = perm[k]; perm[k] = x;
+        }
+    }
+    // Permute the args according to the inverse of perm.
+    static Object[] unpermuteArgs(int[] perm, Object[] args) {
+        return unpermuteArgs(perm, args, Object[].class);
+    }
+    static <T> T[] unpermuteArgs(int[] perm, T[] args, Class<T[]> Tclass) {
+        T[] res = Arrays.copyOf(new Object[0], perm.length, Tclass);
+        for (int i = 0; i < perm.length; i++)
+            res[perm[i]] = args[i];
+        return res;
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/RicochetTest.java b/ojluni/src/test/java/lang/invoke/RicochetTest.java
new file mode 100644
index 0000000..943f17e
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/RicochetTest.java
@@ -0,0 +1,699 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for recursive method handles
+ * @run junit/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -DRicochetTest.MAX_ARITY=10 test.java.lang.invoke.RicochetTest
+ */
+/*
+ * @ignore The following test creates an unreasonable number of adapters in -Xcomp mode (7049122)
+ * @run junit/othervm -DRicochetTest.MAX_ARITY=255 test.java.lang.invoke.RicochetTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import java.util.*;
+import org.junit.*;
+import static java.lang.invoke.MethodType.*;
+import static java.lang.invoke.MethodHandles.*;
+import static org.junit.Assert.*;
+
+
+/**
+ *
+ * @author jrose
+ */
+public class RicochetTest {
+    private static final Class<?> CLASS = RicochetTest.class;
+    private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40);
+
+    public static void main(String... av) throws Throwable {
+        RicochetTest test = new RicochetTest();
+        if (av.length > 0)  test.testOnly = Arrays.asList(av).toString();
+        if (REPEAT == 1 || test.testOnly != null) {
+            test.testAll();
+            if (test.testOnlyTests == null)  throw new RuntimeException("no matching test: "+test.testOnly);
+        } else if (REPEAT == 0) {
+            org.junit.runner.JUnitCore.runClasses(RicochetTest.class);
+        } else {
+            verbose(1, "REPEAT="+REPEAT);
+            for (int i = 0; i < REPEAT; i++) {
+                test.testRepetition = (i+1);
+                verbose(0, "[#"+test.testRepetition+"]");
+                test.testAll();
+            }
+        }
+    }
+    int testRepetition;
+
+    public void testAll() throws Throwable {
+        testNull();
+        testBoxInteger();
+        testFilterReturnValue();
+        testFilterObject();
+        testBoxLong();
+        testFilterInteger();
+        testIntSpreads();
+        testByteSpreads();
+        testLongSpreads();
+        testIntCollects();
+        testReturns();
+        testRecursion();
+    }
+
+    @Test
+    public void testNull() throws Throwable {
+        if (testRepetition > (1+REPEAT/100))  return;  // trivial test
+        if (!startTest("testNull"))  return;
+        assertEquals(opI(37), opI.invokeWithArguments(37));
+        assertEqualFunction(opI, opI);
+    }
+
+    @Test
+    public void testBoxInteger() throws Throwable {
+        if (!startTest("testBoxInteger"))  return;
+        assertEqualFunction(opI, opI.asType(opL_I.type()).asType(opI.type()));
+    }
+
+    @Test
+    public void testFilterReturnValue() throws Throwable {
+        if (!startTest("testFilterReturnValue"))  return;
+        int[] ints = { 12, 23, 34, 45, 56, 67, 78, 89 };
+        Object res = list8ints.invokeExact(ints[0], ints[1], ints[2], ints[3], ints[4], ints[5], ints[6], ints[7]);
+        assertEquals(Arrays.toString(ints), res.toString());
+        MethodHandle idreturn = filterReturnValue(list8ints, identity(Object.class));
+        res = idreturn.invokeExact(ints[0], ints[1], ints[2], ints[3], ints[4], ints[5], ints[6], ints[7]);
+        assertEquals(Arrays.toString(ints), res.toString());
+        MethodHandle add0 = addL.bindTo(0);
+        assertEqualFunction(filterReturnValue(opL2, add0), opL2);
+    }
+
+    @Test
+    public void testFilterObject() throws Throwable {
+        if (!startTest("testFilterObject"))  return;
+        MethodHandle add0 = addL.bindTo(0);
+        assertEqualFunction(sequence(opL2, add0), opL2);
+        int bump13 = -13;  // value near 20 works as long as test values are near [-80..80]
+        MethodHandle add13   = addL.bindTo(bump13);
+        MethodHandle add13_0 = addL.bindTo(opI2(bump13, 0));
+        MethodHandle add13_1 = addL.bindTo(opI2(0, bump13));
+        assertEqualFunction(sequence(opL2, add13_0),
+                            filterArguments(opL2, 0, add13));
+        assertEqualFunction(sequence(opL2, add13_1),
+                            filterArguments(opL2, 1, add13));
+        System.out.println("[testFilterObject done]");
+    }
+
+    @Test
+    public void testBoxLong() throws Throwable {
+        if (!startTest("testBoxLong"))  return;
+        assertEqualFunction(opJ, opJ.asType(opL_J.type()).asType(opJ.type()));
+    }
+
+    @Test
+    public void testFilterInteger() throws Throwable {
+        if (!startTest("testFilterInteger"))  return;
+        assertEqualFunction(opI, sequence(convI_L, opL_I));
+    }
+
+    @Test
+    public void testIntSpreads() throws Throwable {
+        if (!startTest("testIntSpreads"))  return;
+        MethodHandle id = identity(int[].class);
+        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
+        for (int nargs = 0; nargs <= MAX; nargs++) {
+            if (nargs > 30 && nargs < MAX-20)  nargs += 10;
+            int[] args = new int[nargs];
+            for (int j = 0; j < args.length; j++)  args[j] = j + 11;
+            //System.out.println("testIntSpreads "+Arrays.toString(args));
+            int[] args1 = (int[]) id.invokeExact(args);
+            assertArrayEquals(args, args1);
+            MethodHandle coll = id.asCollector(int[].class, nargs);
+            int[] args2 = args;
+            switch (nargs) {
+                case 0:  args2 = (int[]) coll.invokeExact(); break;
+                case 1:  args2 = (int[]) coll.invokeExact(args[0]); break;
+                case 2:  args2 = (int[]) coll.invokeExact(args[0], args[1]); break;
+                case 3:  args2 = (int[]) coll.invokeExact(args[0], args[1], args[2]); break;
+                case 4:  args2 = (int[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
+                case 5:  args2 = (int[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
+            }
+            assertArrayEquals(args, args2);
+            MethodHandle mh = coll.asSpreader(int[].class, nargs);
+            int[] args3 = (int[]) mh.invokeExact(args);
+            assertArrayEquals(args, args3);
+        }
+    }
+
+    @Test
+    public void testByteSpreads() throws Throwable {
+        if (!startTest("testByteSpreads"))  return;
+        MethodHandle id = identity(byte[].class);
+        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
+        for (int nargs = 0; nargs <= MAX; nargs++) {
+            if (nargs > 30 && nargs < MAX-20)  nargs += 10;
+            byte[] args = new byte[nargs];
+            for (int j = 0; j < args.length; j++)  args[j] = (byte)(j + 11);
+            //System.out.println("testByteSpreads "+Arrays.toString(args));
+            byte[] args1 = (byte[]) id.invokeExact(args);
+            assertArrayEquals(args, args1);
+            MethodHandle coll = id.asCollector(byte[].class, nargs);
+            byte[] args2 = args;
+            switch (nargs) {
+                case 0:  args2 = (byte[]) coll.invokeExact(); break;
+                case 1:  args2 = (byte[]) coll.invokeExact(args[0]); break;
+                case 2:  args2 = (byte[]) coll.invokeExact(args[0], args[1]); break;
+                case 3:  args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2]); break;
+                case 4:  args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
+                case 5:  args2 = (byte[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
+            }
+            assertArrayEquals(args, args2);
+            MethodHandle mh = coll.asSpreader(byte[].class, nargs);
+            byte[] args3 = (byte[]) mh.invokeExact(args);
+            assertArrayEquals(args, args3);
+        }
+    }
+
+    @Test
+    public void testLongSpreads() throws Throwable {
+        if (!startTest("testLongSpreads"))  return;
+        MethodHandle id = identity(long[].class);
+        final int MAX = (MAX_ARITY - 2) / 2;  // 253/2+1 would cause parameter overflow with 'this' added
+        for (int nargs = 0; nargs <= MAX; nargs++) {
+            if (nargs > 30 && nargs < MAX-20)  nargs += 10;
+            long[] args = new long[nargs];
+            for (int j = 0; j < args.length; j++)  args[j] = (long)(j + 11);
+            //System.out.println("testLongSpreads "+Arrays.toString(args));
+            long[] args1 = (long[]) id.invokeExact(args);
+            assertArrayEquals(args, args1);
+            MethodHandle coll = id.asCollector(long[].class, nargs);
+            long[] args2 = args;
+            switch (nargs) {
+                case 0:  args2 = (long[]) coll.invokeExact(); break;
+                case 1:  args2 = (long[]) coll.invokeExact(args[0]); break;
+                case 2:  args2 = (long[]) coll.invokeExact(args[0], args[1]); break;
+                case 3:  args2 = (long[]) coll.invokeExact(args[0], args[1], args[2]); break;
+                case 4:  args2 = (long[]) coll.invokeExact(args[0], args[1], args[2], args[3]); break;
+                case 5:  args2 = (long[]) coll.invokeExact(args[0], args[1], args[2], args[3], args[4]); break;
+            }
+            assertArrayEquals(args, args2);
+            MethodHandle mh = coll.asSpreader(long[].class, nargs);
+            long[] args3 = (long[]) mh.invokeExact(args);
+            assertArrayEquals(args, args3);
+        }
+    }
+
+    @Test
+    public void testIntCollects() throws Throwable {
+        if (!startTest("testIntCollects"))  return;
+        for (MethodHandle lister : INT_LISTERS) {
+            int outputs = lister.type().parameterCount();
+            for (int collects = 0; collects <= Math.min(outputs, INT_COLLECTORS.length-1); collects++) {
+                int inputs = outputs - 1 + collects;
+                if (inputs < 0)  continue;
+                for (int pos = 0; pos + collects <= inputs; pos++) {
+                    MethodHandle collector = INT_COLLECTORS[collects];
+                    int[] args = new int[inputs];
+                    int ap = 0, arg = 31;
+                    for (int i = 0; i < pos; i++)
+                        args[ap++] = arg++ + 0;
+                    for (int i = 0; i < collects; i++)
+                        args[ap++] = arg++ + 10;
+                    while (ap < args.length)
+                        args[ap++] = arg++ + 20;
+                    // calculate piecemeal:
+                    //System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args));
+                    int[] collargs = Arrays.copyOfRange(args, pos, pos+collects);
+                    int coll = (int) collector.asSpreader(int[].class, collargs.length).invokeExact(collargs);
+                    int[] listargs = Arrays.copyOfRange(args, 0, outputs);
+                    System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1));
+                    listargs[pos] = coll;
+                    //System.out.println("  coll="+coll+" listargs="+Arrays.toString(listargs));
+                    Object expect = lister.asSpreader(int[].class, listargs.length).invokeExact(listargs);
+                    //System.out.println("  expect="+expect);
+
+                    // now use the combined MH, and test the output:
+                    MethodHandle mh = collectArguments(lister, pos, int[].class, INT_COLLECTORS[collects]);
+                    if (mh == null)  continue;  // no infix collection, yet
+                    assert(mh.type().parameterCount() == inputs);
+                    Object observe = mh.asSpreader(int[].class, args.length).invokeExact(args);
+                    assertEquals(expect, observe);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testByteCollects() throws Throwable {
+        if (!startTest("testByteCollects"))  return;
+        for (MethodHandle lister : BYTE_LISTERS) {
+            int outputs = lister.type().parameterCount();
+            for (int collects = 0; collects <= Math.min(outputs, BYTE_COLLECTORS.length-1); collects++) {
+                int inputs = outputs - 1 + collects;
+                if (inputs < 0)  continue;
+                for (int pos = 0; pos + collects <= inputs; pos++) {
+                    MethodHandle collector = BYTE_COLLECTORS[collects];
+                    byte[] args = new byte[inputs];
+                    int ap = 0, arg = 31;
+                    for (int i = 0; i < pos; i++)
+                        args[ap++] = (byte)(arg++ + 0);
+                    for (int i = 0; i < collects; i++)
+                        args[ap++] = (byte)(arg++ + 10);
+                    while (ap < args.length)
+                        args[ap++] = (byte)(arg++ + 20);
+                    // calculate piecemeal:
+                    //System.out.println("testIntCollects "+Arrays.asList(lister, pos, collector)+" on "+Arrays.toString(args));
+                    byte[] collargs = Arrays.copyOfRange(args, pos, pos+collects);
+                    byte coll = (byte) collector.asSpreader(byte[].class, collargs.length).invokeExact(collargs);
+                    byte[] listargs = Arrays.copyOfRange(args, 0, outputs);
+                    System.arraycopy(args, pos+collects, listargs, pos+1, outputs - (pos+1));
+                    listargs[pos] = coll;
+                    //System.out.println("  coll="+coll+" listargs="+Arrays.toString(listargs));
+                    Object expect = lister.asSpreader(byte[].class, listargs.length).invokeExact(listargs);
+                    //System.out.println("  expect="+expect);
+
+                    // now use the combined MH, and test the output:
+                    MethodHandle mh = collectArguments(lister, pos, byte[].class, BYTE_COLLECTORS[collects]);
+                    if (mh == null)  continue;  // no infix collection, yet
+                    assert(mh.type().parameterCount() == inputs);
+                    Object observe = mh.asSpreader(byte[].class, args.length).invokeExact(args);
+                    assertEquals(expect, observe);
+                }
+            }
+        }
+    }
+
+    private static MethodHandle collectArguments(MethodHandle lister, int pos, Class<?> array, MethodHandle collector) {
+        int collects = collector.type().parameterCount();
+        int outputs = lister.type().parameterCount();
+        if (pos == outputs - 1)
+            return MethodHandles.filterArguments(lister, pos,
+                        collector.asSpreader(array, collects))
+                            .asCollector(array, collects);
+        //return MethodHandles.collectArguments(lister, pos, collector); //no such animal
+        return null;
+    }
+
+    private static final Class<?>[] RETURN_TYPES = {
+        Object.class, String.class, Integer.class,
+        int.class, long.class,
+        boolean.class, byte.class, char.class, short.class,
+        float.class, double.class,
+        void.class,
+    };
+
+    @Test
+    public void testReturns() throws Throwable {
+        if (!startTest("testReturns"))  return;
+        // fault injection:
+        int faultCount = 0;  // total of 1296 tests
+        faultCount = Integer.getInteger("testReturns.faultCount", 0);
+        for (Class<?> ret : RETURN_TYPES) {
+            // make a complicated identity function and pass something through it
+            System.out.println(ret.getSimpleName());
+            Class<?> vret = (ret == void.class) ? Void.class : ret;
+            MethodHandle id = // (vret)->ret
+                identity(vret).asType(methodType(ret, vret));
+            final int LENGTH = 4;
+            int[] index = {0};
+            Object vals = java.lang.reflect.Array.newInstance(vret, LENGTH);
+            MethodHandle indexGetter =  //()->int
+                insertArguments(arrayElementGetter(index.getClass()), 0, index, 0);
+            MethodHandle valSelector =  // (int)->vret
+                arrayElementGetter(vals.getClass()).bindTo(vals);
+            MethodHandle valGetter =  // ()->vret
+                foldArguments(valSelector, indexGetter);
+            if (ret != void.class) {
+                for (int i = 0; i < LENGTH; i++) {
+                    Object val = (i + 50);
+                    if (ret == boolean.class)  val = (i % 3 == 0);
+                    if (ret == String.class)   val = "#"+i;
+                    if (ret == char.class)     val = (char)('a'+i);
+                    if (ret == byte.class)     val = (byte)~i;
+                    if (ret == short.class)    val = (short)(1<<i);
+                    java.lang.reflect.Array.set(vals, i, val);
+                }
+            }
+            for (int i = 0; i < LENGTH; i++) {
+                Object val = java.lang.reflect.Array.get(vals, i);
+                System.out.println(i+" => "+val);
+                index[0] = i;
+                if (--faultCount == 0)  index[0] ^= 1;
+                Object x = valGetter.invokeWithArguments();
+                assertEquals(val, x);
+                // make a return-filter call:  x = id(valGetter())
+                if (--faultCount == 0)  index[0] ^= 1;
+                x = filterReturnValue(valGetter, id).invokeWithArguments();
+                assertEquals(val, x);
+                // make a filter call:  x = id(*,valGetter(),*)
+                for (int len = 1; len <= 4; len++) {
+                    for (int pos = 0; pos < len; pos++) {
+                        MethodHandle proj = id;  // lambda(..., vret x,...){x}
+                        for (int j = 0; j < len; j++) {
+                            if (j == pos)  continue;
+                            proj = dropArguments(proj, j, Object.class);
+                        }
+                        assert(proj.type().parameterCount() == len);
+                        // proj: (Object*, pos: vret, Object*)->ret
+                        assertEquals(vret, proj.type().parameterType(pos));
+                        MethodHandle vgFilter = dropArguments(valGetter, 0, Object.class);
+                        if (--faultCount == 0)  index[0] ^= 1;
+                        x = filterArguments(proj, pos, vgFilter).invokeWithArguments(new Object[len]);
+                        assertEquals(val, x);
+                    }
+                }
+                // make a fold call:
+                for (int len = 0; len <= 4; len++) {
+                    for (int fold = 0; fold <= len; fold++) {
+                        MethodHandle proj = id;  // lambda(ret x, ...){x}
+                        if (ret == void.class)  proj = constant(Object.class, null);
+                        int arg0 = (ret == void.class ? 0 : 1);
+                        for (int j = 0; j < len; j++) {
+                            proj = dropArguments(proj, arg0, Object.class);
+                        }
+                        assert(proj.type().parameterCount() == arg0 + len);
+                        // proj: (Object*, pos: vret, Object*)->ret
+                        if (arg0 != 0)  assertEquals(vret, proj.type().parameterType(0));
+                        MethodHandle vgFilter = valGetter.asType(methodType(ret));
+                        for (int j = 0; j < fold; j++) {
+                            vgFilter = dropArguments(vgFilter, j, Object.class);
+                        }
+                        x = foldArguments(proj, vgFilter).invokeWithArguments(new Object[len]);
+                        if (--faultCount == 0)  index[0] ^= 1;
+                        assertEquals(val, x);
+                    }
+                }
+            }
+        }
+        //System.out.println("faultCount="+faultCount);
+    }
+
+    @Test
+    public void testRecursion() throws Throwable {
+        if (!startTest("testRecursion"))  return;
+        final int LIMIT = 10;
+        for (int i = 0; i < LIMIT; i++) {
+            RFCB rfcb = new RFCB(i);
+            Object x = "x", y = "y";
+            Object result = rfcb.recursiveFunction(x, y);
+            verbose(1, result);
+        }
+    }
+    /** Recursive Function Control Block */
+    private static class RFCB {
+        java.util.Random random;
+        final MethodHandle[] fns;
+        int depth;
+        @SuppressWarnings("LeakingThisInConstructor")
+        RFCB(int seed) throws Throwable {
+            this.random = new java.util.Random(seed);
+            this.fns = new MethodHandle[Math.max(29, (1 << MAX_DEPTH-2)/3)];
+            java.util.Arrays.fill(fns, lookup().bind(this, "recursiveFunction", genericMethodType(2)));
+            for (int i = 5; i < fns.length; i++) {
+                switch (i % 4) {
+                case 0: fns[i] = filterArguments(fns[i - 5], 0, insertArguments(fns[i - 4], 1, ".")); break;
+                case 1: fns[i] = filterArguments(fns[i - 5], 1, insertArguments(fns[i - 3], 1, ".")); break;
+                case 2: fns[i] = filterReturnValue(fns[i - 5], insertArguments(fns[i - 2], 1, ".")); break;
+                }
+            }
+        }
+        Object recursiveFunction(Object x, Object y) throws Throwable {
+            depth++;
+            try {
+                final int ACTION_COUNT = 11;
+                switch (random.nextInt(ACTION_COUNT)) {
+                case 1:
+                    Throwable ex = new RuntimeException();
+                    ex.fillInStackTrace();
+                    if (VERBOSITY >= 2) ex.printStackTrace(System.out);
+                    x = "ST; " + x;
+                    break;
+                case 2:
+                    System.gc();
+                    x = "GC; " + x;
+                    break;
+                }
+                boolean isLeaf = (depth >= MAX_DEPTH);
+                if (isLeaf) {
+                    return Arrays.asList(x, y).toString();
+                }
+                return fns[random.nextInt(fns.length)].invokeExact(x, y);
+            } finally {
+                depth--;
+            }
+        }
+    }
+
+    private static MethodHandle sequence(MethodHandle mh1, MethodHandle... mhs) {
+        MethodHandle res = mh1;
+        for (MethodHandle mh2 : mhs)
+            res = filterReturnValue(res, mh2);
+        return res;
+    }
+    private static void assertEqualFunction(MethodHandle x, MethodHandle y) throws Throwable {
+        assertEquals(x.type(), y.type()); //??
+        MethodType t = x.type();
+        if (t.parameterCount() == 0) {
+            assertEqualFunctionAt(null, x, y);
+            return;
+        }
+        Class<?> ptype = t.parameterType(0);
+        if (ptype == long.class || ptype == Long.class) {
+            for (long i = -10; i <= 10; i++) {
+                assertEqualFunctionAt(i, x, y);
+            }
+        } else {
+            for (int i = -10; i <= 10; i++) {
+                assertEqualFunctionAt(i, x, y);
+            }
+        }
+    }
+    private static void assertEqualFunctionAt(Object v, MethodHandle x, MethodHandle y) throws Throwable {
+        Object[] args = new Object[x.type().parameterCount()];
+        Arrays.fill(args, v);
+        Object xval = invokeWithCatch(x, args);
+        Object yval = invokeWithCatch(y, args);
+        String msg = "ok";
+        if (!Objects.equals(xval, yval)) {
+            msg = ("applying "+x+" & "+y+" to "+v);
+        }
+        assertEquals(msg, xval, yval);
+    }
+    private static Object invokeWithCatch(MethodHandle mh, Object... args) throws Throwable {
+        try {
+            return mh.invokeWithArguments(args);
+        } catch (Throwable ex) {
+            System.out.println("threw: "+mh+Arrays.asList(args));
+            ex.printStackTrace(System.out);
+            return ex;
+        }
+    }
+
+    private static final Lookup LOOKUP = lookup();
+    private static MethodHandle findStatic(String name,
+                                           Class<?> rtype,
+                                           Class<?>... ptypes) {
+        try {
+            return LOOKUP.findStatic(LOOKUP.lookupClass(), name, methodType(rtype, ptypes));
+        } catch (ReflectiveOperationException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+    private static MethodHandle findStatic(String name,
+                                           Class<?> rtype,
+                                           List<?> ptypes) {
+        return findStatic(name, rtype, ptypes.toArray(new Class<?>[ptypes.size()]));
+    }
+    static int getProperty(String name, int dflt) {
+        String qual = LOOKUP.lookupClass().getName();
+        String prop = System.getProperty(qual+"."+name);
+        if (prop == null)  prop = System.getProperty(name);
+        if (prop == null)  return dflt;
+        return Integer.parseInt(prop);
+    }
+
+    private static int opI(int... xs) {
+        stress();
+        int base = 100;
+        int z = 0;
+        for (int x : xs) {
+            z = (z * base) + (x % base);
+        }
+        verbose("opI", xs.length, xs, z);
+        return z;
+    }
+    private static int opI2(int x, int y) { return opI(x, y); }  // x*100 + y%100
+    private static int opI3(int x, int y, int z) { return opI(x, y, z); }
+    private static int opI4(int w, int x, int y, int z) { return opI(w, x, y, z); }
+    private static int opI(int x) { return opI2(x, 37); }
+    private static Object opI_L(int x) { return (Object) opI(x); }
+    private static long opJ3(long x, long y, long z) { return (long) opI3((int)x, (int)y, (int)z); }
+    private static long opJ2(long x, long y) { return (long) opI2((int)x, (int)y); }
+    private static long opJ(long x) { return (long) opI((int)x); }
+    private static Object opL2(Object x, Object y) { return (Object) opI2((int)x, (int)y); }
+    private static Object opL(Object x) { return (Object) opI((int)x); }
+    private static int opL2_I(Object x, Object y) { return opI2((int)x, (int)y); }
+    private static int opL_I(Object x) { return opI((int)x); }
+    private static long opL_J(Object x) { return (long) opI((int)x); }
+    private static final MethodHandle opI, opI2, opI3, opI4, opI_L, opJ, opJ2, opJ3, opL2, opL, opL2_I, opL_I, opL_J;
+    static {
+        opI4 = findStatic("opI4", int.class, int.class, int.class, int.class, int.class);
+        opI3 = findStatic("opI3", int.class, int.class, int.class, int.class);
+        opI2 = findStatic("opI2", int.class, int.class, int.class);
+        opI = findStatic("opI", int.class, int.class);
+        opI_L = findStatic("opI_L", Object.class, int.class);
+        opJ = findStatic("opJ", long.class, long.class);
+        opJ2 = findStatic("opJ2", long.class, long.class, long.class);
+        opJ3 = findStatic("opJ3", long.class, long.class, long.class, long.class);
+        opL2 = findStatic("opL2", Object.class, Object.class, Object.class);
+        opL = findStatic("opL", Object.class, Object.class);
+        opL2_I = findStatic("opL2_I", int.class, Object.class, Object.class);
+        opL_I = findStatic("opL_I", int.class, Object.class);
+        opL_J = findStatic("opL_J", long.class, Object.class);
+    }
+    private static final MethodHandle[] INT_COLLECTORS = {
+        constant(int.class, 42), opI, opI2, opI3, opI4
+    };
+    private static final MethodHandle[] BYTE_COLLECTORS = {
+        constant(byte.class, (byte)42), i2b(opI), i2b(opI2), i2b(opI3), i2b(opI4)
+    };
+    private static final MethodHandle[] LONG_COLLECTORS = {
+        constant(long.class, 42), opJ, opJ2, opJ3
+    };
+
+    private static int addI(int x, int y) { stress(); return x+y; }
+    private static Object addL(Object x, Object y) { return addI((int)x, (int)y); }
+    private static final MethodHandle addI, addL;
+    static {
+        addI = findStatic("addI", int.class, int.class, int.class);
+        addL = findStatic("addL", Object.class, Object.class, Object.class);
+    }
+
+    private static Object list8ints(int a, int b, int c, int d, int e, int f, int g, int h) {
+        return Arrays.asList(a, b, c, d, e, f, g, h);
+    }
+    private static Object list8longs(long a, long b, long c, long d, long e, long f, long g, long h) {
+        return Arrays.asList(a, b, c, d, e, f, g, h);
+    }
+    private static final MethodHandle list8ints = findStatic("list8ints", Object.class,
+                                                             Collections.nCopies(8, int.class));
+    private static final MethodHandle list8longs = findStatic("list8longs", Object.class,
+                                                              Collections.nCopies(8, long.class));
+    private static final MethodHandle[] INT_LISTERS, LONG_LISTERS, BYTE_LISTERS;
+    static {
+        int listerCount = list8ints.type().parameterCount() + 1;
+        INT_LISTERS  = new MethodHandle[listerCount];
+        LONG_LISTERS = new MethodHandle[listerCount];
+        BYTE_LISTERS = new MethodHandle[listerCount];
+        MethodHandle lister = list8ints;
+        MethodHandle llister = list8longs;
+        for (int i = listerCount - 1; ; i--) {
+            INT_LISTERS[i] = lister;
+            LONG_LISTERS[i] = llister;
+            BYTE_LISTERS[i] = i2b(lister);
+            if (i == 0)  break;
+            lister  = insertArguments(lister,  i-1, 0);
+            llister = insertArguments(llister, i-1, 0L);
+        }
+    }
+    private static MethodHandle i2b(MethodHandle mh) {
+        return MethodHandles.explicitCastArguments(mh, subst(mh.type(), int.class, byte.class));
+    }
+    private static MethodType subst(MethodType mt, Class<?> from, Class<?> to) {
+        for (int i = 0; i < mt.parameterCount(); i++) {
+            if (mt.parameterType(i) == from)
+                mt = mt.changeParameterType(i, to);
+        }
+        if (mt.returnType() == from)
+            mt = mt.changeReturnType(to);
+        return mt;
+    }
+
+
+    private static Object  convI_L(int     x) { stress(); return (Object)  x; }
+    private static int     convL_I(Object  x) { stress(); return (int)     x; }
+    private static Object  convJ_L(long    x) { stress(); return (Object)  x; }
+    private static long    convL_J(Object  x) { stress(); return (long)    x; }
+    private static int     convJ_I(long    x) { stress(); return (int)     x; }
+    private static long    convI_J(int     x) { stress(); return (long)    x; }
+    private static final MethodHandle convI_L, convL_I, convJ_L, convL_J, convJ_I, convI_J;
+    static {
+        convI_L = findStatic("convI_L", Object.class, int.class);
+        convL_I = findStatic("convL_I", int.class, Object.class);
+        convJ_L = findStatic("convJ_L", Object.class, long.class);
+        convL_J = findStatic("convL_J", long.class, Object.class);
+        convJ_I = findStatic("convJ_I", int.class, long.class);
+        convI_J = findStatic("convI_J", long.class, int.class);
+    }
+
+    // stress modes:
+    private static final int MAX_DEPTH = getProperty("MAX_DEPTH", 5);
+    private static final int REPEAT = getProperty("REPEAT", 0);
+    private static final int STRESS = getProperty("STRESS", 0);
+    private static /*v*/ int STRESS_COUNT;
+    private static final Object[] SINK = new Object[4];
+    private static void stress() {
+        if (STRESS <= 0) return;
+        int count = STRESS + (STRESS_COUNT++ & 0x1);  // non-constant value
+        for (int i = 0; i < count; i++) {
+            SINK[i % SINK.length] = new Object[STRESS + i % (SINK.length + 1)];
+        }
+    }
+
+    // verbosity:
+    private static final int VERBOSITY = getProperty("VERBOSITY", 0) + (REPEAT == 0 ? 0 : -1);
+    private static void verbose(Object a, Object b, Object c, Object d) {
+        if (VERBOSITY <= 0)  return;
+        verbose(1, a, b, c, d);
+    }
+    private static void verbose(Object a, Object b, Object c) {
+        if (VERBOSITY <= 0)  return;
+        verbose(1, a, b, c);
+    }
+    private static void verbose(int level, Object a, Object... bcd) {
+        if (level > VERBOSITY)  return;
+        String m = a.toString();
+        if (bcd != null && bcd.length > 0) {
+            List<Object> l = new ArrayList<>(bcd.length);
+            for (Object x : bcd) {
+                if (x instanceof Object[])  x = Arrays.asList((Object[])x);
+                if (x instanceof int[])     x = Arrays.toString((int[])x);
+                if (x instanceof long[])    x = Arrays.toString((long[])x);
+                l.add(x);
+            }
+            m = m+Arrays.asList(bcd);
+        }
+        System.out.println(m);
+    }
+    String testOnly;
+    String testOnlyTests;
+    private boolean startTest(String name) {
+        if (testOnly != null && !testOnly.contains(name))
+            return false;
+        verbose(0, "["+name+"]");
+        testOnlyTests = (testOnlyTests == null) ? name : testOnlyTests+" "+name;
+        return true;
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/SpreadCollectTest.java b/ojluni/src/test/java/lang/invoke/SpreadCollectTest.java
new file mode 100644
index 0000000..78332d6
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/SpreadCollectTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885
+ * @bug 8143798
+ * @run testng/othervm -ea -esa test.java.lang.invoke.SpreadCollectTest
+ */
+
+package test.java.lang.invoke;
+
+import java.io.StringWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.*;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the new asSpreader/asCollector API added in JEP 274.
+ */
+public class SpreadCollectTest {
+
+    static final Lookup LOOKUP = MethodHandles.lookup();
+
+    @Test
+    public static void testAsSpreader() throws Throwable {
+        MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3);
+        assertEquals(SpreadCollect.MT_spreader, spreader.type());
+        assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B"));
+    }
+
+    @Test
+    public static void testAsSpreaderExample() throws Throwable {
+        // test the JavaDoc asSpreader-with-pos example
+        MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class));
+        MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2);
+        Object[] ints = new Object[]{3, 9, 7, 7};
+        Comparator<Integer> cmp = (a, b) -> a - b;
+        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0);
+        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0);
+        assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0);
+    }
+
+    @DataProvider
+    static Object[][] asSpreaderIllegalPositions() {
+        return new Object[][]{{-7}, {3}, {19}};
+    }
+
+    @Test(dataProvider = "asSpreaderIllegalPositions")
+    public static void testAsSpreaderIllegalPos(int p) throws Throwable {
+        boolean caught = false;
+        try {
+            SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3);
+        } catch (IllegalArgumentException iae) {
+            assertEquals("bad spread position", iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test(expectedExceptions = {WrongMethodTypeException.class})
+    public static void testAsSpreaderIllegalMethodType() {
+        MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class);
+        MethodHandle s = h.asSpreader(String[].class, 1);
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testAsSpreaderNullArrayType() {
+        SpreadCollect.MH_forSpreading.asSpreader(null, 0);
+    }
+
+    @Test(expectedExceptions = {NullPointerException.class})
+    public static void testAsSpreaderNullArrayNonZeroLength() {
+        SpreadCollect.MH_forSpreading.asSpreader(null, 1);
+    }
+
+    @Test(expectedExceptions = {IllegalArgumentException.class})
+    public static void testAsSpreaderTooManyParams() throws Throwable {
+        SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 6);
+    }
+
+    @Test
+    public static void testAsCollector() throws Throwable {
+        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
+        assertEquals(SpreadCollect.MT_collector1, collector.type());
+        assertEquals("A4B", (String) collector.invoke("A", 4, "B"));
+        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
+        assertEquals(SpreadCollect.MT_collector2, collector.type());
+        assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B"));
+        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
+        assertEquals(SpreadCollect.MT_collector3, collector.type());
+        assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B"));
+    }
+
+    @Test
+    public static void testAsCollectorInvokeWithArguments() throws Throwable {
+        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1);
+        assertEquals(SpreadCollect.MT_collector1, collector.type());
+        assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B"));
+        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2);
+        assertEquals(SpreadCollect.MT_collector2, collector.type());
+        assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B"));
+        collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3);
+        assertEquals(SpreadCollect.MT_collector3, collector.type());
+        assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B"));
+    }
+
+    @Test
+    public static void testAsCollectorLeading() throws Throwable {
+        MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
+        assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
+        assertEquals("7Q", (String) collector.invoke(7, "Q"));
+        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
+        assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
+        assertEquals("78Q", (String) collector.invoke(7, 8, "Q"));
+        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
+        assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
+        assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q"));
+    }
+
+    @Test
+    public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable {
+        MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1);
+        assertEquals(SpreadCollect.MT_collectorLeading1, collector.type());
+        assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q"));
+        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2);
+        assertEquals(SpreadCollect.MT_collectorLeading2, collector.type());
+        assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q"));
+        collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3);
+        assertEquals(SpreadCollect.MT_collectorLeading3, collector.type());
+        assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q"));
+    }
+
+    @Test
+    public static void testAsCollectorNone() throws Throwable {
+        MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0);
+        assertEquals(SpreadCollect.MT_collector0, collector.type());
+        assertEquals("AB", (String) collector.invoke("A", "B"));
+    }
+
+    @DataProvider
+    static Object[][] asCollectorIllegalPositions() {
+        return new Object[][]{{-1}, {17}};
+    }
+
+    @Test(dataProvider = "asCollectorIllegalPositions")
+    public static void testAsCollectorIllegalPos(int p) {
+        boolean caught = false;
+        try {
+            SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0);
+        } catch (IllegalArgumentException iae) {
+            assertEquals("bad collect position", iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public static void testAsCollectorExample() throws Throwable {
+        // test the JavaDoc asCollector-with-pos example
+        StringWriter swr = new StringWriter();
+        MethodHandle swWrite = LOOKUP.
+                findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)).
+                bindTo(swr);
+        MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4);
+        swWrite4.invoke('A', 'B', 'C', 'D', 1, 2);
+        assertEquals("BC", swr.toString());
+        swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4);
+        assertEquals("BCPQRS", swr.toString());
+        swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
+        assertEquals("BCPQRSZ", swr.toString());
+    }
+
+    static class SpreadCollect {
+
+        static String forSpreading(String s1, int i1, int i2, int i3, String s2) {
+            return s1 + i1 + i2 + i3 + s2;
+        }
+
+        static String forCollecting(String s1, int[] is, String s2) {
+            StringBuilder sb = new StringBuilder(s1);
+            for (int i : is) {
+                sb.append(i);
+            }
+            return sb.append(s2).toString();
+        }
+
+        static String forCollectingLeading(int[] is, String s) {
+            return forCollecting("", is, s);
+        }
+
+        static final Class<SpreadCollect> SPREAD_COLLECT = SpreadCollect.class;
+
+        static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
+        static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class);
+        static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class);
+
+        static final MethodHandle MH_forSpreading;
+        static final MethodHandle MH_forCollecting;
+        static final MethodHandle MH_forCollectingLeading;
+
+        static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class);
+        static final MethodType MT_collector0 = methodType(String.class, String.class, String.class);
+        static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class);
+        static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class);
+        static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class);
+        static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class);
+        static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class);
+        static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class);
+
+        static final String NONE_ERROR = "zero array length in MethodHandle.asCollector";
+
+        static {
+            try {
+                MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading);
+                MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting);
+                MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/TryFinallyTest.java b/ojluni/src/test/java/lang/invoke/TryFinallyTest.java
new file mode 100644
index 0000000..9749b14
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/TryFinallyTest.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8139885 8150824 8150825 8194238 8233920
+ * @run testng/othervm -ea -esa -Xverify:all test.java.lang.invoke.TryFinallyTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+/**
+ * Tests for the tryFinally method handle combinator introduced in JEP 274.
+ */
+public class TryFinallyTest {
+
+    static final Lookup LOOKUP = MethodHandles.lookup();
+
+    @Test
+    public static void testTryFinally() throws Throwable {
+        MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim);
+        assertEquals(TryFinally.MT_hello, hello.type());
+        assertEquals("Hello, world!", hello.invoke("world"));
+    }
+
+    @DataProvider
+    static Object[][] tryFinallyArgs() {
+        return new Object[][] {
+                { boolean.class, true },
+                { byte.class, (byte) 2 },
+                { short.class, (short) 2 },
+                { char.class, (char) 2 },
+                { int.class, 2 },
+                { long.class, 2L },
+                { float.class, 2f },
+                { double.class, 2D },
+                { Object.class, new Object() }
+        };
+    }
+
+    @Test(dataProvider = "tryFinallyArgs")
+    public static void testTryFinally(Class<?> argType, Object arg) throws Throwable {
+        MethodHandle identity = MethodHandles.identity(argType);
+        MethodHandle tryFinally = MethodHandles.tryFinally(
+                identity,
+                MethodHandles.dropArguments(identity, 0, Throwable.class));
+        assertEquals(methodType(argType, argType), tryFinally.type());
+        assertEquals(arg, tryFinally.invoke(arg));
+    }
+
+    @Test(dataProvider = "tryFinallyArgs", expectedExceptions = TryFinally.T1.class)
+    public static void testTryFinallyException(Class<?> argType, Object arg) throws Throwable {
+        MethodHandle identity = TryFinally.MH_throwingTargetIdentity.asType(methodType(argType, argType));
+        MethodHandle tryFinally = MethodHandles.tryFinally(
+                identity,
+                MethodHandles.dropArguments(identity, 0, TryFinally.T1.class));
+        assertEquals(methodType(argType, argType), tryFinally.type());
+        tryFinally.invoke(arg); // should throw
+    }
+
+    @Test
+    public static void testTryFinallyVoid() throws Throwable {
+        MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore);
+        assertEquals(TryFinally.MT_printHello, tfVoid.type());
+        tfVoid.invoke("world");
+    }
+
+    @Test
+    public static void testTryFinallySublist() throws Throwable {
+        MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore);
+        assertEquals(TryFinally.MT_moreHello, helloMore.type());
+        assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe"));
+    }
+
+    @DataProvider
+    static Object[][] omitTrailingArguments() {
+        MethodHandle c = TryFinally.MH_voidCleanup;
+        return new Object[][]{
+                {c},
+                {MethodHandles.dropArguments(c, 1, int.class)},
+                {MethodHandles.dropArguments(c, 1, int.class, long.class)},
+                {MethodHandles.dropArguments(c, 1, int.class, long.class, Object.class, int.class)},
+                {MethodHandles.dropArguments(c, 1, int.class, long.class, Object.class, int.class, long.class)}
+        };
+    }
+
+    @Test(dataProvider = "omitTrailingArguments")
+    public static void testTryFinallyOmitTrailingArguments(MethodHandle cleanup) throws Throwable {
+        MethodHandle tf = MethodHandles.tryFinally(TryFinally.MH_dummyTarget, cleanup);
+        tf.invoke(1, 2L, "a", 23, 42L, "b");
+    }
+
+    @DataProvider
+    static Object[][] negativeTestData() {
+        MethodHandle intid = MethodHandles.identity(int.class);
+        MethodHandle intco = MethodHandles.constant(int.class, 0);
+        MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class);
+        MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class,
+                int.class, double.class, Object.class);
+        MethodHandle voidTarget = TryFinally.MH_voidTarget;
+        MethodHandle voidICleanup = MethodHandles.dropArguments(TryFinally.MH_voidCleanup, 1, int.class);
+        return new Object[][]{
+                {intid, MethodHandles.identity(double.class),
+                        "target and return types must match: double != int"},
+                {intid, MethodHandles.dropArguments(intid, 0, String.class),
+                        "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable"},
+                {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class),
+                        "cleanup second argument and target return type must match: (Throwable,double,int)int != int"},
+                {errTarget, errCleanup,
+                        "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+                                errCleanup.type() + " != " + errTarget.type()},
+                {voidTarget, voidICleanup,
+                        "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " +
+                                voidICleanup.type() + " != " + voidTarget.type()}
+        };
+    }
+
+    @Test(dataProvider = "negativeTestData")
+    public static void testTryFinallyNegative(MethodHandle target, MethodHandle cleanup, String expectedMessage) {
+        boolean caught = false;
+        try {
+            MethodHandles.tryFinally(target, cleanup);
+        } catch (IllegalArgumentException iae) {
+            assertEquals(expectedMessage, iae.getMessage());
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public static void testTryFinallyThrowableCheck() {
+        MethodHandle mh = MethodHandles.tryFinally(TryFinally.MH_throwingTarget,
+                                                   TryFinally.MH_catchingCleanup);
+        try {
+            mh.invoke();
+            fail("ClassCastException expected");
+        } catch (Throwable t) {
+            assertTrue("Throwable not assignable to ClassCastException: " + t,
+                       ClassCastException.class.isAssignableFrom(t.getClass()));
+        }
+    }
+
+    static class TryFinally {
+
+        static String greet(String whom) {
+            return "Hello, " + whom;
+        }
+
+        static String exclaim(Throwable t, String r, String whom) {
+            return r + "!";
+        }
+
+        static void print(String what) {
+            System.out.print("Hello, " + what);
+        }
+
+        static void printMore(Throwable t, String what) {
+            System.out.println("!");
+        }
+
+        static String greetMore(String first, String second) {
+            return "Hello, " + first + " and " + second;
+        }
+
+        static String exclaimMore(Throwable t, String r, String first) {
+            return r + " (but " + first + " first)!";
+        }
+
+        static void voidTarget() {}
+
+        static void voidCleanup(Throwable t) {}
+
+        static class T1 extends Throwable {}
+
+        static class T2 extends Throwable {}
+
+        static void throwingTarget() throws Throwable {
+            throw new T1();
+        }
+
+        static Object throwingTargetIdentity(Object o) throws Throwable {
+            throw new T1();
+        }
+
+        static void catchingCleanup(T2 t) throws Throwable {
+        }
+
+        static final Class<TryFinally> TRY_FINALLY = TryFinally.class;
+
+        static final MethodType MT_greet = methodType(String.class, String.class);
+        static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class);
+        static final MethodType MT_print = methodType(void.class, String.class);
+        static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class);
+        static final MethodType MT_greetMore = methodType(String.class, String.class, String.class);
+        static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class);
+        static final MethodType MT_voidTarget = methodType(void.class);
+        static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class);
+        static final MethodType MT_throwingTarget = methodType(void.class);
+        static final MethodType MT_throwingTargetIdentity = methodType(Object.class, Object.class);
+        static final MethodType MT_catchingCleanup = methodType(void.class, T2.class);
+
+        static final MethodHandle MH_greet;
+        static final MethodHandle MH_exclaim;
+        static final MethodHandle MH_print;
+        static final MethodHandle MH_printMore;
+        static final MethodHandle MH_greetMore;
+        static final MethodHandle MH_exclaimMore;
+        static final MethodHandle MH_voidTarget;
+        static final MethodHandle MH_voidCleanup;
+        static final MethodHandle MH_throwingTarget;
+        static final MethodHandle MH_throwingTargetIdentity;
+        static final MethodHandle MH_catchingCleanup;
+
+        static final MethodHandle MH_dummyTarget;
+
+        static final MethodType MT_hello = methodType(String.class, String.class);
+        static final MethodType MT_printHello = methodType(void.class, String.class);
+        static final MethodType MT_moreHello = methodType(String.class, String.class, String.class);
+
+        static {
+            try {
+                MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet);
+                MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim);
+                MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print);
+                MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore);
+                MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore);
+                MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore);
+                MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget);
+                MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup);
+                MH_throwingTarget = LOOKUP.findStatic(TRY_FINALLY, "throwingTarget", MT_throwingTarget);
+                MH_throwingTargetIdentity = LOOKUP.findStatic(TRY_FINALLY, "throwingTargetIdentity", MT_throwingTargetIdentity);
+                MH_catchingCleanup = LOOKUP.findStatic(TRY_FINALLY, "catchingCleanup", MT_catchingCleanup);
+                MH_dummyTarget = MethodHandles.dropArguments(MH_voidTarget, 0, int.class, long.class, Object.class,
+                        int.class, long.class, Object.class);
+            } catch (Exception e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarArgsTest.java b/ojluni/src/test/java/lang/invoke/VarArgsTest.java
new file mode 100644
index 0000000..2fef2cd
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarArgsTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @run testng/othervm -ea -esa test.java.lang.invoke.VarArgsTest
+ */
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.List;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.*;
+
+public class VarArgsTest {
+
+    @Test
+    public void testWithVarargs() throws Throwable {
+        MethodHandle deepToString = publicLookup()
+            .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
+        assertFalse(deepToString.isVarargsCollector());
+        MethodHandle ts = deepToString.withVarargs(false);
+        assertFalse(ts.isVarargsCollector());
+        MethodHandle ts1 = deepToString.withVarargs(true);
+        assertTrue(ts1.isVarargsCollector());
+        assertEquals("[won]", (String) ts1.invokeExact(new Object[]{"won"}));
+        assertEquals("[won]", (String) ts1.invoke(new Object[]{"won"}));
+        assertEquals("[won]", (String) ts1.invoke("won"));
+        assertEquals("[won, won]", (String) ts1.invoke("won", "won"));
+        assertEquals("[won, won]", (String) ts1.invoke(new Object[]{"won", "won"}));
+        assertEquals("[[won]]", (String) ts1.invoke((Object) new Object[]{"won"}));
+    }
+
+    @Test
+    public void testWithVarargs2() throws Throwable {
+        MethodHandle asList = publicLookup()
+            .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
+        MethodHandle asListWithVarargs = asList.withVarargs(asList.isVarargsCollector());
+        assert(asListWithVarargs.isVarargsCollector());
+        assertEquals("[]", asListWithVarargs.invoke().toString());
+        assertEquals("[1]", asListWithVarargs.invoke(1).toString());
+        assertEquals("[two, too]", asListWithVarargs.invoke("two", "too").toString());
+    }
+
+    @Test
+    @ExpectedExceptions(IllegalArgumentException.class)
+    public void testWithVarargsIAE() throws Throwable {
+        MethodHandle lenMH = publicLookup()
+            .findVirtual(String.class, "length", methodType(int.class));
+        MethodHandle lenMHWithVarargs = lenMH.withVarargs(true);
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
new file mode 100644
index 0000000..9679883
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.function.Function;
+
+public abstract class VarHandleBaseByteArrayTest extends VarHandleBaseTest {
+
+    enum MemoryMode {
+        ALIGNED(0, false), UNALIGNED(0, true),
+        BIG_ENDIAN(1, false), LITTLE_ENDIAN(1, true),
+        READ_WRITE(2, false), READ_ONLY(2, true),;
+
+        final int bit;
+        final int value;
+
+        MemoryMode(int bit, boolean value) {
+            this.bit = bit;
+            this.value = value ? 1 << bit : 0;
+        }
+
+        boolean isSet(int bitSet) {
+            return (bitSet & (1 << bit)) == value;
+        }
+
+        static int bitSet(MemoryMode... modes) {
+            if (modes == null) return 0;
+
+            int set = 0;
+            for (MemoryMode m : modes) {
+                set = (set & ~(1 << m.bit)) | m.value;
+            }
+            return set;
+        }
+
+        static EnumSet<MemoryMode> enumSet(int bitSet) {
+            EnumSet<MemoryMode> es = EnumSet.noneOf(MemoryMode.class);
+            for (MemoryMode m : values()) {
+                if (m.isSet(bitSet)) {
+                    es.add(m);
+                }
+            }
+            return es;
+        }
+    }
+
+    static class Source<T> {
+        final T s;
+        final int memoryModes;
+
+        public Source(T s, MemoryMode... modes) {
+            this.s = s;
+            memoryModes = MemoryMode.bitSet(modes);
+        }
+
+        @Override
+        public String toString() {
+            return s.getClass().getCanonicalName() + " " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static abstract class ByteArrayViewSource<T> extends Source<T> {
+        public ByteArrayViewSource(T t, MemoryMode... modes) {
+            super(t, modes);
+        }
+
+        abstract void fill(byte value);
+
+        abstract void fill(byte[] values);
+    }
+
+    static class ByteArraySource extends ByteArrayViewSource<byte[]> {
+        public ByteArraySource(byte[] bytes, MemoryMode... modes) {
+            super(bytes, modes);
+        }
+
+        void fill(byte value) {
+            Arrays.fill(s, value);
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < s.length; i++) {
+                s[i] = values[i % values.length];
+            }
+        }
+    }
+
+    static class ByteBufferSource extends ByteArrayViewSource<ByteBuffer> {
+        public ByteBufferSource(ByteBuffer buffer, MemoryMode... modes) {
+            super(buffer, modes);
+        }
+
+        void fill(byte value) {
+            for (int i = 0; i < s.limit(); i++) {
+                s.put(i, value);
+            }
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < s.limit(); i++) {
+                s.put(i, values[i % values.length]);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return s + " " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static class ByteBufferReadOnlySource extends ByteBufferSource {
+        final ByteBuffer rwSource;
+
+        public ByteBufferReadOnlySource(ByteBuffer roBuffer, ByteBuffer rwSource, MemoryMode... modes) {
+            super(roBuffer, modes);
+            this.rwSource = rwSource;
+        }
+
+        void fill(byte value) {
+            for (int i = 0; i < rwSource.limit(); i++) {
+                rwSource.put(i, value);
+            }
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < rwSource.limit(); i++) {
+                rwSource.put(i, values[i % values.length]);
+            }
+        }
+    }
+
+    static class VarHandleSource extends Source<VarHandle> {
+        VarHandleSource(VarHandle vh, MemoryMode... modes) {
+            super(vh, modes);
+        }
+
+        boolean matches(ByteArrayViewSource<?> bav) {
+            return s.coordinateTypes().get(0).isAssignableFrom(bav.s.getClass());
+        }
+
+        @Override
+        public String toString() {
+            return " VarHandle " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static class VarHandleSourceAccessTestCase extends AccessTestCase<VarHandleSource> {
+        final ByteArrayViewSource<?> bs;
+        final VarHandleSource vhs;
+
+        VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata) {
+            this(desc, bs, vhs, ata, true);
+        }
+
+        VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata, boolean loop) {
+            super(vhs + " -> " + bs + " " + desc, ata, loop);
+            this.bs = bs;
+            this.vhs = vhs;
+        }
+
+        @Override
+        VarHandleSource get() {
+            return vhs;
+        }
+    }
+
+
+    static double rotateLeft(double i, int distance) {
+        return Double.longBitsToDouble(
+                Long.rotateLeft(Double.doubleToRawLongBits(i), distance));
+    }
+
+    static double rotateRight(double i, int distance) {
+        return Double.longBitsToDouble(
+                Long.rotateRight(Double.doubleToRawLongBits(i), distance));
+    }
+
+    static float rotateLeft(float i, int distance) {
+        return Float.intBitsToFloat(
+                Integer.rotateLeft(Float.floatToRawIntBits(i), distance));
+    }
+
+    static float rotateRight(float i, int distance) {
+        return Float.intBitsToFloat(
+                Integer.rotateRight(Float.floatToRawIntBits(i), distance));
+    }
+
+    static long rotateLeft(long i, int distance) {
+        return Long.rotateLeft(i, distance);
+    }
+
+    static long rotateRight(long i, int distance) {
+        return Long.rotateRight(i, distance);
+    }
+
+    static int rotateLeft(int i, int distance) {
+        return Integer.rotateLeft(i, distance);
+    }
+
+    static int rotateRight(int i, int distance) {
+        return Integer.rotateRight(i, distance);
+    }
+
+    static short rotateLeft(short i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateLeft(v, distance);
+        return (short) v;
+    }
+
+    static short rotateRight(short i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateRight(v, distance);
+        return (short) v;
+    }
+
+    static char rotateLeft(char i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateLeft(v, distance);
+        return (char) v;
+    }
+
+    static char rotateRight(char i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateRight(v, distance);
+        return (char) v;
+    }
+
+    static final int LENGTH_BYTES = 32;
+
+    byte[] array;
+
+    List<ByteArrayViewSource<?>> bavss;
+
+    List<VarHandleSource> vhss;
+
+    public void setupByteSources() {
+        array = new byte[LENGTH_BYTES];
+
+        // Native endianess
+        MemoryMode ne = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN
+                        ? MemoryMode.BIG_ENDIAN : MemoryMode.LITTLE_ENDIAN;
+
+        bavss = new ArrayList<>();
+
+        // byte[] source
+        ByteArraySource a =
+                new ByteArraySource(array,
+                                    ne, MemoryMode.READ_WRITE);
+        bavss.add(a);
+
+
+        // Combinations of ByteBuffer sources
+        ByteBufferSource hbb =
+                new ByteBufferSource(ByteBuffer.wrap(array),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb);
+        ByteBufferReadOnlySource hbb_ro =
+                new ByteBufferReadOnlySource(hbb.s.asReadOnlyBuffer(), hbb.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_ro);
+
+        ByteBufferSource hbb_offset_aligned =
+                new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4, array.length / 2).slice(),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb_offset_aligned);
+        ByteBufferReadOnlySource hbb_offset_aligned_ro =
+                new ByteBufferReadOnlySource(hbb_offset_aligned.s.asReadOnlyBuffer(), hbb_offset_aligned.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_offset_aligned_ro);
+
+        ByteBufferSource hbb_offset_unaligned =
+                new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4 - 1, array.length / 2).slice(),
+                                     MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb_offset_unaligned);
+        ByteBufferReadOnlySource hbb_offset_unaligned_ro =
+                new ByteBufferReadOnlySource(hbb_offset_unaligned.s.asReadOnlyBuffer(), hbb_offset_unaligned.s,
+                                             MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_offset_unaligned_ro);
+
+
+        ByteBufferSource dbb =
+                new ByteBufferSource(ByteBuffer.allocateDirect(array.length),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb);
+        ByteBufferReadOnlySource dbb_ro =
+                new ByteBufferReadOnlySource(dbb.s.asReadOnlyBuffer(), dbb.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_ro);
+
+        // Android-changed: Use ByteBuffer.slice() rather than Buffer.slice().
+        ByteBufferSource dbb_offset_aligned =
+                new ByteBufferSource(((ByteBuffer) dbb.s.slice().position(array.length / 4).limit(array.length / 4 + array.length / 2)).slice(),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb_offset_aligned);
+        ByteBufferReadOnlySource dbb_offset_aligned_ro =
+                new ByteBufferReadOnlySource(dbb_offset_aligned.s.asReadOnlyBuffer(), dbb_offset_aligned.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_offset_aligned_ro);
+
+        // Android-changed: Use ByteBuffer.slice() rather than Buffer.slice().
+        ByteBufferSource dbb_offset_unaligned =
+                new ByteBufferSource(((ByteBuffer) dbb.s.slice().position(array.length / 4 - 1).limit(array.length / 4 - 1 + array.length / 2)).slice(),
+                                     MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb_offset_unaligned);
+        ByteBufferReadOnlySource dbb_offset_unaligned_ro =
+                new ByteBufferReadOnlySource(dbb_offset_unaligned.s.asReadOnlyBuffer(), dbb_offset_unaligned.s,
+                                             MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_offset_unaligned_ro);
+    }
+
+    @BeforeClass
+    public void setup() {
+        setupByteSources();
+        setupVarHandleSources();
+    }
+
+    abstract void setupVarHandleSources();
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        return vhss.stream().map(cvh -> new Object[]{cvh}).toArray(Object[][]::new);
+    }
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<java.lang.Class<?>> aepts = Arrays.asList(byte[].class, int.class);
+        List<java.lang.Class<?>> bbpts = Arrays.asList(ByteBuffer.class, int.class);
+
+        Function<VarHandle, List<Class<?>>> vhToPts = vh ->
+                vh.coordinateTypes().get(0) == byte[].class ? aepts : bbpts;
+
+        return vhss.stream().map(vh -> new Object[]{vh.s, vhToPts.apply(vh.s)}).toArray(Object[][]::new);
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java
new file mode 100644
index 0000000..58fc63c
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.WrongMethodTypeException;
+import java.lang.reflect.Method;
+import java.nio.ReadOnlyBufferException;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static org.testng.Assert.*;
+
+abstract class VarHandleBaseTest {
+    static final int ITERS = Integer.getInteger("iters", 1);
+    static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 10);
+
+    interface ThrowingRunnable {
+        void run() throws Throwable;
+    }
+
+    static void checkUOE(ThrowingRunnable r) {
+        checkWithThrowable(UnsupportedOperationException.class, null, r);
+    }
+
+    static void checkUOE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(UnsupportedOperationException.class, message, r);
+    }
+
+    static void checkROBE(ThrowingRunnable r) {
+        checkWithThrowable(ReadOnlyBufferException.class, null, r);
+    }
+
+    static void checkROBE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(ReadOnlyBufferException.class, message, r);
+    }
+
+    static void checkIOOBE(ThrowingRunnable r) {
+        checkWithThrowable(IndexOutOfBoundsException.class, null, r);
+    }
+
+    static void checkIOOBE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IndexOutOfBoundsException.class, message, r);
+    }
+
+    static void checkASE(ThrowingRunnable r) {
+        checkWithThrowable(ArrayStoreException.class, null, r);
+    }
+
+    static void checkASE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(ArrayStoreException.class, message, r);
+    }
+
+    static void checkISE(ThrowingRunnable r) {
+        checkWithThrowable(IllegalStateException.class, null, r);
+    }
+
+    static void checkISE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IllegalStateException.class, message, r);
+    }
+
+    static void checkIAE(ThrowingRunnable r) {
+        checkWithThrowable(IllegalAccessException.class, null, r);
+    }
+
+    static void checkIAE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IllegalAccessException.class, message, r);
+    }
+
+    static void checkWMTE(ThrowingRunnable r) {
+        checkWithThrowable(WrongMethodTypeException.class, null, r);
+    }
+
+    static void checkWMTE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(WrongMethodTypeException.class, message, r);
+    }
+
+    static void checkCCE(ThrowingRunnable r) {
+        checkWithThrowable(ClassCastException.class, null, r);
+    }
+
+    static void checkCCE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(ClassCastException.class, message, r);
+    }
+
+    static void checkNPE(ThrowingRunnable r) {
+        checkWithThrowable(NullPointerException.class, null, r);
+    }
+
+    static void checkNPE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(NullPointerException.class, message, r);
+    }
+
+    static void checkWithThrowable(Class<? extends Throwable> re,
+                                   Object message,
+                                   ThrowingRunnable r) {
+        Throwable _e = null;
+        try {
+            r.run();
+        }
+        catch (Throwable e) {
+            _e = e;
+        }
+        message = message == null ? "" : message + ". ";
+        assertNotNull(_e, String.format("%sNo throwable thrown. Expected %s", message, re));
+        assertTrue(re.isInstance(_e), String.format("%sIncorrect throwable thrown, %s. Expected %s", message, _e, re));
+    }
+
+
+    enum TestAccessType {
+        GET,
+        SET,
+        COMPARE_AND_SET,
+        COMPARE_AND_EXCHANGE,
+        GET_AND_SET,
+        GET_AND_ADD,
+        GET_AND_BITWISE;
+    }
+
+    enum TestAccessMode {
+        GET(TestAccessType.GET),
+        SET(TestAccessType.SET),
+        GET_VOLATILE(TestAccessType.GET),
+        SET_VOLATILE(TestAccessType.SET),
+        GET_ACQUIRE(TestAccessType.GET),
+        SET_RELEASE(TestAccessType.SET),
+        GET_OPAQUE(TestAccessType.GET),
+        SET_OPAQUE(TestAccessType.SET),
+        COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
+        COMPARE_AND_EXCHANGE(TestAccessType.COMPARE_AND_EXCHANGE),
+        COMPARE_AND_EXCHANGE_ACQUIRE(TestAccessType.COMPARE_AND_EXCHANGE),
+        COMPARE_AND_EXCHANGE_RELEASE(TestAccessType.COMPARE_AND_EXCHANGE),
+        WEAK_COMPARE_AND_SET_PLAIN(TestAccessType.COMPARE_AND_SET),
+        WEAK_COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
+        WEAK_COMPARE_AND_SET_ACQUIRE(TestAccessType.COMPARE_AND_SET),
+        WEAK_COMPARE_AND_SET_RELEASE(TestAccessType.COMPARE_AND_SET),
+        GET_AND_SET(TestAccessType.GET_AND_SET),
+        GET_AND_SET_ACQUIRE(TestAccessType.GET_AND_SET),
+        GET_AND_SET_RELEASE(TestAccessType.GET_AND_SET),
+        GET_AND_ADD(TestAccessType.GET_AND_ADD),
+        GET_AND_ADD_ACQUIRE(TestAccessType.GET_AND_ADD),
+        GET_AND_ADD_RELEASE(TestAccessType.GET_AND_ADD),
+        GET_AND_BITWISE_OR(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_OR_ACQUIRE(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_OR_RELEASE(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_AND(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_AND_ACQUIRE(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_AND_RELEASE(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_XOR(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_XOR_ACQUIRE(TestAccessType.GET_AND_BITWISE),
+        GET_AND_BITWISE_XOR_RELEASE(TestAccessType.GET_AND_BITWISE),
+        ;
+
+        final TestAccessType at;
+        final boolean isPolyMorphicInReturnType;
+        final Class<?> returnType;
+
+        TestAccessMode(TestAccessType at) {
+            this.at = at;
+
+            try {
+                VarHandle.AccessMode vh_am = toAccessMode();
+                Method m = VarHandle.class.getMethod(vh_am.methodName(), Object[].class);
+                this.returnType = m.getReturnType();
+                isPolyMorphicInReturnType = returnType != Object.class;
+            }
+            catch (Exception e) {
+                throw new Error(e);
+            }
+        }
+
+        boolean isOfType(TestAccessType at) {
+            return this.at == at;
+        }
+
+        VarHandle.AccessMode toAccessMode() {
+            return VarHandle.AccessMode.valueOf(name());
+        }
+    }
+
+    static List<TestAccessMode> testAccessModes() {
+        return Stream.of(TestAccessMode.values()).collect(toList());
+    }
+
+    static List<TestAccessMode> testAccessModesOfType(TestAccessType... ats) {
+        Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
+        return s.filter(e -> Stream.of(ats).anyMatch(e::isOfType))
+                .collect(toList());
+    }
+
+    static List<VarHandle.AccessMode> accessModes() {
+        return Stream.of(VarHandle.AccessMode.values()).collect(toList());
+    }
+
+    static List<VarHandle.AccessMode> accessModesOfType(TestAccessType... ats) {
+        Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
+        return s.filter(e -> Stream.of(ats).anyMatch(e::isOfType))
+                .map(TestAccessMode::toAccessMode)
+                .collect(toList());
+    }
+
+    static MethodHandle toMethodHandle(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        return vh.toMethodHandle(tam.toAccessMode());
+    }
+
+    static MethodHandle findVirtual(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        MethodHandle mh;
+        try {
+            mh = MethodHandles.publicLookup().
+                    findVirtual(VarHandle.class,
+                                tam.toAccessMode().methodName(),
+                                mt);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return bind(vh, mh, mt);
+    }
+
+    static MethodHandle varHandleInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        MethodHandle mh = MethodHandles.varHandleInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, mh, mt);
+    }
+
+    static MethodHandle varHandleExactInvoker(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        MethodHandle mh = MethodHandles.varHandleExactInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, mh, mt);
+    }
+
+    private static MethodHandle bind(VarHandle vh, MethodHandle mh, MethodType emt) {
+        assertEquals(mh.type(), emt.insertParameterTypes(0, VarHandle.class),
+                     "MethodHandle type differs from access mode type");
+
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+        assertEquals(info.getMethodType(), emt,
+                     "MethodHandleInfo method type differs from access mode type");
+
+        return mh.bindTo(vh);
+    }
+
+    private interface TriFunction<T, U, V, R> {
+        R apply(T t, U u, V v);
+    }
+
+    enum VarHandleToMethodHandle {
+        VAR_HANDLE_TO_METHOD_HANDLE(
+                "VarHandle.toMethodHandle",
+                true,
+                VarHandleBaseTest::toMethodHandle),
+        METHOD_HANDLES_LOOKUP_FIND_VIRTUAL(
+                "Lookup.findVirtual",
+                false,
+                VarHandleBaseTest::findVirtual),
+        METHOD_HANDLES_VAR_HANDLE_INVOKER(
+                "MethodHandles.varHandleInvoker",
+                false,
+                VarHandleBaseTest::varHandleInvoker),
+        METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER(
+                "MethodHandles.varHandleExactInvoker",
+                true,
+                VarHandleBaseTest::varHandleExactInvoker);
+
+        final String desc;
+        final boolean isExact;
+        final TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f;
+
+        VarHandleToMethodHandle(String desc, boolean isExact,
+                                TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f) {
+            this.desc = desc;
+            this.f = f;
+            this.isExact = isExact;
+        }
+
+        MethodHandle apply(VarHandle vh, TestAccessMode am, MethodType mt) {
+            return f.apply(vh, am, mt);
+        }
+
+        @Override
+        public String toString() {
+            return desc;
+        }
+    }
+
+    static class Handles {
+        static class AccessModeAndType {
+            final TestAccessMode tam;
+            final MethodType t;
+
+            public AccessModeAndType(TestAccessMode tam, MethodType t) {
+                this.tam = tam;
+                this.t = t;
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                if (this == o) return true;
+                if (o == null || getClass() != o.getClass()) return false;
+
+                AccessModeAndType x = (AccessModeAndType) o;
+
+                if (tam != x.tam) return false;
+                if (t != null ? !t.equals(x.t) : x.t != null) return false;
+
+                return true;
+            }
+
+            @Override
+            public int hashCode() {
+                int result = tam != null ? tam.hashCode() : 0;
+                result = 31 * result + (t != null ? t.hashCode() : 0);
+                return result;
+            }
+        }
+
+        final VarHandle vh;
+        final VarHandleToMethodHandle f;
+        final EnumMap<TestAccessMode, MethodType> amToType;
+        final Map<AccessModeAndType, MethodHandle> amToHandle;
+
+        Handles(VarHandle vh, VarHandleToMethodHandle f) throws Exception {
+            this.vh = vh;
+            this.f = f;
+            this.amToHandle = new HashMap<>();
+
+            amToType = new EnumMap<>(TestAccessMode.class);
+            for (TestAccessMode am : testAccessModes()) {
+                amToType.put(am, vh.accessModeType(am.toAccessMode()));
+            }
+        }
+
+        MethodHandle get(TestAccessMode am) {
+            return get(am, amToType.get(am));
+        }
+
+        MethodHandle get(TestAccessMode am, MethodType mt) {
+            AccessModeAndType amt = new AccessModeAndType(am, mt);
+            return amToHandle.computeIfAbsent(
+                    amt, k -> f.apply(vh, am, mt));
+        }
+
+        Class<? extends Throwable> getWMTEOOrOther(Class<? extends Throwable> c) {
+            return f.isExact ? WrongMethodTypeException.class : c;
+        }
+
+        void checkWMTEOrCCE(ThrowingRunnable r) {
+            checkWithThrowable(getWMTEOOrOther(ClassCastException.class), null, r);
+        }
+
+    }
+
+    interface AccessTestAction<T> {
+        void action(T t) throws Throwable;
+    }
+
+    static abstract class AccessTestCase<T> {
+        final String desc;
+        final AccessTestAction<T> ata;
+        final boolean loop;
+
+        AccessTestCase(String desc, AccessTestAction<T> ata, boolean loop) {
+            this.desc = desc;
+            this.ata = ata;
+            this.loop = loop;
+        }
+
+        boolean requiresLoop() {
+            return loop;
+        }
+
+        abstract T get() throws Exception;
+
+        void testAccess(T t) throws Throwable {
+            ata.action(t);
+        }
+
+        @Override
+        public String toString() {
+            return desc;
+        }
+    }
+
+    static class VarHandleAccessTestCase extends AccessTestCase<VarHandle> {
+        final VarHandle vh;
+
+        VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata) {
+            this(desc, vh, ata, true);
+        }
+
+        VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata, boolean loop) {
+            super("VarHandle -> " + desc, ata, loop);
+            this.vh = vh;
+        }
+
+        @Override
+        VarHandle get() {
+            return vh;
+        }
+    }
+
+    static class MethodHandleAccessTestCase extends AccessTestCase<Handles> {
+        final VarHandle vh;
+        final VarHandleToMethodHandle f;
+
+        MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata) {
+            this(desc, vh, f, ata, true);
+        }
+
+        MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata, boolean loop) {
+            super("VarHandle -> " + f.toString() + " -> " + desc, ata, loop);
+            this.vh = vh;
+            this.f = f;
+        }
+
+        @Override
+        Handles get() throws Exception {
+            return new Handles(vh, f);
+        }
+    }
+
+    static void testTypes(VarHandle vh) {
+        List<Class<?>> pts = vh.coordinateTypes();
+
+        for (TestAccessMode accessMode : testAccessModes()) {
+            MethodType amt = vh.accessModeType(accessMode.toAccessMode());
+
+            assertEquals(amt.parameterList().subList(0, pts.size()), pts);
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.GET)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterList(), pts);
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.SET)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), void.class);
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), boolean.class);
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.GET_AND_SET, TestAccessType.GET_AND_ADD)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleMethodReferenceTest.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleMethodReferenceTest.java
new file mode 100644
index 0000000..13f7682
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleMethodReferenceTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8195650
+ * @summary Test linking of method references to VarHandle access methods.
+ * @run testng VarHandleMethodReferenceTest
+ */
+
+import org.testng.annotations.Test;
+
+import java.lang.invoke.*;
+
+public class VarHandleMethodReferenceTest {
+
+  interface R {
+      void apply();
+  }
+
+  @Test
+  public void testMethodReferences() {
+      VarHandle vh = MethodHandles.arrayElementVarHandle(int[].class);
+
+      // The compilation of these method references will result in the
+      // placement of MethodHandles in the constant pool that reference
+      // VarHandle signature polymorphic methods.
+      // When those constant method handles are loaded the VarHandle invoker
+      // mechanism will be used where the first argument to invocation will be
+      // the bound VarHandle instance
+
+      // VarHandle invokers are tested by other test classes so here it
+      // is just necessary to check that functional objects can be successfully
+      // obtained, it does not matter about the signature of the functional
+      // interface
+
+      R r;
+      r = vh::get;
+      r = vh::set;
+      r = vh::getVolatile;
+      r = vh::setVolatile;
+      r = vh::getOpaque;
+      r = vh::setOpaque;
+      r = vh::getAcquire;
+      r = vh::setRelease;
+
+      r = vh::compareAndSet;
+      r = vh::compareAndExchange;
+      r = vh::compareAndExchangeAcquire;
+      r = vh::compareAndExchangeRelease;
+      r = vh::weakCompareAndSetPlain;
+      r = vh::weakCompareAndSet;
+      r = vh::weakCompareAndSetAcquire;
+      r = vh::weakCompareAndSetRelease;
+
+      r = vh::getAndSet;
+      r = vh::getAndSetAcquire;
+      r = vh::getAndSetRelease;
+      r = vh::getAndAdd;
+      r = vh::getAndAddAcquire;
+      r = vh::getAndAddRelease;
+      r = vh::getAndBitwiseOr;
+      r = vh::getAndBitwiseOrAcquire;
+      r = vh::getAndBitwiseOrRelease;
+      r = vh::getAndBitwiseAnd;
+      r = vh::getAndBitwiseAndAcquire;
+      r = vh::getAndBitwiseAndRelease;
+      r = vh::getAndBitwiseXor;
+      r = vh::getAndBitwiseXorAcquire;
+      r = vh::getAndBitwiseXorRelease;
+  }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
new file mode 100644
index 0000000..c3eafd2
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java
@@ -0,0 +1,1263 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessBoolean
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
+    static final boolean static_final_v = true;
+
+    static boolean static_v;
+
+    final boolean final_v = true;
+
+    boolean v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "final_v", boolean.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "v", boolean.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessBoolean.class, "static_v", boolean.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessBoolean.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(boolean[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), boolean.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessBoolean.class, "final_v", boolean.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessBoolean.class, "v", boolean.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "static_v", boolean.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessBoolean::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessBoolean::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessBoolean::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessBoolean::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessBoolean::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        // Plain
+        {
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "get boolean value");
+        }
+
+
+        // Volatile
+        {
+            boolean x = (boolean) vh.getVolatile(recv);
+            assertEquals(x, true, "getVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            boolean x = (boolean) vh.getAcquire(recv);
+            assertEquals(x, true, "getRelease boolean value");
+        }
+
+        // Opaque
+        {
+            boolean x = (boolean) vh.getOpaque(recv);
+            assertEquals(x, true, "getOpaque boolean value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, false);
+        });
+
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddAcquire(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddRelease(recv, true);
+        });
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "get boolean value");
+        }
+
+
+        // Volatile
+        {
+            boolean x = (boolean) vh.getVolatile();
+            assertEquals(x, true, "getVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            boolean x = (boolean) vh.getAcquire();
+            assertEquals(x, true, "getRelease boolean value");
+        }
+
+        // Opaque
+        {
+            boolean x = (boolean) vh.getOpaque();
+            assertEquals(x, true, "getOpaque boolean value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(false);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(false);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(false);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(false);
+        });
+
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddAcquire(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddRelease(true);
+        });
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, true);
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, false);
+            boolean x = (boolean) vh.getVolatile(recv);
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, true);
+            boolean x = (boolean) vh.getAcquire(recv);
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, false);
+            boolean x = (boolean) vh.getOpaque(recv);
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+        vh.set(recv, true);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, true, false);
+            assertEquals(r, true, "success compareAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "success compareAndSet boolean value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, true, false);
+            assertEquals(r, false, "failing compareAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "failing compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(recv, false, true);
+            assertEquals(r, false, "success compareAndExchange boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "success compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(recv, false, false);
+            assertEquals(r, true, "failing compareAndExchange boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "failing compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+            assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+            assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, false, true);
+            assertEquals(r, false, "success compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, false, false);
+            assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "weakCompareAndSetPlain boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "weakCompareAndSetRelease boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "weakCompareAndSet boolean value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndSet(recv, false);
+            assertEquals(o, true, "getAndSet boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "getAndSet boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndSetAcquire(recv, false);
+            assertEquals(o, true, "getAndSetAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "getAndSetAcquire boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndSetRelease(recv, false);
+            assertEquals(o, true, "getAndSetRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, false, "getAndSetRelease boolean value");
+        }
+
+
+        // get and bitwise or
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseOr(recv, false);
+            assertEquals(o, true, "getAndBitwiseOr boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOr boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseOrAcquire(recv, false);
+            assertEquals(o, true, "getAndBitwiseOrAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrAcquire boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseOrRelease(recv, false);
+            assertEquals(o, true, "getAndBitwiseOrRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrRelease boolean value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseAnd(recv, false);
+            assertEquals(o, true, "getAndBitwiseAnd boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAnd boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseAndAcquire(recv, false);
+            assertEquals(o, true, "getAndBitwiseAndAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndAcquire boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseAndRelease(recv, false);
+            assertEquals(o, true, "getAndBitwiseAndRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndRelease boolean value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseXor(recv, false);
+            assertEquals(o, true, "getAndBitwiseXor boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXor boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseXorAcquire(recv, false);
+            assertEquals(o, true, "getAndBitwiseXorAcquire boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorAcquire boolean value");
+        }
+
+        {
+            vh.set(recv, true);
+
+            boolean o = (boolean) vh.getAndBitwiseXorRelease(recv, false);
+            assertEquals(o, true, "getAndBitwiseXorRelease boolean");
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorRelease boolean value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddAcquire(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddRelease(recv, true);
+        });
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(true);
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(false);
+            boolean x = (boolean) vh.getVolatile();
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(true);
+            boolean x = (boolean) vh.getAcquire();
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(false);
+            boolean x = (boolean) vh.getOpaque();
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+        vh.set(true);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(true, false);
+            assertEquals(r, true, "success compareAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "success compareAndSet boolean value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(true, false);
+            assertEquals(r, false, "failing compareAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "failing compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(false, true);
+            assertEquals(r, false, "success compareAndExchange boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "success compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchange(false, false);
+            assertEquals(r, true, "failing compareAndExchange boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "failing compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+            assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+            assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(false, true);
+            assertEquals(r, false, "success compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean r = (boolean) vh.compareAndExchangeRelease(false, false);
+            assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "weakCompareAndSetPlain boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "weakCompareAndSetRelease boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "weakCompareAndSet boolean");
+        }
+
+        // Compare set and get
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndSet(false);
+            assertEquals(o, true, "getAndSet boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "getAndSet boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndSetAcquire(false);
+            assertEquals(o, true, "getAndSetAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "getAndSetAcquire boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndSetRelease(false);
+            assertEquals(o, true, "getAndSetRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, false, "getAndSetRelease boolean value");
+        }
+
+
+        // get and bitwise or
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseOr(false);
+            assertEquals(o, true, "getAndBitwiseOr boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOr boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseOrAcquire(false);
+            assertEquals(o, true, "getAndBitwiseOrAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrAcquire boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseOrRelease(false);
+            assertEquals(o, true, "getAndBitwiseOrRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrRelease boolean value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseAnd(false);
+            assertEquals(o, true, "getAndBitwiseAnd boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAnd boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseAndAcquire(false);
+            assertEquals(o, true, "getAndBitwiseAndAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndAcquire boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseAndRelease(false);
+            assertEquals(o, true, "getAndBitwiseAndRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndRelease boolean value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseXor(false);
+            assertEquals(o, true, "getAndBitwiseXor boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXor boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseXorAcquire(false);
+            assertEquals(o, true, "getAndBitwiseXorAcquire boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorAcquire boolean value");
+        }
+
+        {
+            vh.set(true);
+
+            boolean o = (boolean) vh.getAndBitwiseXorRelease(false);
+            assertEquals(o, true, "getAndBitwiseXorRelease boolean");
+            boolean x = (boolean) vh.get();
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorRelease boolean value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddAcquire(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddRelease(true);
+        });
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        boolean[] array = new boolean[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, true);
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "get boolean value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, false);
+                boolean x = (boolean) vh.getVolatile(array, i);
+                assertEquals(x, false, "setVolatile boolean value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, true);
+                boolean x = (boolean) vh.getAcquire(array, i);
+                assertEquals(x, true, "setRelease boolean value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, false);
+                boolean x = (boolean) vh.getOpaque(array, i);
+                assertEquals(x, false, "setOpaque boolean value");
+            }
+
+            vh.set(array, i, true);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, true, false);
+                assertEquals(r, true, "success compareAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "success compareAndSet boolean value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, true, false);
+                assertEquals(r, false, "failing compareAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "failing compareAndSet boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchange(array, i, false, true);
+                assertEquals(r, false, "success compareAndExchange boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "success compareAndExchange boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchange(array, i, false, false);
+                assertEquals(r, true, "failing compareAndExchange boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "failing compareAndExchange boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
+                assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
+                assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeRelease(array, i, false, true);
+                assertEquals(r, false, "success compareAndExchangeRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+            }
+
+            {
+                boolean r = (boolean) vh.compareAndExchangeRelease(array, i, false, false);
+                assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, true, false);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "weakCompareAndSetPlain boolean value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, false, true);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, true, false);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "weakCompareAndSetRelease boolean");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, false, true);
+                }
+                assertEquals(success, true, "weakCompareAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "weakCompareAndSet boolean");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndSet(array, i, false);
+                assertEquals(o, true, "getAndSet boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "getAndSet boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndSetAcquire(array, i, false);
+                assertEquals(o, true, "getAndSetAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "getAndSetAcquire boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndSetRelease(array, i, false);
+                assertEquals(o, true, "getAndSetRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, false, "getAndSetRelease boolean value");
+            }
+
+
+            // get and bitwise or
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseOr(array, i, false);
+                assertEquals(o, true, "getAndBitwiseOr boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true | false), "getAndBitwiseOr boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseOrAcquire(array, i, false);
+                assertEquals(o, true, "getAndBitwiseOrAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true | false), "getAndBitwiseOrAcquire boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseOrRelease(array, i, false);
+                assertEquals(o, true, "getAndBitwiseOrRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true | false), "getAndBitwiseOrRelease boolean value");
+            }
+
+            // get and bitwise and
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseAnd(array, i, false);
+                assertEquals(o, true, "getAndBitwiseAnd boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true & false), "getAndBitwiseAnd boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseAndAcquire(array, i, false);
+                assertEquals(o, true, "getAndBitwiseAndAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true & false), "getAndBitwiseAndAcquire boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseAndRelease(array, i, false);
+                assertEquals(o, true, "getAndBitwiseAndRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true & false), "getAndBitwiseAndRelease boolean value");
+            }
+
+            // get and bitwise xor
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseXor(array, i, false);
+                assertEquals(o, true, "getAndBitwiseXor boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXor boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseXorAcquire(array, i, false);
+                assertEquals(o, true, "getAndBitwiseXorAcquire boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorAcquire boolean value");
+            }
+
+            {
+                vh.set(array, i, true);
+
+                boolean o = (boolean) vh.getAndBitwiseXorRelease(array, i, false);
+                assertEquals(o, true, "getAndBitwiseXorRelease boolean");
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorRelease boolean value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        boolean[] array = new boolean[10];
+
+        int i = 0;
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(array, i, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddAcquire(array, i, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAddRelease(array, i, true);
+        });
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = (boolean) vh.compareAndExchange(array, ci, false, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = (boolean) vh.compareAndExchangeAcquire(array, ci, false, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = (boolean) vh.compareAndExchangeRelease(array, ci, false, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, true, false);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndSet(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndSetAcquire(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndSetRelease(array, ci, true);
+            });
+
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseOr(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseOrAcquire(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseOrRelease(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseAnd(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseAndAcquire(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseAndRelease(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseXor(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseXorAcquire(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean o = (boolean) vh.getAndBitwiseXorRelease(array, ci, true);
+            });
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
new file mode 100644
index 0000000..0f7e4b5
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessByte
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessByte extends VarHandleBaseTest {
+    static final byte static_final_v = (byte)0x01;
+
+    static byte static_v;
+
+    final byte final_v = (byte)0x01;
+
+    byte v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "final_v", byte.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "v", byte.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessByte.class, "static_final_v", byte.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessByte.class, "static_v", byte.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessByte.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(byte[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), byte.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessByte.class, "final_v", byte.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessByte.class, "v", byte.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "static_final_v", byte.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "static_v", byte.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessByte::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessByte::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessByte::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessByte::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessByte::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessByte recv, VarHandle vh) {
+        // Plain
+        {
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "get byte value");
+        }
+
+
+        // Volatile
+        {
+            byte x = (byte) vh.getVolatile(recv);
+            assertEquals(x, (byte)0x01, "getVolatile byte value");
+        }
+
+        // Lazy
+        {
+            byte x = (byte) vh.getAcquire(recv);
+            assertEquals(x, (byte)0x01, "getRelease byte value");
+        }
+
+        // Opaque
+        {
+            byte x = (byte) vh.getOpaque(recv);
+            assertEquals(x, (byte)0x01, "getOpaque byte value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, (byte)0x23);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, (byte)0x23);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, (byte)0x23);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, (byte)0x23);
+        });
+
+
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "get byte value");
+        }
+
+
+        // Volatile
+        {
+            byte x = (byte) vh.getVolatile();
+            assertEquals(x, (byte)0x01, "getVolatile byte value");
+        }
+
+        // Lazy
+        {
+            byte x = (byte) vh.getAcquire();
+            assertEquals(x, (byte)0x01, "getRelease byte value");
+        }
+
+        // Opaque
+        {
+            byte x = (byte) vh.getOpaque();
+            assertEquals(x, (byte)0x01, "getOpaque byte value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set((byte)0x23);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile((byte)0x23);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease((byte)0x23);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque((byte)0x23);
+        });
+
+
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, (byte)0x01);
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, (byte)0x23);
+            byte x = (byte) vh.getVolatile(recv);
+            assertEquals(x, (byte)0x23, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, (byte)0x01);
+            byte x = (byte) vh.getAcquire(recv);
+            assertEquals(x, (byte)0x01, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, (byte)0x23);
+            byte x = (byte) vh.getOpaque(recv);
+            assertEquals(x, (byte)0x23, "setOpaque byte value");
+        }
+
+        vh.set(recv, (byte)0x01);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, (byte)0x01, (byte)0x23);
+            assertEquals(r, true, "success compareAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, (byte)0x01, (byte)0x45);
+            assertEquals(r, false, "failing compareAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange(recv, (byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange(recv, (byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)0x01, (byte)0x23);
+            assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)0x01, (byte)0x45);
+            assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, (byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, (byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, (byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, (byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x01, "weakCompareAndSet byte value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndSet(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSet byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "getAndSet byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndSetAcquire(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSetAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "getAndSetAcquire byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndSetRelease(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSetRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)0x23, "getAndSetRelease byte value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndAdd(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAdd byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAdd byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndAddAcquire(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddAcquire byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndAddRelease(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddReleasebyte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddRelease byte value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseOr(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOr byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOr byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseOrAcquire(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrAcquire byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseOrRelease(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrRelease byte value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseAnd(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAnd byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAnd byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseAndAcquire(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndAcquire byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseAndRelease(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndRelease byte value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseXor(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXor byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXor byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseXorAcquire(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorAcquire byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorAcquire byte value");
+        }
+
+        {
+            vh.set(recv, (byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseXorRelease(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorRelease byte");
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorRelease byte value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
+
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set((byte)0x01);
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile((byte)0x23);
+            byte x = (byte) vh.getVolatile();
+            assertEquals(x, (byte)0x23, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease((byte)0x01);
+            byte x = (byte) vh.getAcquire();
+            assertEquals(x, (byte)0x01, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque((byte)0x23);
+            byte x = (byte) vh.getOpaque();
+            assertEquals(x, (byte)0x23, "setOpaque byte value");
+        }
+
+        vh.set((byte)0x01);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet((byte)0x01, (byte)0x23);
+            assertEquals(r, true, "success compareAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+        }
+
+        {
+            boolean r = vh.compareAndSet((byte)0x01, (byte)0x45);
+            assertEquals(r, false, "failing compareAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange((byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchange((byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)0x01, (byte)0x23);
+            assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)0x01, (byte)0x45);
+            assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+        }
+
+        {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain((byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire((byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease((byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet((byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x01, "weakCompareAndSet byte");
+        }
+
+        // Compare set and get
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndSet((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSet byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "getAndSet byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndSetAcquire((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSetAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "getAndSetAcquire byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndSetRelease((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSetRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)0x23, "getAndSetRelease byte value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndAdd((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAdd byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAdd byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndAddAcquire((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddAcquire byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndAddRelease((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddReleasebyte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddRelease byte value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseOr((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOr byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOr byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseOrAcquire((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrAcquire byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseOrRelease((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrRelease byte value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseAnd((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAnd byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAnd byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseAndAcquire((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndAcquire byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseAndRelease((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndRelease byte value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseXor((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXor byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXor byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseXorAcquire((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorAcquire byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorAcquire byte value");
+        }
+
+        {
+            vh.set((byte)0x01);
+
+            byte o = (byte) vh.getAndBitwiseXorRelease((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorRelease byte");
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorRelease byte value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        byte[] array = new byte[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, (byte)0x01);
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "get byte value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, (byte)0x23);
+                byte x = (byte) vh.getVolatile(array, i);
+                assertEquals(x, (byte)0x23, "setVolatile byte value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, (byte)0x01);
+                byte x = (byte) vh.getAcquire(array, i);
+                assertEquals(x, (byte)0x01, "setRelease byte value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, (byte)0x23);
+                byte x = (byte) vh.getOpaque(array, i);
+                assertEquals(x, (byte)0x23, "setOpaque byte value");
+            }
+
+            vh.set(array, i, (byte)0x01);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, (byte)0x01, (byte)0x23);
+                assertEquals(r, true, "success compareAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, (byte)0x01, (byte)0x45);
+                assertEquals(r, false, "failing compareAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchange(array, i, (byte)0x23, (byte)0x01);
+                assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchange(array, i, (byte)0x23, (byte)0x45);
+                assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)0x01, (byte)0x23);
+                assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)0x01, (byte)0x45);
+                assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)0x23, (byte)0x01);
+                assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+            }
+
+            {
+                byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)0x23, (byte)0x45);
+                assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, (byte)0x01, (byte)0x23);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, (byte)0x23, (byte)0x01);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, (byte)0x01, (byte)0x23);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, (byte)0x23, (byte)0x01);
+                }
+                assertEquals(success, true, "weakCompareAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x01, "weakCompareAndSet byte");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndSet(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndSet byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "getAndSet byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndSetAcquire(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndSetAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "getAndSetAcquire byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndSetRelease(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndSetRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)0x23, "getAndSetRelease byte value");
+            }
+
+            // get and add, add and get
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndAdd(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndAdd byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAdd byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndAddAcquire(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndAddAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddAcquire byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndAddRelease(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndAddReleasebyte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddRelease byte value");
+            }
+
+            // get and bitwise or
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseOr(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseOr byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOr byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseOrAcquire(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseOrAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrAcquire byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseOrRelease(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseOrRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrRelease byte value");
+            }
+
+            // get and bitwise and
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseAnd(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseAnd byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAnd byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseAndAcquire(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseAndAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndAcquire byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseAndRelease(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseAndRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndRelease byte value");
+            }
+
+            // get and bitwise xor
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseXor(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseXor byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXor byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseXorAcquire(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseXorAcquire byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorAcquire byte value");
+            }
+
+            {
+                vh.set(array, i, (byte)0x01);
+
+                byte o = (byte) vh.getAndBitwiseXorRelease(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndBitwiseXorRelease byte");
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorRelease byte value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        byte[] array = new byte[10];
+
+        int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        byte[] array = new byte[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                byte r = (byte) vh.compareAndExchange(array, ci, (byte)0x23, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte r = (byte) vh.compareAndExchangeAcquire(array, ci, (byte)0x23, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte r = (byte) vh.compareAndExchangeRelease(array, ci, (byte)0x23, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, (byte)0x01, (byte)0x23);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndSet(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndSetAcquire(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndSetRelease(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndAdd(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndAddAcquire(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndAddRelease(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseOr(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseOrAcquire(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseOrRelease(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseAnd(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseAndAcquire(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseAndRelease(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseXor(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseXorAcquire(array, ci, (byte)0x01);
+            });
+
+            checkIOOBE(() -> {
+                byte o = (byte) vh.getAndBitwiseXorRelease(array, ci, (byte)0x01);
+            });
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
new file mode 100644
index 0000000..233d9fe
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessChar
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessChar extends VarHandleBaseTest {
+    static final char static_final_v = '\u0123';
+
+    static char static_v;
+
+    final char final_v = '\u0123';
+
+    char v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "final_v", char.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "v", char.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessChar.class, "static_final_v", char.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessChar.class, "static_v", char.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(char[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessChar.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(char[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), char.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessChar.class, "final_v", char.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessChar.class, "v", char.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "static_final_v", char.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "static_v", char.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessChar::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessChar::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessChar::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessChar::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessChar::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessChar recv, VarHandle vh) {
+        // Plain
+        {
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "get char value");
+        }
+
+
+        // Volatile
+        {
+            char x = (char) vh.getVolatile(recv);
+            assertEquals(x, '\u0123', "getVolatile char value");
+        }
+
+        // Lazy
+        {
+            char x = (char) vh.getAcquire(recv);
+            assertEquals(x, '\u0123', "getRelease char value");
+        }
+
+        // Opaque
+        {
+            char x = (char) vh.getOpaque(recv);
+            assertEquals(x, '\u0123', "getOpaque char value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, '\u4567');
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, '\u4567');
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, '\u4567');
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, '\u4567');
+        });
+
+
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "get char value");
+        }
+
+
+        // Volatile
+        {
+            char x = (char) vh.getVolatile();
+            assertEquals(x, '\u0123', "getVolatile char value");
+        }
+
+        // Lazy
+        {
+            char x = (char) vh.getAcquire();
+            assertEquals(x, '\u0123', "getRelease char value");
+        }
+
+        // Opaque
+        {
+            char x = (char) vh.getOpaque();
+            assertEquals(x, '\u0123', "getOpaque char value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set('\u4567');
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile('\u4567');
+        });
+
+        checkUOE(() -> {
+            vh.setRelease('\u4567');
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque('\u4567');
+        });
+
+
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, '\u0123');
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "set char value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, '\u4567');
+            char x = (char) vh.getVolatile(recv);
+            assertEquals(x, '\u4567', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, '\u0123');
+            char x = (char) vh.getAcquire(recv);
+            assertEquals(x, '\u0123', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, '\u4567');
+            char x = (char) vh.getOpaque(recv);
+            assertEquals(x, '\u4567', "setOpaque char value");
+        }
+
+        vh.set(recv, '\u0123');
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, '\u0123', '\u4567');
+            assertEquals(r, true, "success compareAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "success compareAndSet char value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, '\u0123', '\u89AB');
+            assertEquals(r, false, "failing compareAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "failing compareAndSet char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange(recv, '\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchange char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "success compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange(recv, '\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchange char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "failing compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire(recv, '\u0123', '\u4567');
+            assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire(recv, '\u0123', '\u89AB');
+            assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease(recv, '\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease(recv, '\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, '\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "weakCompareAndSetPlain char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, '\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, '\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, '\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u0123', "weakCompareAndSet char value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndSet(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndSet char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "getAndSet char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndSetAcquire(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndSetAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "getAndSetAcquire char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndSetRelease(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndSetRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, '\u4567', "getAndSetRelease char value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndAdd(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndAdd char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAdd char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndAddAcquire(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndAddAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddAcquire char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndAddRelease(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndAddReleasechar");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddRelease char value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseOr(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOr char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOr char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseOrAcquire(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrAcquire char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseOrRelease(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrRelease char value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseAnd(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAnd char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAnd char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseAndAcquire(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndAcquire char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseAndRelease(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndRelease char value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseXor(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXor char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXor char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseXorAcquire(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorAcquire char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorAcquire char value");
+        }
+
+        {
+            vh.set(recv, '\u0123');
+
+            char o = (char) vh.getAndBitwiseXorRelease(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorRelease char");
+            char x = (char) vh.get(recv);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorRelease char value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
+
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set('\u0123');
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "set char value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile('\u4567');
+            char x = (char) vh.getVolatile();
+            assertEquals(x, '\u4567', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease('\u0123');
+            char x = (char) vh.getAcquire();
+            assertEquals(x, '\u0123', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque('\u4567');
+            char x = (char) vh.getOpaque();
+            assertEquals(x, '\u4567', "setOpaque char value");
+        }
+
+        vh.set('\u0123');
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet('\u0123', '\u4567');
+            assertEquals(r, true, "success compareAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "success compareAndSet char value");
+        }
+
+        {
+            boolean r = vh.compareAndSet('\u0123', '\u89AB');
+            assertEquals(r, false, "failing compareAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "failing compareAndSet char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange('\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchange char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "success compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchange('\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchange char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "failing compareAndExchange char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire('\u0123', '\u4567');
+            assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeAcquire('\u0123', '\u89AB');
+            assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease('\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+        }
+
+        {
+            char r = (char) vh.compareAndExchangeRelease('\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain('\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "weakCompareAndSetPlain char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire('\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease('\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet('\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u0123', "weakCompareAndSet char");
+        }
+
+        // Compare set and get
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndSet('\u4567');
+            assertEquals(o, '\u0123', "getAndSet char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "getAndSet char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndSetAcquire('\u4567');
+            assertEquals(o, '\u0123', "getAndSetAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "getAndSetAcquire char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndSetRelease('\u4567');
+            assertEquals(o, '\u0123', "getAndSetRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, '\u4567', "getAndSetRelease char value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndAdd('\u4567');
+            assertEquals(o, '\u0123', "getAndAdd char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAdd char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndAddAcquire('\u4567');
+            assertEquals(o, '\u0123', "getAndAddAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddAcquire char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndAddRelease('\u4567');
+            assertEquals(o, '\u0123', "getAndAddReleasechar");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddRelease char value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseOr('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOr char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOr char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseOrAcquire('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrAcquire char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseOrRelease('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrRelease char value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseAnd('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAnd char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAnd char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseAndAcquire('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndAcquire char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseAndRelease('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndRelease char value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseXor('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXor char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXor char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseXorAcquire('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorAcquire char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorAcquire char value");
+        }
+
+        {
+            vh.set('\u0123');
+
+            char o = (char) vh.getAndBitwiseXorRelease('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorRelease char");
+            char x = (char) vh.get();
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorRelease char value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        char[] array = new char[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, '\u0123');
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "get char value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, '\u4567');
+                char x = (char) vh.getVolatile(array, i);
+                assertEquals(x, '\u4567', "setVolatile char value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, '\u0123');
+                char x = (char) vh.getAcquire(array, i);
+                assertEquals(x, '\u0123', "setRelease char value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, '\u4567');
+                char x = (char) vh.getOpaque(array, i);
+                assertEquals(x, '\u4567', "setOpaque char value");
+            }
+
+            vh.set(array, i, '\u0123');
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, '\u0123', '\u4567');
+                assertEquals(r, true, "success compareAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "success compareAndSet char value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, '\u0123', '\u89AB');
+                assertEquals(r, false, "failing compareAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "failing compareAndSet char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchange(array, i, '\u4567', '\u0123');
+                assertEquals(r, '\u4567', "success compareAndExchange char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "success compareAndExchange char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchange(array, i, '\u4567', '\u89AB');
+                assertEquals(r, '\u0123', "failing compareAndExchange char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "failing compareAndExchange char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeAcquire(array, i, '\u0123', '\u4567');
+                assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeAcquire(array, i, '\u0123', '\u89AB');
+                assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeRelease(array, i, '\u4567', '\u0123');
+                assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+            }
+
+            {
+                char r = (char) vh.compareAndExchangeRelease(array, i, '\u4567', '\u89AB');
+                assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, '\u0123', '\u4567');
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "weakCompareAndSetPlain char value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, '\u4567', '\u0123');
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, '\u0123', '\u4567');
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, '\u4567', '\u0123');
+                }
+                assertEquals(success, true, "weakCompareAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u0123', "weakCompareAndSet char");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndSet(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndSet char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "getAndSet char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndSetAcquire(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndSetAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "getAndSetAcquire char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndSetRelease(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndSetRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, '\u4567', "getAndSetRelease char value");
+            }
+
+            // get and add, add and get
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndAdd(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndAdd char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAdd char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndAddAcquire(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndAddAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddAcquire char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndAddRelease(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndAddReleasechar");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddRelease char value");
+            }
+
+            // get and bitwise or
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseOr(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseOr char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOr char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseOrAcquire(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseOrAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrAcquire char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseOrRelease(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseOrRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrRelease char value");
+            }
+
+            // get and bitwise and
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseAnd(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseAnd char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAnd char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseAndAcquire(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseAndAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndAcquire char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseAndRelease(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseAndRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndRelease char value");
+            }
+
+            // get and bitwise xor
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseXor(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseXor char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXor char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseXorAcquire(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseXorAcquire char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorAcquire char value");
+            }
+
+            {
+                vh.set(array, i, '\u0123');
+
+                char o = (char) vh.getAndBitwiseXorRelease(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndBitwiseXorRelease char");
+                char x = (char) vh.get(array, i);
+                assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorRelease char value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        char[] array = new char[10];
+
+        int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        char[] array = new char[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                char x = (char) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                char r = (char) vh.compareAndExchange(array, ci, '\u4567', '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char r = (char) vh.compareAndExchangeAcquire(array, ci, '\u4567', '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char r = (char) vh.compareAndExchangeRelease(array, ci, '\u4567', '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, '\u0123', '\u4567');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndSet(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndSetAcquire(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndSetRelease(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndAdd(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndAddAcquire(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndAddRelease(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseOr(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseOrAcquire(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseOrRelease(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseAnd(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseAndAcquire(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseAndRelease(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseXor(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseXorAcquire(array, ci, '\u0123');
+            });
+
+            checkIOOBE(() -> {
+                char o = (char) vh.getAndBitwiseXorRelease(array, ci, '\u0123');
+            });
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
new file mode 100644
index 0000000..97f35ce
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java
@@ -0,0 +1,1191 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessDouble
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessDouble
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessDouble
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessDouble
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessDouble extends VarHandleBaseTest {
+    static final double static_final_v = 1.0d;
+
+    static double static_v;
+
+    final double final_v = 1.0d;
+
+    double v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "final_v", double.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "v", double.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessDouble.class, "static_final_v", double.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessDouble.class, "static_v", double.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(double[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessDouble.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(double[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), double.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessDouble.class, "final_v", double.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessDouble.class, "v", double.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "static_final_v", double.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessDouble.class, "static_v", double.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessDouble::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessDouble::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessDouble::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessDouble::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessDouble::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessDouble::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessDouble::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessDouble recv, VarHandle vh) {
+        // Plain
+        {
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "get double value");
+        }
+
+
+        // Volatile
+        {
+            double x = (double) vh.getVolatile(recv);
+            assertEquals(x, 1.0d, "getVolatile double value");
+        }
+
+        // Lazy
+        {
+            double x = (double) vh.getAcquire(recv);
+            assertEquals(x, 1.0d, "getRelease double value");
+        }
+
+        // Opaque
+        {
+            double x = (double) vh.getOpaque(recv);
+            assertEquals(x, 1.0d, "getOpaque double value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessDouble recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 2.0d);
+        });
+
+
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOr(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrAcquire(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrRelease(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAnd(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndAcquire(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndRelease(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXor(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorAcquire(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorRelease(recv, 1.0d);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "get double value");
+        }
+
+
+        // Volatile
+        {
+            double x = (double) vh.getVolatile();
+            assertEquals(x, 1.0d, "getVolatile double value");
+        }
+
+        // Lazy
+        {
+            double x = (double) vh.getAcquire();
+            assertEquals(x, 1.0d, "getRelease double value");
+        }
+
+        // Opaque
+        {
+            double x = (double) vh.getOpaque();
+            assertEquals(x, 1.0d, "getOpaque double value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(2.0d);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(2.0d);
+        });
+
+
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOr(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrAcquire(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrRelease(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAnd(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndAcquire(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndRelease(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXor(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorAcquire(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorRelease(1.0d);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessDouble recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 1.0d);
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 2.0d);
+            double x = (double) vh.getVolatile(recv);
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 1.0d);
+            double x = (double) vh.getAcquire(recv);
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 2.0d);
+            double x = (double) vh.getOpaque(recv);
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+        vh.set(recv, 1.0d);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, 1.0d, 2.0d);
+            assertEquals(r, true, "success compareAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "success compareAndSet double value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, 1.0d, 3.0d);
+            assertEquals(r, false, "failing compareAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "failing compareAndSet double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(recv, 2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchange double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "success compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(recv, 2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchange double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "failing compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 2.0d);
+            assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 3.0d);
+            assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(recv, 2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(recv, 2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, 1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "weakCompareAndSetPlain double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, 2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, 1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, 2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 1.0d, "weakCompareAndSet double value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, 1.0d);
+
+            double o = (double) vh.getAndSet(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndSet double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "getAndSet double value");
+        }
+
+        {
+            vh.set(recv, 1.0d);
+
+            double o = (double) vh.getAndSetAcquire(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndSetAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "getAndSetAcquire double value");
+        }
+
+        {
+            vh.set(recv, 1.0d);
+
+            double o = (double) vh.getAndSetRelease(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndSetRelease double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, 2.0d, "getAndSetRelease double value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(recv, 1.0d);
+
+            double o = (double) vh.getAndAdd(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndAdd double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAdd double value");
+        }
+
+        {
+            vh.set(recv, 1.0d);
+
+            double o = (double) vh.getAndAddAcquire(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndAddAcquire double");
+            double x = (double) vh.get(recv);
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddAcquire double value");
+        }
+
+        {
+            vh.set(recv, 1.0d);
+
+            double o = (double) vh.getAndAddRelease(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndAddReleasedouble");
+            double x = (double) vh.get(recv);
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddRelease double value");
+        }
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessDouble recv, VarHandle vh) {
+
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOr(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrAcquire(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrRelease(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAnd(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndAcquire(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndRelease(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXor(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorAcquire(recv, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorRelease(recv, 1.0d);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(1.0d);
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(2.0d);
+            double x = (double) vh.getVolatile();
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(1.0d);
+            double x = (double) vh.getAcquire();
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(2.0d);
+            double x = (double) vh.getOpaque();
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+        vh.set(1.0d);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(1.0d, 2.0d);
+            assertEquals(r, true, "success compareAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "success compareAndSet double value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(1.0d, 3.0d);
+            assertEquals(r, false, "failing compareAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "failing compareAndSet double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchange double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "success compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchange(2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchange double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "failing compareAndExchange double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(1.0d, 2.0d);
+            assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeAcquire(1.0d, 3.0d);
+            assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+        }
+
+        {
+            double r = (double) vh.compareAndExchangeRelease(2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "weakCompareAndSetPlain double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 1.0d, "weakCompareAndSet double");
+        }
+
+        // Compare set and get
+        {
+            vh.set(1.0d);
+
+            double o = (double) vh.getAndSet(2.0d);
+            assertEquals(o, 1.0d, "getAndSet double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "getAndSet double value");
+        }
+
+        {
+            vh.set(1.0d);
+
+            double o = (double) vh.getAndSetAcquire(2.0d);
+            assertEquals(o, 1.0d, "getAndSetAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "getAndSetAcquire double value");
+        }
+
+        {
+            vh.set(1.0d);
+
+            double o = (double) vh.getAndSetRelease(2.0d);
+            assertEquals(o, 1.0d, "getAndSetRelease double");
+            double x = (double) vh.get();
+            assertEquals(x, 2.0d, "getAndSetRelease double value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(1.0d);
+
+            double o = (double) vh.getAndAdd(2.0d);
+            assertEquals(o, 1.0d, "getAndAdd double");
+            double x = (double) vh.get();
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAdd double value");
+        }
+
+        {
+            vh.set(1.0d);
+
+            double o = (double) vh.getAndAddAcquire(2.0d);
+            assertEquals(o, 1.0d, "getAndAddAcquire double");
+            double x = (double) vh.get();
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddAcquire double value");
+        }
+
+        {
+            vh.set(1.0d);
+
+            double o = (double) vh.getAndAddRelease(2.0d);
+            assertEquals(o, 1.0d, "getAndAddReleasedouble");
+            double x = (double) vh.get();
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddRelease double value");
+        }
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOr(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrAcquire(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrRelease(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAnd(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndAcquire(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndRelease(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXor(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorAcquire(1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorRelease(1.0d);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        double[] array = new double[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 1.0d);
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "get double value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 2.0d);
+                double x = (double) vh.getVolatile(array, i);
+                assertEquals(x, 2.0d, "setVolatile double value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 1.0d);
+                double x = (double) vh.getAcquire(array, i);
+                assertEquals(x, 1.0d, "setRelease double value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 2.0d);
+                double x = (double) vh.getOpaque(array, i);
+                assertEquals(x, 2.0d, "setOpaque double value");
+            }
+
+            vh.set(array, i, 1.0d);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, 1.0d, 2.0d);
+                assertEquals(r, true, "success compareAndSet double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "success compareAndSet double value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, 1.0d, 3.0d);
+                assertEquals(r, false, "failing compareAndSet double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "failing compareAndSet double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchange(array, i, 2.0d, 1.0d);
+                assertEquals(r, 2.0d, "success compareAndExchange double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "success compareAndExchange double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchange(array, i, 2.0d, 3.0d);
+                assertEquals(r, 1.0d, "failing compareAndExchange double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "failing compareAndExchange double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeAcquire(array, i, 1.0d, 2.0d);
+                assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeAcquire(array, i, 1.0d, 3.0d);
+                assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeRelease(array, i, 2.0d, 1.0d);
+                assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+            }
+
+            {
+                double r = (double) vh.compareAndExchangeRelease(array, i, 2.0d, 3.0d);
+                assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, 1.0d, 2.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "weakCompareAndSetPlain double value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, 2.0d, 1.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, 1.0d, 2.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, 2.0d, 1.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSet double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 1.0d, "weakCompareAndSet double");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, 1.0d);
+
+                double o = (double) vh.getAndSet(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndSet double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "getAndSet double value");
+            }
+
+            {
+                vh.set(array, i, 1.0d);
+
+                double o = (double) vh.getAndSetAcquire(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndSetAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "getAndSetAcquire double value");
+            }
+
+            {
+                vh.set(array, i, 1.0d);
+
+                double o = (double) vh.getAndSetRelease(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndSetRelease double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, 2.0d, "getAndSetRelease double value");
+            }
+
+            // get and add, add and get
+            {
+                vh.set(array, i, 1.0d);
+
+                double o = (double) vh.getAndAdd(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndAdd double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, (double)(1.0d + 2.0d), "getAndAdd double value");
+            }
+
+            {
+                vh.set(array, i, 1.0d);
+
+                double o = (double) vh.getAndAddAcquire(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndAddAcquire double");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, (double)(1.0d + 2.0d), "getAndAddAcquire double value");
+            }
+
+            {
+                vh.set(array, i, 1.0d);
+
+                double o = (double) vh.getAndAddRelease(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndAddReleasedouble");
+                double x = (double) vh.get(array, i);
+                assertEquals(x, (double)(1.0d + 2.0d), "getAndAddRelease double value");
+            }
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        double[] array = new double[10];
+
+        int i = 0;
+
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOr(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrAcquire(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrRelease(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAnd(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndAcquire(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndRelease(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXor(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorAcquire(array, i, 1.0d);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorRelease(array, i, 1.0d);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        double[] array = new double[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                double x = (double) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, 1.0d, 2.0d);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchange(array, ci, 2.0d, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchangeAcquire(array, ci, 2.0d, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchangeRelease(array, ci, 2.0d, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, 1.0d, 2.0d);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, 1.0d, 2.0d);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, 1.0d, 2.0d);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, 1.0d, 2.0d);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndSet(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndSetAcquire(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndSetRelease(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndAdd(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndAddAcquire(array, ci, 1.0d);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndAddRelease(array, ci, 1.0d);
+            });
+
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
new file mode 100644
index 0000000..b7d7f04
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java
@@ -0,0 +1,1191 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessFloat
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessFloat
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessFloat
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessFloat
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessFloat extends VarHandleBaseTest {
+    static final float static_final_v = 1.0f;
+
+    static float static_v;
+
+    final float final_v = 1.0f;
+
+    float v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "final_v", float.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "v", float.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessFloat.class, "static_final_v", float.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessFloat.class, "static_v", float.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(float[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessFloat.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(float[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), float.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessFloat.class, "final_v", float.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessFloat.class, "v", float.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "static_final_v", float.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessFloat.class, "static_v", float.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessFloat::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessFloat::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessFloat::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessFloat::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessFloat::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessFloat::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessFloat::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessFloat recv, VarHandle vh) {
+        // Plain
+        {
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "get float value");
+        }
+
+
+        // Volatile
+        {
+            float x = (float) vh.getVolatile(recv);
+            assertEquals(x, 1.0f, "getVolatile float value");
+        }
+
+        // Lazy
+        {
+            float x = (float) vh.getAcquire(recv);
+            assertEquals(x, 1.0f, "getRelease float value");
+        }
+
+        // Opaque
+        {
+            float x = (float) vh.getOpaque(recv);
+            assertEquals(x, 1.0f, "getOpaque float value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessFloat recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 2.0f);
+        });
+
+
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOr(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrAcquire(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrRelease(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAnd(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndAcquire(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndRelease(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXor(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorAcquire(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorRelease(recv, 1.0f);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "get float value");
+        }
+
+
+        // Volatile
+        {
+            float x = (float) vh.getVolatile();
+            assertEquals(x, 1.0f, "getVolatile float value");
+        }
+
+        // Lazy
+        {
+            float x = (float) vh.getAcquire();
+            assertEquals(x, 1.0f, "getRelease float value");
+        }
+
+        // Opaque
+        {
+            float x = (float) vh.getOpaque();
+            assertEquals(x, 1.0f, "getOpaque float value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(2.0f);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(2.0f);
+        });
+
+
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOr(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrAcquire(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrRelease(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAnd(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndAcquire(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndRelease(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXor(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorAcquire(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorRelease(1.0f);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessFloat recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 1.0f);
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 2.0f);
+            float x = (float) vh.getVolatile(recv);
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 1.0f);
+            float x = (float) vh.getAcquire(recv);
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 2.0f);
+            float x = (float) vh.getOpaque(recv);
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+        vh.set(recv, 1.0f);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, 1.0f, 2.0f);
+            assertEquals(r, true, "success compareAndSet float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "success compareAndSet float value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, 1.0f, 3.0f);
+            assertEquals(r, false, "failing compareAndSet float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "failing compareAndSet float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchange(recv, 2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchange float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "success compareAndExchange float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchange(recv, 2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchange float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "failing compareAndExchange float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeAcquire(recv, 1.0f, 2.0f);
+            assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "success compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeAcquire(recv, 1.0f, 3.0f);
+            assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "failing compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeRelease(recv, 2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "success compareAndExchangeRelease float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeRelease(recv, 2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "failing compareAndExchangeRelease float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, 1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "weakCompareAndSetPlain float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, 2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "weakCompareAndSetAcquire float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, 1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "weakCompareAndSetRelease float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, 2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSet float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 1.0f, "weakCompareAndSet float value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, 1.0f);
+
+            float o = (float) vh.getAndSet(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndSet float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "getAndSet float value");
+        }
+
+        {
+            vh.set(recv, 1.0f);
+
+            float o = (float) vh.getAndSetAcquire(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndSetAcquire float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "getAndSetAcquire float value");
+        }
+
+        {
+            vh.set(recv, 1.0f);
+
+            float o = (float) vh.getAndSetRelease(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndSetRelease float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, 2.0f, "getAndSetRelease float value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(recv, 1.0f);
+
+            float o = (float) vh.getAndAdd(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndAdd float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAdd float value");
+        }
+
+        {
+            vh.set(recv, 1.0f);
+
+            float o = (float) vh.getAndAddAcquire(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndAddAcquire float");
+            float x = (float) vh.get(recv);
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddAcquire float value");
+        }
+
+        {
+            vh.set(recv, 1.0f);
+
+            float o = (float) vh.getAndAddRelease(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndAddReleasefloat");
+            float x = (float) vh.get(recv);
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddRelease float value");
+        }
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessFloat recv, VarHandle vh) {
+
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOr(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrAcquire(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrRelease(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAnd(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndAcquire(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndRelease(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXor(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorAcquire(recv, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorRelease(recv, 1.0f);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(1.0f);
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(2.0f);
+            float x = (float) vh.getVolatile();
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(1.0f);
+            float x = (float) vh.getAcquire();
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(2.0f);
+            float x = (float) vh.getOpaque();
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+        vh.set(1.0f);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(1.0f, 2.0f);
+            assertEquals(r, true, "success compareAndSet float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "success compareAndSet float value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(1.0f, 3.0f);
+            assertEquals(r, false, "failing compareAndSet float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "failing compareAndSet float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchange(2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchange float");
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "success compareAndExchange float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchange(2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchange float");
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "failing compareAndExchange float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeAcquire(1.0f, 2.0f);
+            assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "success compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeAcquire(1.0f, 3.0f);
+            assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "failing compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeRelease(2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "success compareAndExchangeRelease float value");
+        }
+
+        {
+            float r = (float) vh.compareAndExchangeRelease(2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "failing compareAndExchangeRelease float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "weakCompareAndSetPlain float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire float");
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "weakCompareAndSetAcquire float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "weakCompareAndSetRelease float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSet float");
+            float x = (float) vh.get();
+            assertEquals(x, 1.0f, "weakCompareAndSet float");
+        }
+
+        // Compare set and get
+        {
+            vh.set(1.0f);
+
+            float o = (float) vh.getAndSet(2.0f);
+            assertEquals(o, 1.0f, "getAndSet float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "getAndSet float value");
+        }
+
+        {
+            vh.set(1.0f);
+
+            float o = (float) vh.getAndSetAcquire(2.0f);
+            assertEquals(o, 1.0f, "getAndSetAcquire float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "getAndSetAcquire float value");
+        }
+
+        {
+            vh.set(1.0f);
+
+            float o = (float) vh.getAndSetRelease(2.0f);
+            assertEquals(o, 1.0f, "getAndSetRelease float");
+            float x = (float) vh.get();
+            assertEquals(x, 2.0f, "getAndSetRelease float value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(1.0f);
+
+            float o = (float) vh.getAndAdd(2.0f);
+            assertEquals(o, 1.0f, "getAndAdd float");
+            float x = (float) vh.get();
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAdd float value");
+        }
+
+        {
+            vh.set(1.0f);
+
+            float o = (float) vh.getAndAddAcquire(2.0f);
+            assertEquals(o, 1.0f, "getAndAddAcquire float");
+            float x = (float) vh.get();
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddAcquire float value");
+        }
+
+        {
+            vh.set(1.0f);
+
+            float o = (float) vh.getAndAddRelease(2.0f);
+            assertEquals(o, 1.0f, "getAndAddReleasefloat");
+            float x = (float) vh.get();
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddRelease float value");
+        }
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOr(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrAcquire(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrRelease(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAnd(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndAcquire(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndRelease(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXor(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorAcquire(1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorRelease(1.0f);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        float[] array = new float[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 1.0f);
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "get float value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 2.0f);
+                float x = (float) vh.getVolatile(array, i);
+                assertEquals(x, 2.0f, "setVolatile float value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 1.0f);
+                float x = (float) vh.getAcquire(array, i);
+                assertEquals(x, 1.0f, "setRelease float value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 2.0f);
+                float x = (float) vh.getOpaque(array, i);
+                assertEquals(x, 2.0f, "setOpaque float value");
+            }
+
+            vh.set(array, i, 1.0f);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, 1.0f, 2.0f);
+                assertEquals(r, true, "success compareAndSet float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "success compareAndSet float value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, 1.0f, 3.0f);
+                assertEquals(r, false, "failing compareAndSet float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "failing compareAndSet float value");
+            }
+
+            {
+                float r = (float) vh.compareAndExchange(array, i, 2.0f, 1.0f);
+                assertEquals(r, 2.0f, "success compareAndExchange float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "success compareAndExchange float value");
+            }
+
+            {
+                float r = (float) vh.compareAndExchange(array, i, 2.0f, 3.0f);
+                assertEquals(r, 1.0f, "failing compareAndExchange float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "failing compareAndExchange float value");
+            }
+
+            {
+                float r = (float) vh.compareAndExchangeAcquire(array, i, 1.0f, 2.0f);
+                assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "success compareAndExchangeAcquire float value");
+            }
+
+            {
+                float r = (float) vh.compareAndExchangeAcquire(array, i, 1.0f, 3.0f);
+                assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "failing compareAndExchangeAcquire float value");
+            }
+
+            {
+                float r = (float) vh.compareAndExchangeRelease(array, i, 2.0f, 1.0f);
+                assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "success compareAndExchangeRelease float value");
+            }
+
+            {
+                float r = (float) vh.compareAndExchangeRelease(array, i, 2.0f, 3.0f);
+                assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "failing compareAndExchangeRelease float value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, 1.0f, 2.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "weakCompareAndSetPlain float value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, 2.0f, 1.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "weakCompareAndSetAcquire float");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, 1.0f, 2.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "weakCompareAndSetRelease float");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, 2.0f, 1.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSet float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 1.0f, "weakCompareAndSet float");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, 1.0f);
+
+                float o = (float) vh.getAndSet(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndSet float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "getAndSet float value");
+            }
+
+            {
+                vh.set(array, i, 1.0f);
+
+                float o = (float) vh.getAndSetAcquire(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndSetAcquire float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "getAndSetAcquire float value");
+            }
+
+            {
+                vh.set(array, i, 1.0f);
+
+                float o = (float) vh.getAndSetRelease(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndSetRelease float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, 2.0f, "getAndSetRelease float value");
+            }
+
+            // get and add, add and get
+            {
+                vh.set(array, i, 1.0f);
+
+                float o = (float) vh.getAndAdd(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndAdd float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, (float)(1.0f + 2.0f), "getAndAdd float value");
+            }
+
+            {
+                vh.set(array, i, 1.0f);
+
+                float o = (float) vh.getAndAddAcquire(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndAddAcquire float");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, (float)(1.0f + 2.0f), "getAndAddAcquire float value");
+            }
+
+            {
+                vh.set(array, i, 1.0f);
+
+                float o = (float) vh.getAndAddRelease(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndAddReleasefloat");
+                float x = (float) vh.get(array, i);
+                assertEquals(x, (float)(1.0f + 2.0f), "getAndAddRelease float value");
+            }
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        float[] array = new float[10];
+
+        int i = 0;
+
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOr(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrAcquire(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrRelease(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAnd(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndAcquire(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndRelease(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXor(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorAcquire(array, i, 1.0f);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorRelease(array, i, 1.0f);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        float[] array = new float[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                float x = (float) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, 1.0f, 2.0f);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchange(array, ci, 2.0f, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchangeAcquire(array, ci, 2.0f, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchangeRelease(array, ci, 2.0f, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, 1.0f, 2.0f);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, 1.0f, 2.0f);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, 1.0f, 2.0f);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, 1.0f, 2.0f);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndSet(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndSetAcquire(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndSetRelease(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndAdd(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndAddAcquire(array, ci, 1.0f);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndAddRelease(array, ci, 1.0f);
+            });
+
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
new file mode 100644
index 0000000..c1a61e8
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessInt
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessInt
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessInt
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessInt
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessInt extends VarHandleBaseTest {
+    static final int static_final_v = 0x01234567;
+
+    static int static_v;
+
+    final int final_v = 0x01234567;
+
+    int v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "final_v", int.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "v", int.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessInt.class, "static_final_v", int.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessInt.class, "static_v", int.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(int[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessInt.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(int[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), int.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessInt.class, "final_v", int.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessInt.class, "v", int.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "static_final_v", int.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessInt.class, "static_v", int.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessInt::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessInt::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessInt::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessInt::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessInt::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessInt::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessInt::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessInt recv, VarHandle vh) {
+        // Plain
+        {
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "get int value");
+        }
+
+
+        // Volatile
+        {
+            int x = (int) vh.getVolatile(recv);
+            assertEquals(x, 0x01234567, "getVolatile int value");
+        }
+
+        // Lazy
+        {
+            int x = (int) vh.getAcquire(recv);
+            assertEquals(x, 0x01234567, "getRelease int value");
+        }
+
+        // Opaque
+        {
+            int x = (int) vh.getOpaque(recv);
+            assertEquals(x, 0x01234567, "getOpaque int value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessInt recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 0x89ABCDEF);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 0x89ABCDEF);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 0x89ABCDEF);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 0x89ABCDEF);
+        });
+
+
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "get int value");
+        }
+
+
+        // Volatile
+        {
+            int x = (int) vh.getVolatile();
+            assertEquals(x, 0x01234567, "getVolatile int value");
+        }
+
+        // Lazy
+        {
+            int x = (int) vh.getAcquire();
+            assertEquals(x, 0x01234567, "getRelease int value");
+        }
+
+        // Opaque
+        {
+            int x = (int) vh.getOpaque();
+            assertEquals(x, 0x01234567, "getOpaque int value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(0x89ABCDEF);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(0x89ABCDEF);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(0x89ABCDEF);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(0x89ABCDEF);
+        });
+
+
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessInt recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 0x01234567);
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "set int value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 0x89ABCDEF);
+            int x = (int) vh.getVolatile(recv);
+            assertEquals(x, 0x89ABCDEF, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 0x01234567);
+            int x = (int) vh.getAcquire(recv);
+            assertEquals(x, 0x01234567, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 0x89ABCDEF);
+            int x = (int) vh.getOpaque(recv);
+            assertEquals(x, 0x89ABCDEF, "setOpaque int value");
+        }
+
+        vh.set(recv, 0x01234567);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, 0x01234567, 0x89ABCDEF);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, 0x01234567, 0xCAFEBABE);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchange(recv, 0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchange int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "success compareAndExchange int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchange(recv, 0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchange int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "failing compareAndExchange int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(recv, 0x01234567, 0x89ABCDEF);
+            assertEquals(r, 0x01234567, "success compareAndExchangeAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(recv, 0x01234567, 0xCAFEBABE);
+            assertEquals(r, 0x89ABCDEF, "failing compareAndExchangeAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(recv, 0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchangeRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(recv, 0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchangeRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, 0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, 0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, 0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, 0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x01234567, "weakCompareAndSet int value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndSet(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSet int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "getAndSet int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndSetAcquire(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSetAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "getAndSetAcquire int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndSetRelease(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSetRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 0x89ABCDEF, "getAndSetRelease int value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndAdd(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAdd int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAdd int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndAddAcquire(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddAcquire int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndAddRelease(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddReleaseint");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddRelease int value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseOr(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOr int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOr int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseOrAcquire(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrAcquire int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseOrRelease(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrRelease int value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseAnd(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAnd int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAnd int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseAndAcquire(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndAcquire int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseAndRelease(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndRelease int value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseXor(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXor int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXor int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseXorAcquire(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorAcquire int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorAcquire int value");
+        }
+
+        {
+            vh.set(recv, 0x01234567);
+
+            int o = (int) vh.getAndBitwiseXorRelease(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorRelease int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorRelease int value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessInt recv, VarHandle vh) {
+
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(0x01234567);
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "set int value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(0x89ABCDEF);
+            int x = (int) vh.getVolatile();
+            assertEquals(x, 0x89ABCDEF, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(0x01234567);
+            int x = (int) vh.getAcquire();
+            assertEquals(x, 0x01234567, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(0x89ABCDEF);
+            int x = (int) vh.getOpaque();
+            assertEquals(x, 0x89ABCDEF, "setOpaque int value");
+        }
+
+        vh.set(0x01234567);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(0x01234567, 0x89ABCDEF);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(0x01234567, 0xCAFEBABE);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchange(0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchange int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "success compareAndExchange int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchange(0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchange int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "failing compareAndExchange int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(0x01234567, 0x89ABCDEF);
+            assertEquals(r, 0x01234567, "success compareAndExchangeAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeAcquire(0x01234567, 0xCAFEBABE);
+            assertEquals(r, 0x89ABCDEF, "failing compareAndExchangeAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchangeRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) vh.compareAndExchangeRelease(0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchangeRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x01234567, "weakCompareAndSet int");
+        }
+
+        // Compare set and get
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndSet(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSet int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "getAndSet int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndSetAcquire(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSetAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "getAndSetAcquire int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndSetRelease(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSetRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, 0x89ABCDEF, "getAndSetRelease int value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndAdd(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAdd int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAdd int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndAddAcquire(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddAcquire int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndAddRelease(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddReleaseint");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddRelease int value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseOr(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOr int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOr int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseOrAcquire(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrAcquire int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseOrRelease(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrRelease int value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseAnd(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAnd int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAnd int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseAndAcquire(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndAcquire int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseAndRelease(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndRelease int value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseXor(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXor int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXor int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseXorAcquire(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorAcquire int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorAcquire int value");
+        }
+
+        {
+            vh.set(0x01234567);
+
+            int o = (int) vh.getAndBitwiseXorRelease(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorRelease int");
+            int x = (int) vh.get();
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorRelease int value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        int[] array = new int[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 0x01234567);
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x01234567, "get int value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 0x89ABCDEF);
+                int x = (int) vh.getVolatile(array, i);
+                assertEquals(x, 0x89ABCDEF, "setVolatile int value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 0x01234567);
+                int x = (int) vh.getAcquire(array, i);
+                assertEquals(x, 0x01234567, "setRelease int value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 0x89ABCDEF);
+                int x = (int) vh.getOpaque(array, i);
+                assertEquals(x, 0x89ABCDEF, "setOpaque int value");
+            }
+
+            vh.set(array, i, 0x01234567);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, 0x01234567, 0x89ABCDEF);
+                assertEquals(r, true, "success compareAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "success compareAndSet int value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, 0x01234567, 0xCAFEBABE);
+                assertEquals(r, false, "failing compareAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "failing compareAndSet int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchange(array, i, 0x89ABCDEF, 0x01234567);
+                assertEquals(r, 0x89ABCDEF, "success compareAndExchange int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x01234567, "success compareAndExchange int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchange(array, i, 0x89ABCDEF, 0xCAFEBABE);
+                assertEquals(r, 0x01234567, "failing compareAndExchange int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x01234567, "failing compareAndExchange int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeAcquire(array, i, 0x01234567, 0x89ABCDEF);
+                assertEquals(r, 0x01234567, "success compareAndExchangeAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "success compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeAcquire(array, i, 0x01234567, 0xCAFEBABE);
+                assertEquals(r, 0x89ABCDEF, "failing compareAndExchangeAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "failing compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeRelease(array, i, 0x89ABCDEF, 0x01234567);
+                assertEquals(r, 0x89ABCDEF, "success compareAndExchangeRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x01234567, "success compareAndExchangeRelease int value");
+            }
+
+            {
+                int r = (int) vh.compareAndExchangeRelease(array, i, 0x89ABCDEF, 0xCAFEBABE);
+                assertEquals(r, 0x01234567, "failing compareAndExchangeRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x01234567, "failing compareAndExchangeRelease int value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, 0x01234567, 0x89ABCDEF);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, 0x89ABCDEF, 0x01234567);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, 0x01234567, 0x89ABCDEF);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, 0x89ABCDEF, 0x01234567);
+                }
+                assertEquals(success, true, "weakCompareAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x01234567, "weakCompareAndSet int");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndSet(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndSet int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "getAndSet int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndSetAcquire(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndSetAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "getAndSetAcquire int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndSetRelease(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndSetRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 0x89ABCDEF, "getAndSetRelease int value");
+            }
+
+            // get and add, add and get
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndAdd(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndAdd int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAdd int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndAddAcquire(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndAddAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddAcquire int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndAddRelease(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndAddReleaseint");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddRelease int value");
+            }
+
+            // get and bitwise or
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseOr(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseOr int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOr int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseOrAcquire(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseOrAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrAcquire int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseOrRelease(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseOrRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrRelease int value");
+            }
+
+            // get and bitwise and
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseAnd(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseAnd int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAnd int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseAndAcquire(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseAndAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndAcquire int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseAndRelease(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseAndRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndRelease int value");
+            }
+
+            // get and bitwise xor
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseXor(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseXor int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXor int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseXorAcquire(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseXorAcquire int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorAcquire int value");
+            }
+
+            {
+                vh.set(array, i, 0x01234567);
+
+                int o = (int) vh.getAndBitwiseXorRelease(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndBitwiseXorRelease int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorRelease int value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        int[] array = new int[10];
+
+        int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        int[] array = new int[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                int x = (int) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, 0x01234567, 0x89ABCDEF);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchange(array, ci, 0x89ABCDEF, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeAcquire(array, ci, 0x89ABCDEF, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeRelease(array, ci, 0x89ABCDEF, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, 0x01234567, 0x89ABCDEF);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, 0x01234567, 0x89ABCDEF);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, 0x01234567, 0x89ABCDEF);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, 0x01234567, 0x89ABCDEF);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSet(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSetAcquire(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSetRelease(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAdd(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAddAcquire(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAddRelease(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseOr(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseOrAcquire(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseOrRelease(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseAnd(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseAndAcquire(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseAndRelease(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseXor(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseXorAcquire(array, ci, 0x01234567);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseXorRelease(array, ci, 0x01234567);
+            });
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
new file mode 100644
index 0000000..8eea846
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessLong
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessLong
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessLong
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessLong
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessLong extends VarHandleBaseTest {
+    static final long static_final_v = 0x0123456789ABCDEFL;
+
+    static long static_v;
+
+    final long final_v = 0x0123456789ABCDEFL;
+
+    long v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "final_v", long.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "v", long.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessLong.class, "static_final_v", long.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessLong.class, "static_v", long.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(long[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessLong.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(long[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), long.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessLong.class, "final_v", long.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessLong.class, "v", long.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "static_final_v", long.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessLong.class, "static_v", long.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessLong::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessLong::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessLong::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessLong::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessLong::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessLong::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessLong::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessLong recv, VarHandle vh) {
+        // Plain
+        {
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "get long value");
+        }
+
+
+        // Volatile
+        {
+            long x = (long) vh.getVolatile(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "getVolatile long value");
+        }
+
+        // Lazy
+        {
+            long x = (long) vh.getAcquire(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "getRelease long value");
+        }
+
+        // Opaque
+        {
+            long x = (long) vh.getOpaque(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "getOpaque long value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessLong recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 0xCAFEBABECAFEBABEL);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 0xCAFEBABECAFEBABEL);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 0xCAFEBABECAFEBABEL);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 0xCAFEBABECAFEBABEL);
+        });
+
+
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "get long value");
+        }
+
+
+        // Volatile
+        {
+            long x = (long) vh.getVolatile();
+            assertEquals(x, 0x0123456789ABCDEFL, "getVolatile long value");
+        }
+
+        // Lazy
+        {
+            long x = (long) vh.getAcquire();
+            assertEquals(x, 0x0123456789ABCDEFL, "getRelease long value");
+        }
+
+        // Opaque
+        {
+            long x = (long) vh.getOpaque();
+            assertEquals(x, 0x0123456789ABCDEFL, "getOpaque long value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(0xCAFEBABECAFEBABEL);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(0xCAFEBABECAFEBABEL);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(0xCAFEBABECAFEBABEL);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(0xCAFEBABECAFEBABEL);
+        });
+
+
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessLong recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "set long value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, 0xCAFEBABECAFEBABEL);
+            long x = (long) vh.getVolatile(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, 0x0123456789ABCDEFL);
+            long x = (long) vh.getAcquire(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, 0xCAFEBABECAFEBABEL);
+            long x = (long) vh.getOpaque(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setOpaque long value");
+        }
+
+        vh.set(recv, 0x0123456789ABCDEFL);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchange(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchange long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchange long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchange(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchange long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchange long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, 0x0123456789ABCDEFL, "success compareAndExchangeAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchangeRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndSet(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSet long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSet long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndSetAcquire(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSetAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetAcquire long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndSetRelease(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSetRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetRelease long value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndAdd(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAdd long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAdd long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndAddAcquire(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddAcquire long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndAddRelease(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddReleaselong");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddRelease long value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseOr(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOr long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOr long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseOrAcquire(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrAcquire long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseOrRelease(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrRelease long value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseAnd(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAnd long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAnd long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseAndAcquire(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndAcquire long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseAndRelease(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndRelease long value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseXor(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXor long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXor long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseXorAcquire(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorAcquire long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorAcquire long value");
+        }
+
+        {
+            vh.set(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseXorRelease(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorRelease long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorRelease long value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessLong recv, VarHandle vh) {
+
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(0x0123456789ABCDEFL);
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "set long value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(0xCAFEBABECAFEBABEL);
+            long x = (long) vh.getVolatile();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(0x0123456789ABCDEFL);
+            long x = (long) vh.getAcquire();
+            assertEquals(x, 0x0123456789ABCDEFL, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(0xCAFEBABECAFEBABEL);
+            long x = (long) vh.getOpaque();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setOpaque long value");
+        }
+
+        vh.set(0x0123456789ABCDEFL);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchange(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchange long");
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchange long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchange(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchange long");
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchange long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, 0x0123456789ABCDEFL, "success compareAndExchangeAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeAcquire(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchangeRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) vh.compareAndExchangeRelease(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long");
+        }
+
+        // Compare set and get
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndSet(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSet long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSet long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndSetAcquire(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSetAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetAcquire long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndSetRelease(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSetRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetRelease long value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndAdd(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAdd long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAdd long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndAddAcquire(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddAcquire long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndAddRelease(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddReleaselong");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddRelease long value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseOr(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOr long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOr long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseOrAcquire(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrAcquire long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseOrRelease(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrRelease long value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseAnd(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAnd long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAnd long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseAndAcquire(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndAcquire long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseAndRelease(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndRelease long value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseXor(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXor long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXor long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseXorAcquire(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorAcquire long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorAcquire long value");
+        }
+
+        {
+            vh.set(0x0123456789ABCDEFL);
+
+            long o = (long) vh.getAndBitwiseXorRelease(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorRelease long");
+            long x = (long) vh.get();
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorRelease long value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        long[] array = new long[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "get long value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, 0xCAFEBABECAFEBABEL);
+                long x = (long) vh.getVolatile(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "setVolatile long value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, 0x0123456789ABCDEFL);
+                long x = (long) vh.getAcquire(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "setRelease long value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, 0xCAFEBABECAFEBABEL);
+                long x = (long) vh.getOpaque(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "setOpaque long value");
+            }
+
+            vh.set(array, i, 0x0123456789ABCDEFL);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                assertEquals(r, true, "success compareAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndSet long value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, false, "failing compareAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndSet long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchange(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchange long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchange long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchange(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchange long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchange long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeAcquire(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                assertEquals(r, 0x0123456789ABCDEFL, "success compareAndExchangeAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeAcquire(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeRelease(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchangeRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchangeRelease long value");
+            }
+
+            {
+                long r = (long) vh.compareAndExchangeRelease(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                }
+                assertEquals(success, true, "weakCompareAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndSet(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndSet long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSet long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndSetAcquire(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndSetAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetAcquire long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndSetRelease(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndSetRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetRelease long value");
+            }
+
+            // get and add, add and get
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndAdd(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndAdd long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAdd long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndAddAcquire(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndAddAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddAcquire long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndAddRelease(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndAddReleaselong");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddRelease long value");
+            }
+
+            // get and bitwise or
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseOr(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOr long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOr long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseOrAcquire(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrAcquire long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseOrRelease(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrRelease long value");
+            }
+
+            // get and bitwise and
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseAnd(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAnd long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAnd long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseAndAcquire(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndAcquire long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseAndRelease(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndRelease long value");
+            }
+
+            // get and bitwise xor
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseXor(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXor long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXor long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseXorAcquire(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorAcquire long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorAcquire long value");
+            }
+
+            {
+                vh.set(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) vh.getAndBitwiseXorRelease(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorRelease long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorRelease long value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        long[] array = new long[10];
+
+        int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        long[] array = new long[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                long x = (long) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchange(array, ci, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeAcquire(array, ci, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeRelease(array, ci, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSet(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSetAcquire(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSetRelease(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAdd(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAddAcquire(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAddRelease(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseOr(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseOrAcquire(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseOrRelease(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseAnd(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseAndAcquire(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseAndRelease(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseXor(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseXorAcquire(array, ci, 0x0123456789ABCDEFL);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseXorRelease(array, ci, 0x0123456789ABCDEFL);
+            });
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessModeMethodNames.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessModeMethodNames.java
new file mode 100644
index 0000000..4034c66
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessModeMethodNames.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng VarHandleTestAccessModeMethodNames
+ * @modules java.base/java.lang.invoke:open
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.stream.Stream;
+
+import static org.testng.Assert.assertEquals;
+
+public class VarHandleTestAccessModeMethodNames {
+
+    @DataProvider
+    public static Object[][] accessModesProvider() {
+        return Stream.of(VarHandle.AccessMode.values()).
+                map(am -> new Object[]{am}).
+                toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessModesProvider")
+    public void testMethodName(VarHandle.AccessMode am) {
+        assertEquals(am.methodName(), toMethodName(am.name()));
+    }
+
+    private static String toMethodName(String name) {
+        StringBuilder s = new StringBuilder(name.toLowerCase());
+        int i;
+        while ((i = s.indexOf("_")) !=  -1) {
+            s.deleteCharAt(i);
+            s.setCharAt(i, Character.toUpperCase(s.charAt(i)));
+        }
+        return s.toString();
+    }
+
+    // BEGIN Android-removed: test for AccessMode return type (not present on Android).
+    // @Test(dataProvider = "accessModesProvider")
+    // public void testReturnType(VarHandle.AccessMode am) throws Exception {
+    //     assertEquals(getReturnType(am.methodName()), getAccessModeReturnType(am));
+    // }
+    //
+    // private static Class<?> getReturnType(String name) throws Exception {
+    //     return VarHandle.class.getMethod(name, Object[].class).getReturnType();
+    // }
+    //
+    // private static Class<?> getAccessModeReturnType(VarHandle.AccessMode am) throws Exception {
+    //     Field field_am_at = VarHandle.AccessMode.class.getDeclaredField("at");
+    //     field_am_at.setAccessible(true);
+    //     Field field_at_returnType = field_am_at.getType().getDeclaredField("returnType");
+    //     field_at_returnType.setAccessible(true);
+    //     return (Class<?>) field_at_returnType.get(field_am_at.get(am));
+    // }
+    // END Android-removed: test for AccessMode return type (not present on Android). */
+
+    // BEGIN Android-added: valueFromMethodName test (b/203822312)
+    @Test(dataProvider = "accessModesProvider")
+    public void testValueFromMethodName(VarHandle.AccessMode am) throws Exception {
+        VarHandle.AccessMode other = VarHandle.AccessMode.valueFromMethodName(am.methodName());
+        assertEquals(am, other);
+    }
+    // END Android-added: valueFromMethodName test (b/203822312)
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
new file mode 100644
index 0000000..4854aeb
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessShort
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessShort
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessShort
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessShort
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessShort extends VarHandleBaseTest {
+    static final short static_final_v = (short)0x0123;
+
+    static short static_v;
+
+    final short final_v = (short)0x0123;
+
+    short v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "final_v", short.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "v", short.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessShort.class, "static_final_v", short.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessShort.class, "static_v", short.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(short[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessShort.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(short[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), short.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessShort.class, "final_v", short.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessShort.class, "v", short.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "static_final_v", short.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessShort.class, "static_v", short.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessShort::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessShort::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessShort::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessShort::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessShort::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessShort::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessShort::testArrayIndexOutOfBounds,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessShort recv, VarHandle vh) {
+        // Plain
+        {
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "get short value");
+        }
+
+
+        // Volatile
+        {
+            short x = (short) vh.getVolatile(recv);
+            assertEquals(x, (short)0x0123, "getVolatile short value");
+        }
+
+        // Lazy
+        {
+            short x = (short) vh.getAcquire(recv);
+            assertEquals(x, (short)0x0123, "getRelease short value");
+        }
+
+        // Opaque
+        {
+            short x = (short) vh.getOpaque(recv);
+            assertEquals(x, (short)0x0123, "getOpaque short value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessShort recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, (short)0x4567);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, (short)0x4567);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, (short)0x4567);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, (short)0x4567);
+        });
+
+
+
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "get short value");
+        }
+
+
+        // Volatile
+        {
+            short x = (short) vh.getVolatile();
+            assertEquals(x, (short)0x0123, "getVolatile short value");
+        }
+
+        // Lazy
+        {
+            short x = (short) vh.getAcquire();
+            assertEquals(x, (short)0x0123, "getRelease short value");
+        }
+
+        // Opaque
+        {
+            short x = (short) vh.getOpaque();
+            assertEquals(x, (short)0x0123, "getOpaque short value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set((short)0x4567);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile((short)0x4567);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease((short)0x4567);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque((short)0x4567);
+        });
+
+
+
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessShort recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, (short)0x0123);
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "set short value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, (short)0x4567);
+            short x = (short) vh.getVolatile(recv);
+            assertEquals(x, (short)0x4567, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, (short)0x0123);
+            short x = (short) vh.getAcquire(recv);
+            assertEquals(x, (short)0x0123, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, (short)0x4567);
+            short x = (short) vh.getOpaque(recv);
+            assertEquals(x, (short)0x4567, "setOpaque short value");
+        }
+
+        vh.set(recv, (short)0x0123);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, (short)0x0123, (short)0x4567);
+            assertEquals(r, true, "success compareAndSet short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "success compareAndSet short value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, (short)0x0123, (short)0x89AB);
+            assertEquals(r, false, "failing compareAndSet short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "failing compareAndSet short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchange(recv, (short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchange short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "success compareAndExchange short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchange(recv, (short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchange short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "failing compareAndExchange short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeAcquire(recv, (short)0x0123, (short)0x4567);
+            assertEquals(r, (short)0x0123, "success compareAndExchangeAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "success compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeAcquire(recv, (short)0x0123, (short)0x89AB);
+            assertEquals(r, (short)0x4567, "failing compareAndExchangeAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "failing compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeRelease(recv, (short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchangeRelease short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "success compareAndExchangeRelease short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeRelease(recv, (short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchangeRelease short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "failing compareAndExchangeRelease short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, (short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, (short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, (short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, (short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSet short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x0123, "weakCompareAndSet short value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndSet(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSet short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "getAndSet short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndSetAcquire(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSetAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "getAndSetAcquire short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndSetRelease(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSetRelease short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)0x4567, "getAndSetRelease short value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndAdd(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAdd short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAdd short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndAddAcquire(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddAcquire short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndAddRelease(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddReleaseshort");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddRelease short value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseOr(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOr short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOr short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseOrAcquire(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrAcquire short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseOrRelease(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrRelease short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrRelease short value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseAnd(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAnd short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAnd short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseAndAcquire(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndAcquire short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseAndRelease(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndRelease short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndRelease short value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseXor(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXor short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXor short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseXorAcquire(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorAcquire short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorAcquire short value");
+        }
+
+        {
+            vh.set(recv, (short)0x0123);
+
+            short o = (short) vh.getAndBitwiseXorRelease(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorRelease short");
+            short x = (short) vh.get(recv);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorRelease short value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessShort recv, VarHandle vh) {
+
+
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set((short)0x0123);
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "set short value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile((short)0x4567);
+            short x = (short) vh.getVolatile();
+            assertEquals(x, (short)0x4567, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease((short)0x0123);
+            short x = (short) vh.getAcquire();
+            assertEquals(x, (short)0x0123, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque((short)0x4567);
+            short x = (short) vh.getOpaque();
+            assertEquals(x, (short)0x4567, "setOpaque short value");
+        }
+
+        vh.set((short)0x0123);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet((short)0x0123, (short)0x4567);
+            assertEquals(r, true, "success compareAndSet short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "success compareAndSet short value");
+        }
+
+        {
+            boolean r = vh.compareAndSet((short)0x0123, (short)0x89AB);
+            assertEquals(r, false, "failing compareAndSet short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "failing compareAndSet short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchange((short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchange short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "success compareAndExchange short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchange((short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchange short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "failing compareAndExchange short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeAcquire((short)0x0123, (short)0x4567);
+            assertEquals(r, (short)0x0123, "success compareAndExchangeAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "success compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeAcquire((short)0x0123, (short)0x89AB);
+            assertEquals(r, (short)0x4567, "failing compareAndExchangeAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "failing compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeRelease((short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchangeRelease short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "success compareAndExchangeRelease short value");
+        }
+
+        {
+            short r = (short) vh.compareAndExchangeRelease((short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchangeRelease short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "failing compareAndExchangeRelease short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain((short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire((short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease((short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet((short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSet short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x0123, "weakCompareAndSet short");
+        }
+
+        // Compare set and get
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndSet((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSet short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "getAndSet short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndSetAcquire((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSetAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "getAndSetAcquire short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndSetRelease((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSetRelease short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)0x4567, "getAndSetRelease short value");
+        }
+
+        // get and add, add and get
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndAdd((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAdd short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAdd short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndAddAcquire((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddAcquire short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndAddRelease((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddReleaseshort");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddRelease short value");
+        }
+
+        // get and bitwise or
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseOr((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOr short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOr short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseOrAcquire((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrAcquire short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseOrRelease((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrRelease short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrRelease short value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseAnd((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAnd short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAnd short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseAndAcquire((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndAcquire short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseAndRelease((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndRelease short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndRelease short value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseXor((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXor short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXor short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseXorAcquire((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorAcquire short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorAcquire short value");
+        }
+
+        {
+            vh.set((short)0x0123);
+
+            short o = (short) vh.getAndBitwiseXorRelease((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorRelease short");
+            short x = (short) vh.get();
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorRelease short value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+
+    }
+
+
+    static void testArray(VarHandle vh) {
+        short[] array = new short[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, (short)0x0123);
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x0123, "get short value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, (short)0x4567);
+                short x = (short) vh.getVolatile(array, i);
+                assertEquals(x, (short)0x4567, "setVolatile short value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, (short)0x0123);
+                short x = (short) vh.getAcquire(array, i);
+                assertEquals(x, (short)0x0123, "setRelease short value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, (short)0x4567);
+                short x = (short) vh.getOpaque(array, i);
+                assertEquals(x, (short)0x4567, "setOpaque short value");
+            }
+
+            vh.set(array, i, (short)0x0123);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, (short)0x0123, (short)0x4567);
+                assertEquals(r, true, "success compareAndSet short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "success compareAndSet short value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, (short)0x0123, (short)0x89AB);
+                assertEquals(r, false, "failing compareAndSet short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "failing compareAndSet short value");
+            }
+
+            {
+                short r = (short) vh.compareAndExchange(array, i, (short)0x4567, (short)0x0123);
+                assertEquals(r, (short)0x4567, "success compareAndExchange short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x0123, "success compareAndExchange short value");
+            }
+
+            {
+                short r = (short) vh.compareAndExchange(array, i, (short)0x4567, (short)0x89AB);
+                assertEquals(r, (short)0x0123, "failing compareAndExchange short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x0123, "failing compareAndExchange short value");
+            }
+
+            {
+                short r = (short) vh.compareAndExchangeAcquire(array, i, (short)0x0123, (short)0x4567);
+                assertEquals(r, (short)0x0123, "success compareAndExchangeAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "success compareAndExchangeAcquire short value");
+            }
+
+            {
+                short r = (short) vh.compareAndExchangeAcquire(array, i, (short)0x0123, (short)0x89AB);
+                assertEquals(r, (short)0x4567, "failing compareAndExchangeAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "failing compareAndExchangeAcquire short value");
+            }
+
+            {
+                short r = (short) vh.compareAndExchangeRelease(array, i, (short)0x4567, (short)0x0123);
+                assertEquals(r, (short)0x4567, "success compareAndExchangeRelease short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x0123, "success compareAndExchangeRelease short value");
+            }
+
+            {
+                short r = (short) vh.compareAndExchangeRelease(array, i, (short)0x4567, (short)0x89AB);
+                assertEquals(r, (short)0x0123, "failing compareAndExchangeRelease short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x0123, "failing compareAndExchangeRelease short value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, (short)0x0123, (short)0x4567);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, (short)0x4567, (short)0x0123);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, (short)0x0123, (short)0x4567);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, (short)0x4567, (short)0x0123);
+                }
+                assertEquals(success, true, "weakCompareAndSet short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x0123, "weakCompareAndSet short");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndSet(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndSet short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "getAndSet short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndSetAcquire(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndSetAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "getAndSetAcquire short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndSetRelease(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndSetRelease short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)0x4567, "getAndSetRelease short value");
+            }
+
+            // get and add, add and get
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndAdd(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndAdd short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAdd short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndAddAcquire(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndAddAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddAcquire short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndAddRelease(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndAddReleaseshort");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddRelease short value");
+            }
+
+            // get and bitwise or
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseOr(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseOr short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOr short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseOrAcquire(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseOrAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrAcquire short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseOrRelease(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseOrRelease short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrRelease short value");
+            }
+
+            // get and bitwise and
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseAnd(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseAnd short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAnd short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseAndAcquire(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseAndAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndAcquire short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseAndRelease(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseAndRelease short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndRelease short value");
+            }
+
+            // get and bitwise xor
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseXor(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseXor short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXor short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseXorAcquire(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseXorAcquire short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorAcquire short value");
+            }
+
+            {
+                vh.set(array, i, (short)0x0123);
+
+                short o = (short) vh.getAndBitwiseXorRelease(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndBitwiseXorRelease short");
+                short x = (short) vh.get(array, i);
+                assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorRelease short value");
+            }
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        short[] array = new short[10];
+
+        int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        short[] array = new short[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                short x = (short) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, (short)0x0123, (short)0x4567);
+            });
+
+            checkIOOBE(() -> {
+                short r = (short) vh.compareAndExchange(array, ci, (short)0x4567, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short r = (short) vh.compareAndExchangeAcquire(array, ci, (short)0x4567, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short r = (short) vh.compareAndExchangeRelease(array, ci, (short)0x4567, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, (short)0x0123, (short)0x4567);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, (short)0x0123, (short)0x4567);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, (short)0x0123, (short)0x4567);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, (short)0x0123, (short)0x4567);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndSet(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndSetAcquire(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndSetRelease(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndAdd(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndAddAcquire(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndAddRelease(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseOr(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseOrAcquire(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseOrRelease(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseAnd(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseAndAcquire(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseAndRelease(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseXor(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseXorAcquire(array, ci, (short)0x0123);
+            });
+
+            checkIOOBE(() -> {
+                short o = (short) vh.getAndBitwiseXorRelease(array, ci, (short)0x0123);
+            });
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
new file mode 100644
index 0000000..144504b
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java
@@ -0,0 +1,1241 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessString
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessString
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessString
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessString
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessString extends VarHandleBaseTest {
+    static final String static_final_v = "foo";
+
+    static String static_v;
+
+    final String final_v = "foo";
+
+    String v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    VarHandle vhArrayObject;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "final_v", String.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "v", String.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessString.class, "static_final_v", String.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessString.class, "static_v", String.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(String[].class);
+        vhArrayObject = MethodHandles.arrayElementVarHandle(Object[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessString.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(String[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), String.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessString.class, "final_v", String.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessString.class, "v", String.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "static_final_v", String.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessString.class, "static_v", String.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessString::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessString::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessString::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessString::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessString::testArray));
+        cases.add(new VarHandleAccessTestCase("Array Object[]",
+                                              vhArrayObject, VarHandleTestAccessString::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessString::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessString::testArrayIndexOutOfBounds,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array store exception",
+                                              vhArrayObject, VarHandleTestAccessString::testArrayStoreException,
+                                              false));
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessString recv, VarHandle vh) {
+        // Plain
+        {
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "get String value");
+        }
+
+
+        // Volatile
+        {
+            String x = (String) vh.getVolatile(recv);
+            assertEquals(x, "foo", "getVolatile String value");
+        }
+
+        // Lazy
+        {
+            String x = (String) vh.getAcquire(recv);
+            assertEquals(x, "foo", "getRelease String value");
+        }
+
+        // Opaque
+        {
+            String x = (String) vh.getOpaque(recv);
+            assertEquals(x, "foo", "getOpaque String value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessString recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, "bar");
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, "bar");
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, "bar");
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, "bar");
+        });
+
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddRelease(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOr(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrRelease(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAnd(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndRelease(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXor(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorRelease(recv, "foo");
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "get String value");
+        }
+
+
+        // Volatile
+        {
+            String x = (String) vh.getVolatile();
+            assertEquals(x, "foo", "getVolatile String value");
+        }
+
+        // Lazy
+        {
+            String x = (String) vh.getAcquire();
+            assertEquals(x, "foo", "getRelease String value");
+        }
+
+        // Opaque
+        {
+            String x = (String) vh.getOpaque();
+            assertEquals(x, "foo", "getOpaque String value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set("bar");
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile("bar");
+        });
+
+        checkUOE(() -> {
+            vh.setRelease("bar");
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque("bar");
+        });
+
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddRelease("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOr("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrRelease("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAnd("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndRelease("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXor("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorRelease("foo");
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessString recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, "foo");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, "bar");
+            String x = (String) vh.getVolatile(recv);
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, "foo");
+            String x = (String) vh.getAcquire(recv);
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, "bar");
+            String x = (String) vh.getOpaque(recv);
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        vh.set(recv, "foo");
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, "foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, "foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchange(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchange String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "success compareAndExchange String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchange(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchange String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "failing compareAndExchange String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire(recv, "foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire(recv, "foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "weakCompareAndSetPlain String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "weakCompareAndSet String value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, "foo");
+
+            String o = (String) vh.getAndSet(recv, "bar");
+            assertEquals(o, "foo", "getAndSet String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "getAndSet String value");
+        }
+
+        {
+            vh.set(recv, "foo");
+
+            String o = (String) vh.getAndSetAcquire(recv, "bar");
+            assertEquals(o, "foo", "getAndSetAcquire String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "getAndSetAcquire String value");
+        }
+
+        {
+            vh.set(recv, "foo");
+
+            String o = (String) vh.getAndSetRelease(recv, "bar");
+            assertEquals(o, "foo", "getAndSetRelease String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "bar", "getAndSetRelease String value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessString recv, VarHandle vh) {
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddRelease(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOr(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrRelease(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAnd(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndRelease(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXor(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorAcquire(recv, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorRelease(recv, "foo");
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set("foo");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile("bar");
+            String x = (String) vh.getVolatile();
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease("foo");
+            String x = (String) vh.getAcquire();
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque("bar");
+            String x = (String) vh.getOpaque();
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        vh.set("foo");
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet("foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = vh.compareAndSet("foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchange("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchange String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "success compareAndExchange String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchange("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchange String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "failing compareAndExchange String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire("foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeAcquire("foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) vh.compareAndExchangeRelease("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "weakCompareAndSetPlain String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "weakCompareAndSet String");
+        }
+
+        // Compare set and get
+        {
+            vh.set("foo");
+
+            String o = (String) vh.getAndSet("bar");
+            assertEquals(o, "foo", "getAndSet String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "getAndSet String value");
+        }
+
+        {
+            vh.set("foo");
+
+            String o = (String) vh.getAndSetAcquire("bar");
+            assertEquals(o, "foo", "getAndSetAcquire String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "getAndSetAcquire String value");
+        }
+
+        {
+            vh.set("foo");
+
+            String o = (String) vh.getAndSetRelease("bar");
+            assertEquals(o, "foo", "getAndSetRelease String");
+            String x = (String) vh.get();
+            assertEquals(x, "bar", "getAndSetRelease String value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddRelease("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOr("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrRelease("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAnd("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndRelease("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXor("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorAcquire("foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorRelease("foo");
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        String[] array = new String[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, "foo");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "get String value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, "bar");
+                String x = (String) vh.getVolatile(array, i);
+                assertEquals(x, "bar", "setVolatile String value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, "foo");
+                String x = (String) vh.getAcquire(array, i);
+                assertEquals(x, "foo", "setRelease String value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, "bar");
+                String x = (String) vh.getOpaque(array, i);
+                assertEquals(x, "bar", "setOpaque String value");
+            }
+
+            vh.set(array, i, "foo");
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, "foo", "bar");
+                assertEquals(r, true, "success compareAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "success compareAndSet String value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, "foo", "baz");
+                assertEquals(r, false, "failing compareAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "failing compareAndSet String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchange(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchange String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "success compareAndExchange String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchange(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchange String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "failing compareAndExchange String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeAcquire(array, i, "foo", "bar");
+                assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeAcquire(array, i, "foo", "baz");
+                assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeRelease(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchangeRelease String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+            }
+
+            {
+                String r = (String) vh.compareAndExchangeRelease(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "weakCompareAndSetPlain String value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "weakCompareAndSetRelease String");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "weakCompareAndSet String");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, "foo");
+
+                String o = (String) vh.getAndSet(array, i, "bar");
+                assertEquals(o, "foo", "getAndSet String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "getAndSet String value");
+            }
+
+            {
+                vh.set(array, i, "foo");
+
+                String o = (String) vh.getAndSetAcquire(array, i, "bar");
+                assertEquals(o, "foo", "getAndSetAcquire String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "getAndSetAcquire String value");
+            }
+
+            {
+                vh.set(array, i, "foo");
+
+                String o = (String) vh.getAndSetRelease(array, i, "bar");
+                assertEquals(o, "foo", "getAndSetRelease String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "bar", "getAndSetRelease String value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        String[] array = new String[10];
+
+        int i = 0;
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAdd(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddAcquire(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndAddRelease(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOr(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrAcquire(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseOrRelease(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAnd(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndAcquire(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseAndRelease(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXor(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorAcquire(array, i, "foo");
+        });
+
+        checkUOE(() -> {
+            String o = (String) vh.getAndBitwiseXorRelease(array, i, "foo");
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        String[] array = new String[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                String x = (String) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String x = (String) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String x = (String) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String x = (String) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                String r = (String) vh.compareAndExchange(array, ci, "bar", "foo");
+            });
+
+            checkIOOBE(() -> {
+                String r = (String) vh.compareAndExchangeAcquire(array, ci, "bar", "foo");
+            });
+
+            checkIOOBE(() -> {
+                String r = (String) vh.compareAndExchangeRelease(array, ci, "bar", "foo");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
+                String o = (String) vh.getAndSet(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String o = (String) vh.getAndSetAcquire(array, ci, "foo");
+            });
+
+            checkIOOBE(() -> {
+                String o = (String) vh.getAndSetRelease(array, ci, "foo");
+            });
+
+
+        }
+    }
+
+    static void testArrayStoreException(VarHandle vh) throws Throwable {
+        Object[] array = new String[10];
+        Arrays.fill(array, "foo");
+        Object value = new Object();
+
+        // Set
+        checkASE(() -> {
+            vh.set(array, 0, value);
+        });
+
+        // SetVolatile
+        checkASE(() -> {
+            vh.setVolatile(array, 0, value);
+        });
+
+        // SetOpaque
+        checkASE(() -> {
+            vh.setOpaque(array, 0, value);
+        });
+
+        // SetRelease
+        checkASE(() -> {
+            vh.setRelease(array, 0, value);
+        });
+
+        // CompareAndSet
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(array, 0, "foo", value);
+        });
+
+        // WeakCompareAndSet
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, "foo", value);
+        });
+
+        // WeakCompareAndSetVolatile
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(array, 0, "foo", value);
+        });
+
+        // WeakCompareAndSetAcquire
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, "foo", value);
+        });
+
+        // WeakCompareAndSetRelease
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, "foo", value);
+        });
+
+        // CompareAndExchange
+        checkASE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchange(array, 0, "foo", value);
+        });
+
+        // CompareAndExchangeAcquire
+        checkASE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchangeAcquire(array, 0, "foo", value);
+        });
+
+        // CompareAndExchangeRelease
+        checkASE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchangeRelease(array, 0, "foo", value);
+        });
+
+        // GetAndSet
+        checkASE(() -> { // receiver reference class
+            String x = (String) vh.getAndSet(array, 0, value);
+        });
+
+        // GetAndSetAcquire
+        checkASE(() -> { // receiver reference class
+            String x = (String) vh.getAndSetAcquire(array, 0, value);
+        });
+
+        // GetAndSetRelease
+        checkASE(() -> { // receiver reference class
+            String x = (String) vh.getAndSetRelease(array, 0, value);
+        });
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
new file mode 100644
index 0000000..83d57ed
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
@@ -0,0 +1,914 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8154556
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsChar
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsChar
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Character.BYTES;
+
+    static final char VALUE_1 = (char)0x0102;
+
+    static final char VALUE_2 = (char)0x1112;
+
+    static final char VALUE_3 = (char)0xFFFE;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(char[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(char[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), char.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null array", bav, vh, h -> testArrayNPE(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            char x = (char) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            char x = (char) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            char x = (char) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            char x = (char) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+
+
+    }
+
+    static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            char x = (char) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            char x = (char) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            char x = (char) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            char x = (char) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+
+
+    }
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                char o = (char) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                char x = (char) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                char x = (char) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                char x = (char) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    char x = (char) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    char x = (char) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    char x = (char) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                char x = (char) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get char value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    char x = (char) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile char value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    char x = (char) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease char value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    char x = (char) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque char value");
+                }
+
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                char x = (char) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get char value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    char x = (char) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile char value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    char x = (char) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease char value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    char x = (char) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque char value");
+                }
+
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putChar(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            char v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                char x = (char) vh.get(array, i);
+                assertEquals(x, v, "get char value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    char x = (char) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile char value");
+                }
+
+                // Lazy
+                {
+                    char x = (char) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease char value");
+                }
+
+                // Opaque
+                {
+                    char x = (char) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque char value");
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
new file mode 100644
index 0000000..55fa4a7
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
@@ -0,0 +1,1344 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8154556
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsDouble
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsDouble
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Double.BYTES;
+
+    static final double VALUE_1 = 0x0102030405060708L;
+
+    static final double VALUE_2 = 0x1112131415161718L;
+
+    static final double VALUE_3 = 0xFFFEFDFCFBFAF9F8L;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(double[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(double[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), double.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null array", bav, vh, h -> testArrayNPE(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            double x = (double) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double x = (double) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            double x = (double) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            double x = (double) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            double o = (double) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+
+    }
+
+    static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            double x = (double) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double x = (double) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            double x = (double) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            double x = (double) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            double o = (double) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+
+    }
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            double o = (double) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                double o = (double) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                double o = (double) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                double o = (double) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                double x = (double) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                double x = (double) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                double x = (double) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    double o = (double) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    double x = (double) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    double o = (double) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    double x = (double) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    double x = (double) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        double o = (double) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+                    });
+
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                double x = (double) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get double value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    double x = (double) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile double value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    double x = (double) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease double value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    double x = (double) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque double value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet double value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain double value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet double");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    double o = (double) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet double value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    double o = (double) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire double value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    double o = (double) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease double value");
+                }
+
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                double x = (double) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get double value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    double x = (double) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile double value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    double x = (double) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease double value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    double x = (double) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque double value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet double value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value");
+                }
+
+                {
+                    double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain double value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet double");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    double o = (double) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet double value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    double o = (double) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire double value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    double o = (double) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease double value");
+                }
+
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putDouble(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            double v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                double x = (double) vh.get(array, i);
+                assertEquals(x, v, "get double value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    double x = (double) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile double value");
+                }
+
+                // Lazy
+                {
+                    double x = (double) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease double value");
+                }
+
+                // Opaque
+                {
+                    double x = (double) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque double value");
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
new file mode 100644
index 0000000..bfeb8a8
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
@@ -0,0 +1,1344 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8154556
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsFloat
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsFloat
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Float.BYTES;
+
+    static final float VALUE_1 = 0x01020304;
+
+    static final float VALUE_2 = 0x11121314;
+
+    static final float VALUE_3 = 0xFFFEFDFC;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(float[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(float[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), float.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null array", bav, vh, h -> testArrayNPE(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            float x = (float) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float x = (float) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            float x = (float) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            float x = (float) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            float o = (float) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+
+    }
+
+    static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            float x = (float) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float x = (float) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            float x = (float) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            float x = (float) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            float o = (float) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+
+    }
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            float o = (float) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                float o = (float) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                float o = (float) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                float o = (float) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                float x = (float) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                float x = (float) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                float x = (float) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    float o = (float) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    float x = (float) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    float o = (float) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    float x = (float) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    float x = (float) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        float o = (float) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+                    });
+
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                float x = (float) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get float value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    float x = (float) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile float value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    float x = (float) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease float value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    float x = (float) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque float value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet float value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain float value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet float");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    float o = (float) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet float value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    float o = (float) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire float value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    float o = (float) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease float value");
+                }
+
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                float x = (float) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get float value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    float x = (float) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile float value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    float x = (float) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease float value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    float x = (float) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque float value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet float value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value");
+                }
+
+                {
+                    float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain float value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet float");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    float o = (float) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet float value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    float o = (float) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire float value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    float o = (float) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease float value");
+                }
+
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putFloat(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            float v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                float x = (float) vh.get(array, i);
+                assertEquals(x, v, "get float value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    float x = (float) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile float value");
+                }
+
+                // Lazy
+                {
+                    float x = (float) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease float value");
+                }
+
+                // Opaque
+                {
+                    float x = (float) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque float value");
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
new file mode 100644
index 0000000..5e19b1a
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
@@ -0,0 +1,1748 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8154556
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsInt
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsInt
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Integer.BYTES;
+
+    static final int VALUE_1 = 0x01020304;
+
+    static final int VALUE_2 = 0x11121314;
+
+    static final int VALUE_3 = 0xFFFEFDFC;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(int[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(int[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), int.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null array", bav, vh, h -> testArrayNPE(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            int x = (int) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int x = (int) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            int x = (int) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            int x = (int) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            int x = (int) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int x = (int) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            int x = (int) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            int x = (int) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+        else {
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                int x = (int) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                int x = (int) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                int x = (int) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                });
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    int x = (int) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                });
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    int x = (int) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    int x = (int) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                    });
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                int x = (int) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get int value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    int x = (int) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile int value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    int x = (int) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease int value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    int x = (int) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque int value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet int value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain int value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet int");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease int value");
+                }
+
+                // get and add, add and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndAdd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAdd int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndAddAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndAddRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease int value");
+                }
+
+                // get and bitwise or
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseOr(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOr int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease int value");
+                }
+
+                // get and bitwise and
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseAnd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAnd int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease int value");
+                }
+
+                // get and bitwise xor
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseXor(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXor int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease int value");
+                }
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                int x = (int) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get int value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    int x = (int) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile int value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    int x = (int) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease int value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    int x = (int) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque int value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet int value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value");
+                }
+
+                {
+                    int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain int value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet int");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease int value");
+                }
+
+                // get and add, add and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndAdd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAdd int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndAddAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndAddRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease int value");
+                }
+
+                // get and bitwise or
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseOr(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOr int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease int value");
+                }
+
+                // get and bitwise and
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseAnd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAnd int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease int value");
+                }
+
+                // get and bitwise xor
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseXor(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXor int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire int value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    int o = (int) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorRelease int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease int value");
+                }
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putInt(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            int v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                int x = (int) vh.get(array, i);
+                assertEquals(x, v, "get int value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    int x = (int) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile int value");
+                }
+
+                // Lazy
+                {
+                    int x = (int) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease int value");
+                }
+
+                // Opaque
+                {
+                    int x = (int) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque int value");
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
new file mode 100644
index 0000000..926c3d8
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
@@ -0,0 +1,1748 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8154556
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsLong
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsLong
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Long.BYTES;
+
+    static final long VALUE_1 = 0x0102030405060708L;
+
+    static final long VALUE_2 = 0x1112131415161718L;
+
+    static final long VALUE_3 = 0xFFFEFDFCFBFAF9F8L;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(long[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(long[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), long.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null array", bav, vh, h -> testArrayNPE(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            long x = (long) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long x = (long) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            long x = (long) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            long x = (long) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            long x = (long) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long x = (long) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            long x = (long) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            long x = (long) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+
+
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+        else {
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                long x = (long) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                long x = (long) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                long x = (long) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                });
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    long x = (long) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                });
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    long x = (long) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    long x = (long) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                    });
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                long x = (long) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get long value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    long x = (long) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile long value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    long x = (long) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease long value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    long x = (long) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque long value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet long value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain long value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet long");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease long value");
+                }
+
+                // get and add, add and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndAdd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAdd long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndAddAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndAddRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease long value");
+                }
+
+                // get and bitwise or
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseOr(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOr long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease long value");
+                }
+
+                // get and bitwise and
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseAnd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAnd long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease long value");
+                }
+
+                // get and bitwise xor
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseXor(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXor long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease long value");
+                }
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                long x = (long) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get long value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    long x = (long) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile long value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    long x = (long) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease long value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    long x = (long) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque long value");
+                }
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet long value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value");
+                }
+
+                {
+                    long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain long value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet long");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease long value");
+                }
+
+                // get and add, add and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndAdd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAdd long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndAddAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndAddRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease long value");
+                }
+
+                // get and bitwise or
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseOr(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOr long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease long value");
+                }
+
+                // get and bitwise and
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseAnd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAnd long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease long value");
+                }
+
+                // get and bitwise xor
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseXor(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXor long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire long value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    long o = (long) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorRelease long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease long value");
+                }
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putLong(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            long v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                long x = (long) vh.get(array, i);
+                assertEquals(x, v, "get long value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    long x = (long) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile long value");
+                }
+
+                // Lazy
+                {
+                    long x = (long) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease long value");
+                }
+
+                // Opaque
+                {
+                    long x = (long) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque long value");
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
new file mode 100644
index 0000000..d1c740e
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
@@ -0,0 +1,914 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8154556
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsShort
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsShort
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest {
+    static final int SIZE = Short.BYTES;
+
+    static final short VALUE_1 = (short)0x0102;
+
+    static final short VALUE_2 = (short)0x1112;
+
+    static final short VALUE_3 = (short)0xFFFE;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle(short[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle(short[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), short.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null array", bav, vh, h -> testArrayNPE(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            short x = (short) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            short x = (short) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            short x = (short) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            short x = (short) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+
+
+    }
+
+    static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            short x = (short) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            short x = (short) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            short x = (short) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            short x = (short) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+
+
+    }
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            short o = (short) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+        else {
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short r = (short) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                short o = (short) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                short o = (short) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                short x = (short) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+
+
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                short x = (short) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                short x = (short) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    short x = (short) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    short x = (short) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    short x = (short) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+
+
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                short x = (short) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get short value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    short x = (short) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile short value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    short x = (short) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease short value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    short x = (short) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque short value");
+                }
+
+
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                short x = (short) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get short value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    short x = (short) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile short value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    short x = (short) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease short value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    short x = (short) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque short value");
+                }
+
+
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.putShort(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            short v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                short x = (short) vh.get(array, i);
+                assertEquals(x, v, "get short value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    short x = (short) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile short value");
+                }
+
+                // Lazy
+                {
+                    short x = (short) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease short value");
+                }
+
+                // Opaque
+                {
+                    short x = (short) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque short value");
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java
new file mode 100644
index 0000000..2db5c64
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessBoolean.java
@@ -0,0 +1,919 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessBoolean
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessBoolean extends VarHandleBaseTest {
+    static final boolean static_final_v = true;
+
+    static boolean static_v;
+
+    final boolean final_v = true;
+
+    boolean v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessBoolean.class, "final_v", boolean.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessBoolean.class, "v", boolean.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessBoolean.class, "static_final_v", boolean.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessBoolean.class, "static_v", boolean.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessBoolean::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessBoolean::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessBoolean::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessBoolean recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, false);
+            boolean x = (boolean) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, true);
+            boolean x = (boolean) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, false);
+            boolean x = (boolean) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, true, false);
+            assertEquals(r, true, "success compareAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, false, "success compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, true, false);
+            assertEquals(r, false, "failing compareAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, false, "failing compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, false, true);
+            assertEquals(r, false, "success compareAndExchange boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, true, "success compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, false, false);
+            assertEquals(r, true, "failing compareAndExchange boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, true, "failing compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, true, false);
+            assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, true, false);
+            assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, false, true);
+            assertEquals(r, false, "success compareAndExchangeRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, false, false);
+            assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, false, "weakCompareAndSetPlain boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, false, "weakCompareAndSetRelease boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, true, "weakCompareAndSet boolean");
+        }
+
+        // Compare set and get
+        {
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, false);
+            assertEquals(o, true, "getAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, false, "getAndSet boolean value");
+        }
+
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseOr boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOr boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseOrAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseOrRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrRelease boolean value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseAnd boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAnd boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseAndAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseAndRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndRelease boolean value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseXor boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXor boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseXorAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(recv, false);
+            assertEquals(o, true, "getAndBitwiseXorRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorRelease boolean value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessBoolean recv, Handles hs) throws Throwable {
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, true);
+            });
+        }
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(false);
+            boolean x = (boolean) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(true);
+            boolean x = (boolean) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(false);
+            boolean x = (boolean) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(true);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(true, false);
+            assertEquals(r, true, "success compareAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "success compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(true, false);
+            assertEquals(r, false, "failing compareAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "failing compareAndSet boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(false, true);
+            assertEquals(r, false, "success compareAndExchange boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, true, "success compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(false, false);
+            assertEquals(r, true, "failing compareAndExchange boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, true, "failing compareAndExchange boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(true, false);
+            assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(true, false);
+            assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(false, true);
+            assertEquals(r, false, "success compareAndExchangeRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(false, false);
+            assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "weakCompareAndSetPlain boolean value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(true, false);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "weakCompareAndSetRelease boolean");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(false, true);
+            }
+            assertEquals(success, true, "weakCompareAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, true, "weakCompareAndSet boolean");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET).invokeExact(false);
+            assertEquals(o, true, "getAndSet boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "getAndSet boolean value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(false);
+            assertEquals(o, true, "getAndSetAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "getAndSetAcquire boolean value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(false);
+            assertEquals(o, true, "getAndSetRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, false, "getAndSetRelease boolean value");
+        }
+
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseOr boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOr boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseOrAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseOrRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrRelease boolean value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseAnd boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAnd boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseAndAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseAndRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndRelease boolean value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseXor boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXor boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseXorAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(false);
+            assertEquals(o, true, "getAndBitwiseXorRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorRelease boolean value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(true);
+            });
+        }
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, true, "get boolean value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, false);
+                boolean x = (boolean) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, false, "setVolatile boolean value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, true);
+                boolean x = (boolean) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, true, "setRelease boolean value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, false);
+                boolean x = (boolean) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, false, "setOpaque boolean value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, true, false);
+                assertEquals(r, true, "success compareAndSet boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "success compareAndSet boolean value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, true, false);
+                assertEquals(r, false, "failing compareAndSet boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "failing compareAndSet boolean value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, false, true);
+                assertEquals(r, false, "success compareAndExchange boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, true, "success compareAndExchange boolean value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, false, false);
+                assertEquals(r, true, "failing compareAndExchange boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, true, "failing compareAndExchange boolean value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, true, false);
+                assertEquals(r, true, "success compareAndExchangeAcquire boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "success compareAndExchangeAcquire boolean value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, true, false);
+                assertEquals(r, false, "failing compareAndExchangeAcquire boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "failing compareAndExchangeAcquire boolean value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, false, true);
+                assertEquals(r, false, "success compareAndExchangeRelease boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, true, "success compareAndExchangeRelease boolean value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, false, false);
+                assertEquals(r, true, "failing compareAndExchangeRelease boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, true, "failing compareAndExchangeRelease boolean value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, true, false);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "weakCompareAndSetPlain boolean value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, false, true);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, true, "weakCompareAndSetAcquire boolean");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, true, false);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "weakCompareAndSetRelease boolean");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, false, true);
+                }
+                assertEquals(success, true, "weakCompareAndSet boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, true, "weakCompareAndSet boolean");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+                boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, false);
+                assertEquals(o, true, "getAndSet boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "getAndSet boolean value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+                boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, false);
+                assertEquals(o, true, "getAndSetAcquire boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "getAndSetAcquire boolean value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+                boolean o = (boolean) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, false);
+                assertEquals(o, true, "getAndSetRelease boolean");
+                boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, false, "getAndSetRelease boolean value");
+            }
+
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseOr boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOr boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseOrAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseOrRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true | false), "getAndBitwiseOrRelease boolean value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseAnd boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAnd boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseAndAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseAndRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true & false), "getAndBitwiseAndRelease boolean value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseXor boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXor boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseXorAcquire boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorAcquire boolean value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, true);
+
+            boolean o = (boolean) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(array, i, false);
+            assertEquals(o, true, "getAndBitwiseXorRelease boolean");
+            boolean x = (boolean) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (boolean)(true ^ false), "getAndBitwiseXorRelease boolean value");
+        }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        final int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                boolean o = (boolean) hs.get(am).invokeExact(array, i, true);
+            });
+        }
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    boolean x = (boolean) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, true);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, true, false);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, false, true);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean o = (boolean) hs.get(am).invokeExact(array, ci, true);
+                });
+            }
+
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+                checkIOOBE(am, () -> {
+                    boolean o = (boolean) hs.get(am).invokeExact(array, ci, false);
+                });
+            }
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java
new file mode 100644
index 0000000..1eac796
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessByte.java
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessByte
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessByte extends VarHandleBaseTest {
+    static final byte static_final_v = (byte)0x01;
+
+    static byte static_v;
+
+    final byte final_v = (byte)0x01;
+
+    byte v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessByte.class, "final_v", byte.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessByte.class, "v", byte.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessByte.class, "static_final_v", byte.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessByte.class, "static_v", byte.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessByte::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessByte::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessByte::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessByte::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessByte::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessByte recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, (byte)0x23);
+            byte x = (byte) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, (byte)0x01);
+            byte x = (byte) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, (byte)0x23);
+            byte x = (byte) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "setOpaque byte value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, (byte)0x01, (byte)0x23);
+            assertEquals(r, true, "success compareAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, (byte)0x01, (byte)0x45);
+            assertEquals(r, false, "failing compareAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, (byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, (byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, (byte)0x01, (byte)0x23);
+            assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, (byte)0x01, (byte)0x45);
+            assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, (byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, (byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, (byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, (byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, (byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, (byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x01, "weakCompareAndSet byte");
+        }
+
+        // Compare set and get
+        {
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)0x23, "getAndSet byte value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAdd byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAdd byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddRelease byte value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOr byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOr byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrRelease byte value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAnd byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAnd byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndRelease byte value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXor byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXor byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(recv, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorRelease byte value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessByte recv, Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x01, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact((byte)0x23);
+            byte x = (byte) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, (byte)0x23, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact((byte)0x01);
+            byte x = (byte) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, (byte)0x01, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact((byte)0x23);
+            byte x = (byte) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, (byte)0x23, "setOpaque byte value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact((byte)0x01, (byte)0x23);
+            assertEquals(r, true, "success compareAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact((byte)0x01, (byte)0x45);
+            assertEquals(r, false, "failing compareAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact((byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact((byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact((byte)0x01, (byte)0x23);
+            assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact((byte)0x01, (byte)0x45);
+            assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact((byte)0x23, (byte)0x01);
+            assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+        }
+
+        {
+            byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact((byte)0x23, (byte)0x45);
+            assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact((byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact((byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact((byte)0x01, (byte)0x23);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((byte)0x23, (byte)0x01);
+            }
+            assertEquals(success, true, "weakCompareAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x01, "weakCompareAndSet byte");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_SET).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSet byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "getAndSet byte value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSetAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "getAndSetAcquire byte value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndSetRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)0x23, "getAndSetRelease byte value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAdd byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAdd byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndAddRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddRelease byte value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOr byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOr byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrRelease byte value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAnd byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAnd byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndRelease byte value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXor byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXor byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact((byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorRelease byte value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "get byte value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, (byte)0x23);
+                byte x = (byte) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "setVolatile byte value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, (byte)0x01);
+                byte x = (byte) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "setRelease byte value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, (byte)0x23);
+                byte x = (byte) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "setOpaque byte value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, (byte)0x01, (byte)0x23);
+                assertEquals(r, true, "success compareAndSet byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "success compareAndSet byte value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, (byte)0x01, (byte)0x45);
+                assertEquals(r, false, "failing compareAndSet byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "failing compareAndSet byte value");
+            }
+
+            {
+                byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, (byte)0x23, (byte)0x01);
+                assertEquals(r, (byte)0x23, "success compareAndExchange byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "success compareAndExchange byte value");
+            }
+
+            {
+                byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, (byte)0x23, (byte)0x45);
+                assertEquals(r, (byte)0x01, "failing compareAndExchange byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "failing compareAndExchange byte value");
+            }
+
+            {
+                byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, (byte)0x01, (byte)0x23);
+                assertEquals(r, (byte)0x01, "success compareAndExchangeAcquire byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "success compareAndExchangeAcquire byte value");
+            }
+
+            {
+                byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, (byte)0x01, (byte)0x45);
+                assertEquals(r, (byte)0x23, "failing compareAndExchangeAcquire byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "failing compareAndExchangeAcquire byte value");
+            }
+
+            {
+                byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, (byte)0x23, (byte)0x01);
+                assertEquals(r, (byte)0x23, "success compareAndExchangeRelease byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "success compareAndExchangeRelease byte value");
+            }
+
+            {
+                byte r = (byte) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, (byte)0x23, (byte)0x45);
+                assertEquals(r, (byte)0x01, "failing compareAndExchangeRelease byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "failing compareAndExchangeRelease byte value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, (byte)0x01, (byte)0x23);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "weakCompareAndSetPlain byte value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (byte)0x23, (byte)0x01);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "weakCompareAndSetAcquire byte");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, (byte)0x01, (byte)0x23);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "weakCompareAndSetRelease byte");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, (byte)0x23, (byte)0x01);
+                }
+                assertEquals(success, true, "weakCompareAndSet byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x01, "weakCompareAndSet byte");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+                byte o = (byte) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndSet byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "getAndSet byte value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+                byte o = (byte) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndSetAcquire byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "getAndSetAcquire byte value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+                byte o = (byte) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndSetRelease byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)0x23, "getAndSetRelease byte value");
+            }
+
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+                byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndAdd byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAdd byte value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+                byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndAddAcquire byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddAcquire byte value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+                byte o = (byte) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, (byte)0x23);
+                assertEquals(o, (byte)0x01, "getAndAddRelease byte");
+                byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (byte)((byte)0x01 + (byte)0x23), "getAndAddRelease byte value");
+            }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOr byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOr byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseOrRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 | (byte)0x23), "getAndBitwiseOrRelease byte value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAnd byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAnd byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseAndRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 & (byte)0x23), "getAndBitwiseAndRelease byte value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXor byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXor byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorAcquire byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorAcquire byte value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (byte)0x01);
+
+            byte o = (byte) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(array, i, (byte)0x23);
+            assertEquals(o, (byte)0x01, "getAndBitwiseXorRelease byte");
+            byte x = (byte) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (byte)((byte)0x01 ^ (byte)0x23), "getAndBitwiseXorRelease byte value");
+        }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+
+        final int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    byte x = (byte) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, (byte)0x01);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, (byte)0x01, (byte)0x23);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    byte r = (byte) hs.get(am).invokeExact(array, ci, (byte)0x23, (byte)0x01);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    byte o = (byte) hs.get(am).invokeExact(array, ci, (byte)0x01);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    byte o = (byte) hs.get(am).invokeExact(array, ci, (byte)0x45);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+                checkIOOBE(am, () -> {
+                    byte o = (byte) hs.get(am).invokeExact(array, ci, (byte)0x45);
+                });
+            }
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java
new file mode 100644
index 0000000..1c5796b
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessChar.java
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessChar
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessChar extends VarHandleBaseTest {
+    static final char static_final_v = '\u0123';
+
+    static char static_v;
+
+    final char final_v = '\u0123';
+
+    char v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessChar.class, "final_v", char.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessChar.class, "v", char.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessChar.class, "static_final_v", char.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessChar.class, "static_v", char.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(char[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessChar::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessChar::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessChar::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessChar::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessChar::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessChar recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u0123', "set char value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, '\u4567');
+            char x = (char) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, '\u4567', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, '\u0123');
+            char x = (char) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, '\u0123', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, '\u4567');
+            char x = (char) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, '\u4567', "setOpaque char value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, '\u0123', '\u4567');
+            assertEquals(r, true, "success compareAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u4567', "success compareAndSet char value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, '\u0123', '\u89AB');
+            assertEquals(r, false, "failing compareAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u4567', "failing compareAndSet char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, '\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchange char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u0123', "success compareAndExchange char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, '\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchange char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u0123', "failing compareAndExchange char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, '\u0123', '\u4567');
+            assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, '\u0123', '\u89AB');
+            assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, '\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, '\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, '\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u4567', "weakCompareAndSetPlain char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, '\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, '\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, '\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u0123', "weakCompareAndSet char");
+        }
+
+        // Compare set and get
+        {
+            char o = (char) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, '\u4567', "getAndSet char value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndAdd char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAdd char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndAddAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndAddRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddRelease char value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOr char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOr char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrRelease char value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAnd char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAnd char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndRelease char value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXor char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXor char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(recv, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorRelease char value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessChar recv, Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u0123', "set char value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact('\u4567');
+            char x = (char) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, '\u4567', "setVolatile char value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact('\u0123');
+            char x = (char) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, '\u0123', "setRelease char value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact('\u4567');
+            char x = (char) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, '\u4567', "setOpaque char value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact('\u0123', '\u4567');
+            assertEquals(r, true, "success compareAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "success compareAndSet char value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact('\u0123', '\u89AB');
+            assertEquals(r, false, "failing compareAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "failing compareAndSet char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact('\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchange char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u0123', "success compareAndExchange char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact('\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchange char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u0123', "failing compareAndExchange char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact('\u0123', '\u4567');
+            assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact('\u0123', '\u89AB');
+            assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact('\u4567', '\u0123');
+            assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+        }
+
+        {
+            char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact('\u4567', '\u89AB');
+            assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact('\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "weakCompareAndSetPlain char value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact('\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact('\u0123', '\u4567');
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact('\u4567', '\u0123');
+            }
+            assertEquals(success, true, "weakCompareAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u0123', "weakCompareAndSet char");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_SET).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndSet char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "getAndSet char value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndSetAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "getAndSetAcquire char value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndSetRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, '\u4567', "getAndSetRelease char value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_ADD).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndAdd char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAdd char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndAddAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndAddRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddRelease char value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOr char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOr char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrRelease char value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAnd char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAnd char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndRelease char value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXor char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXor char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact('\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact('\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorRelease char value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        char[] array = new char[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u0123', "get char value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, '\u4567');
+                char x = (char) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, '\u4567', "setVolatile char value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, '\u0123');
+                char x = (char) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, '\u0123', "setRelease char value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, '\u4567');
+                char x = (char) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, '\u4567', "setOpaque char value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, '\u0123', '\u4567');
+                assertEquals(r, true, "success compareAndSet char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "success compareAndSet char value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, '\u0123', '\u89AB');
+                assertEquals(r, false, "failing compareAndSet char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "failing compareAndSet char value");
+            }
+
+            {
+                char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, '\u4567', '\u0123');
+                assertEquals(r, '\u4567', "success compareAndExchange char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u0123', "success compareAndExchange char value");
+            }
+
+            {
+                char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, '\u4567', '\u89AB');
+                assertEquals(r, '\u0123', "failing compareAndExchange char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u0123', "failing compareAndExchange char value");
+            }
+
+            {
+                char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, '\u0123', '\u4567');
+                assertEquals(r, '\u0123', "success compareAndExchangeAcquire char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "success compareAndExchangeAcquire char value");
+            }
+
+            {
+                char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, '\u0123', '\u89AB');
+                assertEquals(r, '\u4567', "failing compareAndExchangeAcquire char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "failing compareAndExchangeAcquire char value");
+            }
+
+            {
+                char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, '\u4567', '\u0123');
+                assertEquals(r, '\u4567', "success compareAndExchangeRelease char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u0123', "success compareAndExchangeRelease char value");
+            }
+
+            {
+                char r = (char) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, '\u4567', '\u89AB');
+                assertEquals(r, '\u0123', "failing compareAndExchangeRelease char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u0123', "failing compareAndExchangeRelease char value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, '\u0123', '\u4567');
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "weakCompareAndSetPlain char value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, '\u4567', '\u0123');
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u0123', "weakCompareAndSetAcquire char");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, '\u0123', '\u4567');
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "weakCompareAndSetRelease char");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, '\u4567', '\u0123');
+                }
+                assertEquals(success, true, "weakCompareAndSet char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u0123', "weakCompareAndSet char");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+                char o = (char) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndSet char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "getAndSet char value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+                char o = (char) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndSetAcquire char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "getAndSetAcquire char value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+                char o = (char) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndSetRelease char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, '\u4567', "getAndSetRelease char value");
+            }
+
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+                char o = (char) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndAdd char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAdd char value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+                char o = (char) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndAddAcquire char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddAcquire char value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+                char o = (char) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, '\u4567');
+                assertEquals(o, '\u0123', "getAndAddRelease char");
+                char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (char)('\u0123' + '\u4567'), "getAndAddRelease char value");
+            }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOr char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOr char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseOrRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' | '\u4567'), "getAndBitwiseOrRelease char value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAnd char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAnd char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseAndRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' & '\u4567'), "getAndBitwiseAndRelease char value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXor char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXor char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorAcquire char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorAcquire char value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, '\u0123');
+
+            char o = (char) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(array, i, '\u4567');
+            assertEquals(o, '\u0123', "getAndBitwiseXorRelease char");
+            char x = (char) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (char)('\u0123' ^ '\u4567'), "getAndBitwiseXorRelease char value");
+        }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        char[] array = new char[10];
+
+        final int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        char[] array = new char[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    char x = (char) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, '\u0123');
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, '\u0123', '\u4567');
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    char r = (char) hs.get(am).invokeExact(array, ci, '\u4567', '\u0123');
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    char o = (char) hs.get(am).invokeExact(array, ci, '\u0123');
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    char o = (char) hs.get(am).invokeExact(array, ci, '\u89AB');
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+                checkIOOBE(am, () -> {
+                    char o = (char) hs.get(am).invokeExact(array, ci, '\u89AB');
+                });
+            }
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java
new file mode 100644
index 0000000..e7864e3
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessDouble.java
@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessDouble
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessDouble extends VarHandleBaseTest {
+    static final double static_final_v = 1.0d;
+
+    static double static_v;
+
+    final double final_v = 1.0d;
+
+    double v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessDouble.class, "final_v", double.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessDouble.class, "v", double.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessDouble.class, "static_final_v", double.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessDouble.class, "static_v", double.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(double[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessDouble::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessDouble::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessDouble::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessDouble::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessDouble::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessDouble recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, 2.0d);
+            double x = (double) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, 1.0d);
+            double x = (double) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, 2.0d);
+            double x = (double) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0d, 2.0d);
+            assertEquals(r, true, "success compareAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0d, "success compareAndSet double value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0d, 3.0d);
+            assertEquals(r, false, "failing compareAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0d, "failing compareAndSet double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchange double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0d, "success compareAndExchange double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchange double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0d, "failing compareAndExchange double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0d, 2.0d);
+            assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0d, 3.0d);
+            assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0d, "weakCompareAndSetPlain double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0d, "weakCompareAndSet double");
+        }
+
+        // Compare set and get
+        {
+            double o = (double) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0d, "getAndSet double value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndAdd double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAdd double value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndAddAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddAcquire double value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, 2.0d);
+            assertEquals(o, 1.0d, "getAndAddRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddRelease double value");
+        }
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessDouble recv, Handles hs) throws Throwable {
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(recv, 1.0d);
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0d);
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0d, "set double value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(2.0d);
+            double x = (double) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, 2.0d, "setVolatile double value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(1.0d);
+            double x = (double) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, 1.0d, "setRelease double value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(2.0d);
+            double x = (double) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, 2.0d, "setOpaque double value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(1.0d);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0d, 2.0d);
+            assertEquals(r, true, "success compareAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "success compareAndSet double value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0d, 3.0d);
+            assertEquals(r, false, "failing compareAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "failing compareAndSet double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchange double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0d, "success compareAndExchange double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchange double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0d, "failing compareAndExchange double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0d, 2.0d);
+            assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0d, 3.0d);
+            assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0d, 1.0d);
+            assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+        }
+
+        {
+            double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0d, 3.0d);
+            assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "weakCompareAndSetPlain double value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0d, 2.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0d, 1.0d);
+            }
+            assertEquals(success, true, "weakCompareAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0d, "weakCompareAndSet double");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2.0d);
+            assertEquals(o, 1.0d, "getAndSet double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "getAndSet double value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(2.0d);
+            assertEquals(o, 1.0d, "getAndSetAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "getAndSetAcquire double value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(2.0d);
+            assertEquals(o, 1.0d, "getAndSetRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0d, "getAndSetRelease double value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(2.0d);
+            assertEquals(o, 1.0d, "getAndAdd double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAdd double value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(2.0d);
+            assertEquals(o, 1.0d, "getAndAddAcquire double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddAcquire double value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0d);
+
+            double o = (double) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(2.0d);
+            assertEquals(o, 1.0d, "getAndAddRelease double");
+            double x = (double) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (double)(1.0d + 2.0d), "getAndAddRelease double value");
+        }
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                double r = (double) hs.get(am).invokeExact(1.0d);
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        double[] array = new double[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0d, "get double value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, 2.0d);
+                double x = (double) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, 2.0d, "setVolatile double value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, 1.0d);
+                double x = (double) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, 1.0d, "setRelease double value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, 2.0d);
+                double x = (double) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, 2.0d, "setOpaque double value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0d, 2.0d);
+                assertEquals(r, true, "success compareAndSet double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "success compareAndSet double value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0d, 3.0d);
+                assertEquals(r, false, "failing compareAndSet double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "failing compareAndSet double value");
+            }
+
+            {
+                double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0d, 1.0d);
+                assertEquals(r, 2.0d, "success compareAndExchange double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0d, "success compareAndExchange double value");
+            }
+
+            {
+                double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0d, 3.0d);
+                assertEquals(r, 1.0d, "failing compareAndExchange double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0d, "failing compareAndExchange double value");
+            }
+
+            {
+                double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0d, 2.0d);
+                assertEquals(r, 1.0d, "success compareAndExchangeAcquire double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "success compareAndExchangeAcquire double value");
+            }
+
+            {
+                double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0d, 3.0d);
+                assertEquals(r, 2.0d, "failing compareAndExchangeAcquire double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "failing compareAndExchangeAcquire double value");
+            }
+
+            {
+                double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0d, 1.0d);
+                assertEquals(r, 2.0d, "success compareAndExchangeRelease double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0d, "success compareAndExchangeRelease double value");
+            }
+
+            {
+                double r = (double) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0d, 3.0d);
+                assertEquals(r, 1.0d, "failing compareAndExchangeRelease double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0d, "failing compareAndExchangeRelease double value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0d, 2.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "weakCompareAndSetPlain double value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0d, 1.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0d, "weakCompareAndSetAcquire double");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1.0d, 2.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "weakCompareAndSetRelease double");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0d, 1.0d);
+                }
+                assertEquals(success, true, "weakCompareAndSet double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0d, "weakCompareAndSet double");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+
+                double o = (double) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndSet double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "getAndSet double value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+
+                double o = (double) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndSetAcquire double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "getAndSetAcquire double value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+
+                double o = (double) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndSetRelease double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0d, "getAndSetRelease double value");
+            }
+
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+
+                double o = (double) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndAdd double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (double)(1.0d + 2.0d), "getAndAdd double value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+
+                double o = (double) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndAddAcquire double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (double)(1.0d + 2.0d), "getAndAddAcquire double value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0d);
+
+                double o = (double) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, 2.0d);
+                assertEquals(o, 1.0d, "getAndAddRelease double");
+                double x = (double) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (double)(1.0d + 2.0d), "getAndAddRelease double value");
+            }
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        double[] array = new double[10];
+
+        final int i = 0;
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                double o = (double) hs.get(am).invokeExact(array, i, 1.0d);
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        double[] array = new double[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    double x = (double) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 1.0d);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1.0d, 2.0d);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    double r = (double) hs.get(am).invokeExact(array, ci, 2.0d, 1.0d);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    double o = (double) hs.get(am).invokeExact(array, ci, 1.0d);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    double o = (double) hs.get(am).invokeExact(array, ci, 3.0d);
+                });
+            }
+
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java
new file mode 100644
index 0000000..3f291de
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessFloat.java
@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessFloat
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessFloat extends VarHandleBaseTest {
+    static final float static_final_v = 1.0f;
+
+    static float static_v;
+
+    final float final_v = 1.0f;
+
+    float v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessFloat.class, "final_v", float.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessFloat.class, "v", float.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessFloat.class, "static_final_v", float.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessFloat.class, "static_v", float.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(float[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessFloat::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessFloat::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessFloat::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessFloat::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessFloat::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessFloat recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, 2.0f);
+            float x = (float) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, 1.0f);
+            float x = (float) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, 2.0f);
+            float x = (float) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0f, 2.0f);
+            assertEquals(r, true, "success compareAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0f, "success compareAndSet float value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 1.0f, 3.0f);
+            assertEquals(r, false, "failing compareAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0f, "failing compareAndSet float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchange float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0f, "success compareAndExchange float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchange float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0f, "failing compareAndExchange float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0f, 2.0f);
+            assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0f, "success compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 1.0f, 3.0f);
+            assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0f, "failing compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0f, "success compareAndExchangeRelease float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0f, "failing compareAndExchangeRelease float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0f, "weakCompareAndSetPlain float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0f, "weakCompareAndSetAcquire float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0f, "weakCompareAndSetRelease float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1.0f, "weakCompareAndSet float");
+        }
+
+        // Compare set and get
+        {
+            float o = (float) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 2.0f, "getAndSet float value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndAdd float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAdd float value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndAddAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddAcquire float value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, 2.0f);
+            assertEquals(o, 1.0f, "getAndAddRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddRelease float value");
+        }
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessFloat recv, Handles hs) throws Throwable {
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(recv, 1.0f);
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0f);
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0f, "set float value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(2.0f);
+            float x = (float) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, 2.0f, "setVolatile float value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(1.0f);
+            float x = (float) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, 1.0f, "setRelease float value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(2.0f);
+            float x = (float) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, 2.0f, "setOpaque float value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(1.0f);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0f, 2.0f);
+            assertEquals(r, true, "success compareAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "success compareAndSet float value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(1.0f, 3.0f);
+            assertEquals(r, false, "failing compareAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "failing compareAndSet float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchange float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0f, "success compareAndExchange float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchange float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0f, "failing compareAndExchange float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0f, 2.0f);
+            assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "success compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(1.0f, 3.0f);
+            assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "failing compareAndExchangeAcquire float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0f, 1.0f);
+            assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0f, "success compareAndExchangeRelease float value");
+        }
+
+        {
+            float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(2.0f, 3.0f);
+            assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0f, "failing compareAndExchangeRelease float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "weakCompareAndSetPlain float value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0f, "weakCompareAndSetAcquire float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1.0f, 2.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "weakCompareAndSetRelease float");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(2.0f, 1.0f);
+            }
+            assertEquals(success, true, "weakCompareAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1.0f, "weakCompareAndSet float");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2.0f);
+            assertEquals(o, 1.0f, "getAndSet float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "getAndSet float value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(2.0f);
+            assertEquals(o, 1.0f, "getAndSetAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "getAndSetAcquire float value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(2.0f);
+            assertEquals(o, 1.0f, "getAndSetRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 2.0f, "getAndSetRelease float value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(2.0f);
+            assertEquals(o, 1.0f, "getAndAdd float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAdd float value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(2.0f);
+            assertEquals(o, 1.0f, "getAndAddAcquire float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddAcquire float value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(1.0f);
+
+            float o = (float) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(2.0f);
+            assertEquals(o, 1.0f, "getAndAddRelease float");
+            float x = (float) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (float)(1.0f + 2.0f), "getAndAddRelease float value");
+        }
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                float r = (float) hs.get(am).invokeExact(1.0f);
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        float[] array = new float[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0f, "get float value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, 2.0f);
+                float x = (float) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, 2.0f, "setVolatile float value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, 1.0f);
+                float x = (float) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, 1.0f, "setRelease float value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, 2.0f);
+                float x = (float) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, 2.0f, "setOpaque float value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0f, 2.0f);
+                assertEquals(r, true, "success compareAndSet float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "success compareAndSet float value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 1.0f, 3.0f);
+                assertEquals(r, false, "failing compareAndSet float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "failing compareAndSet float value");
+            }
+
+            {
+                float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0f, 1.0f);
+                assertEquals(r, 2.0f, "success compareAndExchange float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0f, "success compareAndExchange float value");
+            }
+
+            {
+                float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 2.0f, 3.0f);
+                assertEquals(r, 1.0f, "failing compareAndExchange float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0f, "failing compareAndExchange float value");
+            }
+
+            {
+                float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0f, 2.0f);
+                assertEquals(r, 1.0f, "success compareAndExchangeAcquire float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "success compareAndExchangeAcquire float value");
+            }
+
+            {
+                float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 1.0f, 3.0f);
+                assertEquals(r, 2.0f, "failing compareAndExchangeAcquire float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "failing compareAndExchangeAcquire float value");
+            }
+
+            {
+                float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0f, 1.0f);
+                assertEquals(r, 2.0f, "success compareAndExchangeRelease float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0f, "success compareAndExchangeRelease float value");
+            }
+
+            {
+                float r = (float) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 2.0f, 3.0f);
+                assertEquals(r, 1.0f, "failing compareAndExchangeRelease float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0f, "failing compareAndExchangeRelease float value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 1.0f, 2.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "weakCompareAndSetPlain float value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2.0f, 1.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0f, "weakCompareAndSetAcquire float");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1.0f, 2.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "weakCompareAndSetRelease float");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 2.0f, 1.0f);
+                }
+                assertEquals(success, true, "weakCompareAndSet float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1.0f, "weakCompareAndSet float");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+
+                float o = (float) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndSet float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "getAndSet float value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+
+                float o = (float) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndSetAcquire float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "getAndSetAcquire float value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+
+                float o = (float) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndSetRelease float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 2.0f, "getAndSetRelease float value");
+            }
+
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+
+                float o = (float) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndAdd float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (float)(1.0f + 2.0f), "getAndAdd float value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+
+                float o = (float) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndAddAcquire float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (float)(1.0f + 2.0f), "getAndAddAcquire float value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 1.0f);
+
+                float o = (float) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, 2.0f);
+                assertEquals(o, 1.0f, "getAndAddRelease float");
+                float x = (float) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (float)(1.0f + 2.0f), "getAndAddRelease float value");
+            }
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        float[] array = new float[10];
+
+        final int i = 0;
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                float o = (float) hs.get(am).invokeExact(array, i, 1.0f);
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        float[] array = new float[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    float x = (float) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 1.0f);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, 1.0f, 2.0f);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    float r = (float) hs.get(am).invokeExact(array, ci, 2.0f, 1.0f);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    float o = (float) hs.get(am).invokeExact(array, ci, 1.0f);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    float o = (float) hs.get(am).invokeExact(array, ci, 3.0f);
+                });
+            }
+
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java
new file mode 100644
index 0000000..d938e3d
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessInt
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest {
+    static final int static_final_v = 0x01234567;
+
+    static int static_v;
+
+    final int final_v = 0x01234567;
+
+    int v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessInt.class, "final_v", int.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessInt.class, "v", int.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessInt.class, "static_final_v", int.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessInt.class, "static_v", int.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(int[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessInt::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessInt::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessInt::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessInt::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessInt::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessInt recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x01234567, "set int value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, 0x89ABCDEF);
+            int x = (int) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, 0x01234567);
+            int x = (int) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, 0x01234567, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, 0x89ABCDEF);
+            int x = (int) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "setOpaque int value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 0x01234567, 0x89ABCDEF);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 0x01234567, 0xCAFEBABE);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchange int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x01234567, "success compareAndExchange int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchange int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x01234567, "failing compareAndExchange int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 0x01234567, 0x89ABCDEF);
+            assertEquals(r, 0x01234567, "success compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 0x01234567, 0xCAFEBABE);
+            assertEquals(r, 0x89ABCDEF, "failing compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x01234567, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x01234567, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x01234567, "weakCompareAndSet int");
+        }
+
+        // Compare set and get
+        {
+            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x89ABCDEF, "getAndSet int value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAdd int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAdd int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddRelease int value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOr int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOr int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrRelease int value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAnd int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAnd int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndRelease int value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXor int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXor int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(recv, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorRelease int value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessInt recv, Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x01234567, "set int value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(0x89ABCDEF);
+            int x = (int) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "setVolatile int value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(0x01234567);
+            int x = (int) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, 0x01234567, "setRelease int value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(0x89ABCDEF);
+            int x = (int) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "setOpaque int value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(0x01234567, 0x89ABCDEF);
+            assertEquals(r, true, "success compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "success compareAndSet int value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(0x01234567, 0xCAFEBABE);
+            assertEquals(r, false, "failing compareAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "failing compareAndSet int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchange int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x01234567, "success compareAndExchange int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchange int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x01234567, "failing compareAndExchange int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(0x01234567, 0x89ABCDEF);
+            assertEquals(r, 0x01234567, "success compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "success compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(0x01234567, 0xCAFEBABE);
+            assertEquals(r, 0x89ABCDEF, "failing compareAndExchangeAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "failing compareAndExchangeAcquire int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(0x89ABCDEF, 0x01234567);
+            assertEquals(r, 0x89ABCDEF, "success compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x01234567, "success compareAndExchangeRelease int value");
+        }
+
+        {
+            int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(0x89ABCDEF, 0xCAFEBABE);
+            assertEquals(r, 0x01234567, "failing compareAndExchangeRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x01234567, "failing compareAndExchangeRelease int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(0x01234567, 0x89ABCDEF);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0x89ABCDEF, 0x01234567);
+            }
+            assertEquals(success, true, "weakCompareAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x01234567, "weakCompareAndSet int");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSet int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "getAndSet int value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSetAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "getAndSetAcquire int value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndSetRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x89ABCDEF, "getAndSetRelease int value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAdd int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAdd int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndAddRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddRelease int value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOr int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOr int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrRelease int value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAnd int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAnd int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndRelease int value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXor int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXor int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorRelease int value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        int[] array = new int[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "get int value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, 0x89ABCDEF);
+                int x = (int) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "setVolatile int value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, 0x01234567);
+                int x = (int) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "setRelease int value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, 0x89ABCDEF);
+                int x = (int) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "setOpaque int value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 0x01234567, 0x89ABCDEF);
+                assertEquals(r, true, "success compareAndSet int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "success compareAndSet int value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 0x01234567, 0xCAFEBABE);
+                assertEquals(r, false, "failing compareAndSet int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "failing compareAndSet int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 0x89ABCDEF, 0x01234567);
+                assertEquals(r, 0x89ABCDEF, "success compareAndExchange int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "success compareAndExchange int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 0x89ABCDEF, 0xCAFEBABE);
+                assertEquals(r, 0x01234567, "failing compareAndExchange int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "failing compareAndExchange int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 0x01234567, 0x89ABCDEF);
+                assertEquals(r, 0x01234567, "success compareAndExchangeAcquire int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "success compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 0x01234567, 0xCAFEBABE);
+                assertEquals(r, 0x89ABCDEF, "failing compareAndExchangeAcquire int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "failing compareAndExchangeAcquire int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 0x89ABCDEF, 0x01234567);
+                assertEquals(r, 0x89ABCDEF, "success compareAndExchangeRelease int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "success compareAndExchangeRelease int value");
+            }
+
+            {
+                int r = (int) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 0x89ABCDEF, 0xCAFEBABE);
+                assertEquals(r, 0x01234567, "failing compareAndExchangeRelease int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "failing compareAndExchangeRelease int value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 0x01234567, 0x89ABCDEF);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "weakCompareAndSetPlain int value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0x89ABCDEF, 0x01234567);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "weakCompareAndSetAcquire int");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 0x01234567, 0x89ABCDEF);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "weakCompareAndSetRelease int");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 0x89ABCDEF, 0x01234567);
+                }
+                assertEquals(success, true, "weakCompareAndSet int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x01234567, "weakCompareAndSet int");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+                int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndSet int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "getAndSet int value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+                int o = (int) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndSetAcquire int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "getAndSetAcquire int value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+                int o = (int) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndSetRelease int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x89ABCDEF, "getAndSetRelease int value");
+            }
+
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+                int o = (int) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndAdd int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAdd int value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+                int o = (int) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndAddAcquire int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddAcquire int value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+                int o = (int) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, 0x89ABCDEF);
+                assertEquals(o, 0x01234567, "getAndAddRelease int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (int)(0x01234567 + 0x89ABCDEF), "getAndAddRelease int value");
+            }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOr int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOr int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseOrRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 | 0x89ABCDEF), "getAndBitwiseOrRelease int value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAnd int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAnd int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseAndRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 & 0x89ABCDEF), "getAndBitwiseAndRelease int value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXor int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXor int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorAcquire int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorAcquire int value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x01234567);
+
+            int o = (int) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(array, i, 0x89ABCDEF);
+            assertEquals(o, 0x01234567, "getAndBitwiseXorRelease int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (int)(0x01234567 ^ 0x89ABCDEF), "getAndBitwiseXorRelease int value");
+        }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        int[] array = new int[10];
+
+        final int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        int[] array = new int[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    int x = (int) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 0x01234567);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, 0x01234567, 0x89ABCDEF);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    int r = (int) hs.get(am).invokeExact(array, ci, 0x89ABCDEF, 0x01234567);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    int o = (int) hs.get(am).invokeExact(array, ci, 0x01234567);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    int o = (int) hs.get(am).invokeExact(array, ci, 0xCAFEBABE);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+                checkIOOBE(am, () -> {
+                    int o = (int) hs.get(am).invokeExact(array, ci, 0xCAFEBABE);
+                });
+            }
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java
new file mode 100644
index 0000000..6bb35c0
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessLong
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest {
+    static final long static_final_v = 0x0123456789ABCDEFL;
+
+    static long static_v;
+
+    final long final_v = 0x0123456789ABCDEFL;
+
+    long v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessLong.class, "final_v", long.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessLong.class, "v", long.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessLong.class, "static_final_v", long.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessLong.class, "static_v", long.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(long[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessLong::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessLong::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessLong::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessLong::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessLong::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessLong recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "set long value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            long x = (long) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, 0x0123456789ABCDEFL);
+            long x = (long) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            long x = (long) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setOpaque long value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchange long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchange long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchange long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchange long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, 0x0123456789ABCDEFL, "success compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long");
+        }
+
+        // Compare set and get
+        {
+            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSet long value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAdd long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAdd long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddRelease long value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOr long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOr long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrRelease long value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAnd long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAnd long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndRelease long value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXor long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXor long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(recv, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorRelease long value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessLong recv, Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "set long value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(0xCAFEBABECAFEBABEL);
+            long x = (long) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setVolatile long value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(0x0123456789ABCDEFL);
+            long x = (long) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "setRelease long value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(0xCAFEBABECAFEBABEL);
+            long x = (long) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "setOpaque long value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, true, "success compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndSet long value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, false, "failing compareAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndSet long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchange long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchange long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchange long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchange long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            assertEquals(r, 0x0123456789ABCDEFL, "success compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchangeRelease long value");
+        }
+
+        {
+            long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+            assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+            }
+            assertEquals(success, true, "weakCompareAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSet long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSet long value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSetAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetAcquire long value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndSetRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetRelease long value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAdd long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAdd long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndAddRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddRelease long value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOr long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOr long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrRelease long value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAnd long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAnd long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndRelease long value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXor long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXor long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorRelease long value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        long[] array = new long[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "get long value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                long x = (long) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "setVolatile long value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, 0x0123456789ABCDEFL);
+                long x = (long) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "setRelease long value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                long x = (long) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "setOpaque long value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                assertEquals(r, true, "success compareAndSet long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndSet long value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, false, "failing compareAndSet long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndSet long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchange long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchange long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchange long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchange long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                assertEquals(r, 0x0123456789ABCDEFL, "success compareAndExchangeAcquire long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "success compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, 0x0123456789ABCDEFL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "failing compareAndExchangeAcquire long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                assertEquals(r, 0xCAFEBABECAFEBABEL, "success compareAndExchangeRelease long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "success compareAndExchangeRelease long value");
+            }
+
+            {
+                long r = (long) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0xDEADBEEFDEADBEEFL);
+                assertEquals(r, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "failing compareAndExchangeRelease long value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetPlain long value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSetAcquire long");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "weakCompareAndSetRelease long");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                }
+                assertEquals(success, true, "weakCompareAndSet long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0x0123456789ABCDEFL, "weakCompareAndSet long");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndSet long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSet long value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndSetAcquire long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetAcquire long value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndSetRelease long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 0xCAFEBABECAFEBABEL, "getAndSetRelease long value");
+            }
+
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndAdd long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAdd long value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndAddAcquire long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddAcquire long value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+                long o = (long) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+                assertEquals(o, 0x0123456789ABCDEFL, "getAndAddRelease long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (long)(0x0123456789ABCDEFL + 0xCAFEBABECAFEBABEL), "getAndAddRelease long value");
+            }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOr long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOr long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseOrRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL | 0xCAFEBABECAFEBABEL), "getAndBitwiseOrRelease long value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAnd long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAnd long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseAndRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL & 0xCAFEBABECAFEBABEL), "getAndBitwiseAndRelease long value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXor long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXor long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorAcquire long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorAcquire long value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, 0x0123456789ABCDEFL);
+
+            long o = (long) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(array, i, 0xCAFEBABECAFEBABEL);
+            assertEquals(o, 0x0123456789ABCDEFL, "getAndBitwiseXorRelease long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (long)(0x0123456789ABCDEFL ^ 0xCAFEBABECAFEBABEL), "getAndBitwiseXorRelease long value");
+        }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        long[] array = new long[10];
+
+        final int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        long[] array = new long[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    long x = (long) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, 0x0123456789ABCDEFL);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, 0x0123456789ABCDEFL, 0xCAFEBABECAFEBABEL);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    long r = (long) hs.get(am).invokeExact(array, ci, 0xCAFEBABECAFEBABEL, 0x0123456789ABCDEFL);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    long o = (long) hs.get(am).invokeExact(array, ci, 0x0123456789ABCDEFL);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    long o = (long) hs.get(am).invokeExact(array, ci, 0xDEADBEEFDEADBEEFL);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+                checkIOOBE(am, () -> {
+                    long o = (long) hs.get(am).invokeExact(array, ci, 0xDEADBEEFDEADBEEFL);
+                });
+            }
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java
new file mode 100644
index 0000000..45c78bd
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessShort.java
@@ -0,0 +1,990 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessShort
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessShort extends VarHandleBaseTest {
+    static final short static_final_v = (short)0x0123;
+
+    static short static_v;
+
+    final short final_v = (short)0x0123;
+
+    short v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessShort.class, "final_v", short.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessShort.class, "v", short.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessShort.class, "static_final_v", short.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessShort.class, "static_v", short.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(short[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessShort::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessShort::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessShort::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessShort::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessShort::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessShort recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "set short value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, (short)0x4567);
+            short x = (short) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, (short)0x0123);
+            short x = (short) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, (short)0x4567);
+            short x = (short) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "setOpaque short value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, (short)0x0123, (short)0x4567);
+            assertEquals(r, true, "success compareAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "success compareAndSet short value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, (short)0x0123, (short)0x89AB);
+            assertEquals(r, false, "failing compareAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "failing compareAndSet short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, (short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchange short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "success compareAndExchange short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, (short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchange short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "failing compareAndExchange short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, (short)0x0123, (short)0x4567);
+            assertEquals(r, (short)0x0123, "success compareAndExchangeAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "success compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, (short)0x0123, (short)0x89AB);
+            assertEquals(r, (short)0x4567, "failing compareAndExchangeAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "failing compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, (short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchangeRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "success compareAndExchangeRelease short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, (short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchangeRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "failing compareAndExchangeRelease short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, (short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, (short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, (short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, (short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x0123, "weakCompareAndSet short");
+        }
+
+        // Compare set and get
+        {
+            short o = (short) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)0x4567, "getAndSet short value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAdd short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAdd short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddRelease short value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOr short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOr short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrRelease short value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAnd short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAnd short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndRelease short value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXor short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXor short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(recv, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorRelease short value");
+        }
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessShort recv, Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x0123, "set short value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact((short)0x4567);
+            short x = (short) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, (short)0x4567, "setVolatile short value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact((short)0x0123);
+            short x = (short) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, (short)0x0123, "setRelease short value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact((short)0x4567);
+            short x = (short) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, (short)0x4567, "setOpaque short value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact((short)0x0123, (short)0x4567);
+            assertEquals(r, true, "success compareAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "success compareAndSet short value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact((short)0x0123, (short)0x89AB);
+            assertEquals(r, false, "failing compareAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "failing compareAndSet short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact((short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchange short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x0123, "success compareAndExchange short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact((short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchange short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x0123, "failing compareAndExchange short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact((short)0x0123, (short)0x4567);
+            assertEquals(r, (short)0x0123, "success compareAndExchangeAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "success compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact((short)0x0123, (short)0x89AB);
+            assertEquals(r, (short)0x4567, "failing compareAndExchangeAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "failing compareAndExchangeAcquire short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact((short)0x4567, (short)0x0123);
+            assertEquals(r, (short)0x4567, "success compareAndExchangeRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x0123, "success compareAndExchangeRelease short value");
+        }
+
+        {
+            short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact((short)0x4567, (short)0x89AB);
+            assertEquals(r, (short)0x0123, "failing compareAndExchangeRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x0123, "failing compareAndExchangeRelease short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact((short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact((short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact((short)0x0123, (short)0x4567);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact((short)0x4567, (short)0x0123);
+            }
+            assertEquals(success, true, "weakCompareAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x0123, "weakCompareAndSet short");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_SET).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSet short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "getAndSet short value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSetAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "getAndSetAcquire short value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndSetRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)0x4567, "getAndSetRelease short value");
+        }
+
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_ADD).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAdd short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAdd short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndAddRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddRelease short value");
+        }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOr short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOr short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrRelease short value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAnd short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAnd short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndRelease short value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXor short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXor short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact((short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact((short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorRelease short value");
+        }
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        short[] array = new short[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "get short value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, (short)0x4567);
+                short x = (short) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "setVolatile short value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, (short)0x0123);
+                short x = (short) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "setRelease short value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, (short)0x4567);
+                short x = (short) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "setOpaque short value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, (short)0x0123, (short)0x4567);
+                assertEquals(r, true, "success compareAndSet short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "success compareAndSet short value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, (short)0x0123, (short)0x89AB);
+                assertEquals(r, false, "failing compareAndSet short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "failing compareAndSet short value");
+            }
+
+            {
+                short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, (short)0x4567, (short)0x0123);
+                assertEquals(r, (short)0x4567, "success compareAndExchange short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "success compareAndExchange short value");
+            }
+
+            {
+                short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, (short)0x4567, (short)0x89AB);
+                assertEquals(r, (short)0x0123, "failing compareAndExchange short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "failing compareAndExchange short value");
+            }
+
+            {
+                short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, (short)0x0123, (short)0x4567);
+                assertEquals(r, (short)0x0123, "success compareAndExchangeAcquire short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "success compareAndExchangeAcquire short value");
+            }
+
+            {
+                short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, (short)0x0123, (short)0x89AB);
+                assertEquals(r, (short)0x4567, "failing compareAndExchangeAcquire short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "failing compareAndExchangeAcquire short value");
+            }
+
+            {
+                short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, (short)0x4567, (short)0x0123);
+                assertEquals(r, (short)0x4567, "success compareAndExchangeRelease short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "success compareAndExchangeRelease short value");
+            }
+
+            {
+                short r = (short) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, (short)0x4567, (short)0x89AB);
+                assertEquals(r, (short)0x0123, "failing compareAndExchangeRelease short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "failing compareAndExchangeRelease short value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, (short)0x0123, (short)0x4567);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "weakCompareAndSetPlain short value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, (short)0x4567, (short)0x0123);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "weakCompareAndSetAcquire short");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, (short)0x0123, (short)0x4567);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "weakCompareAndSetRelease short");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, (short)0x4567, (short)0x0123);
+                }
+                assertEquals(success, true, "weakCompareAndSet short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x0123, "weakCompareAndSet short");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+                short o = (short) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndSet short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "getAndSet short value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+                short o = (short) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndSetAcquire short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "getAndSetAcquire short value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+                short o = (short) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndSetRelease short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)0x4567, "getAndSetRelease short value");
+            }
+
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+                short o = (short) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndAdd short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAdd short value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+                short o = (short) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndAddAcquire short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddAcquire short value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+                short o = (short) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, (short)0x4567);
+                assertEquals(o, (short)0x0123, "getAndAddRelease short");
+                short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, (short)((short)0x0123 + (short)0x4567), "getAndAddRelease short value");
+            }
+
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOr short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOr short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseOrRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 | (short)0x4567), "getAndBitwiseOrRelease short value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAnd short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAnd short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseAndRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 & (short)0x4567), "getAndBitwiseAndRelease short value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXor short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXor short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorAcquire short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorAcquire short value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, (short)0x0123);
+
+            short o = (short) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(array, i, (short)0x4567);
+            assertEquals(o, (short)0x0123, "getAndBitwiseXorRelease short");
+            short x = (short) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, (short)((short)0x0123 ^ (short)0x4567), "getAndBitwiseXorRelease short value");
+        }
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        short[] array = new short[10];
+
+        final int i = 0;
+
+
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        short[] array = new short[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    short x = (short) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, (short)0x0123);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, (short)0x0123, (short)0x4567);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    short r = (short) hs.get(am).invokeExact(array, ci, (short)0x4567, (short)0x0123);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    short o = (short) hs.get(am).invokeExact(array, ci, (short)0x0123);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    short o = (short) hs.get(am).invokeExact(array, ci, (short)0x89AB);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+                checkIOOBE(am, () -> {
+                    short o = (short) hs.get(am).invokeExact(array, ci, (short)0x89AB);
+                });
+            }
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java
new file mode 100644
index 0000000..36f6357
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccessString
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest {
+    static final String static_final_v = "foo";
+
+    static String static_v;
+
+    final String final_v = "foo";
+
+    String v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessString.class, "final_v", String.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccessString.class, "v", String.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessString.class, "static_final_v", String.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccessString.class, "static_v", String.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(String[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessString::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessString::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccessString::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, "foo");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, "bar");
+            String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, "foo");
+            String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, "bar");
+            String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact(recv, "foo");
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, "foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, "foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchange String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "success compareAndExchange String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchange String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "failing compareAndExchange String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, "foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, "foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, "bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, "bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "bar", "weakCompareAndSetPlain String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "weakCompareAndSet String");
+        }
+
+        // Compare set and get
+        {
+            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "bar");
+            assertEquals(o, "foo", "getAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "bar", "getAndSet String value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                String r = (String) hs.get(am).invokeExact(recv, "foo");
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                String r = (String) hs.get(am).invokeExact(recv, "foo");
+            });
+        }
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact("foo");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "set String value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact("bar");
+            String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, "bar", "setVolatile String value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact("foo");
+            String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, "foo", "setRelease String value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact("bar");
+            String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, "bar", "setOpaque String value");
+        }
+
+        hs.get(TestAccessMode.SET).invokeExact("foo");
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact("foo", "bar");
+            assertEquals(r, true, "success compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "success compareAndSet String value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact("foo", "baz");
+            assertEquals(r, false, "failing compareAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "failing compareAndSet String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchange String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "success compareAndExchange String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchange String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "failing compareAndExchange String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact("foo", "bar");
+            assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact("foo", "baz");
+            assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact("bar", "foo");
+            assertEquals(r, "bar", "success compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+        }
+
+        {
+            String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact("bar", "baz");
+            assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "weakCompareAndSetPlain String value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar");
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "weakCompareAndSetRelease String");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("bar", "foo");
+            }
+            assertEquals(success, true, "weakCompareAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "weakCompareAndSet String");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact("foo");
+
+            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar");
+            assertEquals(o, "foo", "getAndSet String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "getAndSet String value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact("foo");
+
+            String o = (String) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact("bar");
+            assertEquals(o, "foo", "getAndSetAcquire String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "getAndSetAcquire String value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact("foo");
+
+            String o = (String) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact("bar");
+            assertEquals(o, "foo", "getAndSetRelease String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "bar", "getAndSetRelease String value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                String r = (String) hs.get(am).invokeExact("foo");
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                String r = (String) hs.get(am).invokeExact("foo");
+            });
+        }
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        String[] array = new String[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "get String value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, "bar");
+                String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, "bar", "setVolatile String value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, "foo");
+                String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, "foo", "setRelease String value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, "bar");
+                String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, "bar", "setOpaque String value");
+            }
+
+            hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, "foo", "bar");
+                assertEquals(r, true, "success compareAndSet String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "success compareAndSet String value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, "foo", "baz");
+                assertEquals(r, false, "failing compareAndSet String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "failing compareAndSet String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchange String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "success compareAndExchange String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchange String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "failing compareAndExchange String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, "foo", "bar");
+                assertEquals(r, "foo", "success compareAndExchangeAcquire String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "success compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, "foo", "baz");
+                assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "failing compareAndExchangeAcquire String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, "bar", "foo");
+                assertEquals(r, "bar", "success compareAndExchangeRelease String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "success compareAndExchangeRelease String value");
+            }
+
+            {
+                String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, "bar", "baz");
+                assertEquals(r, "foo", "failing compareAndExchangeRelease String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "failing compareAndExchangeRelease String value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "weakCompareAndSetPlain String value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "weakCompareAndSetAcquire String");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar");
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "weakCompareAndSetRelease String");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "bar", "foo");
+                }
+                assertEquals(success, true, "weakCompareAndSet String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "weakCompareAndSet String");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
+
+                String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "bar");
+                assertEquals(o, "foo", "getAndSet String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "getAndSet String value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
+
+                String o = (String) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, "bar");
+                assertEquals(o, "foo", "getAndSetAcquire String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "getAndSetAcquire String value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
+
+                String o = (String) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, "bar");
+                assertEquals(o, "foo", "getAndSetRelease String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "bar", "getAndSetRelease String value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        String[] array = new String[10];
+
+        final int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                String o = (String) hs.get(am).invokeExact(array, i, "foo");
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                String o = (String) hs.get(am).invokeExact(array, i, "foo");
+            });
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        String[] array = new String[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    String x = (String) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, "foo");
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, "foo", "bar");
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    String r = (String) hs.get(am).invokeExact(array, ci, "bar", "foo");
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    String o = (String) hs.get(am).invokeExact(array, ci, "foo");
+                });
+            }
+
+
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java
new file mode 100644
index 0000000..63e8042
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeBoolean.java
@@ -0,0 +1,2911 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeBoolean
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeBoolean
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeBoolean extends VarHandleBaseTest {
+    static final boolean static_final_v = true;
+
+    static boolean static_v = true;
+
+    final boolean final_v = true;
+
+    boolean v = true;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeBoolean.class, "final_v", boolean.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeBoolean.class, "v", boolean.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeBoolean.class, "static_final_v", boolean.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeBoolean.class, "static_v", boolean.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeBoolean::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeBoolean::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.get();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, true, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, true, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, true, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean x = (boolean) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, true, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, true, true, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.compareAndExchange(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.compareAndExchange(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchange(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchange(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.compareAndExchange(0, true, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchange(recv, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchange(recv, true, true, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.compareAndExchangeAcquire(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(0, true, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchangeAcquire(recv, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, true, true, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.compareAndExchangeRelease(null, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(Void.class, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, true, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(0, true, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchangeRelease(recv, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, true, true, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndSet(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndSet(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndSet(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSet(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSet(recv, true, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndSetAcquire(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndSetAcquire(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSetAcquire(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSetAcquire(recv, true, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndSetRelease(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndSetRelease(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndSetRelease(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSetRelease(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSetRelease(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseOr(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOr(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOrAcquire(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOr(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseAnd(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAnd(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAndAcquire(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAnd(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseXor(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXor(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXorAcquire(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, true, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(null, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(Void.class, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(0, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXor(recv, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, true, Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeBoolean recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeBoolean.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, boolean.class)).
+                    invokeExact(Void.class, true);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, boolean.class)).
+                    invokeExact(0, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)).
+                    invokeExact(recv, true, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class, boolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null, true, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, boolean.class, boolean.class)).
+                    invokeExact(Void.class, true, true);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class, boolean.class)).
+                    invokeExact(recv, Void.class, true);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)).
+                    invokeExact(recv, true, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , boolean.class, boolean.class)).
+                    invokeExact(0, true, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class, boolean.class, Class.class)).
+                    invokeExact(recv, true, true, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class, boolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null, true, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, boolean.class, boolean.class)).
+                    invokeExact(Void.class, true, true);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class, boolean.class)).
+                    invokeExact(recv, Void.class, true);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class, Class.class)).
+                    invokeExact(recv, true, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class , boolean.class, boolean.class)).
+                    invokeExact(0, true, true);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeBoolean.class , boolean.class, boolean.class)).
+                    invokeExact(recv, true, true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class , boolean.class, boolean.class)).
+                    invokeExact(recv, true, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class, boolean.class, Class.class)).
+                    invokeExact(recv, true, true, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, boolean.class)).
+                    invokeExact(Void.class, true);
+            });
+            checkWMTE(() -> { // value reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, boolean.class)).
+                    invokeExact(0, true);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact(recv, true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact(recv, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact(recv, true, Void.class);
+            });
+        }
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkNPE(() -> { // null receiver
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact((VarHandleTestMethodTypeBoolean) null, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, boolean.class)).
+                    invokeExact(Void.class, true);
+            });
+            checkWMTE(() -> { // value reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, boolean.class)).
+                    invokeExact(0, true);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact(recv, true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact(recv, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeBoolean.class, boolean.class)).
+                    invokeExact(recv, true, Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(true, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(true, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(true, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(true, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(true, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(true, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(true, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(true, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(true, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(true, true, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchange(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchange(true, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchange(true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchange(true, true, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(true, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchangeAcquire(true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchangeAcquire(true, true, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(true, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchangeRelease(true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchangeRelease(true, true, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSet(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSet(true, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSetAcquire(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSetAcquire(true, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSetRelease(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSetRelease(true, Void.class);
+        });
+
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOr(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOr(true, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOrAcquire(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(true, Void.class);
+        });
+
+
+        // GetAndBitwiseOrReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOrRelease(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(true, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAnd(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAnd(true, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAndAcquire(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(true, Void.class);
+        });
+
+
+        // GetAndBitwiseAndReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAndRelease(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(true, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXor(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXor(true, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXorAcquire(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(true, Void.class);
+        });
+
+
+        // GetAndBitwiseXorReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXorRelease(true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(true, Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, boolean.class, Class.class)).
+                    invokeExact(true, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, boolean.class)).
+                    invokeExact(Void.class, true);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, boolean.class, Class.class)).
+                    invokeExact(true, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, boolean.class, boolean.class, Class.class)).
+                    invokeExact(true, true, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, boolean.class)).
+                    invokeExact(Void.class, true);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean.class, Class.class)).
+                    invokeExact(true, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, boolean.class, boolean.class)).
+                    invokeExact(true, true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean.class, boolean.class)).
+                    invokeExact(true, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean.class, boolean.class, Class.class)).
+                    invokeExact(true, true, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, boolean.class)).
+                    invokeExact(true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean.class)).
+                    invokeExact(true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean.class, Class.class)).
+                    invokeExact(true, Void.class);
+            });
+        }
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, boolean.class)).
+                    invokeExact(true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean.class)).
+                    invokeExact(true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean.class, Class.class)).
+                    invokeExact(true, Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        boolean[] array = new boolean[10];
+        Arrays.fill(array, true);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.get();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, true, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, true, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, true, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, true, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, true, true, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, true, true);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, true, true, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.compareAndExchange(null, 0, true, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.compareAndExchange(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.compareAndExchange(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.compareAndExchange(array, Void.class, true, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchange(array, 0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchange(array, 0, true, true, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.compareAndExchangeAcquire(null, 0, true, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, Void.class, true, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchangeAcquire(array, 0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, true, true, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean x = (boolean) vh.compareAndExchangeRelease(null, 0, true, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(Void.class, 0, true, true);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, Void.class, true);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, true, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(0, 0, true, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, Void.class, true, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, true, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.compareAndExchangeRelease(array, 0, true, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, true, true, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndSet(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndSet(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            boolean x = (boolean) vh.getAndSet(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndSet(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSet(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSet(array, 0, true, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndSetAcquire(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndSetAcquire(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndSetAcquire(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSetAcquire(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, true, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndSetRelease(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndSetRelease(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            boolean x = (boolean) vh.getAndSetRelease(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndSetRelease(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndSetRelease(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseOr(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseOr(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOr(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOr(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOrAcquire(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseOrRelease(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseAnd(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAnd(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAndAcquire(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseAndRelease(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseXor(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseXor(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXor(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXor(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXorAcquire(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, 0, true, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(null, 0, true);
+        });
+        checkCCE(() -> { // array reference class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(Void.class, 0, true);
+        });
+        checkWMTE(() -> { // value reference class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(0, 0, true);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, Void.class, true);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(array, 0, true);
+        });
+        checkWMTE(() -> { // primitive class
+            int x = (int) vh.getAndBitwiseXorRelease(array, 0, true);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean x = (boolean) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, 0, true, Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        boolean[] array = new boolean[10];
+        Arrays.fill(array, true);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class)).
+                    invokeExact((boolean[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact((boolean[]) null, 0, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, boolean.class)).
+                    invokeExact(Void.class, 0, true);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, boolean.class)).
+                    invokeExact(0, 0, true);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, boolean[].class, Class.class, boolean.class)).
+                    invokeExact(array, Void.class, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, boolean[].class, int.class, Class.class)).
+                    invokeExact(array, 0, true, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, boolean.class)).
+                    invokeExact((boolean[]) null, 0, true, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, boolean.class, boolean.class)).
+                    invokeExact(Void.class, 0, true, true);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class, boolean.class)).
+                    invokeExact(array, 0, Void.class, true);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, Class.class)).
+                    invokeExact(array, 0, true, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, boolean.class, boolean.class)).
+                    invokeExact(0, 0, true, true);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class, boolean.class, boolean.class)).
+                    invokeExact(array, Void.class, true, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, boolean.class, Class.class)).
+                    invokeExact(array, 0, true, true, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, boolean.class)).
+                    invokeExact((boolean[]) null, 0, true, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, boolean.class, boolean.class)).
+                    invokeExact(Void.class, 0, true, true);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class, boolean.class)).
+                    invokeExact(array, 0, Void.class, true);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, Class.class)).
+                    invokeExact(array, 0, true, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, boolean.class, boolean.class)).
+                    invokeExact(0, 0, true, true);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class, boolean.class, boolean.class)).
+                    invokeExact(array, Void.class, true, true);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class, boolean.class, boolean.class)).
+                    invokeExact(array, 0, true, true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class, boolean.class, boolean.class)).
+                    invokeExact(array, 0, true, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, boolean.class, Class.class)).
+                    invokeExact(array, 0, true, true, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact((boolean[]) null, 0, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, boolean.class)).
+                    invokeExact(Void.class, 0, true);
+            });
+            checkWMTE(() -> { // value reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, boolean.class)).
+                    invokeExact(0, 0, true);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class, boolean.class)).
+                    invokeExact(array, Void.class, true);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact(array, 0, true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact(array, 0, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, Class.class)).
+                    invokeExact(array, 0, true, Void.class);
+            });
+        }
+
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact((boolean[]) null, 0, true);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, boolean.class)).
+                    invokeExact(Void.class, 0, true);
+            });
+            checkWMTE(() -> { // value reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, boolean.class)).
+                    invokeExact(0, 0, true);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, Class.class, boolean.class)).
+                    invokeExact(array, Void.class, true);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact(array, 0, true);
+            });
+            checkWMTE(() -> { // primitive class
+                int x = (int) hs.get(am, methodType(int.class, boolean[].class, int.class, boolean.class)).
+                    invokeExact(array, 0, true);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, boolean[].class, int.class, boolean.class, Class.class)).
+                    invokeExact(array, 0, true, Void.class);
+            });
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java
new file mode 100644
index 0000000..8fddf7f
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeByte.java
@@ -0,0 +1,3257 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeByte
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeByte
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeByte extends VarHandleBaseTest {
+    static final byte static_final_v = (byte)0x01;
+
+    static byte static_v = (byte)0x01;
+
+    final byte final_v = (byte)0x01;
+
+    byte v = (byte)0x01;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeByte.class, "final_v", byte.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeByte.class, "v", byte.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeByte.class, "static_final_v", byte.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeByte.class, "static_v", byte.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeByte::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeByte::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.get();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            byte x = (byte) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.compareAndExchange(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.compareAndExchange(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchange(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchange(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.compareAndExchange(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchange(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.compareAndExchangeAcquire(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.compareAndExchangeAcquire(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchangeAcquire(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.compareAndExchangeRelease(null, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.compareAndExchangeRelease(Void.class, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchangeRelease(recv, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchangeRelease(recv, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.compareAndExchangeRelease(0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchangeRelease(recv, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndSet(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndSet(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndSet(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSet(recv, (byte)0x01, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndSetAcquire(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndSetAcquire(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndSetAcquire(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSetAcquire(recv, (byte)0x01, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndSetRelease(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndSetRelease(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndSetRelease(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSetRelease(recv, (byte)0x01, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndAdd(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndAdd(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndAdd(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAdd(recv, (byte)0x01, Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndAddAcquire(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndAddAcquire(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndAddAcquire(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAddAcquire(recv, (byte)0x01, Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndAddRelease(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndAddRelease(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndAddRelease(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAddRelease(recv, (byte)0x01, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseOr(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseOr(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseOr(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOr(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseOrAcquire(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOrAcquire(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseOrRelease(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseOr(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseOr(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOr(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseAnd(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseAnd(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseAnd(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAnd(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseAndAcquire(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAndAcquire(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseAndRelease(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseAnd(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseAnd(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAnd(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseXor(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseXor(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseXor(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXor(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseXorAcquire(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXorAcquire(recv, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.getAndBitwiseXorRelease(null, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            byte x = (byte) vh.getAndBitwiseXor(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            byte x = (byte) vh.getAndBitwiseXor(0, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXor(recv, (byte)0x01, Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeByte recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeByte.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, byte.class)).
+                    invokeExact(0, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)).
+                    invokeExact(recv, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class, byte.class, byte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null, (byte)0x01, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, byte.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class, Class.class, byte.class)).
+                    invokeExact(recv, Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)).
+                    invokeExact(recv, (byte)0x01, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , byte.class, byte.class)).
+                    invokeExact(0, (byte)0x01, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class, byte.class, byte.class, Class.class)).
+                    invokeExact(recv, (byte)0x01, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class, byte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null, (byte)0x01, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, byte.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // expected reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class, byte.class)).
+                    invokeExact(recv, Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // actual reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class, Class.class)).
+                    invokeExact(recv, (byte)0x01, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class , byte.class, byte.class)).
+                    invokeExact(0, (byte)0x01, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeByte.class , byte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class , byte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class, byte.class, Class.class)).
+                    invokeExact(recv, (byte)0x01, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, byte.class)).
+                    invokeExact(0, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, byte.class)).
+                    invokeExact(0, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkNPE(() -> { // null receiver
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact((VarHandleTestMethodTypeByte) null, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, byte.class)).
+                    invokeExact(0, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, VarHandleTestMethodTypeByte.class, byte.class)).
+                    invokeExact(recv, (byte)0x01, Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set((byte)0x01, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile((byte)0x01, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque((byte)0x01, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease((byte)0x01, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet((byte)0x01, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain((byte)0x01, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet((byte)0x01, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire((byte)0x01, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease((byte)0x01, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchange(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchange((byte)0x01, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange((byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange((byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchange((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchangeAcquire((byte)0x01, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire((byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire((byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchangeAcquire((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchangeRelease(Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchangeRelease((byte)0x01, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease((byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease((byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchangeRelease((byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSet((byte)0x01, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSetAcquire((byte)0x01, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSetRelease((byte)0x01, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAdd((byte)0x01, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAddAcquire((byte)0x01, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAddRelease((byte)0x01, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOr(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOr((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOrAcquire((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseOrReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOrRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOrRelease((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAnd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAnd((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAndAcquire((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAndReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAndRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAndRelease((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXor(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXor((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXorAcquire((byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXorReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXorRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease((byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease((byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXorRelease((byte)0x01, Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, byte.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, byte.class)).
+                    invokeExact(Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // actual reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte.class, byte.class)).
+                    invokeExact((byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte.class, byte.class)).
+                    invokeExact((byte)0x01, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte.class)).
+                    invokeExact((byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte.class)).
+                    invokeExact((byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte.class)).
+                    invokeExact((byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte.class)).
+                    invokeExact((byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte.class)).
+                    invokeExact((byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte.class)).
+                    invokeExact((byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte.class, Class.class)).
+                    invokeExact((byte)0x01, Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        byte[] array = new byte[10];
+        Arrays.fill(array, (byte)0x01);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.get();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.compareAndExchange(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.compareAndExchange(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchange(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchange(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.compareAndExchange(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.compareAndExchange(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchange(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.compareAndExchangeAcquire(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.compareAndExchangeAcquire(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.compareAndExchangeAcquire(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchangeAcquire(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            byte x = (byte) vh.compareAndExchangeRelease(null, 0, (byte)0x01, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.compareAndExchangeRelease(Void.class, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // expected reference class
+            byte x = (byte) vh.compareAndExchangeRelease(array, 0, Void.class, (byte)0x01);
+        });
+        checkWMTE(() -> { // actual reference class
+            byte x = (byte) vh.compareAndExchangeRelease(array, 0, (byte)0x01, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.compareAndExchangeRelease(0, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.compareAndExchangeRelease(array, Void.class, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, (byte)0x01, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, (byte)0x01, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.compareAndExchangeRelease(array, 0, (byte)0x01, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndSet(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndSet(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            byte x = (byte) vh.getAndSet(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndSet(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSet(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndSetAcquire(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndSetAcquire(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            byte x = (byte) vh.getAndSetAcquire(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndSetAcquire(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSetAcquire(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndSetRelease(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndSetRelease(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            byte x = (byte) vh.getAndSetRelease(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndSetRelease(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndSetRelease(array, 0, (byte)0x01, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndAdd(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndAdd(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndAdd(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndAdd(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAdd(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndAddAcquire(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndAddAcquire(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndAddAcquire(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndAddAcquire(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAddAcquire(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndAddRelease(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndAddRelease(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndAddRelease(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndAddRelease(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndAddRelease(array, 0, (byte)0x01, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseOr(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseOr(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOr(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseOr(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseOr(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOr(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseOrAcquire(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseOrAcquire(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOrAcquire(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseOrRelease(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseOrRelease(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseOrRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseOrRelease(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseOrRelease(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseOrRelease(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseAnd(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseAnd(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAnd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseAnd(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseAnd(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAnd(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseAndAcquire(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseAndAcquire(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAndAcquire(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseAndRelease(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseAndRelease(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseAndRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseAndRelease(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseAndRelease(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseAndRelease(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseXor(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseXor(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXor(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseXor(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseXor(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXor(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseXorAcquire(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseXorAcquire(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXorAcquire(array, 0, (byte)0x01, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            byte x = (byte) vh.getAndBitwiseXorRelease(null, 0, (byte)0x01);
+        });
+        checkCCE(() -> { // array reference class
+            byte x = (byte) vh.getAndBitwiseXorRelease(Void.class, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // value reference class
+            byte x = (byte) vh.getAndBitwiseXorRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            byte x = (byte) vh.getAndBitwiseXorRelease(0, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // index reference class
+            byte x = (byte) vh.getAndBitwiseXorRelease(array, Void.class, (byte)0x01);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(array, 0, (byte)0x01);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, 0, (byte)0x01);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            byte x = (byte) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            byte x = (byte) vh.getAndBitwiseXorRelease(array, 0, (byte)0x01, Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        byte[] array = new byte[10];
+        Arrays.fill(array, (byte)0x01);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class)).
+                    invokeExact((byte[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, byte[].class, int.class, byte.class)).
+                    invokeExact((byte[]) null, 0, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, byte.class)).
+                    invokeExact(Void.class, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, byte.class)).
+                    invokeExact(0, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, byte[].class, Class.class, byte.class)).
+                    invokeExact(array, Void.class, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, byte[].class, int.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, byte.class, byte.class)).
+                    invokeExact((byte[]) null, 0, (byte)0x01, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, byte.class, byte.class)).
+                    invokeExact(Void.class, 0, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, Class.class, byte.class)).
+                    invokeExact(array, 0, Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, byte.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, byte.class, byte.class)).
+                    invokeExact(0, 0, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, byte[].class, Class.class, byte.class, byte.class)).
+                    invokeExact(array, Void.class, (byte)0x01, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, byte.class, byte.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class, byte.class)).
+                    invokeExact((byte[]) null, 0, (byte)0x01, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class, byte.class, byte.class)).
+                    invokeExact(Void.class, 0, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // expected reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class, byte.class)).
+                    invokeExact(array, 0, Void.class, (byte)0x01);
+            });
+            checkWMTE(() -> { // actual reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class, byte.class, byte.class)).
+                    invokeExact(0, 0, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // index reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class, byte.class, byte.class)).
+                    invokeExact(array, Void.class, (byte)0x01, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class, byte.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, byte.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class, byte.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class)).
+                    invokeExact((byte[]) null, 0, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class, byte.class)).
+                    invokeExact(Void.class, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class, byte.class)).
+                    invokeExact(0, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // index reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class, byte.class)).
+                    invokeExact(array, Void.class, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class)).
+                    invokeExact((byte[]) null, 0, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class, byte.class)).
+                    invokeExact(Void.class, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class, byte.class)).
+                    invokeExact(0, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // index reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class, byte.class)).
+                    invokeExact(array, Void.class, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class)).
+                    invokeExact((byte[]) null, 0, (byte)0x01);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, Class.class, int.class, byte.class)).
+                    invokeExact(Void.class, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // value reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                byte x = (byte) hs.get(am, methodType(byte.class, int.class, int.class, byte.class)).
+                    invokeExact(0, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // index reference class
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, Class.class, byte.class)).
+                    invokeExact(array, Void.class, (byte)0x01);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, byte[].class, int.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, byte[].class, int.class, byte.class)).
+                    invokeExact(array, 0, (byte)0x01);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                byte x = (byte) hs.get(am, methodType(byte.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                byte x = (byte) hs.get(am, methodType(byte.class, byte[].class, int.class, byte.class, Class.class)).
+                    invokeExact(array, 0, (byte)0x01, Void.class);
+            });
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java
new file mode 100644
index 0000000..89cd895
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeChar.java
@@ -0,0 +1,3257 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeChar
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeChar
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeChar extends VarHandleBaseTest {
+    static final char static_final_v = '\u0123';
+
+    static char static_v = '\u0123';
+
+    final char final_v = '\u0123';
+
+    char v = '\u0123';
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeChar.class, "final_v", char.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeChar.class, "v", char.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeChar.class, "static_final_v", char.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeChar.class, "static_v", char.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(char[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeChar::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeChar::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.get();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, '\u0123', Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, '\u0123', Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            char x = (char) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, '\u0123', Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.compareAndExchange(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.compareAndExchange(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchange(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchange(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.compareAndExchange(0, '\u0123', '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchange(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.compareAndExchangeAcquire(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.compareAndExchangeAcquire(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchangeAcquire(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchangeAcquire(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.compareAndExchangeAcquire(0, '\u0123', '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchangeAcquire(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.compareAndExchangeRelease(null, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.compareAndExchangeRelease(Void.class, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchangeRelease(recv, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchangeRelease(recv, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.compareAndExchangeRelease(0, '\u0123', '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchangeRelease(recv, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndSet(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndSet(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndSet(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSet(recv, '\u0123', Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndSetAcquire(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndSetAcquire(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndSetAcquire(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSetAcquire(recv, '\u0123', Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndSetRelease(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndSetRelease(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndSetRelease(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSetRelease(recv, '\u0123', Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndAdd(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndAdd(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndAdd(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAdd(recv, '\u0123', Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndAddAcquire(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndAddAcquire(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndAddAcquire(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAddAcquire(recv, '\u0123', Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndAddRelease(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndAddRelease(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndAddRelease(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAddRelease(recv, '\u0123', Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseOr(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseOr(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseOr(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOr(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseOrAcquire(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseOrAcquire(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOrAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseOrAcquire(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOrAcquire(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseOrRelease(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseOr(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseOr(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOr(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseAnd(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseAnd(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseAnd(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAnd(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseAndAcquire(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseAndAcquire(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAndAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseAndAcquire(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAndAcquire(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseAndRelease(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseAnd(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseAnd(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAnd(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseXor(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseXor(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseXor(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXor(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseXorAcquire(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseXorAcquire(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXorAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseXorAcquire(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXorAcquire(recv, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.getAndBitwiseXorRelease(null, '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            char x = (char) vh.getAndBitwiseXor(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            char x = (char) vh.getAndBitwiseXor(0, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXor(recv, '\u0123', Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeChar recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeChar.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, char.class)).
+                    invokeExact(Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, char.class)).
+                    invokeExact(0, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)).
+                    invokeExact(recv, '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class, char.class, char.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null, '\u0123', '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, char.class, char.class)).
+                    invokeExact(Void.class, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class, Class.class, char.class)).
+                    invokeExact(recv, Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)).
+                    invokeExact(recv, '\u0123', Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , char.class, char.class)).
+                    invokeExact(0, '\u0123', '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class, char.class, char.class, Class.class)).
+                    invokeExact(recv, '\u0123', '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class, char.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null, '\u0123', '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, char.class, char.class)).
+                    invokeExact(Void.class, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // expected reference class
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class, char.class)).
+                    invokeExact(recv, Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // actual reference class
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class, Class.class)).
+                    invokeExact(recv, '\u0123', Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class , char.class, char.class)).
+                    invokeExact(0, '\u0123', '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeChar.class , char.class, char.class)).
+                    invokeExact(recv, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class , char.class, char.class)).
+                    invokeExact(recv, '\u0123', '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class, char.class, Class.class)).
+                    invokeExact(recv, '\u0123', '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, char.class)).
+                    invokeExact(Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, char.class)).
+                    invokeExact(0, '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, char.class)).
+                    invokeExact(Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, char.class)).
+                    invokeExact(0, '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkNPE(() -> { // null receiver
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact((VarHandleTestMethodTypeChar) null, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, char.class)).
+                    invokeExact(Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, char.class)).
+                    invokeExact(0, '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, VarHandleTestMethodTypeChar.class, char.class)).
+                    invokeExact(recv, '\u0123', Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            char x = (char) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set('\u0123', Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile('\u0123', Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque('\u0123', Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease('\u0123', Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet('\u0123', Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet('\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain('\u0123', Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain('\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet('\u0123', Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet('\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire('\u0123', Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire('\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease('\u0123', Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease('\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchange(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchange('\u0123', Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange('\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange('\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchange('\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchangeAcquire(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchangeAcquire('\u0123', Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire('\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire('\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchangeAcquire('\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchangeRelease(Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchangeRelease('\u0123', Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease('\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease('\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchangeRelease('\u0123', '\u0123', Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSet('\u0123', Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSetAcquire('\u0123', Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSetRelease('\u0123', Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAdd('\u0123', Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAddAcquire('\u0123', Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAddRelease('\u0123', Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOr(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOr('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOrAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOrAcquire('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseOrReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOrRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOrRelease('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAnd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAnd('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAndAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAndAcquire('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAndReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAndRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAndRelease('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXor(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXor('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXorAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXorAcquire('\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXorReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXorRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease('\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease('\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXorRelease('\u0123', Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, char.class, Class.class)).
+                    invokeExact('\u0123', Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, char.class)).
+                    invokeExact(Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, char.class, Class.class)).
+                    invokeExact('\u0123', Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, char.class, char.class, Class.class)).
+                    invokeExact('\u0123', '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, char.class)).
+                    invokeExact(Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // actual reference class
+                char x = (char) hs.get(am, methodType(char.class, char.class, Class.class)).
+                    invokeExact('\u0123', Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char.class, char.class)).
+                    invokeExact('\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char.class, char.class)).
+                    invokeExact('\u0123', '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char.class, char.class, Class.class)).
+                    invokeExact('\u0123', '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char.class)).
+                    invokeExact('\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char.class)).
+                    invokeExact('\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char.class, Class.class)).
+                    invokeExact('\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char.class)).
+                    invokeExact('\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char.class)).
+                    invokeExact('\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char.class, Class.class)).
+                    invokeExact('\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char.class)).
+                    invokeExact('\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char.class)).
+                    invokeExact('\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char.class, Class.class)).
+                    invokeExact('\u0123', Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        char[] array = new char[10];
+        Arrays.fill(array, '\u0123');
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.get();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, '\u0123', Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.compareAndExchange(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.compareAndExchange(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchange(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchange(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.compareAndExchange(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.compareAndExchange(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchange(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.compareAndExchangeAcquire(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.compareAndExchangeAcquire(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchangeAcquire(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchangeAcquire(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.compareAndExchangeAcquire(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.compareAndExchangeAcquire(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchangeAcquire(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            char x = (char) vh.compareAndExchangeRelease(null, 0, '\u0123', '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.compareAndExchangeRelease(Void.class, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // expected reference class
+            char x = (char) vh.compareAndExchangeRelease(array, 0, Void.class, '\u0123');
+        });
+        checkWMTE(() -> { // actual reference class
+            char x = (char) vh.compareAndExchangeRelease(array, 0, '\u0123', Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.compareAndExchangeRelease(0, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.compareAndExchangeRelease(array, Void.class, '\u0123', '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, '\u0123', '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, '\u0123', '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.compareAndExchangeRelease(array, 0, '\u0123', '\u0123', Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndSet(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndSet(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            char x = (char) vh.getAndSet(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndSet(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSet(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndSetAcquire(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndSetAcquire(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            char x = (char) vh.getAndSetAcquire(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndSetAcquire(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSetAcquire(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndSetRelease(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndSetRelease(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            char x = (char) vh.getAndSetRelease(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndSetRelease(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndSetRelease(array, 0, '\u0123', Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndAdd(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndAdd(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndAdd(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndAdd(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAdd(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndAddAcquire(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndAddAcquire(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndAddAcquire(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndAddAcquire(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAddAcquire(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndAddRelease(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndAddRelease(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndAddRelease(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndAddRelease(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndAddRelease(array, 0, '\u0123', Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseOr(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseOr(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOr(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseOr(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseOr(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOr(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseOrAcquire(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseOrAcquire(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOrAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseOrAcquire(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseOrAcquire(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOrAcquire(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseOrRelease(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseOrRelease(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseOrRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseOrRelease(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseOrRelease(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseOrRelease(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseAnd(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseAnd(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAnd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseAnd(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseAnd(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAnd(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseAndAcquire(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseAndAcquire(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAndAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseAndAcquire(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseAndAcquire(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAndAcquire(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseAndRelease(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseAndRelease(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseAndRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseAndRelease(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseAndRelease(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseAndRelease(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseXor(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseXor(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXor(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseXor(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseXor(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXor(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseXorAcquire(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseXorAcquire(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXorAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseXorAcquire(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseXorAcquire(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXorAcquire(array, 0, '\u0123', Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            char x = (char) vh.getAndBitwiseXorRelease(null, 0, '\u0123');
+        });
+        checkCCE(() -> { // array reference class
+            char x = (char) vh.getAndBitwiseXorRelease(Void.class, 0, '\u0123');
+        });
+        checkWMTE(() -> { // value reference class
+            char x = (char) vh.getAndBitwiseXorRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            char x = (char) vh.getAndBitwiseXorRelease(0, 0, '\u0123');
+        });
+        checkWMTE(() -> { // index reference class
+            char x = (char) vh.getAndBitwiseXorRelease(array, Void.class, '\u0123');
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(array, 0, '\u0123');
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, 0, '\u0123');
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            char x = (char) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            char x = (char) vh.getAndBitwiseXorRelease(array, 0, '\u0123', Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        char[] array = new char[10];
+        Arrays.fill(array, '\u0123');
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class)).
+                    invokeExact((char[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, char[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, char[].class, int.class, char.class)).
+                    invokeExact((char[]) null, 0, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, char.class)).
+                    invokeExact(Void.class, 0, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, char.class)).
+                    invokeExact(0, 0, '\u0123');
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, char[].class, Class.class, char.class)).
+                    invokeExact(array, Void.class, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, char[].class, int.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, char.class, char.class)).
+                    invokeExact((char[]) null, 0, '\u0123', '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, char.class, char.class)).
+                    invokeExact(Void.class, 0, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, Class.class, char.class)).
+                    invokeExact(array, 0, Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, char.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, char.class, char.class)).
+                    invokeExact(0, 0, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, char[].class, Class.class, char.class, char.class)).
+                    invokeExact(array, Void.class, '\u0123', '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, char.class, char.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class, char.class)).
+                    invokeExact((char[]) null, 0, '\u0123', '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, int.class, char.class, char.class)).
+                    invokeExact(Void.class, 0, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // expected reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class, char.class)).
+                    invokeExact(array, 0, Void.class, '\u0123');
+            });
+            checkWMTE(() -> { // actual reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, int.class, char.class, char.class)).
+                    invokeExact(0, 0, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // index reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class, char.class, char.class)).
+                    invokeExact(array, Void.class, '\u0123', '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char[].class, int.class, char.class, char.class)).
+                    invokeExact(array, 0, '\u0123', '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, char.class, char.class)).
+                    invokeExact(array, 0, '\u0123', '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class, char.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class)).
+                    invokeExact((char[]) null, 0, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, int.class, char.class)).
+                    invokeExact(Void.class, 0, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, int.class, char.class)).
+                    invokeExact(0, 0, '\u0123');
+            });
+            checkWMTE(() -> { // index reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class, char.class)).
+                    invokeExact(array, Void.class, '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char[].class, int.class, char.class)).
+                    invokeExact(array, 0, '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, char.class)).
+                    invokeExact(array, 0, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class)).
+                    invokeExact((char[]) null, 0, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, int.class, char.class)).
+                    invokeExact(Void.class, 0, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, int.class, char.class)).
+                    invokeExact(0, 0, '\u0123');
+            });
+            checkWMTE(() -> { // index reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class, char.class)).
+                    invokeExact(array, Void.class, '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char[].class, int.class, char.class)).
+                    invokeExact(array, 0, '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, char.class)).
+                    invokeExact(array, 0, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class)).
+                    invokeExact((char[]) null, 0, '\u0123');
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                char x = (char) hs.get(am, methodType(char.class, Class.class, int.class, char.class)).
+                    invokeExact(Void.class, 0, '\u0123');
+            });
+            checkWMTE(() -> { // value reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                char x = (char) hs.get(am, methodType(char.class, int.class, int.class, char.class)).
+                    invokeExact(0, 0, '\u0123');
+            });
+            checkWMTE(() -> { // index reference class
+                char x = (char) hs.get(am, methodType(char.class, char[].class, Class.class, char.class)).
+                    invokeExact(array, Void.class, '\u0123');
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, char[].class, int.class, char.class)).
+                    invokeExact(array, 0, '\u0123');
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, char[].class, int.class, char.class)).
+                    invokeExact(array, 0, '\u0123');
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                char x = (char) hs.get(am, methodType(char.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                char x = (char) hs.get(am, methodType(char.class, char[].class, int.class, char.class, Class.class)).
+                    invokeExact(array, 0, '\u0123', Void.class);
+            });
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java
new file mode 100644
index 0000000..ad80a40
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeDouble.java
@@ -0,0 +1,2405 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeDouble
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeDouble
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeDouble extends VarHandleBaseTest {
+    static final double static_final_v = 1.0d;
+
+    static double static_v = 1.0d;
+
+    final double final_v = 1.0d;
+
+    double v = 1.0d;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeDouble.class, "final_v", double.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeDouble.class, "v", double.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeDouble.class, "static_final_v", double.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeDouble.class, "static_v", double.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(double[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeDouble::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeDouble::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.get();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 1.0d, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 1.0d, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 1.0d, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            double x = (double) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 1.0d, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.compareAndExchange(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.compareAndExchange(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchange(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchange(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.compareAndExchange(0, 1.0d, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchange(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.compareAndExchangeAcquire(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.compareAndExchangeAcquire(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchangeAcquire(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchangeAcquire(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.compareAndExchangeAcquire(0, 1.0d, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchangeAcquire(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.compareAndExchangeRelease(null, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.compareAndExchangeRelease(Void.class, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchangeRelease(recv, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchangeRelease(recv, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.compareAndExchangeRelease(0, 1.0d, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchangeRelease(recv, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAndSet(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAndSet(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.getAndSet(0, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSet(recv, 1.0d, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAndSetAcquire(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAndSetAcquire(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.getAndSetAcquire(0, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSetAcquire(recv, 1.0d, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAndSetRelease(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAndSetRelease(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.getAndSetRelease(0, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSetRelease(recv, 1.0d, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAndAdd(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAndAdd(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.getAndAdd(0, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAdd(recv, 1.0d, Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAndAddAcquire(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAndAddAcquire(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.getAndAddAcquire(0, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(recv, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAddAcquire(recv, 1.0d, Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.getAndAddRelease(null, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            double x = (double) vh.getAndAddRelease(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            double x = (double) vh.getAndAddRelease(0, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(recv, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAddRelease(recv, 1.0d, Void.class);
+        });
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeDouble recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeDouble.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, double.class)).
+                    invokeExact(Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, double.class)).
+                    invokeExact(0, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)).
+                    invokeExact(recv, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class, double.class, double.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null, 1.0d, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, double.class, double.class)).
+                    invokeExact(Void.class, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class, Class.class, double.class)).
+                    invokeExact(recv, Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)).
+                    invokeExact(recv, 1.0d, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , double.class, double.class)).
+                    invokeExact(0, 1.0d, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class, double.class, double.class, Class.class)).
+                    invokeExact(recv, 1.0d, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class, double.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null, 1.0d, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, double.class, double.class)).
+                    invokeExact(Void.class, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // expected reference class
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class, double.class)).
+                    invokeExact(recv, Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // actual reference class
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class, Class.class)).
+                    invokeExact(recv, 1.0d, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class , double.class, double.class)).
+                    invokeExact(0, 1.0d, 1.0d);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeDouble.class , double.class, double.class)).
+                    invokeExact(recv, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class , double.class, double.class)).
+                    invokeExact(recv, 1.0d, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class, double.class, Class.class)).
+                    invokeExact(recv, 1.0d, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, double.class)).
+                    invokeExact(Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class, double.class)).
+                    invokeExact(0, 1.0d);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact(recv, 1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact(recv, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact(recv, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact((VarHandleTestMethodTypeDouble) null, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, double.class)).
+                    invokeExact(Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class, double.class)).
+                    invokeExact(0, 1.0d);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact(recv, 1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact(recv, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, VarHandleTestMethodTypeDouble.class, double.class)).
+                    invokeExact(recv, 1.0d, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            double x = (double) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(1.0d, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(1.0d, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(1.0d, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(1.0d, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(1.0d, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(1.0d, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(1.0d, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(1.0d, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(1.0d, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchange(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchange(1.0d, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchange(1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchangeAcquire(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchangeAcquire(1.0d, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchangeAcquire(1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchangeRelease(Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchangeRelease(1.0d, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchangeRelease(1.0d, 1.0d, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSet(1.0d, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSetAcquire(1.0d, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSetRelease(1.0d, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAdd(1.0d, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAddAcquire(1.0d, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAddRelease(1.0d, Void.class);
+        });
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, double.class, Class.class)).
+                    invokeExact(1.0d, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, double.class)).
+                    invokeExact(Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, double.class, Class.class)).
+                    invokeExact(1.0d, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, double.class, double.class, Class.class)).
+                    invokeExact(1.0d, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, double.class)).
+                    invokeExact(Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // actual reference class
+                double x = (double) hs.get(am, methodType(double.class, double.class, Class.class)).
+                    invokeExact(1.0d, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, double.class, double.class)).
+                    invokeExact(1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double.class, double.class)).
+                    invokeExact(1.0d, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double.class, double.class, Class.class)).
+                    invokeExact(1.0d, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, double.class)).
+                    invokeExact(1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double.class)).
+                    invokeExact(1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double.class, Class.class)).
+                    invokeExact(1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, double.class)).
+                    invokeExact(1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double.class)).
+                    invokeExact(1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double.class, Class.class)).
+                    invokeExact(1.0d, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        double[] array = new double[10];
+        Arrays.fill(array, 1.0d);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.get();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 1.0d, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.compareAndExchange(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.compareAndExchange(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchange(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchange(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.compareAndExchange(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.compareAndExchange(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchange(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.compareAndExchangeAcquire(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.compareAndExchangeAcquire(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchangeAcquire(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchangeAcquire(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.compareAndExchangeAcquire(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.compareAndExchangeAcquire(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchangeAcquire(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            double x = (double) vh.compareAndExchangeRelease(null, 0, 1.0d, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.compareAndExchangeRelease(Void.class, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // expected reference class
+            double x = (double) vh.compareAndExchangeRelease(array, 0, Void.class, 1.0d);
+        });
+        checkWMTE(() -> { // actual reference class
+            double x = (double) vh.compareAndExchangeRelease(array, 0, 1.0d, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.compareAndExchangeRelease(0, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.compareAndExchangeRelease(array, Void.class, 1.0d, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, 1.0d, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, 1.0d, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.compareAndExchangeRelease(array, 0, 1.0d, 1.0d, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAndSet(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAndSet(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            double x = (double) vh.getAndSet(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAndSet(array, Void.class, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSet(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAndSetAcquire(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAndSetAcquire(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            double x = (double) vh.getAndSetAcquire(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAndSetAcquire(array, Void.class, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSetAcquire(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAndSetRelease(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAndSetRelease(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            double x = (double) vh.getAndSetRelease(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAndSetRelease(array, Void.class, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndSetRelease(array, 0, 1.0d, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAndAdd(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAndAdd(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getAndAdd(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAndAdd(array, Void.class, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAdd(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAndAddAcquire(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAndAddAcquire(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getAndAddAcquire(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAndAddAcquire(array, Void.class, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(array, 0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAddAcquire(array, 0, 1.0d, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            double x = (double) vh.getAndAddRelease(null, 0, 1.0d);
+        });
+        checkCCE(() -> { // array reference class
+            double x = (double) vh.getAndAddRelease(Void.class, 0, 1.0d);
+        });
+        checkWMTE(() -> { // value reference class
+            double x = (double) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            double x = (double) vh.getAndAddRelease(0, 0, 1.0d);
+        });
+        checkWMTE(() -> { // index reference class
+            double x = (double) vh.getAndAddRelease(array, Void.class, 1.0d);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, 1.0d);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(array, 0, 1.0d);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            double x = (double) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            double x = (double) vh.getAndAddRelease(array, 0, 1.0d, Void.class);
+        });
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        double[] array = new double[10];
+        Arrays.fill(array, 1.0d);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class)).
+                    invokeExact((double[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, double[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, double[].class, int.class, double.class)).
+                    invokeExact((double[]) null, 0, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, double.class)).
+                    invokeExact(Void.class, 0, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, double.class)).
+                    invokeExact(0, 0, 1.0d);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, double[].class, Class.class, double.class)).
+                    invokeExact(array, Void.class, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, double[].class, int.class, Class.class)).
+                    invokeExact(array, 0, 1.0d, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class, double.class, double.class)).
+                    invokeExact((double[]) null, 0, 1.0d, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, double.class, double.class)).
+                    invokeExact(Void.class, 0, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class, Class.class, double.class)).
+                    invokeExact(array, 0, Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class, double.class, Class.class)).
+                    invokeExact(array, 0, 1.0d, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, double.class, double.class)).
+                    invokeExact(0, 0, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, double[].class, Class.class, double.class, double.class)).
+                    invokeExact(array, Void.class, 1.0d, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class, double.class, double.class, Class.class)).
+                    invokeExact(array, 0, 1.0d, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, double.class, double.class)).
+                    invokeExact((double[]) null, 0, 1.0d, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, int.class, double.class, double.class)).
+                    invokeExact(Void.class, 0, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // expected reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class, double.class)).
+                    invokeExact(array, 0, Void.class, 1.0d);
+            });
+            checkWMTE(() -> { // actual reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, double.class, Class.class)).
+                    invokeExact(array, 0, 1.0d, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class, int.class, double.class, double.class)).
+                    invokeExact(0, 0, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // index reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class, double.class, double.class)).
+                    invokeExact(array, Void.class, 1.0d, 1.0d);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, double[].class, int.class, double.class, double.class)).
+                    invokeExact(array, 0, 1.0d, 1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class, double.class, double.class)).
+                    invokeExact(array, 0, 1.0d, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, double.class, double.class, Class.class)).
+                    invokeExact(array, 0, 1.0d, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, double.class)).
+                    invokeExact((double[]) null, 0, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, int.class, double.class)).
+                    invokeExact(Void.class, 0, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class, int.class, double.class)).
+                    invokeExact(0, 0, 1.0d);
+            });
+            checkWMTE(() -> { // index reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class, double.class)).
+                    invokeExact(array, Void.class, 1.0d);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, double[].class, int.class, double.class)).
+                    invokeExact(array, 0, 1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class, double.class)).
+                    invokeExact(array, 0, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, double.class, Class.class)).
+                    invokeExact(array, 0, 1.0d, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, double.class)).
+                    invokeExact((double[]) null, 0, 1.0d);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                double x = (double) hs.get(am, methodType(double.class, Class.class, int.class, double.class)).
+                    invokeExact(Void.class, 0, 1.0d);
+            });
+            checkWMTE(() -> { // value reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                double x = (double) hs.get(am, methodType(double.class, int.class, int.class, double.class)).
+                    invokeExact(0, 0, 1.0d);
+            });
+            checkWMTE(() -> { // index reference class
+                double x = (double) hs.get(am, methodType(double.class, double[].class, Class.class, double.class)).
+                    invokeExact(array, Void.class, 1.0d);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, double[].class, int.class, double.class)).
+                    invokeExact(array, 0, 1.0d);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, double[].class, int.class, double.class)).
+                    invokeExact(array, 0, 1.0d);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                double x = (double) hs.get(am, methodType(double.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                double x = (double) hs.get(am, methodType(double.class, double[].class, int.class, double.class, Class.class)).
+                    invokeExact(array, 0, 1.0d, Void.class);
+            });
+        }
+
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java
new file mode 100644
index 0000000..26dd830
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeFloat.java
@@ -0,0 +1,2405 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeFloat
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeFloat
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeFloat extends VarHandleBaseTest {
+    static final float static_final_v = 1.0f;
+
+    static float static_v = 1.0f;
+
+    final float final_v = 1.0f;
+
+    float v = 1.0f;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeFloat.class, "final_v", float.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeFloat.class, "v", float.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeFloat.class, "static_final_v", float.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeFloat.class, "static_v", float.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(float[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeFloat::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeFloat::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.get();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 1.0f, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 1.0f, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 1.0f, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            float x = (float) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 1.0f, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.compareAndExchange(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.compareAndExchange(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchange(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchange(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.compareAndExchange(0, 1.0f, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchange(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.compareAndExchangeAcquire(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.compareAndExchangeAcquire(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchangeAcquire(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchangeAcquire(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.compareAndExchangeAcquire(0, 1.0f, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchangeAcquire(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.compareAndExchangeRelease(null, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.compareAndExchangeRelease(Void.class, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchangeRelease(recv, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchangeRelease(recv, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.compareAndExchangeRelease(0, 1.0f, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchangeRelease(recv, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAndSet(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAndSet(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.getAndSet(0, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSet(recv, 1.0f, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAndSetAcquire(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAndSetAcquire(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.getAndSetAcquire(0, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSetAcquire(recv, 1.0f, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAndSetRelease(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAndSetRelease(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.getAndSetRelease(0, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSetRelease(recv, 1.0f, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAndAdd(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAndAdd(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.getAndAdd(0, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAdd(recv, 1.0f, Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAndAddAcquire(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAndAddAcquire(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.getAndAddAcquire(0, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(recv, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAddAcquire(recv, 1.0f, Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.getAndAddRelease(null, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            float x = (float) vh.getAndAddRelease(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            float x = (float) vh.getAndAddRelease(0, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(recv, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAddRelease(recv, 1.0f, Void.class);
+        });
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeFloat recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeFloat.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, float.class)).
+                    invokeExact(Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, float.class)).
+                    invokeExact(0, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)).
+                    invokeExact(recv, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class, float.class, float.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null, 1.0f, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, float.class, float.class)).
+                    invokeExact(Void.class, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class, Class.class, float.class)).
+                    invokeExact(recv, Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)).
+                    invokeExact(recv, 1.0f, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , float.class, float.class)).
+                    invokeExact(0, 1.0f, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class, float.class, float.class, Class.class)).
+                    invokeExact(recv, 1.0f, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class, float.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null, 1.0f, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, float.class, float.class)).
+                    invokeExact(Void.class, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // expected reference class
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class, float.class)).
+                    invokeExact(recv, Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // actual reference class
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class, Class.class)).
+                    invokeExact(recv, 1.0f, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class , float.class, float.class)).
+                    invokeExact(0, 1.0f, 1.0f);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeFloat.class , float.class, float.class)).
+                    invokeExact(recv, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class , float.class, float.class)).
+                    invokeExact(recv, 1.0f, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class, float.class, Class.class)).
+                    invokeExact(recv, 1.0f, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, float.class)).
+                    invokeExact(Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class, float.class)).
+                    invokeExact(0, 1.0f);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact(recv, 1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact(recv, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact(recv, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact((VarHandleTestMethodTypeFloat) null, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, float.class)).
+                    invokeExact(Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class, float.class)).
+                    invokeExact(0, 1.0f);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact(recv, 1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact(recv, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, VarHandleTestMethodTypeFloat.class, float.class)).
+                    invokeExact(recv, 1.0f, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            float x = (float) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(1.0f, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(1.0f, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(1.0f, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(1.0f, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(1.0f, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(1.0f, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(1.0f, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(1.0f, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(1.0f, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchange(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchange(1.0f, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchange(1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchangeAcquire(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchangeAcquire(1.0f, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchangeAcquire(1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchangeRelease(Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchangeRelease(1.0f, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchangeRelease(1.0f, 1.0f, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSet(1.0f, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSetAcquire(1.0f, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSetRelease(1.0f, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAdd(1.0f, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAddAcquire(1.0f, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAddRelease(1.0f, Void.class);
+        });
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, float.class, Class.class)).
+                    invokeExact(1.0f, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, float.class)).
+                    invokeExact(Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, float.class, Class.class)).
+                    invokeExact(1.0f, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, float.class, float.class, Class.class)).
+                    invokeExact(1.0f, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, float.class)).
+                    invokeExact(Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // actual reference class
+                float x = (float) hs.get(am, methodType(float.class, float.class, Class.class)).
+                    invokeExact(1.0f, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, float.class, float.class)).
+                    invokeExact(1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float.class, float.class)).
+                    invokeExact(1.0f, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float.class, float.class, Class.class)).
+                    invokeExact(1.0f, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, float.class)).
+                    invokeExact(1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float.class)).
+                    invokeExact(1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float.class, Class.class)).
+                    invokeExact(1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, float.class)).
+                    invokeExact(1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float.class)).
+                    invokeExact(1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float.class, Class.class)).
+                    invokeExact(1.0f, Void.class);
+            });
+        }
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        float[] array = new float[10];
+        Arrays.fill(array, 1.0f);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.get();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 1.0f, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.compareAndExchange(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.compareAndExchange(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchange(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchange(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.compareAndExchange(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.compareAndExchange(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchange(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.compareAndExchangeAcquire(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.compareAndExchangeAcquire(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchangeAcquire(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchangeAcquire(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.compareAndExchangeAcquire(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.compareAndExchangeAcquire(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchangeAcquire(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            float x = (float) vh.compareAndExchangeRelease(null, 0, 1.0f, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.compareAndExchangeRelease(Void.class, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // expected reference class
+            float x = (float) vh.compareAndExchangeRelease(array, 0, Void.class, 1.0f);
+        });
+        checkWMTE(() -> { // actual reference class
+            float x = (float) vh.compareAndExchangeRelease(array, 0, 1.0f, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.compareAndExchangeRelease(0, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.compareAndExchangeRelease(array, Void.class, 1.0f, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, 1.0f, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, 1.0f, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.compareAndExchangeRelease(array, 0, 1.0f, 1.0f, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAndSet(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAndSet(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            float x = (float) vh.getAndSet(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAndSet(array, Void.class, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSet(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAndSetAcquire(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAndSetAcquire(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            float x = (float) vh.getAndSetAcquire(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAndSetAcquire(array, Void.class, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSetAcquire(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAndSetRelease(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAndSetRelease(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            float x = (float) vh.getAndSetRelease(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAndSetRelease(array, Void.class, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndSetRelease(array, 0, 1.0f, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAndAdd(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAndAdd(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getAndAdd(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAndAdd(array, Void.class, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAdd(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAndAddAcquire(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAndAddAcquire(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getAndAddAcquire(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAndAddAcquire(array, Void.class, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(array, 0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAddAcquire(array, 0, 1.0f, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            float x = (float) vh.getAndAddRelease(null, 0, 1.0f);
+        });
+        checkCCE(() -> { // array reference class
+            float x = (float) vh.getAndAddRelease(Void.class, 0, 1.0f);
+        });
+        checkWMTE(() -> { // value reference class
+            float x = (float) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            float x = (float) vh.getAndAddRelease(0, 0, 1.0f);
+        });
+        checkWMTE(() -> { // index reference class
+            float x = (float) vh.getAndAddRelease(array, Void.class, 1.0f);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, 1.0f);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(array, 0, 1.0f);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            float x = (float) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            float x = (float) vh.getAndAddRelease(array, 0, 1.0f, Void.class);
+        });
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        float[] array = new float[10];
+        Arrays.fill(array, 1.0f);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class)).
+                    invokeExact((float[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, float[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, float[].class, int.class, float.class)).
+                    invokeExact((float[]) null, 0, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, float.class)).
+                    invokeExact(Void.class, 0, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, float.class)).
+                    invokeExact(0, 0, 1.0f);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, float[].class, Class.class, float.class)).
+                    invokeExact(array, Void.class, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, float[].class, int.class, Class.class)).
+                    invokeExact(array, 0, 1.0f, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class, float.class, float.class)).
+                    invokeExact((float[]) null, 0, 1.0f, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, float.class, float.class)).
+                    invokeExact(Void.class, 0, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class, Class.class, float.class)).
+                    invokeExact(array, 0, Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class, float.class, Class.class)).
+                    invokeExact(array, 0, 1.0f, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, float.class, float.class)).
+                    invokeExact(0, 0, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, float[].class, Class.class, float.class, float.class)).
+                    invokeExact(array, Void.class, 1.0f, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class, float.class, float.class, Class.class)).
+                    invokeExact(array, 0, 1.0f, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, float.class, float.class)).
+                    invokeExact((float[]) null, 0, 1.0f, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, int.class, float.class, float.class)).
+                    invokeExact(Void.class, 0, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // expected reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class, float.class)).
+                    invokeExact(array, 0, Void.class, 1.0f);
+            });
+            checkWMTE(() -> { // actual reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, float.class, Class.class)).
+                    invokeExact(array, 0, 1.0f, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class, int.class, float.class, float.class)).
+                    invokeExact(0, 0, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // index reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class, float.class, float.class)).
+                    invokeExact(array, Void.class, 1.0f, 1.0f);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, float[].class, int.class, float.class, float.class)).
+                    invokeExact(array, 0, 1.0f, 1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class, float.class, float.class)).
+                    invokeExact(array, 0, 1.0f, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, float.class, float.class, Class.class)).
+                    invokeExact(array, 0, 1.0f, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, float.class)).
+                    invokeExact((float[]) null, 0, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, int.class, float.class)).
+                    invokeExact(Void.class, 0, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class, int.class, float.class)).
+                    invokeExact(0, 0, 1.0f);
+            });
+            checkWMTE(() -> { // index reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class, float.class)).
+                    invokeExact(array, Void.class, 1.0f);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, float[].class, int.class, float.class)).
+                    invokeExact(array, 0, 1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class, float.class)).
+                    invokeExact(array, 0, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, float.class, Class.class)).
+                    invokeExact(array, 0, 1.0f, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, float.class)).
+                    invokeExact((float[]) null, 0, 1.0f);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                float x = (float) hs.get(am, methodType(float.class, Class.class, int.class, float.class)).
+                    invokeExact(Void.class, 0, 1.0f);
+            });
+            checkWMTE(() -> { // value reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                float x = (float) hs.get(am, methodType(float.class, int.class, int.class, float.class)).
+                    invokeExact(0, 0, 1.0f);
+            });
+            checkWMTE(() -> { // index reference class
+                float x = (float) hs.get(am, methodType(float.class, float[].class, Class.class, float.class)).
+                    invokeExact(array, Void.class, 1.0f);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, float[].class, int.class, float.class)).
+                    invokeExact(array, 0, 1.0f);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, float[].class, int.class, float.class)).
+                    invokeExact(array, 0, 1.0f);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                float x = (float) hs.get(am, methodType(float.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                float x = (float) hs.get(am, methodType(float.class, float[].class, int.class, float.class, Class.class)).
+                    invokeExact(array, 0, 1.0f, Void.class);
+            });
+        }
+
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
new file mode 100644
index 0000000..44de44e
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java
@@ -0,0 +1,3257 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeInt
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeInt
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeInt extends VarHandleBaseTest {
+    static final int static_final_v = 0x01234567;
+
+    static int static_v = 0x01234567;
+
+    final int final_v = 0x01234567;
+
+    int v = 0x01234567;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeInt.class, "final_v", int.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeInt.class, "v", int.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeInt.class, "static_final_v", int.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeInt.class, "static_v", int.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(int[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeInt::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeInt::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeInt::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.get();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            int x = (int) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchange(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.compareAndExchange(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchange(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchange(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.compareAndExchange(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchange(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeAcquire(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.compareAndExchangeAcquire(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeAcquire(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeAcquire(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.compareAndExchangeAcquire(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeAcquire(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeRelease(null, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.compareAndExchangeRelease(Void.class, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeRelease(recv, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeRelease(recv, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.compareAndExchangeRelease(0, 0x01234567, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeRelease(recv, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndSet(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndSet(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndSet(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSet(recv, 0x01234567, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndSetAcquire(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndSetAcquire(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndSetAcquire(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSetAcquire(recv, 0x01234567, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndSetRelease(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndSetRelease(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndSetRelease(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSetRelease(recv, 0x01234567, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndAdd(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndAdd(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndAdd(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAdd(recv, 0x01234567, Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndAddAcquire(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndAddAcquire(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndAddAcquire(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAddAcquire(recv, 0x01234567, Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndAddRelease(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndAddRelease(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndAddRelease(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAddRelease(recv, 0x01234567, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseOr(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseOr(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseOr(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOr(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseOrAcquire(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseOrAcquire(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOrAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseOrAcquire(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOrAcquire(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseOrRelease(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseOr(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseOr(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOr(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseAnd(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseAnd(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseAnd(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAnd(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseAndAcquire(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseAndAcquire(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAndAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseAndAcquire(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAndAcquire(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseAndRelease(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseAnd(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseAnd(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAnd(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseXor(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseXor(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseXor(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXor(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseXorAcquire(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseXorAcquire(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXorAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseXorAcquire(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXorAcquire(recv, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.getAndBitwiseXorRelease(null, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            int x = (int) vh.getAndBitwiseXor(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            int x = (int) vh.getAndBitwiseXor(0, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXor(recv, 0x01234567, Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeInt recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class)).
+                    invokeExact(0, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
+                    invokeExact(recv, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 0x01234567, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class)).
+                    invokeExact(Void.class, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)).
+                    invokeExact(recv, Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
+                    invokeExact(recv, 0x01234567, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , int.class, int.class)).
+                    invokeExact(0, 0x01234567, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)).
+                    invokeExact(recv, 0x01234567, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 0x01234567, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
+                    invokeExact(Void.class, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // expected reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class, int.class)).
+                    invokeExact(recv, Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // actual reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, Class.class)).
+                    invokeExact(recv, 0x01234567, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class , int.class, int.class)).
+                    invokeExact(0, 0x01234567, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class , int.class, int.class)).
+                    invokeExact(recv, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class , int.class, int.class)).
+                    invokeExact(recv, 0x01234567, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class, int.class, Class.class)).
+                    invokeExact(recv, 0x01234567, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
+                    invokeExact(0, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
+                    invokeExact(0, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact((VarHandleTestMethodTypeInt) null, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
+                    invokeExact(0, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, VarHandleTestMethodTypeInt.class, int.class)).
+                    invokeExact(recv, 0x01234567, Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            int x = (int) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(0x01234567, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(0x01234567, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(0x01234567, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(0x01234567, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(0x01234567, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(0x01234567, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(0x01234567, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(0x01234567, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(0x01234567, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchange(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchange(0x01234567, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchange(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeAcquire(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeAcquire(0x01234567, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeAcquire(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeRelease(Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeRelease(0x01234567, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeRelease(0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSet(0x01234567, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSetAcquire(0x01234567, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSetRelease(0x01234567, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAdd(0x01234567, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAddAcquire(0x01234567, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAddRelease(0x01234567, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOr(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOr(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOrAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOrAcquire(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseOrReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOrRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOrRelease(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAnd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAnd(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAndAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAndAcquire(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAndReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAndRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAndRelease(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXor(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXor(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXorAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXorAcquire(0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXorReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXorRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXorRelease(0x01234567, Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, int.class, Class.class)).
+                    invokeExact(0x01234567, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, Class.class)).
+                    invokeExact(0x01234567, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, Class.class)).
+                    invokeExact(0x01234567, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // actual reference class
+                int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
+                    invokeExact(0x01234567, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int.class, int.class)).
+                    invokeExact(0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class)).
+                    invokeExact(0x01234567, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, Class.class)).
+                    invokeExact(0x01234567, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int.class)).
+                    invokeExact(0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
+                    invokeExact(0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
+                    invokeExact(0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int.class)).
+                    invokeExact(0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
+                    invokeExact(0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
+                    invokeExact(0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int.class)).
+                    invokeExact(0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int.class)).
+                    invokeExact(0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int.class, Class.class)).
+                    invokeExact(0x01234567, Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        int[] array = new int[10];
+        Arrays.fill(array, 0x01234567);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.get();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchange(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.compareAndExchange(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchange(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchange(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.compareAndExchange(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.compareAndExchange(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchange(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeAcquire(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.compareAndExchangeAcquire(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeAcquire(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeAcquire(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.compareAndExchangeAcquire(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.compareAndExchangeAcquire(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeAcquire(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            int x = (int) vh.compareAndExchangeRelease(null, 0, 0x01234567, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.compareAndExchangeRelease(Void.class, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // expected reference class
+            int x = (int) vh.compareAndExchangeRelease(array, 0, Void.class, 0x01234567);
+        });
+        checkWMTE(() -> { // actual reference class
+            int x = (int) vh.compareAndExchangeRelease(array, 0, 0x01234567, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.compareAndExchangeRelease(0, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.compareAndExchangeRelease(array, Void.class, 0x01234567, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, 0x01234567, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, 0x01234567, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.compareAndExchangeRelease(array, 0, 0x01234567, 0x01234567, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndSet(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndSet(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            int x = (int) vh.getAndSet(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndSet(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSet(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndSetAcquire(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndSetAcquire(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            int x = (int) vh.getAndSetAcquire(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndSetAcquire(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSetAcquire(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndSetRelease(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndSetRelease(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            int x = (int) vh.getAndSetRelease(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndSetRelease(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndSetRelease(array, 0, 0x01234567, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndAdd(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndAdd(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndAdd(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndAdd(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAdd(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndAddAcquire(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndAddAcquire(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndAddAcquire(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndAddAcquire(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAddAcquire(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndAddRelease(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndAddRelease(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndAddRelease(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndAddRelease(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndAddRelease(array, 0, 0x01234567, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseOr(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseOr(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOr(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseOr(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseOr(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOr(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseOrAcquire(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseOrAcquire(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOrAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseOrAcquire(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseOrAcquire(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOrAcquire(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseOrRelease(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseOrRelease(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseOrRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseOrRelease(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseOrRelease(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseOrRelease(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseAnd(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseAnd(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAnd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseAnd(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseAnd(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAnd(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseAndAcquire(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseAndAcquire(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAndAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseAndAcquire(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseAndAcquire(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAndAcquire(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseAndRelease(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseAndRelease(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseAndRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseAndRelease(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseAndRelease(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseAndRelease(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseXor(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseXor(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXor(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseXor(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseXor(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXor(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseXorAcquire(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseXorAcquire(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXorAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseXorAcquire(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseXorAcquire(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXorAcquire(array, 0, 0x01234567, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            int x = (int) vh.getAndBitwiseXorRelease(null, 0, 0x01234567);
+        });
+        checkCCE(() -> { // array reference class
+            int x = (int) vh.getAndBitwiseXorRelease(Void.class, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // value reference class
+            int x = (int) vh.getAndBitwiseXorRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            int x = (int) vh.getAndBitwiseXorRelease(0, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // index reference class
+            int x = (int) vh.getAndBitwiseXorRelease(array, Void.class, 0x01234567);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(array, 0, 0x01234567);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, 0, 0x01234567);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            int x = (int) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            int x = (int) vh.getAndBitwiseXorRelease(array, 0, 0x01234567, Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        int[] array = new int[10];
+        Arrays.fill(array, 0x01234567);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class)).
+                    invokeExact((int[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, int[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, int[].class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, int.class)).
+                    invokeExact(Void.class, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, int[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, int.class)).
+                    invokeExact(0, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, int[].class, Class.class, int.class)).
+                    invokeExact(array, Void.class, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, int[].class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 0x01234567, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, int.class, int.class)).
+                    invokeExact(Void.class, 0, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, Class.class, int.class)).
+                    invokeExact(array, 0, Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, int.class, int.class)).
+                    invokeExact(0, 0, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, Class.class, int.class, int.class)).
+                    invokeExact(array, Void.class, 0x01234567, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 0x01234567, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class, int.class)).
+                    invokeExact(Void.class, 0, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // expected reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class, int.class)).
+                    invokeExact(array, 0, Void.class, 0x01234567);
+            });
+            checkWMTE(() -> { // actual reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class, int.class)).
+                    invokeExact(0, 0, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class, int.class)).
+                    invokeExact(array, Void.class, 0x01234567, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
+                    invokeExact(Void.class, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)).
+                    invokeExact(0, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)).
+                    invokeExact(array, Void.class, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
+                    invokeExact(Void.class, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)).
+                    invokeExact(0, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)).
+                    invokeExact(array, Void.class, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class)).
+                    invokeExact((int[]) null, 0, 0x01234567);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                int x = (int) hs.get(am, methodType(int.class, Class.class, int.class, int.class)).
+                    invokeExact(Void.class, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // value reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                int x = (int) hs.get(am, methodType(int.class, int.class, int.class, int.class)).
+                    invokeExact(0, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // index reference class
+                int x = (int) hs.get(am, methodType(int.class, int[].class, Class.class, int.class)).
+                    invokeExact(array, Void.class, 0x01234567);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, int[].class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, int[].class, int.class, int.class)).
+                    invokeExact(array, 0, 0x01234567);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                int x = (int) hs.get(am, methodType(int.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                int x = (int) hs.get(am, methodType(int.class, int[].class, int.class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x01234567, Void.class);
+            });
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java
new file mode 100644
index 0000000..c740a94
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java
@@ -0,0 +1,3257 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeLong
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeLong
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeLong extends VarHandleBaseTest {
+    static final long static_final_v = 0x0123456789ABCDEFL;
+
+    static long static_v = 0x0123456789ABCDEFL;
+
+    final long final_v = 0x0123456789ABCDEFL;
+
+    long v = 0x0123456789ABCDEFL;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeLong.class, "final_v", long.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeLong.class, "v", long.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeLong.class, "static_final_v", long.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeLong.class, "static_v", long.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(long[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeLong::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeLong::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeLong::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.get();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            long x = (long) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchange(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.compareAndExchange(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchange(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchange(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.compareAndExchange(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchange(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeAcquire(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.compareAndExchangeAcquire(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeAcquire(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeAcquire(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.compareAndExchangeAcquire(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeAcquire(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeRelease(null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.compareAndExchangeRelease(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeRelease(recv, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeRelease(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.compareAndExchangeRelease(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeRelease(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndSet(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndSet(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndSet(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSet(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndSetAcquire(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndSetAcquire(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndSetAcquire(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSetAcquire(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndSetRelease(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndSetRelease(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndSetRelease(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSetRelease(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndAdd(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndAdd(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndAdd(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAdd(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndAddAcquire(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndAddAcquire(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndAddAcquire(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAddAcquire(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndAddRelease(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndAddRelease(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndAddRelease(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAddRelease(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseOr(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseOr(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseOr(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseOrAcquire(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseOrAcquire(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOrAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseOrAcquire(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOrAcquire(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseOrRelease(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseOr(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseOr(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOr(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseAnd(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseAnd(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseAnd(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseAndAcquire(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseAndAcquire(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAndAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseAndAcquire(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAndAcquire(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseAndRelease(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseAnd(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseAnd(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAnd(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseXor(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseXor(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseXor(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseXorAcquire(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseXorAcquire(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXorAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseXorAcquire(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXorAcquire(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.getAndBitwiseXorRelease(null, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            long x = (long) vh.getAndBitwiseXor(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            long x = (long) vh.getAndBitwiseXor(0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXor(recv, 0x0123456789ABCDEFL, Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeLong recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, long.class)).
+                    invokeExact(0, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)).
+                    invokeExact(recv, Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , long.class, long.class)).
+                    invokeExact(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // expected reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class, long.class)).
+                    invokeExact(recv, Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // actual reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, Class.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class , long.class, long.class)).
+                    invokeExact(0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class , long.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class , long.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class, long.class, Class.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, long.class)).
+                    invokeExact(0, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, long.class)).
+                    invokeExact(0, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact((VarHandleTestMethodTypeLong) null, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, long.class)).
+                    invokeExact(0, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, VarHandleTestMethodTypeLong.class, long.class)).
+                    invokeExact(recv, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            long x = (long) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchange(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchange(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchange(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeAcquire(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeAcquire(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeAcquire(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeRelease(Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeRelease(0x0123456789ABCDEFL, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeRelease(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSet(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSetAcquire(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSetRelease(0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAdd(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAddAcquire(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAddRelease(0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOr(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOr(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOrAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOrAcquire(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseOrReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOrRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOrRelease(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAnd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAnd(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAndAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAndAcquire(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAndReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAndRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAndRelease(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXor(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXor(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXorAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXorAcquire(0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXorReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXorRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXorRelease(0x0123456789ABCDEFL, Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, long.class)).
+                    invokeExact(Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // actual reference class
+                long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long.class)).
+                    invokeExact(0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long.class, Class.class)).
+                    invokeExact(0x0123456789ABCDEFL, Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        long[] array = new long[10];
+        Arrays.fill(array, 0x0123456789ABCDEFL);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.get();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchange(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.compareAndExchange(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchange(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchange(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.compareAndExchange(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.compareAndExchange(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchange(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeAcquire(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.compareAndExchangeAcquire(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeAcquire(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeAcquire(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.compareAndExchangeAcquire(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.compareAndExchangeAcquire(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeAcquire(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            long x = (long) vh.compareAndExchangeRelease(null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.compareAndExchangeRelease(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // expected reference class
+            long x = (long) vh.compareAndExchangeRelease(array, 0, Void.class, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // actual reference class
+            long x = (long) vh.compareAndExchangeRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.compareAndExchangeRelease(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.compareAndExchangeRelease(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.compareAndExchangeRelease(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndSet(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndSet(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            long x = (long) vh.getAndSet(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndSet(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSet(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndSetAcquire(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndSetAcquire(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            long x = (long) vh.getAndSetAcquire(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndSetAcquire(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSetAcquire(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndSetRelease(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndSetRelease(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            long x = (long) vh.getAndSetRelease(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndSetRelease(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndSetRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndAdd(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndAdd(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndAdd(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndAdd(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAdd(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndAddAcquire(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndAddAcquire(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndAddAcquire(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndAddAcquire(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAddAcquire(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndAddRelease(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndAddRelease(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndAddRelease(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndAddRelease(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndAddRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseOr(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseOr(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOr(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseOr(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseOr(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOr(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseOrAcquire(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseOrAcquire(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOrAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseOrAcquire(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseOrAcquire(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOrAcquire(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseOrRelease(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseOrRelease(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseOrRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseOrRelease(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseOrRelease(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseOrRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseAnd(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseAnd(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAnd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseAnd(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseAnd(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAnd(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseAndAcquire(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseAndAcquire(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAndAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseAndAcquire(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseAndAcquire(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAndAcquire(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseAndRelease(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseAndRelease(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseAndRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseAndRelease(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseAndRelease(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseAndRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseXor(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseXor(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXor(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseXor(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseXor(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXor(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseXorAcquire(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseXorAcquire(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXorAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseXorAcquire(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseXorAcquire(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXorAcquire(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            long x = (long) vh.getAndBitwiseXorRelease(null, 0, 0x0123456789ABCDEFL);
+        });
+        checkCCE(() -> { // array reference class
+            long x = (long) vh.getAndBitwiseXorRelease(Void.class, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // value reference class
+            long x = (long) vh.getAndBitwiseXorRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            long x = (long) vh.getAndBitwiseXorRelease(0, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // index reference class
+            long x = (long) vh.getAndBitwiseXorRelease(array, Void.class, 0x0123456789ABCDEFL);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, 0, 0x0123456789ABCDEFL);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            long x = (long) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            long x = (long) vh.getAndBitwiseXorRelease(array, 0, 0x0123456789ABCDEFL, Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        long[] array = new long[10];
+        Arrays.fill(array, 0x0123456789ABCDEFL);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class)).
+                    invokeExact((long[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, long[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, long[].class, int.class, long.class)).
+                    invokeExact((long[]) null, 0, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, long.class)).
+                    invokeExact(Void.class, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, long[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, long.class)).
+                    invokeExact(0, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, long[].class, Class.class, long.class)).
+                    invokeExact(array, Void.class, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, long[].class, int.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class)).
+                    invokeExact((long[]) null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, long.class, long.class)).
+                    invokeExact(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, Class.class, long.class)).
+                    invokeExact(array, 0, Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, long.class, long.class)).
+                    invokeExact(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, Class.class, long.class, long.class)).
+                    invokeExact(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, long.class)).
+                    invokeExact((long[]) null, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class, long.class)).
+                    invokeExact(Void.class, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // expected reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class, long.class)).
+                    invokeExact(array, 0, Void.class, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // actual reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class, long.class)).
+                    invokeExact(0, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class, long.class)).
+                    invokeExact(array, Void.class, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, long.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class)).
+                    invokeExact((long[]) null, 0, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)).
+                    invokeExact(Void.class, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)).
+                    invokeExact(0, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)).
+                    invokeExact(array, Void.class, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class)).
+                    invokeExact((long[]) null, 0, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)).
+                    invokeExact(Void.class, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)).
+                    invokeExact(0, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)).
+                    invokeExact(array, Void.class, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class)).
+                    invokeExact((long[]) null, 0, 0x0123456789ABCDEFL);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                long x = (long) hs.get(am, methodType(long.class, Class.class, int.class, long.class)).
+                    invokeExact(Void.class, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // value reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                long x = (long) hs.get(am, methodType(long.class, int.class, int.class, long.class)).
+                    invokeExact(0, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // index reference class
+                long x = (long) hs.get(am, methodType(long.class, long[].class, Class.class, long.class)).
+                    invokeExact(array, Void.class, 0x0123456789ABCDEFL);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, long[].class, int.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, long[].class, int.class, long.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                long x = (long) hs.get(am, methodType(long.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                long x = (long) hs.get(am, methodType(long.class, long[].class, int.class, long.class, Class.class)).
+                    invokeExact(array, 0, 0x0123456789ABCDEFL, Void.class);
+            });
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java
new file mode 100644
index 0000000..db7d38a
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeShort.java
@@ -0,0 +1,3257 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeShort
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeShort
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeShort extends VarHandleBaseTest {
+    static final short static_final_v = (short)0x0123;
+
+    static short static_v = (short)0x0123;
+
+    final short final_v = (short)0x0123;
+
+    short v = (short)0x0123;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeShort.class, "final_v", short.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeShort.class, "v", short.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeShort.class, "static_final_v", short.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeShort.class, "static_v", short.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(short[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeShort::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeShort::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.get(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.get();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            short x = (short) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.compareAndExchange(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.compareAndExchange(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchange(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchange(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.compareAndExchange(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchange(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.compareAndExchangeAcquire(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.compareAndExchangeAcquire(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchangeAcquire(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchangeAcquire(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.compareAndExchangeAcquire(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchangeAcquire(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.compareAndExchangeRelease(null, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.compareAndExchangeRelease(Void.class, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchangeRelease(recv, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchangeRelease(recv, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.compareAndExchangeRelease(0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchangeRelease(recv, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndSet(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndSet(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndSet(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSet(recv, (short)0x0123, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndSetAcquire(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndSetAcquire(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndSetAcquire(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSetAcquire(recv, (short)0x0123, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndSetRelease(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndSetRelease(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndSetRelease(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSetRelease(recv, (short)0x0123, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndAdd(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndAdd(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndAdd(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAdd(recv, (short)0x0123, Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndAddAcquire(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndAddAcquire(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndAddAcquire(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAddAcquire(recv, (short)0x0123, Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndAddRelease(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndAddRelease(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndAddRelease(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAddRelease(recv, (short)0x0123, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseOr(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseOr(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseOr(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOr(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseOrAcquire(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseOrAcquire(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOrAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseOrAcquire(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOrAcquire(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseOrRelease(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseOr(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseOr(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOr(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseAnd(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseAnd(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseAnd(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAnd(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseAndAcquire(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseAndAcquire(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAndAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseAndAcquire(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAndAcquire(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseAndRelease(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseAnd(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseAnd(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAnd(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseXor(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseXor(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseXor(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXor(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseXorAcquire(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseXorAcquire(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXorAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseXorAcquire(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXorAcquire(recv, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.getAndBitwiseXorRelease(null, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            short x = (short) vh.getAndBitwiseXor(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            short x = (short) vh.getAndBitwiseXor(0, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(recv, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXor(recv, (short)0x0123, Void.class);
+        });
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeShort recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeShort.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, short.class)).
+                    invokeExact(0, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)).
+                    invokeExact(recv, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class, short.class, short.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null, (short)0x0123, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, short.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class, Class.class, short.class)).
+                    invokeExact(recv, Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)).
+                    invokeExact(recv, (short)0x0123, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , short.class, short.class)).
+                    invokeExact(0, (short)0x0123, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class, short.class, short.class, Class.class)).
+                    invokeExact(recv, (short)0x0123, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class, short.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null, (short)0x0123, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, short.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // expected reference class
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class, short.class)).
+                    invokeExact(recv, Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // actual reference class
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class, Class.class)).
+                    invokeExact(recv, (short)0x0123, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class , short.class, short.class)).
+                    invokeExact(0, (short)0x0123, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeShort.class , short.class, short.class)).
+                    invokeExact(recv, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class , short.class, short.class)).
+                    invokeExact(recv, (short)0x0123, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class, short.class, Class.class)).
+                    invokeExact(recv, (short)0x0123, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, short.class)).
+                    invokeExact(0, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, short.class)).
+                    invokeExact(0, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkNPE(() -> { // null receiver
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact((VarHandleTestMethodTypeShort) null, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, short.class)).
+                    invokeExact(0, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, VarHandleTestMethodTypeShort.class, short.class)).
+                    invokeExact(recv, (short)0x0123, Void.class);
+            });
+        }
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            short x = (short) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set((short)0x0123, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile((short)0x0123, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque((short)0x0123, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease((short)0x0123, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet((short)0x0123, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain((short)0x0123, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet((short)0x0123, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire((short)0x0123, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease((short)0x0123, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchange(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchange((short)0x0123, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange((short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange((short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchange((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchangeAcquire(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchangeAcquire((short)0x0123, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire((short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire((short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchangeAcquire((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchangeRelease(Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchangeRelease((short)0x0123, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease((short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease((short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchangeRelease((short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSet((short)0x0123, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSetAcquire((short)0x0123, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSetRelease((short)0x0123, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAdd((short)0x0123, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAddAcquire((short)0x0123, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAddRelease((short)0x0123, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOr(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOr((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOrAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOrAcquire((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseOrReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOrRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOrRelease((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAnd(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAnd((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAndAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAndAcquire((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAndReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAndRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAndRelease((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXor(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXor((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXorAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXorAcquire((short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXorReleaseRelease
+        // Incorrect argument types
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXorRelease(Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease((short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease((short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXorRelease((short)0x0123, Void.class);
+        });
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, short.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // expected reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, short.class)).
+                    invokeExact(Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // actual reference class
+                short x = (short) hs.get(am, methodType(short.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short.class, short.class)).
+                    invokeExact((short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short.class, short.class)).
+                    invokeExact((short)0x0123, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short.class)).
+                    invokeExact((short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short.class)).
+                    invokeExact((short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short.class)).
+                    invokeExact((short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short.class)).
+                    invokeExact((short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short.class)).
+                    invokeExact((short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short.class)).
+                    invokeExact((short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short.class, Class.class)).
+                    invokeExact((short)0x0123, Void.class);
+            });
+        }
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        short[] array = new short[10];
+        Arrays.fill(array, (short)0x0123);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.get();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.compareAndExchange(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.compareAndExchange(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchange(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchange(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.compareAndExchange(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.compareAndExchange(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchange(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.compareAndExchangeAcquire(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.compareAndExchangeAcquire(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchangeAcquire(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchangeAcquire(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.compareAndExchangeAcquire(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.compareAndExchangeAcquire(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchangeAcquire(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            short x = (short) vh.compareAndExchangeRelease(null, 0, (short)0x0123, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.compareAndExchangeRelease(Void.class, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // expected reference class
+            short x = (short) vh.compareAndExchangeRelease(array, 0, Void.class, (short)0x0123);
+        });
+        checkWMTE(() -> { // actual reference class
+            short x = (short) vh.compareAndExchangeRelease(array, 0, (short)0x0123, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.compareAndExchangeRelease(0, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.compareAndExchangeRelease(array, Void.class, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, (short)0x0123, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, (short)0x0123, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.compareAndExchangeRelease(array, 0, (short)0x0123, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndSet(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndSet(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            short x = (short) vh.getAndSet(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndSet(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSet(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndSetAcquire(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndSetAcquire(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            short x = (short) vh.getAndSetAcquire(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndSetAcquire(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSetAcquire(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndSetRelease(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndSetRelease(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            short x = (short) vh.getAndSetRelease(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndSetRelease(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndSetRelease(array, 0, (short)0x0123, Void.class);
+        });
+
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndAdd(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndAdd(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndAdd(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndAdd(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAdd(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAdd(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndAddAcquire(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndAddAcquire(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndAddAcquire(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndAddAcquire(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddAcquire(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAddAcquire(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndAddRelease(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndAddRelease(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndAddRelease(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndAddRelease(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndAddRelease(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndAddRelease(array, 0, (short)0x0123, Void.class);
+        });
+
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseOr(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseOr(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOr(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseOr(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseOr(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOr(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOr(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseOrAcquire(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseOrAcquire(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOrAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseOrAcquire(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseOrAcquire(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrAcquire(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOrAcquire(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseOrRelease(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseOrRelease(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseOrRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseOrRelease(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseOrRelease(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseOrRelease(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseOrRelease(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseAnd(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseAnd(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAnd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseAnd(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseAnd(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAnd(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAnd(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseAndAcquire(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseAndAcquire(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAndAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseAndAcquire(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseAndAcquire(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndAcquire(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAndAcquire(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseAndRelease(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseAndRelease(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseAndRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseAndRelease(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseAndRelease(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseAndRelease(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseAndRelease(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseXor(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseXor(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXor(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseXor(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseXor(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXor(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXor(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseXorAcquire(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseXorAcquire(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXorAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseXorAcquire(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseXorAcquire(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorAcquire(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXorAcquire(array, 0, (short)0x0123, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            short x = (short) vh.getAndBitwiseXorRelease(null, 0, (short)0x0123);
+        });
+        checkCCE(() -> { // array reference class
+            short x = (short) vh.getAndBitwiseXorRelease(Void.class, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // value reference class
+            short x = (short) vh.getAndBitwiseXorRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            short x = (short) vh.getAndBitwiseXorRelease(0, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // index reference class
+            short x = (short) vh.getAndBitwiseXorRelease(array, Void.class, (short)0x0123);
+        });
+        // Incorrect return type
+        checkWMTE(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(array, 0, (short)0x0123);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndBitwiseXorRelease(array, 0, (short)0x0123);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            short x = (short) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            short x = (short) vh.getAndBitwiseXorRelease(array, 0, (short)0x0123, Void.class);
+        });
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        short[] array = new short[10];
+        Arrays.fill(array, (short)0x0123);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class)).
+                    invokeExact((short[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, short[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, short[].class, int.class, short.class)).
+                    invokeExact((short[]) null, 0, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, short.class)).
+                    invokeExact(Void.class, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, short.class)).
+                    invokeExact(0, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, short[].class, Class.class, short.class)).
+                    invokeExact(array, Void.class, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, short[].class, int.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, short.class, short.class)).
+                    invokeExact((short[]) null, 0, (short)0x0123, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, short.class, short.class)).
+                    invokeExact(Void.class, 0, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, Class.class, short.class)).
+                    invokeExact(array, 0, Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, short.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, short.class, short.class)).
+                    invokeExact(0, 0, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, short[].class, Class.class, short.class, short.class)).
+                    invokeExact(array, Void.class, (short)0x0123, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, short.class, short.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class, short.class)).
+                    invokeExact((short[]) null, 0, (short)0x0123, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, int.class, short.class, short.class)).
+                    invokeExact(Void.class, 0, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // expected reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class, short.class)).
+                    invokeExact(array, 0, Void.class, (short)0x0123);
+            });
+            checkWMTE(() -> { // actual reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, int.class, short.class, short.class)).
+                    invokeExact(0, 0, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // index reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class, short.class, short.class)).
+                    invokeExact(array, Void.class, (short)0x0123, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short[].class, int.class, short.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, short.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class, short.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class)).
+                    invokeExact((short[]) null, 0, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, int.class, short.class)).
+                    invokeExact(Void.class, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, int.class, short.class)).
+                    invokeExact(0, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // index reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class, short.class)).
+                    invokeExact(array, Void.class, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short[].class, int.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class)).
+                    invokeExact((short[]) null, 0, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, int.class, short.class)).
+                    invokeExact(Void.class, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, int.class, short.class)).
+                    invokeExact(0, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // index reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class, short.class)).
+                    invokeExact(array, Void.class, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short[].class, int.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class)).
+                    invokeExact((short[]) null, 0, (short)0x0123);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                short x = (short) hs.get(am, methodType(short.class, Class.class, int.class, short.class)).
+                    invokeExact(Void.class, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // value reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                short x = (short) hs.get(am, methodType(short.class, int.class, int.class, short.class)).
+                    invokeExact(0, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // index reference class
+                short x = (short) hs.get(am, methodType(short.class, short[].class, Class.class, short.class)).
+                    invokeExact(array, Void.class, (short)0x0123);
+            });
+            // Incorrect return type
+            checkWMTE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, short[].class, int.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, short[].class, int.class, short.class)).
+                    invokeExact(array, 0, (short)0x0123);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                short x = (short) hs.get(am, methodType(short.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                short x = (short) hs.get(am, methodType(short.class, short[].class, int.class, short.class, Class.class)).
+                    invokeExact(array, 0, (short)0x0123, Void.class);
+            });
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java
new file mode 100644
index 0000000..ea78495
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java
@@ -0,0 +1,2059 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodTypeString
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodTypeString
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodTypeString extends VarHandleBaseTest {
+    static final String static_final_v = "foo";
+
+    static String static_v = "foo";
+
+    final String final_v = "foo";
+
+    String v = "foo";
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeString.class, "final_v", String.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodTypeString.class, "v", String.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeString.class, "static_final_v", String.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodTypeString.class, "static_v", String.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(String[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodTypeString::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodTypeString::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodTypeString::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.get(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.get();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, "foo", Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, "foo", Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, "foo", Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            String x = (String) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, "foo", Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchange(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchange(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchange(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchange(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.compareAndExchange(0, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(recv, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchange(recv, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeAcquire(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchangeAcquire(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeAcquire(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeAcquire(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.compareAndExchangeAcquire(0, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(recv, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeAcquire(recv, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeRelease(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.compareAndExchangeRelease(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeRelease(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeRelease(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.compareAndExchangeRelease(0, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(recv, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeRelease(recv, "foo", "foo", Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getAndSet(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getAndSet(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.getAndSet(0, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(recv, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSet(recv, "foo", Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getAndSetAcquire(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getAndSetAcquire(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.getAndSetAcquire(0, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(recv, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSetAcquire(recv, "foo", Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.getAndSetRelease(null, "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            String x = (String) vh.getAndSetRelease(Void.class, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            String x = (String) vh.getAndSetRelease(0, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(recv, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSetRelease(recv, "foo", Void.class);
+        });
+
+
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodTypeString recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, String.class)).
+                    invokeExact(Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, String.class)).
+                    invokeExact(0, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
+                    invokeExact(recv, "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class, String.class)).
+                    invokeExact(Void.class, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, Class.class, String.class)).
+                    invokeExact(recv, Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
+                    invokeExact(recv, "foo", Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , String.class, String.class)).
+                    invokeExact(0, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)).
+                    invokeExact(recv, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, String.class, String.class)).
+                    invokeExact(Void.class, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // expected reference class
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class, String.class)).
+                    invokeExact(recv, Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // actual reference class
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, Class.class)).
+                    invokeExact(recv, "foo", Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class , String.class, String.class)).
+                    invokeExact(0, "foo", "foo");
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class , String.class, String.class)).
+                    invokeExact(recv, "foo", "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class , String.class, String.class)).
+                    invokeExact(recv, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class, String.class, Class.class)).
+                    invokeExact(recv, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invokeExact((VarHandleTestMethodTypeString) null, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)).
+                    invokeExact(Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // value reference class
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, String.class)).
+                    invokeExact(0, "foo");
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invokeExact(recv, "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invokeExact(recv, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, VarHandleTestMethodTypeString.class, String.class)).
+                    invokeExact(recv, "foo", Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            String x = (String) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set("foo", Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile("foo", Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque("foo", Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease("foo", Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.compareAndSet("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet("foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain("foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet("foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire("foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease("foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchange(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchange("foo", Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange("foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange("foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchange("foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeAcquire(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeAcquire("foo", Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire("foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire("foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeAcquire("foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeRelease(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeRelease("foo", Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease("foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease("foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeRelease("foo", "foo", Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSet("foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet("foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSet("foo", Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire("foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire("foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSetAcquire("foo", Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease("foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease("foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSetRelease("foo", Void.class);
+        });
+
+
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            hs.checkWMTEOrCCE(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, String.class, Class.class)).
+                    invokeExact("foo", Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            hs.checkWMTEOrCCE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, String.class)).
+                    invokeExact(Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, Class.class)).
+                    invokeExact("foo", Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class, Class.class)).
+                    invokeExact("foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            hs.checkWMTEOrCCE(() -> { // expected reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, String.class)).
+                    invokeExact(Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // actual reference class
+                String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)).
+                    invokeExact("foo", Void.class);
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String.class, String.class)).
+                    invokeExact("foo", "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class, String.class)).
+                    invokeExact("foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String.class, String.class, Class.class)).
+                    invokeExact("foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            hs.checkWMTEOrCCE(() -> { // value reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String.class)).
+                    invokeExact("foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String.class)).
+                    invokeExact("foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String.class, Class.class)).
+                    invokeExact("foo", Void.class);
+            });
+        }
+
+
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        String[] array = new String[10];
+        Arrays.fill(array, "foo");
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.get();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, "foo", Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, "foo", Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, "foo", Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, "foo", Void.class);
+        });
+
+
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchange(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.compareAndExchange(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchange(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchange(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.compareAndExchange(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.compareAndExchange(array, Void.class, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchange(array, 0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchange(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeAcquire(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.compareAndExchangeAcquire(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeAcquire(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeAcquire(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.compareAndExchangeAcquire(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.compareAndExchangeAcquire(array, Void.class, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeAcquire(array, 0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeAcquire(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            String x = (String) vh.compareAndExchangeRelease(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.compareAndExchangeRelease(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            String x = (String) vh.compareAndExchangeRelease(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            String x = (String) vh.compareAndExchangeRelease(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            String x = (String) vh.compareAndExchangeRelease(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.compareAndExchangeRelease(array, Void.class, "foo", "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.compareAndExchangeRelease(array, 0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.compareAndExchangeRelease(array, 0, "foo", "foo", Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getAndSet(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getAndSet(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            String x = (String) vh.getAndSet(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getAndSet(array, Void.class, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSet(array, 0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSet(array, 0, "foo", Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getAndSetAcquire(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getAndSetAcquire(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            String x = (String) vh.getAndSetAcquire(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getAndSetAcquire(array, Void.class, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetAcquire(array, 0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSetAcquire(array, 0, "foo", Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            String x = (String) vh.getAndSetRelease(null, 0, "foo");
+        });
+        checkCCE(() -> { // array reference class
+            String x = (String) vh.getAndSetRelease(Void.class, 0, "foo");
+        });
+        checkCCE(() -> { // value reference class
+            String x = (String) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            String x = (String) vh.getAndSetRelease(0, 0, "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            String x = (String) vh.getAndSetRelease(array, Void.class, "foo");
+        });
+        // Incorrect return type
+        checkCCE(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, "foo");
+        });
+        checkWMTE(() -> { // primitive class
+            boolean x = (boolean) vh.getAndSetRelease(array, 0, "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            String x = (String) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            String x = (String) vh.getAndSetRelease(array, 0, "foo", Void.class);
+        });
+
+
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        String[] array = new String[10];
+        Arrays.fill(array, "foo");
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class)).
+                    invokeExact((String[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, String[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, String[].class, int.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, String.class)).
+                    invokeExact(Void.class, 0, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // value reference class
+                hs.get(am, methodType(void.class, String[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, String.class)).
+                    invokeExact(0, 0, "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, String[].class, Class.class, String.class)).
+                    invokeExact(array, Void.class, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, String[].class, int.class, Class.class)).
+                    invokeExact(array, 0, "foo", Void.class);
+            });
+        }
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, String.class, String.class)).
+                    invokeExact(Void.class, 0, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, Class.class, String.class)).
+                    invokeExact(array, 0, Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, Class.class)).
+                    invokeExact(array, 0, "foo", Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, String.class, String.class)).
+                    invokeExact(0, 0, "foo", "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, Class.class, String.class, String.class)).
+                    invokeExact(array, Void.class, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class, Class.class)).
+                    invokeExact(array, 0, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class, String.class)).
+                    invokeExact(Void.class, 0, "foo", "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // expected reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class, String.class)).
+                    invokeExact(array, 0, Void.class, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // actual reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)).
+                    invokeExact(array, 0, "foo", Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class, String.class)).
+                    invokeExact(0, 0, "foo", "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class, String.class)).
+                    invokeExact(array, Void.class, "foo", "foo");
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class, String.class)).
+                    invokeExact(array, 0, "foo", "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class, String.class)).
+                    invokeExact(array, 0, "foo", "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, String.class, Class.class)).
+                    invokeExact(array, 0, "foo", "foo", Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class)).
+                    invokeExact((String[]) null, 0, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                String x = (String) hs.get(am, methodType(String.class, Class.class, int.class, String.class)).
+                    invokeExact(Void.class, 0, "foo");
+            });
+            hs.checkWMTEOrCCE(() -> { // value reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                String x = (String) hs.get(am, methodType(String.class, int.class, int.class, String.class)).
+                    invokeExact(0, 0, "foo");
+            });
+            checkWMTE(() -> { // index reference class
+                String x = (String) hs.get(am, methodType(String.class, String[].class, Class.class, String.class)).
+                    invokeExact(array, Void.class, "foo");
+            });
+            // Incorrect return type
+            hs.checkWMTEOrCCE(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, String[].class, int.class, String.class)).
+                    invokeExact(array, 0, "foo");
+            });
+            checkWMTE(() -> { // primitive class
+                boolean x = (boolean) hs.get(am, methodType(boolean.class, String[].class, int.class, String.class)).
+                    invokeExact(array, 0, "foo");
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                String x = (String) hs.get(am, methodType(String.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                String x = (String) hs.get(am, methodType(String.class, String[].class, int.class, String.class, Class.class)).
+                    invokeExact(array, 0, "foo", Void.class);
+            });
+        }
+
+
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestReflection.java b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestReflection.java
new file mode 100644
index 0000000..c4aa506
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/VarHandleTestReflection.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng VarHandleTestReflection
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Method;
+import java.util.stream.Stream;
+
+public class VarHandleTestReflection extends VarHandleBaseTest {
+    String string;
+
+    @DataProvider
+    public static Object[][] accessModesProvider() {
+        return Stream.of(VarHandle.AccessMode.values()).
+                map(am -> new Object[]{am}).
+                toArray(Object[][]::new);
+    }
+
+    static VarHandle handle() throws Exception {
+        return MethodHandles.lookup().
+                findVarHandle(VarHandleTestReflection.class, "string", String.class);
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void methodInvocation(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        // Try a reflective invoke using a Method
+
+        Method vhm = VarHandle.class.getMethod(accessMode.methodName(), Object[].class);
+        vhm.invoke(v, new Object[]{});
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = UnsupportedOperationException.class)
+    public void methodHandleInvoke(VarHandle.AccessMode accessMode) throws Throwable {
+        VarHandle v = handle();
+
+        // Try a reflective invoke using a MethodHandle
+
+        MethodHandle mh = MethodHandles.lookup().unreflect(
+                VarHandle.class.getMethod(accessMode.methodName(), Object[].class));
+        // Use invoke to avoid WrongMethodTypeException for
+        // non-signature-polymorphic return types
+        Object o = (Object) mh.invoke(v, new Object[]{});
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void methodInvocationFromMethodInfo(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        // Try a reflective invoke using a Method obtained from cracking
+        // a MethodHandle
+
+        MethodHandle mh = MethodHandles.lookup().unreflect(
+                VarHandle.class.getMethod(accessMode.methodName(), Object[].class));
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+        Method im = info.reflectAs(Method.class, MethodHandles.lookup());
+        im.invoke(v, new Object[]{});
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void reflectAsFromVarHandleInvoker(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        MethodHandle mh = MethodHandles.varHandleInvoker(
+                accessMode, v.accessModeType(accessMode));
+
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+
+        info.reflectAs(Method.class, MethodHandles.lookup());
+    }
+
+    @Test(dataProvider = "accessModesProvider", expectedExceptions = IllegalArgumentException.class)
+    public void reflectAsFromFindVirtual(VarHandle.AccessMode accessMode) throws Exception {
+        VarHandle v = handle();
+
+        MethodHandle mh = MethodHandles.publicLookup().findVirtual(
+                VarHandle.class, accessMode.methodName(), v.accessModeType(accessMode));
+
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+
+        info.reflectAs(Method.class, MethodHandles.lookup());
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template
new file mode 100644
index 0000000..6c38f7c
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template
@@ -0,0 +1,1928 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccess$Type$
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccess$Type$
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccess$Type$
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccess$Type$
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccess$Type$ extends VarHandleBaseTest {
+    static final $type$ static_final_v = $value1$;
+
+    static $type$ static_v;
+
+    final $type$ final_v = $value1$;
+
+    $type$ v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+#if[String]
+    VarHandle vhArrayObject;
+#end[String]
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "final_v", $type$.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "v", $type$.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccess$Type$.class, "static_final_v", $type$.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccess$Type$.class, "static_v", $type$.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle($type$[].class);
+#if[String]
+        vhArrayObject = MethodHandles.arrayElementVarHandle(Object[].class);
+#end[String]
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+#if[CAS]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+#else[CAS]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+#end[CAS]
+
+#if[AtomicAdd]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+#else[AtomicAdd]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+#end[AtomicAdd]
+
+#if[Bitwise]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+#else[Bitwise]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+#end[Bitwise]
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccess$Type$.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList($type$[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), $type$.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccess$Type$.class, "final_v", $type$.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccess$Type$.class, "v", $type$.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "static_final_v", $type$.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccess$Type$.class, "static_v", $type$.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccess$Type$::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccess$Type$::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccess$Type$::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccess$Type$::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccess$Type$::testArray));
+#if[String]
+        cases.add(new VarHandleAccessTestCase("Array Object[]",
+                                              vhArrayObject, VarHandleTestAccess$Type$::testArray));
+#end[String]
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccess$Type$::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccess$Type$::testArrayIndexOutOfBounds,
+                                              false));
+#if[String]
+        cases.add(new VarHandleAccessTestCase("Array store exception",
+                                              vhArrayObject, VarHandleTestAccess$Type$::testArrayStoreException,
+                                              false));
+#end[String]
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+        // Plain
+        {
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "get $type$ value");
+        }
+
+
+        // Volatile
+        {
+            $type$ x = ($type$) vh.getVolatile(recv);
+            assertEquals(x, $value1$, "getVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            $type$ x = ($type$) vh.getAcquire(recv);
+            assertEquals(x, $value1$, "getRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            $type$ x = ($type$) vh.getOpaque(recv);
+            assertEquals(x, $value1$, "getOpaque $type$ value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, $value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, $value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, $value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, $value2$);
+        });
+
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetRelease(recv, $value1$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease(recv, $value1$);
+        });
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease(recv, $value1$);
+        });
+#end[Bitwise]
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "get $type$ value");
+        }
+
+
+        // Volatile
+        {
+            $type$ x = ($type$) vh.getVolatile();
+            assertEquals(x, $value1$, "getVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            $type$ x = ($type$) vh.getAcquire();
+            assertEquals(x, $value1$, "getRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            $type$ x = ($type$) vh.getOpaque();
+            assertEquals(x, $value1$, "getOpaque $type$ value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set($value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile($value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease($value2$);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque($value2$);
+        });
+
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetRelease($value1$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease($value1$);
+        });
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease($value1$);
+        });
+#end[Bitwise]
+    }
+
+
+    static void testInstanceField(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, $value1$);
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, $value2$);
+            $type$ x = ($type$) vh.getVolatile(recv);
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, $value1$);
+            $type$ x = ($type$) vh.getAcquire(recv);
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, $value2$);
+            $type$ x = ($type$) vh.getOpaque(recv);
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        vh.set(recv, $value1$);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet(recv, $value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = vh.compareAndSet(recv, $value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchange(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchange $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "success compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchange(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchange $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "failing compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "weakCompareAndSet $type$ value");
+        }
+
+        // Compare set and get
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndSet(recv, $value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "getAndSet $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndSetAcquire(recv, $value2$);
+            assertEquals(o, $value1$, "getAndSetAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "getAndSetAcquire $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndSetRelease(recv, $value2$);
+            assertEquals(o, $value1$, "getAndSetRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value2$, "getAndSetRelease $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        // get and add, add and get
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndAdd(recv, $value2$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndAddAcquire(recv, $value2$);
+            assertEquals(o, $value1$, "getAndAddAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddAcquire $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndAddRelease(recv, $value2$);
+            assertEquals(o, $value1$, "getAndAddRelease$type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddRelease $type$ value");
+        }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // get and bitwise or
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseOr(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOr $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOr $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrAcquire $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrRelease $type$ value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseAnd(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAnd $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAnd $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndAcquire $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndRelease $type$ value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseXor(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXor $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXor $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorAcquire $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorAcquire $type$ value");
+        }
+
+        {
+            vh.set(recv, $value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorRelease $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorRelease $type$ value");
+        }
+#end[Bitwise]
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccess$Type$ recv, VarHandle vh) {
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetRelease(recv, $value1$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease(recv, $value1$);
+        });
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire(recv, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease(recv, $value1$);
+        });
+#end[Bitwise]
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set($value1$);
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile($value2$);
+            $type$ x = ($type$) vh.getVolatile();
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease($value1$);
+            $type$ x = ($type$) vh.getAcquire();
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque($value2$);
+            $type$ x = ($type$) vh.getOpaque();
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        vh.set($value1$);
+
+        // Compare
+        {
+            boolean r = vh.compareAndSet($value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = vh.compareAndSet($value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchange($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchange $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "success compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchange($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchange $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "failing compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetPlain($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetAcquire($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSetRelease($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = vh.weakCompareAndSet($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "weakCompareAndSet $type$");
+        }
+
+        // Compare set and get
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndSet($value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "getAndSet $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndSetAcquire($value2$);
+            assertEquals(o, $value1$, "getAndSetAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "getAndSetAcquire $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndSetRelease($value2$);
+            assertEquals(o, $value1$, "getAndSetRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value2$, "getAndSetRelease $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        // get and add, add and get
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndAdd($value2$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndAddAcquire($value2$);
+            assertEquals(o, $value1$, "getAndAddAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddAcquire $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndAddRelease($value2$);
+            assertEquals(o, $value1$, "getAndAddRelease$type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddRelease $type$ value");
+        }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // get and bitwise or
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseOr($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOr $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOr $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrAcquire $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrRelease $type$ value");
+        }
+
+        // get and bitwise and
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseAnd($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAnd $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAnd $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndAcquire $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndRelease $type$ value");
+        }
+
+        // get and bitwise xor
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseXor($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXor $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXor $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorAcquire $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorAcquire $type$ value");
+        }
+
+        {
+            vh.set($value1$);
+
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorRelease $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorRelease $type$ value");
+        }
+#end[Bitwise]
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetRelease($value1$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease($value1$);
+        });
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire($value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease($value1$);
+        });
+#end[Bitwise]
+    }
+
+
+    static void testArray(VarHandle vh) {
+        $type$[] array = new $type$[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, $value1$);
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "get $type$ value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, $value2$);
+                $type$ x = ($type$) vh.getVolatile(array, i);
+                assertEquals(x, $value2$, "setVolatile $type$ value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, $value1$);
+                $type$ x = ($type$) vh.getAcquire(array, i);
+                assertEquals(x, $value1$, "setRelease $type$ value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, $value2$);
+                $type$ x = ($type$) vh.getOpaque(array, i);
+                assertEquals(x, $value2$, "setOpaque $type$ value");
+            }
+
+#if[CAS]
+            vh.set(array, i, $value1$);
+
+            // Compare
+            {
+                boolean r = vh.compareAndSet(array, i, $value1$, $value2$);
+                assertEquals(r, true, "success compareAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "success compareAndSet $type$ value");
+            }
+
+            {
+                boolean r = vh.compareAndSet(array, i, $value1$, $value3$);
+                assertEquals(r, false, "failing compareAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchange(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchange $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "success compareAndExchange $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchange(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchange $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchange $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, $value1$, $value2$);
+                assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, $value1$, $value3$);
+                assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetPlain(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = vh.weakCompareAndSet(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSet $type$");
+            }
+
+            // Compare set and get
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndSet(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSet $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "getAndSet $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndSetAcquire(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSetAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "getAndSetAcquire $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndSetRelease(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSetRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value2$, "getAndSetRelease $type$ value");
+            }
+#end[CAS]
+
+#if[AtomicAdd]
+            // get and add, add and get
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndAdd(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndAdd $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndAddAcquire(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndAddAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddAcquire $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndAddRelease(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndAddRelease$type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddRelease $type$ value");
+            }
+#end[AtomicAdd]
+
+#if[Bitwise]
+            // get and bitwise or
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseOr(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseOr $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOr $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseOrAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrAcquire $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseOrRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrRelease $type$ value");
+            }
+
+            // get and bitwise and
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseAnd(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseAnd $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAnd $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseAndAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndAcquire $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseAndRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndRelease $type$ value");
+            }
+
+            // get and bitwise xor
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseXor(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseXor $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXor $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseXorAcquire $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorAcquire $type$ value");
+            }
+
+            {
+                vh.set(array, i, $value1$);
+
+                $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndBitwiseXorRelease $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorRelease $type$ value");
+            }
+#end[Bitwise]
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        $type$[] array = new $type$[10];
+
+        int i = 0;
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSet(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetAcquire(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.getAndSetRelease(array, i, $value1$);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease(array, i, $value1$);
+        });
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, i, $value1$);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, i, $value1$);
+        });
+#end[Bitwise]
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, $value1$);
+            });
+
+#if[CAS]
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchange(array, ci, $value2$, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, $value2$, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, $value2$, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSetAcquire(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSetRelease(array, ci, $value1$);
+            });
+#end[CAS]
+
+#if[AtomicAdd]
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAddAcquire(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAddRelease(array, ci, $value1$);
+            });
+#end[AtomicAdd]
+
+#if[Bitwise]
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, $value1$);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, $value1$);
+            });
+#end[Bitwise]
+        }
+    }
+
+#if[String]
+    static void testArrayStoreException(VarHandle vh) throws Throwable {
+        Object[] array = new $type$[10];
+        Arrays.fill(array, $value1$);
+        Object value = new Object();
+
+        // Set
+        checkASE(() -> {
+            vh.set(array, 0, value);
+        });
+
+        // SetVolatile
+        checkASE(() -> {
+            vh.setVolatile(array, 0, value);
+        });
+
+        // SetOpaque
+        checkASE(() -> {
+            vh.setOpaque(array, 0, value);
+        });
+
+        // SetRelease
+        checkASE(() -> {
+            vh.setRelease(array, 0, value);
+        });
+
+        // CompareAndSet
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(array, 0, $value1$, value);
+        });
+
+        // WeakCompareAndSet
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, $value1$, value);
+        });
+
+        // WeakCompareAndSetVolatile
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(array, 0, $value1$, value);
+        });
+
+        // WeakCompareAndSetAcquire
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, value);
+        });
+
+        // WeakCompareAndSetRelease
+        checkASE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, value);
+        });
+
+        // CompareAndExchange
+        checkASE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchange(array, 0, $value1$, value);
+        });
+
+        // CompareAndExchangeAcquire
+        checkASE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, value);
+        });
+
+        // CompareAndExchangeRelease
+        checkASE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, value);
+        });
+
+        // GetAndSet
+        checkASE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndSet(array, 0, value);
+        });
+
+        // GetAndSetAcquire
+        checkASE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndSetAcquire(array, 0, value);
+        });
+
+        // GetAndSetRelease
+        checkASE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndSetRelease(array, 0, value);
+        });
+    }
+#end[String]
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
new file mode 100644
index 0000000..0587d48
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
@@ -0,0 +1,2116 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8154556
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$
+ * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAs$Type$
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAs$Type$
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
+    static final int SIZE = $BoxType$.BYTES;
+
+    static final $type$ VALUE_1 = $value1$;
+
+    static final $type$ VALUE_2 = $value2$;
+
+    static final $type$ VALUE_3 = $value3$;
+
+
+    @Override
+    public void setupVarHandleSources() {
+        // Combinations of VarHandle byte[] or ByteBuffer
+        vhss = new ArrayList<>();
+        for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
+            VarHandleSource aeh = new VarHandleSource(
+                    MethodHandles.byteArrayViewVarHandle($type$[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(aeh);
+
+            VarHandleSource bbh = new VarHandleSource(
+                    MethodHandles.byteBufferViewVarHandle($type$[].class, bo),
+                    endianess, MemoryMode.READ_WRITE);
+            vhss.add(bbh);
+        }
+    }
+
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
+
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+
+#if[CAS]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+#else[CAS]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+#end[CAS]
+
+#if[AtomicAdd]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+#else[AtomicAdd]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+#end[AtomicAdd]
+
+#if[Bitwise]
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+#else[Bitwise]
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+#end[Bitwise]
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
+        assertEquals(vh.varType(), $type$.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (ByteArrayViewSource<?> bav : bavss) {
+            for (VarHandleSource vh : vhss) {
+                if (vh.matches(bav)) {
+                    if (bav instanceof ByteArraySource) {
+                        ByteArraySource bas = (ByteArraySource) bav;
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "read write", bav, vh, h -> testArrayReadWrite(bas, h),
+                                true));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null array", bav, vh, h -> testArrayNPE(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
+                                false));
+                    }
+                    else {
+                        ByteBufferSource bbs = (ByteBufferSource) bav;
+
+                        if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
+                                    true));
+                        }
+                        else {
+                            cases.add(new VarHandleSourceAccessTestCase(
+                                    "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
+                                    true));
+                        }
+
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
+                                false));
+                        cases.add(new VarHandleSourceAccessTestCase(
+                                "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+                                false));
+                    }
+                }
+            }
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+#if[CAS]
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+#end[AtomicAdd]
+
+#if[Bitwise]
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+#end[Bitwise]
+    }
+
+    static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = null;
+        int ci = 1;
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.get(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.set(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.getVolatile(array, ci);
+        });
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.getAcquire(array, ci);
+        });
+
+        checkNPE(() -> {
+            $type$ x = ($type$) vh.getOpaque(array, ci);
+        });
+
+        checkNPE(() -> {
+            vh.setVolatile(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            vh.setOpaque(array, ci, VALUE_1);
+        });
+
+#if[CAS]
+        checkNPE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+#end[AtomicAdd]
+
+#if[Bitwise]
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkNPE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+#end[Bitwise]
+    }
+
+    static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+        int ci = 1;
+
+#if[!CAS]
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+        });
+#end[CAS]
+
+#if[!AtomicAdd]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+        });
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+        });
+
+        checkUOE(() -> {
+            $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+        });
+#end[Bitwise]
+    }
+
+    static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+        int ci = 0;
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+        }
+
+        if (readOnly) {
+            checkROBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+#if[CAS]
+
+            checkROBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+
+#else[CAS]
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+#end[CAS]
+
+#if[AtomicAdd]
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+#else[AtomicAdd]
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+#end[AtomicAdd]
+
+#if[Bitwise]
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkROBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+#else[Bitwise]
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+#end[Bitwise]
+        }
+        else {
+#if[!CAS]
+            checkUOE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+#end[CAS]
+#if[!AtomicAdd]
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+#end[AtomicAdd]
+#if[!Bitwise]
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkUOE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+#end[Bitwise]
+        }
+    }
+
+
+    static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int length = array.length - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, VALUE_1);
+            });
+#if[CAS]
+
+            checkIOOBE(() -> {
+                boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+            });
+#end[CAS]
+
+#if[AtomicAdd]
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+            });
+#end[AtomicAdd]
+
+#if[Bitwise]
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+            });
+
+            checkIOOBE(() -> {
+                $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+            });
+#end[Bitwise]
+
+        }
+    }
+
+    static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.get(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.set(array, ci, VALUE_1);
+                });
+            }
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                $type$ x = ($type$) vh.getOpaque(array, ci);
+            });
+
+            if (!readOnly) {
+                checkIOOBE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+
+#if[CAS]
+                checkIOOBE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+#end[CAS]
+
+#if[AtomicAdd]
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+                });
+#end[AtomicAdd]
+
+#if[Bitwise]
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                });
+
+                checkIOOBE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                });
+#end[Bitwise]
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getOpaque(array, ci);
+                });
+
+                checkISE(() -> {
+                    vh.setVolatile(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    vh.setOpaque(array, ci, VALUE_1);
+                });
+#if[CAS]
+
+                checkISE(() -> {
+                    boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+                });
+#end[CAS]
+
+#if[AtomicAdd]
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+                });
+#end[AtomicAdd]
+
+#if[Bitwise]
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                });
+
+                checkISE(() -> {
+                    $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                });
+#end[Bitwise]
+            }
+        }
+    }
+
+    static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+            final int ci = i;
+
+            if (!iAligned) {
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getVolatile(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getAcquire(array, ci);
+                });
+
+                checkISE(() -> {
+                    $type$ x = ($type$) vh.getOpaque(array, ci);
+                });
+
+                if (!readOnly) {
+                    checkISE(() -> {
+                        vh.setVolatile(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        vh.setOpaque(array, ci, VALUE_1);
+                    });
+
+#if[CAS]
+                    checkISE(() -> {
+                        boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+                    });
+#end[CAS]
+
+#if[AtomicAdd]
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+                    });
+#end[AtomicAdd]
+
+#if[Bitwise]
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+                    });
+
+                    checkISE(() -> {
+                        $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+                    });
+#end[Bitwise]
+                }
+            }
+        }
+    }
+
+    static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        byte[] array = bs.s;
+
+        int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.length - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get $type$ value");
+            }
+
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile $type$ value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    $type$ x = ($type$) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease $type$ value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque $type$ value");
+                }
+#if[CAS]
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet $type$ value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain $type$ value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet $type$");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease $type$ value");
+                }
+#end[CAS]
+
+#if[AtomicAdd]
+                // get and add, add and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAdd $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndAddAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndAddRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease $type$ value");
+                }
+#end[AtomicAdd]
+
+#if[Bitwise]
+                // get and bitwise or
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseOr(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOr $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease $type$ value");
+                }
+
+                // get and bitwise and
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseAnd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAnd $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease $type$ value");
+                }
+
+                // get and bitwise xor
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseXor(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXor $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease $type$ value");
+                }
+#end[Bitwise]
+            }
+        }
+    }
+
+
+    static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        bs.fill((byte) 0xff);
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            // Plain
+            {
+                vh.set(array, i, VALUE_1);
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, VALUE_1, "get $type$ value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    vh.setVolatile(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getVolatile(array, i);
+                    assertEquals(x, VALUE_2, "setVolatile $type$ value");
+                }
+
+                // Lazy
+                {
+                    vh.setRelease(array, i, VALUE_1);
+                    $type$ x = ($type$) vh.getAcquire(array, i);
+                    assertEquals(x, VALUE_1, "setRelease $type$ value");
+                }
+
+                // Opaque
+                {
+                    vh.setOpaque(array, i, VALUE_2);
+                    $type$ x = ($type$) vh.getOpaque(array, i);
+                    assertEquals(x, VALUE_2, "setOpaque $type$ value");
+                }
+#if[CAS]
+
+                vh.set(array, i, VALUE_1);
+
+                // Compare
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, true, "success compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndSet $type$ value");
+                }
+
+                {
+                    boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, false, "failing compareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndSet $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchange $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchange $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchange $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchange $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
+                    assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
+                    assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
+                    assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetPlain $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetPlain $type$ value");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
+                    }
+                    assertEquals(success, true, "weakCompareAndSetRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
+                }
+
+                {
+                    boolean success = false;
+                    for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                        success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
+                    }
+                    assertEquals(success, true, "weakCompareAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSet $type$");
+                }
+
+                // Compare set and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSet $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndSetAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndSetRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSetRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_2, "getAndSetRelease $type$ value");
+                }
+#end[CAS]
+
+#if[AtomicAdd]
+                // get and add, add and get
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAdd $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndAddAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndAddRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndAddRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease $type$ value");
+                }
+#end[AtomicAdd]
+
+#if[Bitwise]
+                // get and bitwise or
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseOr(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOr $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseOrRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease $type$ value");
+                }
+
+                // get and bitwise and
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseAnd(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAnd $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseAndRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease $type$ value");
+                }
+
+                // get and bitwise xor
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseXor(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXor $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire $type$ value");
+                }
+
+                {
+                    vh.set(array, i, VALUE_1);
+
+                    $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndBitwiseXorRelease $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease $type$ value");
+                }
+#end[Bitwise]
+            }
+        }
+    }
+
+    static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
+        VarHandle vh = vhs.s;
+        ByteBuffer array = bs.s;
+
+        int misalignmentAtZero = array.alignmentOffset(0, SIZE);
+
+        ByteBuffer bb = ByteBuffer.allocate(SIZE);
+        bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
+        bs.fill(bb.put$Type$(0, VALUE_2).array());
+
+        int length = array.limit() - SIZE + 1;
+        for (int i = 0; i < length; i++) {
+            boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+
+            $type$ v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
+                    ? rotateLeft(VALUE_2, (i % SIZE) << 3)
+                    : rotateRight(VALUE_2, (i % SIZE) << 3);
+            // Plain
+            {
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, v, "get $type$ value");
+            }
+
+            if (iAligned) {
+                // Volatile
+                {
+                    $type$ x = ($type$) vh.getVolatile(array, i);
+                    assertEquals(x, v, "getVolatile $type$ value");
+                }
+
+                // Lazy
+                {
+                    $type$ x = ($type$) vh.getAcquire(array, i);
+                    assertEquals(x, v, "getRelease $type$ value");
+                }
+
+                // Opaque
+                {
+                    $type$ x = ($type$) vh.getOpaque(array, i);
+                    assertEquals(x, v, "getOpaque $type$ value");
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template
new file mode 100644
index 0000000..fee66ba
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template
@@ -0,0 +1,1113 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @run testng/othervm -Diters=20000 VarHandleTestMethodHandleAccess$Type$
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest {
+    static final $type$ static_final_v = $value1$;
+
+    static $type$ static_v;
+
+    final $type$ final_v = $value1$;
+
+    $type$ v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccess$Type$.class, "final_v", $type$.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodHandleAccess$Type$.class, "v", $type$.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccess$Type$.class, "static_final_v", $type$.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodHandleAccess$Type$.class, "static_v", $type$.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle($type$[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceField(this, hs)));
+            cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
+                                                     vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticField));
+            cases.add(new MethodHandleAccessTestCase("Static field unsupported",
+                                                     vhStaticField, f, VarHandleTestMethodHandleAccess$Type$::testStaticFieldUnsupported,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArray));
+            cases.add(new MethodHandleAccessTestCase("Array unsupported",
+                                                     vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayUnsupported,
+                                                     false));
+            cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
+                                                     vhArray, f, VarHandleTestMethodHandleAccess$Type$::testArrayIndexOutOfBounds,
+                                                     false));
+        }
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceField(VarHandleTestMethodHandleAccess$Type$ recv, Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, $value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, $value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, $value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, $value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, $value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchange $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "success compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchange $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "failing compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, $value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, $value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, $value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, $value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "weakCompareAndSet $type$");
+        }
+
+        // Compare set and get
+        {
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value2$, "getAndSet $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndAddAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndAddRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddRelease $type$ value");
+        }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOr $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOr $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrRelease $type$ value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAnd $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAnd $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndRelease $type$ value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXor $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXor $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(recv, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorRelease $type$ value");
+        }
+#end[Bitwise]
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccess$Type$ recv, Handles hs) throws Throwable {
+#if[!CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(recv, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$);
+            });
+        }
+#end[CAS]
+
+#if[!AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$);
+            });
+        }
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(recv, $value1$);
+            });
+        }
+#end[Bitwise]
+    }
+
+
+    static void testStaticField(Handles hs) throws Throwable {
+        // Plain
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "set $type$ value");
+        }
+
+
+        // Volatile
+        {
+            hs.get(TestAccessMode.SET_VOLATILE).invokeExact($value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
+            assertEquals(x, $value2$, "setVolatile $type$ value");
+        }
+
+        // Lazy
+        {
+            hs.get(TestAccessMode.SET_RELEASE).invokeExact($value1$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
+            assertEquals(x, $value1$, "setRelease $type$ value");
+        }
+
+        // Opaque
+        {
+            hs.get(TestAccessMode.SET_OPAQUE).invokeExact($value2$);
+            $type$ x = ($type$) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
+            assertEquals(x, $value2$, "setOpaque $type$ value");
+        }
+
+#if[CAS]
+        hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+        // Compare
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact($value1$, $value2$);
+            assertEquals(r, true, "success compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "success compareAndSet $type$ value");
+        }
+
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact($value1$, $value3$);
+            assertEquals(r, false, "failing compareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchange $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "success compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchange $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "failing compareAndExchange $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact($value1$, $value2$);
+            assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact($value1$, $value3$);
+            assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact($value2$, $value1$);
+            assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact($value2$, $value3$);
+            assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetPlain $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$);
+            }
+            assertEquals(success, true, "weakCompareAndSetRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+        }
+
+        {
+            boolean success = false;
+            for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value2$, $value1$);
+            }
+            assertEquals(success, true, "weakCompareAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "weakCompareAndSet $type$");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "getAndSet $type$ value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndSetAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "getAndSetAcquire $type$ value");
+        }
+
+        // Compare set and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndSetRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value2$, "getAndSetRelease $type$ value");
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        // get and add, add and get
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndAdd $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndAddAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndAddRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddRelease $type$ value");
+        }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOr $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOr $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrRelease $type$ value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAnd $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAnd $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndRelease $type$ value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXor $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXor $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact($value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorRelease $type$ value");
+        }
+#end[Bitwise]
+    }
+
+    static void testStaticFieldUnsupported(Handles hs) throws Throwable {
+#if[!CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact($value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact($value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact($value1$);
+            });
+        }
+#end[CAS]
+
+#if[!AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact($value1$);
+            });
+        }
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact($value1$);
+            });
+        }
+#end[Bitwise]
+    }
+
+
+    static void testArray(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "get $type$ value");
+            }
+
+
+            // Volatile
+            {
+                hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, $value2$);
+                $type$ x = ($type$) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
+                assertEquals(x, $value2$, "setVolatile $type$ value");
+            }
+
+            // Lazy
+            {
+                hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, $value1$);
+                $type$ x = ($type$) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
+                assertEquals(x, $value1$, "setRelease $type$ value");
+            }
+
+            // Opaque
+            {
+                hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, $value2$);
+                $type$ x = ($type$) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
+                assertEquals(x, $value2$, "setOpaque $type$ value");
+            }
+
+#if[CAS]
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            // Compare
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, $value1$, $value2$);
+                assertEquals(r, true, "success compareAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "success compareAndSet $type$ value");
+            }
+
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, $value1$, $value3$);
+                assertEquals(r, false, "failing compareAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "failing compareAndSet $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchange $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "success compareAndExchange $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchange $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchange $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, $value1$, $value2$);
+                assertEquals(r, $value1$, "success compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "success compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, $value1$, $value3$);
+                assertEquals(r, $value2$, "failing compareAndExchangeAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "failing compareAndExchangeAcquire $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, $value2$, $value1$);
+                assertEquals(r, $value2$, "success compareAndExchangeRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "success compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                $type$ r = ($type$) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, $value2$, $value3$);
+                assertEquals(r, $value1$, "failing compareAndExchangeRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "failing compareAndExchangeRelease $type$ value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSetPlain $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSetPlain $type$ value");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSetAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$);
+                }
+                assertEquals(success, true, "weakCompareAndSetRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
+            }
+
+            {
+                boolean success = false;
+                for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
+                    success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value2$, $value1$);
+                }
+                assertEquals(success, true, "weakCompareAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSet $type$");
+            }
+
+            // Compare set and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSet $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "getAndSet $type$ value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSetAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "getAndSetAcquire $type$ value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSetRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value2$, "getAndSetRelease $type$ value");
+            }
+#end[CAS]
+
+#if[AtomicAdd]
+            // get and add, add and get
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD).invokeExact(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndAdd $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, ($type$)($value1$ + $value2$), "getAndAdd $type$ value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD_ACQUIRE).invokeExact(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndAddAcquire $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddAcquire $type$ value");
+            }
+
+            {
+                hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_ADD_RELEASE).invokeExact(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndAddRelease $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, ($type$)($value1$ + $value2$), "getAndAddRelease $type$ value");
+            }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // get and bitwise or
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOr $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOr $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR_ACQUIRE).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_OR_RELEASE).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseOrRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ | $value2$), "getAndBitwiseOrRelease $type$ value");
+        }
+
+        // get and bitwise and
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAnd $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAnd $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND_ACQUIRE).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_AND_RELEASE).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseAndRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ & $value2$), "getAndBitwiseAndRelease $type$ value");
+        }
+
+        // get and bitwise xor
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXor $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXor $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_ACQUIRE).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorAcquire $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorAcquire $type$ value");
+        }
+
+        {
+            hs.get(TestAccessMode.SET).invokeExact(array, i, $value1$);
+
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_BITWISE_XOR_RELEASE).invokeExact(array, i, $value2$);
+            assertEquals(o, $value1$, "getAndBitwiseXorRelease $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+            assertEquals(x, ($type$)($value1$ ^ $value2$), "getAndBitwiseXorRelease $type$ value");
+        }
+#end[Bitwise]
+        }
+    }
+
+    static void testArrayUnsupported(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        final int i = 0;
+#if[!CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            checkUOE(am, () -> {
+                boolean r = (boolean) hs.get(am).invokeExact(array, i, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(array, i, $value1$, $value2$);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkUOE(am, () -> {
+                $type$ r = ($type$) hs.get(am).invokeExact(array, i, $value1$);
+            });
+        }
+#end[CAS]
+
+#if[!AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkUOE(am, () -> {
+                $type$ o = ($type$) hs.get(am).invokeExact(array, i, $value1$);
+            });
+        }
+#end[AtomicAdd]
+
+#if[!Bitwise]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkUOE(am, () -> {
+                $type$ o = ($type$) hs.get(am).invokeExact(array, i, $value1$);
+            });
+        }
+#end[Bitwise]
+    }
+
+    static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+                checkIOOBE(am, () -> {
+                    $type$ x = ($type$) hs.get(am).invokeExact(array, ci);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+                checkIOOBE(am, () -> {
+                    hs.get(am).invokeExact(array, ci, $value1$);
+                });
+            }
+
+#if[CAS]
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    boolean r = (boolean) hs.get(am).invokeExact(array, ci, $value1$, $value2$);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+                checkIOOBE(am, () -> {
+                    $type$ r = ($type$) hs.get(am).invokeExact(array, ci, $value2$, $value1$);
+                });
+            }
+
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+                checkIOOBE(am, () -> {
+                    $type$ o = ($type$) hs.get(am).invokeExact(array, ci, $value1$);
+                });
+            }
+#end[CAS]
+
+#if[AtomicAdd]
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+                checkIOOBE(am, () -> {
+                    $type$ o = ($type$) hs.get(am).invokeExact(array, ci, $value3$);
+                });
+            }
+#end[AtomicAdd]
+
+#if[Bitwise]
+            for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+                checkIOOBE(am, () -> {
+                    $type$ o = ($type$) hs.get(am).invokeExact(array, ci, $value3$);
+                });
+            }
+#end[Bitwise]
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template
new file mode 100644
index 0000000..d64749c
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template
@@ -0,0 +1,3293 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles;
+
+/*
+ * @test
+ * @bug 8156486
+ * @run testng/othervm VarHandleTestMethodType$Type$
+ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false VarHandleTestMethodType$Type$
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+import static java.lang.invoke.MethodType.*;
+
+public class VarHandleTestMethodType$Type$ extends VarHandleBaseTest {
+    static final $type$ static_final_v = $value1$;
+
+    static $type$ static_v = $value1$;
+
+    final $type$ final_v = $value1$;
+
+    $type$ v = $value1$;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodType$Type$.class, "final_v", $type$.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestMethodType$Type$.class, "v", $type$.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodType$Type$.class, "static_final_v", $type$.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestMethodType$Type$.class, "static_v", $type$.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle($type$[].class);
+    }
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceFieldWrongMethodType(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestMethodType$Type$::testArrayWrongMethodType,
+                                              false));
+
+        for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
+            cases.add(new MethodHandleAccessTestCase("Instance field",
+                                                     vhField, f, hs -> testInstanceFieldWrongMethodType(this, hs),
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Static field",
+                                                     vhStaticField, f, VarHandleTestMethodType$Type$::testStaticFieldWrongMethodType,
+                                                     false));
+
+            cases.add(new MethodHandleAccessTestCase("Array",
+                                                     vhArray, f, VarHandleTestMethodType$Type$::testArrayWrongMethodType,
+                                                     false));
+        }
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodType$Type$ recv, VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.get(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.get(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.get(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.get(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.get(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.get();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.get(recv, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.set(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.set(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.set(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(recv, $value1$, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getVolatile(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getVolatile(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.getVolatile(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getVolatile(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getVolatile(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getVolatile(recv, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setVolatile(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setVolatile(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setVolatile(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(recv, $value1$, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getOpaque(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getOpaque(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.getOpaque(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getOpaque(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getOpaque(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getOpaque(recv, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setOpaque(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setOpaque(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setOpaque(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(recv, $value1$, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAcquire(null);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAcquire(Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            $type$ x = ($type$) vh.getAcquire(0);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getAcquire(recv);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAcquire(recv);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAcquire(recv, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            vh.setRelease(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            vh.setRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(recv, $value1$, Void.class);
+        });
+
+
+#if[CAS]
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.compareAndSet(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.compareAndSet(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchange(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchange(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchange(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchange(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.compareAndExchange(0, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(recv, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchange(recv, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchange(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(0, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(recv, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeAcquire(recv, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeRelease(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(0, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(recv, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeRelease(recv, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeRelease(recv, $value1$, $value1$, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndSet(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndSet(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSet(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndSet(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSet(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSet(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSet(recv, $value1$, Void.class);
+        });
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndSetAcquire(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndSetAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSetAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndSetAcquire(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSetAcquire(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSetAcquire(recv, $value1$, Void.class);
+        });
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndSetRelease(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndSetRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSetRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndSetRelease(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSetRelease(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSetRelease(recv, $value1$, Void.class);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndAdd(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndAdd(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAdd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndAdd(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAdd(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAdd(recv, $value1$, Void.class);
+        });
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndAddAcquire(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndAddAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAddAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndAddAcquire(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAddAcquire(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAddAcquire(recv, $value1$, Void.class);
+        });
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndAddRelease(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndAddRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAddRelease(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndAddRelease(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAddRelease(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAddRelease(recv, $value1$, Void.class);
+        });
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseOr(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseOr(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOr(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOr(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOrAcquire(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseOr(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOr(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOr(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseAnd(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAnd(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAnd(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAndAcquire(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAnd(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAnd(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseXor(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseXor(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXor(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXor(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXorAcquire(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(recv, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(null, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(recv, Void.class);
+        });
+        checkWMTE(() -> { // reciever primitive class
+            $type$ x = ($type$) vh.getAndBitwiseXor(0, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(recv, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXor(recv, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXor(recv, $value1$, Void.class);
+        });
+#end[Bitwise]
+    }
+
+    static void testInstanceFieldWrongMethodType(VarHandleTestMethodType$Type$ recv, Handles hs) throws Throwable {
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class)).
+                    invokeExact(0);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class)).
+                    invokeExact(recv);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class)).
+                    invokeExact(recv);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                hs.get(am, methodType(void.class, Class.class, $type$.class)).
+                    invokeExact(Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, $type$.class)).
+                    invokeExact(0, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
+                    invokeExact(recv, $value1$, Void.class);
+            });
+        }
+
+#if[CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class, $type$.class)).
+                    invokeExact(Void.class, $value1$, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)).
+                    invokeExact(recv, Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
+                    invokeExact(recv, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class , $type$.class, $type$.class)).
+                    invokeExact(0, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)).
+                    invokeExact(recv, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class, $type$.class)).
+                    invokeExact(Void.class, $value1$, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class, $type$.class)).
+                    invokeExact(recv, Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, Class.class)).
+                    invokeExact(recv, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class , $type$.class, $type$.class)).
+                    invokeExact(0, $value1$, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)).
+                    invokeExact(recv, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class , $type$.class, $type$.class)).
+                    invokeExact(recv, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class, $type$.class, Class.class)).
+                    invokeExact(recv, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
+                    invokeExact(Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)).
+                    invokeExact(0, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$, Void.class);
+            });
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
+                    invokeExact(Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)).
+                    invokeExact(0, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$, Void.class);
+            });
+        }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact((VarHandleTestMethodType$Type$) null, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
+                    invokeExact(Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, Class.class)).
+                    invokeExact(recv, Void.class);
+            });
+            checkWMTE(() -> { // reciever primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, $type$.class)).
+                    invokeExact(0, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, VarHandleTestMethodType$Type$.class, $type$.class)).
+                    invokeExact(recv, $value1$, Void.class);
+            });
+        }
+#end[Bitwise]
+    }
+
+
+    static void testStaticFieldWrongMethodType(VarHandle vh) throws Throwable {
+        // Get
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.get();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.get();
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.get(Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.set(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set($value1$, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getVolatile();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getVolatile(Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setVolatile(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile($value1$, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getOpaque();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getOpaque(Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setOpaque(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque($value1$, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getAcquire();
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAcquire(Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setRelease(Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease($value1$, Void.class);
+        });
+
+
+#if[CAS]
+        // CompareAndSet
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.compareAndSet(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.compareAndSet($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet($value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain($value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet($value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire($value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease($value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchange(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchange($value1$, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange($value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchange($value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchange($value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire($value1$, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire($value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeAcquire($value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeAcquire($value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease($value1$, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease($value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeRelease($value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeRelease($value1$, $value1$, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSet(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSet($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSet($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSet($value1$, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSetAcquire(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSetAcquire($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSetAcquire($value1$, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSetRelease(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSetRelease($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSetRelease($value1$, Void.class);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        // GetAndAdd
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAdd(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAdd($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAdd($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAdd($value1$, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAddAcquire(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAddAcquire($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAddAcquire($value1$, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAddRelease(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAddRelease($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAddRelease($value1$, Void.class);
+        });
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOr($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOr($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOrAcquire($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseOrReleaseRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOrRelease($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAnd($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAnd($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAndAcquire($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAndReleaseRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAndRelease($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXor($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXor($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXorAcquire($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire($value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXorReleaseRelease
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease($value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXorRelease($value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease($value1$, Void.class);
+        });
+#end[Bitwise]
+    }
+
+    static void testStaticFieldWrongMethodType(Handles hs) throws Throwable {
+        int i = 0;
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class)).
+                    invokeExact();
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType(Class.class)).
+                    invokeExact(Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                hs.get(am, methodType(void.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, $type$.class, Class.class)).
+                    invokeExact($value1$, Void.class);
+            });
+        }
+#if[CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, $type$.class)).
+                    invokeExact(Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, Class.class)).
+                    invokeExact($value1$, Void.class);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$.class, $type$.class, Class.class)).
+                    invokeExact($value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, $type$.class)).
+                    invokeExact(Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
+                    invokeExact($value1$, Void.class);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$.class, $type$.class)).
+                    invokeExact($value1$, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class, $type$.class)).
+                    invokeExact($value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, $type$.class, Class.class)).
+                    invokeExact($value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)).
+                    invokeExact($value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)).
+                    invokeExact($value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
+                    invokeExact($value1$, Void.class);
+            });
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)).
+                    invokeExact($value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)).
+                    invokeExact($value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
+                    invokeExact($value1$, Void.class);
+            });
+        }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            check{#if[String]?CCE:WMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class)).
+                    invokeExact(Void.class);
+            });
+            // Incorrect return type
+            check{#if[String]?CCE:WMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$.class)).
+                    invokeExact($value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$.class)).
+                    invokeExact($value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$.class, Class.class)).
+                    invokeExact($value1$, Void.class);
+            });
+        }
+#end[Bitwise]
+    }
+
+
+    static void testArrayWrongMethodType(VarHandle vh) throws Throwable {
+        $type$[] array = new $type$[10];
+        Arrays.fill(array, $value1$);
+
+        // Get
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.get(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.get(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.get(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.get(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.get(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.get(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.get();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.get(array, 0, Void.class);
+        });
+
+
+        // Set
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.set(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.set(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.set(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.set(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.set(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.set();
+        });
+        checkWMTE(() -> { // >
+            vh.set(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getVolatile(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getVolatile(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getVolatile(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getVolatile(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getVolatile(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getVolatile(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getVolatile();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getVolatile(array, 0, Void.class);
+        });
+
+
+        // SetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setVolatile(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setVolatile(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setVolatile(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setVolatile(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setVolatile(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setVolatile();
+        });
+        checkWMTE(() -> { // >
+            vh.setVolatile(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getOpaque(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getOpaque(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getOpaque(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getOpaque(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getOpaque(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getOpaque(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getOpaque();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getOpaque(array, 0, Void.class);
+        });
+
+
+        // SetOpaque
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setOpaque(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setOpaque(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setOpaque(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setOpaque(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setOpaque(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setOpaque();
+        });
+        checkWMTE(() -> { // >
+            vh.setOpaque(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAcquire(null, 0);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAcquire(Void.class, 0);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAcquire(0, 0);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAcquire(array, Void.class);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void x = (Void) vh.getAcquire(array, 0);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAcquire(array, 0);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAcquire(array, 0, Void.class);
+        });
+
+
+        // SetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            vh.setRelease(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            vh.setRelease(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            vh.setRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            vh.setRelease(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            vh.setRelease(array, Void.class, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            vh.setRelease();
+        });
+        checkWMTE(() -> { // >
+            vh.setRelease(array, 0, $value1$, Void.class);
+        });
+
+
+#if[CAS]
+        // CompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.compareAndSet(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.compareAndSet(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.compareAndSet(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.compareAndSet(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.compareAndSet(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.compareAndSet(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.compareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.compareAndSet(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetPlain(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetPlain(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetPlain(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetPlain(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetPlain(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetPlain();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetPlain(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSet(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSet(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSet(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSet(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSet(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSet(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSet();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSet(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetAcquire(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetAcquire(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetAcquire(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetAcquire(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetAcquire(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // WeakCompareAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetRelease(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetRelease(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetRelease(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetRelease(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetRelease(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchange
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchange(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.compareAndExchange(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchange(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchange(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.compareAndExchange(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.compareAndExchange(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchange(array, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchange(array, 0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchange();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchange(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeAcquire(array, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeAcquire(array, 0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeAcquire(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // CompareAndExchangeRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            $type$ x = ($type$) vh.compareAndExchangeRelease(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.compareAndExchangeRelease(array, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.compareAndExchangeRelease(array, 0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.compareAndExchangeRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.compareAndExchangeRelease(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
+        // GetAndSet
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndSet(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndSet(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSet(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            $type$ x = ($type$) vh.getAndSet(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndSet(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSet(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSet(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSet();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSet(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndSetAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndSetAcquire(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndSetAcquire(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSetAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            $type$ x = ($type$) vh.getAndSetAcquire(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndSetAcquire(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSetAcquire(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSetAcquire(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSetAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSetAcquire(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndSetRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndSetRelease(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndSetRelease(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndSetRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // reciarrayever primitive class
+            $type$ x = ($type$) vh.getAndSetRelease(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndSetRelease(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndSetRelease(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndSetRelease(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndSetRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndSetRelease(array, 0, $value1$, Void.class);
+        });
+#end[CAS]
+
+#if[AtomicAdd]
+        // GetAndAdd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndAdd(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndAdd(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAdd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndAdd(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndAdd(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAdd(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAdd(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAdd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAdd(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndAddAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndAddAcquire(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndAddAcquire(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAddAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndAddAcquire(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndAddAcquire(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAddAcquire(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAddAcquire(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAddAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAddAcquire(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndAddRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndAddRelease(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndAddRelease(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndAddRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndAddRelease(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndAddRelease(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndAddRelease(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndAddRelease(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndAddRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndAddRelease(array, 0, $value1$, Void.class);
+        });
+#end[AtomicAdd]
+
+#if[Bitwise]
+        // GetAndBitwiseOr
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseOr(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseOr(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseOr(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOr(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOr(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOr();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOr(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseOrAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrAcquire(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOrAcquire(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOrAcquire(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseOrRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseOrRelease(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseOrRelease(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseOrRelease(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAnd
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseAnd(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseAnd(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAnd(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAnd(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAnd();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAnd(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAndAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndAcquire(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAndAcquire(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAndAcquire(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseAndRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseAndRelease(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseAndRelease(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseAndRelease(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXor
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseXor(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseXor(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseXor(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXor(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXor(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXor();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXor(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXorAcquire
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorAcquire(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXorAcquire(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXorAcquire(array, 0, $value1$, Void.class);
+        });
+
+
+        // GetAndBitwiseXorRelease
+        // Incorrect argument types
+        checkNPE(() -> { // null array
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(null, 0, $value1$);
+        });
+        checkCCE(() -> { // array reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(Void.class, 0, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // value reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(array, 0, Void.class);
+        });
+        checkWMTE(() -> { // array primitive class
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(0, 0, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(array, Void.class, $value1$);
+        });
+        // Incorrect return type
+        check{#if[String]?CCE:WMTE}(() -> { // reference class
+            Void r = (Void) vh.getAndBitwiseXorRelease(array, 0, $value1$);
+        });
+        checkWMTE(() -> { // primitive class
+            $wrong_primitive_type$ x = ($wrong_primitive_type$) vh.getAndBitwiseXorRelease(array, 0, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease();
+        });
+        checkWMTE(() -> { // >
+            $type$ x = ($type$) vh.getAndBitwiseXorRelease(array, 0, $value1$, Void.class);
+        });
+#end[Bitwise]
+    }
+
+    static void testArrayWrongMethodType(Handles hs) throws Throwable {
+        $type$[] array = new $type$[10];
+        Arrays.fill(array, $value1$);
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class)).
+                    invokeExact(($type$[]) null, 0);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class)).
+                    invokeExact(Void.class, 0);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class)).
+                    invokeExact(0, 0);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class)).
+                    invokeExact(array, Void.class);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void x = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class)).
+                    invokeExact(array, 0);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                hs.get(am, methodType(void.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                hs.get(am, methodType(void.class, Class.class, int.class, $type$.class)).
+                    invokeExact(Void.class, 0, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                hs.get(am, methodType(void.class, int.class, int.class, $type$.class)).
+                    invokeExact(0, 0, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                hs.get(am, methodType(void.class, $type$[].class, Class.class, $type$.class)).
+                    invokeExact(array, Void.class, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                hs.get(am, methodType(void.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                hs.get(am, methodType(void.class, $type$[].class, int.class, Class.class)).
+                    invokeExact(array, 0, $value1$, Void.class);
+            });
+        }
+#if[CAS]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // receiver reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, Class.class, int.class, $type$.class, $type$.class)).
+                    invokeExact(Void.class, 0, $value1$, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, Class.class, $type$.class)).
+                    invokeExact(array, 0, Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invokeExact(array, 0, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // receiver primitive class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, int.class, int.class, $type$.class, $type$.class)).
+                    invokeExact(0, 0, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, Class.class, $type$.class, $type$.class)).
+                    invokeExact(array, Void.class, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                boolean r = (boolean) hs.get(am, methodType(boolean.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                boolean r = (boolean) hs.get(am, methodType(boolean.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)).
+                    invokeExact(array, 0, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null receiver
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class, $type$.class)).
+                    invokeExact(Void.class, 0, $value1$, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // expected reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class, $type$.class)).
+                    invokeExact(array, 0, Void.class, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // actual reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invokeExact(array, 0, $value1$, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class, $type$.class)).
+                    invokeExact(0, 0, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class, $type$.class)).
+                    invokeExact(array, Void.class, $value1$, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invokeExact(array, 0, $value1$, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class, $type$.class)).
+                    invokeExact(array, 0, $value1$, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, $type$.class, Class.class)).
+                    invokeExact(array, 0, $value1$, $value1$, Void.class);
+            });
+        }
+
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)).
+                    invokeExact(Void.class, 0, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)).
+                    invokeExact(0, 0, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)).
+                    invokeExact(array, Void.class, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(array, 0, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(array, 0, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invokeExact(array, 0, $value1$, Void.class);
+            });
+        }
+#end[CAS]
+
+#if[AtomicAdd]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)).
+                    invokeExact(Void.class, 0, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)).
+                    invokeExact(0, 0, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)).
+                    invokeExact(array, Void.class, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(array, 0, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(array, 0, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invokeExact(array, 0, $value1$, Void.class);
+            });
+        }
+#end[AtomicAdd]
+
+#if[Bitwise]
+        for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
+            // Incorrect argument types
+            checkNPE(() -> { // null array
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(($type$[]) null, 0, $value1$);
+            });
+            hs.checkWMTEOrCCE(() -> { // array reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, Class.class, int.class, $type$.class)).
+                    invokeExact(Void.class, 0, $value1$);
+            });
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // value reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, Class.class)).
+                    invokeExact(array, 0, Void.class);
+            });
+            checkWMTE(() -> { // array primitive class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, int.class, int.class, $type$.class)).
+                    invokeExact(0, 0, $value1$);
+            });
+            checkWMTE(() -> { // index reference class
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, Class.class, $type$.class)).
+                    invokeExact(array, Void.class, $value1$);
+            });
+            // Incorrect return type
+            {#if[String]?hs.checkWMTEOrCCE:checkWMTE}(() -> { // reference class
+                Void r = (Void) hs.get(am, methodType(Void.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(array, 0, $value1$);
+            });
+            checkWMTE(() -> { // primitive class
+                $wrong_primitive_type$ x = ($wrong_primitive_type$) hs.get(am, methodType($wrong_primitive_type$.class, $type$[].class, int.class, $type$.class)).
+                    invokeExact(array, 0, $value1$);
+            });
+            // Incorrect arity
+            checkWMTE(() -> { // 0
+                $type$ x = ($type$) hs.get(am, methodType($type$.class)).
+                    invokeExact();
+            });
+            checkWMTE(() -> { // >
+                $type$ x = ($type$) hs.get(am, methodType($type$.class, $type$[].class, int.class, $type$.class, Class.class)).
+                    invokeExact(array, 0, $value1$, Void.class);
+            });
+        }
+#end[Bitwise]
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java
new file mode 100644
index 0000000..29759a9
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package for test.
+package test.java.lang.invoke.VarHandles.accessibility;
+
+/* @test
+ * @bug 8152645
+ * @summary test field lookup accessibility of MethodHandles and VarHandles
+ * @compile TestFieldLookupAccessibility.java
+ *          pkg/A.java pkg/B_extends_A.java pkg/C.java
+ *          pkg/subpkg/B_extends_A.java pkg/subpkg/C.java
+ * @run testng/othervm TestFieldLookupAccessibility
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import pkg.B_extends_A;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class TestFieldLookupAccessibility {
+
+    // The set of possible field lookup mechanisms
+    enum FieldLookup {
+        MH_GETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findGetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return !Modifier.isStatic(f.getModifiers());
+            }
+        },
+        MH_SETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findSetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return !Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers());
+            }
+        },
+        MH_STATIC_GETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findStaticGetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return Modifier.isStatic(f.getModifiers());
+            }
+        },
+        MH_STATIC_SETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findStaticSetter(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return Modifier.isStatic(f.getModifiers()) && !Modifier.isFinal(f.getModifiers());
+            }
+        },
+        MH_UNREFLECT_GETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectGetter(f);
+            }
+        },
+        MH_UNREFLECT_GETTER_ACCESSIBLE() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectGetter(cloneAndSetAccessible(f));
+            }
+        },
+        MH_UNREFLECT_SETTER() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectSetter(f);
+            }
+
+            boolean isAccessible(Field f) {
+                return f.isAccessible() || !Modifier.isFinal(f.getModifiers());
+            }
+        },
+        MH_UNREFLECT_SETTER_ACCESSIBLE() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectSetter(cloneAndSetAccessible(f));
+            }
+        },
+        VH() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return !Modifier.isStatic(f.getModifiers());
+            }
+        },
+        VH_STATIC() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.findStaticVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
+            }
+
+            boolean isAccessible(Field f) {
+                return Modifier.isStatic(f.getModifiers());
+            }
+        },
+        VH_UNREFLECT() {
+            Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
+                return l.unreflectVarHandle(f);
+            }
+        };
+
+        // Look up a handle to a field
+        abstract Object lookup(MethodHandles.Lookup l, Field f) throws Exception;
+
+        boolean isAccessible(Field f) {
+            return true;
+        }
+
+        static Field cloneAndSetAccessible(Field f) throws Exception {
+            // Clone to avoid mutating source field
+            f = f.getDeclaringClass().getDeclaredField(f.getName());
+            f.setAccessible(true);
+            return f;
+        }
+    }
+
+    @DataProvider
+    public Object[][] lookupProvider() throws Exception {
+        Stream<List<Object>> baseCases = Stream.of(
+                // Look up from same package
+                List.of(pkg.A.class, pkg.A.lookup(), pkg.A.inaccessibleFields()),
+                List.of(pkg.A.class, pkg.A.lookup(), pkg.A.inaccessibleFields()),
+                List.of(pkg.A.class, B_extends_A.lookup(), B_extends_A.inaccessibleFields()),
+                List.of(pkg.A.class, pkg.C.lookup(), pkg.C.inaccessibleFields()),
+
+                // Look up from sub-package
+                List.of(pkg.A.class, pkg.subpkg.B_extends_A.lookup(), pkg.subpkg.B_extends_A.inaccessibleFields()),
+                List.of(pkg.A.class, pkg.subpkg.C.lookup(), pkg.subpkg.C.inaccessibleFields())
+        );
+
+        // Cross product base cases with the field lookup classes
+        return baseCases.
+                flatMap(l -> Stream.of(FieldLookup.values()).map(fl -> prepend(fl, l))).
+                toArray(Object[][]::new);
+    }
+
+    private static Object[] prepend(Object o, List<Object> l) {
+        List<Object> pl = new ArrayList<>();
+        pl.add(o);
+        pl.addAll(l);
+        return pl.toArray();
+    }
+
+    @Test(dataProvider = "lookupProvider")
+    public void test(FieldLookup fl, Class<?> src, MethodHandles.Lookup l, Set<String> inaccessibleFields) {
+        // Add to the expected failures all inaccessible fields due to accessibility modifiers
+        Set<String> expected = new HashSet<>(inaccessibleFields);
+        Map<Field, Throwable> actual = new HashMap<>();
+
+        for (Field f : fields(src)) {
+            // Add to the expected failures all inaccessible fields due to static/final modifiers
+            if (!fl.isAccessible(f)) {
+                expected.add(f.getName());
+            }
+
+            try {
+                fl.lookup(l, f);
+            }
+            catch (Throwable t) {
+                // Lookup failed, add to the actual failures
+                actual.put(f, t);
+            }
+        }
+
+        Set<String> actualFieldNames = actual.keySet().stream().map(Field::getName).
+                collect(Collectors.toSet());
+        if (!actualFieldNames.equals(expected)) {
+            if (actualFieldNames.isEmpty()) {
+                // Setting the accessibility bit of a Field grants access under
+                // all conditions for MethodHander getters and setters
+                if (fl != FieldLookup.MH_UNREFLECT_GETTER_ACCESSIBLE &&
+                    fl != FieldLookup.MH_UNREFLECT_SETTER_ACCESSIBLE) {
+                    Assert.assertEquals(actualFieldNames, expected, "No accessibility failures:");
+                }
+            }
+            else {
+                Assert.assertEquals(actualFieldNames, expected, "Accessibility failures differ:");
+            }
+        }
+        else {
+            if (!actual.values().stream().allMatch(IllegalAccessException.class::isInstance)) {
+                Assert.fail("Expecting an IllegalArgumentException for all failures " + actual);
+            }
+        }
+    }
+
+    static List<Field> fields(Class<?> src) {
+        return List.of(src.getDeclaredFields());
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/A.java b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/A.java
new file mode 100644
index 0000000..c81bf4d
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/A.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class A {
+    public static Object f_public_static;
+    protected static Object f_protected_static;
+    static /*package*/ Object f_package_static;
+    private static Object f_private_static;
+
+    public static final Object f_public_static_final = null;
+    protected static final Object f_protected_static_final = null;
+    static /*package*/ final Object f_package_static_final = null;
+    private static final Object f_private_static_final = null;
+
+    public Object f_public;
+    protected Object f_protected;
+    /*package*/ Object f_package;
+    private Object f_private;
+
+    public final Object f_public_final = null;
+    protected final Object f_protected_final = null;
+    /*package*/ final Object f_package_final = null;
+    private final Object f_private_final = null;
+
+    //
+
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // All fields of pkg.A are accessible to itself
+        return Set.of();
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/B_extends_A.java b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/B_extends_A.java
new file mode 100644
index 0000000..026f7cc
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/B_extends_A.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class B_extends_A extends A {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only private fields of pkg.A are not accessible to subclass pkg.B
+        // Note: protected fields are also package accessible
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_private_static",
+                "f_private_static_final"
+        );
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/C.java b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/C.java
new file mode 100644
index 0000000..fcf1f0b
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/C.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class C {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only private fields of pkg.A are not accessible to independent
+        // class pkg.C
+        // Note: protected fields are also package accessible
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_private_static",
+                "f_private_static_final"
+        );
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/B_extends_A.java b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/B_extends_A.java
new file mode 100644
index 0000000..0ee5fba
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/B_extends_A.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg.subpkg;
+
+
+import pkg.A;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class B_extends_A extends A {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only public and protected fields of pkg.A are accessible to subclass
+        // pkg.subpkg.B
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_package",
+                "f_package_final",
+                "f_private_static",
+                "f_private_static_final",
+                "f_package_static",
+                "f_package_static_final"
+        );
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/C.java b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/C.java
new file mode 100644
index 0000000..c2fd8ac
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/accessibility/pkg/subpkg/C.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pkg.subpkg;
+
+
+import java.lang.invoke.MethodHandles;
+import java.util.Set;
+
+public class C {
+    public static MethodHandles.Lookup lookup() {
+        return MethodHandles.lookup();
+    }
+
+    public static Set<String> inaccessibleFields() {
+        // Only public fields of pkg.A are accessible to independent
+        // class pkg.subpkg.C
+        return Set.of(
+                "f_private",
+                "f_private_final",
+                "f_protected",
+                "f_protected_final",
+                "f_package",
+                "f_package_final",
+                "f_private_static",
+                "f_private_static_final",
+                "f_protected_static",
+                "f_protected_static_final",
+                "f_package_static",
+                "f_package_static_final"
+        );
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/VarHandles/generate-vh-tests.sh b/ojluni/src/test/java/lang/invoke/VarHandles/generate-vh-tests.sh
new file mode 100644
index 0000000..d3b4197
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarHandles/generate-vh-tests.sh
@@ -0,0 +1,169 @@
+#!/bin/bash
+
+# Android-changed: different path to Spp.java
+# javac -d . ../../../../../../make/jdk/src/classes/build/tools/spp/Spp.java
+javac -d . $ANDROID_BUILD_TOP/libcore/ojluni/src/tools/build/tools/spp/Spp.java
+
+SPP=build.tools.spp.Spp
+
+# Generates variable handle tests for objects and all primitive types
+# This is likely to be a temporary testing approach as it may be more
+# desirable to generate code using ASM which will allow more flexibility
+# in the kinds of tests that are generated.
+
+for type in boolean byte short char int long float double String
+do
+  Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
+  args="-K$type -Dtype=$type -DType=$Type"
+
+  args="$args -KCAS"
+
+  case $type in
+    byte|short|char|int|long|float|double)
+      args="$args -KAtomicAdd"
+      ;;
+  esac
+
+  case $type in
+    boolean|byte|short|char|int|long)
+      args="$args -KBitwise"
+      ;;
+  esac
+
+  wrong_primitive_type=boolean
+
+  case $type in
+    boolean)
+      value1=true
+      value2=false
+      value3=false
+      wrong_primitive_type=int
+      ;;
+    byte)
+      value1=(byte)0x01
+      value2=(byte)0x23
+      value3=(byte)0x45
+      ;;
+    short)
+      value1=(short)0x0123
+      value2=(short)0x4567
+      value3=(short)0x89AB
+      ;;
+    char)
+      value1=\'\\\\u0123\'
+      value2=\'\\\\u4567\'
+      value3=\'\\\\u89AB\'
+      ;;
+    int)
+      value1=0x01234567
+      value2=0x89ABCDEF
+      value3=0xCAFEBABE
+      ;;
+    long)
+      value1=0x0123456789ABCDEFL
+      value2=0xCAFEBABECAFEBABEL
+      value3=0xDEADBEEFDEADBEEFL
+      ;;
+    float)
+      value1=1.0f
+      value2=2.0f
+      value3=3.0f
+      ;;
+    double)
+      value1=1.0d
+      value2=2.0d
+      value3=3.0d
+      ;;
+    String)
+      value1=\"foo\"
+      value2=\"bar\"
+      value3=\"baz\"
+      ;;
+  esac
+
+  args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3 -Dwrong_primitive_type=$wrong_primitive_type"
+
+  echo $args
+  java $SPP -nel $args < X-VarHandleTestAccess.java.template > VarHandleTestAccess${Type}.java
+  java $SPP -nel $args < X-VarHandleTestMethodHandleAccess.java.template > VarHandleTestMethodHandleAccess${Type}.java
+  java $SPP -nel $args < X-VarHandleTestMethodType.java.template > VarHandleTestMethodType${Type}.java
+done
+
+for type in short char int long float double
+do
+  Type="$(tr '[:lower:]' '[:upper:]' <<< ${type:0:1})${type:1}"
+  args="-K$type -Dtype=$type -DType=$Type"
+
+  BoxType=$Type
+  case $type in
+    char)
+      BoxType=Character
+      ;;
+    int)
+      BoxType=Integer
+      ;;
+  esac
+  args="$args -DBoxType=$BoxType"
+
+  case $type in
+    int|long|float|double)
+      args="$args -KCAS"
+      ;;
+  esac
+
+  case $type in
+    int|long)
+      args="$args -KAtomicAdd"
+      ;;
+  esac
+
+  case $type in
+    int|long)
+      args="$args -KBitwise"
+      ;;
+  esac
+
+  # The value of `value3` is chosen such that when added to `value1` or `value2`
+  # it will result in carrying of bits over to the next byte, thereby detecting
+  # possible errors in endianness conversion e.g. if say for atomic addition the
+  # augend is incorrectly processed
+  case $type in
+    short)
+      value1=(short)0x0102
+      value2=(short)0x1112
+      value3=(short)0xFFFE
+      ;;
+    char)
+      value1=(char)0x0102
+      value2=(char)0x1112
+      value3=(char)0xFFFE
+      ;;
+    int)
+      value1=0x01020304
+      value2=0x11121314
+      value3=0xFFFEFDFC
+      ;;
+    long)
+      value1=0x0102030405060708L
+      value2=0x1112131415161718L
+      value3=0xFFFEFDFCFBFAF9F8L
+      ;;
+    float)
+      value1=0x01020304
+      value2=0x11121314
+      value3=0xFFFEFDFC
+      ;;
+    double)
+      value1=0x0102030405060708L
+      value2=0x1112131415161718L
+      value3=0xFFFEFDFCFBFAF9F8L
+      ;;
+  esac
+
+  args="$args -Dvalue1=$value1 -Dvalue2=$value2 -Dvalue3=$value3"
+
+  echo $args
+  java $SPP -nel $args < X-VarHandleTestByteArrayView.java.template > VarHandleTestByteArrayAs${Type}.java
+done
+
+rm -fr build
diff --git a/ojluni/src/test/java/lang/invoke/VarargsArrayTest.java b/ojluni/src/test/java/lang/invoke/VarargsArrayTest.java
new file mode 100644
index 0000000..aec41779
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/VarargsArrayTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// Android-added: package name.
+package test.java.lang.invoke;
+
+import sun.invoke.util.Wrapper;
+import test.java.lang.invoke.lib.CodeCacheOverflowProcessor;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.Collections;
+
+// Android-added: testng imports.
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.*;
+
+/* @test
+ * @summary unit tests for varargs array methods: MethodHandleInfo.varargsArray(int),
+ *          MethodHandleInfo.varargsArray(Class,int) & MethodHandleInfo.varargsList(int)
+ * @modules java.base/sun.invoke.util
+ * @library /lib/testlibrary /java/lang/invoke/common
+ * @compile/module=java.base java/lang/invoke/MethodHandleHelper.java
+ * @run main/bootclasspath VarargsArrayTest
+ * @run main/bootclasspath/othervm -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250
+ *                         VarargsArrayTest
+ */
+
+/* This might take a while and burn lots of metadata:
+ * @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.EXHAUSTIVE=true VarargsArrayTest
+ */
+public class VarargsArrayTest {
+    private static final Class<?> CLASS = VarargsArrayTest.class;
+    private static final int MAX_ARITY = Integer.getInteger(
+            CLASS.getSimpleName()+".MAX_ARITY", 40);
+    private static final int START_ARITY = Integer.getInteger(
+            CLASS.getSimpleName()+".START_ARITY", 0);
+    private static final boolean EXHAUSTIVE = Boolean.getBoolean(
+            CLASS.getSimpleName()+".EXHAUSTIVE");
+
+    public static void main(String[] args) throws Throwable {
+        // Android-removed: test converted to testng.
+        // CodeCacheOverflowProcessor.runMHTest(VarargsArrayTest::test);
+    }
+
+    // Android-removed: Added @Test annotations.
+    /*
+    @Test
+    public static void test() throws Throwable {
+        testVarargsArray();
+        testVarargsReferenceArray();
+        testVarargsPrimitiveArray();
+    }
+    */
+
+    // Android-added: @Test annotation.
+    @Test
+    public static void testVarargsArray() throws Throwable {
+        final int MIN = START_ARITY;
+        final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
+        for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) {
+            // Android-changed: use VarargsArrayTest.varargsArray().
+            // MethodHandle target = MethodHandleHelper.varargsArray(nargs);
+            MethodHandle target = varargsArray(Object[].class, nargs);
+            Object[] args = new Object[nargs];
+            for (int i = 0; i < nargs; i++)
+                args[i] = "#"+i;
+            Object res = target.invokeWithArguments(args);
+            assertArrayEquals(args, (Object[])res);
+        }
+    }
+
+    // Android-added: @Test annotation.
+    @Test
+    public static void testVarargsReferenceArray() throws Throwable {
+        testTypedVarargsArray(Object[].class);
+        testTypedVarargsArray(String[].class);
+        testTypedVarargsArray(Number[].class);
+    }
+
+    // Android-added: @Test annotation.
+    @Test
+    public static void testVarargsPrimitiveArray() throws Throwable {
+        testTypedVarargsArray(int[].class);
+        testTypedVarargsArray(long[].class);
+        testTypedVarargsArray(byte[].class);
+        testTypedVarargsArray(boolean[].class);
+        testTypedVarargsArray(short[].class);
+        testTypedVarargsArray(char[].class);
+        testTypedVarargsArray(float[].class);
+        testTypedVarargsArray(double[].class);
+    }
+
+    private static int nextArgCount(int nargs, int density, int MAX) {
+        if (EXHAUSTIVE)  return nargs + 1;
+        if (nargs >= MAX)  return Integer.MAX_VALUE;
+        int BOT = 20, TOP = MAX-5;
+        if (density < 10) { BOT = 10; MAX = TOP-2; }
+        if (nargs <= BOT || nargs >= TOP) {
+            ++nargs;
+        } else {
+            int bump = Math.max(1, 100 / density);
+            nargs += bump;
+            if (nargs > TOP)  nargs = TOP;
+        }
+        return nargs;
+    }
+
+    // Android-added: simplified alternative to MethodHandleHelper.varargsArray().
+    private static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
+        return MethodHandles.identity(arrayType).asCollector(arrayType, nargs);
+    }
+
+    private static void testTypedVarargsArray(Class<?> arrayType) throws Throwable {
+        Class<?> elemType = arrayType.getComponentType();
+        int MIN = START_ARITY;
+        int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
+        int density = 3;
+        if (elemType == int.class || elemType == long.class)  density = 7;
+        if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; }
+        for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) {
+            Object[] args = makeTestArray(elemType, nargs);
+            // Android-changed: used varargsArrayHelper above.
+            // MethodHandle varargsArray = MethodHandleHelper.varargsArray(arrayType, nargs);
+            MethodHandle varargsArray = varargsArray(arrayType, nargs);
+            MethodType vaType = varargsArray.type();
+            assertEquals(arrayType, vaType.returnType());
+            if (nargs != 0) {
+                assertEquals(elemType, vaType.parameterType(0));
+                assertEquals(elemType, vaType.parameterType(vaType.parameterCount()-1));
+            }
+            assertEquals(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)),
+                         vaType);
+            Object res = varargsArray.invokeWithArguments(args);
+            assertEquals(res.getClass(), arrayType);
+            String resString = toArrayString(res);
+            assertEquals(Arrays.toString(args), resString);
+
+            MethodHandle spreader = varargsArray.asSpreader(arrayType, nargs);
+            MethodType stype = spreader.type();
+            assert(stype == MethodType.methodType(arrayType, arrayType));
+            if (nargs <= 5) {
+                // invoke target as a spreader also:
+                @SuppressWarnings("cast")
+                Object res2 = spreader.invokeWithArguments((Object)res);
+                String res2String = toArrayString(res2);
+                assertEquals(Arrays.toString(args), res2String);
+                // invoke the spreader on a generic Object[] array; check for error
+                try {
+                    Object res3 = spreader.invokeWithArguments((Object)args);
+                    String res3String = toArrayString(res3);
+                    assertTrue(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
+                    assertEquals(Arrays.toString(args), res3String);
+                } catch (ClassCastException ex) {
+                    assertFalse(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
+                }
+            }
+            if (nargs == 0) {
+                // invoke spreader on null arglist
+                Object res3 = spreader.invokeWithArguments((Object)null);
+                String res3String = toArrayString(res3);
+                assertEquals(Arrays.toString(args), res3String);
+            }
+        }
+    }
+
+    private static Object[] makeTestArray(Class<?> elemType, int len) {
+        Wrapper elem = null;
+        if (elemType.isPrimitive())
+            elem = Wrapper.forPrimitiveType(elemType);
+        else if (Wrapper.isWrapperType(elemType))
+            elem = Wrapper.forWrapperType(elemType);
+        Object[] args = new Object[len];
+        for (int i = 0; i < len; i++) {
+            Object arg = i * 100;
+            if (elem == null) {
+                if (elemType == String.class)
+                    arg = "#"+arg;
+                arg = elemType.cast(arg);  // just to make sure
+            } else {
+                switch (elem) {
+                    case BOOLEAN: arg = (i % 3 == 0);           break;
+                    case CHAR:    arg = 'a' + i;                break;
+                    case LONG:    arg = (long)i * 1000_000_000; break;
+                    case FLOAT:   arg = (float)i / 100;         break;
+                    case DOUBLE:  arg = (double)i / 1000_000;   break;
+                }
+                arg = elem.cast(arg, elemType);
+            }
+            args[i] = arg;
+        }
+        return args;
+    }
+
+    private static String toArrayString(Object a) {
+        if (a == null)  return "null";
+        Class<?> elemType = a.getClass().getComponentType();
+        if (elemType == null)  return a.toString();
+        if (elemType.isPrimitive()) {
+            switch (Wrapper.forPrimitiveType(elemType)) {
+                case INT:      return Arrays.toString((int[])a);
+                case BYTE:     return Arrays.toString((byte[])a);
+                case BOOLEAN:  return Arrays.toString((boolean[])a);
+                case SHORT:    return Arrays.toString((short[])a);
+                case CHAR:     return Arrays.toString((char[])a);
+                case FLOAT:    return Arrays.toString((float[])a);
+                case LONG:     return Arrays.toString((long[])a);
+                case DOUBLE:   return Arrays.toString((double[])a);
+            }
+        }
+        return Arrays.toString((Object[])a);
+    }
+
+    public static void assertArrayEquals(Object[] arr1, Object[] arr2) {
+        if (arr1 == null && arr2 == null)  return;
+        if (arr1 != null && arr2 != null && arr1.length == arr2.length) {
+            for (int i = 0; i < arr1.length; i++) {
+                assertEquals(arr1[i], arr2[i]);
+            }
+            return;
+        }
+        throw new AssertionError(Arrays.deepToString(arr1)
+                + " != " + Arrays.deepToString(arr2));
+    }
+
+    // Android-removed: use asserts from testng API for use in test harness.
+    /*
+    public static void assertEquals(Object o1, Object o2) {
+        if (o1 == null && o2 == null)    return;
+        if (o1 != null && o1.equals(o2)) return;
+        throw new AssertionError(o1 + " != " + o2);
+    }
+
+    public static void assertTrue(String msg, boolean b) {
+        if (!b) {
+            throw new AssertionError(msg);
+        }
+    }
+
+    public static void assertFalse(String msg, boolean b) {
+        assertTrue(msg, !b);
+    }
+    */
+}
diff --git a/ojluni/src/test/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java b/ojluni/src/test/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
new file mode 100644
index 0000000..9561660
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.lang.invoke.lib;
+
+// Android-added: import of Function for filterException
+import java.util.function.Function;
+
+/**
+ * Helper class used to catch and process VirtualMachineError with message "Out
+ * of space in CodeCache". Some JSR292 tests run out of code cache size, so code
+ * cache overflows and VME is thrown. This VME is considered as non-critical in
+ * some JSR292 tests, so it should be processed to prevent test failure.
+ */
+public class CodeCacheOverflowProcessor {
+
+    /**
+     * Checks if an instance of Throwable is caused by VirtualMachineError with
+     * message "Out of space in CodeCache". May be used as filter in method
+     * {@code jdk.testlibrary.Utils.filterException}.
+     *
+     * @param t - Throwable to check.
+     * @return true if Throwable is caused by VME, false otherwise.
+     */
+    public static Boolean isThrowableCausedByVME(Throwable t) {
+        Throwable causeOfT = t;
+        do {
+            if (causeOfT instanceof VirtualMachineError
+                    && causeOfT.getMessage().matches(".*[Oo]ut of space"
+                            + " in CodeCache.*")) {
+                return true;
+            }
+            causeOfT = causeOfT != null ? causeOfT.getCause() : null;
+        } while (causeOfT != null && causeOfT != t);
+        return false;
+    }
+
+    /**
+     * Checks if the given test throws an exception caused by
+     * VirtualMachineError with message "Out of space in CodeCache", and, if VME
+     * takes place, processes it so that no exception is thrown, and prints its
+     * stack trace. If test throws exception not caused by VME, this method just
+     * re-throws this exception.
+     *
+     * @param test - test to check for and process VirtualMachineError.
+     * @return - an exception caused by VME or null
+     *           if test has thrown no exception.
+     * @throws Throwable - if test has thrown an exception
+     *                     that is not caused by VME.
+     */
+    public static Throwable runMHTest(ThrowingRunnable test) throws Throwable {
+        Throwable t = filterException(test::run,
+                CodeCacheOverflowProcessor::isThrowableCausedByVME);
+        if (t != null) {
+            System.err.printf("%nNon-critical exception caught becuse of"
+                    + " code cache size is not enough to run all test cases.%n%n");
+        }
+        return t;
+    }
+
+    // BEGIN Android-changed: these interfaces methods taken from jdk.testlibrary
+    /**
+     * Interface same as java.lang.Runnable but with
+     * method {@code run()} able to throw any Throwable.
+     */
+    public static interface ThrowingRunnable {
+        void run() throws Throwable;
+    }
+
+    /**
+     * Filters out an exception that may be thrown by the given
+     * test according to the given filter.
+     *
+     * @param test - method that is invoked and checked for exception.
+     * @param filter - function that checks if the thrown exception matches
+     *                 criteria given in the filter's implementation.
+     * @return - exception that matches the filter if it has been thrown or
+     *           {@code null} otherwise.
+     * @throws Throwable - if test has thrown an exception that does not
+     *                     match the filter.
+     */
+    public static Throwable filterException(ThrowingRunnable test,
+                                            Function<Throwable, Boolean> filter) throws Throwable {
+        try {
+            test.run();
+        } catch (Throwable t) {
+            if (filter.apply(t)) {
+                return t;
+            } else {
+                throw t;
+            }
+        }
+        return null;
+    }
+    // END Android-changed: these interfaces methods taken from jdk.testlibrary
+}
diff --git a/ojluni/src/test/java/lang/invoke/common/test/java/lang/invoke/lib/Helper.java b/ojluni/src/test/java/lang/invoke/common/test/java/lang/invoke/lib/Helper.java
new file mode 100644
index 0000000..5d6e318
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/common/test/java/lang/invoke/lib/Helper.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.lang.invoke.lib;
+
+// Android-removed: drop dependency on jdk.testlibrary.Asserts.
+// import jdk.testlibrary.Asserts;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+public class Helper {
+    /** Flag for verbose output, true if {@code -Dverbose} specified */
+    public static final boolean IS_VERBOSE
+            = System.getProperty("verbose") != null;
+    /**
+     * Flag for thorough testing -- all test will be executed,
+     * true if {@code -Dthorough} specified. */
+    public static final boolean IS_THOROUGH
+            = System.getProperty("thorough") != null;
+    /** Random number generator w/ initial seed equal to {@code -Dseed} */
+    public static final Random RNG;
+
+    static {
+        String str = System.getProperty("seed");
+        long seed = str != null ? Long.parseLong(str) : new Random().nextLong();
+        RNG = new Random(seed);
+        System.out.printf("-Dseed=%d%n", seed);
+    }
+
+    public static final long TEST_LIMIT;
+    static {
+        String str = System.getProperty("testLimit");
+        TEST_LIMIT = str != null ? Long.parseUnsignedLong(str) : 2000L;
+        System.out.printf("-DtestLimit=%d%n", TEST_LIMIT);
+    }
+
+    public static final int MAX_ARITY = 254;
+    public static final String MISSING_ARG = "missingArg";
+    public static final String MISSING_ARG_2 = "missingArg#2";
+
+    private static final int
+            // first int value
+            ONE_MILLION = (1000 * 1000),
+            // scale factor to reach upper 32 bits
+            TEN_BILLION = (10 * 1000 * 1000 * 1000),
+            // <<1 makes space for sign bit;
+            INITIAL_ARG_VAL = ONE_MILLION << 1;
+
+    public static final MethodHandle AS_LIST;
+
+    static {
+        try {
+            AS_LIST = MethodHandles.lookup().findStatic(
+                    Arrays.class, "asList",
+                    MethodType.methodType(List.class, Object[].class));
+        } catch (NoSuchMethodException | IllegalAccessException ex) {
+            throw new Error(ex);
+        }
+    }
+
+    public static boolean isDoubleCost(Class<?> aClass) {
+        return aClass == double.class || aClass == long.class;
+    }
+
+    private static List<List<Object>> calledLog = new ArrayList<>();
+    private static long nextArgVal;
+
+    public static void assertCalled(String name, Object... args) {
+        assertCalled(0, name, args);
+    }
+
+    public static void assertCalled(int lag, String name, Object... args) {
+        Object expected = logEntry(name, args);
+        Object actual = getCalled(lag);
+        // Android-changed: check and throw in-situ.
+        // Asserts.assertEQ(expected, actual, "method call w/ lag = " + lag);
+        if (expected != actual) {
+            throw new AssertionError("Expected " + expected + " actual " + actual +
+                    "method call w/ lag = " + lag);
+        }
+    }
+
+    public static Object called(String name, Object... args) {
+        List<Object> entry = logEntry(name, args);
+        calledLog.add(entry);
+        return entry;
+    }
+
+    private static List<Object> logEntry(String name, Object... args) {
+        return Arrays.asList(name, Arrays.asList(args));
+    }
+
+    public static void clear() {
+        calledLog.clear();
+    }
+
+    public static List<Object> getCalled(int lag) {
+        int size = calledLog.size();
+        return size <= lag ? null : calledLog.get(size - lag - 1);
+    }
+
+    public static List<Class<?>> randomClasses(Class<?>[] classes, int size) {
+        List<Class<?>> result = new ArrayList<>(size);
+        for (int i = 0; i < size; ++i) {
+            result.add(classes[RNG.nextInt(classes.length)]);
+        }
+        return result;
+    }
+
+    public static List<Class<?>> getParams(List<Class<?>> classes,
+            boolean isVararg, int argsCount) {
+        boolean unmodifiable = true;
+        List<Class<?>> result = classes.subList(0,
+                Math.min(argsCount, (MAX_ARITY / 2) - 1));
+        int extra = 0;
+        if (argsCount >= MAX_ARITY / 2) {
+            result = new ArrayList<>(result);
+            unmodifiable = false;
+            extra = (int) result.stream().filter(Helper::isDoubleCost).count();
+            int i = result.size();
+            while (result.size() + extra < argsCount) {
+                Class<?> aClass = classes.get(i);
+                if (Helper.isDoubleCost(aClass)) {
+                    ++extra;
+                    if (result.size() + extra >= argsCount) {
+                        break;
+                    }
+                }
+                result.add(aClass);
+            }
+        }
+        if (isVararg && result.size() > 0) {
+            if (unmodifiable) {
+                result = new ArrayList<>(result);
+            }
+            int last = result.size() - 1;
+            Class<?> aClass = result.get(last);
+            aClass = Array.newInstance(aClass, 2).getClass();
+            result.set(last, aClass);
+        }
+        return result;
+    }
+
+    public static MethodHandle addTrailingArgs(MethodHandle target, int nargs,
+            List<Class<?>> classes) {
+        int targetLen = target.type().parameterCount();
+        int extra = (nargs - targetLen);
+        if (extra <= 0) {
+            return target;
+        }
+        List<Class<?>> fakeArgs = new ArrayList<>(extra);
+        for (int i = 0; i < extra; ++i) {
+            fakeArgs.add(classes.get(i % classes.size()));
+        }
+        return MethodHandles.dropArguments(target, targetLen, fakeArgs);
+    }
+
+    public static MethodHandle varargsList(int arity) {
+        return AS_LIST.asCollector(Object[].class, arity);
+    }
+
+    private static long nextArg(boolean moreBits) {
+        long val = nextArgVal++;
+        long sign = -(val & 1); // alternate signs
+        val >>= 1;
+        if (moreBits)
+        // Guarantee some bits in the high word.
+        // In any case keep the decimal representation simple-looking,
+        // with lots of zeroes, so as not to make the printed decimal
+        // strings unnecessarily noisy.
+        {
+            val += (val % ONE_MILLION) * TEN_BILLION;
+        }
+        return val ^ sign;
+    }
+
+    private static int nextArg() {
+        // Produce a 32-bit result something like ONE_MILLION+(smallint).
+        // Example: 1_000_042.
+        return (int) nextArg(false);
+    }
+
+    private static long nextArg(Class<?> kind) {
+        if (kind == long.class || kind == Long.class ||
+                kind == double.class || kind == Double.class)
+        // produce a 64-bit result something like
+        // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+        // Example: 10_000_420_001_000_042.
+        {
+            return nextArg(true);
+        }
+        return (long) nextArg();
+    }
+
+    private static Object randomArg(Class<?> param) {
+        Object wrap = castToWrapperOrNull(nextArg(param), param);
+        if (wrap != null) {
+            return wrap;
+        }
+
+        if (param.isInterface()) {
+            for (Class<?> c : param.getClasses()) {
+                if (param.isAssignableFrom(c) && !c.isInterface()) {
+                    param = c;
+                    break;
+                }
+            }
+        }
+        if (param.isArray()) {
+            Class<?> ctype = param.getComponentType();
+            Object arg = Array.newInstance(ctype, 2);
+            Array.set(arg, 0, randomArg(ctype));
+            return arg;
+        }
+        if (param.isInterface() && param.isAssignableFrom(List.class)) {
+            return Arrays.asList("#" + nextArg());
+        }
+        if (param.isInterface() || param.isAssignableFrom(String.class)) {
+            return "#" + nextArg();
+        }
+
+        try {
+            return param.newInstance();
+        } catch (InstantiationException | IllegalAccessException ex) {
+        }
+        return null;  // random class not Object, String, Integer, etc.
+    }
+
+    public static Object[] randomArgs(Class<?>... params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < args.length; i++) {
+            args[i] = randomArg(params[i]);
+        }
+        return args;
+    }
+
+    public static Object[] randomArgs(int nargs, Class<?> param) {
+        Object[] args = new Object[nargs];
+        for (int i = 0; i < args.length; i++) {
+            args[i] = randomArg(param);
+        }
+        return args;
+    }
+
+    public static Object[] randomArgs(int nargs, Class<?>... params) {
+        Object[] args = new Object[nargs];
+        for (int i = 0; i < args.length; i++) {
+            Class<?> param = params[i % params.length];
+            args[i] = randomArg(param);
+        }
+        return args;
+    }
+
+    public static Object[] randomArgs(List<Class<?>> params) {
+        return randomArgs(params.toArray(new Class<?>[params.size()]));
+    }
+
+    public static Object castToWrapper(Object value, Class<?> dst) {
+        Object wrap = null;
+        if (value instanceof Number) {
+            wrap = castToWrapperOrNull(((Number) value).longValue(), dst);
+        }
+        if (value instanceof Character) {
+            wrap = castToWrapperOrNull((char) (Character) value, dst);
+        }
+        if (wrap != null) {
+            return wrap;
+        }
+        return dst.cast(value);
+    }
+
+    @SuppressWarnings("cast")
+    // primitive cast to (long) is part of the pattern
+    private static Object castToWrapperOrNull(long value, Class<?> dst) {
+        if (dst == int.class || dst == Integer.class) {
+            return (int) (value);
+        }
+        if (dst == long.class || dst == Long.class) {
+            return (long) (value);
+        }
+        if (dst == char.class || dst == Character.class) {
+            return (char) (value);
+        }
+        if (dst == short.class || dst == Short.class) {
+            return (short) (value);
+        }
+        if (dst == float.class || dst == Float.class) {
+            return (float) (value);
+        }
+        if (dst == double.class || dst == Double.class) {
+            return (double) (value);
+        }
+        if (dst == byte.class || dst == Byte.class) {
+            return (byte) (value);
+        }
+        if (dst == boolean.class || dst == Boolean.class) {
+            return ((value % 29) & 1) == 0;
+        }
+        return null;
+    }
+
+    /**
+     * Routine used to obtain a randomly generated method type.
+     *
+     * @param arity Arity of returned method type.
+     * @return MethodType generated randomly.
+     */
+    public static MethodType randomMethodTypeGenerator(int arity) {
+        final Class<?>[] CLASSES = {
+            Object.class,
+            int.class,
+            boolean.class,
+            byte.class,
+            short.class,
+            char.class,
+            long.class,
+            float.class,
+            double.class
+        };
+        if (arity > MAX_ARITY) {
+            throw new IllegalArgumentException(
+                    String.format("Arity should not exceed %d!", MAX_ARITY));
+        }
+        List<Class<?>> list = randomClasses(CLASSES, arity);
+        list = getParams(list, false, arity);
+        int i = RNG.nextInt(CLASSES.length + 1);
+        Class<?> rtype = i == CLASSES.length ? void.class : CLASSES[i];
+        return MethodType.methodType(rtype, list);
+    }
+}
diff --git a/ojluni/src/test/java/lang/invoke/remote/RemoteExample.java b/ojluni/src/test/java/lang/invoke/remote/RemoteExample.java
new file mode 100644
index 0000000..5237f9d
--- /dev/null
+++ b/ojluni/src/test/java/lang/invoke/remote/RemoteExample.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.invoke.remote;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import test.java.lang.invoke.MethodHandlesTest;
+
+/**
+ * Out-of-package access into protected members of test.java.lang.invoke.remote.MethodHandle.PubExample.
+ */
+public class RemoteExample extends MethodHandlesTest.PubExample {
+    public RemoteExample() { super("RemoteExample"); }
+    public static Lookup lookup() { return MethodHandles.lookup(); }
+    public final     void fin_v0() { MethodHandlesTest.called("Rem/fin_v0", this); }
+    protected        void pro_v0() { MethodHandlesTest.called("Rem/pro_v0", this); }
+    protected static void pro_s0() { MethodHandlesTest.called("Rem/pro_s0"); }
+}
diff --git a/ojluni/src/test/java/lang/ref/BasicTest.java b/ojluni/src/test/java/lang/ref/BasicTest.java
new file mode 100644
index 0000000..8d47984
--- /dev/null
+++ b/ojluni/src/test/java/lang/ref/BasicTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary Basic functional test of reference objects
+ * @author Mark Reinhold
+ */
+package test.java.lang.ref;
+
+import java.lang.ref.*;
+import java.util.Vector;
+
+import org.testng.annotations.Test;
+
+public class BasicTest {
+
+    static ReferenceQueue q = new ReferenceQueue();
+    static ReferenceQueue q2 = new ReferenceQueue();
+    static Reference rw, rw2, rp, rp2;
+    static Vector keep = new Vector();
+    static boolean finalized = false;
+
+    public static class ClearFinalizerThread {
+        protected void finalize() {
+            System.err.println("Cleared finalizer thread");
+        }
+    };
+
+    protected void finalize() {
+        BasicTest.finalized = true;
+        System.err.println("Finalized " + this);
+    }
+
+    public static class Sub { };
+
+    Object sub = new Sub();
+
+    static void fork(Runnable proc) throws InterruptedException {
+        Thread t = new Thread(proc);
+        t.start();
+        t.join();
+    }
+
+    static void showReferences() throws InterruptedException {
+        fork(new Runnable() {
+            public void run() {
+                System.err.println("References: W " + rw.get()
+                                   + ", W2 " + rw2.get()
+                                   + ", P " + rp.get()
+                                   + ", P2 " + rp2.get());
+            }
+        });
+    }
+
+    static void createNoise() throws InterruptedException {
+        fork(new Runnable() {
+            public void run() {
+                keep.addElement(new PhantomReference(new Object(), q2));
+            }
+        });
+    }
+
+    @Test
+    public void test() throws Exception {
+
+        fork(new Runnable() {
+            public void run() {
+                BasicTest s = new BasicTest();
+                rw = new WeakReference(s, q);
+                rw2 = new WeakReference(s);
+                rp = new PhantomReference(s, q);
+                rp2 = new PhantomReference(s.sub, q);
+                s = null;
+            }
+        });
+
+        showReferences();
+
+        int ndq = 0;
+        boolean prevFinalized = false;
+    outer:
+        for (int i = 1;; i++) {
+            Reference r;
+
+            createNoise();
+            System.err.println("GC " + i);
+            Thread.sleep(10);
+            System.gc();
+            System.runFinalization();
+
+            showReferences();
+            while ((r = q2.poll()) != null) {
+                System.err.println("Noise " + r);
+            }
+
+            /* Cause a dummy object to be finalized, since the finalizer thread
+               might retain a reference to the Basic instance after it's been
+               finalized (this happens with java_g) */
+            if (BasicTest.finalized && !prevFinalized) {
+                fork(new Runnable() {
+                    public void run() {
+                        new ClearFinalizerThread();
+                    }});
+                prevFinalized = true;
+            }
+
+            while ((r = q.poll()) != null) {
+                ndq++;
+                if (r != null) {
+                    System.err.println("Dequeued " + r);
+                    if (ndq == 3) break outer;
+                }
+            }
+
+            if (i >= 10) break;
+
+        }
+
+        if (ndq != 3) {
+            throw new Exception("Expected to dequeue 3 reference objects,"
+                                + " but only got " + ndq);
+        }
+
+        if (! BasicTest.finalized) {
+            throw new Exception("Test object not finalized");
+        }
+
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/ref/CleanerTest.java b/ojluni/src/test/java/lang/ref/CleanerTest.java
new file mode 100644
index 0000000..ec9874b
--- /dev/null
+++ b/ojluni/src/test/java/lang/ref/CleanerTest.java
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.lang.ref;
+
+import android.system.SystemCleaner;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Reference;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import jdk.internal.ref.PhantomCleanable;
+// Android-removed: WeakCleanable and SoftCleanable. b/198792576
+// import jdk.internal.ref.WeakCleanable;
+// import jdk.internal.ref.SoftCleanable;
+import jdk.internal.ref.CleanerFactory;
+
+// Android-removed: Remove sun.hotspot.WhiteBox usage
+// import sun.hotspot.WhiteBox;
+
+// Android-removed: inline Utils.adjustTimeout call
+// import jdk.test.lib.Utils;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @library /lib/testlibrary /test/lib
+ * @build sun.hotspot.WhiteBox
+ *        jdk.test.lib.Utils
+ *        jdk.test.lib.Asserts
+ *        jdk.test.lib.JDKToolFinder
+ *        jdk.test.lib.JDKToolLauncher
+ *        jdk.test.lib.Platform
+ *        jdk.test.lib.process.*
+ * @modules java.base/jdk.internal
+ *          java.base/jdk.internal.misc
+ *          java.base/jdk.internal.ref
+ *          java.management
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run testng/othervm
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      -verbose:gc CleanerTest
+ */
+
+public class CleanerTest {
+    // A common CleaningService used by the test for notifications
+    static final Cleaner COMMON = CleanerFactory.cleaner();
+
+    // Android-removed: Remove sun.hotspot.WhiteBox usage
+    // Access to WhiteBox utilities
+    // static final WhiteBox whitebox = WhiteBox.getWhiteBox();
+
+    /**
+     * Test that sequences of the various actions on a Reference
+     * and on the Cleanable instance have the desired result.
+     * The test cases are generated for each of phantom, weak and soft
+     * references.
+     * The sequence of actions includes all permutations to an initial
+     * list of actions including clearing the ref and resulting garbage
+     * collection actions on the reference and explicitly performing
+     * the cleaning action.
+     */
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testCleanableActions() {
+        Cleaner cleaner = Cleaner.create();
+
+        // Individually
+        generateCases(cleaner, c -> c.clearRef());
+        generateCases(cleaner, c -> c.doClean());
+
+        // Pairs
+        generateCases(cleaner, c -> c.doClean(), c -> c.clearRef());
+
+        CleanableCase s = setupPhantom(COMMON, cleaner);
+        cleaner = null;
+        checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:");
+    }
+
+    // Android-added: Test (trivially) SystemCleaner by repeating above.
+    /**
+     * Check that SystemCleaner.cleaner() also behaves as above.
+     */
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSystemCleanerActions() {
+        Cleaner cleaner = SystemCleaner.cleaner();
+
+        // Individually
+        generateCases(cleaner, c -> c.clearRef());
+        generateCases(cleaner, c -> c.doClean());
+
+        // Pairs
+        generateCases(cleaner, c -> c.doClean(), c -> c.clearRef());
+    }
+
+    /**
+     * Test the jdk.internal.misc APIs with sequences of the various actions
+     * on a Reference and on the Cleanable instance have the desired result.
+     * The test cases are generated for each of phantom, weak and soft
+     * references.
+     * The sequence of actions includes all permutations to an initial
+     * list of actions including clearing the ref and resulting garbage
+     * collection actions on the reference, explicitly performing
+     * the cleanup and explicitly clearing the cleaning action.
+     */
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testRefSubtypes() {
+        Cleaner cleaner = Cleaner.create();
+
+        // Individually
+        generateCasesInternal(cleaner, c -> c.clearRef());
+        generateCasesInternal(cleaner, c -> c.doClean());
+        generateCasesInternal(cleaner, c -> c.doClear());
+
+        // Pairs
+        generateCasesInternal(cleaner,
+                c -> c.doClear(), c -> c.doClean());
+
+        // Triplets
+        generateCasesInternal(cleaner,
+                c -> c.doClear(), c -> c.doClean(), c -> c.clearRef());
+
+        generateExceptionCasesInternal(cleaner);
+
+        CleanableCase s = setupPhantom(COMMON, cleaner);
+        cleaner = null;
+        checkCleaned(s.getSemaphore(), true, "Cleaner was cleaned:");
+    }
+
+    /**
+     * Generate tests using the runnables for each of phantom, weak,
+     * and soft references.
+     * @param cleaner  the cleaner
+     * @param runnables the sequence of actions on the test case
+     */
+    @SuppressWarnings("unchecked")
+    void generateCases(Cleaner cleaner, Consumer<CleanableCase>... runnables) {
+        generateCases(() -> setupPhantom(cleaner, null), runnables.length, runnables);
+    }
+
+    @SuppressWarnings("unchecked")
+    void generateCasesInternal(Cleaner cleaner, Consumer<CleanableCase>... runnables) {
+        generateCases(() -> setupPhantomSubclass(cleaner, null),
+                runnables.length, runnables);
+        // Android-removed: WeakCleanable and SoftCleanable. b/198792576
+        // generateCases(() -> setupWeakSubclass(cleaner, null),
+        //         runnables.length, runnables);
+        // generateCases(() -> setupSoftSubclass(cleaner, null),
+        //         runnables.length, runnables);
+    }
+
+    @SuppressWarnings("unchecked")
+    void generateExceptionCasesInternal(Cleaner cleaner) {
+        generateCases(() -> setupPhantomSubclassException(cleaner, null),
+                1, c -> c.clearRef());
+        // Android-removed: WeakCleanable and SoftCleanable. b/198792576
+        // generateCases(() -> setupWeakSubclassException(cleaner, null),
+        //         1, c -> c.clearRef());
+        // generateCases(() -> setupSoftSubclassException(cleaner, null),
+        //         1, c -> c.clearRef());
+    }
+
+    /**
+     * Generate all permutations of the sequence of runnables
+     * and test each one.
+     * The permutations are generated using Heap, B.R. (1963) Permutations by Interchanges.
+     * @param generator the supplier of a CleanableCase
+     * @param n the first index to interchange
+     * @param runnables the sequence of actions
+     */
+    @SuppressWarnings("unchecked")
+    void generateCases(Supplier<CleanableCase> generator, int n,
+                       Consumer<CleanableCase> ... runnables) {
+        if (n == 1) {
+            CleanableCase test = generator.get();
+            try {
+                verifyGetRef(test);
+
+                // Apply the sequence of actions on the Ref
+                for (Consumer<CleanableCase> c : runnables) {
+                    c.accept(test);
+                }
+                verify(test);
+            } catch (Exception e) {
+                Assert.fail(test.toString(), e);
+            }
+        } else {
+            for (int i = 0; i < n - 1; i += 1) {
+                generateCases(generator, n - 1, runnables);
+                Consumer<CleanableCase> t = runnables[n - 1];
+                int ndx = ((n & 1) == 0) ? i : 0;
+                runnables[n - 1] = runnables[ndx];
+                runnables[ndx] = t;
+            }
+            generateCases(generator, n - 1, runnables);
+        }
+    }
+
+    /**
+     * Verify the test case.
+     * Any actions directly on the Reference or Cleanable have been executed.
+     * The CleanableCase under test is given a chance to do the cleanup
+     * by forcing a GC.
+     * The result is compared with the expected result computed
+     * from the sequence of operations on the Cleanable.
+     * The Cleanable itself should have been cleanedup.
+     *
+     * @param test A CleanableCase containing the references
+     */
+    void verify(CleanableCase test) {
+        System.out.println(test);
+        int r = test.expectedResult();
+
+        CleanableCase cc = setupPhantom(COMMON, test.getCleanable());
+        test.clearCleanable();        // release this hard reference
+
+        checkCleaned(test.getSemaphore(),
+                r == CleanableCase.EV_CLEAN,
+                "Cleanable was cleaned:");
+        checkCleaned(cc.getSemaphore(), true,
+                "The reference to the Cleanable was freed:");
+    }
+
+    /**
+     * Verify that the reference.get works (or not) as expected.
+     * It handles the cases where UnsupportedOperationException is expected.
+     *
+     * @param test the CleanableCase
+     */
+    void verifyGetRef(CleanableCase test) {
+        Reference<?> r = (Reference) test.getCleanable();
+        try {
+            Object o = r.get();
+            Reference<?> expectedRef = test.getRef();
+            Assert.assertEquals(expectedRef.get(), o,
+                    "Object reference incorrect");
+            if (r.getClass().getName().endsWith("CleanableRef")) {
+                Assert.fail("should not be able to get referent");
+            }
+        } catch (UnsupportedOperationException uoe) {
+            if (r.getClass().getName().endsWith("CleanableRef")) {
+                // Expected exception
+            } else {
+                Assert.fail("Unexpected exception from subclassed cleanable: " +
+                        uoe.getMessage() + ", class: " + r.getClass());
+            }
+        }
+    }
+
+    // BEGIN Android-removed: Disable non-passing test.
+    /**
+     * Test that releasing the reference to the Cleaner service allows it to be
+     * be freed.
+     *
+    @Test
+    public void testCleanerTermination() {
+        ReferenceQueue<Object> queue = new ReferenceQueue<>();
+        Cleaner service = Cleaner.create();
+
+        PhantomReference<Object> ref = new PhantomReference<>(service, queue);
+        System.gc();
+        // Clear the Reference to the cleaning service and force a gc.
+        service = null;
+        System.gc();
+        try {
+            Reference<?> r = queue.remove(1000L);
+            Assert.assertNotNull(r, "queue.remove timeout,");
+            Assert.assertEquals(r, ref, "Wrong Reference dequeued");
+        } catch (InterruptedException ie) {
+            System.out.printf("queue.remove Interrupted%n");
+        }
+    }
+    // END Android-removed: Disable non-passing test.
+
+    /**
+     * Check a semaphore having been released by cleanup handler.
+     * Force a number of GC cycles to give the GC a chance to process
+     * the Reference and for the cleanup action to be run.
+     * Use a larger number of cycles to wait for an expected cleaning to occur.
+     *
+     * @param semaphore a Semaphore
+     * @param expectCleaned true if cleaning should occur
+     * @param msg a message to explain the error
+     */
+    static void checkCleaned(Semaphore semaphore, boolean expectCleaned,
+                             String msg) {
+        long max_cycles = expectCleaned ? 10 : 3;
+        long cycle = 0;
+        for (; cycle < max_cycles; cycle++) {
+            // Force GC
+            // Android-removed: Remove sun.hotspot.WhiteBox usage
+            // whitebox.fullGC();
+            Runtime.getRuntime().gc();
+
+            try {
+                // Android-changed: inline Utils.adjustTimeout call
+                // It is "Math.round(arg * Utils.TIMEOUT_FACTOR), where TIMEOUT_FACTOR defaults to 1.0"
+                //if (semaphore.tryAcquire(Utils.adjustTimeout(10L), TimeUnit.MILLISECONDS)) {
+                if (semaphore.tryAcquire(10L, TimeUnit.MILLISECONDS)) {
+                    System.out.printf(" Cleanable cleaned in cycle: %d%n", cycle);
+                    Assert.assertEquals(true, expectCleaned, msg);
+                    return;
+                }
+            } catch (InterruptedException ie) {
+                // retry in outer loop
+            }
+        }
+        // Object has not been cleaned
+        Assert.assertEquals(false, expectCleaned, msg);
+    }
+
+    /**
+     * Create a CleanableCase for a PhantomReference.
+     * @param cleaner the cleaner to use
+     * @param obj an object or null to create a new Object
+     * @return a new CleanableCase preset with the object, cleanup, and semaphore
+     */
+    static CleanableCase setupPhantom(Cleaner cleaner, Object obj) {
+        if (obj == null) {
+            obj = new Object();
+        }
+        Semaphore s1 = new Semaphore(0);
+        Cleaner.Cleanable c1 = cleaner.register(obj, () -> s1.release());
+
+        return new CleanableCase(new PhantomReference<>(obj, null), c1, s1);
+    }
+
+    /**
+     * Create a CleanableCase for a PhantomReference.
+     * @param cleaner the cleaner to use
+     * @param obj an object or null to create a new Object
+     * @return a new CleanableCase preset with the object, cleanup, and semaphore
+     */
+    static CleanableCase setupPhantomSubclass(Cleaner cleaner, Object obj) {
+        if (obj == null) {
+            obj = new Object();
+        }
+        Semaphore s1 = new Semaphore(0);
+
+        Cleaner.Cleanable c1 = new PhantomCleanable<Object>(obj, cleaner) {
+            protected void performCleanup() {
+                s1.release();
+            }
+        };
+
+        return new CleanableCase(new PhantomReference<>(obj, null), c1, s1);
+    }
+
+    // BEGIN Android-removed: WeakCleanable and SoftCleanable. b/198792576
+    /*
+     * Create a CleanableCase for a WeakReference.
+     * @param cleaner the cleaner to use
+     * @param obj an object or null to create a new Object
+     * @return a new CleanableCase preset with the object, cleanup, and semaphore
+     *
+    static CleanableCase setupWeakSubclass(Cleaner cleaner, Object obj) {
+        if (obj == null) {
+            obj = new Object();
+        }
+        Semaphore s1 = new Semaphore(0);
+
+        Cleaner.Cleanable c1 = new WeakCleanable<Object>(obj, cleaner) {
+            protected void performCleanup() {
+                s1.release();
+            }
+        };
+
+        return new CleanableCase(new WeakReference<>(obj, null), c1, s1);
+    }
+
+    /*
+     * Create a CleanableCase for a SoftReference.
+     * @param cleaner the cleaner to use
+     * @param obj an object or null to create a new Object
+     * @return a new CleanableCase preset with the object, cleanup, and semaphore
+     *
+    static CleanableCase setupSoftSubclass(Cleaner cleaner, Object obj) {
+        if (obj == null) {
+            obj = new Object();
+        }
+        Semaphore s1 = new Semaphore(0);
+
+        Cleaner.Cleanable c1 = new SoftCleanable<Object>(obj, cleaner) {
+            protected void performCleanup() {
+                s1.release();
+            }
+        };
+
+        return new CleanableCase(new SoftReference<>(obj, null), c1, s1);
+    }
+    */
+    // END Android-removed: WeakCleanable and SoftCleanable. b/198792576
+
+    /**
+     * Create a CleanableCase for a PhantomReference.
+     * @param cleaner the cleaner to use
+     * @param obj an object or null to create a new Object
+     * @return a new CleanableCase preset with the object, cleanup, and semaphore
+     */
+    static CleanableCase setupPhantomSubclassException(Cleaner cleaner, Object obj) {
+        if (obj == null) {
+            obj = new Object();
+        }
+        Semaphore s1 = new Semaphore(0);
+
+        Cleaner.Cleanable c1 = new PhantomCleanable<Object>(obj, cleaner) {
+            protected void performCleanup() {
+                s1.release();
+                throw new RuntimeException("Exception thrown to cleaner thread");
+            }
+        };
+
+        return new CleanableCase(new PhantomReference<>(obj, null), c1, s1, true);
+    }
+
+    // BEGIN Android-removed: WeakCleanable and SoftCleanable. b/198792576
+    /**
+     * Create a CleanableCase for a WeakReference.
+     * @param cleaner the cleaner to use
+     * @param obj an object or null to create a new Object
+     * @return a new CleanableCase preset with the object, cleanup, and semaphore
+     *
+    static CleanableCase setupWeakSubclassException(Cleaner cleaner, Object obj) {
+        if (obj == null) {
+            obj = new Object();
+        }
+        Semaphore s1 = new Semaphore(0);
+
+        Cleaner.Cleanable c1 = new WeakCleanable<Object>(obj, cleaner) {
+            protected void performCleanup() {
+                s1.release();
+                throw new RuntimeException("Exception thrown to cleaner thread");
+            }
+        };
+
+        return new CleanableCase(new WeakReference<>(obj, null), c1, s1, true);
+    }
+
+    /**
+     * Create a CleanableCase for a SoftReference.
+     * @param cleaner the cleaner to use
+     * @param obj an object or null to create a new Object
+     * @return a new CleanableCase preset with the object, cleanup, and semaphore
+     *
+    static CleanableCase setupSoftSubclassException(Cleaner cleaner, Object obj) {
+        if (obj == null) {
+            obj = new Object();
+        }
+        Semaphore s1 = new Semaphore(0);
+
+        Cleaner.Cleanable c1 = new SoftCleanable<Object>(obj, cleaner) {
+            protected void performCleanup() {
+                s1.release();
+                throw new RuntimeException("Exception thrown to cleaner thread");
+            }
+        };
+
+        return new CleanableCase(new SoftReference<>(obj, null), c1, s1, true);
+    }
+    */
+    // END Android-removed: WeakCleanable and SoftCleanable. b/198792576
+
+    /**
+     * CleanableCase encapsulates the objects used for a test.
+     * The reference to the object is not held directly,
+     * but in a Reference object that can be cleared.
+     * The semaphore is used to count whether the cleanup occurred.
+     * It can be awaited on to determine that the cleanup has occurred.
+     * It can be checked for non-zero to determine if it was
+     * invoked or if it was invoked twice (a bug).
+     */
+    static class CleanableCase {
+
+        private volatile Reference<?> ref;
+        private volatile Cleaner.Cleanable cleanup;
+        private final Semaphore semaphore;
+        private final boolean throwsEx;
+        private final int[] events;   // Sequence of calls to clean, clear, etc.
+        private volatile int eventNdx;
+
+        public static int EV_UNKNOWN = 0;
+        public static int EV_CLEAR = 1;
+        public static int EV_CLEAN = 2;
+        public static int EV_UNREF = 3;
+        public static int EV_CLEAR_CLEANUP = 4;
+
+
+        CleanableCase(Reference<Object> ref, Cleaner.Cleanable cleanup,
+                      Semaphore semaphore) {
+            this.ref = ref;
+            this.cleanup = cleanup;
+            this.semaphore = semaphore;
+            this.throwsEx = false;
+            this.events = new int[4];
+            this.eventNdx = 0;
+        }
+        CleanableCase(Reference<Object> ref, Cleaner.Cleanable cleanup,
+                      Semaphore semaphore,
+                      boolean throwsEx) {
+            this.ref = ref;
+            this.cleanup = cleanup;
+            this.semaphore = semaphore;
+            this.throwsEx = throwsEx;
+            this.events = new int[4];
+            this.eventNdx = 0;
+        }
+
+        public Reference<?> getRef() {
+            return ref;
+        }
+
+        public void clearRef() {
+            addEvent(EV_UNREF);
+            ref.clear();
+        }
+
+        public Cleaner.Cleanable getCleanable() {
+            return cleanup;
+        }
+
+        public void doClean() {
+            try {
+                addEvent(EV_CLEAN);
+                cleanup.clean();
+            } catch (RuntimeException ex) {
+                if (!throwsEx) {
+                    // unless it is known this case throws an exception, rethrow
+                    throw ex;
+                }
+            }
+        }
+
+        public void doClear() {
+            addEvent(EV_CLEAR);
+            ((Reference)cleanup).clear();
+        }
+
+        public void clearCleanable() {
+            addEvent(EV_CLEAR_CLEANUP);
+            cleanup = null;
+        }
+
+        public Semaphore getSemaphore() {
+            return semaphore;
+        }
+
+        public boolean isCleaned() {
+            return semaphore.availablePermits() != 0;
+        }
+
+        private synchronized void addEvent(int e) {
+            events[eventNdx++] = e;
+        }
+
+        /**
+         * Computed the expected result from the sequence of events.
+         * If EV_CLEAR appears before anything else, it is cleared.
+         * If EV_CLEAN appears before EV_UNREF, then it is cleaned.
+         * Anything else is Unknown.
+         * @return EV_CLEAR if the cleanup should occur;
+         *         EV_CLEAN if the cleanup should occur;
+         *         EV_UNKNOWN if it is unknown.
+         */
+        public synchronized int expectedResult() {
+            // Test if EV_CLEAR appears before anything else
+            int clearNdx = indexOfEvent(EV_CLEAR);
+            int cleanNdx = indexOfEvent(EV_CLEAN);
+            int unrefNdx = indexOfEvent(EV_UNREF);
+            if (clearNdx < cleanNdx) {
+                return EV_CLEAR;
+            }
+            if (cleanNdx < clearNdx || cleanNdx < unrefNdx) {
+                return EV_CLEAN;
+            }
+            if (unrefNdx < eventNdx) {
+                return EV_CLEAN;
+            }
+
+            return EV_UNKNOWN;
+        }
+
+        private synchronized  int indexOfEvent(int e) {
+            for (int i = 0; i < eventNdx; i++) {
+                if (events[i] == e) {
+                    return i;
+                }
+            }
+            return eventNdx;
+        }
+
+        private static final String[] names =
+                {"UNKNOWN", "EV_CLEAR", "EV_CLEAN", "EV_UNREF", "EV_CLEAR_CLEANUP"};
+
+        public String eventName(int event) {
+            return names[event];
+        }
+
+        public synchronized String eventsString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append('[');
+            for (int i = 0; i < eventNdx; i++) {
+                if (i > 0) {
+                    sb.append(", ");
+                }
+                sb.append(eventName(events[i]));
+            }
+            sb.append(']');
+            sb.append(", throwEx: ");
+            sb.append(throwsEx);
+            return sb.toString();
+        }
+
+        public String toString() {
+            return String.format("Case: %s, expect: %s, events: %s",
+                    getRef().getClass().getName(),
+                    eventName(expectedResult()), eventsString());
+        }
+    }
+
+    // BEGIN Android-removed: WeakCleanable and SoftCleanable. b/198792576
+    /**
+     * Example using a Cleaner to remove WeakKey references from a Map.
+     *
+    @Test
+    public void testWeakKey() {
+        ConcurrentHashMap<WeakKey<String>, String> map = new ConcurrentHashMap<>();
+        Cleaner cleaner = Cleaner.create();
+        String key = new String("foo");  //  ensure it is not interned
+        String data = "bar";
+
+        map.put(new WeakKey<>(key, cleaner, map), data);
+
+        WeakKey<String> k2 = new WeakKey<>(key, cleaner, map);
+
+        Assert.assertEquals(map.get(k2), data, "value should be found in the map");
+        key = null;
+        System.gc();
+        Assert.assertNotEquals(map.get(k2), data, "value should not be found in the map");
+
+        // Android-changed: inline Utils.adjustTimeout call
+        // It is "Math.round(arg * Utils.TIMEOUT_FACTOR), where TIMEOUT_FACTOR defaults to 1.0"
+        // final long CYCLE_MAX = Utils.adjustTimeout(30L);
+        final long CYCLE_MAX = 30L;
+        for (int i = 1; map.size() > 0 && i < CYCLE_MAX; i++) {
+            map.forEach( (k, v) -> System.out.printf("    k: %s, v: %s%n", k, v));
+            try {
+                Thread.sleep(10L);
+            } catch (InterruptedException ie) {}
+        }
+        Assert.assertEquals(map.size(), 0, "Expected map to be empty;");
+        cleaner = null;
+    }
+
+    /**
+     * Test sample class for WeakKeys in Map.
+     * @param <K> A WeakKey of type K
+     *
+    class WeakKey<K> extends WeakReference<K> {
+        private final int hash;
+        private final ConcurrentHashMap<WeakKey<K>, ?> map;
+        Cleaner.Cleanable cleanable;
+
+        public WeakKey(K key, Cleaner c, ConcurrentHashMap<WeakKey<K>, ?> map) {
+            super(key);
+            this.hash = key.hashCode();
+            this.map = map;
+            cleanable = new WeakCleanable<Object>(key, c) {
+                protected void performCleanup() {
+                    map.remove(WeakKey.this);
+                }
+            };
+        }
+        public int hashCode() { return hash; }
+
+        public boolean equals(Object obj) {
+            if (obj == this) {
+                return true;
+            }
+            if (!(obj instanceof WeakKey)) return false;
+            K key = get();
+            if (key == null) return obj == this;
+            return key == ((WeakKey<?>)obj).get();
+        }
+
+        public String toString() {
+            return "WeakKey:" + Objects.toString(get() + ", cleanableRef: " +
+                    ((Reference)cleanable).get());
+        }
+    }
+    */
+    // END Android-removed: WeakCleanable and SoftCleanable. b/198792576
+
+    /**
+     * Verify that casting a Cleanup to a Reference is not allowed to
+     * get the referent or clear the reference.
+     */
+    @Test
+    @SuppressWarnings("rawtypes")
+    public void testReferentNotAvailable() {
+        Cleaner cleaner = Cleaner.create();
+        Semaphore s1 = new Semaphore(0);
+
+        Object obj = new String("a new string");
+        Cleaner.Cleanable c = cleaner.register(obj, () -> s1.release());
+        Reference r = (Reference) c;
+        try {
+            Object o = r.get();
+            System.out.printf("r: %s%n", Objects.toString(o));
+            Assert.fail("should not be able to get the referent from Cleanable");
+        } catch (UnsupportedOperationException uoe) {
+            // expected
+        }
+
+        try {
+            r.clear();
+            Assert.fail("should not be able to clear the referent from Cleanable");
+        } catch (UnsupportedOperationException uoe) {
+            // expected
+        }
+
+        obj = null;
+        checkCleaned(s1, true, "reference was cleaned:");
+        cleaner = null;
+    }
+
+    /**
+     * Test the Cleaner from the CleanerFactory.
+     */
+    @Test
+    public void testCleanerFactory() {
+        Cleaner cleaner = CleanerFactory.cleaner();
+
+        Object obj = new Object();
+        CleanableCase s = setupPhantom(cleaner, obj);
+        obj = null;
+        checkCleaned(s.getSemaphore(), true,
+                "Object was cleaned using CleanerFactor.cleaner():");
+    }
+}
diff --git a/ojluni/src/test/java/lang/ref/EnqueueNullRefTest.java b/ojluni/src/test/java/lang/ref/EnqueueNullRefTest.java
new file mode 100644
index 0000000..ec0a551
--- /dev/null
+++ b/ojluni/src/test/java/lang/ref/EnqueueNullRefTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 4247236
+ * @summary Ensure that reference objects with null referents can be enqueued
+ */
+package test.java.lang.ref;
+
+import java.lang.ref.*;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class EnqueueNullRefTest {
+
+    static void test(ReferenceQueue q, Reference r) {
+        if (!r.enqueue())
+            throw new RuntimeException("Enqueue operation failed");
+    }
+
+    @Test
+    public void test() {
+        ReferenceQueue q = new ReferenceQueue();
+        test(q, new WeakReference(null, q));
+        test(q, new SoftReference(null, q));
+        test(q, new PhantomReference(null, q));
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/ref/EnqueuePollRaceTest.java b/ojluni/src/test/java/lang/ref/EnqueuePollRaceTest.java
new file mode 100644
index 0000000..a873a68
--- /dev/null
+++ b/ojluni/src/test/java/lang/ref/EnqueuePollRaceTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8014890
+ * @summary Verify that a race between ReferenceQueue.enqueue() and poll() does not occur.
+ * @author thomas.schatzl@oracle.com
+ * @run main/othervm -Xmx10M EnqueuePollRace
+ */
+package test.java.lang.ref;
+
+import java.lang.ref.*;
+
+import org.testng.annotations.Test;
+
+public class EnqueuePollRaceTest {
+
+    @Test
+    public void test() throws Exception {
+        new WeakRef().run();
+        // System.out.println("Test passed.");
+    }
+
+    static class WeakRef {
+        ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
+        final int numReferences = 100;
+        final Reference refs[] = new Reference[numReferences];
+        final int iterations = 1000;
+
+        void run() throws InterruptedException {
+            for (int i = 0; i < iterations; i++) {
+                queue = new ReferenceQueue<Object>();
+
+                for (int j = 0; j < refs.length; j++) {
+                    refs[j] = new WeakReference(new Object(), queue);
+                }
+
+                System.gc(); // enqueues references into the list of discovered references
+
+                // now manually enqueue all of them
+                for (int j = 0; j < refs.length; j++) {
+                    refs[j].enqueue();
+                }
+                // and get them back. There should be exactly numReferences
+                // entries in the queue now.
+                int foundReferences = 0;
+                while (queue.poll() != null) {
+                    foundReferences++;
+                }
+
+                if (foundReferences != refs.length) {
+                    throw new RuntimeException("Got " + foundReferences + " references in the queue, but expected " + refs.length);
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/lang/ref/ReferenceCloneTest.java b/ojluni/src/test/java/lang/ref/ReferenceCloneTest.java
new file mode 100644
index 0000000..a527940
--- /dev/null
+++ b/ojluni/src/test/java/lang/ref/ReferenceCloneTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8201793
+ * @summary Test Reference::clone to throw CloneNotSupportedException
+ */
+package test.java.lang.ref;
+
+import java.lang.ref.*;
+
+import org.testng.annotations.Test;
+
+public class ReferenceCloneTest {
+    private static final ReferenceQueue<Object> QUEUE = new ReferenceQueue<>();
+
+    @Test
+    public void testReferenceClone(String... args) {
+        ReferenceCloneTest refClone = new ReferenceCloneTest();
+        refClone.test();
+    }
+
+    public void test() {
+        // test Reference::clone that throws CNSE
+        Object o = new Object();
+        assertCloneNotSupported(new SoftRef(o));
+        assertCloneNotSupported(new WeakRef(o));
+        assertCloneNotSupported(new PhantomRef(o));
+
+        // Reference subclass may override the clone method
+        CloneableReference ref = new CloneableReference(o);
+        try {
+            ref.clone();
+        } catch (CloneNotSupportedException e) {}
+    }
+
+    private void assertCloneNotSupported(CloneableRef ref) {
+        try {
+            ref.clone();
+            throw new RuntimeException("Reference::clone should throw CloneNotSupportedException");
+        } catch (CloneNotSupportedException e) {}
+    }
+
+    // override clone to be public that throws CNSE
+    interface CloneableRef extends Cloneable {
+        public Object clone() throws CloneNotSupportedException;
+    }
+
+    class SoftRef extends SoftReference<Object> implements CloneableRef {
+        public SoftRef(Object referent) {
+            super(referent, QUEUE);
+        }
+        public Object clone() throws CloneNotSupportedException {
+            return super.clone();
+        }
+    }
+
+    class WeakRef extends WeakReference<Object> implements CloneableRef {
+        public WeakRef(Object referent) {
+            super(referent, QUEUE);
+        }
+        public Object clone() throws CloneNotSupportedException {
+            return super.clone();
+        }
+    }
+
+    class PhantomRef extends PhantomReference<Object> implements CloneableRef {
+        public PhantomRef(Object referent) {
+            super(referent, QUEUE);
+        }
+
+        public Object clone() throws CloneNotSupportedException {
+            return super.clone();
+        }
+    }
+
+    // override clone to return a new instance
+    class CloneableReference extends WeakReference<Object> implements Cloneable {
+        public CloneableReference(Object referent) {
+            super(referent, QUEUE);
+        }
+
+        public Object clone() throws CloneNotSupportedException {
+            return new CloneableReference(this.get());
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/lang/ref/ReferenceEnqueuePendingTest.java b/ojluni/src/test/java/lang/ref/ReferenceEnqueuePendingTest.java
new file mode 100644
index 0000000..b77dbf0
--- /dev/null
+++ b/ojluni/src/test/java/lang/ref/ReferenceEnqueuePendingTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 4243978
+ * @summary Test if Reference.enqueue() works properly with pending references
+ */
+package test.java.lang.ref;
+
+import java.lang.ref.*;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ReferenceEnqueuePendingTest {
+    static class NumberedWeakReference extends WeakReference<Integer> {
+        //  Add an integer to identify the weak reference object.
+        int number;
+
+        NumberedWeakReference(Integer referent, ReferenceQueue<Integer> q, int i) {
+            super(referent, q);
+            number = i;
+        }
+    }
+
+    static final boolean debug = System.getProperty("test.debug") != null;
+    static final int iterations = 1000;
+    static final int gc_trigger = 99;
+    static int[] a = new int[2 * iterations];
+    // Keep all weak references alive with the following array.
+    static NumberedWeakReference[] b = new NumberedWeakReference[iterations];
+
+    @Test
+    public void testReferenceEnqueuePending() throws Exception {
+        if (debug) {
+            System.out.println("Starting the test.");
+        }
+        // Raise thread priority to match the referenceHandler
+        // priority, so that they can race also on a uniprocessor.
+        raisePriority();
+
+        ReferenceQueue<Integer> refQueue = new ReferenceQueue<>();
+
+        // Our objective is to let the mutator enqueue
+        // a Reference object that may already be in the
+        // pending state because of having been identified
+        // as weakly reachable at a previous garbage collection.
+        // To this end, we create many Reference objects, each with a
+        // a unique integer object as its referant.
+        // We let the referents become eligible for collection,
+        // while racing with the garbage collector which may
+        // have pended some of these Reference objects.
+        // Finally we check that all of the Reference objects
+        // end up on the their queue. The test was originally
+        // submitted to show that such races could break the
+        // pending list and/or the reference queue, because of sharing
+        // the same link ("next") for maintaining both lists, thus
+        // losing some of the Reference objects on either queue.
+
+        Integer obj = new Integer(0);
+        NumberedWeakReference weaky = new NumberedWeakReference(obj, refQueue, 0);
+        for (int i = 1; i < iterations; i++) {
+            // Create a new object, dropping the onlY strong reference to
+            // the previous Integer object.
+            obj = new Integer(i);
+            // Trigger gc each gc_trigger iterations.
+            if ((i % gc_trigger) == 0) {
+                forceGc(0);
+            }
+            // Enqueue every other weaky.
+            if ((i % 2) == 0) {
+                weaky.enqueue();
+            }
+            // Remember the Reference objects, for testing later.
+            b[i - 1] = weaky;
+            // Get a new weaky for the Integer object just
+            // created, which may be explicitly enqueued in
+            // our next trip around the loop.
+            weaky = new NumberedWeakReference(obj, refQueue, i);
+        }
+
+        // Do a final collection to discover and process all
+        // Reference objects created above, allowing some time
+        // for the ReferenceHandler thread to queue the References.
+        forceGc(100);
+        forceGc(100);
+
+        // Verify that all WeakReference objects ended up queued.
+        checkResult(refQueue, iterations-1);
+
+        // Ensure the final weaky is live but won't be enqueued during
+        // result checking, by ensuring its referent remains live.
+        // This eliminates behavior changes resulting from different
+        // compiler optimizations.
+        Reference.reachabilityFence(weaky);
+        Reference.reachabilityFence(obj);
+
+        System.out.println("Test passed.");
+    }
+
+    private static NumberedWeakReference waitForReference(ReferenceQueue<Integer> queue) {
+        try {
+            return (NumberedWeakReference) queue.remove(30000); // 30sec
+        } catch (InterruptedException ie) {
+            return null;
+        }
+    }
+
+    private static void checkResult(ReferenceQueue<Integer> queue,
+                                    int expected) {
+        if (debug) {
+            System.out.println("Reading the queue");
+        }
+
+        // Empty the queue and record numbers into a[];
+        NumberedWeakReference weakRead = waitForReference(queue);
+        int length = 0;
+        while (weakRead != null) {
+            a[length++] = weakRead.number;
+            if (length < expected) {
+                weakRead = waitForReference(queue);
+            } else {            // Check for unexpected extra entries.
+                weakRead = (NumberedWeakReference) queue.poll();
+            }
+        }
+        if (debug) {
+            System.out.println("Reference Queue had " + length + " elements");
+        }
+
+
+        // verify the queued references: all but the last Reference object
+        // should have been in the queue.
+        if (debug) {
+            System.out.println("Start of final check");
+        }
+
+        // Sort the first "length" elements in array "a[]".
+        sort(length);
+
+        boolean fail = (length != expected);
+        for (int i = 0; i < length; i++) {
+            if (a[i] != i) {
+                if (debug) {
+                    System.out.println("a[" + i + "] is not " + i + " but " + a[i]);
+                }
+                fail = true;
+            }
+        }
+        if (fail) {
+             printMissingElements(length, expected);
+             throw new RuntimeException("TEST FAILED: only " + length
+                    + " reference objects have been queued out of "
+                    + expected);
+        }
+    }
+
+    private static void printMissingElements(int length, int expected) {
+        System.out.println("The following numbers were not found in the reference queue: ");
+        int missing = 0;
+        int element = 0;
+        for (int i = 0; i < length; i++) {
+            while ((a[i] != element) & (element < expected)) {
+                System.out.print(element + " ");
+                if (missing % 20 == 19) {
+                    System.out.println(" ");
+                }
+                missing++;
+                element++;
+            }
+            element++;
+        }
+        System.out.print("\n");
+    }
+
+    private static void forceGc(long millis) throws InterruptedException {
+        Runtime.getRuntime().gc();
+        Thread.sleep(millis);
+    }
+
+    // Bubble sort the first "length" elements in array "a".
+    private static void sort(int length) {
+        int hold;
+        if (debug) {
+            System.out.println("Sorting. Length=" + length);
+        }
+        for (int pass = 1; pass < length; pass++) {    // passes over the array
+            for (int i = 0; i < length - pass; i++) {  //  a single pass
+                if (a[i] > a[i + 1]) {  // then swap
+                    hold = a[i];
+                    a[i] = a[i + 1];
+                    a[i + 1] = hold;
+                }
+            }  // End of i loop
+        } // End of pass loop
+    }
+
+    // Raise thread priority so as to increase the
+    // probability of the mutator succeeding in enqueueing
+    // an object that is still in the pending state.
+    // This is (probably) only required for a uniprocessor.
+    static void raisePriority() {
+        Thread tr = Thread.currentThread();
+        tr.setPriority(Thread.MAX_PRIORITY);
+    }
+}   // End of class ReferenceEnqueuePending
diff --git a/ojluni/src/test/java/lang/ref/SoftReference/BashTest.java b/ojluni/src/test/java/lang/ref/SoftReference/BashTest.java
new file mode 100644
index 0000000..23e7fa0
--- /dev/null
+++ b/ojluni/src/test/java/lang/ref/SoftReference/BashTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 4076283
+ * @summary java.lang.ref.SoftReference should reliably prevent
+ *          OutOfMemoryErrors
+ * @author Peter Jones
+ * @author Mark Reinhold
+ */
+package test.java.lang.ref.SoftReference;
+
+/* If this test fails, an OutOfMemoryError will be thrown */
+
+import java.lang.ref.SoftReference;
+
+import org.testng.annotations.Test;
+
+
+public class BashTest {
+
+    static class TestReference extends SoftReference {
+
+        public static TestReference head;
+        public TestReference next;
+
+        public TestReference(Object referent) {
+            super(referent);
+            next = head;
+            head = this;
+        }
+    }
+
+
+    static final int NUM_BLOCKS = 2048;
+    static final int BLOCK_SIZE = 32768;
+
+    @Test
+    public void test() throws Exception {
+
+        for (int i = 0; i < NUM_BLOCKS; ++ i) {
+            TestReference ref = new TestReference(new byte[BLOCK_SIZE]);
+        }
+
+        int emptyCount = 0;
+        int fullCount = 0;
+        for (TestReference r = TestReference.head; r != null; r = r.next) {
+            if (r.get() == null) emptyCount++;
+            else fullCount++;
+        }
+
+        System.err.println(fullCount + " full, " + emptyCount + " empty ");
+
+    }
+
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/AddTests.java b/ojluni/src/test/java/math/BigDecimal/AddTests.java
new file mode 100644
index 0000000..30d3045
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/AddTests.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6362557 8200698
+ * @summary Some tests of add(BigDecimal, mc)
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+import static java.math.BigDecimal.*;
+import java.util.Set;
+import java.util.EnumSet;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class AddTests {
+
+    private static Set<RoundingMode> nonExactRoundingModes =
+        EnumSet.complementOf(EnumSet.of(RoundingMode.UNNECESSARY));
+
+    /**
+     * Test for some simple additions, particularly, it will test
+     * the overflow case.
+     */
+    private static int simpleTests() {
+        int failures = 0;
+
+        BigDecimal[] bd1 = {
+            new BigDecimal(new BigInteger("7812404666936930160"), 11),
+            new BigDecimal(new BigInteger("7812404666936930160"), 12),
+            new BigDecimal(new BigInteger("7812404666936930160"), 13),
+        };
+        BigDecimal bd2 = new BigDecimal(new BigInteger("2790000"), 1);
+        BigDecimal[] expectedResult = {
+            new BigDecimal("78403046.66936930160"),
+            new BigDecimal("8091404.666936930160"),
+            new BigDecimal("1060240.4666936930160"),
+        };
+        for (int i = 0; i < bd1.length; i++) {
+            if (!bd1[i].add(bd2).equals(expectedResult[i]))
+                failures++;
+        }
+        return failures;
+    }
+
+    /**
+     * Test for extreme value of scale and rounding precision that
+     * could cause integer overflow in right-shift-into-sticky-bit
+     * computations.
+     */
+    @Test
+    public void extremaTests() {
+        addWithoutException(valueOf(1, -Integer.MAX_VALUE),
+                                        valueOf(2, Integer.MAX_VALUE), null);
+        addWithoutException(valueOf(1, -Integer.MAX_VALUE),
+                                        valueOf(-2, Integer.MAX_VALUE), null);
+    }
+
+    /**
+     * Print sum of b1 and b2; correct result will not throw an
+     * exception.
+     */
+    private static void addWithoutException(BigDecimal b1, BigDecimal b2, MathContext mc) {
+        if (mc == null)
+            mc = new MathContext(2, RoundingMode.DOWN);
+
+        try {
+            BigDecimal sum = b1.add(b2, mc);
+        } catch(ArithmeticException ae) {
+            Assert.fail("Unexpected ArithmeticException: " + ae.getMessage());
+        }
+    }
+
+    /**
+     * Test combinations of operands that may meet the condensation
+     * criteria when rounded to different precisions.
+     */
+    @Test
+    public void roundingGradationTests() {
+        roundAway(new BigDecimal("1234e100"),
+                              new BigDecimal(   "1234e97"));
+
+        roundAway(new BigDecimal("1234e100"),
+                              new BigDecimal(    "1234e96"));
+
+        roundAway(new BigDecimal("1234e100"),
+                              new BigDecimal(     "1234e95"));
+
+        roundAway(new BigDecimal("1234e100"),
+                              new BigDecimal(      "1234e94"));
+
+        roundAway(new BigDecimal("1234e100"),
+                              new BigDecimal(       "1234e93"));
+
+        roundAway(new BigDecimal("1234e100"),
+                              new BigDecimal(        "1234e92"));
+
+        roundAway(new BigDecimal("1234e100"),
+                              new BigDecimal("1234e50"));
+
+
+        roundAway(new BigDecimal("1000e100"),
+                              new BigDecimal(   "1234e97"));
+
+        roundAway(new BigDecimal("1000e100"),
+                              new BigDecimal(    "1234e96"));
+
+        roundAway(new BigDecimal("1000e100"),
+                              new BigDecimal(     "1234e95"));
+
+        roundAway(new BigDecimal("1000e100"),
+                              new BigDecimal(      "1234e94"));
+
+        roundAway(new BigDecimal("1000e100"),
+                              new BigDecimal(       "1234e93"));
+
+        roundAway(new BigDecimal("1000e100"),
+                              new BigDecimal(        "1234e92"));
+
+        roundAway(new BigDecimal("1000e100"),
+                              new BigDecimal("1234e50"));
+
+
+
+        roundAway(new BigDecimal("1999e100"),
+                              new BigDecimal(   "1234e97"));
+
+        roundAway(new BigDecimal("1999e100"),
+                              new BigDecimal(    "1234e96"));
+
+        roundAway(new BigDecimal("1999e100"),
+                              new BigDecimal(     "1234e95"));
+
+        roundAway(new BigDecimal("1999e100"),
+                              new BigDecimal(      "1234e94"));
+
+        roundAway(new BigDecimal("1999e100"),
+                              new BigDecimal(       "1234e93"));
+
+        roundAway(new BigDecimal("1999e100"),
+                              new BigDecimal(        "1234e92"));
+
+        roundAway(new BigDecimal("1999e100"),
+                              new BigDecimal("1234e50"));
+
+
+
+        roundAway(new BigDecimal("9999e100"),
+                              new BigDecimal(   "1234e97"));
+
+        roundAway(new BigDecimal("9999e100"),
+                              new BigDecimal(    "1234e96"));
+
+        roundAway(new BigDecimal("9999e100"),
+                              new BigDecimal(     "1234e95"));
+
+        roundAway(new BigDecimal("9999e100"),
+                              new BigDecimal(      "1234e94"));
+
+        roundAway(new BigDecimal("9999e100"),
+                              new BigDecimal(       "1234e93"));
+
+        roundAway(new BigDecimal("9999e100"),
+                              new BigDecimal(        "1234e92"));
+
+        roundAway(new BigDecimal("9999e100"),
+                              new BigDecimal("1234e50"));
+    }
+
+    private static void roundAway(BigDecimal b1, BigDecimal b2) {
+        b1.precision();
+        b2.precision();
+
+        BigDecimal b1_negate = b1.negate();
+        BigDecimal b2_negate = b2.negate();
+
+        b1_negate.precision();
+        b2_negate.precision();
+
+        roundAway1(b1,        b2);
+        roundAway1(b1,        b2_negate);
+        roundAway1(b1_negate, b2);
+        roundAway1(b1_negate, b2_negate);
+    }
+
+    private static void roundAway1(BigDecimal b1, BigDecimal b2) {
+        roundAway0(b1, b2);
+        roundAway0(b2, b1);
+    }
+
+    /**
+     * Compare b1.add(b2, mc) with b1.add(b2).round(mc) for a variety
+     * of MathContexts.
+     */
+    private static void roundAway0(BigDecimal b1, BigDecimal b2) {
+        BigDecimal exactSum = b1.add(b2);
+
+        for(int precision = 1 ; precision < exactSum.precision()+2; precision++) {
+            for(RoundingMode rm : nonExactRoundingModes) {
+                MathContext mc = new MathContext(precision, rm);
+                BigDecimal roundedExactSum = exactSum.round(mc);
+
+                try {
+                    BigDecimal sum = b1.add(b2, mc);
+
+                    Assert.assertEquals(sum, roundedExactSum, "Exact sum " + exactSum +
+                                           "\trounded by " + mc +
+                                           "\texpected: " + roundedExactSum + " got: ");
+                } catch (ArithmeticException ae) {
+                    Assert.fail("Unexpected ArithmeticException: " + ae.getMessage());
+                }
+            }
+        }
+    }
+
+    /**
+     * Verify calling the precision method should not change the
+     * computed result.
+     */
+    @Test
+    public void precisionConsistencyTest() {
+        MathContext mc = new MathContext(1,RoundingMode.DOWN);
+        BigDecimal a = BigDecimal.valueOf(1999, -1); //value is equivalent to 19990
+
+        BigDecimal sum1 = a.add(BigDecimal.ONE, mc);
+        a.precision();
+        BigDecimal sum2 = a.add(BigDecimal.ONE, mc);
+
+        Assert.assertEquals(sum2, sum1, "Unequal sums after calling precision!" +
+            "Before:\t" + sum1.toString() +
+            "After:\t" + sum2.toString());
+    }
+
+    @Test
+    public static void arithmeticExceptionTest() {
+        int failures = 0;
+        BigDecimal x;
+        try {
+            //
+            // The string representation "1e2147483647", which is equivalent
+            // to 10^Integer.MAX_VALUE, is used to create an augend with an
+            // unscaled value of 1 and a scale of -Integer.MAX_VALUE. The
+            // addend "1" has an unscaled value of 1 with a scale of 0. The
+            // addition is performed exactly and is specified to have a
+            // preferred scale of max(-Integer.MAX_VALUE, 0). As the scale
+            // of the result is 0, a value with Integer.MAX_VALUE + 1 digits
+            // would need to be created. Therefore the next statement is
+            // expected to overflow with an ArithmeticException.
+            //
+            x = new BigDecimal("1e2147483647").add(new BigDecimal(1));
+            failures++;
+            // Android-added: Add assert statement.
+            Assert.fail("ArithmeticException is expected.");
+        } catch (ArithmeticException ae) {
+        }
+        // Android-removed: Remove return the statement.
+        // return failures;
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/CompareToTests.java b/ojluni/src/test/java/math/BigDecimal/CompareToTests.java
new file mode 100644
index 0000000..4885944
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/CompareToTests.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6473768
+ * @summary Tests of BigDecimal.compareTo
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+import static java.math.BigDecimal.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class CompareToTests {
+
+    @Test
+    public void compareToTests() {
+        final BigDecimal MINUS_ONE = BigDecimal.ONE.negate();
+
+        // First operand, second operand, expected compareTo result
+        BigDecimal [][] testCases = {
+            // Basics
+            {valueOf(0),        valueOf(0),     ZERO},
+            {valueOf(0),        valueOf(1),     MINUS_ONE},
+            {valueOf(1),        valueOf(2),     MINUS_ONE},
+            {valueOf(2),        valueOf(1),     ONE},
+            {valueOf(10),       valueOf(10),    ZERO},
+
+            // Significands would compare differently than scaled value
+            {valueOf(2,1),      valueOf(2),     MINUS_ONE},
+            {valueOf(2,-1),     valueOf(2),     ONE},
+            {valueOf(1,1),      valueOf(2),     MINUS_ONE},
+            {valueOf(1,-1),     valueOf(2),     ONE},
+            {valueOf(5,-1),     valueOf(2),     ONE},
+
+            // Boundary and near boundary values
+            {valueOf(Long.MAX_VALUE),            valueOf(Long.MAX_VALUE), ZERO},
+            {valueOf(Long.MAX_VALUE).negate(),   valueOf(Long.MAX_VALUE), MINUS_ONE},
+
+            {valueOf(Long.MAX_VALUE-1),          valueOf(Long.MAX_VALUE), MINUS_ONE},
+            {valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MAX_VALUE), MINUS_ONE},
+
+            {valueOf(Long.MIN_VALUE),            valueOf(Long.MAX_VALUE), MINUS_ONE},
+            {valueOf(Long.MIN_VALUE).negate(),   valueOf(Long.MAX_VALUE), ONE},
+
+            {valueOf(Long.MIN_VALUE+1),          valueOf(Long.MAX_VALUE), MINUS_ONE},
+            {valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MAX_VALUE), ZERO},
+
+            {valueOf(Long.MAX_VALUE),            valueOf(Long.MIN_VALUE), ONE},
+            {valueOf(Long.MAX_VALUE).negate(),   valueOf(Long.MIN_VALUE), ONE},
+
+            {valueOf(Long.MAX_VALUE-1),          valueOf(Long.MIN_VALUE), ONE},
+            {valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MIN_VALUE), ONE},
+
+            {valueOf(Long.MIN_VALUE),            valueOf(Long.MIN_VALUE), ZERO},
+            {valueOf(Long.MIN_VALUE).negate(),   valueOf(Long.MIN_VALUE), ONE},
+
+            {valueOf(Long.MIN_VALUE+1),          valueOf(Long.MIN_VALUE), ONE},
+            {valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MIN_VALUE), ONE},
+        };
+
+        for (BigDecimal[] testCase : testCases) {
+            BigDecimal a = testCase[0];
+            BigDecimal a_negate = a.negate();
+            BigDecimal b = testCase[1];
+            BigDecimal b_negate = b.negate();
+            int expected = testCase[2].intValue();
+
+            compareToTest(a,        b,         expected);
+            compareToTest(a_negate, b_negate, -expected);
+        }
+    }
+
+    private static void compareToTest(BigDecimal a, BigDecimal b, int expected) {
+        int result = a.compareTo(b);
+        Assert.assertEquals(result, expected, "(" + a + ").compareTo(" + b + ") => " + result +
+                               "\n\tExpected " + expected);
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/Constructor.java b/ojluni/src/test/java/math/BigDecimal/Constructor.java
new file mode 100644
index 0000000..d072496
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/Constructor.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4259453 8200698
+ * @summary Test constructors of BigDecimal
+ * @library ..
+ * @run testng Constructor
+ */
+
+import java.math.BigDecimal;
+import org.testng.annotations.Test;
+
+public class Constructor {
+    @Test(expectedExceptions=NumberFormatException.class)
+    public void stringConstructor() {
+        BigDecimal bd = new BigDecimal("1.2e");
+    }
+
+    @Test(expectedExceptions=NumberFormatException.class)
+    public void charArrayConstructorNegativeOffset() {
+        BigDecimal bd = new BigDecimal(new char[5], -1, 4, null);
+    }
+
+    @Test(expectedExceptions=NumberFormatException.class)
+    public void charArrayConstructorNegativeLength() {
+        BigDecimal bd = new BigDecimal(new char[5], 0, -1, null);
+    }
+
+    @Test(expectedExceptions=NumberFormatException.class)
+    public void charArrayConstructorIntegerOverflow() {
+        try {
+            BigDecimal bd = new BigDecimal(new char[5], Integer.MAX_VALUE - 5,
+                6, null);
+        } catch (NumberFormatException nfe) {
+            if (nfe.getCause() instanceof IndexOutOfBoundsException) {
+                throw new RuntimeException
+                    ("NumberFormatException should not have a cause");
+            } else {
+                throw nfe;
+            }
+        }
+    }
+
+    @Test(expectedExceptions=NumberFormatException.class)
+    public void charArrayConstructorIndexOutOfBounds() {
+        BigDecimal bd = new BigDecimal(new char[5], 1, 5, null);
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/DivideMcTests.java b/ojluni/src/test/java/math/BigDecimal/DivideMcTests.java
new file mode 100644
index 0000000..acf717f
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/DivideMcTests.java
@@ -0,0 +1,5783 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 7036582
+ * @summary Some tests for the divide(..,MathContext) method.
+ * @run main DivideMcTests
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 DivideMcTests
+ * @author Sergey V. Kuksenko
+ */
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class DivideMcTests {
+
+    static String[] value = new String[75];
+    static String[][] results = new String[75][75];
+    static {
+        value[0]="11061";
+        value[1]="5030285645";
+        value[2]="224198292018431";
+        value[3]="19226185404220649458";
+        value[4]="2754593222460641763294400";
+        value[5]="88290e4";
+        value[6]="14207e-4";
+        value[7]="9206524943e4";
+        value[8]="9637167289e-4";
+        value[9]="987673128759528e4";
+        value[10]="270627774630281e-4";
+        value[11]="81503625886547904651e4";
+        value[12]="60700032235397315737e-4";
+        value[13]="6477954854329556663533122e4";
+        value[14]="8056417378028557868905113e-4";
+        value[15]="74996e8";
+        value[16]="65282e-8";
+        value[17]="6336626690e8";
+        value[18]="8318166778e-8";
+        value[19]="983114227763768e8";
+        value[20]="245802997834566e-8";
+        value[21]="52727924122290902686e8";
+        value[22]="42785567085625398961e-8";
+        value[23]="4810906998143118279742863e8";
+        value[24]="8077506080975981172874361e-8";
+        value[25]="80689e12";
+        value[26]="30125e-12";
+        value[27]="6921467144e12";
+        value[28]="1953347181e-12";
+        value[29]="405471649883944e12";
+        value[30]="866720590936024e-12";
+        value[31]="33231666378140173438e12";
+        value[32]="42631490906110209257e-12";
+        value[33]="7723154992826793726050991e12";
+        value[34]="1611437259018380210686834e-12";
+        value[35]="65645e16";
+        value[36]="31153e-16";
+        value[37]="7758733150e16";
+        value[38]="6365465077e-16";
+        value[39]="727973863299662e16";
+        value[40]="351084160935215e-16";
+        value[41]="45470432070181568402e16";
+        value[42]="97216256670931719037e-16";
+        value[43]="2520581904836081418366563e16";
+        value[44]="3700768934485477578987416e-16";
+        value[45]="28736e20";
+        value[46]="52779e-20";
+        value[47]="7904805864e20";
+        value[48]="6373815349e-20";
+        value[49]="186651310031326e20";
+        value[50]="189125880591366e-20";
+        value[51]="74987916068454915171e20";
+        value[52]="10554589082317914511e-20";
+        value[53]="3599986721169840668392202e20";
+        value[54]="2588106172836128849130551e-20";
+        value[55]="71080e24";
+        value[56]="61576e-24";
+        value[57]="7086656363e24";
+        value[58]="7703864845e-24";
+        value[59]="361167296280301e24";
+        value[60]="149150690375117e-24";
+        value[61]="78129219923655854302e24";
+        value[62]="20861932490694515212e-24";
+        value[63]="9185868654811652011998047e24";
+        value[64]="1996563690880014012200226e-24";
+        value[65]="84665e28";
+        value[66]="94968e-28";
+        value[67]="2622821029e28";
+        value[68]="4451579486e-28";
+        value[69]="590522407411869e28";
+        value[70]="606293232614518e-28";
+        value[71]="96628087822208148505e28";
+        value[72]="24875240094942654314e-28";
+        value[73]="5099400093819597146233149e28";
+        value[74]="8906650752845770170008864e-28";
+        //--------------------------------------------
+        initResults1();
+        initResults2();
+    }
+
+    private static void initResults1() {
+        results[0][0]="1";
+        results[0][1]="0.000002198881093560642";
+        results[0][2]="4.933579065397471E-11";
+        results[0][3]="5.753091300977375E-16";
+        results[0][4]="4.015474920147867E-21";
+        results[0][5]="0.00001252803261977574";
+        results[0][6]="7785.598648553530";
+        results[0][7]="1.201430514605841E-10";
+        results[0][8]="0.01147743903192921";
+        results[0][9]="1.119904923797219E-15";
+        results[0][10]="4.087163638363069E-7";
+        results[0][11]="1.357117536758031E-20";
+        results[0][12]="1.822239559462666E-12";
+        results[0][13]="1.707483341383177E-25";
+        results[0][14]="1.372942771084022E-17";
+        results[0][15]="1.474878660195210E-9";
+        results[0][16]="16943414.72381361";
+        results[0][17]="1.745565983468090E-14";
+        results[0][18]="132.9740109233477";
+        results[0][19]="1.125098151123273E-19";
+        results[0][20]="0.004499945117611804";
+        results[0][21]="2.097749946374985E-24";
+        results[0][22]="2.585217575324869E-8";
+        results[0][23]="2.299150660004288E-29";
+        results[0][24]="1.369358300583728E-13";
+        results[0][25]="1.370818822887878E-13";
+        results[0][26]="367170124481.3278";
+        results[0][27]="1.598071589430057E-18";
+        results[0][28]="5662587.842852089";
+        results[0][29]="2.727934247231818E-23";
+        results[0][30]="12.76189825841631";
+        results[0][31]="3.328451806821200E-28";
+        results[0][32]="0.0002594560913752765";
+        results[0][33]="1.432186717769276E-33";
+        results[0][34]="6.864058738928437E-9";
+        results[0][35]="1.684972198948892E-17";
+        results[0][36]="3550540878888069";
+        results[0][37]="1.425619335806130E-22";
+        results[0][38]="17376577934.52694";
+        results[0][39]="1.519422682273810E-27";
+        results[0][40]="315052.6634564146";
+        results[0][41]="2.432569803367569E-32";
+        results[0][42]="1.137772670824026";
+        results[0][43]="4.388272398043467E-37";
+        results[0][44]="0.00002988838318687904";
+        results[0][45]="3.849178730512249E-21";
+        results[0][46]="2.095719888592054E+19";
+        results[0][47]="1.399275351008165E-26";
+        results[0][48]="173538130528606.9";
+        results[0][49]="5.926023234524105E-31";
+        results[0][50]="5848485656.967753";
+        results[0][51]="1.475037656720937E-36";
+        results[0][52]="104798.0164242535";
+        results[0][53]="3.072511333154488E-41";
+        results[0][54]="0.4273781391232109";
+        results[0][55]="1.556133933595948E-25";
+        results[0][56]="1.796316746784461E+23";
+        results[0][57]="1.560820707738894E-30";
+        results[0][58]="1.435772852009322E+18";
+        results[0][59]="3.062569649555309E-35";
+        results[0][60]="74159898101586.80";
+        results[0][61]="1.415731529229177E-40";
+        results[0][62]="530200162.6615257";
+        results[0][63]="1.204132174718842E-45";
+        results[0][64]="5540.018608234184";
+        results[0][65]="1.306443040217327E-29";
+        results[0][66]="1.164708112206217E+27";
+        results[0][67]="4.217214929154817E-34";
+        results[0][68]="2.484736043641657E+22";
+        results[0][69]="1.873087263272185E-39";
+        results[0][70]="1.824364747121068E+17";
+        results[0][71]="1.144698218633054E-44";
+        results[0][72]="4446590247082.196";
+        results[0][73]="2.169078675235893E-49";
+        results[0][74]="12418809.61422664";
+        results[1][0]="454776.7511979025";
+        results[1][1]="1";
+        results[1][2]="0.00002243677059139446";
+        results[1][3]="2.616372171203405E-10";
+        results[1][4]="1.826144638701504E-15";
+        results[1][5]="5.697457973722958";
+        results[1][6]="3540709259.519955";
+        results[1][7]="0.00005463826662224685";
+        results[1][8]="5219.672435012765";
+        results[1][9]="5.093067228950338E-10";
+        results[1][10]="0.1858747001068956";
+        results[1][11]="6.171855043605175E-15";
+        results[1][12]="8.287121867567282E-7";
+        results[1][13]="7.765237267187802E-20";
+        results[1][14]="6.243824530142372E-12";
+        results[1][15]="0.0006707405254946931";
+        results[1][16]="7705471102294.660";
+        results[1][17]="7.938428269631898E-9";
+        results[1][18]="60473488.68147447";
+        results[1][19]="5.116684819466090E-14";
+        results[1][20]="2046.470421156359";
+        results[1][21]="9.540079054379898E-19";
+        results[1][22]="0.01175696850045963";
+        results[1][23]="1.045600267671264E-23";
+        results[1][24]="6.227523191653488E-8";
+        results[1][25]="6.234165307538822E-8";
+        results[1][26]="1.669804363485477E+17";
+        results[1][27]="7.267658056226699E-13";
+        results[1][28]="2575213302545.012";
+        results[1][29]="1.240601074437582E-17";
+        results[1][30]="5803814.629080740";
+        results[1][31]="1.513702499224934E-22";
+        results[1][32]="117.9945983141544";
+        results[1][33]="6.513252226158986E-28";
+        results[1][34]="0.003121614333321446";
+        results[1][35]="7.662861824967629E-12";
+        results[1][36]="1.614703445896061E+21";
+        results[1][37]="6.483385299828233E-17";
+        results[1][38]="7902463660001319";
+        results[1][39]="6.909981111408860E-22";
+        results[1][40]="143278626742.9544";
+        results[1][41]="1.106276192237624E-26";
+        results[1][42]="517432.5588391111";
+        results[1][43]="1.995684264553637E-31";
+        results[1][44]="13.59254180428686";
+        results[1][45]="1.750516997842428E-15";
+        results[1][46]="9.530846823547244E+24";
+        results[1][47]="6.363578981627979E-21";
+        results[1][48]="7.892110721075739E+19";
+        results[1][49]="2.695017594120158E-25";
+        results[1][50]="2659755306503325";
+        results[1][51]="6.708128334181145E-31";
+        results[1][52]="47659701441.40646";
+        results[1][53]="1.397306722110734E-35";
+        results[1][54]="194361.6416434591";
+        results[1][55]="7.076935347495779E-20";
+        results[1][56]="8.169230942250227E+28";
+        results[1][57]="7.098249706679054E-25";
+        results[1][58]="6.529561130949462E+23";
+        results[1][59]="1.392785475542062E-29";
+        results[1][60]="3.372619752780715E+19";
+        results[1][61]="6.438417854312836E-35";
+        results[1][62]="241122707459808.1";
+        results[1][63]="5.476113184315002E-40";
+        results[1][64]="2519471664.228668";
+        results[1][65]="5.941399214551468E-24";
+        results[1][66]="5.296821713629854E+32";
+        results[1][67]="1.917891304584321E-28";
+        results[1][68]="1.130000185511682E+28";
+        results[1][69]="8.518365403010947E-34";
+        results[1][70]="8.296786726957023E+22";
+        results[1][71]="5.205821369719668E-39";
+        results[1][72]="2.022205866476320E+18";
+        results[1][73]="9.864465530164297E-44";
+        results[1][74]="5647785890103.269";
+        results[2][0]="20269260647.17756";
+        results[2][1]="44569.69401753148";
+        results[2][2]="1";
+        results[2][3]="0.00001166109071065203";
+        results[2][4]="8.139070777868161E-11";
+        results[2][5]="253933.9585665772";
+        results[2][6]="157808328301844.9";
+        results[2][7]="2.435210825001846";
+        results[2][8]="232639203.3002624";
+        results[2][9]="0.00002269964480050335";
+        results[2][10]="8284.378509364762";
+        results[2][11]="2.750776908140411E-10";
+        results[2][12]="0.03693544859234678";
+        results[2][13]="3.460942489720927E-15";
+        results[2][14]="2.782853488076028E-7";
+        results[2][15]="29.89469998645674";
+        results[2][16]="3.434304892902040E+17";
+        results[2][17]="0.0003538133189576156";
+        results[2][18]="2695284886705.971";
+        results[2][19]="2.280490767877520E-9";
+        results[2][20]="91210560.48686773";
+        results[2][21]="4.251984043567731E-14";
+        results[2][22]="524.0044886392415";
+        results[2][23]="4.660208399475724E-19";
+        results[2][24]="0.002775588031390770";
+        results[2][25]="0.002778548402117154";
+        results[2][26]="7.442266954968664E+21";
+        results[2][27]="3.239172957900716E-8";
+        results[2][28]="1.147764689243079E+17";
+        results[2][29]="5.529321028550383E-13";
+        results[2][30]="258674242152.6016";
+        results[2][31]="6.746525722402801E-18";
+        results[2][32]="5258983.142583397";
+        results[2][33]="2.902936587789118E-23";
+        results[2][34]="139.1293956768774";
+        results[2][35]="3.415314068374301E-7";
+        results[2][36]="7.196683851264116E+25";
+        results[2][37]="2.889624990111060E-12";
+        results[2][38]="3.522103873109208E+20";
+        results[2][39]="3.079757438024150E-17";
+        results[2][40]="6385884553185581";
+        results[2][41]="4.930639138691073E-22";
+        results[2][42]="23061810822.16754";
+        results[2][43]="8.894703702675794E-27";
+        results[2][44]="605815.4291375707";
+        results[2][45]="7.802000696632482E-11";
+        results[2][46]="4.247869266534626E+29";
+        results[2][47]="2.836227680675536E-16";
+        results[2][48]="3.517489599908254E+24";
+        results[2][49]="1.201161095417993E-20";
+        results[2][50]="1.185444801723589E+20";
+        results[2][51]="2.989792272847868E-26";
+        results[2][52]="2124178310210390";
+        results[2][53]="6.227753305311532E-31";
+        results[2][54]="8662638896.794075";
+        results[2][55]="3.154168430197397E-15";
+        results[2][56]="3.641001234546430E+33";
+        results[2][57]="3.163668174867180E-20";
+        results[2][58]="2.910205416751843E+28";
+        results[2][59]="6.207602247697180E-25";
+        results[2][60]="1.503166304189191E+24";
+        results[2][61]="2.869583137237347E-30";
+        results[2][62]="1.074676529216240E+19";
+        results[2][63]="2.440686890302896E-35";
+        results[2][64]="112292081160512.5";
+        results[2][65]="2.648063450285608E-19";
+        results[2][66]="2.360777230418994E+37";
+        results[2][67]="8.547982860420744E-24";
+        results[2][68]="5.036376250800950E+32";
+        results[2][69]="3.796609395417242E-29";
+        results[2][70]="3.697852457491911E+27";
+        results[2][71]="2.320218655583322E-34";
+        results[2][72]="9.012909670930670E+22";
+        results[2][73]="4.396562103259092E-39";
+        results[2][74]="2.517200889984344E+17";
+        results[3][0]="1738195950114877";
+        results[3][1]="3822086211.611279";
+        results[3][2]="85755.27151045421";
+        results[3][3]="1";
+        results[3][4]="0.000006979682243988879";
+        results[3][5]="21776175562.60126";
+        results[3][6]="1.353289604013560E+19";
+        results[3][7]="208832.1654832305";
+        results[3][8]="19950038042989.76";
+        results[3][9]="1.946614203058035";
+        results[3][10]="710429128.3659471";
+        results[3][11]="0.00002358936206222687";
+        results[3][12]="3167.409422397122";
+        results[3][13]="2.967940628880855E-10";
+        results[3][14]="0.02386443564437743";
+        results[3][15]="2563628.114062170";
+        results[3][16]="2.945097485404958E+22";
+        results[3][17]="30.34135723122526";
+        results[3][18]="2.311348872574943E+17";
+        results[3][19]="0.0001955641049764209";
+        results[3][20]="7821786379172.049";
+        results[3][21]="3.646300461142698E-9";
+        results[3][22]="44936147.19595487";
+        results[3][23]="3.996374365923399E-14";
+        results[3][24]="238.0213052330826";
+        results[3][25]="238.2751726284952";
+        results[3][26]="6.382136233766191E+26";
+        results[3][27]="0.002777761564740970";
+        results[3][28]="9.842687255615237E+21";
+        results[3][29]="4.741684260718020E-8";
+        results[3][30]="2.218267986855733E+16";
+        results[3][31]="5.785501450769154E-13";
+        results[3][32]="450985527261.1410";
+        results[3][33]="2.489421152634873E-18";
+        results[3][34]="11931079.10135604";
+        results[3][35]="0.02928811852269122";
+        results[3][36]="6.171535776400555E+30";
+        results[3][37]="2.478005755903675E-7";
+        results[3][38]="3.020389739265025E+25";
+        results[3][39]="2.641054352841019E-12";
+        results[3][40]="5.476232636928451E+20";
+        results[3][41]="4.228282980585251E-17";
+        results[3][42]="1977671848577708";
+        results[3][43]="7.627677310280051E-22";
+        results[3][44]="51951866610.91471";
+        results[3][45]="0.000006690626880644714";
+        results[3][46]="3.642771822925908E+34";
+        results[3][47]="2.432214748217965E-11";
+        results[3][48]="3.016432756753313E+29";
+        results[3][49]="1.030058958653646E-15";
+        results[3][50]="1.016581408324629E+25";
+        results[3][51]="2.563904481179269E-21";
+        results[3][52]="1.821594877287098E+20";
+        results[3][53]="5.340626755971191E-26";
+        results[3][54]="742866950591597.5";
+        results[3][55]="2.704865701212809E-10";
+        results[3][56]="3.122350494384281E+38";
+        results[3][57]="2.713012233047182E-15";
+        results[3][58]="2.495654556647489E+33";
+        results[3][59]="5.323346161801775E-20";
+        results[3][60]="1.289044345411101E+29";
+        results[3][61]="2.460818810556097E-25";
+        results[3][62]="9.215917754885128E+23";
+        results[3][63]="2.093017669499310E-30";
+        results[3][64]="9.629637908393713E+18";
+        results[3][65]="2.270854001561525E-14";
+        results[3][66]="2.024490923702789E+42";
+        results[3][67]="7.330345910620899E-19";
+        results[3][68]="4.318958128162389E+37";
+        results[3][69]="3.255792695231470E-24";
+        results[3][70]="3.171103414978191E+32";
+        results[3][71]="1.989709807731689E-29";
+        results[3][72]="7.729045159298581E+27";
+        results[3][73]="3.770283768775571E-34";
+        results[3][74]="2.158632457669644E+22";
+        results[4][0]="2.490365448386802E+20";
+        results[4][1]="547601750051441.0";
+        results[4][2]="12286414841.35031";
+        results[4][3]="143272.9979736873";
+        results[4][4]="1";
+        results[4][5]="3119937957255229";
+        results[4][6]="1.938898586936469E+24";
+        results[4][7]="29920010422.11961";
+        results[4][8]="2.858301760108257E+18";
+        results[4][9]="278897.2527702849";
+        results[4][10]="101785311068822.8";
+        results[4][11]="3.379718622942007";
+        results[4][12]="453804243.7569410";
+        results[4][13]="0.00004252257517076709";
+        results[4][14]="3419.129239720079";
+        results[4][15]="367298685591.3171";
+        results[4][16]="4.219529460587362E+27";
+        results[4][17]="4347097.213108260";
+        results[4][18]="3.311538823369143E+22";
+        results[4][19]="28.01905561601273";
+        results[4][20]="1.120650784053732E+18";
+        results[4][21]="0.0005224163985807529";
+        results[4][22]="6438136526151.358";
+        results[4][23]="5.725725364310391E-9";
+        results[4][24]="34102025.98235386";
+        results[4][25]="34138398.32518239";
+        results[4][26]="9.143877916881798E+31";
+        results[4][27]="397.9782270365194";
+        results[4][28]="1.410191311229400E+27";
+        results[4][29]="0.006793553194777180";
+        results[4][30]="3.178179047858768E+21";
+        results[4][31]="8.289061376328140E-8";
+        results[4][32]="6.461404853344776E+16";
+        results[4][33]="3.566668317571105E-13";
+        results[4][34]="1709401471912.486";
+        results[4][35]="4196.196545754653";
+        results[4][36]="8.842144327867755E+35";
+        results[4][37]="0.03550313136443727";
+        results[4][38]="4.327402929934638E+30";
+        results[4][39]="3.783917749429893E-7";
+        results[4][40]="7.845962674940902E+25";
+        results[4][41]="6.057987789095672E-12";
+        results[4][42]="2.833469747538924E+20";
+        results[4][43]="1.092840195819694E-16";
+        results[4][44]="7443299679674857";
+        results[4][45]="0.9585861715133080";
+        results[4][46]="5.219108400046689E+39";
+        results[4][47]="0.000003484706986930048";
+        results[4][48]="4.321733642460815E+34";
+        results[4][49]="1.475796350959623E-10";
+        results[4][50]="1.456486660549828E+30";
+        results[4][51]="3.673382815367253E-16";
+        results[4][52]="2.609853591624336E+25";
+        results[4][53]="7.651676063864807E-21";
+        results[4][54]="1.064327751068292E+20";
+        results[4][55]="0.00003875342181289592";
+        results[4][56]="4.473485160550607E+43";
+        results[4][57]="3.887013961679578E-10";
+        results[4][58]="3.575599102375792E+38";
+        results[4][59]="7.626917638530619E-15";
+        results[4][60]="1.846852478880778E+34";
+        results[4][61]="3.525688884584153E-20";
+        results[4][62]="1.320392165821326E+29";
+        results[4][63]="2.998729163210665E-25";
+        results[4][64]="1.379667092536635E+24";
+        results[4][65]="3.253520607642641E-9";
+        results[4][66]="2.900548840094181E+47";
+        results[4][67]="1.050240634798815E-13";
+        results[4][68]="6.187900791446503E+42";
+        results[4][69]="4.664671802266443E-19";
+        results[4][70]="4.543334931485233E+37";
+        results[4][71]="2.850716892513680E-24";
+        results[4][72]="1.107363471446723E+33";
+        results[4][73]="5.401798587640085E-29";
+        results[4][74]="3.092737437336386E+27";
+        results[5][0]="79820.99267697315";
+        results[5][1]="0.1755168716666387";
+        results[5][2]="0.000003938031784503595";
+        results[5][3]="4.592174586052730E-11";
+        results[5][4]="3.205191941956922E-16";
+        results[5][5]="1";
+        results[5][6]="621454212.7120434";
+        results[5][7]="0.000009589937630824491";
+        results[5][8]="916.1405769180272";
+        results[5][9]="8.939192272132398E-11";
+        results[5][10]="0.03262414588473695";
+        results[5][11]="1.083264689633546E-15";
+        results[5][12]="1.454529705315602E-7";
+        results[5][13]="1.362930152886002E-20";
+        results[5][14]="1.095896548766010E-12";
+        results[5][15]="0.0001177262787348659";
+        results[5][16]="1352440182592.445";
+        results[5][17]="1.393328095835799E-9";
+        results[5][18]="10614117.55214028";
+        results[5][19]="8.980645128168683E-15";
+        results[5][20]="359.1900862796728";
+        results[5][21]="1.674444831077185E-19";
+        results[5][22]="0.002063546331483886";
+        results[5][23]="1.835204879954603E-24";
+        results[5][24]="1.093035388830462E-8";
+        results[5][25]="1.094201192231903E-8";
+        results[5][26]="2.930788381742739E+16";
+        results[5][27]="1.275596606371755E-13";
+        results[5][28]="451993382737.0138";
+        results[5][29]="2.177464195715552E-18";
+        results[5][30]="1018667.387429325";
+        results[5][31]="2.656803272979331E-23";
+        results[5][32]="20.71004276966202";
+        results[5][33]="1.143185655111196E-28";
+        results[5][34]="0.0005478959823343203";
+        results[5][35]="1.344961535532028E-12";
+        results[5][36]="2.834076974930183E+20";
+        results[5][37]="1.137943505635324E-17";
+        results[5][38]="1387015700062728";
+        results[5][39]="1.212818267950047E-22";
+        results[5][40]="25147816342.61536";
+        results[5][41]="1.941701364608288E-27";
+        results[5][42]="90818.14402590475";
+        results[5][43]="3.502762589487909E-32";
+        results[5][44]="2.385720415486439";
+        results[5][45]="3.072452672605791E-16";
+        results[5][46]="1.672824418802933E+24";
+        results[5][47]="1.116915475458918E-21";
+        results[5][48]="1.385198584609954E+19";
+        results[5][49]="4.730210572065213E-26";
+        results[5][50]="466831930796205.5";
+        results[5][51]="1.177389699953815E-31";
+        results[5][52]="8365081701.561654";
+        results[5][53]="2.452509046236414E-36";
+        results[5][54]="34113.74731325223";
+        results[5][55]="1.242121553179516E-20";
+        results[5][56]="1.433837858906067E+28";
+        results[5][57]="1.245862582824943E-25";
+        results[5][58]="1.146048143060329E+23";
+        results[5][59]="2.444573495698746E-30";
+        results[5][60]="5.919516683291835E+18";
+        results[5][61]="1.130050960271621E-35";
+        results[5][62]="42321103301135.62";
+        results[5][63]="9.611502550034045E-41";
+        results[5][64]="442209784.7581557";
+        results[5][65]="1.042815803460698E-24";
+        results[5][66]="9.296815769522365E+31";
+        results[5][67]="3.366222819772885E-29";
+        results[5][68]="1.983340975437319E+27";
+        results[5][69]="1.495116847249808E-34";
+        results[5][70]="1.456226051200787E+22";
+        results[5][71]="9.137094812685324E-40";
+        results[5][72]="3.549312475498482E+17";
+        results[5][73]="1.731380130517828E-44";
+        results[5][74]="991281711273.9084";
+        results[6][0]="0.0001284422746587108";
+        results[6][1]="2.824292893609623E-10";
+        results[6][2]="6.336801173682476E-15";
+        results[6][3]="7.389401330167758E-20";
+        results[6][4]="5.157567325787970E-25";
+        results[6][5]="1.609129006682524E-9";
+        results[6][6]="1";
+        results[6][7]="1.543144681403597E-14";
+        results[6][8]="0.000001474188376517659";
+        results[6][9]="1.438431358140050E-19";
+        results[6][10]="5.249645946137250E-11";
+        results[6][11]="1.743112634004281E-24";
+        results[6][12]="2.340525939904718E-16";
+        results[6][13]="2.193130443091112E-29";
+        results[6][14]="1.763438924942655E-21";
+        results[6][15]="1.894367699610646E-13";
+        results[6][16]="2176.250727612512";
+        results[6][17]="2.242044654835111E-18";
+        results[6][18]="0.01707948443348703";
+        results[6][19]="1.445101657445832E-23";
+        results[6][20]="5.779831867454199E-7";
+        results[6][21]="2.694397747775916E-28";
+        results[6][22]="3.320512258624031E-12";
+        results[6][23]="2.953081405540270E-33";
+        results[6][24]="1.758834949497607E-17";
+        results[6][25]="1.760710877566955E-17";
+        results[6][26]="47160165.97510373";
+        results[6][27]="2.052599500138579E-22";
+        results[6][28]="727.3156629906847";
+        results[6][29]="3.503820798338526E-27";
+        results[6][30]="0.001639167241274031";
+        results[6][31]="4.275139211600108E-32";
+        results[6][32]="3.332513055029883E-8";
+        results[6][33]="1.839533197662788E-37";
+        results[6][34]="8.816353178189703E-13";
+        results[6][35]="2.164216619696854E-21";
+        results[6][36]="456039546753.1217";
+        results[6][37]="1.831097902883797E-26";
+        results[6][38]="2231887.195695002";
+        results[6][39]="1.951581054792877E-31";
+        results[6][40]="40.46608073162718";
+        results[6][41]="3.124447988106234E-36";
+        results[6][42]="0.0001461381098851545";
+        results[6][43]="5.636396886267384E-41";
+        results[6][44]="3.838931922393911E-9";
+        results[6][45]="4.943972717149220E-25";
+        results[6][46]="2691790295382633";
+        results[6][47]="1.797261089573547E-30";
+        results[6][48]="22289632225.11453";
+        results[6][49]="7.611519039226468E-35";
+        results[6][50]="751192.8010897827";
+        results[6][51]="1.894571918364917E-40";
+        results[6][52]="13.46049560925206";
+        results[6][53]="3.946403445450303E-45";
+        results[6][54]="0.00005489342032839216";
+        results[6][55]="1.998733821046708E-29";
+        results[6][56]="2.307230089645316E+19";
+        results[6][57]="2.004753620364024E-34";
+        results[6][58]="184413931005301.8";
+        results[6][59]="3.933634120896147E-39";
+        results[6][60]="9525266000.626017";
+        results[6][61]="1.818397779202506E-44";
+        results[6][62]="68100.11491666482";
+        results[6][63]="1.546614755106283E-49";
+        results[6][64]="0.7115725916931837";
+        results[6][65]="1.678025157975551E-33";
+        results[6][66]="1.495977592452194E+23";
+        results[6][67]="5.416686782253186E-38";
+        results[6][68]="3.191451493718201E+18";
+        results[6][69]="2.405835887289389E-43";
+        results[6][70]="23432555792739.37";
+        results[6][71]="1.470276429990037E-48";
+        results[6][72]="571130165.8104760";
+        results[6][73]="2.786013989610011E-53";
+        results[6][74]="1595.100155404736";
+        results[7][0]="8323411032.456378";
+        results[7][1]="18302.19115320239";
+        results[7][2]="0.4106420642242513";
+        results[7][3]="0.000004788534360528390";
+        results[7][4]="3.342244825091065E-11";
+        results[7][5]="104275.9649224148";
+        results[7][6]="64802737685647.92";
+        results[7][7]="1";
+        results[7][8]="95531442.66270503";
+        results[7][9]="0.000009321428998035992";
+        results[7][10]="3401.914291900572";
+        results[7][11]="1.129584707779182E-10";
+        results[7][12]="0.01516724885301000";
+        results[7][13]="1.421208568140421E-15";
+        results[7][14]="1.142756700777198E-7";
+        results[7][15]="12.27602131180330";
+        results[7][16]="1.410270050396740E+17";
+        results[7][17]="0.0001452906316467887";
+        results[7][18]="1106797349549.367";
+        results[7][19]="9.364654363655727E-10";
+        results[7][20]="37454892.83737830";
+        results[7][21]="1.746043504699232E-14";
+        results[7][22]="215.1782848775914";
+        results[7][23]="1.913677596875906E-19";
+        results[7][24]="0.001139773198646432";
+        results[7][25]="0.001140988851392383";
+        results[7][26]="3.056107864896266E+21";
+        results[7][27]="1.330140669811724E-8";
+        results[7][28]="4.713204612344845E+16";
+        results[7][29]="2.270571800922490E-13";
+        results[7][30]="106222524759.1882";
+        results[7][31]="2.770407248989495E-18";
+        results[7][32]="2159559.693390987";
+        results[7][33]="1.192067872721828E-23";
+        results[7][34]="57.13238223502557";
+        results[7][35]="1.402471619011349E-7";
+        results[7][36]="2.955261112252432E+25";
+        results[7][37]="1.186601570773187E-12";
+        results[7][38]="1.446324004865796E+20";
+        results[7][39]="1.264677951660229E-17";
+        results[7][40]="2622312814817888";
+        results[7][41]="2.024727833856987E-22";
+        results[7][42]="9470149600.764056";
+        results[7][43]="3.652539489129880E-27";
+        results[7][44]="248773.2983599527";
+        results[7][45]="3.203829671144209E-11";
+        results[7][46]="1.744353804164535E+29";
+        results[7][47]="1.164674389402563E-16";
+        results[7][48]="1.444429190193662E+24";
+        results[7][49]="4.932472716883077E-21";
+        results[7][50]="4.867935004036829E+19";
+        results[7][51]="1.227734470523965E-26";
+        results[7][52]="872276966085176.7";
+        results[7][53]="2.557377472772532E-31";
+        results[7][54]="3557243918.208811";
+        results[7][55]="1.295234235087226E-15";
+        results[7][56]="1.495148262797194E+33";
+        results[7][57]="1.299135229848029E-20";
+        results[7][58]="1.195052759651575E+28";
+        results[7][59]="2.549102600877473E-25";
+        results[7][60]="6.172633140245884E+23";
+        results[7][61]="1.178371542938247E-30";
+        results[7][62]="4.413073883307109E+18";
+        results[7][63]="1.002248702759050E-35";
+        results[7][64]="46111852003790.03";
+        results[7][65]="1.087406241422075E-19";
+        results[7][66]="9.694344350728666E+36";
+        results[7][67]="3.510161326756695E-24";
+        results[7][68]="2.068147939838898E+32";
+        results[7][69]="1.559047519187323E-29";
+        results[7][70]="1.518493766341199E+27";
+        results[7][71]="9.527793781803528E-35";
+        results[7][72]="3.701079831937688E+22";
+        results[7][73]="1.805413337572430E-39";
+        results[7][74]="1.033668569530294E+17";
+        results[8][0]="87.12745040231444";
+        results[8][1]="0.0001915829034197918";
+        results[8][2]="4.298501653263149E-9";
+        results[8][3]="5.012521769858929E-14";
+        results[8][4]="3.498580919469208E-19";
+        results[8][5]="0.001091535540718088";
+        results[8][6]="678339.3601041740";
+        results[8][7]="1.046775775731475E-8";
+        results[8][8]="1";
+        results[8][9]="9.757446070344992E-14";
+        results[8][10]="0.00003561041471876213";
+        results[8][11]="1.182421908739965E-18";
+        results[8][12]="1.587670868382187E-10";
+        results[8][13]="1.487686701391408E-23";
+        results[8][14]="1.196210031928393E-15";
+        results[8][15]="1.285024173155902E-7";
+        results[8][16]="1476236525.994914";
+        results[8][17]="1.520867136485833E-12";
+        results[8][18]="11585.68654152080";
+        results[8][19]="9.802693335972867E-18";
+        results[8][20]="0.3920687450478594";
+        results[8][21]="1.827716044092442E-22";
+        results[8][22]="0.000002252434160733091";
+        results[8][23]="2.003191350969721E-27";
+        results[8][24]="1.193086974171064E-11";
+        results[8][25]="1.194359490017227E-11";
+        results[8][26]="31990596809958.51";
+        results[8][27]="1.392359031474151E-16";
+        results[8][28]="493366841.4268441";
+        results[8][29]="2.376779558264652E-21";
+        results[8][30]="1111.911657549550";
+        results[8][31]="2.899995197153080E-26";
+        results[8][32]="0.02260574773287777";
+        results[8][33]="1.247827772192961E-31";
+        results[8][34]="5.980479373345604E-7";
+        results[8][35]="1.468073316931983E-15";
+        results[8][36]="3.093495743267101E+17";
+        results[8][37]="1.242105779730290E-20";
+        results[8][38]="1513976932152.447";
+        results[8][39]="1.323834243899629E-25";
+        results[8][40]="27449735.30941583";
+        results[8][41]="2.119436048930757E-30";
+        results[8][42]="99.13123194632914";
+        results[8][43]="3.823389857123776E-35";
+        results[8][44]="0.002604098623720172";
+        results[8][45]="3.353691289323497E-19";
+        results[8][46]="1.825947306504481E+21";
+        results[8][47]="1.219152937441450E-24";
+        results[8][48]="1.511993486054156E+16";
+        results[8][49]="5.163192954489619E-29";
+        results[8][50]="509563644006.1053";
+        results[8][51]="1.285162702774995E-34";
+        results[8][52]="9130783.978265085";
+        results[8][53]="2.677000787899666E-39";
+        results[8][54]="37.23636761949100";
+        results[8][55]="1.355819821187394E-23";
+        results[8][56]="1.565084982623100E+25";
+        results[8][57]="1.359903288004258E-28";
+        results[8][58]="1.250952279524317E+20";
+        results[8][59]="2.668338852452637E-33";
+        results[8][60]="6461362843686697";
+        results[8][61]="1.233490785959079E-38";
+        results[8][62]="46194988375.59113";
+        results[8][63]="1.049129663306469E-43";
+        results[8][64]="482687.6965168229";
+        results[8][65]="1.138270511899841E-27";
+        results[8][66]="1.014780482794204E+29";
+        results[8][67]="3.674351845758363E-32";
+        results[8][68]="2.164887164052315E+24";
+        results[8][69]="1.631973176299542E-37";
+        results[8][70]="1.589522490205218E+19";
+        results[8][71]="9.973463726956913E-43";
+        results[8][72]="387420071212069.1";
+        results[8][73]="1.889862946953332E-47";
+        results[8][74]="1082019218.719317";
+        results[9][0]="892932943458573.4";
+        results[9][1]="1963453367.188511";
+        results[9][2]="44053.55276650961";
+        results[9][3]="0.5137124749367641";
+        results[9][4]="0.000003585549839831714";
+        results[9][5]="11186693042.92137";
+        results[9][6]="6.952017517839994E+18";
+        results[9][7]="107279.6885767942";
+        results[9][8]="10248583418146.87";
+        results[9][9]="1";
+        results[9][10]="364956305.8000387";
+        results[9][11]="0.00001211814956716597";
+        results[9][12]="1627.137733517652";
+        results[9][13]="1.524668125927760E-10";
+        results[9][14]="0.01225945829784226";
+        results[9][15]="1316967.743292346";
+        results[9][16]="1.512933318157422E+22";
+        results[9][17]="15.58673371619321";
+        results[9][18]="1.187368749772774E+17";
+        results[9][19]="0.0001004637203762303";
+        results[9][20]="4018149239271.144";
+        results[9][21]="1.873150034256679E-9";
+        results[9][22]="23084259.39015671";
+        results[9][23]="2.052987366292351E-14";
+        results[9][24]="122.2745137989658";
+        results[9][25]="122.4049286469690";
+        results[9][26]="3.278583000031628E+26";
+        results[9][27]="0.001426970768207302";
+        results[9][28]="5.056311230110650E+21";
+        results[9][29]="2.435862356942155E-8";
+        results[9][30]="1.139551937600652E+16";
+        results[9][31]="2.972084269024861E-13";
+        results[9][32]="231676891369.9822";
+        results[9][33]="1.278846701479992E-18";
+        results[9][34]="6129144.173823912";
+        results[9][35]="0.01504567185253299";
+        results[9][36]="3.170394917855513E+30";
+        results[9][37]="1.272982469772824E-7";
+        results[9][38]="1.551611888231443E+25";
+        results[9][39]="1.356742568040473E-12";
+        results[9][40]="2.813209021245996E+20";
+        results[9][41]="2.172121714689447E-17";
+        results[9][42]="1015954699945620";
+        results[9][43]="3.918432989082965E-22";
+        results[9][44]="26688321974.27763";
+        results[9][45]="0.000003437058493734438";
+        results[9][46]="1.871337328785176E+34";
+        results[9][47]="1.249459057884749E-11";
+        results[9][48]="1.549579136952070E+29";
+        results[9][49]="5.291541369807505E-16";
+        results[9][50]="5.222305512451464E+24";
+        results[9][51]="1.317109716528063E-21";
+        results[9][52]="9.357760127432864E+19";
+        results[9][53]="2.743546588523462E-26";
+        results[9][54]="381620019737136.4";
+        results[9][55]="1.389523253741598E-10";
+        results[9][56]="1.603990400090178E+38";
+        results[9][57]="1.393708228772385E-15";
+        results[9][58]="1.282048878882594E+33";
+        results[9][59]="2.734669331724314E-20";
+        results[9][60]="6.621981609843777E+28";
+        results[9][61]="1.264153321541716E-25";
+        results[9][62]="4.734331918675705E+23";
+        results[9][63]="1.075209287084869E-30";
+        results[9][64]="4.946865122665819E+18";
+        results[9][65]="1.166566029362225E-14";
+        results[9][66]="1.040006242902376E+42";
+        results[9][67]="3.765690139887650E-19";
+        results[9][68]="2.218702669166555E+37";
+        results[9][69]="1.672541323348396E-24";
+        results[9][70]="1.629035383588871E+32";
+        results[9][71]="1.022138749735799E-29";
+        results[9][72]="3.970506917681290E+27";
+        results[9][73]="1.936841806071609E-34";
+        results[9][74]="1.108916422308302E+22";
+        results[10][0]="2446684.518852554";
+        results[10][1]="5.379968330412397";
+        results[10][2]="0.0001207091152184304";
+        results[10][3]="1.407599942164664E-9";
+        results[10][4]="9.824600322966481E-15";
+        results[10][5]="30.65214346248511";
+        results[10][6]="19048903683.41529";
+        results[10][7]="0.0002939521440563168";
+        results[10][8]="28081.67239549524";
+        results[10][9]="2.740054039641405E-9";
+        results[10][10]="1";
+        results[10][11]="3.320438467449187E-14";
+        results[10][12]="0.000004458445319778002";
+        results[10][13]="4.177673057560849E-19";
+        results[10][14]="3.359157823281803E-11";
+        results[10][15]="0.003608562785085618";
+        results[10][16]="41455190501253.18";
+        results[10][17]="4.270849268387010E-8";
+        results[10][18]="325345453.9358852";
+        results[10][19]="2.752760228542944E-13";
+        results[10][20]="11009.94605494694";
+        results[10][21]="5.132532318219450E-18";
+        results[10][22]="0.06325211819412893";
+        results[10][23]="5.625296326342124E-23";
+        results[10][24]="3.350387754800450E-7";
+        results[10][25]="3.353961192111453E-7";
+        results[10][26]="8.983494593536299E+17";
+        results[10][27]="3.909977017876616E-12";
+        results[10][28]="13854566011748.89";
+        results[10][29]="6.674394491149785E-17";
+        results[10][30]="31224338.90003856";
+        results[10][31]="8.143671507496243E-22";
+        results[10][32]="634.8072020898827";
+        results[10][33]="3.504109070472339E-27";
+        results[10][34]="0.01679418625303079";
+        results[10][35]="4.122595393865199E-11";
+        results[10][36]="8.687053401928578E+21";
+        results[10][37]="3.488040758693718E-16";
+        results[10][38]="4.251500422304194E+16";
+        results[10][39]="3.717547954312753E-21";
+        results[10][40]="770834474302.0734";
+        results[10][41]="5.951730878927634E-26";
+        results[10][42]="2783770.779678667";
+        results[10][43]="1.073671814080092E-30";
+        results[10][44]="73.12744443686990";
+        results[10][45]="9.417726010240848E-15";
+        results[10][46]="5.127565407269577E+25";
+        results[10][47]="3.423585338923651E-20";
+        results[10][48]="4.245930573949562E+20";
+        results[10][49]="1.449910930627067E-24";
+        results[10][50]="1.430939931563421E+16";
+        results[10][51]="3.608951799423663E-30";
+        results[10][52]="256407684391.6768";
+        results[10][53]="7.517465912828107E-35";
+        results[10][54]="1045659.476688773";
+        results[10][55]="3.807368804590335E-19";
+        results[10][56]="4.395020375313125E+29";
+        results[10][57]="3.818835862329240E-24";
+        results[10][58]="3.512883209599986E+24";
+        results[10][59]="7.493141749474667E-29";
+        results[10][60]="1.814458746048353E+20";
+        results[10][61]="3.463848415416480E-34";
+        results[10][62]="1297232529877061";
+        results[10][63]="2.946131550536850E-39";
+        results[10][64]="13554677762.92165";
+        results[10][65]="3.196453961262399E-23";
+        results[10][66]="2.849673307116934E+33";
+        results[10][67]="1.031819447983696E-27";
+        results[10][68]="6.079365211412986E+28";
+        results[10][69]="4.582853609507953E-33";
+        results[10][70]="4.463644983521472E+23";
+        results[10][71]="2.800715410287590E-38";
+        results[10][72]="1.087940351921676E+19";
+        results[10][73]="5.307051214872866E-43";
+        results[10][74]="30384909225705.58";
+        results[11][0]="7.368558528753992E+19";
+        results[11][1]="162025840356721.7";
+        results[11][2]="3635336609.961668";
+        results[11][3]="42391.98997251724";
+        results[11][4]="0.2958826196985332";
+        results[11][5]="923135416089567.4";
+        results[11][6]="5.736863932325467E+23";
+        results[11][7]="8852811065.104166";
+        results[11][8]="8.457218126697593E+17";
+        results[11][9]="82520.84977639587";
+        results[11][10]="30116504485873.39";
+        results[11][11]="1";
+        results[11][12]="134272788.4731154";
+        results[11][13]="0.00001258169093785437";
+        results[11][14]="1011.660916536231";
+        results[11][15]="108677297304.5868";
+        results[11][16]="1.248485430693727E+27";
+        results[11][17]="1286230.511498665";
+        results[11][18]="9.798267822918602E+21";
+        results[11][19]="8.290351577144743";
+        results[11][20]="3.315810897530334E+17";
+        results[11][21]="0.0001545739325855462";
+        results[11][22]="1904932701334.478";
+        results[11][23]="1.694142620466497E-9";
+        results[11][24]="10090196.78468630";
+        results[11][25]="10100958.72876698";
+        results[11][26]="2.705514552250553E+31";
+        results[11][27]="117.7548403985430";
+        results[11][28]="4.172510994426643E+26";
+        results[11][29]="0.002010094316332011";
+        results[11][30]="9.403679425514422E+20";
+        results[11][31]="2.452589194869899E-8";
+        results[11][32]="1.911817394940469E+16";
+        results[11][33]="1.055315165398698E-13";
+        results[11][34]="505782185625.9951";
+        results[11][35]="1241.581626727822";
+        results[11][36]="2.616236827482037E+35";
+        results[11][37]="0.01050475951561086";
+        results[11][38]="1.280403315400169E+30";
+        results[11][39]="1.119595496425095E-7";
+        results[11][40]="2.321483990318425E+25";
+        results[11][41]="1.792453297139352E-12";
+        results[11][42]="8.383744517383584E+19";
+        results[11][43]="3.233524200509892E-17";
+        results[11][44]="2202343008423450";
+        results[11][45]="0.2836289876341450";
+        results[11][46]="1.544243465896434E+39";
+        results[11][47]="0.000001031064232174645";
+        results[11][48]="1.278725871770590E+34";
+        results[11][49]="4.366624904634691E-11";
+        results[11][50]="4.309490886794513E+29";
+        results[11][51]="1.086890130566436E-16";
+        results[11][52]="7.722103177194344E+24";
+        results[11][53]="2.263997958860880E-21";
+        results[11][54]="3.149160832039346E+19";
+        results[11][55]="0.00001146646396828192";
+        results[11][56]="1.323626508486227E+43";
+        results[11][57]="1.150099873786527E-10";
+        results[11][58]="1.057957629402673E+38";
+        results[11][59]="2.256672371113390E-15";
+        results[11][60]="5.464515496479744E+33";
+        results[11][61]="1.043190063412758E-20";
+        results[11][62]="3.906810930526339E+28";
+        results[11][63]="8.872718405771617E-26";
+        results[11][64]="4.082195136515981E+23";
+        results[11][65]="9.626602006324680E-10";
+        results[11][66]="8.582219893706080E+46";
+        results[11][67]="3.107479503381239E-14";
+        results[11][68]="1.830892296607818E+42";
+        results[11][69]="1.380195312888473E-19";
+        results[11][70]="1.344293841695707E+37";
+        results[11][71]="8.434775821758094E-25";
+        results[11][72]="3.276496048901183E+32";
+        results[11][73]="1.598298317194785E-29";
+        results[11][74]="9.150872549988179E+26";
+        results[12][0]="548775266570.8102";
+        results[12][1]="1206691.558276256";
+        results[12][2]="27.07426166761666";
+        results[12][3]="0.0003157154212300068";
+        results[12][4]="2.203593319712548E-9";
+        results[12][5]="6875074.440525237";
+        results[12][6]="4272543973773303";
+        results[12][7]="65.93153509191260";
+        results[12][8]="6298534664.297173";
+        results[12][9]="0.0006145761230907817";
+        results[12][10]="224293.4315161216";
+        results[12][11]="7.447525380023099E-9";
+        results[12][12]="1";
+        results[12][13]="9.370246258327704E-14";
+        results[12][14]="0.000007534370351881011";
+        results[12][15]="809.3769299082260";
+        results[12][16]="9.298126931680603E+18";
+        results[12][17]="0.009579234378946397";
+        results[12][18]="72972848291449.96";
+        results[12][19]="6.174260378010000E-8";
+        results[12][20]="2469458581.471433";
+        results[12][21]="1.151193286020835E-12";
+        results[12][22]="14187.03464042448";
+        results[12][23]="1.261717016330308E-17";
+        results[12][24]="0.07514699664337871";
+        results[12][25]="0.07522714649505796";
+        results[12][26]="2.014938829390782E+23";
+        results[12][27]="8.769821624887181E-7";
+        results[12][28]="3.107488152941784E+18";
+        results[12][29]="1.497022843712283E-11";
+        results[12][30]="7003414118711.969";
+        results[12][31]="1.826572027556399E-16";
+        results[12][32]="142383085.7078879";
+        results[12][33]="7.859486478230080E-22";
+        results[12][34]="3766.825664213152";
+        results[12][35]="0.000009246710676425823";
+        results[12][36]="1.948449017282359E+27";
+        results[12][37]="7.823446310355102E-11";
+        results[12][38]="9.535836188108477E+21";
+        results[12][39]="8.338215874985453E-16";
+        results[12][40]="1.728931093721377E+17";
+        results[12][41]="1.334934142295141E-20";
+        results[12][42]="624381500728.4375";
+        results[12][43]="2.408175355021632E-25";
+        results[12][44]="16402005.45075007";
+        results[12][45]="2.112334083915552E-9";
+        results[12][46]="1.150079240519853E+31";
+        results[12][47]="7.678877037554697E-15";
+        results[12][48]="9.523343384103629E+25";
+        results[12][49]="3.252054980230781E-19";
+        results[12][50]="3.209504275438039E+21";
+        results[12][51]="8.094641832690152E-25";
+        results[12][52]="5.751055939931189E+16";
+        results[12][53]="1.686118225893689E-29";
+        results[12][54]="234534552223.8769";
+        results[12][55]="8.539678142289999E-14";
+        results[12][56]="9.857742015622534E+34";
+        results[12][57]="8.565397999586525E-19";
+        results[12][58]="7.879166295965479E+29";
+        results[12][59]="1.680662475826388E-23";
+        results[12][60]="4.069711784956242E+25";
+        results[12][61]="7.769184473454425E-29";
+        results[12][62]="2.909607356004657E+20";
+        results[12][63]="6.607979551678220E-34";
+        results[12][64]="3040225188540963";
+        results[12][65]="7.169436276548434E-18";
+        results[12][66]="6.391630047531518E+38";
+        results[12][67]="2.314303246933335E-22";
+        results[12][68]="1.363561684707550E+34";
+        results[12][69]="1.027903962212583E-27";
+        results[12][70]="1.001166250423753E+29";
+        results[12][71]="6.281820700734860E-33";
+        results[12][72]="2.440178748173697E+24";
+        results[12][73]="1.190336728215637E-37";
+        results[12][74]="6.815135556539365E+18";
+        results[13][0]="5.856572510920854E+24";
+        results[13][1]="1.287790656733084E+19";
+        results[13][2]="288938635348614.2";
+        results[13][3]="3369339636.612199";
+        results[13][4]="23516.92003563011";
+        results[13][5]="7.337133145689837E+19";
+        results[13][6]="4.559692302618115E+28";
+        results[13][7]="703626492562206.3";
+        results[13][8]="6.721845393016666E+22";
+        results[13][9]="6558804391.555706";
+        results[13][10]="2.393677021207241E+18";
+        results[13][11]="79480.57259865707";
+        results[13][12]="10672078112261.57";
+        results[13][13]="1";
+        results[13][14]="80407388.92198187";
+        results[13][15]="8637733818243049";
+        results[13][16]="9.923033691261843E+31";
+        results[13][17]="102230337547.7774";
+        results[13][18]="7.787719370405676E+26";
+        results[13][19]="658921.8903956439";
+        results[13][20]="2.635425487645780E+22";
+        results[13][21]="12.28562467072543";
+        results[13][22]="1.514051418639709E+17";
+        results[13][23]="0.0001346514255384665";
+        results[13][24]="801974618079.9959";
+        results[13][25]="802829983557.8030";
+        results[13][26]="2.150358457868733E+36";
+        results[13][27]="9359222.141139671";
+        results[13][28]="3.316335630112216E+31";
+        results[13][29]="159.7634472393744";
+        results[13][30]="7.474098252740968E+25";
+        results[13][31]="0.001949331935575389";
+        results[13][32]="1.519523412539414E+21";
+        results[13][33]="8.387705361793504E-9";
+        results[13][34]="4.019985772375435E+16";
+        results[13][35]="98681618.62029944";
+        results[13][36]="2.079400011019663E+40";
+        results[13][37]="834.9243013119425";
+        results[13][38]="1.017671886652243E+35";
+        results[13][39]="0.008898609113474424";
+        results[13][40]="1.845128768291237E+30";
+        results[13][41]="1.424652144129865E-7";
+        results[13][42]="6.663448147624991E+24";
+        results[13][43]="2.570023549681410E-12";
+        results[13][44]="1.750434833681448E+20";
+        results[13][45]="22542.99434273927";
+        results[13][46]="1.227373549011834E+44";
+        results[13][47]="0.08194957555923548";
+        results[13][48]="1.016338644850434E+39";
+        results[13][49]="0.000003470618477439216";
+        results[13][50]="3.425208032911223E+34";
+        results[13][51]="8.638664992924948E-12";
+        results[13][52]="6.137571821893155E+29";
+        results[13][53]="1.799438541324536E-16";
+        results[13][54]="2.502971061357505E+24";
+        results[13][55]="0.9113611218809168";
+        results[13][56]="1.052025928012465E+48";
+        results[13][57]="0.000009141059651419642";
+        results[13][58]="8.408707817004228E+42";
+        results[13][59]="1.793616122236614E-10";
+        results[13][60]="4.343228206344449E+38";
+        results[13][61]="8.291334356927543E-16";
+        results[13][62]="3.105155697929257E+33";
+        results[13][63]="7.052087393973718E-21";
+        results[13][64]="3.244552069097433E+28";
+        results[13][65]="0.00007651278396420666";
+        results[13][66]="6.821197513193451E+51";
+        results[13][67]="2.469842502673314E-9";
+        results[13][68]="1.455203681008597E+47";
+        results[13][69]="1.096987137663585E-14";
+        results[13][70]="1.068452442788232E+42";
+        results[13][71]="6.704008120546416E-20";
+        results[13][72]="2.604177820839036E+37";
+        results[13][73]="1.270336654341115E-24";
+        results[13][74]="7.273165900503936E+31";
+        results[14][0]="7.283624788019671E+16";
+        results[14][1]="160158248389.6609";
+        results[14][2]="3593433.877438394";
+        results[14][3]="41.90335840753915";
+        results[14][4]="0.0002924721266406031";
+        results[14][5]="912494889345.1759";
+        results[14][6]="5.670737930617694E+20";
+        results[14][7]="8750769.077266332";
+        results[14][8]="835973594359440.8";
+        results[14][9]="81.56967263194704";
+        results[14][10]="29769366389.07392";
+        results[14][11]="0.0009884734930986993";
+        results[14][12]="132725.0922501232";
+        results[14][13]="1.243666799042916E-8";
+        results[14][14]="1";
+        results[14][15]="107424627.6871908";
+        results[14][16]="1.234094754760663E+24";
+        results[14][17]="1271.404766631212";
+        results[14][18]="9.685328021236938E+18";
+        results[14][19]="0.008194792782476575";
+        results[14][20]="327759118033654.3";
+        results[14][21]="1.527922350848377E-7";
+        results[14][22]="1882975481.406032";
+        results[14][23]="1.674615073859902E-12";
+        results[14][24]="9973.892061812134";
+        results[14][25]="9984.529958270096";
+        results[14][26]="2.674329420092467E+28";
+        results[14][27]="0.1163975384180276";
+        results[14][28]="4.124416517653632E+23";
+        results[14][29]="0.000001986924950322545";
+        results[14][30]="9.295287849718610E+17";
+        results[14][31]="2.424319408589176E-11";
+        results[14][32]="18897808185436.61";
+        results[14][33]="1.043151067861683E-16";
+        results[14][34]="499952283.7728221";
+        results[14][35]="1.227270527538816";
+        results[14][36]="2.586080755634628E+32";
+        results[14][37]="0.00001038367633255766";
+        results[14][38]="1.265644737748760E+27";
+        results[14][39]="1.106690471208886E-10";
+        results[14][40]="2.294725389082761E+22";
+        results[14][41]="1.771792571839617E-15";
+        results[14][42]="8.287109228345220E+16";
+        results[14][43]="3.196252961497192E-20";
+        results[14][44]="2176957686537.825";
+        results[14][45]="0.0002803597361507711";
+        results[14][46]="1.526443732929490E+36";
+        results[14][47]="1.019179663186800E-9";
+        results[14][48]="1.263986629184754E+31";
+        results[14][49]="4.316292972536028E-14";
+        results[14][50]="4.259817510346784E+26";
+        results[14][51]="1.074362083975506E-19";
+        results[14][52]="7.633094301629857E+21";
+        results[14][53]="2.237901970763539E-24";
+        results[14][54]="3.112862007975538E+16";
+        results[14][55]="1.133429569221800E-8";
+        results[14][56]="1.308369718401416E+40";
+        results[14][57]="1.136843239654142E-13";
+        results[14][58]="1.045763073486079E+35";
+        results[14][59]="2.230660821453777E-18";
+        results[14][60]="5.401528720897306E+30";
+        results[14][61]="1.031165725947463E-23";
+        results[14][62]="3.861779047373550E+25";
+        results[14][63]="8.770446955834192E-29";
+        results[14][64]="4.035141686102474E+20";
+        results[14][65]="9.515640911862703E-13";
+        results[14][66]="8.483296876872797E+43";
+        results[14][67]="3.071661119439865E-17";
+        results[14][68]="1.809788503915430E+39";
+        results[14][69]="1.364286482089321E-22";
+        results[14][70]="1.328798829452025E+34";
+        results[14][71]="8.337552320037675E-28";
+        results[14][72]="3.238729494581439E+29";
+        results[14][73]="1.579875520611302E-32";
+        results[14][74]="9.045394954387817E+23";
+        results[15][0]="678021878.6728144";
+        results[15][1]="1490.889490034119";
+        results[15][2]="0.03345074546501661";
+        results[15][3]="3.900721772064906E-7";
+        results[15][4]="2.722579849122226E-12";
+        results[15][5]="8494.280212934647";
+        results[15][6]="5278806222284.789";
+        results[15][7]="0.08145961746078984";
+        results[15][8]="7781954.774781330";
+        results[15][9]="7.593200403679254E-7";
+        results[15][10]="277.1186368526144";
+        results[15][11]="9.201553818525026E-12";
+        results[15][12]="0.001235518289498798";
+        results[15][13]="1.157711062927156E-16";
+        results[15][14]="9.308852369606484E-9";
+        results[15][15]="1";
+        results[15][16]="1.148800588217273E+16";
+        results[15][17]="0.00001183531927458393";
+        results[15][18]="90159288700.90755";
+        results[15][19]="7.628411621159118E-11";
+        results[15][20]="3051061.242567714";
+        results[15][21]="1.422320359626963E-15";
+        results[15][22]="17.52834077199745";
+        results[15][23]="1.558874449847949E-20";
+        results[15][24]="0.00009284548875379919";
+        results[15][25]="0.00009294451536144952";
+        results[15][26]="2.489493775933610E+20";
+        results[15][27]="1.083527501319018E-9";
+        results[15][28]="3839358447360413";
+        results[15][29]="1.849599103204027E-14";
+        results[15][30]="8652846232.602745";
+        results[15][31]="2.256763147132834E-19";
+        results[15][32]="175916.9065073704";
+        results[15][33]="9.710539289921761E-25";
+        results[15][34]="4.653982001488808";
+        results[15][35]="1.142448015842791E-8";
+        results[15][36]="2.407344397008314E+24";
+        results[15][37]="9.666011003355619E-14";
+        results[15][38]="1.178170001607253E+19";
+        results[15][39]="1.030201821533375E-18";
+        results[15][40]="213612598757592.2";
+        results[15][41]="1.649335548082038E-23";
+        results[15][42]="771434763.7746916";
+        results[15][43]="2.975344695449488E-28";
+        results[15][44]="20264.97771886068";
+        results[15][45]="2.609827394209354E-12";
+        results[15][46]="1.420943936035166E+28";
+        results[15][47]="9.487393022711177E-18";
+        results[15][48]="1.176626492823741E+23";
+        results[15][49]="4.017973406530782E-22";
+        results[15][50]="3.965401232528285E+18";
+        results[15][51]="1.000107803123075E-27";
+        results[15][52]="71055347977156.85";
+        results[15][53]="2.083229906348919E-32";
+        results[15][54]="289771728.7920109";
+        results[15][55]="1.055092853123241E-16";
+        results[15][56]="1.217942055346239E+32";
+        results[15][57]="1.058270588532557E-21";
+        results[15][58]="9.734854064667849E+26";
+        results[15][59]="2.076489227357834E-26";
+        results[15][60]="5.028203343302236E+22";
+        results[15][61]="9.598969511443032E-32";
+        results[15][62]="3.594873103603994E+17";
+        results[15][63]="8.164279592732510E-37";
+        results[15][64]="3756253824637.292";
+        results[15][65]="8.857969645071753E-21";
+        results[15][66]="7.896975823435262E+35";
+        results[15][67]="2.859363989032589E-25";
+        results[15][68]="1.684705400315972E+31";
+        results[15][69]="1.269994145161927E-30";
+        results[15][70]="1.236959213227480E+26";
+        results[15][71]="7.761304367110075E-36";
+        results[15][72]="3.014885473014884E+21";
+        results[15][73]="1.470682798372580E-40";
+        results[15][74]="8420224625517956";
+        results[16][0]="5.901998011029744E-8";
+        results[16][1]="1.297779184068582E-13";
+        results[16][2]="2.911797383123386E-18";
+        results[16][3]="3.395473341564099E-23";
+        results[16][4]="2.369932499205253E-28";
+        results[16][5]="7.394042360403217E-13";
+        results[16][6]="0.0004595058773843880";
+        results[16][7]="7.090840507594115E-18";
+        results[16][8]="6.773982233816134E-10";
+        results[16][9]="6.609676632793603E-23";
+        results[16][10]="2.412243166437193E-14";
+        results[16][11]="8.009705002679486E-28";
+        results[16][12]="1.075485425556837E-19";
+        results[16][13]="1.007756328470993E-32";
+        results[16][14]="8.103105504195564E-25";
+        results[16][15]="8.704730918982346E-17";
+        results[16][16]="1";
+        results[16][17]="1.030232696254985E-21";
+        results[16][18]="0.000007848123479882456";
+        results[16][19]="6.640327050142802E-27";
+        results[16][20]="2.655866713388787E-10";
+        results[16][21]="1.238091601114291E-31";
+        results[16][22]="1.525794898764651E-15";
+        results[16][23]="1.356958262240303E-36";
+        results[16][24]="8.081949966432234E-21";
+        results[16][25]="8.090569966166392E-21";
+        results[16][26]="21670.37344398340";
+        results[16][27]="9.431815342299341E-26";
+        results[16][28]="0.3342058218579424";
+        results[16][29]="1.610026250138211E-30";
+        results[16][30]="7.532069813813702E-7";
+        results[16][31]="1.964451594366708E-35";
+        results[16][32]="1.531309335246434E-11";
+        results[16][33]="8.452763159697483E-41";
+        results[16][34]="4.051166102474697E-16";
+        results[16][35]="9.944702566836774E-25";
+        results[16][36]="209552852.0527718";
+        results[16][37]="8.414002484413322E-30";
+        results[16][38]="1025.565284080813";
+        results[16][39]="8.967629648693503E-35";
+        results[16][40]="0.01859440193089382";
+        results[16][41]="1.435702214116641E-39";
+        results[16][42]="6.715132040207400E-8";
+        results[16][43]="2.589957496510927E-44";
+        results[16][44]="1.764011781218549E-12";
+        results[16][45]="2.271784521158129E-28";
+        results[16][46]="1236893461414.578";
+        results[16][47]="8.258520338533136E-34";
+        results[16][48]="10242217.01217658";
+        results[16][49]="3.497537734347732E-38";
+        results[16][50]="345.1775071495967";
+        results[16][51]="8.705669316160942E-44";
+        results[16][52]="0.006185176844958069";
+        results[16][53]="1.813395577714413E-48";
+        results[16][54]="2.522384927062784E-8";
+        results[16][55]="9.184299380979178E-33";
+        results[16][56]="1.060185786670131E+16";
+        results[16][57]="9.211960712648993E-38";
+        results[16][58]="84739285168.49519";
+        results[16][59]="1.807527998031550E-42";
+        results[16][60]="4376915.710937338";
+        results[16][61]="8.355644669662702E-48";
+        results[16][62]="31.29240305475972";
+        results[16][63]="7.106785700207527E-53";
+        results[16][64]="0.0003269717880686592";
+        results[16][65]="7.710624224886317E-37";
+        results[16][66]="6.874104961671300E+19";
+        results[16][67]="2.488999412395668E-41";
+        results[16][68]="1466490718750697";
+        results[16][69]="1.105495730231758E-46";
+        results[16][70]="10767397108.90133";
+        results[16][71]="6.756006609601578E-52";
+        results[16][72]="262437.6679414338";
+        results[16][73]="1.280189802700927E-56";
+        results[16][74]="0.7329578964252270";
+        results[17][0]="57288009131181.63";
+        results[17][1]="125969520.1662847";
+        results[17][2]="2826.349225478968";
+        results[17][3]="0.03295831469829135";
+        results[17][4]="2.300385638914618E-7";
+        results[17][5]="717706047.1174538";
+        results[17][6]="4.460214464700500E+17";
+        results[17][7]="6882.756229121966";
+        results[17][8]="657519632063.7410";
+        results[17][9]="0.06415712350055034";
+        results[17][10]="23414546.78351770";
+        results[17][11]="7.774656183788081E-7";
+        results[17][12]="104.3924765216976";
+        results[17][13]="9.781832125249994E-12";
+        results[17][14]="0.0007865315800645127";
+        results[17][15]="84492.86215264814";
+        results[17][16]="9.706544974112313E+20";
+        results[17][17]="1";
+        results[17][18]="7617816351986589";
+        results[17][19]="0.000006445463315502565";
+        results[17][20]="257792896987.5612";
+        results[17][21]="1.201759180828659E-10";
+        results[17][22]="1481019.680613023";
+        results[17][23]="1.317137640042879E-15";
+        results[17][24]="7.844781082769998";
+        results[17][25]="7.853148124279642";
+        results[17][26]="2.103444544398340E+25";
+        results[17][27]="0.00009155033980755107";
+        results[17][28]="3.243983840474286E+20";
+        results[17][29]="1.562779220646795E-9";
+        results[17][30]="731103743959364.5";
+        results[17][31]="1.906803775018709E-14";
+        results[17][32]="14863722931.84754";
+        results[17][33]="8.204712576512332E-20";
+        results[17][34]="393228.2597126994";
+        results[17][35]="0.0009652870271917130";
+        results[17][36]="2.034034182903733E+29";
+        results[17][37]="8.167089352725064E-9";
+        results[17][38]="9.954695553818683E+23";
+        results[17][39]="8.704470049622648E-14";
+        results[17][40]="1.804873986089417E+19";
+        results[17][41]="1.393570811075580E-18";
+        results[17][42]="65180731155375.70";
+        results[17][43]="2.513953892092264E-23";
+        results[17][44]="1712245968.926182";
+        results[17][45]="2.205117862611359E-7";
+        results[17][46]="1.200596201140605E+33";
+        results[17][47]="8.016169908559313E-13";
+        results[17][48]="9.941654006331020E+27";
+        results[17][49]="3.394900731710114E-17";
+        results[17][50]="3.350480997199534E+23";
+        results[17][51]="8.450197074706576E-23";
+        results[17][52]="6.003669721842360E+18";
+        results[17][53]="1.760180573094133E-27";
+        results[17][54]="24483642736557.92";
+        results[17][55]="8.914781499718627E-12";
+        results[17][56]="1.029074101922827E+37";
+        results[17][57]="8.941631095708316E-17";
+        results[17][58]="8.225256825621270E+31";
+        results[17][59]="1.754485180486043E-21";
+        results[17][60]="4.248472919611204E+27";
+        results[17][61]="8.110444077378283E-27";
+        results[17][62]="3.037411175990747E+22";
+        results[17][63]="6.898233502044262E-32";
+        results[17][64]="3.173766366154361E+17";
+        results[17][65]="7.484352081733892E-16";
+        results[17][66]="6.672380896723107E+40";
+        results[17][67]="2.415958473695767E-20";
+        results[17][68]="1.423455811567193E+36";
+        results[17][69]="1.073054402418369E-25";
+        results[17][70]="1.045142242916776E+31";
+        results[17][71]="6.557748200149776E-31";
+        results[17][72]="2.547363026774680E+26";
+        results[17][73]="1.242621989531652E-35";
+        results[17][74]="7.114488785782220E+20";
+        results[18][0]="0.007520266502124582";
+        results[18][1]="1.653617183005917E-8";
+        results[18][2]="3.710182938109170E-13";
+        results[18][3]="4.326477979440449E-18";
+        results[18][4]="3.019744153210938E-23";
+        results[18][5]="9.421414404802356E-8";
+        results[18][6]="58.54977671570353";
+        results[18][7]="9.035077653620603E-13";
+        results[18][8]="0.00008631340028199442";
+        results[18][9]="8.421983483996608E-18";
+        results[18][10]="3.073655979828342E-9";
+        results[18][11]="1.020588555112725E-22";
+        results[18][12]="1.370372711787334E-14";
+        results[18][13]="1.284072977513965E-27";
+        results[18][14]="1.032489553071727E-19";
+        results[18][15]="1.109148058296442E-11";
+        results[18][16]="127418.9941790999";
+        results[18][17]="1.312712139272323E-16";
+        results[18][18]="1";
+        results[18][19]="8.461037937494653E-22";
+        results[18][20]="0.00003384078652937511";
+        results[18][21]="1.577563865155743E-26";
+        results[18][22]="1.944152513241934E-10";
+        results[18][23]="1.729022569176787E-31";
+        results[18][24]="1.029793935728606E-15";
+        results[18][25]="1.030892287424556E-15";
+        results[18][26]="2761217187.717842";
+        results[18][27]="1.201792424198785E-20";
+        results[18][28]="42584.16966993846";
+        results[18][29]="2.051479253945588E-25";
+        results[18][30]="0.09597287597629022";
+        results[18][31]="2.503084462677351E-30";
+        results[18][32]="0.000001951178952741667";
+        results[18][33]="1.077042579842804E-35";
+        results[18][34]="5.161955100297903E-11";
+        results[18][35]="1.267143998476655E-19";
+        results[18][36]="26701013635925.91";
+        results[18][37]="1.072103733584393E-24";
+        results[18][38]="130676496.9625801";
+        results[18][39]="1.142646350007201E-29";
+        results[18][40]="2369.279991396404";
+        results[18][41]="1.829357320634491E-34";
+        results[18][42]="0.008556353703430740";
+        results[18][43]="3.300097791720419E-39";
+        results[18][44]="2.247686068829500E-7";
+        results[18][45]="2.894684986776169E-23";
+        results[18][46]="1.576037207601508E+17";
+        results[18][47]="1.052292354943532E-28";
+        results[18][48]="1305052989855.606";
+        results[18][49]="4.456527402140359E-33";
+        results[18][50]="43982170.77425067";
+        results[18][51]="1.109267627921080E-38";
+        results[18][52]="788.1090124044157";
+        results[18][53]="2.310610405611983E-43";
+        results[18][54]="0.003213997503388622";
+        results[18][55]="1.170254189364097E-27";
+        results[18][56]="1.350878065804859E+21";
+        results[18][57]="1.173778768423119E-32";
+        results[18][58]="1.079739448362558E+16";
+        results[18][59]="2.303133994597421E-37";
+        results[18][60]="557702197494.3356";
+        results[18][61]="1.064667839526379E-42";
+        results[18][62]="3987246.522684476";
+        results[18][63]="9.055394857668533E-48";
+        results[18][64]="41.66241636065038";
+        results[18][65]="9.824799832280163E-32";
+        results[18][66]="8.758915400977171E+24";
+        results[18][67]="3.171458016398266E-36";
+        results[18][68]="1.868587723561991E+20";
+        results[18][69]="1.408611540154202E-41";
+        results[18][70]="1371970909543155";
+        results[18][71]="8.608435668627840E-47";
+        results[18][72]="33439543683.80610";
+        results[18][73]="1.631204970184925E-51";
+        results[18][74]="93392.75793813131";
+        results[19][0]="8.888113441495055E+18";
+        results[19][1]="19543904603925.69";
+        results[19][2]="438502104.0583787";
+        results[19][3]="5113.412812236528";
+        results[19][4]="0.03568999661175253";
+        results[19][5]="111350575123317.2";
+        results[19][6]="6.919928399829436E+22";
+        results[19][7]="1067845070.589050";
+        results[19][8]="1.020127801336300E+17";
+        results[19][9]="9953.842006398556";
+        results[19][10]="3632717407172.463";
+        results[19][11]="0.1206221462014772";
+        results[19][12]="16196271.92208414";
+        results[19][13]="0.000001517630563767670";
+        results[19][14]="122.0287109807536";
+        results[19][15]="13108888844.25527";
+        results[19][16]="1.505949921515530E+26";
+        results[19][17]="155147.8848067927";
+        results[19][18]="1.181888093857317E+21";
+        results[19][19]="1";
+        results[19][20]="3.999602268583552E+16";
+        results[19][21]="0.00001864503949527103";
+        results[19][22]="229777070804.3422";
+        results[19][23]="2.043511188520634E-10";
+        results[19][24]="1217101.191764106";
+        results[19][25]="1218399.320556418";
+        results[19][26]="3.263449718717902E+30";
+        results[19][27]="14.20384157448466";
+        results[19][28]="5.032972311970014E+25";
+        results[19][29]="0.0002424618905033581";
+        results[19][30]="1.134291994496223E+20";
+        results[19][31]="2.958365724357601E-9";
+        results[19][32]="2306075173230364";
+        results[19][33]="1.272943801693578E-14";
+        results[19][34]="61008532740.68144";
+        results[19][35]="149.7622405002312";
+        results[19][36]="3.155761011022271E+34";
+        results[19][37]="0.001267106638103371";
+        results[19][38]="1.544449959070552E+29";
+        results[19][39]="1.350480116563032E-8";
+        results[19][40]="2.800223812845777E+24";
+        results[19][41]="2.162095636668628E-13";
+        results[19][42]="1.011265256891675E+19";
+        results[19][43]="3.900346288599187E-18";
+        results[19][44]="265651340347854.4";
+        results[19][45]="0.03421193721338280";
+        results[19][46]="1.862699611140355E+38";
+        results[19][47]="1.243691805564838E-7";
+        results[19][48]="1.542426590563234E+33";
+        results[19][49]="5.267116676538570E-12";
+        results[19][50]="5.198200398008612E+28";
+        results[19][51]="1.311030202341272E-17";
+        results[19][52]="9.314566584224275E+23";
+        results[19][53]="2.730882927935629E-22";
+        results[19][54]="3.798585382942154E+18";
+        results[19][55]="0.000001383109493196072";
+        results[19][56]="1.596586702227764E+42";
+        results[19][57]="1.387275151221789E-11";
+        results[19][58]="1.276131198487774E+37";
+        results[19][59]="2.722046646772734E-16";
+        results[19][60]="6.591415871366172E+32";
+        results[19][61]="1.258318243449020E-21";
+        results[19][62]="4.712479192434771E+27";
+        results[19][63]="1.070246336745521E-26";
+        results[19][64]="4.924031385797897E+22";
+        results[19][65]="1.161181394630329E-10";
+        results[19][66]="1.035205782751841E+46";
+        results[19][67]="3.748308469749455E-15";
+        results[19][68]="2.208461582805865E+41";
+        results[19][69]="1.664821208178269E-20";
+        results[19][70]="1.621516083107649E+36";
+        results[19][71]="1.017420762348790E-25";
+        results[19][72]="3.952179854391208E+31";
+        results[19][73]="1.927901732902443E-30";
+        results[19][74]="1.103797886595758E+26";
+        results[20][0]="222.2249324966694";
+        results[20][1]="0.0004886462025847162";
+        results[20][2]="1.096364274774934E-8";
+        results[20][3]="1.278480326006873E-13";
+        results[20][4]="8.923386430719285E-19";
+        results[20][5]="0.002784041203245736";
+        results[20][6]="1730154.134120969";
+        results[20][7]="2.669878150077217E-8";
+        results[20][8]="2.550573114105107";
+        results[20][9]="2.488707960935246E-13";
+        results[20][10]="0.00009082696636380747";
+        results[20][11]="3.015853529960997E-18";
+        results[20][12]="4.049470630943514E-10";
+        results[20][13]="3.794453702780639E-23";
+        results[20][14]="3.051021146259370E-15";
+        results[20][15]="3.277548107026588E-7";
+        results[20][16]="3765249193.262553";
+        results[20][17]="3.879082828446787E-12";
+        results[20][18]="29550.14060125232";
+        results[20][19]="2.500248606854969E-17";
+        results[20][20]="1";
+        results[20][21]="4.661723402280728E-22";
+        results[20][22]="0.000005744998011657722";
+        results[20][23]="5.109286002191258E-27";
+        results[20][24]="3.043055559109729E-11";
+        results[20][25]="3.046301203814225E-11";
+        results[20][26]="81594356127656.76";
+        results[20][27]="3.551313510859396E-16";
+        results[20][28]="1258368201.134266";
+        results[20][29]="6.062150039464433E-21";
+        results[20][30]="2836.011979005927";
+        results[20][31]="7.396649780892585E-26";
+        results[20][32]="0.05765761239172050";
+        results[20][33]="3.182675966789038E-31";
+        results[20][34]="0.000001525364989911545";
+        results[20][35]="3.744428331701820E-15";
+        results[20][36]="7.890187071375662E+17";
+        results[20][37]="3.168081606654638E-20";
+        results[20][38]="3861508858523.363";
+        results[20][39]="3.376536030022057E-25";
+        results[20][40]="70012556.86949763";
+        results[20][41]="5.405776603467944E-30";
+        results[20][42]="252.8414549704244";
+        results[20][43]="9.751835374322068E-35";
+        results[20][44]="0.006641943936138782";
+        results[20][45]="8.553834835557002E-19";
+        results[20][46]="4.657212107742966E+21";
+        results[20][47]="3.109538704220428E-24";
+        results[20][48]="3.856449934231786E+16";
+        results[20][49]="1.316910113265814E-28";
+        results[20][50]="1299679330327.398";
+        results[20][51]="3.277901436948555E-34";
+        results[20][52]="23288732.12566459";
+        results[20][53]="6.827886236055077E-39";
+        results[20][54]="94.97407811720772";
+        results[20][55]="3.458117583491362E-23";
+        results[20][56]="3.991863677968137E+25";
+        results[20][57]="3.468532764166796E-28";
+        results[20][58]="3.190645251183220E+20";
+        results[20][59]="6.805793336387770E-33";
+        results[20][60]="1.648017834958501E+16";
+        results[20][61]="3.146108435163604E-38";
+        results[20][62]="117823695357.1807";
+        results[20][63]="2.675881912439624E-43";
+        results[20][64]="1231130.261245134";
+        results[20][65]="2.903242164230390E-27";
+        results[20][66]="2.588271816133498E+29";
+        results[20][67]="9.371703029553756E-32";
+        results[20][68]="5.521702995703085E+24";
+        results[20][69]="4.162466906410325E-37";
+        results[20][70]="4.054193327782826E+19";
+        results[20][71]="2.543804843647882E-42";
+        results[20][72]="988143217498189.4";
+        results[20][73]="4.820233621842614E-47";
+        results[20][74]="2759769128.210504";
+        results[21][0]="4.767012396916274E+23";
+        results[21][1]="1.048209343234839E+18";
+        results[21][2]="23518432565916.35";
+        results[21][3]="274250575.5235032";
+        results[21][4]="1914.181872385126";
+        results[21][5]="5.972128680744241E+18";
+        results[21][6]="3.711404527506926E+27";
+        results[21][7]="57272341571595.42";
+        results[21][8]="5.471309415005725E+21";
+        results[21][9]="533860065.5108917";
+        results[21][10]="1.948355973230217E+17";
+        results[21][11]="6469.396121798011";
+        results[21][12]="868663857010.9776";
+        results[21][13]="0.08139594255901624";
+        results[21][14]="6544835.210014115";
+        results[21][15]="703076485709783.2";
+        results[21][16]="8.076946803451319E+30";
+        results[21][17]="8321134682.827734";
+        results[21][18]="6.338887585392785E+25";
+        results[21][19]="53633.56834152223";
+        results[21][20]="2.145129416109833E+21";
+        results[21][21]="1";
+        results[21][22]="1.232376423029948E+16";
+        results[21][23]="0.00001096007969861868";
+        results[21][24]="65277479947.02833";
+        results[21][25]="65347103226.32689";
+        results[21][26]="1.750304535179781E+35";
+        results[21][27]="761802.7077972777";
+        results[21][28]="2.699362644550329E+30";
+        results[21][29]="13.00409637452654";
+        results[21][30]="6.083612720605475E+24";
+        results[21][31]="0.0001586677102565503";
+        results[21][32]="1.236830404041385E+20";
+        results[21][33]="6.827251838304966E-10";
+        results[21][34]="3272105310163334";
+        results[21][35]="8032283.360848641";
+        results[21][36]="1.692547238541742E+39";
+        results[21][37]="67.95945047071364";
+        results[21][38]="8.283436242987168E+33";
+        results[21][39]="0.0007243106762555027";
+        results[21][40]="1.501859952378219E+29";
+        results[21][41]="1.159609040901739E-8";
+        results[21][42]="5.423776426690670E+23";
+        results[21][43]="2.091894892251871E-13";
+        results[21][44]="1.424782931756363E+19";
+        results[21][45]="1834.908272629834";
+        results[21][46]="9.990322689382312E+42";
+        results[21][47]="0.006670362944955292";
+        results[21][48]="8.272584195675434E+37";
+        results[21][49]="2.824942622339028E-7";
+        results[21][50]="2.787980362995230E+33";
+        results[21][51]="7.031522795507035E-13";
+        results[21][52]="4.995734434666519E+28";
+        results[21][53]="1.464669961481319E-17";
+        results[21][54]="2.037316887371354E+23";
+        results[21][55]="0.07418109752713971";
+        results[21][56]="8.563064200709839E+46";
+        results[21][57]="7.440451663154942E-7";
+        results[21][58]="6.844346984684270E+41";
+        results[21][59]="1.459930748584969E-11";
+        results[21][60]="3.535211536043119E+37";
+        results[21][61]="6.748809750540721E-17";
+        results[21][62]="2.527470748254518E+32";
+        results[21][63]="5.740113004410473E-22";
+        results[21][64]="2.640933738459919E+27";
+        results[21][65]="0.000006227830168580984";
+        results[21][66]="5.552178009675986E+50";
+        results[21][67]="2.010351584774140E-10";
+        results[21][68]="1.184476752310447E+46";
+        results[21][69]="8.929030204524482E-16";
+        results[21][70]="8.696769366023154E+40";
+        results[21][71]="5.456790598951745E-21";
+        results[21][72]="2.119695083184782E+36";
+        results[21][73]="1.034002493473623E-25";
+        results[21][74]="5.920061938596140E+30";
+        results[22][0]="38681463.77870482";
+        results[22][1]="85.05593937424482";
+        results[22][2]="0.001908380599175486";
+        results[22][3]="2.225379927743381E-8";
+        results[22][4]="1.553244476779973E-13";
+        results[22][5]="484.6026400002877";
+        results[22][6]="301158352119.5565";
+        results[22][7]="0.004647309093335652";
+        results[22][8]="443964.1421858626";
+        results[22][9]="4.331956174545530E-8";
+        results[22][10]="15.80974722349805";
+        results[22][11]="5.249529284155089E-13";
+        results[22][12]="0.00007048689351547812";
+        results[22][13]="6.604795502245522E-18";
+        results[22][14]="5.310743606992122E-10";
+        results[22][15]="0.05705046547232572";
+        results[22][16]="655396082926770.0";
+        results[22][17]="6.752104736286019E-7";
+        results[22][18]="5143629387.040573";
+        results[22][19]="4.352044338016266E-12";
+        results[22][20]="174064.4640730606";
+        results[22][21]="8.114403856748394E-17";
+        results[22][22]="1";
+        results[22][23]="8.893451297674116E-22";
+        results[22][24]="0.000005296878350409827";
+        results[22][25]="0.000005302527864470423";
+        results[22][26]="1.420267787074702E+19";
+        results[22][27]="6.181574830231600E-11";
+        results[22][28]="219037186537017.3";
+        results[22][29]="1.055204897749860E-15";
+        results[22][30]="493648905.2304466";
+        results[22][31]="1.287493880047189E-20";
+        results[22][32]="10036.14140069709";
+        results[22][33]="5.539907864773438E-26";
+        results[22][34]="0.2655118394847626";
+        results[22][35]="6.517719108176616E-10";
+        results[22][36]="1.373401184015196E+23";
+        results[22][37]="5.514504270020602E-15";
+        results[22][38]="6.721514699722450E+17";
+        results[22][39]="5.877349344891688E-20";
+        results[22][40]="12186698189873.78";
+        results[22][41]="9.409536073813374E-25";
+        results[22][42]="44010712.35487979";
+        results[22][43]="1.697447998160085E-29";
+        results[22][44]="1156.126411647312";
+        results[22][45]="1.488918676420706E-13";
+        results[22][46]="8.106551296088482E+26";
+        results[22][47]="5.412601880645680E-19";
+        results[22][48]="6.712708910266456E+21";
+        results[22][49]="2.292272530980073E-23";
+        results[22][50]="2.262279861002728E+17";
+        results[22][51]="5.705661569067654E-29";
+        results[22][52]="4053740676394.876";
+        results[22][53]="1.188492358430754E-33";
+        results[22][54]="16531612.00830475";
+        results[22][55]="6.019353838720512E-18";
+        results[22][56]="6.948416117582402E+30";
+        results[22][57]="6.037482967145447E-23";
+        results[22][58]="5.553779556944628E+25";
+        results[22][59]="1.184646769690344E-27";
+        results[22][60]="2.868613412248970E+21";
+        results[22][61]="5.476256786824880E-33";
+        results[22][62]="2.050891838745521E+16";
+        results[22][63]="4.657759510115996E-38";
+        results[22][64]="214296029127.7612";
+        results[22][65]="5.053512913910754E-22";
+        results[22][66]="4.505261465506844E+34";
+        results[22][67]="1.631280465291153E-26";
+        results[22][68]="9.611322727176706E+29";
+        results[22][69]="7.245375712861636E-32";
+        results[22][70]="7.056909888490957E+24";
+        results[22][71]="4.427860268160242E-37";
+        results[22][72]="1.720006195812521E+20";
+        results[22][73]="8.390313820929822E-42";
+        results[22][74]="480377734267339.0";
+        results[23][0]="4.349432237720928E+28";
+        results[23][1]="9.563884315247705E+22";
+        results[23][2]="2.145826783438484E+18";
+        results[23][3]="25022680771022.83";
+        results[23][4]="174650360.6745100";
+        results[23][5]="5.448982895167197E+23";
+        results[23][6]="3.386293375197521E+32";
+        results[23][7]="5.225540611608288E+18";
+        results[23][8]="4.992034333194938E+26";
+        results[23][9]="48709505787460.23";
+        results[23][10]="1.777684128953709E+22";
+        results[23][11]="590269076.4751797";
+        results[23][12]="7.925707484777299E+16";
+        results[23][13]="7426.583090383436";
+        results[23][14]="597152154909.8750";
+        results[23][15]="6.414884791379698E+19";
+        results[23][16]="7.369423421683034E+35";
+        results[23][17]="759222096156514.8";
+        results[23][18]="5.783614498890633E+30";
+        results[23][19]="4893538169.095777";
+        results[23][20]="1.957220636251567E+26";
+        results[23][21]="91240.21243440706";
+        results[23][22]="1.124422866364071E+21";
+        results[23][23]="1";
+        results[23][24]="5955931137549612";
+        results[23][25]="5962283580343192";
+        results[23][26]="1.596981576147093E+40";
+        results[23][27]="69507040892.53014";
+        results[23][28]="2.462904211262749E+35";
+        results[23][29]="1186496.515729304";
+        results[23][30]="5.550701169967046E+29";
+        results[23][31]="14.47687559028860";
+        results[23][32]="1.128486688100694E+25";
+        results[23][33]="0.00006229199080701412";
+        results[23][34]="2.985475836070540E+20";
+        results[23][35]="732867240177.1831";
+        results[23][36]="1.544283695998176E+44";
+        results[23][37]="6200634.697873477";
+        results[23][38]="7.557824824970159E+38";
+        results[23][39]="66.08625997006110";
+        results[23][40]="1.370300211017172E+34";
+        results[23][41]="0.001058029752327336";
+        results[23][42]="4.948665133679859E+28";
+        results[23][43]="1.908649343595118E-8";
+        results[23][44]="1.299974973663679E+24";
+        results[23][45]="167417420.5923969";
+        results[23][46]="9.115191644675190E+47";
+        results[23][47]="608.6053321123179";
+        results[23][48]="7.547923393949451E+42";
+        results[23][49]="0.02577483649772239";
+        results[23][50]="2.543759205826400E+38";
+        results[23][51]="6.415576335994377E-8";
+        results[23][52]="4.558118710848557E+33";
+        results[23][53]="1.336367984318503E-12";
+        results[23][54]="1.858852255999673E+28";
+        results[23][55]="6768.299096993695";
+        results[23][56]="7.812957967622318E+51";
+        results[23][57]="0.06788683903541942";
+        results[23][58]="6.244796728573862E+46";
+        results[23][59]="0.000001332043916404155";
+        results[23][60]="3.225534515491407E+42";
+        results[23][61]="6.157628353187331E-12";
+        results[23][62]="2.306069679924920E+37";
+        results[23][63]="5.237291299199141E-17";
+        results[23][64]="2.409593553222759E+32";
+        results[23][65]="0.5682285475867381";
+        results[23][66]="5.065819010764803E+55";
+        results[23][67]="0.00001834249056626394";
+        results[23][68]="1.080719105044218E+51";
+        results[23][69]="8.146866126940509E-11";
+        results[23][70]="7.934950844489962E+45";
+        results[23][71]="4.978787334584325E-16";
+        results[23][72]="1.934014296859477E+41";
+        results[23][73]="9.434260716223996E-21";
+        results[23][74]="5.401477089023595E+35";
+        results[24][0]="7302690607518.291";
+        results[24][1]="16057748.30899485";
+        results[24][2]="360.2840150232697";
+        results[24][3]="0.004201304580784266";
+        results[24][4]="2.932377098408908E-8";
+        results[24][5]="91488346.14311905";
+        results[24][6]="5.685581812469896E+16";
+        results[24][7]="877.3675334597941";
+        results[24][8]="83816186216.83326";
+        results[24][9]="0.008178319168327438";
+        results[24][10]="2984729.151326427";
+        results[24][11]="9.910609488981233E-8";
+        results[24][12]="13.30725171553627";
+        results[24][13]="1.246922255961287E-12";
+        results[24][14]="0.0001002617627905542";
+        results[24][15]="10770.58253903672";
+        results[24][16]="1.237325155628808E+20";
+        results[24][17]="0.1274732831227585";
+        results[24][18]="971068060613965.9";
+        results[24][19]="8.216243700744122E-7";
+        results[24][20]="32861706944.73151";
+        results[24][21]="1.531921883031460E-11";
+        results[24][22]="188790.4410571613";
+        results[24][23]="1.678998593008280E-16";
+        results[24][24]="1";
+        results[24][25]="1.001066574251259";
+        results[24][26]="2.681329819411114E+24";
+        results[24][27]="0.00001167022238627271";
+        results[24][28]="4.135212705424321E+19";
+        results[24][29]="1.992125980518727E-10";
+        results[24][30]="93196194545840.82";
+        results[24][31]="2.430665374725046E-15";
+        results[24][32]="1894727561.549639";
+        results[24][33]="1.045881649206614E-20";
+        results[24][34]="50126.09728222654";
+        results[24][35]="0.0001230483065119351";
+        results[24][36]="2.592850152786563E+28";
+        results[24][37]="1.041085693348789E-9";
+        results[24][38]="1.268957724732794E+23";
+        results[24][39]="1.109587375069120E-14";
+        results[24][40]="2.300732126296780E+18";
+        results[24][41]="1.776430465518496E-19";
+        results[24][42]="8308801796717.613";
+        results[24][43]="3.204619562442379E-24";
+        results[24][44]="218265615.1727291";
+        results[24][45]="2.810936136197098E-8";
+        results[24][46]="1.530439394641047E+32";
+        results[24][47]="1.021847496313918E-13";
+        results[24][48]="1.267295275857541E+27";
+        results[24][49]="4.327591421469434E-18";
+        results[24][50]="4.270968127534385E+22";
+        results[24][51]="1.077174364147177E-23";
+        results[24][52]="7.653074902279439E+17";
+        results[24][53]="2.243759965412078E-28";
+        results[24][54]="3121010322433.718";
+        results[24][55]="1.136396466091162E-12";
+        results[24][56]="1.311794543487070E+36";
+        results[24][57]="1.139819072242488E-17";
+        results[24][58]="1.048500492089822E+31";
+        results[24][59]="2.236499861467814E-22";
+        results[24][60]="5.415667913209714E+26";
+        results[24][61]="1.033864934126942E-27";
+        results[24][62]="3.871887747972994E+21";
+        results[24][63]="8.793404722529862E-33";
+        results[24][64]="4.045704185582832E+16";
+        results[24][65]="9.540549319052715E-17";
+        results[24][66]="8.505502991508699E+39";
+        results[24][67]="3.079701585302480E-21";
+        results[24][68]="1.814525856806408E+35";
+        results[24][69]="1.367857676455993E-26";
+        results[24][70]="1.332277130348850E+30";
+        results[24][71]="8.359376929654525E-32";
+        results[24][72]="3.247207283284959E+25";
+        results[24][73]="1.584011046861337E-36";
+        results[24][74]="9.069072432637074E+19";
+        results[25][0]="7294910044299.792";
+        results[25][1]="16040639.77563644";
+        results[25][2]="359.9001547851519";
+        results[25][3]="0.004196828351727361";
+        results[25][4]="2.929252832762058E-8";
+        results[25][5]="91390870.99331748";
+        results[25][6]="5.679524178222003E+16";
+        results[25][7]="876.4327528526417";
+        results[25][8]="83726885276.85887";
+        results[25][9]="0.008169605677269126";
+        results[25][10]="2981549.107819164";
+        results[25][11]="9.900050350191554E-8";
+        results[25][12]="13.29307366544463";
+        results[25][13]="1.245593737753071E-12";
+        results[25][14]="0.0001001549401102962";
+        results[25][15]="10759.10715238146";
+        results[25][16]="1.236006862534849E+20";
+        results[25][17]="0.1273374682578942";
+        results[25][18]="970033447915559.5";
+        results[25][19]="8.207489803452292E-7";
+        results[25][20]="32826694837.26416";
+        results[25][21]="1.530289715424023E-11";
+        results[25][22]="188589.2965693774";
+        results[25][23]="1.677209724302378E-16";
+        results[25][24]="0.9989345621173533";
+        results[25][25]="1";
+        results[25][26]="2.678473029045643E+24";
+        results[25][27]="0.00001165778848924346";
+        results[25][28]="4.130806893155160E+19";
+        results[25][29]="1.990003494032078E-10";
+        results[25][30]="93096899789653.17";
+        results[25][31]="2.428075651754777E-15";
+        results[25][32]="1892708847.028269";
+        results[25][33]="1.044767327276784E-20";
+        results[25][34]="50072.69103927282";
+        results[25][35]="0.0001229172061847818";
+        results[25][36]="2.590087632009758E+28";
+        results[25][37]="1.039976481212013E-9";
+        results[25][38]="1.267605729101387E+23";
+        results[25][39]="1.108405178645614E-14";
+        results[25][40]="2.298280839131601E+18";
+        results[25][41]="1.774537789204645E-19";
+        results[25][42]="8299949284523.987";
+        results[25][43]="3.201205239361082E-24";
+        results[25][44]="218033066.7178449";
+        results[25][45]="2.807941258351893E-8";
+        results[25][46]="1.528808806532901E+32";
+        results[25][47]="1.020758781281058E-13";
+        results[25][48]="1.265945051462143E+27";
+        results[25][49]="4.322980641628383E-18";
+        results[25][50]="4.266417676295733E+22";
+        results[25][51]="1.076026701773399E-23";
+        results[25][52]="7.644921026359818E+17";
+        results[25][53]="2.241369378545362E-28";
+        results[25][54]="3117685079804.065";
+        results[25][55]="1.135185706246483E-12";
+        results[25][56]="1.310396907886189E+36";
+        results[25][57]="1.138604665823557E-17";
+        results[25][58]="1.047383379945576E+31";
+        results[25][59]="2.234117009790872E-22";
+        results[25][60]="5.409897855455146E+26";
+        results[25][61]="1.032763415260583E-27";
+        results[25][62]="3.867762492088947E+21";
+        results[25][63]="8.784035896021034E-33";
+        results[25][64]="4.041393739081530E+16";
+        results[25][65]="9.530384456386937E-17";
+        results[25][66]="8.496440906410580E+39";
+        results[25][67]="3.076420354566251E-21";
+        results[25][68]="1.812592592219525E+35";
+        results[25][69]="1.366400309069427E-26";
+        results[25][70]="1.330857671823993E+30";
+        results[25][71]="8.350470532798348E-32";
+        results[25][72]="3.243747585632540E+25";
+        results[25][73]="1.582323381485480E-36";
+        results[25][74]="9.059409899306875E+19";
+        results[26][0]="2.723533134436308E-12";
+        results[26][1]="5.988725516997952E-18";
+        results[26][2]="1.343676605597132E-22";
+        results[26][3]="1.566873478364917E-27";
+        results[26][4]="1.093627899552070E-32";
+        results[26][5]="3.412051194925813E-17";
+        results[26][6]="2.120433589075808E-8";
+        results[26][7]="3.272135815251872E-22";
+        results[26][8]="3.125918550193178E-14";
+        results[26][9]="3.050098167380094E-27";
+        results[26][10]="1.113152559494507E-18";
+        results[26][11]="3.696154578685082E-32";
+        results[26][12]="4.962929819077190E-24";
+        results[26][13]="4.650387456755103E-37";
+        results[26][14]="3.739255128732137E-29";
+        results[26][15]="4.016880900314683E-21";
+        results[26][16]="0.00004614595141080237";
+        results[26][17]="4.754106794320244E-26";
+        results[26][18]="3.621591247686330E-10";
+        results[26][19]="3.064242094077263E-31";
+        results[26][20]="1.225574963096063E-14";
+        results[26][21]="5.713291486714258E-36";
+        results[26][22]="7.040925726124371E-20";
+        results[26][23]="6.261813003582785E-41";
+        results[26][24]="3.729492704555177E-25";
+        results[26][25]="3.733470485444113E-25";
+        results[26][26]="1";
+        results[26][27]="4.352400925014057E-30";
+        results[26][28]="0.00001542224561666388";
+        results[26][29]="7.429619310899423E-35";
+        results[26][30]="3.475745276510183E-11";
+        results[26][31]="9.065148782251936E-40";
+        results[26][32]="7.066372617918999E-16";
+        results[26][33]="3.900607980544203E-45";
+        results[26][34]="1.869449141218870E-20";
+        results[26][35]="4.589077614441313E-29";
+        results[26][36]="9670.015728822264";
+        results[26][37]="3.882721498161075E-34";
+        results[26][38]="0.04732568576779893";
+        results[26][39]="4.138198020386811E-39";
+        results[26][40]="8.580563680159561E-7";
+        results[26][41]="6.625184461300789E-44";
+        results[26][42]="3.098761568445328E-12";
+        results[26][43]="1.195160527900366E-48";
+        results[26][44]="8.140200194419411E-17";
+        results[26][45]="1.048336581291759E-32";
+        results[26][46]="57077625.57077626";
+        results[26][47]="3.810972782670732E-38";
+        results[26][48]="472.6368485827938";
+        results[26][49]="1.613972063466582E-42";
+        results[26][50]="0.01592854447302717";
+        results[26][51]="4.017313932620759E-48";
+        results[26][52]="2.854208701546549E-7";
+        results[26][53]="8.368086421777320E-53";
+        results[26][54]="1.163978522835795E-12";
+        results[26][55]="4.238182329769274E-37";
+        results[26][56]="489232817981.0316";
+        results[26][57]="4.250946914441208E-42";
+        results[26][58]="3910374.935971505";
+        results[26][59]="8.341009917082876E-47";
+        results[26][60]="201.9769397260919";
+        results[26][61]="3.855791729321848E-52";
+        results[26][62]="0.001444017710892185";
+        results[26][63]="3.279493876087616E-57";
+        results[26][64]="1.508842424491952E-8";
+        results[26][65]="3.558140908285596E-41";
+        results[26][66]="3172121135540393";
+        results[26][67]="1.148572459459261E-45";
+        results[26][68]="67672609451.86232";
+        results[26][69]="5.101415225212420E-51";
+        results[26][70]="496871.7838081744";
+        results[26][71]="3.117623527377340E-56";
+        results[26][72]="12.11043587318969";
+        results[26][73]="5.907557643204166E-61";
+        results[26][74]="0.00003382303947460244";
+        results[27][0]="6.257541943766386E+17";
+        results[27][1]="1375959067231.062";
+        results[27][2]="30872077.93461244";
+        results[27][3]="360.0021012218345";
+        results[27][4]="0.002512700273696726";
+        results[27][5]="7839468959112.017";
+        results[27][6]="4.871871010065461E+21";
+        results[27][7]="75180018.37666884";
+        results[27][8]="7182055614931850";
+        results[27][9]="700.7852033691596";
+        results[27][10]="255755978980.9374";
+        results[27][11]="0.008492219908884301";
+        results[27][12]="1140274.047492801";
+        results[27][13]="1.068464862698761E-7";
+        results[27][14]="8.591246976449121";
+        results[27][15]="922911507.8137501";
+        results[27][16]="1.060241283048926E+25";
+        results[27][17]="10922.95235716340";
+        results[27][18]="8.320904507836979E+19";
+        results[27][19]="0.07040348871507895";
+        results[27][20]="2815859531810263";
+        results[27][21]="0.000001312675827697515";
+        results[27][22]="16177107411.35740";
+        results[27][23]="1.438703169001500E-11";
+        results[27][24]="85688.17001947338";
+        results[27][25]="85779.56281525363";
+        results[27][26]="2.297582454439834E+29";
+        results[27][27]="1";
+        results[27][28]="3.543388093690857E+24";
+        results[27][29]="0.00001707016297188988";
+        results[27][30]="7.985811363411926E+18";
+        results[27][31]="2.082792678898868E-10";
+        results[27][32]="162355737434647.7";
+        results[27][33]="8.961968457746355E-16";
+        results[27][34]="4295213546.332090";
+        results[27][35]="10.54378420900297";
+        results[27][36]="2.221765847269926E+33";
+        results[27][37]="0.00008920872789651233";
+        results[27][38]="1.087346652644278E+28";
+        results[27][39]="9.507851164638391E-10";
+        results[27][40]="1.971455256073830E+23";
+        results[27][41]="1.522190757571212E-14";
+        results[27][42]="7.119660210152448E+17";
+        results[27][43]="2.745979859142930E-19";
+        results[27][44]="18702781142325.76";
+        results[27][45]="0.002408639735523385";
+        results[27][46]="1.311405510525019E+37";
+        results[27][47]="8.756024199812025E-9";
+        results[27][48]="1.085922130625564E+32";
+        results[27][49]="3.708233894976874E-13";
+        results[27][50]="3.659714430599182E+27";
+        results[27][51]="9.230110005566145E-19";
+        results[27][52]="6.557779833982852E+22";
+        results[27][53]="1.922636853991178E-23";
+        results[27][54]="2.674336631412318E+17";
+        results[27][55]="9.737573359594823E-8";
+        results[27][56]="1.124052738729375E+41";
+        results[27][57]="9.766901045375269E-13";
+        results[27][58]="8.984408843169418E+35";
+        results[27][59]="1.916415803779827E-17";
+        results[27][60]="4.640586729161206E+31";
+        results[27][61]="8.858999425264104E-23";
+        results[27][62]="3.317749756446258E+26";
+        results[27][63]="7.534907589141790E-28";
+        results[27][64]="3.466689881027168E+21";
+        results[27][65]="8.175122121301600E-12";
+        results[27][66]="7.288209864375369E+44";
+        results[27][67]="2.638939930506406E-16";
+        results[27][68]="1.554834001227581E+40";
+        results[27][69]="1.172092211426029E-21";
+        results[27][70]="1.141603892583884E+35";
+        results[27][71]="7.162997116051003E-27";
+        results[27][72]="2.782472497785938E+30";
+        results[27][73]="1.357310078961783E-31";
+        results[27][74]="7.771122205267246E+24";
+        results[28][0]="1.765977019256848E-7";
+        results[28][1]="3.883173479306462E-13";
+        results[28][2]="8.712587252178613E-18";
+        results[28][3]="1.015982702721253E-22";
+        results[28][4]="7.091236430383361E-28";
+        results[28][5]="2.212421770302413E-12";
+        results[28][6]="0.001374918829450271";
+        results[28][7]="2.121698679027844E-17";
+        results[28][8]="2.026889357030855E-9";
+        results[28][9]="1.977726359178481E-22";
+        results[28][10]="7.217837059291388E-14";
+        results[28][11]="2.396638382345144E-27";
+        results[28][12]="3.218033185591791E-19";
+        results[28][13]="3.015376341646586E-32";
+        results[28][14]="2.424585382489199E-24";
+        results[28][15]="2.604601820097072E-16";
+        results[28][16]="2.992168102999295";
+        results[28][17]="3.082629412401127E-21";
+        results[28][18]="0.00002348290474490412";
+        results[28][19]="1.986897479292069E-26";
+        results[28][20]="7.946799665619501E-10";
+        results[28][21]="3.704578197445509E-31";
+        results[28][22]="4.565434827802628E-15";
+        results[28][23]="4.060247229376789E-36";
+        results[28][24]="2.418255289959476E-20";
+        results[28][25]="2.420834538784717E-20";
+        results[28][26]="64841.40019917012";
+        results[28][27]="2.822157702060747E-25";
+        results[28][28]="1";
+        results[28][29]="4.817469190655120E-30";
+        results[28][30]="0.000002253721904645720";
+        results[28][31]="5.877969400550175E-35";
+        results[28][32]="4.581934948749433E-11";
+        results[28][33]="2.529208830865435E-40";
+        results[28][34]="1.212176999177676E-15";
+        results[28][35]="2.975622181430421E-24";
+        results[28][36]="627017359.8048342";
+        results[28][37]="2.517610985241837E-29";
+        results[28][38]="3068.663730570020";
+        results[28][39]="2.683265539433148E-34";
+        results[28][40]="0.05563757635196901";
+        results[28][41]="4.295862370485278E-39";
+        results[28][42]="2.009280389813716E-7";
+        results[28][43]="7.749588209183903E-44";
+        results[28][44]="5.278219785077115E-12";
+        results[28][45]="6.797561181096882E-28";
+        results[28][46]="3700993162053.089";
+        results[28][47]="2.471088113492979E-33";
+        results[28][48]="30646435.04783151";
+        results[28][49]="1.046522084775171E-37";
+        results[28][50]="1032.829126765834";
+        results[28][51]="2.604882604307646E-43";
+        results[28][52]="0.01850708886689335";
+        results[28][53]="5.425984405757048E-48";
+        results[28][54]="7.547399722243467E-8";
+        results[28][55]="2.748096765616207E-32";
+        results[28][56]="3.172254094127582E+16";
+        results[28][57]="2.756373501047097E-37";
+        results[28][58]="253554186152.1326";
+        results[28][59]="5.408427620988176E-42";
+        results[28][60]="13096467.57978319";
+        results[28][61]="2.500149346056082E-47";
+        results[28][62]="93.63213028664973";
+        results[28][63]="2.126469748701247E-52";
+        results[28][64]="0.0009783545548396877";
+        results[28][65]="2.307148385991850E-36";
+        results[28][66]="2.056847760298206E+20";
+        results[28][67]="7.447504650154305E-41";
+        results[28][68]="4387986751990347";
+        results[28][69]="3.307829062001381E-46";
+        results[28][70]="32217862181.58138";
+        results[28][71]="2.021510748090225E-51";
+        results[28][72]="785257.6190398789";
+        results[28][73]="3.830543093426676E-56";
+        results[28][74]="2.193133238525025";
+        results[29][0]="3.665777505505325E+22";
+        results[29][1]="8.060608850055552E+16";
+        results[29][2]="1808540315956.603";
+        results[29][3]="21089552.67824123";
+        results[29][4]="147.1983763619884";
+        results[29][5]="4.592498016581085E+17";
+        results[29][6]="2.854027239276019E+26";
+        results[29][7]="4404176954869.778";
+        results[29][8]="4.207373782405491E+20";
+        results[29][9]="41053222.77960500";
+        results[29][10]="1.498263252683064E+16";
+        results[29][11]="497.4890938574387";
+        results[29][12]="66799247867.20172";
+        results[29][13]="0.006259254023867518";
+        results[29][14]="503290.2726585955";
+        results[29][15]="54065770158934.34";
+        results[29][16]="6.211078856100365E+29";
+        results[29][17]="639885651.6572606";
+        results[29][18]="4.874531380596274E+24";
+        results[29][19]="4124.359493873326";
+        results[29][20]="1.649579758814986E+20";
+        results[29][21]="0.07689884565596421";
+        results[29][22]="947683243446292.2";
+        results[29][23]="8.428174771211442E-7";
+        results[29][24]="5019762855.256830";
+        results[29][25]="5025116805.065672";
+        results[29][26]="1.345963983017241E+34";
+        results[29][27]="58581.74884719846";
+        results[29][28]="2.075778713727511E+29";
+        results[29][29]="1";
+        results[29][30]="4.678227956325009E+23";
+        results[29][31]="0.00001220136376160371";
+        results[29][32]="9.511083034298228E+18";
+        results[29][33]="5.250077853682115E-11";
+        results[29][34]="251621121216311.1";
+        results[29][35]="617673.3184308691";
+        results[29][36]="1.301549288620499E+38";
+        results[29][37]="5.226003292611552";
+        results[29][38]="6.369866851504902E+32";
+        results[29][39]="0.00005569865490033896";
+        results[29][40]="1.154912966748064E+28";
+        results[29][41]="8.917259665756348E-10";
+        results[29][42]="4.170821463085429E+22";
+        results[29][43]="1.608643024477765E-14";
+        results[29][44]="1.095641627623847E+18";
+        results[29][45]="141.1023280498135";
+        results[29][46]="7.682442825440876E+41";
+        results[29][47]="0.0005129432105733799";
+        results[29][48]="6.361521752392140E+36";
+        results[29][49]="2.172348267022037E-8";
+        results[29][50]="2.143924716258292E+32";
+        results[29][51]="5.407159861780895E-14";
+        results[29][52]="3.841662112296063E+27";
+        results[29][53]="1.126314293048790E-18";
+        results[29][54]="1.566673168742592E+22";
+        results[29][55]="0.005704440769329544";
+        results[29][56]="6.584897523124984E+45";
+        results[29][57]="5.721621440556141E-8";
+        results[29][58]="5.263223823910997E+40";
+        results[29][59]="1.122669893038318E-12";
+        results[29][60]="2.718536862713640E+36";
+        results[29][61]="5.189756793682972E-18";
+        results[29][62]="1.943595829699885E+31";
+        results[29][63]="4.414080639739539E-23";
+        results[29][64]="2.030847559414579E+26";
+        results[29][65]="4.789129509052666E-7";
+        results[29][66]="4.269560798205122E+49";
+        results[29][67]="1.545937162317696E-11";
+        results[29][68]="9.108489495899883E+44";
+        results[29][69]="6.866321155551707E-17";
+        results[29][70]="6.687715251833322E+39";
+        results[29][71]="4.196208980457067E-22";
+        results[29][72]="1.630021050395328E+35";
+        results[29][73]="7.951359815351027E-27";
+        results[29][74]="4.552459292898528E+29";
+        results[30][0]="0.07835824888672127";
+        results[30][1]="1.723004720015306E-7";
+        results[30][2]="3.865866163087327E-12";
+        results[30][3]="4.508021600300163E-17";
+        results[30][4]="3.146455831913338E-22";
+        results[30][5]="9.816746980813501E-7";
+        results[30][6]="610.0658766354783";
+        results[30][7]="9.414199128358610E-12";
+        results[30][8]="0.0008993520242460782";
+        results[30][9]="8.775378874836710E-17";
+        results[30][10]="3.202629856156106E-8";
+        results[30][11]="1.063413537138199E-21";
+        results[30][12]="1.427875009316049E-13";
+        results[30][13]="1.337954046340334E-26";
+        results[30][14]="1.075813913638266E-18";
+        results[30][15]="1.155689091332903E-10";
+        results[30][16]="1327656.307919525";
+        results[30][17]="1.367794937807870E-15";
+        results[30][18]="10.41961064339727";
+        results[30][19]="8.816072094770739E-21";
+        results[30][20]="0.0003526078195024119";
+        results[30][21]="1.643760124001572E-25";
+        results[30][22]="2.025731221936322E-9";
+        results[30][23]="1.801574196446855E-30";
+        results[30][24]="1.073005185322375E-14";
+        results[30][25]="1.074149625024506E-14";
+        results[30][26]="28770807997.87632";
+        results[30][27]="1.252220913433587E-19";
+        results[30][28]="443710.4675331262";
+        results[30][29]="2.137561506912014E-24";
+        results[30][30]="1";
+        results[30][31]="2.608116550863527E-29";
+        results[30][32]="0.00002033052498315981";
+        results[30][33]="1.122236432832213E-34";
+        results[30][34]="5.378556230380286E-10";
+        results[30][35]="1.320314709324433E-18";
+        results[30][36]="278214165870389.4";
+        results[30][37]="1.117090347328190E-23";
+        results[30][38]="1361598218.593171";
+        results[30][39]="1.190593007017408E-28";
+        results[30][40]="24686.97501554217";
+        results[30][41]="1.906119100865986E-33";
+        results[30][42]="0.08915387411693861";
+        results[30][43]="3.438573407486192E-38";
+        results[30][44]="0.000002342001368579163";
+        results[30][45]="3.016149049749527E-22";
+        results[30][46]="1.642169406271479E+18";
+        results[30][47]="1.096447662153521E-27";
+        results[30][48]="13598144023296.90";
+        results[30][49]="4.643528035193328E-32";
+        results[30][50]="458277094.7190988";
+        results[30][51]="1.155813678226253E-37";
+        results[30][52]="8211.789053806363";
+        results[30][53]="2.407566077505911E-42";
+        results[30][54]="0.03348860259416035";
+        results[30][55]="1.219359300697839E-26";
+        results[30][56]="1.407562347239223E+22";
+        results[30][57]="1.223031774845527E-31";
+        results[30][58]="1.125046464825440E+17";
+        results[30][59]="2.399775948327737E-36";
+        results[30][60]="5811039752858.027";
+        results[30][61]="1.109342435241184E-41";
+        results[30][62]="41545556.30561193";
+        results[30][63]="9.435368863912798E-47";
+        results[30][64]="434.1061569410814";
+        results[30][65]="1.023705889016741E-30";
+        results[30][66]="9.126448813663803E+25";
+        results[30][67]="3.304535770275098E-35";
+        results[30][68]="1.946995653254801E+21";
+        results[30][69]="1.467718379620295E-40";
+        results[30][70]="1.429540269150730E+16";
+        results[30][71]="8.969654791583536E-46";
+        results[30][72]="348427025278.1341";
+        results[30][73]="1.699652066890138E-50";
+        results[30][74]="973116.1746283781";
+        results[31][0]="3.004399817208225E+27";
+        results[31][1]="6.606317955556214E+21";
+        results[31][2]="1.482244404226248E+17";
+        results[31][3]="1728458645303.865";
+        results[31][4]="12064092.11609646";
+        results[31][5]="3.763921891283291E+22";
+        results[31][6]="2.339105115657083E+31";
+        results[31][7]="3.609577618470172E+17";
+        results[31][8]="3.448281572954666E+25";
+        results[31][9]="3364642148346.955";
+        results[31][10]="1.227947368799811E+21";
+        results[31][11]="40773236.79365905";
+        results[31][12]="5474736199359228";
+        results[31][13]="512.9962638737704";
+        results[31][14]="41248690104.82190";
+        results[31][15]="4.431125177094802E+18";
+        results[31][16]="5.090479209910875E+34";
+        results[31][17]="52443781216564.26";
+        results[31][18]="3.995070941115503E+29";
+        results[31][19]="338024467.9576074";
+        results[31][20]="1.351963428879995E+25";
+        results[31][21]="6302.479555437567";
+        results[31][22]="7.767027210749525E+19";
+        results[31][23]="0.06907567822651053";
+        results[31][24]="411409982796631.8";
+        results[31][25]="411848782090993.5";
+        results[31][26]="1.103125854876022E+39";
+        results[31][27]="4801245991.169322";
+        results[31][28]="1.701267787999033E+34";
+        results[31][29]="81958.05153739330";
+        results[31][30]="3.834184479481592E+28";
+        results[31][31]="1";
+        results[31][32]="7.795098335014412E+23";
+        results[31][33]="0.000004302861513074059";
+        results[31][34]="2.062237682054311E+19";
+        results[31][35]="50623301665.22991";
+        results[31][36]="1.066724436752164E+43";
+        results[31][37]="428313.0471904447";
+        results[31][38]="5.220618757019720E+37";
+        results[31][39]="4.564953228885464";
+        results[31][40]="9.465441644994164E+32";
+        results[31][41]="0.00007308412272583773";
+        results[31][42]="3.418324004248217E+27";
+        results[31][43]="1.318412479054169E-9";
+        results[31][44]="8.979665298330876E+22";
+        results[31][45]="11564471.87435279";
+        results[31][46]="6.296380450205607E+46";
+        results[31][47]="42.03982608792905";
+        results[31][48]="5.213779276388035E+41";
+        results[31][49]="0.001780414312257591";
+        results[31][50]="1.757118923873884E+37";
+        results[31][51]="4.431602866227630E-9";
+        results[31][52]="3.148551413888119E+32";
+        results[31][53]="9.231052487699542E-14";
+        results[31][54]="1.284014803060566E+27";
+        results[31][55]="467.5248505647183";
+        results[31][56]="5.396853705687309E+50";
+        results[31][57]="0.004689329449025547";
+        results[31][58]="4.313635694129337E+45";
+        results[31][59]="9.201183695311428E-8";
+        results[31][60]="2.228059843005880E+41";
+        results[31][61]="4.253423547632060E-13";
+        results[31][62]="1.592933271784059E+36";
+        results[31][63]="3.617694485619832E-18";
+        results[31][64]="1.664443089390894E+31";
+        results[31][65]="0.03925077231221895";
+        results[31][66]="3.499248839413294E+54";
+        results[31][67]="0.000001267019976228053";
+        results[31][68]="7.465140515327681E+49";
+        results[31][69]="5.627503031390007E-12";
+        results[31][70]="5.481121112771666E+44";
+        results[31][71]="3.439131118819729E-17";
+        results[31][72]="1.335933492553362E+40";
+        results[31][73]="6.516779575388975E-22";
+        results[31][74]="3.731106933492626E+34";
+        results[32][0]="3854.216698861785";
+        results[32][1]="0.008474964229612891";
+        results[32][2]="1.901508281900985E-7";
+        results[32][3]="2.217366056230347E-12";
+        results[32][4]="1.547651049109460E-17";
+        results[32][5]="0.04828575252702482";
+        results[32][6]="30007384.32189076";
+        results[32][7]="4.630573551915940E-7";
+        results[32][8]="44.23653717702960";
+        results[32][9]="4.316356258436777E-12";
+        results[32][10]="0.001575281434595963";
+        results[32][11]="5.230625072490977E-17";
+        results[32][12]="7.023306139407549E-9";
+        results[32][13]="6.581010807387358E-22";
+        results[32][14]="5.291618954893612E-14";
+        results[32][15]="0.000005684501960919277";
+        results[32][16]="65303591964.26306";
+        results[32][17]="6.727789562447809E-11";
+        results[32][18]="512510.6534153962";
+        results[32][19]="4.336372081917841E-16";
+        results[32][20]="17.34376361626097";
+        results[32][21]="8.085182873354881E-21";
+        results[32][22]="0.00009963988749008084";
+        results[32][23]="8.861424866987624E-26";
+        results[32][24]="5.277803628834801E-10";
+        results[32][25]="5.283432798288516E-10";
+        results[32][26]="1415153225099094";
+        results[32][27]="6.159314205957922E-15";
+        results[32][28]="21824840622.69226";
+        results[32][29]="1.051404972907783E-19";
+        results[32][30]="49187.12137676328";
+        results[32][31]="1.282857453520695E-24";
+        results[32][32]="1";
+        results[32][33]="5.519957963514394E-30";
+        results[32][34]="0.00002645556981354615";
+        results[32][35]="6.494247986306681E-14";
+        results[32][36]="1.368455394540179E+19";
+        results[32][37]="5.494645850284232E-19";
+        results[32][38]="66973096844326.95";
+        results[32][39]="5.856184274649082E-24";
+        results[32][40]="1214281236.514595";
+        results[32][41]="9.375651157286216E-29";
+        results[32][42]="4385.222427398534";
+        results[32][43]="1.691335275569338E-33";
+        results[32][44]="0.1151963055808490";
+        results[32][45]="1.483556894004392E-17";
+        results[32][46]="8.077358590748254E+22";
+        results[32][47]="5.393110424161355E-23";
+        results[32][48]="6.688535605726128E+17";
+        results[32][49]="2.284017770834574E-27";
+        results[32][50]="22541331082138.75";
+        results[32][51]="5.685114767983791E-33";
+        results[32][52]="403914264.9099497";
+        results[32][53]="1.184212448768611E-37";
+        results[32][54]="1647.207960537155";
+        results[32][55]="5.997677392530980E-22";
+        results[32][56]="6.923394001901749E+26";
+        results[32][57]="6.015741235696518E-27";
+        results[32][58]="5.533779701986738E+21";
+        results[32][59]="1.180380708474336E-31";
+        results[32][60]="2.858283176490243E+17";
+        results[32][61]="5.456536101060227E-37";
+        results[32][62]="2043506320669.287";
+        results[32][63]="4.640986335438119E-42";
+        results[32][64]="21352432.23186122";
+        results[32][65]="5.035314581717381E-26";
+        results[32][66]="4.489037455364987E+30";
+        results[32][67]="1.625406020263772E-30";
+        results[32][68]="9.576711151667440E+25";
+        results[32][69]="7.219284208528977E-36";
+        results[32][70]="7.031497073168779E+20";
+        results[32][71]="4.411914989412857E-41";
+        results[32][72]="1.713812238330015E+16";
+        results[32][73]="8.360099251239178E-46";
+        results[32][74]="47864783395.13761";
+        results[33][0]="6.982329800946383E+32";
+        results[33][1]="1.535331298830604E+27";
+        results[33][2]="3.444787613364996E+22";
+        results[33][3]="4.016998083837972E+17";
+        results[33][4]="2803737019990.124";
+        results[33][5]="8.747485550828852E+27";
+        results[33][6]="5.436161746200319E+36";
+        results[33][7]="8.388784085898711E+22";
+        results[33][8]="8.013926459118452E+30";
+        results[33][9]="7.819545523655909E+17";
+        results[33][10]="2.853792447348690E+26";
+        results[33][11]="9475842220292.549";
+        results[33][12]="1.272347758049958E+21";
+        results[33][13]="119222118.1915926";
+        results[33][14]="9586339225533875";
+        results[33][15]="1.029808922186089E+24";
+        results[33][16]="1.183045095558775E+40";
+        results[33][17]="1.218811738588753E+19";
+        results[33][18]="9.284683992214605E+34";
+        results[33][19]="78558063495777.08";
+        results[33][20]="3.142010089732407E+30";
+        results[33][21]="1464718196.550773";
+        results[33][22]="1.805084171812118E+25";
+        results[33][23]="16053.42817021349";
+        results[33][24]="9.561311270339060E+19";
+        results[33][25]="9.571509118748273E+19";
+        results[33][26]="2.563702902183168E+44";
+        results[33][27]="1115826288292324";
+        results[33][28]="3.953805584562284E+39";
+        results[33][29]="19047336589.46896";
+        results[33][30]="8.910778252638594E+33";
+        results[33][31]="232403.4824178150";
+        results[33][32]="1.811607998846661E+29";
+        results[33][33]="1";
+        results[33][34]="4.792712188826647E+24";
+        results[33][35]="1.176503159848700E+16";
+        results[33][36]="2.479104738813852E+48";
+        results[33][37]="99541443732.04527";
+        results[33][38]="1.213289979507148E+43";
+        results[33][39]="1060911.027467431";
+        results[33][40]="2.199801600919255E+38";
+        results[33][41]="16.98500463093566";
+        results[33][42]="7.944304026196954E+32";
+        results[33][43]="0.0003064036513952934";
+        results[33][44]="2.086905486278503E+28";
+        results[33][45]="2687623535922.464";
+        results[33][46]="1.463300743255233E+52";
+        results[33][47]="9770201.983074019";
+        results[33][48]="1.211700460390415E+47";
+        results[33][49]="413.7744863151833";
+        results[33][50]="4.083605569305342E+42";
+        results[33][51]="0.001029919938804072";
+        results[33][52]="7.317343131591340E+37";
+        results[33][53]="2.145328744523008E-8";
+        results[33][54]="2.984095117073005E+32";
+        results[33][55]="108654403.3881091";
+        results[33][56]="1.254247595301220E+56";
+        results[33][57]="1089.816494157951";
+        results[33][58]="1.002503957197447E+51";
+        results[33][59]="0.02138387133156396";
+        results[33][60]="5.178088665498566E+46";
+        results[33][61]="9.885104446676278E-8";
+        results[33][62]="3.702032396218190E+41";
+        results[33][63]="8.407647967817748E-13";
+        results[33][64]="3.868223702607104E+36";
+        results[33][65]="9122.016172948436";
+        results[33][66]="8.132376161261471E+59";
+        results[33][67]="0.2944598547683367";
+        results[33][68]="1.734924652500475E+55";
+        results[33][69]="0.000001307851301811848";
+        results[33][70]="1.273831634161944E+50";
+        results[33][71]="7.992660485051813E-12";
+        results[33][72]="3.104755959479955E+45";
+        results[33][73]="1.514522267469688E-16";
+        results[33][74]="8.671222446169412E+39";
+        results[34][0]="145686398.9710135";
+        results[34][1]="320.3470682862941";
+        results[34][2]="0.007187553680765358";
+        results[34][3]="8.381471545908569E-8";
+        results[34][4]="5.850000812747606E-13";
+        results[34][5]="1825.163958566520";
+        results[34][6]="1134255830941.353";
+        results[34][7]="0.01750320852868166";
+        results[34][8]="1672106.761971122";
+        results[34][9]="1.631549155379241E-7";
+        results[34][10]="59.54441524783812";
+        results[34][11]="1.977135669106896E-12";
+        results[34][12]="0.0002654755194806417";
+        results[34][13]="2.487570993091087E-17";
+        results[34][14]="2.000190883125157E-9";
+        results[34][15]="0.2148697609230333";
+        results[34][16]="2468425077384854";
+        results[34][17]="0.000002543052222977617";
+        results[34][18]="19372504808.15474";
+        results[34][19]="1.639114981260948E-11";
+        results[34][20]="655580.7997520574";
+        results[34][21]="3.056136356290082E-16";
+        results[34][22]="3.766310391056549";
+        results[34][23]="3.349549803478537E-21";
+        results[34][24]="0.00001994968797131100";
+        results[34][25]="0.00001997096579482185";
+        results[34][26]="5.349169324542341E+19";
+        results[34][27]="2.328172951619490E-10";
+        results[34][28]="824962031682160.1";
+        results[34][29]="3.974229171089060E-15";
+        results[34][30]="1859235001.303121";
+        results[34][31]="4.849101578843441E-20";
+        results[34][32]="37799.22364355827";
+        results[34][33]="2.086501255659210E-25";
+        results[34][34]="1";
+        results[34][35]="2.454775320311342E-9";
+        results[34][36]="5.172655150445800E+23";
+        results[34][37]="2.076933473370431E-14";
+        results[34][38]="2.531531065720401E+18";
+        results[34][39]="2.213592190953497E-19";
+        results[34][40]="45898888025191.66";
+        results[34][41]="3.543923348982476E-24";
+        results[34][42]="165758003.2599846";
+        results[34][43]="6.393116033748466E-29";
+        results[34][44]="4354.330917562191";
+        results[34][45]="5.607729882441468E-13";
+        results[34][46]="3.053178838209099E+27";
+        results[34][47]="2.038553870572805E-18";
+        results[34][48]="2.528214532087444E+22";
+        results[34][49]="8.633409852563746E-23";
+        results[34][50]="8.520448147972540E+17";
+        results[34][51]="2.148929245543152E-28";
+        results[34][52]="15267645632154.63";
+        results[34][53]="4.476231119249052E-33";
+        results[34][54]="62263182.08779341";
+        results[34][55]="2.267075491021919E-17";
+        results[34][56]="2.616989182503541E+31";
+        results[34][57]="2.273903483498682E-22";
+        results[34][58]="2.091725765495799E+26";
+        results[34][59]="4.461747438416318E-27";
+        results[34][60]="1.080408850247748E+22";
+        results[34][61]="2.062528284031250E-32";
+        results[34][62]="7.724295243200328E+16";
+        results[34][63]="1.754256804199234E-37";
+        results[34][64]="807105361266.0442";
+        results[34][65]="1.903309819900053E-21";
+        results[34][66]="1.696821307196509E+35";
+        results[34][67]="6.143908567153631E-26";
+        results[34][68]="3.619922465916360E+30";
+        results[34][69]="2.728833383445953E-31";
+        results[34][70]="2.657851304177320E+25";
+        results[34][71]="1.667669613811836E-36";
+        results[34][72]="6.478077207970342E+20";
+        results[34][73]="3.160052612799337E-41";
+        results[34][74]="1809251652203281";
+        results[35][0]="5.934816020251334E+16";
+        results[35][1]="130499547406.9147";
+        results[35][2]="2927988.407449751";
+        results[35][3]="34.14353841900911";
+        results[35][4]="0.0002383110488501100";
+        results[35][5]="743515686940.7634";
+        results[35][6]="4.620609558668262E+20";
+        results[35][7]="7130269.065301548";
+        results[35][8]="681164890381514.3";
+        results[35][9]="66.46429682910084";
+        results[35][10]="24256564238.34587";
+        results[35][11]="0.0008054242898515592";
+        results[35][12]="108146.5653023476";
+        results[35][13]="1.013359948875315E-8";
+        results[35][14]="0.8148162752717714";
+        results[35][15]="87531335.00453358";
+        results[35][16]="1.005560491406513E+24";
+        results[35][17]="1035.961296309220";
+        results[35][18]="7.891762903049598E+18";
+        results[35][19]="0.006677250531641558";
+        results[35][20]="267063463742543.0";
+        results[35][21]="1.244975998822763E-7";
+        results[35][22]="1534279068.187334";
+        results[35][23]="1.364503616996488E-12";
+        results[35][24]="8126.889579768451";
+        results[35][25]="8135.557510937055";
+        results[35][26]="2.179087136929461E+28";
+        results[35][27]="0.09484260870458016";
+        results[35][28]="3.360641704583902E+23";
+        results[35][29]="0.000001618978787266365";
+        results[35][30]="7.573951823286671E+17";
+        results[35][31]="1.975374910575696E-11";
+        results[35][32]="15398241676457.85";
+        results[35][33]="8.499764676608273E-17";
+        results[35][34]="407369257.6773865";
+        results[35][35]="1";
+        results[35][36]="2.107180688858216E+32";
+        results[35][37]="0.000008460788472922284";
+        results[35][38]="1.031267931029763E+27";
+        results[35][39]="9.017494076291857E-11";
+        results[35][40]="1.869779594303981E+22";
+        results[35][41]="1.443685423940549E-15";
+        results[35][42]="6.752471474210576E+16";
+        results[35][43]="2.604358932913510E-20";
+        results[35][44]="1773820553569.003";
+        results[35][45]="0.0002284416759465479";
+        results[35][46]="1.243771196877546E+36";
+        results[35][47]="8.304441769906065E-10";
+        results[35][48]="1.029916877185643E+31";
+        results[35][49]="3.516985762863528E-14";
+        results[35][50]="3.470968637118237E+26";
+        results[35][51]="8.754077115581401E-20";
+        results[35][52]="6.219569467652223E+21";
+        results[35][53]="1.823478948240904E-24";
+        results[35][54]="2.536410626773635E+16";
+        results[35][55]="9.235368598761958E-9";
+        results[35][56]="1.066080940626218E+40";
+        results[35][57]="9.263183741028816E-14";
+        results[35][58]="8.521047723546869E+34";
+        results[35][59]="1.817578741931636E-18";
+        results[35][60]="4.401253513135038E+30";
+        results[35][61]="8.402106160044240E-24";
+        results[35][62]="3.146640419303486E+25";
+        results[35][63]="7.146302921021462E-29";
+        results[35][64]="3.287899118863873E+20";
+        results[35][65]="7.753499084627650E-13";
+        results[35][66]="6.912328363238143E+43";
+        results[35][67]="2.502839472239110E-17";
+        results[35][68]="1.474645127790042E+39";
+        results[35][69]="1.111642829739649E-22";
+        results[35][70]="1.082726912799589E+34";
+        results[35][71]="6.793573326296614E-28";
+        results[35][72]="2.638969503387675E+29";
+        results[35][73]="1.287308287097552E-32";
+        results[35][74]="7.370335025096355E+23";
+        results[36][0]="2.816472290028026E-16";
+        results[36][1]="6.193087669080073E-22";
+        results[36][2]="1.389528872835434E-26";
+        results[36][3]="1.620342223120407E-31";
+        results[36][4]="1.130947384389897E-36";
+        results[36][5]="3.528485672216559E-21";
+        results[36][6]="2.192792285493067E-12";
+        results[36][7]="3.383795752781463E-26";
+        results[36][8]="3.232588899391471E-18";
+        results[36][9]="3.154181185340816E-31";
+        results[36][10]="1.151138313225971E-22";
+        results[36][11]="3.822283936590086E-36";
+        results[36][12]="5.132287225019476E-28";
+        results[36][13]="4.809079516690182E-41";
+        results[36][14]="3.866855270552440E-33";
+        results[36][15]="4.153954877593472E-25";
+        results[36][16]="4.772065806807389E-9";
+        results[36][17]="4.916338222853396E-30";
+        results[36][18]="3.745176170594929E-14";
+        results[36][19]="3.168807766200464E-35";
+        results[36][20]="1.267397073040055E-18";
+        results[36][21]="5.908254595372923E-40";
+        results[36][22]="7.281193664595935E-24";
+        results[36][23]="6.475494124501726E-45";
+        results[36][24]="3.856759708713939E-29";
+        results[36][25]="3.860873229312546E-29";
+        results[36][26]="0.0001034124481327801";
+        results[36][27]="4.500924349110802E-34";
+        results[36][28]="1.594852174924249E-9";
+        results[36][29]="7.683151216346878E-39";
+        results[36][30]="3.594353281298647E-15";
+        results[36][31]="9.374492282605629E-44";
+        results[36][32]="7.307508918374459E-20";
+        results[36][33]="4.033714204743355E-49";
+        results[36][34]="1.933243123531666E-24";
+        results[36][35]="4.745677507807144E-33";
+        results[36][36]="1";
+        results[36][37]="4.015217355426124E-38";
+        results[36][38]="0.000004894065024810755";
+        results[36][39]="4.279411881464243E-43";
+        results[36][40]="8.873370965245172E-11";
+        results[36][41]="6.851265444743684E-48";
+        results[36][42]="3.204505199727048E-16";
+        results[36][43]="1.235944761018426E-52";
+        results[36][44]="8.417980303958437E-21";
+        results[36][45]="1.084110523385301E-36";
+        results[36][46]="5902.536993880142";
+        results[36][47]="3.941020252233737E-42";
+        results[36][48]="0.04887653358970880";
+        results[36][49]="1.669048023009940E-46";
+        results[36][50]="0.000001647209779147603";
+        results[36][51]="4.154402686902390E-52";
+        results[36][52]="2.951607093088121E-11";
+        results[36][53]="8.653643030626684E-57";
+        results[36][54]="1.203698686204266E-16";
+        results[36][55]="4.382808103545301E-41";
+        results[36][56]="50592763.41431727";
+        results[36][57]="4.396008273048529E-46";
+        results[36][58]="404.3814452458765";
+        results[36][59]="8.625642554253372E-51";
+        results[36][60]="0.02088692980344213";
+        results[36][61]="3.987368622192980E-56";
+        results[36][62]="1.493294066304539E-7";
+        results[36][63]="3.391404903626805E-61";
+        results[36][64]="1.560330889633121E-12";
+        results[36][65]="3.679560621272072E-45";
+        results[36][66]="328036812399.9663";
+        results[36][67]="1.187766898905705E-49";
+        results[36][68]="6998190.214950595";
+        results[36][69]="5.275498373810540E-55";
+        results[36][70]="51.38272757170476";
+        results[36][71]="3.224010813224441E-60";
+        results[36][72]="0.001252369821601588";
+        results[36][73]="6.109149983692593E-65";
+        results[36][74]="3.497723315360298E-9";
+        results[37][0]="7.014495208389838E+21";
+        results[37][1]="1.542404089460013E+16";
+        results[37][2]="346065667144.4297";
+        results[37][3]="4035503.136413506";
+        results[37][4]="28.16652958678678";
+        results[37][5]="8.787782478196851E+16";
+        results[37][6]="5.461204441472514E+25";
+        results[37][7]="842742858791.6008";
+        results[37][8]="8.050844109405394E+19";
+        results[37][9]="7855567.721827779";
+        results[37][10]="2866938975720293";
+        results[37][11]="95.19494458811030";
+        results[37][12]="12782090658.38928";
+        results[37][13]="0.001197713371653776";
+        results[37][14]="96305.00489162340";
+        results[37][15]="10345529294895.73";
+        results[37][16]="1.188495013939524E+29";
+        results[37][17]="122442642.2696522";
+        results[37][18]="9.327455624622005E+23";
+        results[37][19]="789.1995590022467";
+        results[37][20]="3.156484346550524E+19";
+        results[37][21]="0.01471465694724737";
+        results[37][22]="181339962947614.9";
+        results[37][23]="1.612738128796641E-7";
+        results[37][24]="960535723.8013413";
+        results[37][25]="961560206.4717620";
+        results[37][26]="2.575513078838174E+33";
+        results[37][27]="11209.66550672107";
+        results[37][28]="3.972019529077253E+28";
+        results[37][29]="0.1913508170601013";
+        results[37][30]="8.951827418361983E+22";
+        results[37][31]="0.000002334740925030381";
+        results[37][32]="1.819953509739433E+18";
+        results[37][33]="1.004606686931215E-11";
+        results[37][34]="48147907134319.92";
+        results[37][35]="118192.2941579709";
+        results[37][36]="2.490525198215260E+37";
+        results[37][37]="1";
+        results[37][38]="1.218879226599518E+32";
+        results[37][39]="0.00001065798312432847";
+        results[37][40]="2.209935398205477E+27";
+        results[37][41]="1.706324922979563E-10";
+        results[37][42]="7.980900947732038E+21";
+        results[37][43]="3.078151570918528E-15";
+        results[37][44]="2.096519206508824E+17";
+        results[37][45]="27.00004576141425";
+        results[37][46]="1.470041711665625E+41";
+        results[37][47]="0.00009815210244864781";
+        results[37][48]="1.217282385065843E+36";
+        results[37][49]="4.156806158337618E-9";
+        results[37][50]="4.102417461713700E+31";
+        results[37][51]="1.034664457526358E-14";
+        results[37][52]="7.351051840566861E+26";
+        results[37][53]="2.155211602413563E-19";
+        results[37][54]="2.997841909050329E+21";
+        results[37][55]="0.001091549402082161";
+        results[37][56]="1.260025521307003E+45";
+        results[37][57]="1.094836937559011E-8";
+        results[37][58]="1.007122179075560E+40";
+        results[37][59]="2.148238013216586E-13";
+        results[37][60]="5.201942498882593E+35";
+        results[37][61]="9.930642028144481E-19";
+        results[37][62]="3.719086500476785E+30";
+        results[37][63]="8.446379369833354E-24";
+        results[37][64]="3.886043398184922E+25";
+        results[37][65]="9.164038445638694E-8";
+        results[37][66]="8.169839472243282E+48";
+        results[37][67]="2.958163391330656E-12";
+        results[37][68]="1.742916907223793E+44";
+        results[37][69]="1.313876163311878E-17";
+        results[37][70]="1.279699777703607E+39";
+        results[37][71]="8.029480169653943E-23";
+        results[37][72]="3.119058598183105E+34";
+        results[37][73]="1.521499197406275E-27";
+        results[37][74]="8.711168053289843E+28";
+    }
+
+    private static void initResults2() {
+        results[38][0]="5.754873046740801E-11";
+        results[38][1]="1.265428153832008E-16";
+        results[38][2]="2.839212118742058E-21";
+        results[38][3]="3.310831006343367E-26";
+        results[38][4]="2.310854838782263E-31";
+        results[38][5]="7.209723725223695E-16";
+        results[38][6]="4.480513181530232E-7";
+        results[38][7]="6.914080086037084E-21";
+        results[38][8]="6.605120453046024E-13";
+        results[38][9]="6.444910660872926E-26";
+        results[38][10]="2.352110786003469E-17";
+        results[38][11]="7.810039133548062E-31";
+        results[38][12]="1.048675732545652E-22";
+        results[38][13]="9.826349859084964E-36";
+        results[38][14]="7.901111348029064E-28";
+        results[38][15]="8.487739448770601E-20";
+        results[38][16]="0.0009750720071382617";
+        results[38][17]="1.004551062956811E-24";
+        results[38][18]="7.652485513797906E-9";
+        results[38][19]="6.474797024837234E-30";
+        results[38][20]="2.589661286915703E-13";
+        results[38][21]="1.207228462519536E-34";
+        results[38][22]="1.487759894419769E-18";
+        results[38][23]="1.323132016365500E-39";
+        results[38][24]="7.880483175360085E-24";
+        results[38][25]="7.888888295802402E-24";
+        results[38][26]="21.13017452946058";
+        results[38][27]="9.196699116773269E-29";
+        results[38][28]="0.0003258747415163162";
+        results[38][29]="1.569891527267555E-33";
+        results[38][30]="7.344310431260839E-10";
+        results[38][31]="1.915481759045105E-38";
+        results[38][32]="1.493136867068297E-14";
+        results[38][33]="8.242052739990580E-44";
+        results[38][34]="3.950178662790491E-19";
+        results[38][35]="9.696801092238556E-28";
+        results[38][36]="204329.1200526434";
+        results[38][37]="8.204258290543218E-33";
+        results[38][38]="1";
+        results[38][39]="8.744084640824158E-38";
+        results[38][40]="0.00001813088081229221";
+        results[38][41]="1.399913039571560E-42";
+        results[38][42]="6.547737276643480E-11";
+        results[38][43]="2.525395054525697E-47";
+        results[38][44]="1.720038508128311E-15";
+        results[38][45]="2.215153492831292E-31";
+        results[38][46]="1206060190.037704";
+        results[38][47]="8.052652002485662E-37";
+        results[38][48]="9986.899099608667";
+        results[38][49]="3.410351138672251E-41";
+        results[38][50]="0.3365729247153389";
+        results[38][51]="8.488654453591028E-47";
+        results[38][52]="0.000006030992800718365";
+        results[38][53]="1.768191265697641E-51";
+        results[38][54]="2.459506933606407E-11";
+        results[38][55]="8.955353231570062E-36";
+        results[38][56]="10337574829479.02";
+        results[38][57]="8.982325021761465E-41";
+        results[38][58]="82626904.87270614";
+        results[38][59]="1.762469952999227E-45";
+        results[38][60]="4267.807987338662";
+        results[38][61]="8.147355218982128E-51";
+        results[38][62]="0.03051234625478403";
+        results[38][63]="6.929627797002850E-56";
+        results[38][64]="3.188210376696939E-7";
+        results[38][65]="7.518413839248804E-40";
+        results[38][66]="6.702747322255918E+16";
+        results[38][67]="2.426953652810597E-44";
+        results[38][68]="1429934048581.875";
+        results[38][69]="1.077937940559859E-49";
+        results[38][70]="10498987.51063113";
+        results[38][71]="6.587592925063573E-55";
+        results[38][72]="255.8956236283385";
+        results[38][73]="1.248277240437528E-59";
+        results[38][74]="0.0007146867272151842";
+        results[39][0]="6.581447096100371E+26";
+        results[39][1]="1.447181958788470E+21";
+        results[39][2]="3.247008961334176E+16";
+        results[39][3]="378636660364.1785";
+        results[39][4]="2642763.575267104";
+        results[39][5]="8.245258390527376E+21";
+        results[39][6]="5.124050561692560E+30";
+        results[39][7]="7.907151371518986E+16";
+        results[39][8]="7.553815778735954E+24";
+        results[39][9]="737059500863.3713";
+        results[39][10]="2.689945125899165E+20";
+        results[39][11]="8931797.271363033";
+        results[39][12]="1199297325702478";
+        results[39][13]="112.3771127878607";
+        results[39][14]="9035950213.862933";
+        results[39][15]="9.706835875242173E+17";
+        results[39][16]="1.115121876320673E+34";
+        results[39][17]="11488350172947.65";
+        results[39][18]="8.751614180482857E+28";
+        results[39][19]="74047739.59538163";
+        results[39][20]="2.961615072691725E+24";
+        results[39][21]="1380.623029291435";
+        results[39][22]="1.701447270390950E+19";
+        results[39][23]="0.01513173843478247";
+        results[39][24]="90123592108977.16";
+        results[39][25]="90219715611751.54";
+        results[39][26]="2.416510749542446E+38";
+        results[39][27]="1051762362.161496";
+        results[39][28]="3.726802231475215E+33";
+        results[39][29]="17953.75492979660";
+        results[39][30]="8.399175823358240E+27";
+        results[39][31]="0.2190602947851342";
+        results[39][32]="1.707596539147366E+23";
+        results[39][33]="9.425861114736121E-7";
+        results[39][34]="4.517543945478293E+18";
+        results[39][35]="11089555385.78204";
+        results[39][36]="2.336769695694354E+42";
+        results[39][37]="93826.38237785791";
+        results[39][38]="1.143630283873541E+37";
+        results[39][39]="1";
+        results[39][40]="2.073502437023907E+32";
+        results[39][41]="0.00001600982946843494";
+        results[39][42]="7.488190640417148E+26";
+        results[39][43]="2.888118263100058E-10";
+        results[39][44]="1.967088127324202E+22";
+        results[39][45]="2533316.617830116";
+        results[39][46]="1.379286957501396E+46";
+        results[39][47]="9.209256695537514";
+        results[39][48]="1.142132025230187E+41";
+        results[39][49]="0.0003900180840828200";
+        results[39][50]="3.849149894363509E+36";
+        results[39][51]="9.707882302464703E-10";
+        results[39][52]="6.897226008724825E+31";
+        results[39][53]="2.022157079132508E-14";
+        results[39][54]="2.812766612669237E+26";
+        results[39][55]="102.4161315840830";
+        results[39][56]="1.182236363680106E+50";
+        results[39][57]="0.001027245891448147";
+        results[39][58]="9.449463067516497E+44";
+        results[39][59]="2.015614012667092E-8";
+        results[39][60]="4.880794460077878E+40";
+        results[39][61]="9.317562161903105E-14";
+        results[39][62]="3.489484320900643E+35";
+        results[39][63]="7.924932204624348E-19";
+        results[39][64]="3.646133938150488E+30";
+        results[39][65]="0.008598285753258867";
+        results[39][66]="7.665464822884150E+53";
+        results[39][67]="2.775537694911710E-7";
+        results[39][68]="1.635315881900131E+49";
+        results[39][69]="1.232762472960531E-12";
+        results[39][70]="1.200696006716784E+44";
+        results[39][71]="7.533770766933783E-18";
+        results[39][72]="2.926499846920735E+39";
+        results[39][73]="1.427567654834451E-22";
+        results[39][74]="8.173373847257529E+33";
+        results[40][0]="0.000003174072515461667";
+        results[40][1]="6.979408043839129E-12";
+        results[40][2]="1.565953771433517E-16";
+        results[40][3]="1.826072897737389E-21";
+        results[40][4]="1.274540858056698E-26";
+        results[40][5]="3.976488401123740E-11";
+        results[40][6]="0.02471205468678926";
+        results[40][7]="3.813427575647367E-16";
+        results[40][8]="3.643022377913347E-8";
+        results[40][9]="3.554659438554945E-21";
+        results[40][10]="1.297295377072253E-12";
+        results[40][11]="4.307589473674706E-26";
+        results[40][12]="5.783920502277423E-18";
+        results[40][13]="5.419675944492992E-31";
+        results[40][14]="4.357819914999574E-23";
+        results[40][15]="4.681371818966545E-15";
+        results[40][16]="53.77962699292531";
+        results[40][17]="5.540553012050880E-20";
+        results[40][18]="0.0004220691533424975";
+        results[40][19]="3.571143118677119E-25";
+        results[40][20]="1.428315211889754E-8";
+        results[40][21]="6.658410449100025E-30";
+        results[40][22]="8.205668052327118E-14";
+        results[40][23]="7.297670918825164E-35";
+        results[40][24]="4.346442545702108E-19";
+        results[40][25]="4.351078349405929E-19";
+        results[40][26]="1165424.600614822";
+        results[40][27]="5.072395109750087E-24";
+        results[40][28]="17.97346443838419";
+        results[40][29]="8.658661118125126E-29";
+        results[40][30]="0.00004050719050715733";
+        results[40][31]="1.056474739906990E-33";
+        results[40][32]="8.235324486033761E-10";
+        results[40][33]="4.545864497880714E-39";
+        results[40][34]="2.178702018774722E-14";
+        results[40][35]="5.348223946000686E-23";
+        results[40][36]="11269674218.70173";
+        results[40][37]="4.525019151292953E-28";
+        results[40][38]="55154.51843475961";
+        results[40][39]="4.822757775174344E-33";
+        results[40][40]="1";
+        results[40][41]="7.721152954810994E-38";
+        results[40][42]="0.000003611372963305955";
+        results[40][43]="1.392869480898883E-42";
+        results[40][44]="9.486789560505935E-11";
+        results[40][45]="1.221757241561856E-26";
+        results[40][46]="66519668984864.25";
+        results[40][47]="4.441401433197993E-32";
+        results[40][48]="550822610.4954504";
+        results[40][49]="1.880962747469021E-36";
+        results[40][50]="18563.51758085312";
+        results[40][51]="4.681876485468906E-42";
+        results[40][52]="0.3326365036071236";
+        results[40][53]="9.752373776010145E-47";
+        results[40][54]="0.000001356529205100136";
+        results[40][55]="4.939281949004150E-31";
+        results[40][56]="5.701639615032074E+17";
+        results[40][57]="4.954158109997452E-36";
+        results[40][58]="4557247148008.799";
+        results[40][59]="9.720818151340577E-41";
+        results[40][60]="235388894.3136845";
+        results[40][61]="4.493634536198847E-46";
+        results[40][62]="1682.893763997254";
+        results[40][63]="3.822002840758163E-51";
+        results[40][64]="0.01758442079954232";
+        results[40][65]="4.146744946969999E-35";
+        results[40][66]="3.696868007488996E+21";
+        results[40][67]="1.338574599842493E-39";
+        results[40][68]="7.886732384299944E+16";
+        results[40][69]="5.945314801413554E-45";
+        results[40][70]="579066600201.4157";
+        results[40][71]="3.633355154261108E-50";
+        results[40][72]="14113799.89078350";
+        results[40][73]="6.884813006940251E-55";
+        results[40][74]="39.41820227126789";
+        results[41][0]="4.110878950382567E+31";
+        results[41][1]="9.039334001912643E+25";
+        results[41][2]="2.028134632999056E+21";
+        results[41][3]="2.365026192881695E+16";
+        results[41][4]="165071313250.2498";
+        results[41][5]="5.150122558634225E+26";
+        results[41][6]="3.200565360046566E+35";
+        results[41][7]="4.938935412840446E+21";
+        results[41][8]="4.718236252065705E+29";
+        results[41][9]="4.603793577667779E+16";
+        results[41][10]="1.680183496771577E+25";
+        results[41][11]="557894591505.3629";
+        results[41][12]="7.491006247549473E+19";
+        results[41][13]="7019257.326220990";
+        results[41][14]="564400153772921.7";
+        results[41][15]="6.063047638564933E+22";
+        results[41][16]="6.965232693572741E+38";
+        results[41][17]="7.175810457942816E+17";
+        results[41][18]="5.466400624527316E+33";
+        results[41][19]="4625142306567.008";
+        results[41][20]="1.849872966186717E+29";
+        results[41][21]="86235960.97719082";
+        results[41][22]="1.062751651256206E+24";
+        results[41][23]="945.1530051969814";
+        results[41][24]="5.629266213401292E+18";
+        results[41][25]="5.635270243797986E+18";
+        results[41][26]="1.509391935939637E+43";
+        results[41][27]="65694788581924.34";
+        results[41][28]="2.327821316787288E+38";
+        results[41][29]="1121420747.497299";
+        results[41][30]="5.246261891744755E+32";
+        results[41][31]="13682.86247002409";
+        results[41][32]="1.066592584583160E+28";
+        results[41][33]="0.05887546231095213";
+        results[41][34]="2.821731458405042E+23";
+        results[41][35]="692671674463882.5";
+        results[41][36]="1.459584376149378E+47";
+        results[41][37]="5860548518.823794";
+        results[41][38]="7.143300846072895E+41";
+        results[41][39]="62461.62721293222";
+        results[41][40]="1.295143362464938E+37";
+        results[41][41]="1";
+        results[41][42]="4.677245722811041E+31";
+        results[41][43]="0.00001803965662966171";
+        results[41][44]="1.228675253039092E+27";
+        results[41][45]="158235078195.2310";
+        results[41][46]="8.615250775911171E+50";
+        results[41][47]="575225.1586248642";
+        results[41][48]="7.133942478787923E+45";
+        results[41][49]="24.36116417428315";
+        results[41][50]="2.404241657884309E+41";
+        results[41][51]="0.00006063701254035724";
+        results[41][52]="4.308119597603104E+36";
+        results[41][53]="1.263072216427666E-9";
+        results[41][54]="1.756899795975280E+31";
+        results[41][55]="6397078.231595606";
+        results[41][56]="7.384440702575934E+54";
+        results[41][57]="64.16344992765041";
+        results[41][58]="5.902288394855864E+49";
+        results[41][59]="0.001258985310643743";
+        results[41][60]="3.048623640683292E+45";
+        results[41][61]="5.819900942901146E-9";
+        results[41][62]="2.179588688174679E+40";
+        results[41][63]="4.950041610530071E-14";
+        results[41][64]="2.277434588131763E+35";
+        results[41][65]="537.0629193903215";
+        results[41][66]="4.787974061808353E+58";
+        results[41][67]="0.01733646008150164";
+        results[41][68]="1.021444909906334E+54";
+        results[41][69]="7.700035002815314E-8";
+        results[41][70]="7.499742636760013E+48";
+        results[41][71]="4.705715811519044E-13";
+        results[41][72]="1.827939424770661E+44";
+        results[41][73]="8.916819867750936E-18";
+        results[41][74]="5.105222303193294E+38";
+        results[42][0]="0.8789101950179163";
+        results[42][1]="0.000001932619010762593";
+        results[42][2]="4.336172938504800E-11";
+        results[42][3]="5.056450597297903E-16";
+        results[42][4]="3.529241845156713E-21";
+        results[42][5]="0.00001101101559303791";
+        results[42][6]="6842.842026531408";
+        results[42][7]="1.055949527892695E-10";
+        results[42][8]="0.01008763817785915";
+        results[42][9]="9.842958549761383E-16";
+        results[42][10]="3.592249790463821E-7";
+        results[42][11]="1.192784438894235E-20";
+        results[42][12]="1.601584926576693E-12";
+        results[42][13]="1.500724516564931E-25";
+        results[42][14]="1.206693398681896E-17";
+        results[42][15]="1.296285890859935E-9";
+        results[42][16]="14891739.93917645";
+        results[42][17]="1.534195738946580E-14";
+        results[42][18]="116.8722138729541";
+        results[42][19]="9.888602354180532E-20";
+        results[42][20]="0.003955047640890110";
+        results[42][21]="1.843733814467261E-24";
+        results[42][22]="2.272174083292525E-8";
+        results[42][23]="2.020746954959940E-29";
+        results[42][24]="1.203542971015447E-13";
+        results[42][25]="1.204826638958615E-13";
+        results[42][26]="322709565712.6364";
+        results[42][27]="1.404561412318563E-18";
+        results[42][28]="4976906.185267212";
+        results[42][29]="2.397609221230570E-23";
+        results[42][30]="11.21656248710349";
+        results[42][31]="2.925410226640957E-28";
+        results[42][32]="0.0002280386038692306";
+        results[42][33]="1.258763507416664E-33";
+        results[42][34]="6.032891204846025E-9";
+        results[42][35]="1.480939243977938E-17";
+        results[42][36]="3120606576282596";
+        results[42][37]="1.252991368454678E-22";
+        results[42][38]="15272451501.17909";
+        results[42][39]="1.335436085991919E-27";
+        results[42][40]="276902.9978793913";
+        results[42][41]="2.138010400272485E-32";
+        results[42][42]="1";
+        results[42][43]="3.856897349156122E-37";
+        results[42][44]="0.00002626920469555007";
+        results[42][45]="3.383082428693337E-21";
+        results[42][46]="1.841949575985368E+19";
+        results[42][47]="1.229837371638349E-26";
+        results[42][48]="152524432145942.5";
+        results[42][49]="5.208442236736284E-31";
+        results[42][50]="5140293669.325014";
+        results[42][51]="1.296425634527369E-36";
+        results[42][52]="92108.04505293148";
+        results[42][53]="2.700461535017569E-41";
+        results[42][54]="0.3756270036031754";
+        results[42][55]="1.367701979050812E-25";
+        results[42][56]="1.578801102230280E+23";
+        results[42][57]="1.371821232626794E-30";
+        results[42][58]="1.261915397360943E+18";
+        results[42][59]="2.691723687946608E-35";
+        results[42][60]="65179890502974.45";
+        results[42][61]="1.244300874447829E-40";
+        results[42][62]="465998328.3633725";
+        results[42][63]="1.058324044509485E-45";
+        results[42][64]="4869.178835365991";
+        results[42][65]="1.148246107257210E-29";
+        results[42][66]="1.023673834038115E+27";
+        results[42][67]="3.706553195815928E-34";
+        results[42][68]="2.183859840685134E+22";
+        results[42][69]="1.646275491848131E-39";
+        results[42][70]="1.603452775675989E+17";
+        results[42][71]="1.006086934575439E-44";
+        results[42][72]="3908153501227.777";
+        results[42][73]="1.906425361460782E-49";
+        results[42][74]="10915018.37993031";
+        results[43][0]="2.278801107346606E+36";
+        results[43][1]="5.010812670929508E+30";
+        results[43][2]="1.124264543740979E+26";
+        results[43][3]="1.311015082733337E+21";
+        results[43][4]="9150468694555485";
+        results[43][5]="2.854889460681936E+31";
+        results[43][6]="1.774183082168003E+40";
+        results[43][7]="2.737821187083793E+26";
+        results[43][8]="2.615480077546344E+34";
+        results[43][9]="2.552040580472019E+21";
+        results[43][10]="9.313833025008547E+29";
+        results[43][11]="3.092600945563700E+16";
+        results[43][12]="4.152521525954315E+24";
+        results[43][13]="389101492911.9866";
+        results[43][14]="3.128663507069788E+19";
+        results[43][15]="3.360955124054725E+27";
+        results[43][16]="3.861067223485925E+43";
+        results[43][17]="3.977797696073652E+22";
+        results[43][18]="3.030213233404445E+38";
+        results[43][19]="2.563874912653335E+17";
+        results[43][20]="1.025447991701273E+34";
+        results[43][21]="4780354900735.599";
+        results[43][22]="5.891196673382220E+28";
+        results[43][23]="52393070.69974453";
+        results[43][24]="3.120495211724467E+23";
+        results[43][25]="3.123823451568468E+23";
+        results[43][26]="8.367076862526411E+47";
+        results[43][27]="3.641687307612366E+18";
+        results[43][28]="1.290391144673877E+43";
+        results[43][29]="62164195833605.98";
+        results[43][30]="2.908182788312382E+37";
+        results[43][31]="758487966.3133965";
+        results[43][32]="5.912488283338024E+32";
+        results[43][33]="3263.668678379727";
+        results[43][34]="1.564182465516227E+28";
+        results[43][35]="3.839716512812981E+19";
+        results[43][36]="8.090976486489524E+51";
+        results[43][37]="324870292108974.2";
+        results[43][38]="3.959776503909459E+46";
+        results[43][39]="3462462090.893108";
+        results[43][40]="7.179423583569754E+41";
+        results[43][41]="55433.42761611934";
+        results[43][42]="2.592757622182496E+36";
+        results[43][43]="1";
+        results[43][44]="6.810968070305965E+31";
+        results[43][45]="8771512753466319";
+        results[43][46]="4.775728802811879E+55";
+        results[43][47]="31886702193.60218";
+        results[43][48]="3.954588840154493E+50";
+        results[43][49]="1350422.830899525";
+        results[43][50]="1.332753559139886E+46";
+        results[43][51]="3.361317445513614";
+        results[43][52]="2.388138358753168E+41";
+        results[43][53]="0.00007001642228327445";
+        results[43][54]="9.739097766897050E+35";
+        results[43][55]="354611973105.8077";
+        results[43][56]="4.093448591717685E+59";
+        results[43][57]="3556799.957164907";
+        results[43][58]="3.271840765057037E+54";
+        results[43][59]="69.78987108732747";
+        results[43][60]="1.689956579146075E+50";
+        results[43][61]="0.0003226170576512954";
+        results[43][62]="1.208220717788436E+45";
+        results[43][63]="2.743977733140975E-9";
+        results[43][64]="1.262460053916486E+40";
+        results[43][65]="29771238.46732512";
+        results[43][66]="2.654138135831102E+63";
+        results[43][67]="961.0194050476638";
+        results[43][68]="5.662219247714633E+58";
+        results[43][69]="0.004268393329701480";
+        results[43][70]="4.157364405943601E+53";
+        results[43][71]="2.608539568198692E-8";
+        results[43][72]="1.013289477896753E+49";
+        results[43][73]="4.942898887049463E-13";
+        results[43][74]="2.829999710082635E+43";
+        results[44][0]="33457.81515672613";
+        results[44][1]="0.07356975717997179";
+        results[44][2]="0.000001650667764311622";
+        results[44][3]="1.924858653278701E-11";
+        results[44][4]="1.343490176447769E-16";
+        results[44][5]="0.4191605996698921";
+        results[44][6]="260489120.4677608";
+        results[44][7]="0.000004019724008133258";
+        results[44][8]="384.0100336028812";
+        results[44][9]="3.746957193351482E-11";
+        results[44][10]="0.01367475655276438";
+        results[44][11]="4.540618769080169E-16";
+        results[44][12]="6.096815435177592E-8";
+        results[44][13]="5.712866201918743E-21";
+        results[44][14]="4.593566545569257E-13";
+        results[44][15]="0.00004934621759141124";
+        results[44][16]="566889637953.1077";
+        results[44][17]="5.840282401874423E-10";
+        results[44][18]="4449019.878121849";
+        results[44][19]="3.764332597345680E-15";
+        results[44][20]="150.5583319604680";
+        results[44][21]="7.018612995084639E-20";
+        results[44][22]="0.0008649573177513917";
+        results[44][23]="7.692455779988837E-25";
+        results[44][24]="4.581573690425900E-9";
+        results[44][25]="4.586460278954353E-9";
+        results[44][26]="1.228471015596839E+16";
+        results[44][27]="5.346798384636640E-14";
+        results[44][28]="189457817354.8698";
+        results[44][29]="9.127071980358501E-19";
+        results[44][30]="426985.2329790381";
+        results[44][31]="1.113627253106948E-23";
+        results[44][32]="8.680833946520647";
+        results[44][33]="4.791783847304273E-29";
+        results[44][34]="0.0002296564085119783";
+        results[44][35]="5.637548837665439E-13";
+        results[44][36]="1.187933404322369E+20";
+        results[44][37]="4.769810822125617E-18";
+        results[44][38]="581382332589848.2";
+        results[44][39]="5.083656324845414E-23";
+        results[44][40]="10540973778.55897";
+        results[44][41]="8.138847083690577E-28";
+        results[44][42]="38067.38771080486";
+        results[44][43]="1.468220067511016E-32";
+        results[44][44]="1";
+        results[44][45]="1.287851104706806E-16";
+        results[44][46]="7.011820865278762E+23";
+        results[44][47]="4.681669604739426E-22";
+        results[44][48]="5.806206693869941E+18";
+        results[44][49]="1.982717899951718E-26";
+        results[44][50]="195677552057591.1";
+        results[44][51]="4.935153726777955E-32";
+        results[44][52]="3506312662.314225";
+        results[44][53]="1.027995162516290E-36";
+        results[44][54]="14299.13878080998";
+        results[44][55]="5.206484150936237E-21";
+        results[44][56]="6.010083367684613E+27";
+        results[44][57]="5.222165073231839E-26";
+        results[44][58]="4.803782268957339E+22";
+        results[44][59]="1.024668892394211E-30";
+        results[44][60]="2.481228162724536E+18";
+        results[44][61]="4.736728381649903E-36";
+        results[44][62]="17739339038395.46";
+        results[44][63]="4.028763172600968E-41";
+        results[44][64]="185356918.5591225";
+        results[44][65]="4.371072975238266E-25";
+        results[44][66]="3.896858872973504E+31";
+        results[44][67]="1.410987975758478E-29";
+        results[44][68]="8.313383926141755E+26";
+        results[44][69]="6.266940742697879E-35";
+        results[44][70]="6.103925848762411E+21";
+        results[44][71]="3.829910140925841E-40";
+        results[44][72]="1.487731945645773E+17";
+        results[44][73]="7.257263337643890E-45";
+        results[44][74]="415506236539.3683";
+        results[45][0]="2.597956785100805E+20";
+        results[45][1]="571259805664574.7";
+        results[45][2]="12817225207.78065";
+        results[45][3]="149462.8258067859";
+        results[45][4]="1.043203031420026";
+        results[45][5]="3254728734851059";
+        results[45][6]="2.022664883508130E+24";
+        results[45][7]="31212645572.47396";
+        results[45][8]="2.981789060858130E+18";
+        results[45][9]="290946.4595446784";
+        results[45][10]="106182745061026.3";
+        results[45][11]="3.525732712799818";
+        results[45][12]="473409962.7585133";
+        results[45][13]="0.00004435967932193017";
+        results[45][14]="3566.845987692836";
+        results[45][15]="383167102245.4531";
+        results[45][16]="4.401825924450844E+27";
+        results[45][17]="4534904.990592084";
+        results[45][18]="3.454607339203797E+22";
+        results[45][19]="29.22956375615078";
+        results[45][20]="1.169066295088082E+18";
+        results[45][21]="0.0005449863706629740";
+        results[45][22]="6716283540777.093";
+        results[45][23]="5.973094057127134E-9";
+        results[45][24]="35575336.88235604";
+        results[45][25]="35613280.62065461";
+        results[45][26]="9.538921161825726E+31";
+        results[45][27]="415.1720928836645";
+        results[45][28]="1.471115850756691E+27";
+        results[45][29]="0.007087055286904757";
+        results[45][30]="3.315486017121880E+21";
+        results[45][31]="8.647173955412170E-8";
+        results[45][32]="6.740557130241340E+16";
+        results[45][33]="3.720759200959941E-13";
+        results[45][34]="1783252797412.961";
+        results[45][35]="4377.484956965496";
+        results[45][36]="9.224151767085032E+35";
+        results[45][37]="0.03703697426428437";
+        results[45][38]="4.514359854683718E+30";
+        results[45][39]="3.947394466849308E-7";
+        results[45][40]="8.184932046906727E+25";
+        results[45][41]="6.319711225890107E-12";
+        results[45][42]="2.955884230069542E+20";
+        results[45][43]="1.140054205136760E-16";
+        results[45][44]="7764872789604521";
+        results[45][45]="1";
+        results[45][46]="5.444589704238428E+39";
+        results[45][47]="0.000003635256892375972";
+        results[45][48]="4.508445636805033E+34";
+        results[45][49]="1.539555227079692E-10";
+        results[45][50]="1.519411299508411E+30";
+        results[45][51]="3.832084088557348E-16";
+        results[45][52]="2.722607178344951E+25";
+        results[45][53]="7.982251665267820E-21";
+        results[45][54]="1.110309936338901E+20";
+        results[45][55]="0.00004042768711311199";
+        results[45][56]="4.666753280498896E+43";
+        results[45][57]="4.054944747996101E-10";
+        results[45][58]="3.730075822741150E+38";
+        results[45][59]="7.956423600906009E-15";
+        results[45][60]="1.926642104554017E+34";
+        results[45][61]="3.678009332242079E-20";
+        results[45][62]="1.377437110048061E+29";
+        results[45][63]="3.128283353469004E-25";
+        results[45][64]="1.439272893284671E+24";
+        results[45][65]="3.394082560680328E-9";
+        results[45][66]="3.025861342768090E+47";
+        results[45][67]="1.095614213942617E-13";
+        results[45][68]="6.455236863763371E+42";
+        results[45][69]="4.866199764703870E-19";
+        results[45][70]="4.739620773281892E+37";
+        results[45][71]="2.973876503990548E-24";
+        results[45][72]="1.155204930297025E+33";
+        results[45][73]="5.635172661746553E-29";
+        results[45][74]="3.226353070015521E+27";
+        results[46][0]="4.771630051532411E-20";
+        results[46][1]="1.049224710578041E-25";
+        results[46][2]="2.354121413006176E-30";
+        results[46][3]="2.745162334095334E-35";
+        results[46][4]="1.916036080015227E-40";
+        results[46][5]="5.977913693510024E-25";
+        results[46][6]="3.714999648060815E-16";
+        results[46][7]="5.732781948321280E-30";
+        results[46][8]="5.476609299938448E-22";
+        results[46][9]="5.343771989249925E-35";
+        results[46][10]="1.950243284234377E-26";
+        results[46][11]="6.475662821856263E-40";
+        results[46][12]="8.695053043023237E-32";
+        results[46][13]="8.147478824234940E-45";
+        results[46][14]="6.551174985538704E-37";
+        results[46][15]="7.037575337351325E-29";
+        results[46][16]="8.084770687172574E-13";
+        results[46][17]="8.329195103649068E-34";
+        results[46][18]="6.345027865946450E-18";
+        results[46][19]="5.368552148823365E-39";
+        results[46][20]="2.147207335344303E-22";
+        results[46][21]="1.000968668472338E-43";
+        results[46][22]="1.233570187216990E-27";
+        results[46][23]="1.097069638227704E-48";
+        results[46][24]="6.534071218380670E-33";
+        results[46][25]="6.541040290498085E-33";
+        results[46][26]="1.752E-8";
+        results[46][27]="7.625406420624627E-38";
+        results[46][28]="2.701977432039512E-13";
+        results[46][29]="1.301669303269579E-42";
+        results[46][30]="6.089505724445841E-19";
+        results[46][31]="1.588214066650539E-47";
+        results[46][32]="1.238028482659409E-23";
+        results[46][33]="6.833865181913444E-53";
+        results[46][34]="3.275274895415460E-28";
+        results[46][35]="8.040063980501181E-37";
+        results[46][36]="0.0001694186755689661";
+        results[46][37]="6.802528064778204E-42";
+        results[46][38]="8.291460146518372E-10";
+        results[46][39]="7.250122931717692E-47";
+        results[46][40]="1.503314756763955E-14";
+        results[46][41]="1.160732317619898E-51";
+        results[46][42]="5.429030267916215E-20";
+        results[46][43]="2.093921244881440E-56";
+        results[46][44]="1.426163074062281E-24";
+        results[46][45]="1.836685690423163E-40";
+        results[46][46]="1";
+        results[46][47]="6.676824315239122E-46";
+        results[46][48]="0.000008280597587170547";
+        results[46][49]="2.827679055193452E-50";
+        results[46][50]="2.790680991674361E-10";
+        results[46][51]="7.038334009951569E-56";
+        results[46][52]="5.000573645109554E-15";
+        results[46][53]="1.466088741095387E-60";
+        results[46][54]="2.039290372008313E-20";
+        results[46][55]="7.425295441755768E-45";
+        results[46][56]="8571.358971027673";
+        results[46][57]="7.447658994100996E-50";
+        results[46][58]="0.06850976887822076";
+        results[46][59]="1.461344937472920E-54";
+        results[46][60]="0.000003538635984001130";
+        results[46][61]="6.755347109771878E-60";
+        results[46][62]="2.529919029483109E-11";
+        results[46][63]="5.745673270905503E-65";
+        results[46][64]="2.643491927709899E-16";
+        results[46][65]="6.233862871316364E-49";
+        results[46][66]="55575562.29466768";
+        results[46][67]="2.012298948972625E-53";
+        results[46][68]="1185.624117596628";
+        results[46][69]="8.937679474572159E-59";
+        results[46][70]="0.008705193652319216";
+        results[46][71]="5.462076419965100E-64";
+        results[46][72]="2.121748364982833E-7";
+        results[46][73]="1.035004099089370E-68";
+        results[46][74]="5.925796515950347E-13";
+        results[47][0]="7.146556246270681E+25";
+        results[47][1]="1.571442741399231E+20";
+        results[47][2]="3525810028628656";
+        results[47][3]="41114790572.36538";
+        results[47][4]="286968.1737232600";
+        results[47][5]="8.953228977234115E+20";
+        results[47][6]="5.564021865277680E+29";
+        results[47][7]="8586090748616571";
+        results[47][8]="8.202416360482460E+23";
+        results[47][9]="80034635283.92306";
+        results[47][10]="2.920914482927399E+19";
+        results[47][11]="969871.6809241588";
+        results[47][12]="130227375058794.5";
+        results[47][13]="12.20262573876507";
+        results[47][14]="981181273.6462696";
+        results[47][15]="1.054030330150941E+17";
+        results[47][16]="1.210870663276248E+33";
+        results[47][17]="1247478548243.150";
+        results[47][18]="9.503062483559163E+27";
+        results[47][19]="8040577.219577623";
+        results[47][20]="3.215911088814389E+23";
+        results[47][21]="149.9168798238013";
+        results[47][22]="1.847540281090668E+18";
+        results[47][23]="0.001643100951037101";
+        results[47][24]="9786196116419.247";
+        results[47][25]="9796633821214.788";
+        results[47][26]="2.624001946556017E+37";
+        results[47][27]="114207084.9942909";
+        results[47][28]="4.046800251839102E+32";
+        results[47][29]="1949.533553397026";
+        results[47][30]="9.120362371295601E+26";
+        results[47][31]="0.02378696805044898";
+        results[47][32]="1.854217550450959E+22";
+        results[47][33]="1.023520293369992E-7";
+        results[47][34]="4.905438185545787E+17";
+        results[47][35]="1204174859.319065";
+        results[47][36]="2.537414009565692E+41";
+        results[47][37]="10188.26876910955";
+        results[47][38]="1.241826915768028E+36";
+        results[47][39]="0.1085863966072925";
+        results[47][40]="2.251541579928655E+31";
+        results[47][41]="0.000001738449692274594";
+        results[47][42]="8.131156387513517E+25";
+        results[47][43]="3.136103551657476E-11";
+        results[47][44]="2.135990115551220E+21";
+        results[47][45]="275083.7229955457";
+        results[47][46]="1.497718006025124E+45";
+        results[47][47]="1";
+        results[47][48]="1.240200010695352E+40";
+        results[47][49]="0.00004235065836223342";
+        results[47][50]="4.179653170302738E+35";
+        results[47][51]="1.054143957912348E-10";
+        results[47][52]="7.489449188735266E+30";
+        results[47][53]="2.195787505969266E-15";
+        results[47][54]="3.054281909670523E+25";
+        results[47][55]="11.12099868317389";
+        results[47][56]="1.283747866701312E+49";
+        results[47][57]="0.0001115449297820002";
+        results[47][58]="1.026083144375309E+44";
+        results[47][59]="2.188682625866851E-9";
+        results[47][60]="5.299878830006924E+39";
+        results[47][61]="1.011760500325512E-14";
+        results[47][62]="3.789105284242457E+34";
+        results[47][63]="8.605398314572440E-20";
+        results[47][64]="3.959205458913181E+29";
+        results[47][65]="0.0009336568669461997";
+        results[47][66]="8.323652034369472E+52";
+        results[47][67]="3.013856369381733E-8";
+        results[47][68]="1.775730589302118E+48";
+        results[47][69]="1.338612348114789E-13";
+        results[47][70]="1.303792527901410E+43";
+        results[47][71]="8.180650204466976E-19";
+        results[47][72]="3.177780730489156E+38";
+        results[47][73]="1.550144275515960E-23";
+        results[47][74]="8.875172141979778E+32";
+        results[48][0]="5.762422338848205E-15";
+        results[48][1]="1.267088153400481E-20";
+        results[48][2]="2.842936621692024E-25";
+        results[48][3]="3.315174183018531E-30";
+        results[48][4]="2.313886238094478E-35";
+        results[48][5]="7.219181503001472E-20";
+        results[48][6]="4.486390757373126E-11";
+        results[48][7]="6.923150035938593E-25";
+        results[48][8]="6.613785107035720E-17";
+        results[48][9]="6.453365150275192E-30";
+        results[48][10]="2.355196305223146E-21";
+        results[48][11]="7.820284410257130E-35";
+        results[48][12]="1.050051394418058E-26";
+        results[48][13]="9.839240149597593E-40";
+        results[48][14]="7.911476094054727E-32";
+        results[48][15]="8.498873738599392E-24";
+        results[48][16]="9.763511150087314E-8";
+        results[48][17]="1.005868841707006E-28";
+        results[48][18]="7.662524110309441E-13";
+        results[48][19]="6.483290719429564E-34";
+        results[48][20]="2.593058426931717E-17";
+        results[48][21]="1.208812115230884E-38";
+        results[48][22]="1.489711550683502E-22";
+        results[48][23]="1.324867712358631E-43";
+        results[48][24]="7.890820861170891E-28";
+        results[48][25]="7.899237007522711E-28";
+        results[48][26]="0.002115789327468880";
+        results[48][27]="9.208763426010420E-33";
+        results[48][28]="3.263022268134115E-8";
+        results[48][29]="1.571950924515769E-37";
+        results[48][30]="7.353944761040615E-14";
+        results[48][31]="1.917994504540616E-42";
+        results[48][32]="1.495095576891135E-18";
+        results[48][33]="8.252864735875365E-48";
+        results[48][34]="3.955360541236747E-23";
+        results[48][35]="9.709521439561277E-32";
+        results[48][36]="20.45971607549835";
+        results[48][37]="8.215020707343183E-37";
+        results[48][38]="0.0001001311808626548";
+        results[48][39]="8.755555206487259E-42";
+        results[48][40]="1.815466505814869E-9";
+        results[48][41]="1.401749457573287E-46";
+        results[48][42]="6.556326654887352E-15";
+        results[48][43]="2.528707889543666E-51";
+        results[48][44]="1.722294869481269E-19";
+        results[48][45]="2.218059350292316E-35";
+        results[48][46]="120764.2310199132";
+        results[48][47]="8.063215540849113E-41";
+        results[48][48]="1";
+        results[48][49]="3.414824866715520E-45";
+        results[48][50]="0.00003370144439814430";
+        results[48][51]="8.499789943731035E-51";
+        results[48][52]="6.038904309100998E-10";
+        results[48][53]="1.770510794253370E-55";
+        results[48][54]="2.462733336018967E-15";
+        results[48][55]="8.967100941193022E-40";
+        results[48][56]="1035113574.931792";
+        results[48][57]="8.994108113211472E-45";
+        results[48][58]="8273.529555930313";
+        results[48][59]="1.764781976287603E-49";
+        results[48][60]="0.4273406534672904";
+        results[48][61]="8.158042989841942E-55";
+        results[48][62]="0.000003055237261381728";
+        results[48][63]="6.938718142525727E-60";
+        results[48][64]="3.192392698572340E-11";
+        results[48][65]="7.528276559381090E-44";
+        results[48][66]="6711540044014.826";
+        results[48][67]="2.430137351548587E-48";
+        results[48][68]="143180984.8402199";
+        results[48][69]="1.079351988849169E-53";
+        results[48][70]="1051.276017301760";
+        results[48][71]="6.596234586290859E-59";
+        results[48][72]="0.02562313097149101";
+        results[48][73]="1.249914741289858E-63";
+        results[48][74]="7.156242594292246E-8";
+        results[49][0]="1.687472290311238E+30";
+        results[49][1]="3.710550915072856E+24";
+        results[49][2]="8.325277964917845E+19";
+        results[49][3]="970818215402995.0";
+        results[49][4]="6776002660.189255";
+        results[49][5]="2.114070789798686E+25";
+        results[49][6]="1.313798198291870E+34";
+        results[49][7]="2.027380702131727E+20";
+        results[49][8]="1.936786033011718E+28";
+        results[49][9]="1889808526690925";
+        results[49][10]="6.896975385705340E+23";
+        results[49][11]="22900982379.74620";
+        results[49][12]="3.074978762902205E+18";
+        results[49][13]="288133.0824752154";
+        results[49][14]="23168028823874.12";
+        results[49][15]="2.488816870650781E+21";
+        results[49][16]="2.859154284968690E+37";
+        results[49][17]="2.945594228012286E+16";
+        results[49][18]="2.243899587646931E+32";
+        results[49][19]="189857195390.0929";
+        results[49][20]="7.593532693891262E+27";
+        results[49][21]="3539894.906509671";
+        results[49][22]="4.362483022786321E+22";
+        results[49][23]="38.79753030008030";
+        results[49][24]="2.310754187742728E+17";
+        results[49][25]="2.313218778660363E+17";
+        results[49][26]="6.195894108923685E+41";
+        results[49][27]="2696701525096.859";
+        results[49][28]="9.555460076266186E+36";
+        results[49][29]="46033134.51994738";
+        results[49][30]="2.153534968284877E+31";
+        results[49][31]="561.6670193647148";
+        results[49][32]="4.378249647482396E+26";
+        results[49][33]="0.002416775400787454";
+        results[49][34]="1.158290892101044E+22";
+        results[49][35]="28433438956710.49";
+        results[49][36]="5.991439348740924E+45";
+        results[49][37]="240569312.5704755";
+        results[49][38]="2.932249376494788E+40";
+        results[49][39]="2563.983673607429";
+        results[49][40]="5.316426395714516E+35";
+        results[49][41]="0.04104894137430629";
+        results[49][42]="1.919959854688953E+30";
+        results[49][43]="7.405088074035996E-7";
+        results[49][44]="5.043581843006266E+25";
+        results[49][45]="6495382448.194808";
+        results[49][46]="3.536469240253245E+49";
+        results[49][47]="23612.38381341809";
+        results[49][48]="2.928407865794388E+44";
+        results[49][49]="1";
+        results[49][50]="9.869157486415798E+39";
+        results[49][51]="0.000002489085172882200";
+        results[49][52]="1.768437487955098E+35";
+        results[49][53]="5.184777736365438E-11";
+        results[49][54]="7.211887672551995E+29";
+        results[49][55]="262593.2892956190";
+        results[49][56]="3.031234734820807E+53";
+        results[49][57]="2.633841694453359";
+        results[49][58]="2.422826902946868E+48";
+        results[49][59]="0.00005168001420772782";
+        results[49][60]="1.251427730987327E+44";
+        results[49][61]="2.389007726094191E-10";
+        results[49][62]="8.946980828098355E+38";
+        results[49][63]="2.031939678710256E-15";
+        results[49][64]="9.348627889203813E+33";
+        results[49][65]="22.04586429236709";
+        results[49][66]="1.965412665648703E+57";
+        results[49][67]="0.0007116433335235624";
+        results[49][68]="4.192923222382870E+52";
+        results[49][69]="3.160782854106722E-9";
+        results[49][70]="3.078564958187471E+47";
+        results[49][71]="1.931646524711914E-14";
+        results[49][72]="7.503497828319405E+42";
+        results[49][73]="3.660260159965578E-19";
+        results[49][74]="2.095639710265825E+37";
+        results[50][0]="1.709844323220016E-10";
+        results[50][1]="3.759744355260485E-16";
+        results[50][2]="8.435652158126978E-21";
+        results[50][3]="9.836890501942623E-26";
+        results[50][4]="6.865836997247178E-31";
+        results[50][5]="2.142098545603874E-15";
+        results[50][6]="0.000001331216165209868";
+        results[50][7]="2.054259145142100E-20";
+        results[50][8]="1.962463397384800E-12";
+        results[50][9]="1.914863076500820E-25";
+        results[50][10]="6.988413545126361E-17";
+        results[50][11]="2.320459716168051E-30";
+        results[50][12]="3.115745966294182E-22";
+        results[50][13]="2.919530698256769E-35";
+        results[50][14]="2.347518403243974E-27";
+        results[50][15]="2.521812904573124E-19";
+        results[50][16]="0.002897060148147514";
+        results[50][17]="2.984646087638879E-24";
+        results[50][18]="2.273648577130825E-8";
+        results[50][19]="1.923742686763465E-29";
+        results[50][20]="7.694205614150171E-13";
+        results[50][21]="3.586825837344361E-34";
+        results[50][22]="4.420319595457841E-18";
+        results[50][23]="3.931189704235886E-39";
+        results[50][24]="2.341389516707296E-23";
+        results[50][25]="2.343886782477983E-23";
+        results[50][26]="62.78037530003851";
+        results[50][27]="2.732453635286172E-28";
+        results[50][28]="0.0009682143677835323";
+        results[50][29]="4.664342886746792E-33";
+        results[50][30]="2.182085929066454E-9";
+        results[50][31]="5.691134427004636E-38";
+        results[50][32]="4.436295249628704E-14";
+        results[50][33]="2.448816329168904E-43";
+        results[50][34]="1.173647186900553E-18";
+        results[50][35]="2.881040149156310E-27";
+        results[50][36]="607087.2166127371";
+        results[50][37]="2.437587128400801E-32";
+        results[50][38]="2.971124313834108";
+        results[50][39]="2.597976247857604E-37";
+        results[50][40]="0.00005386910081262968";
+        results[50][41]="4.159315669124470E-42";
+        results[50][42]="1.945414142323337E-10";
+        results[50][43]="7.503262648537709E-47";
+        results[50][44]="5.110448232230970E-15";
+        results[50][45]="6.581496401425599E-31";
+        results[50][46]="3583354754.568408";
+        results[50][47]="2.392543015543006E-36";
+        results[50][48]="29672.31873465527";
+        results[50][49]="1.013257718682096E-40";
+        results[50][50]="1";
+        results[50][51]="2.522084763880048E-46";
+        results[50][52]="0.00001791882934677280";
+        results[50][53]="5.253516061023365E-51";
+        results[50][54]="7.307500850481565E-11";
+        results[50][55]="2.660746772529066E-35";
+        results[50][56]="30714219921944.59";
+        results[50][57]="2.668760426691597E-40";
+        results[50][58]="245494806.0441551";
+        results[50][59]="5.236517329758060E-45";
+        results[50][60]="12680.18807795731";
+        results[50][61]="2.420680518456101E-50";
+        results[50][62]="0.09065597382971390";
+        results[50][63]="2.058878563349585E-55";
+        results[50][64]="9.472569367822474E-7";
+        results[50][65]="2.233814215925896E-39";
+        results[50][66]="1.991469553864102E+17";
+        results[50][67]="7.210781006414067E-44";
+        results[50][68]="4248511818920.849";
+        results[50][69]="3.202687624001662E-49";
+        results[50][70]="31193797.06347679";
+        results[50][71]="1.957255750929793E-54";
+        results[50][72]="760.2977091658982";
+        results[50][73]="3.708786859469685E-59";
+        results[50][74]="0.002123423112003558";
+        results[51][0]="6.779487936755711E+35";
+        results[51][1]="1.490728784815458E+30";
+        results[51][2]="3.344713975889266E+25";
+        results[51][3]="3.900301307403033E+20";
+        results[51][4]="2722286378148756";
+        results[51][5]="8.493364601705167E+30";
+        results[51][6]="5.278237211829022E+39";
+        results[51][7]="8.145083680620504E+25";
+        results[51][8]="7.781115946181321E+33";
+        results[51][9]="7.592381921196569E+20";
+        results[51][10]="2.770887658182901E+29";
+        results[51][11]="9200561969210697";
+        results[51][12]="1.235385111125618E+24";
+        results[51][13]="115758627151.1858";
+        results[51][14]="9.307848954420085E+18";
+        results[51][15]="9.998922084971854E+26";
+        results[51][16]="1.148676757275435E+43";
+        results[51][17]="1.183404352773304E+22";
+        results[51][18]="9.014957029568579E+37";
+        results[51][19]="7.627589343206385E+16";
+        results[51][20]="3.050732364091198E+33";
+        results[51][21]="1422167045577.915";
+        results[51][22]="1.752645136580379E+28";
+        results[51][23]="15587064.16428300";
+        results[51][24]="9.283548079903686E+22";
+        results[51][25]="9.293449673246033E+22";
+        results[51][26]="2.489225429658254E+47";
+        results[51][27]="1.083410706261310E+18";
+        results[51][28]="3.838944597143528E+42";
+        results[51][29]="18493997321370.88";
+        results[51][30]="8.651913529303709E+36";
+        results[51][31]="225651988.7241708";
+        results[51][32]="1.758979441596474E+32";
+        results[51][33]="970.9492576298560";
+        results[51][34]="4.653480341774795E+27";
+        results[51][35]="1.142324869654275E+19";
+        results[51][36]="2.407084905737968E+51";
+        results[51][37]="96649690895033.44";
+        results[51][38]="1.178043004892208E+46";
+        results[51][39]="1030090774.530830";
+        results[51][40]="2.135895731345520E+41";
+        results[51][41]="16491.57763724665";
+        results[51][42]="7.713516096621809E+35";
+        results[51][43]="0.2975023978573374";
+        results[51][44]="2.026279332645786E+31";
+        results[51][45]="2609546076992446";
+        results[51][46]="1.420790770352885E+55";
+        results[51][47]="9486370362.359466";
+        results[51][48]="1.176499662485828E+50";
+        results[51][49]="401754.0303139023";
+        results[51][50]="3.964973795970168E+45";
+        results[51][51]="1";
+        results[51][52]="7.104768881441538E+40";
+        results[51][53]="0.00002083005351866606";
+        results[51][54]="2.897404938618912E+35";
+        results[51][55]="105497912307.8994";
+        results[51][56]="1.217810771541752E+59";
+        results[51][57]="1058156.515955435";
+        results[51][58]="9.733804730118538E+53";
+        results[51][59]="20.76265399463438";
+        results[51][60]="5.027661345707404E+49";
+        results[51][61]="0.00009597934824093921";
+        results[51][62]="3.594485606829729E+44";
+        results[51][63]="8.163399552765810E-10";
+        results[51][64]="3.755848932392581E+39";
+        results[51][65]="8857014.831211825";
+        results[51][66]="7.896124596543564E+62";
+        results[51][67]="285.9055773891117";
+        results[51][68]="1.684523803389072E+58";
+        results[51][69]="0.001269857250584455";
+        results[51][70]="1.236825879534966E+53";
+        results[51][71]="7.760467764448543E-9";
+        results[51][72]="3.014560493978934E+48";
+        results[51][73]="1.470524271263579E-13";
+        results[51][74]="8.419316996851535E+42";
+        results[52][0]="0.000009542165339768479";
+        results[52][1]="2.098208695724657E-11";
+        results[52][2]="4.707702715884311E-16";
+        results[52][3]="5.489694840870986E-21";
+        results[52][4]="3.831632560574457E-26";
+        results[52][5]="1.195445586399130E-10";
+        results[52][6]="0.07429146957357580";
+        results[52][7]="1.146424861461206E-15";
+        results[52][8]="1.095196209197808E-7";
+        results[52][9]="1.068631794769388E-20";
+        results[52][10]="3.900039120795011E-12";
+        results[52][11]="1.294983992124446E-25";
+        results[52][12]="1.738811116505963E-17";
+        results[52][13]="1.629308835837862E-30";
+        results[52][14]="1.310084692372364E-22";
+        results[52][15]="1.407353603167891E-14";
+        results[52][16]="161.6768647148971";
+        results[52][17]="1.665647922572809E-19";
+        results[52][18]="0.001268859998122764";
+        results[52][19]="1.073587258148610E-24";
+        results[52][20]="4.293922033213574E-8";
+        results[52][21]="2.001707682980056E-29";
+        results[52][22]="2.466857354302527E-13";
+        results[52][23]="2.193887573879874E-34";
+        results[52][24]="1.306664331355432E-18";
+        results[52][25]="1.308057985886294E-18";
+        results[52][26]="3503598.035624204";
+        results[52][27]="1.524906333112822E-23";
+        results[52][28]="54.03334944745757";
+        results[52][29]="2.603039962310287E-28";
+        results[52][30]="0.0001217761432311118";
+        results[52][31]="3.176063746613903E-33";
+        results[52][32]="2.475772922312967E-9";
+        results[52][33]="1.366616245837476E-38";
+        results[52][34]="6.549798338873787E-14";
+        results[52][35]="1.607828331528359E-22";
+        results[52][36]="33879848111.95684";
+        results[52][37]="1.360349541383301E-27";
+        results[52][38]="165810.1796906287";
+        results[52][39]="1.449858245525120E-32";
+        results[52][40]="3.006284605435543";
+        results[52][41]="2.321198326426144E-37";
+        results[52][42]="0.00001085681494407283";
+        results[52][43]="4.187362077807307E-42";
+        results[52][44]="2.851998941075561E-10";
+        results[52][45]="3.672949986886802E-26";
+        results[52][46]="199977056827865.5";
+        results[52][47]="1.335211675518248E-31";
+        results[52][48]="1655929534.258291";
+        results[52][49]="5.654709351113861E-36";
+        results[52][50]="55807.21712605078";
+        results[52][51]="1.407505320281584E-41";
+        results[52][52]="1";
+        results[52][53]="2.931841114927259E-46";
+        results[52][54]="0.000004078112866116254";
+        results[52][55]="1.484888728519684E-30";
+        results[52][56]="1.714075140041236E+18";
+        results[52][57]="1.489360925897899E-35";
+        results[52][58]="13700381944223.89";
+        results[52][59]="2.922354596061357E-40";
+        results[52][60]="707646009.2657238";
+        results[52][61]="1.350914432862808E-45";
+        results[52][62]="5059.257615288420";
+        results[52][63]="1.149002830210218E-50";
+        results[52][64]="0.05286377354516463";
+        results[52][65]="1.246629549674354E-34";
+        results[52][66]="1.111383737924134E+22";
+        results[52][67]="4.024136212733528E-39";
+        results[52][68]="2.370976215411088E+17";
+        results[52][69]="1.787330836195764E-44";
+        results[52][70]="1740839005707.414";
+        results[52][71]="1.092289966633505E-49";
+        results[52][72]="42430099.33586029";
+        results[52][73]="2.069770735406687E-54";
+        results[52][74]="118.5023346620570";
+        results[53][0]="3.254666595398102E+40";
+        results[53][1]="7.156624842464271E+34";
+        results[53][2]="1.605715497990454E+30";
+        results[53][3]="1.872439407756647E+25";
+        results[53][4]="1.306903208726412E+20";
+        results[53][5]="4.077456927364187E+35";
+        results[53][6]="2.533952784662378E+44";
+        results[53][7]="3.910255762579582E+30";
+        results[53][8]="3.735523741793833E+38";
+        results[53][9]="3.644917145504665E+25";
+        results[53][10]="1.330235496370605E+34";
+        results[53][11]="4.416965112915320E+20";
+        results[53][12]="5.930782222996091E+28";
+        results[53][13]="5557288993398558";
+        results[53][14]="4.468470974440470E+23";
+        results[53][15]="4.800238307602860E+31";
+        results[53][16]="5.514516591357251E+47";
+        results[53][17]="5.681235296456829E+26";
+        results[53][18]="4.327860714083221E+42";
+        results[53][19]="3.661819369005083E+21";
+        results[53][20]="1.464582105541592E+38";
+        results[53][21]="6.827476675964822E+16";
+        results[53][22]="8.414021284245927E+32";
+        results[53][23]="748296885090.3456";
+        results[53][24]="4.456804718040974E+27";
+        results[53][25]="4.461558231196124E+27";
+        results[53][26]="1.195016338977540E+52";
+        results[53][27]="5.201190219172758E+22";
+        results[53][28]="1.842983549563809E+47";
+        results[53][29]="8.878516468907865E+17";
+        results[53][30]="4.153572395553678E+41";
+        results[53][31]="10833000910053.42";
+        results[53][32]="8.444430735716701E+36";
+        results[53][33]="46612902.68696511";
+        results[53][34]="2.234022268644081E+32";
+        results[53][35]="5.484022730093443E+23";
+        results[53][36]="1.155582679411242E+56";
+        results[53][37]="4.639915630001839E+18";
+        results[53][38]="5.655496774583657E+50";
+        results[53][39]="49452142482867.52";
+        results[53][40]="1.025391379542793E+46";
+        results[53][41]="791720367.9994558";
+        results[53][42]="3.703070704887838E+40";
+        results[53][43]="14282.36358541959";
+        results[53][44]="9.727672234879347E+35";
+        results[53][45]="1.252779343391509E+20";
+        results[53][46]="6.820869514711989E+59";
+        results[53][47]="455417474269022.8";
+        results[53][48]="5.648087564592924E+54";
+        results[53][49]="19287229864.95862";
+        results[53][50]="1.903487090139787E+50";
+        results[53][51]="48007.55788283925";
+        results[53][52]="3.410826033199997E+45";
+        results[53][53]="1";
+        results[53][54]="1.390973353007717E+40";
+        results[53][55]="5064697131640181";
+        results[53][56]="5.846412110513578E+63";
+        results[53][57]="50799510188.83404";
+        results[53][58]="4.672961940014202E+58";
+        results[53][59]="996764.3134487737";
+        results[53][60]="2.413657430693617E+54";
+        results[53][61]="4.607734116234075";
+        results[53][62]="1.725624758289108E+49";
+        results[53][63]="0.00003919048765501487";
+        results[53][64]="1.803091350210368E+44";
+        results[53][65]="425203652178.5674";
+        results[53][66]="3.790736586186758E+67";
+        results[53][67]="13725628.55553436";
+        results[53][68]="8.086987399622141E+62";
+        results[53][69]="60.96274546037631";
+        results[53][70]="5.937699000276846E+57";
+        results[53][71]="0.0003725611053996715";
+        results[53][72]="1.447216874060142E+53";
+        results[53][73]="7.059627907080629E-9";
+        results[53][74]="4.041908480603224E+47";
+        results[54][0]="2.339848271255880";
+        results[54][1]="0.000005145048125465107";
+        results[54][2]="1.154382644727447E-10";
+        results[54][3]="1.346136073496915E-15";
+        results[54][4]="9.395602050179328E-21";
+        results[54][5]="0.00002931369546761954";
+        results[54][6]="18217.11953851009";
+        results[54][7]="2.811165112634539E-10";
+        results[54][8]="0.02685546587730432";
+        results[54][9]="2.620407599917871E-15";
+        results[54][10]="9.563342773563720E-7";
+        results[54][11]="3.175449122274317E-20";
+        results[54][12]="4.263764083022794E-12";
+        results[54][13]="3.995251944533639E-25";
+        results[54][14]="3.212477769454207E-17";
+        results[54][15]="3.450992283369952E-9";
+        results[54][16]="39645019.65068670";
+        results[54][17]="4.084359548780881E-14";
+        results[54][18]="311.1390095809556";
+        results[54][19]="2.632558963898978E-19";
+        results[54][20]="0.01052918880419032";
+        results[54][21]="4.908416585552623E-24";
+        results[54][22]="6.049016874444212E-8";
+        results[54][23]="5.379663697167850E-29";
+        results[54][24]="3.204090652350726E-13";
+        results[54][25]="3.207508052939222E-13";
+        results[54][26]="859122381024.4411";
+        results[54][27]="3.739245045871056E-18";
+        results[54][28]="13249596.37493202";
+        results[54][29]="6.382952232485079E-23";
+        results[54][30]="29.86090557789883";
+        results[54][31]="7.788072206149096E-28";
+        results[54][32]="0.0006070878868712484";
+        results[54][33]="3.351099615688073E-33";
+        results[54][34]="1.606085597408052E-8";
+        results[54][35]="3.942579286824783E-17";
+        results[54][36]="8307726937489580";
+        results[54][37]="3.335732938354928E-22";
+        results[54][38]="40658555840.44592";
+        results[54][39]="3.555218536425345E-27";
+        results[54][40]="737175.4299430523";
+        results[54][41]="5.691844249118863E-32";
+        results[54][42]="2.662215416909782";
+        results[54][43]="1.026789158436190E-36";
+        results[54][44]="0.00006993428173045223";
+        results[54][45]="9.006494198343990E-21";
+        results[54][46]="4.903666558358682E+19";
+        results[54][47]="3.274092011067419E-26";
+        results[54][48]="406052894714338.1";
+        results[54][49]="1.386599522072340E-30";
+        results[54][50]="13684569053.92081";
+        results[54][51]="3.451364311115807E-36";
+        results[54][52]="245211.4575613350";
+        results[54][53]="7.189210331295627E-41";
+        results[54][54]="1";
+        results[54][55]="3.641117294367092E-25";
+        results[54][56]="4.203108634591608E+23";
+        results[54][57]="3.652083634743231E-30";
+        results[54][58]="3.359490625690135E+18";
+        results[54][59]="7.165948300112717E-35";
+        results[54][60]="173522909369510.1";
+        results[54][61]="3.312596971229334E-40";
+        results[54][62]="1240587934.023157";
+        results[54][63]="2.817486587379466E-45";
+        results[54][64]="12962.80296320216";
+        results[54][65]="3.056878489146789E-29";
+        results[54][66]="2.725240262863416E+27";
+        results[54][67]="9.867643061497388E-34";
+        results[54][68]="5.813905336242105E+22";
+        results[54][69]="4.382739994878830E-39";
+        results[54][70]="4.268736699691402E+17";
+        results[54][71]="2.678420147978238E-44";
+        results[54][72]="10404346502618.53";
+        results[54][73]="5.075314988468698E-49";
+        results[54][74]="29058130.20690411";
+        results[55][0]="6.426182081186150E+24";
+        results[55][1]="1.413041028209840E+19";
+        results[55][2]="317040773861723.4";
+        results[55][3]="3697041222.976872";
+        results[55][4]="25804.17297930660";
+        results[55][5]="8.050741873371843E+19";
+        results[55][6]="5.003167452664180E+28";
+        results[55][7]="772061124475030.9";
+        results[55][8]="7.375611304488999E+22";
+        results[55][9]="7196712953.937829";
+        results[55][10]="2.626485773572434E+18";
+        results[55][11]="87210.84396777946";
+        results[55][12]="11710043204647.52";
+        results[55][13]="1.097259885232042";
+        results[55][14]="88227802.34034201";
+        results[55][15]="9477838818070297";
+        results[55][16]="1.088814680922766E+32";
+        results[55][17]="112173248444.9072";
+        results[55][18]="8.545152062590683E+26";
+        results[55][19]="723008.5578324046";
+        results[55][20]="2.891746668111807E+22";
+        results[55][21]="13.48052311620413";
+        results[55][22]="1.661307885852018E+17";
+        results[55][23]="0.0001477476077326687";
+        results[55][24]="879974577393.4671";
+        results[55][25]="880913135619.4773";
+        results[55][26]="2.359502074688797E+36";
+        results[55][27]="10269499.01244810";
+        results[55][28]="3.638882052887863E+31";
+        results[55][29]="175.3020217821514";
+        results[55][30]="8.201028191015562E+25";
+        results[55][31]="0.002138923735908606";
+        results[55][32]="1.667312085250398E+21";
+        results[55][33]="9.203492622641725E-9";
+        results[55][34]="4.410969127231112E+16";
+        results[55][35]="108279381.5218219";
+        results[55][36]="2.281642217442943E+40";
+        results[55][37]="916.1289430349850";
+        results[55][38]="1.116650537551916E+35";
+        results[55][39]="0.009764086814575751";
+        results[55][40]="2.024585780533582E+30";
+        results[55][41]="1.563213648163519E-7";
+        results[55][42]="7.311534349712662E+24";
+        results[55][43]="2.819983745167070E-12";
+        results[55][44]="1.920681924711475E+20";
+        results[55][45]="24735.52338530067";
+        results[55][46]="1.346747759525569E+44";
+        results[55][47]="0.08991998187294129";
+        results[55][48]="1.115187624805477E+39";
+        results[55][49]="0.000003808170432239159";
+        results[55][50]="3.758343373088038E+34";
+        results[55][51]="9.478860558694889E-12";
+        results[55][52]="6.734511352893900E+29";
+        results[55][53]="1.974451727335874E-16";
+        results[55][54]="2.746409739524259E+24";
+        results[55][55]="1";
+        results[55][56]="1.154345849032090E+48";
+        results[55][57]="0.00001003011806401597";
+        results[55][58]="9.226537774235836E+42";
+        results[55][59]="1.968063020435687E-10";
+        results[55][60]="4.765650083230079E+38";
+        results[55][61]="9.097748584902804E-16";
+        results[55][62]="3.407162784737478E+33";
+        results[55][63]="7.737972604557934E-21";
+        results[55][64]="3.560116830967234E+28";
+        results[55][65]="0.00008395440855134944";
+        results[55][66]="7.484626400471738E+51";
+        results[55][67]="2.710059101024540E-9";
+        results[55][68]="1.596736624012738E+47";
+        results[55][69]="1.203679980773772E-14";
+        results[55][70]="1.172370004749711E+42";
+        results[55][71]="7.356039180945439E-20";
+        results[55][72]="2.857459856817670E+37";
+        results[55][73]="1.393889451548389E-24";
+        results[55][74]="7.980553181260552E+31";
+        results[56][0]="5.566946930657264E-24";
+        results[56][1]="1.224105435467771E-29";
+        results[56][2]="2.746497283526938E-34";
+        results[56][3]="3.202715395976701E-39";
+        results[56][4]="2.235393578184839E-44";
+        results[56][5]="6.974289273983464E-29";
+        results[56][6]="4.334201449989442E-20";
+        results[56][7]="6.688299915682963E-34";
+        results[56][8]="6.389429399060419E-26";
+        results[56][9]="6.234451278160885E-39";
+        results[56][10]="2.275302307167926E-30";
+        results[56][11]="7.555001305796269E-44";
+        results[56][12]="1.014431092247293E-35";
+        results[56][13]="9.505469146461484E-49";
+        results[56][14]="7.643099545454276E-41";
+        results[56][15]="8.210571230465625E-33";
+        results[56][16]="9.432309059158727E-17";
+        results[56][17]="9.717473193927414E-38";
+        results[56][18]="7.402592619669160E-22";
+        results[56][19]="6.263361699083869E-43";
+        results[56][20]="2.505095566061517E-26";
+        results[56][21]="1.167806262525866E-47";
+        results[56][22]="1.439176904603599E-31";
+        results[56][23]="1.279924970982950E-52";
+        results[56][24]="7.623144988404633E-37";
+        results[56][25]="7.631275638562877E-37";
+        results[56][26]="2.044016597510373E-12";
+        results[56][27]="8.896379729748234E-42";
+        results[56][28]="3.152332601134258E-17";
+        results[56][29]="1.518626518466200E-46";
+        results[56][30]="7.104481033905097E-23";
+        results[56][31]="1.852931456982391E-51";
+        results[56][32]="1.444378291521926E-27";
+        results[56][33]="7.972907452613771E-57";
+        results[56][34]="3.821185072852883E-32";
+        results[56][35]="9.380150811181354E-41";
+        results[56][36]="1.976567264789908E-8";
+        results[56][37]="7.936347185751581E-46";
+        results[56][38]="9.673448719794147E-14";
+        results[56][39]="8.458545437455212E-51";
+        results[56][40]="1.753881457824083E-18";
+        results[56][41]="1.354198700046664E-55";
+        results[56][42]="6.333920077629528E-24";
+        results[56][43]="2.442927955717607E-60";
+        results[56][44]="1.663870430445044E-28";
+        results[56][45]="2.142817371937639E-44";
+        results[56][46]="0.0001166676140131492";
+        results[56][47]="7.789691620439270E-50";
+        results[56][48]="9.660775630982277E-10";
+        results[56][49]="3.298985685643760E-54";
+        results[56][50]="3.255820927704967E-14";
+        results[56][51]="8.211456355686501E-60";
+        results[56][52]="5.834049958719679E-19";
+        results[56][53]="1.710450753551403E-64";
+        results[56][54]="2.379191419821972E-24";
+        results[56][55]="8.662915025323579E-49";
+        results[56][56]="1";
+        results[56][57]="8.689006048253338E-54";
+        results[56][58]="0.000007992871271614319";
+        results[56][59]="1.704916271051602E-58";
+        results[56][60]="4.128442171144841E-10";
+        results[56][61]="7.881302291277083E-64";
+        results[56][62]="2.951596168162563E-15";
+        results[56][63]="6.703339914156715E-69";
+        results[56][64]="3.084098958689342E-20";
+        results[56][65]="7.272899072816394E-53";
+        results[56][66]="6483.868250358015";
+        results[56][67]="2.347701170578040E-57";
+        results[56][68]="0.1383239369164440";
+        results[56][69]="1.042737739112631E-62";
+        results[56][70]="0.000001015614172938495";
+        results[56][71]="6.372474234748120E-68";
+        results[56][72]="2.475393192788476E-11";
+        results[56][73]="1.207514587345858E-72";
+        results[56][74]="6.913485406433592E-17";
+        results[57][0]="6.406885781574903E+29";
+        results[57][1]="1.408798001370755E+24";
+        results[57][2]="3.160887756637065E+19";
+        results[57][3]="368593988563342.1";
+        results[57][4]="2572668917.216598";
+        results[57][5]="8.026567406274776E+24";
+        results[57][6]="4.988144128246639E+33";
+        results[57][7]="7.697428081578381E+19";
+        results[57][8]="7.353464094256007E+27";
+        results[57][9]="717510293299212.7";
+        results[57][10]="2.618599060159830E+23";
+        results[57][11]="8694897050.180986";
+        results[57][12]="1.167488072414467E+18";
+        results[57][13]="109396.5074218388";
+        results[57][14]="8796287518974.268";
+        results[57][15]="9.449379117552936E+20";
+        results[57][16]="1.085545228853283E+37";
+        results[57][17]="1.118364188028252E+16";
+        results[57][18]="8.519492999037822E+31";
+        results[57][19]="72083753473.07911";
+        results[57][20]="2.883063439189447E+27";
+        results[57][21]="1344004.430472940";
+        results[57][22]="1.656319372562645E+22";
+        results[57][23]="14.73039567328003";
+        results[57][24]="8.773322225891460E+16";
+        results[57][25]="8.782679625475591E+16";
+        results[57][26]="2.352417049958506E+41";
+        results[57][27]="1023866214425.824";
+        results[57][28]="3.627955353728795E+36";
+        results[57][29]="17477563.14166077";
+        results[57][30]="8.176402449775297E+30";
+        results[57][31]="213.2501055578004";
+        results[57][32]="1.662305542775258E+26";
+        results[57][33]="0.0009175856718636401";
+        results[57][34]="4.397724033833556E+21";
+        results[57][35]="10795424423794.65";
+        results[57][36]="2.274790987384843E+45";
+        results[57][37]="91337802.52514549";
+        results[57][38]="1.113297501011488E+40";
+        results[57][39]="973.4767579262472";
+        results[57][40]="2.018506429946206E+35";
+        results[57][41]="0.01558519688588414";
+        results[57][42]="7.289579547366953E+29";
+        results[57][43]="2.811516003270229E-7";
+        results[57][44]="1.914914572742777E+25";
+        results[57][45]="2466124847.925947";
+        results[57][46]="1.342703795638417E+49";
+        results[57][47]="8964.997350882443";
+        results[57][48]="1.111838981044821E+44";
+        results[57][49]="0.3796735400255500";
+        results[57][50]="3.747057959937145E+39";
+        results[57][51]="9.450397790132930E-7";
+        results[57][52]="6.714289213658032E+34";
+        results[57][53]="1.968522917411524E-11";
+        results[57][54]="2.738162922904441E+29";
+        results[57][55]="99699.72373382105";
+        results[57][56]="1.150879622417825E+53";
+        results[57][57]="1";
+        results[57][58]="9.198832671109769E+47";
+        results[57][59]="0.00001962153394281874";
+        results[57][60]="4.751339967101001E+43";
+        results[57][61]="9.070430205145709E-11";
+        results[57][62]="3.396931883544830E+38";
+        results[57][63]="7.714737309343017E-16";
+        results[57][64]="3.549426645075597E+33";
+        results[57][65]="8.370231338805882";
+        results[57][66]="7.462151843778957E+56";
+        results[57][67]="0.0002701921436744741";
+        results[57][68]="1.591942002897441E+52";
+        results[57][69]="1.200065615470761E-9";
+        results[57][70]="1.168849655873646E+47";
+        results[57][71]="7.333950741154235E-15";
+        results[57][72]="2.848879583052055E+42";
+        results[57][73]="1.389703932348617E-19";
+        results[57][74]="7.956589474147437E+36";
+        results[58][0]="6.964890014465238E-19";
+        results[58][1]="1.531496497153692E-24";
+        results[58][2]="3.436183556816159E-29";
+        results[58][3]="4.006964815448415E-34";
+        results[58][4]="2.796734117467348E-39";
+        results[58][5]="8.725636929437082E-24";
+        results[58][6]="5.422583828394453E-15";
+        results[58][7]="8.367831394252054E-29";
+        results[58][8]="7.993910050511732E-21";
+        results[58][9]="7.800014620905704E-34";
+        results[58][10]="2.846664521232035E-25";
+        results[58][11]="9.452174380221672E-39";
+        results[58][12]="1.269169811166505E-30";
+        results[58][13]="1.189243367426543E-43";
+        results[58][14]="9.562395396755339E-36";
+        results[58][15]="1.027236765294149E-27";
+        results[58][16]="1.180090200208327E-11";
+        results[58][17]="1.215767508784710E-32";
+        results[58][18]="9.261493608634160E-17";
+        results[58][19]="7.836184878051788E-38";
+        results[58][20]="3.134162281529605E-21";
+        results[58][21]="1.461059765435212E-42";
+        results[58][22]="1.800575607560021E-26";
+        results[58][23]="1.601333147361503E-47";
+        results[58][24]="9.537429953960697E-32";
+        results[58][25]="9.547602331172774E-32";
+        results[58][26]="2.557299533609959E-7";
+        results[58][27]="1.113039285562200E-36";
+        results[58][28]="3.943930152271277E-12";
+        results[58][29]="1.899976199866263E-41";
+        results[58][30]="8.888521774566507E-18";
+        results[58][31]="2.318230075295776E-46";
+        results[58][32]="1.807083140011844E-22";
+        results[58][33]="9.975022969440973E-52";
+        results[58][34]="4.780741416946553E-27";
+        results[58][35]="1.173564604311067E-35";
+        results[58][36]="0.002472912671331814";
+        results[58][37]="9.929281876384678E-41";
+        results[58][38]="1.210259541417636E-8";
+        results[58][39]="1.058261186752084E-45";
+        results[58][40]="2.194307149738259E-13";
+        results[58][41]="1.694258113296445E-50";
+        results[58][42]="7.924461513753702E-19";
+        results[58][43]="3.056383460588637E-55";
+        results[58][44]="2.081693016068045E-23";
+        results[58][45]="2.680910650403675E-39";
+        results[58][46]="14.59645852517100";
+        results[58][47]="9.745798919724109E-45";
+        results[58][48]="0.0001208673992447659";
+        results[58][49]="4.127410005162593E-49";
+        results[58][50]="4.073405935195787E-9";
+        results[58][51]="1.027347504625585E-54";
+        results[58][52]="7.299066581290476E-14";
+        results[58][53]="2.139970350361897E-59";
+        results[58][54]="2.976641733579987E-19";
+        results[58][55]="1.083830169527293E-43";
+        results[58][56]="125111.4857249578";
+        results[58][57]="1.087094456170119E-48";
+        results[58][58]="1";
+        results[58][59]="2.133046077079208E-53";
+        results[58][60]="0.00005165155337615015";
+        results[58][61]="9.860414391091898E-59";
+        results[58][62]="3.692785818589105E-10";
+        results[58][63]="8.386648159795576E-64";
+        results[58][64]="3.858562028444187E-15";
+        results[58][65]="9.099232085277269E-48";
+        results[58][66]="811206390.0471738";
+        results[58][67]="2.937243814892411E-52";
+        results[58][68]="17305.91325894164";
+        results[58][69]="1.304584677618646E-57";
+        results[58][70]="0.1270649980996593";
+        results[58][71]="7.972697192533506E-63";
+        results[58][72]="0.000003097001201032130";
+        results[58][73]="1.510739440573996E-67";
+        results[58][74]="8.649564307367203E-12";
+        results[59][0]="3.265231862221327E+34";
+        results[59][1]="7.179856607930284E+28";
+        results[59][2]="1.610927955912394E+24";
+        results[59][3]="1.878517702221967E+19";
+        results[59][4]="131114566512174.5";
+        results[59][5]="4.090693128103987E+29";
+        results[59][6]="2.542178477372429E+38";
+        results[59][7]="3.922949196535957E+24";
+        results[59][8]="3.747649962375796E+32";
+        results[59][9]="3.656749239841227E+19";
+        results[59][10]="1.334553693809554E+28";
+        results[59][11]="443130342180164.7";
+        results[59][12]="5.950034670157650E+22";
+        results[59][13]="5575329010.496484";
+        results[59][14]="4.482976481149991E+17";
+        results[59][15]="4.815820794179703E+25";
+        results[59][16]="5.532417761102616E+41";
+        results[59][17]="5.699677666829715E+20";
+        results[59][18]="4.341909773142817E+36";
+        results[59][19]="3673706331174018";
+        results[59][20]="1.469336417627336E+32";
+        results[59][21]="68496399638.76680";
+        results[59][22]="8.441334797725325E+26";
+        results[59][23]="750725.9991093196";
+        results[59][24]="4.471272353863239E+21";
+        results[59][25]="4.476041297826234E+21";
+        results[59][26]="1.198895589312202E+46";
+        results[59][27]="5.218074271917703E+16";
+        results[59][28]="1.848966224710778E+41";
+        results[59][29]="890733782210.6083";
+        results[59][30]="4.167055681580780E+35";
+        results[59][31]="10868166.89150073";
+        results[59][32]="8.471842964059609E+30";
+        results[59][33]="46.76421703510423";
+        results[59][34]="2.241274329850788E+26";
+        results[59][35]="5.501824910965054E+17";
+        results[59][36]="1.159333920586464E+50";
+        results[59][37]="4654977678672.980";
+        results[59][38]="5.673855592818941E+44";
+        results[59][39]="49612673.54342235";
+        results[59][40]="1.028719994995578E+40";
+        results[59][41]="794.2904429033256";
+        results[59][42]="3.715091576739267E+34";
+        results[59][43]="0.01432872685419792";
+        results[59][44]="9.759250109207765E+29";
+        results[59][45]="125684610342532.4";
+        results[59][46]="6.843011354521704E+53";
+        results[59][47]="456895846.0132791";
+        results[59][48]="5.666422331123308E+48";
+        results[59][49]="19349.83988163200";
+        results[59][50]="1.909666171287554E+44";
+        results[59][51]="0.04816339954701486";
+        results[59][52]="3.421898223260666E+39";
+        results[59][53]="0.000001003246190205216";
+        results[59][54]="1.395488717081967E+34";
+        results[59][55]="5081138101.861297";
+        results[59][56]="5.865390676242383E+57";
+        results[59][57]="50964.41506123880";
+        results[59][58]="4.688131263293223E+52";
+        results[59][59]="1";
+        results[59][60]="2.421492621803881E+48";
+        results[59][61]="0.000004622691697590433";
+        results[59][62]="1.731226464477344E+43";
+        results[59][63]="3.931770743217822E-11";
+        results[59][64]="1.808944527690531E+38";
+        results[59][65]="426583.9441094915";
+        results[59][66]="3.803042038163392E+61";
+        results[59][67]="13.77018455651177";
+        results[59][68]="8.113239298908500E+56";
+        results[59][69]="0.00006116064212757286";
+        results[59][70]="5.956973900613066E+51";
+        results[59][71]="3.737705096108644E-10";
+        results[59][72]="1.451914815301539E+47";
+        results[59][73]="7.082544802045064E-15";
+        results[59][74]="4.055029284323338E+41";
+        results[60][0]="1.348437667255375E-14";
+        results[60][1]="2.965054092372860E-20";
+        results[60][2]="6.652623846164517E-25";
+        results[60][3]="7.757685013397121E-30";
+        results[60][4]="5.414617634246651E-35";
+        results[60][5]="1.689327108110964E-19";
+        results[60][6]="1.049839447984212E-10";
+        results[60][7]="1.620054160484525E-24";
+        results[60][8]="1.547661111428041E-16";
+        results[60][9]="1.510121982992930E-29";
+        results[60][10]="5.511285402205287E-21";
+        results[60][11]="1.829988405457360E-34";
+        results[60][12]="2.457176460742298E-26";
+        results[60][13]="2.302434853732143E-39";
+        results[60][14]="1.851327747515669E-31";
+        results[60][15]="1.988781940038362E-23";
+        results[60][16]="2.284713862551959E-7";
+        results[60][17]="2.353786922788046E-28";
+        results[60][18]="1.793071650950697E-12";
+        results[60][19]="1.517124726334002E-33";
+        results[60][20]="6.067895497169673E-17";
+        results[60][21]="2.828685044174972E-38";
+        results[60][22]="3.486004756618662E-22";
+        results[60][23]="3.100261352644838E-43";
+        results[60][24]="1.846494312475907E-27";
+        results[60][25]="1.848463735764689E-27";
+        results[60][26]="0.004951060261414672";
+        results[60][27]="2.154899926158156E-32";
+        results[60][28]="7.635646741444116E-8";
+        results[60][29]="3.678449292763319E-37";
+        results[60][30]="1.720862431732932E-13";
+        results[60][31]="4.488209789961917E-42";
+        results[60][32]="3.498603666092752E-18";
+        results[60][33]="1.931214516782934E-47";
+        results[60][34]="9.255755353824531E-23";
+        results[60][35]="2.272079981340803E-31";
+        results[60][36]="47.87683060222675";
+        results[60][37]="1.922358811568574E-36";
+        results[60][38]="0.0002343123221491472";
+        results[60][39]="2.048846777260200E-41";
+        results[60][40]="4.248288785737604E-9";
+        results[60][41]="3.280168751088831E-46";
+        results[60][42]="1.534215526112867E-14";
+        results[60][43]="5.917311795698881E-51";
+        results[60][44]="4.030262170254993E-19";
+        results[60][45]="5.190377588220942E-35";
+        results[60][46]="282594.7637793763";
+        results[60][47]="1.886835590161396E-40";
+        results[60][48]="2.340053519098534";
+        results[60][49]="7.990872946462834E-45";
+        results[60][50]="0.00007886318356258115";
+        results[60][51]="1.988996336942614E-50";
+        results[60][52]="1.413135928001109E-9";
+        results[60][53]="4.143090014694539E-55";
+        results[60][54]="5.762927809552455E-15";
+        results[60][55]="2.098349611355051E-39";
+        results[60][56]="2422221163.685803";
+        results[60][57]="2.104669434147318E-44";
+        results[60][58]="19360.50195272046";
+        results[60][59]="4.129684274053472E-49";
+        results[60][60]="1";
+        results[60][61]="1.909025720733676E-54";
+        results[60][62]="0.000007149418705177280";
+        results[60][63]="1.623697180745017E-59";
+        results[60][64]="7.470369768638670E-11";
+        results[60][65]="1.761657005552672E-43";
+        results[60][66]="15705362898567.62";
+        results[60][67]="5.686651461384062E-48";
+        results[60][68]="335051167.4433505";
+        results[60][69]="2.525741419852499E-53";
+        results[60][70]="2460.042143830875";
+        results[60][71]="1.543554195644939E-58";
+        results[60][72]="0.05995949780016016";
+        results[60][73]="2.924867388928466E-63";
+        results[60][74]="1.674599066629639E-7";
+        results[61][0]="7.063486115509977E+39";
+        results[61][1]="1.553176607402299E+34";
+        results[61][2]="3.484826722820572E+29";
+        results[61][3]="4.063688052571492E+24";
+        results[61][4]="2.836325134564299E+19";
+        results[61][5]="8.849158446444201E+34";
+        results[61][6]="5.499346795499110E+43";
+        results[61][7]="8.486287758668364E+29";
+        results[61][8]="8.107073124364424E+37";
+        results[61][9]="7.910432879932915E+24";
+        results[61][10]="2.886962361139478E+33";
+        results[61][11]="9.585980878005454E+19";
+        results[61][12]="1.287136382739755E+28";
+        results[61][13]="1206078487432465";
+        results[61][14]="9.697762200941783E+22";
+        results[61][15]="1.041778493835083E+31";
+        results[61][16]="1.196795746509847E+47";
+        results[61][17]="1.232978108793337E+26";
+        results[61][18]="9.392600798807385E+41";
+        results[61][19]="7.947115169045187E+20";
+        results[61][20]="3.178529985880788E+37";
+        results[61][21]="1.481742762003150E+16";
+        results[61][22]="1.826064844887958E+32";
+        results[61][23]="162400187644.0589";
+        results[61][24]="9.672443343331502E+26";
+        results[61][25]="9.682759722348257E+26";
+        results[61][26]="2.593501076303929E+51";
+        results[61][27]="1.128795648353017E+22";
+        results[61][28]="3.999761060584132E+46";
+        results[61][29]="1.926872567934611E+17";
+        results[61][30]="9.014349115587456E+40";
+        results[61][31]="2351047312362.565";
+        results[61][32]="1.832664499013753E+36";
+        results[61][33]="10116230.99578109";
+        results[61][34]="4.848418359846594E+31";
+        results[61][35]="1.190177773229581E+23";
+        results[61][36]="2.507919620057646E+55";
+        results[61][37]="1.006984238446915E+18";
+        results[61][38]="1.227392169756080E+50";
+        results[61][39]="10732421019831.98";
+        results[61][40]="2.225370113978822E+45";
+        results[61][41]="171824230.3109566";
+        results[61][42]="8.036641462972210E+39";
+        results[61][43]="3099.650115465570";
+        results[61][44]="2.111161796555619E+35";
+        results[61][45]="2.718862051908959E+19";
+        results[61][46]="1.480308833506809E+59";
+        results[61][47]="98837620136215.22";
+        results[61][48]="1.225784175500373E+54";
+        results[61][49]="4185838283.725054";
+        results[61][50]="4.131069723475097E+49";
+        results[61][51]="10418.90800810271";
+        results[61][52]="7.402393339457015E+44";
+        results[61][53]="0.2170264114148377";
+        results[61][54]="3.018779551769291E+39";
+        results[61][55]="1099173043382890";
+        results[61][56]="1.268825839997009E+63";
+        results[61][57]="11024835397.91414";
+        results[61][58]="1.014156160519400E+58";
+        results[61][59]="216324.1819741618";
+        results[61][60]="5.238274105681931E+53";
+        results[61][61]="1";
+        results[61][62]="3.745061487400818E+48";
+        results[61][63]="0.000008505370897365375";
+        results[61][64]="3.913184451892906E+43";
+        results[61][65]="92280422752.79732";
+        results[61][66]="8.226899579190449E+66";
+        results[61][67]="2978823.909820644";
+        results[61][68]="1.755089854497003E+62";
+        results[61][69]="13.23052587726166";
+        results[61][70]="1.288637506091553E+57";
+        results[61][71]="0.00008085559973763583";
+        results[61][72]="3.140842847162717E+52";
+        results[61][73]="1.532125710597750E-9";
+        results[61][74]="8.772008928125169E+46";
+        results[62][0]="1.886080145619249E-9";
+        results[62][1]="4.147265973142270E-15";
+        results[62][2]="9.305125522088941E-20";
+        results[62][3]="1.085079127870824E-24";
+        results[62][4]="7.573507522122931E-30";
+        results[62][5]="2.362887358782933E-14";
+        results[62][6]="0.00001468426303279687";
+        results[62][7]="2.265994239939194E-19";
+        results[62][8]="2.164736988067710E-11";
+        results[62][9]="2.112230441755173E-24";
+        results[62][10]="7.708718190213518E-16";
+        results[62][11]="2.559632441351024E-29";
+        results[62][12]="3.436889853664501E-21";
+        results[62][13]="3.220450429158424E-34";
+        results[62][14]="2.589480101613048E-26";
+        results[62][15]="2.781739358191706E-18";
+        results[62][16]="0.03195663810957770";
+        results[62][17]="3.292277344287504E-23";
+        results[62][18]="2.507996418858833E-7";
+        results[62][19]="2.122025284706531E-28";
+        results[62][20]="8.487257142703900E-12";
+        results[62][21]="3.956524524331703E-33";
+        results[62][22]="4.875927540926171E-17";
+        results[62][23]="4.336382411621481E-38";
+        results[62][24]="2.582719502969886E-22";
+        results[62][25]="2.585474165089977E-22";
+        results[62][26]="692.5122818487806";
+        results[62][27]="3.014091096102228E-27";
+        results[62][28]="0.01068009450322826";
+        results[62][29]="5.145102622258724E-32";
+        results[62][30]="2.406996292561188E-8";
+        results[62][31]="6.277726868495983E-37";
+        results[62][32]="4.893549826028827E-13";
+        results[62][33]="2.701218933204230E-42";
+        results[62][34]="1.294616490585723E-17";
+        results[62][35]="3.177992610357912E-26";
+        results[62][36]="6696604.657880305";
+        results[62][37]="2.688832324474842E-31";
+        results[62][38]="32.77361864111679";
+        results[62][39]="2.865752953840177E-36";
+        results[62][40]="0.0005942145733696068";
+        results[62][41]="4.588021608964494E-41";
+        results[62][42]="2.145930444669381E-9";
+        results[62][43]="8.276633443518753E-46";
+        results[62][44]="5.637188611343273E-14";
+        results[62][45]="7.259859580559060E-30";
+        results[62][46]="39526956726.52857";
+        results[62][47]="2.639145457790906E-35";
+        results[62][48]="327306.8224978871";
+        results[62][49]="1.117695476511428E-39";
+        results[62][50]="11.03071267954583";
+        results[62][51]="2.782039238382100E-45";
+        results[62][52]="0.0001976574580780646";
+        results[62][53]="5.795002622652810E-50";
+        results[62][54]="8.060694228719894E-10";
+        results[62][55]="2.934993316079701E-34";
+        results[62][56]="338799735135353.3";
+        results[62][57]="2.943832947737714E-39";
+        results[62][58]="2707982669.793906";
+        results[62][59]="5.776251810602371E-44";
+        results[62][60]="139871.5114105495";
+        results[62][61]="2.670183128806329E-49";
+        results[62][62]="1";
+        results[62][63]="2.271089787438537E-54";
+        results[62][64]="0.00001044891910335168";
+        results[62][65]="2.464056279536351E-38";
+        results[62][66]="2.196732845873822E+18";
+        results[62][67]="7.954005347687989E-43";
+        results[62][68]="46864113190170.53";
+        results[62][69]="3.532792698269964E-48";
+        results[62][70]="344089812.7912729";
+        results[62][71]="2.158992582889526E-53";
+        results[62][72]="8386.625580725921";
+        results[62][73]="4.091056223648521E-58";
+        results[62][74]="0.02342287024561831";
+        results[63][0]="8.304736149364119E+44";
+        results[63][1]="1.826112730584637E+39";
+        results[63][2]="4.097207241015242E+34";
+        results[63][3]="4.777790529781906E+29";
+        results[63][4]="3.334745972621699E+24";
+        results[63][5]="1.040420053778644E+40";
+        results[63][6]="6.465734254108293E+48";
+        results[63][7]="9.977563425596263E+34";
+        results[63][8]="9.531710283058522E+42";
+        results[63][9]="9.300514904509633E+29";
+        results[63][10]="3.394281561588036E+38";
+        results[63][11]="1.127050306645041E+25";
+        results[63][12]="1.513321874227095E+33";
+        results[63][13]="1.418019862962190E+20";
+        results[63][14]="1.140192746202962E+28";
+        results[63][15]="1.224847812524888E+36";
+        results[63][16]="1.407105887505231E+52";
+        results[63][17]="1.449646492400778E+31";
+        results[63][18]="1.104314075441065E+47";
+        results[63][19]="9.343643287216183E+25";
+        results[63][20]="3.737085688838532E+42";
+        results[63][21]="1.742125981198698E+21";
+        results[63][22]="2.146954985177189E+37";
+        results[63][23]="1.909383959897199E+16";
+        results[63][24]="1.137215938028950E+32";
+        results[63][25]="1.138428863266573E+32";
+        results[63][26]="3.049251005746606E+56";
+        results[63][27]="1.327156289801157E+27";
+        results[63][28]="4.702629795748353E+51";
+        results[63][29]="2.265477415607447E+22";
+        results[63][30]="1.059841978011769E+46";
+        results[63][31]="2.764191404152434E+17";
+        results[63][32]="2.154714381216979E+41";
+        results[63][33]="1189393280769.765";
+        results[63][34]="5.700419674053768E+36";
+        results[63][35]="1.399324953128441E+28";
+        results[63][36]="2.948630518669679E+60";
+        results[63][37]="1.183939243330163E+23";
+        results[63][38]="1.443078949251087E+55";
+        results[63][39]="1.261840447564310E+18";
+        results[63][40]="2.616429243159934E+50";
+        results[63][41]="20201850381878.22";
+        results[63][42]="9.448901829150850E+44";
+        results[63][43]="364434444.1728835";
+        results[63][44]="2.482151362981211E+40";
+        results[63][45]="3.196641374864857E+24";
+        results[63][46]="1.740440071773177E+64";
+        results[63][47]="1.162061259043167E+19";
+        results[63][48]="1.441188385893991E+59";
+        results[63][49]="492140593777240.2";
+        results[63][50]="4.857013025445766E+54";
+        results[63][51]="1224979854.944370";
+        results[63][52]="8.703198753801531E+49";
+        results[63][53]="25516.39593777902";
+        results[63][54]="3.549262681424497E+44";
+        results[63][55]="1.292328173158645E+20";
+        results[63][56]="1.491793662272907E+68";
+        results[63][57]="1296220415423529";
+        results[63][58]="1.192371470635743E+63";
+        results[63][59]="25433832878.60738";
+        results[63][60]="6.158783865974074E+58";
+        results[63][61]="117572.7680858409";
+        results[63][62]="4.403172457253908E+53";
+        results[63][63]="1";
+        results[63][64]="4.600839280395232E+48";
+        results[63][65]="1.084966474317800E+16";
+        results[63][66]="9.672593562896609E+71";
+        results[63][67]="350228572717.9005";
+        results[63][68]="2.063507724325885E+67";
+        results[63][69]="1555549.550621002";
+        results[63][70]="1.515086786504186E+62";
+        results[63][71]="9.506416676394638";
+        results[63][72]="3.692775876635344E+57";
+        results[63][73]="0.0001801362608504635";
+        results[63][74]="1.031349371353387E+52";
+        results[64][0]="0.0001805048088671923";
+        results[64][1]="3.969086115148465E-10";
+        results[64][2]="8.905347462307516E-15";
+        results[64][3]="1.038460645678428E-19";
+        results[64][4]="7.248125329722949E-25";
+        results[64][5]="2.261370133514570E-9";
+        results[64][6]="1.405337995973826";
+        results[64][7]="2.168639854061398E-14";
+        results[64][8]="0.000002071732938743234";
+        results[64][9]="2.021482242194446E-19";
+        results[64][10]="7.377526913516641E-11";
+        results[64][11]="2.449662415828232E-24";
+        results[64][12]="3.289230033910451E-16";
+        results[64][13]="3.082089541802851E-29";
+        results[64][14]="2.478227724801148E-21";
+        results[64][15]="2.662226906608371E-13";
+        results[64][16]="3058.367836279547";
+        results[64][17]="3.150830542109802E-18";
+        results[64][18]="0.02400244842602282";
+        results[64][19]="2.030856267253379E-23";
+        results[64][20]="8.122617333673738E-7";
+        results[64][21]="3.786539531215795E-28";
+        results[64][22]="4.666442043141217E-12";
+        results[64][23]="4.150077504409531E-33";
+        results[64][24]="2.471757583175691E-17";
+        results[64][25]="2.474393896169260E-17";
+        results[64][26]="66275973.14124528";
+        results[64][27]="2.884596068061627E-22";
+        results[64][28]="1022.124336267703";
+        results[64][29]="4.924052498988474E-27";
+        results[64][30]="0.002303584005917990";
+        results[64][31]="6.008015572139217E-32";
+        results[64][32]="4.683307218312307E-8";
+        results[64][33]="2.585165897530746E-37";
+        results[64][34]="1.238995610723459E-12";
+        results[64][35]="3.041455847178024E-21";
+        results[64][36]="640889702718.8438";
+        results[64][37]="2.573311457270591E-26";
+        results[64][38]="3136555.878837656";
+        results[64][39]="2.742631008523106E-31";
+        results[64][40]="56.86852080029998";
+        results[64][41]="4.390905474129667E-36";
+        results[64][42]="0.0002053734384814057";
+        results[64][43]="7.921042704660115E-41";
+        results[64][44]="5.394996894497005E-9";
+        results[64][45]="6.947952710467755E-25";
+        results[64][46]="3782875179294822";
+        results[64][47]="2.525759297863022E-30";
+        results[64][48]="31324467082.23605";
+        results[64][49]="1.069675691290314E-34";
+        results[64][50]="1055679.785673480";
+        results[64][51]="2.662513902983238E-40";
+        results[64][52]="18.91654592432077";
+        results[64][53]="5.546030709333330E-45";
+        results[64][54]="0.00007714380931645150";
+        results[64][55]="2.808896582554887E-29";
+        results[64][56]="3.242438110432659E+19";
+        results[64][57]="2.817356435263650E-34";
+        results[64][58]="259163904228646.2";
+        results[64][59]="5.528085492354452E-39";
+        results[64][60]="13386218232.43738";
+        results[64][61]="2.555463490907705E-44";
+        results[64][62]="95703.67902257296";
+        results[64][63]="2.173516480484612E-49";
+        results[64][64]="1";
+        results[64][65]="2.358192512703023E-33";
+        results[64][66]="2.102354151798515E+23";
+        results[64][67]="7.612275747389602E-38";
+        results[64][68]="4.485068046429608E+18";
+        results[64][69]="3.381012584485181E-43";
+        results[64][70]="32930660998313.20";
+        results[64][71]="2.066235331649750E-48";
+        results[64][72]="802630922.6602931";
+        results[64][73]="3.915291316913575E-53";
+        results[64][74]="2241.654855774030";
+        results[65][0]="7.654371214175933E+28";
+        results[65][1]="1.683105214594628E+23";
+        results[65][2]="3.776344558103940E+18";
+        results[65][3]="44036296446727.19";
+        results[65][4]="307359356.4002524";
+        results[65][5]="9.589421225506852E+23";
+        results[65][6]="5.959386218061519E+32";
+        results[65][7]="9.196195146831527E+18";
+        results[65][8]="8.785257893845823E+26";
+        results[65][9]="85721680113273.25";
+        results[65][10]="3.128466770111285E+22";
+        results[65][11]="1038788140.761402";
+        results[65][12]="1.394809802928366E+17";
+        results[65][13]="13069.71133696832";
+        results[65][14]="1050901362569.648";
+        results[65][15]="1.128926876100059E+20";
+        results[65][16]="1.296911859318036E+36";
+        results[65][17]="1336121001630285";
+        results[65][18]="1.017832441445189E+31";
+        results[65][19]="8611918901.080548";
+        results[65][20]="3.444425037361932E+26";
+        results[65][21]="160569.5680407179";
+        results[65][22]="1.978821499094838E+21";
+        results[65][23]="1.759855262899042";
+        results[65][24]="1.048157675788096E+16";
+        results[65][25]="1.049275613776351E+16";
+        results[65][26]="2.810456431535270E+40";
+        results[65][27]="122322331723.2581";
+        results[65][28]="4.334354938206963E+35";
+        results[65][29]="2088062.137617592";
+        results[65][30]="9.768430666746378E+29";
+        results[65][31]="25.47720569790407";
+        results[65][32]="1.985973237165517E+25";
+        results[65][33]="0.0001096248878581826";
+        results[65][34]="5.254005362366659E+20";
+        results[65][35]="1289740269632.112";
+        results[65][36]="2.717715789811575E+44";
+        results[65][37]="10912219.60636705";
+        results[65][38]="1.330067779429277E+39";
+        results[65][39]="116.3022524136263";
+        results[65][40]="2.411530038110238E+34";
+        results[65][41]="0.001861979227937033";
+        results[65][42]="8.708934379831493E+28";
+        results[65][43]="3.358946592354670E-8";
+        results[65][44]="2.287767799039069E+24";
+        results[65][45]="294630428.7305122";
+        results[65][46]="1.604141798821501E+48";
+        results[65][47]="1071.057296746282";
+        results[65][48]="1.328325270880074E+43";
+        results[65][49]="0.04535998166087906";
+        results[65][50]="4.476648025921479E+38";
+        results[65][51]="1.129048577943026E-7";
+        results[65][52]="8.021629202205431E+33";
+        results[65][53]="2.351814230372703E-12";
+        results[65][54]="3.271310925672783E+28";
+        results[65][55]="11911.22678671919";
+        results[65][56]="1.374967519812914E+52";
+        results[65][57]="0.1194710109580630";
+        results[65][58]="1.098993838851543E+47";
+        results[65][59]="0.000002344204496696504";
+        results[65][60]="5.676473892750065E+42";
+        results[65][61]="1.083653466433309E-11";
+        results[65][62]="4.058348862827780E+37";
+        results[65][63]="9.216874656230971E-17";
+        results[65][64]="4.240535896086675E+32";
+        results[65][65]="1";
+        results[65][66]="8.915108246988459E+55";
+        results[65][67]="0.00003228012855771563";
+        results[65][68]="1.901909204727609E+51";
+        results[65][69]="1.433730522963019E-10";
+        results[65][70]="1.396436500452086E+46";
+        results[65][71]="8.761945093623320E-16";
+        results[65][72]="3.403585238850141E+41";
+        results[65][73]="1.660293337300849E-20";
+        results[65][74]="9.505817882546773E+35";
+        results[66][0]="8.585842148087876E-28";
+        results[66][1]="1.887924597172652E-33";
+        results[66][2]="4.235893108061360E-38";
+        results[66][3]="4.939513377372926E-43";
+        results[66][4]="3.447623381399535E-48";
+        results[66][5]="1.075637104994903E-32";
+        results[66][6]="6.684592102484691E-24";
+        results[66][7]="1.031529275030174E-37";
+        results[66][8]="9.854347979244672E-30";
+        results[66][9]="9.615326896589304E-43";
+        results[66][10]="3.509174183238983E-34";
+        results[66][11]="1.165199694700630E-47";
+        results[66][12]="1.564546121354764E-39";
+        results[66][13]="1.466018243960560E-52";
+        results[66][14]="1.178786991088576E-44";
+        results[66][15]="1.266307536401941E-36";
+        results[66][16]="1.454734842682516E-20";
+        results[66][17]="1.498715399312880E-41";
+        results[66][18]="1.141693867585976E-25";
+        results[66][19]="9.659915126649943E-47";
+        results[66][20]="3.863581845487368E-30";
+        results[66][21]="1.801094990573543E-51";
+        results[66][22]="2.219627002020180E-35";
+        results[66][23]="1.974014464146888E-56";
+        results[66][24]="1.175709421298576E-40";
+        results[66][25]="1.176963402694295E-40";
+        results[66][26]="3.152464730290456E-16";
+        results[66][27]="1.372079040819037E-45";
+        results[66][28]="4.861808536840948E-21";
+        results[66][29]="2.342161283709532E-50";
+        results[66][30]="1.095716439567200E-26";
+        results[66][31]="2.857756181088471E-55";
+        results[66][32]="2.227649044907988E-31";
+        results[66][33]="1.229652908535508E-60";
+        results[66][34]="5.893372482764269E-36";
+        results[66][35]="1.446690532409171E-44";
+        results[66][36]="3.048438352646615E-12";
+        results[66][37]="1.224014258049331E-49";
+        results[66][38]="1.491925552197951E-17";
+        results[66][39]="1.304552330622721E-54";
+        results[66][40]="2.704992436771430E-22";
+        results[66][41]="2.088566034591912E-59";
+        results[66][42]="9.768736552103434E-28";
+        results[66][43]="3.767701411241225E-64";
+        results[66][44]="2.566169401041071E-32";
+        results[66][45]="3.304844097995546E-48";
+        results[66][46]="1.799352015005968E-8";
+        results[66][47]="1.201395728546636E-53";
+        results[66][48]="1.489970995392888E-13";
+        results[66][49]="5.087990005752511E-58";
+        results[66][50]="5.021417465608115E-18";
+        results[66][51]="1.266444048309139E-63";
+        results[66][52]="8.997792264513616E-23";
+        results[66][53]="2.638009730467547E-68";
+        results[66][54]="3.669401240055428E-28";
+        results[66][55]="1.336072031513787E-52";
+        results[66][56]="0.0001542289203585813";
+        results[66][57]="1.340096021811295E-57";
+        results[66][58]="1.232731906786197E-9";
+        results[66][59]="2.629473957860669E-62";
+        results[66][60]="6.367251788185060E-14";
+        results[66][61]="1.215524743403277E-67";
+        results[66][62]="4.552214903502375E-19";
+        results[66][63]="1.033848877756975E-72";
+        results[66][64]="4.756572526776819E-24";
+        results[66][65]="1.121691371877399E-56";
+        results[66][66]="1";
+        results[66][67]="3.620834168628286E-61";
+        results[66][68]="0.00002133355145037165";
+        results[66][69]="1.608203157204890E-66";
+        results[66][70]="1.566370773931775E-10";
+        results[66][71]="9.828198212380789E-72";
+        results[66][72]="3.817772195867480E-15";
+        results[66][73]="1.862336711235894E-76";
+        results[66][74]="1.066259390149060E-20";
+        results[67][0]="2.371233187776874E+33";
+        results[67][1]="5.214059825026099E+27";
+        results[67][2]="1.169866641439169E+23";
+        results[67][3]="1.364192102518798E+18";
+        results[67][4]="9521627395340.313";
+        results[67][5]="2.970688672556348E+28";
+        results[67][6]="1.846146990216091E+37";
+        results[67][7]="2.848871909041218E+23";
+        results[67][8]="2.721568434319621E+31";
+        results[67][9]="2.655555722462696E+18";
+        results[67][10]="9.691618063161386E+26";
+        results[67][11]="32180421428746.45";
+        results[67][12]="4.320954919477782E+21";
+        results[67][13]="404884116.6663938";
+        results[67][14]="3.255567463712780E+16";
+        results[67][15]="3.497281226998773E+24";
+        results[67][16]="4.017678730737416E+40";
+        results[67][17]="4.139143991453913E+19";
+        results[67][18]="3.153123878132466E+35";
+        results[67][19]="266787007544990.6";
+        results[67][20]="1.067041920605562E+31";
+        results[67][21]="4974254292.501521";
+        results[67][22]="6.130153712234388E+25";
+        results[67][23]="54518.22348701272";
+        results[67][24]="3.247067848301876E+20";
+        results[67][25]="3.250531087260965E+20";
+        results[67][26]="8.706459847302905E+44";
+        results[67][27]="3789400389299890";
+        results[67][28]="1.342731622167273E+40";
+        results[67][29]="64685682211.09210";
+        results[67][30]="3.026143668938864E+34";
+        results[67][31]="789253.5388250330";
+        results[67][32]="6.152308946399247E+29";
+        results[67][33]="3.396048676267737";
+        results[67][34]="1.627628388459699E+25";
+        results[67][35]="3.995461998628989E+16";
+        results[67][36]="8.419160366577858E+48";
+        results[67][37]="338047588219.9918";
+        results[67][38]="4.120391828834159E+43";
+        results[67][39]="3602905.490468613";
+        results[67][40]="7.470633314853486E+38";
+        results[67][41]="57.68190249329044";
+        results[67][42]="2.697924317203462E+33";
+        results[67][43]="0.001040561714724588";
+        results[67][44]="7.087232614171990E+28";
+        results[67][45]="9127300351475.501";
+        results[67][46]="4.969440552113530E+52";
+        results[67][47]="33180081.51148695";
+        results[67][48]="4.114993744541877E+47";
+        results[67][49]="1405.198296524041";
+        results[67][50]="1.386812328803897E+43";
+        results[67][51]="0.003497658244837316";
+        results[67][52]="2.485005345583759E+38";
+        results[67][53]="7.285640842996488E-8";
+        results[67][54]="1.013413227219280E+33";
+        results[67][55]="368995642.7968486";
+        results[67][56]="4.259485885734702E+56";
+        results[67][57]="3701.069862359855";
+        results[67][58]="3.404552236793557E+51";
+        results[67][59]="0.07262066792903739";
+        results[67][60]="1.758504115806338E+47";
+        results[67][61]="3.357029587090330E-7";
+        results[67][62]="1.257228221867707E+42";
+        results[67][63]="2.855278175163260E-12";
+        results[67][64]="1.313667598474634E+37";
+        results[67][65]="30978.81094903443";
+        results[67][66]="2.761794529736332E+60";
+        results[67][67]="1";
+        results[67][68]="5.891888569548503E+55";
+        results[67][69]="0.000004441526682273164";
+        results[67][70]="4.325994234983640E+50";
+        results[67][71]="2.714346406011766E-11";
+        results[67][72]="1.054390236632627E+46";
+        results[67][73]="5.143391341618445E-16";
+        results[67][74]="2.944789350993672E+40";
+        results[68][0]="4.024572358737908E-23";
+        results[68][1]="8.849556069295544E-29";
+        results[68][2]="1.985554593624666E-33";
+        results[68][3]="2.315373222720905E-38";
+        results[68][4]="1.616056937083241E-43";
+        results[68][5]="5.041997379091630E-28";
+        results[68][6]="3.133370511719575E-19";
+        results[68][7]="4.835244040026928E-33";
+        results[68][8]="4.619178387700187E-25";
+        results[68][9]="4.507138400728770E-38";
+        results[68][10]="1.644908580459467E-29";
+        results[68][11]="5.461817725994849E-43";
+        results[68][12]="7.333734962012186E-35";
+        results[68][13]="6.871890258736175E-48";
+        results[68][14]="5.525507526633783E-40";
+        results[68][15]="5.935755888314043E-32";
+        results[68][16]="6.818999856009313E-16";
+        results[68][17]="7.025156607418828E-37";
+        results[68][18]="5.351635287926178E-21";
+        results[68][19]="4.528038919877851E-42";
+        results[68][20]="1.811035473617807E-25";
+        results[68][21]="8.442546449724692E-47";
+        results[68][22]="1.040439519497590E-30";
+        results[68][23]="9.253098194827277E-52";
+        results[68][24]="5.511081565737588E-36";
+        results[68][25]="5.516959543432190E-36";
+        results[68][26]="1.477702733941909E-11";
+        results[68][27]="6.431554746104564E-41";
+        results[68][28]="2.278949451126784E-16";
+        results[68][29]="1.097876876786368E-45";
+        results[68][30]="5.136118297584773E-22";
+        results[68][31]="1.339559513912385E-50";
+        results[68][32]="1.044199813655115E-26";
+        results[68][33]="5.763939076885797E-56";
+        results[68][34]="2.762490106944477E-31";
+        results[68][35]="6.781292537131541E-40";
+        results[68][36]="1.428940867974192E-7";
+        results[68][37]="5.737508172967645E-45";
+        results[68][38]="6.993329524475215E-13";
+        results[68][39]="6.115026528318585E-50";
+        results[68][40]="1.267952240893443E-17";
+        results[68][41]="9.790053191333628E-55";
+        results[68][42]="4.579048441525779E-23";
+        results[68][43]="1.766091979577825E-59";
+        results[68][44]="1.202879608212802E-27";
+        results[68][45]="1.549129832266147E-43";
+        results[68][46]="0.0008434376335284867";
+        results[68][47]="5.631484899930744E-49";
+        results[68][48]="6.984167633124823E-9";
+        results[68][49]="2.384970930690432E-53";
+        results[68][50]="2.353765371550753E-13";
+        results[68][51]="5.936395781336616E-59";
+        results[68][52]="4.217672001516121E-18";
+        results[68][53]="1.236554418332251E-63";
+        results[68][54]="1.720014245444119E-23";
+        results[68][55]="6.262773615644344E-48";
+        results[68][56]="7.229406726646745";
+        results[68][57]="6.281635877311693E-53";
+        results[68][58]="0.00005778371733623009";
+        results[68][59]="1.232553315830994E-57";
+        results[68][60]="2.984618760264661E-9";
+        results[68][61]="5.697713979929495E-63";
+        results[68][62]="2.133828919245919E-14";
+        results[68][63]="4.846117066640417E-68";
+        results[68][64]="2.229620575759295E-19";
+        results[68][65]="5.257874547924172E-52";
+        results[68][66]="46874.52074382950";
+        results[68][67]="1.697248663473332E-56";
+        results[68][68]="1";
+        results[68][69]="7.538375225269271E-62";
+        results[68][70]="0.000007342287933519324";
+        results[68][71]="4.606920809807113E-67";
+        results[68][72]="1.789562419904057E-10";
+        results[68][73]="8.729614080282214E-72";
+        results[68][74]="4.998039790184512E-16";
+        results[69][0]="5.338779562533849E+38";
+        results[69][1]="1.173934144274364E+33";
+        results[69][2]="2.633929108448886E+28";
+        results[69][3]="3.071448625904928E+23";
+        results[69][4]="2.143773543755267E+18";
+        results[69][5]="6.688440450921611E+33";
+        results[69][6]="4.156559494698874E+42";
+        results[69][7]="6.414172677182188E+28";
+        results[69][8]="6.127551693389194E+36";
+        results[69][9]="5.978925519149620E+23";
+        results[69][10]="2.182046570122424E+32";
+        results[69][11]="7.245351369200056E+18";
+        results[69][12]="9.728535318099962E+26";
+        results[69][13]="91158771663435.09";
+        results[69][14]="7.329838806791966E+21";
+        results[69][15]="7.874052048267494E+29";
+        results[69][16]="9.045715624703119E+45";
+        results[69][17]="9.319191997593739E+24";
+        results[69][18]="7.099189318657215E+40";
+        results[69][19]="6.006651015061551E+19";
+        results[69][20]="2.402421502642987E+36";
+        results[69][21]="1119942454101324";
+        results[69][22]="1.380190675584772E+31";
+        results[69][23]="12274658554.81710";
+        results[69][24]="7.310702108942491E+25";
+        results[69][25]="7.318499515570511E+25";
+        results[69][26]="1.960240356553922E+50";
+        results[69][27]="8.531751941115174E+20";
+        results[69][28]="3.023130824647137E+45";
+        results[69][29]="1.456383960705739E+16";
+        results[69][30]="6.813296160116931E+39";
+        results[69][31]="177698704811.3589";
+        results[69][32]="1.385178878009241E+35";
+        results[69][33]="764612.9178559042";
+        results[69][34]="3.664569651142300E+30";
+        results[69][35]="8.995695139186061E+21";
+        results[69][36]="1.895555508014859E+54";
+        results[69][37]="7.611067373954845E+16";
+        results[69][38]="9.276971914362904E+48";
+        results[69][39]="811186276297.3776";
+        results[69][40]="1.681996720782961E+44";
+        results[69][41]="12986953.95065576";
+        results[69][42]="6.074317481804861E+38";
+        results[69][43]="234.2801899350586";
+        results[69][44]="1.595674893152901E+34";
+        results[69][45]="2.054991673899878E+18";
+        results[69][46]="1.118858651001097E+58";
+        results[69][47]="7470422646319.768";
+        results[69][48]="9.264818245864578E+52";
+        results[69][49]="316377317.3157802";
+        results[69][50]="3.122377569719179E+48";
+        results[69][51]="787.4900895669555";
+        results[69][52]="5.594935082798914E+43";
+        results[69][53]="0.01640346071109881";
+        results[69][54]="2.281677674624746E+38";
+        results[69][55]="83078560412474.54";
+        results[69][56]="9.590139135570173E+61";
+        results[69][57]="833287769.5256027";
+        results[69][58]="7.665274758748302E+56";
+        results[69][59]="16350.38425388234";
+        results[69][60]="3.959233483443444E+52";
+        results[69][61]="0.07558278554283523";
+        results[69][62]="2.830621792469476E+47";
+        results[69][63]="6.428596244978392E-7";
+        results[69][64]="2.957693812169788E+42";
+        results[69][65]="6974811402.726853";
+        results[69][66]="6.218119865763931E+65";
+        results[69][67]="225147.8087458437";
+        results[69][68]="1.326545800808529E+61";
+        results[69][69]="1";
+        results[69][70]="9.739881226537191E+55";
+        results[69][71]="0.000006111291454907054";
+        results[69][72]="2.373936513408476E+51";
+        results[69][73]="1.158023290087738E-10";
+        results[69][74]="6.630128695943206E+45";
+        results[70][0]="5.481360027253576E-18";
+        results[70][1]="1.205285893092693E-23";
+        results[70][2]="2.704272308036475E-28";
+        results[70][3]="3.153476469031765E-33";
+        results[70][4]="2.201026371773776E-38";
+        results[70][5]="6.867065722216763E-23";
+        results[70][6]="4.267566922042078E-14";
+        results[70][7]="6.585473198283149E-28";
+        results[70][8]="6.291197552485674E-20";
+        results[70][9]="6.138602083626537E-33";
+        results[70][10]="2.240321539216762E-24";
+        results[70][11]="7.438849818270307E-38";
+        results[70][12]="9.988351081318820E-30";
+        results[70][13]="9.359330934659115E-43";
+        results[70][14]="7.525593625126715E-35";
+        results[70][15]="8.084340933043336E-27";
+        results[70][16]="9.287295619229160E-11";
+        results[70][17]="9.568075606715566E-32";
+        results[70][18]="7.288784281388184E-16";
+        results[70][19]="6.167068032304013E-37";
+        results[70][20]="2.466581929251223E-20";
+        results[70][21]="1.149852270323317E-41";
+        results[70][22]="1.417050827913914E-25";
+        results[70][23]="1.260247252438118E-46";
+        results[70][24]="7.505945851807534E-31";
+        results[70][25]="7.513951500384414E-31";
+        results[70][26]="0.000002012591643533670";
+        results[70][27]="8.759605730991504E-36";
+        results[70][28]="3.103868265262150E-11";
+        results[70][29]="1.495278973975256E-40";
+        results[70][30]="6.995255898556019E-17";
+        results[70][31]="1.824444268654967E-45";
+        results[70][32]="1.422172248091892E-21";
+        results[70][33]="7.850331026344006E-51";
+        results[70][34]="3.762437719628292E-26";
+        results[70][35]="9.235939258352015E-35";
+        results[70][36]="0.01946179284866684";
+        results[70][37]="7.814332841367511E-40";
+        results[70][38]="9.524727970077244E-8";
+        results[70][39]="8.328502755118070E-45";
+        results[70][40]="1.726917075949764E-12";
+        results[70][41]="1.333379088368309E-49";
+        results[70][42]="6.236541637956356E-18";
+        results[70][43]="2.405370091133565E-54";
+        results[70][44]="1.638289888797966E-22";
+        results[70][45]="2.109873443118451E-38";
+        results[70][46]="114.8739522564880";
+        results[70][47]="7.669931976137371E-44";
+        results[70][48]="0.0009512249718838192";
+        results[70][49]="3.248266687829637E-48";
+        results[70][50]="3.205765550006891E-8";
+        results[70][51]="8.085212450243923E-54";
+        results[70][52]="5.744356581633671E-13";
+        results[70][53]="1.684154080483660E-58";
+        results[70][54]="2.342613448311986E-18";
+        results[70][55]="8.529730340665701E-43";
+        results[70][56]="984625.8812110530";
+        results[70][57]="8.555420237109612E-48";
+        results[70][58]="7.869987919219759";
+        results[70][59]="1.678704685775246E-52";
+        results[70][60]="0.0004064971010792362";
+        results[70][61]="7.760134213639389E-58";
+        results[70][62]="2.906217978056231E-9";
+        results[70][63]="6.600281970033780E-63";
+        results[70][64]="3.036683654941584E-14";
+        results[70][65]="7.161084658530892E-47";
+        results[70][66]="6384184489.665129";
+        results[70][67]="2.311607333900624E-51";
+        results[70][68]="136197.3282789357";
+        results[70][69]="1.026706565245795E-56";
+        results[70][70]="1";
+        results[70][71]="6.274503058883598E-62";
+        results[70][72]="0.00002437336203793195";
+        results[70][73]="1.188950114640616E-66";
+        results[70][74]="6.807196660549431E-11";
+        results[71][0]="8.735926934473208E+43";
+        results[71][1]="1.920926457094031E+38";
+        results[71][2]="4.309938624075892E+33";
+        results[71][3]="5.025858525269176E+28";
+        results[71][4]="3.507889550962140E+23";
+        results[71][5]="1.094439775990578E+39";
+        results[71][6]="6.801442093489699E+47";
+        results[71][7]="1.049560919244317E+34";
+        results[71][8]="1.002660687778045E+42";
+        results[71][9]="9.783407587849290E+28";
+        results[71][10]="3.570516291397545E+37";
+        results[71][11]="1.185567964261042E+24";
+        results[71][12]="1.591895164857249E+32";
+        results[71][13]="1.491644971215360E+19";
+        results[71][14]="1.199392773340319E+27";
+        results[71][15]="1.288443221267910E+35";
+        results[71][16]="1.480164330477132E+51";
+        results[71][17]="1.524913689087910E+30";
+        results[71][18]="1.161651243610208E+46";
+        results[71][19]="9.828775242323811E+24";
+        results[71][20]="3.931119175659616E+41";
+        results[71][21]="1.832579025832696E+20";
+        results[71][22]="2.258427184775404E+36";
+        results[71][23]="2008521217714331";
+        results[71][24]="1.196261406101385E+31";
+        results[71][25]="1.197537307714907E+31";
+        results[71][26]="3.207571379990312E+55";
+        results[71][27]="1.396063664131845E+26";
+        results[71][28]="4.946795365519211E+50";
+        results[71][29]="2.383103426586433E+21";
+        results[71][30]="1.114870107307058E+45";
+        results[71][31]="2.907711178930534E+16";
+        results[71][32]="2.266589456958420E+40";
+        results[71][33]="125114785229.5539";
+        results[71][34]="5.996391561721113E+35";
+        results[71][35]="1.471979401663617E+27";
+        results[71][36]="3.101726569582645E+59";
+        results[71][37]="1.245410635397457E+22";
+        results[71][38]="1.518005152072067E+54";
+        results[71][39]="1.327356553492530E+17";
+        results[71][40]="2.752277048466415E+49";
+        results[71][41]="2125075206522.494";
+        results[71][42]="9.939498920359126E+43";
+        results[71][43]="38335627.03787325";
+        results[71][44]="2.611027317101128E+39";
+        results[71][45]="3.362614414748335E+23";
+        results[71][46]="1.830805582186251E+63";
+        results[71][47]="1.222396722761668E+18";
+        results[71][48]="1.516016428642984E+58";
+        results[71][49]="51769305988793.17";
+        results[71][50]="5.109194337658483E+53";
+        results[71][51]="128858211.9471067";
+        results[71][52]="9.155078143600022E+48";
+        results[71][53]="2684.123451177847";
+        results[71][54]="3.733544196771496E+43";
+        results[71][55]="1.359427234414859E+19";
+        results[71][56]="1.569249185107967E+67";
+        results[71][57]="136352156606197.4";
+        results[71][58]="1.254280672965365E+62";
+        results[71][59]="2675438469.025040";
+        results[71][60]="6.478554512834406E+57";
+        results[71][61]="12367.72719817611";
+        results[71][62]="4.631789881656898E+52";
+        results[71][63]="0.1051921069779213";
+        results[71][64]="4.839719777715578E+47";
+        results[71][65]="1141299094338961";
+        results[71][66]="1.017480496822173E+71";
+        results[71][67]="36841281488.06609";
+        results[71][68]="2.170647252870554E+66";
+        results[71][69]="163631.5347383819";
+        results[71][70]="1.593751713267834E+61";
+        results[71][71]="1";
+        results[71][72]="3.884508750605123E+56";
+        results[71][73]="0.00001894891282198470";
+        results[71][74]="1.084898134030173E+51";
+        results[72][0]="2.248914211639332E-13";
+        results[72][1]="4.945094941013564E-19";
+        results[72][2]="1.109519607441867E-23";
+        results[72][3]="1.293820878762663E-28";
+        results[72][4]="9.030458614401850E-34";
+        results[72][5]="2.817447060249479E-18";
+        results[72][6]="1.750914344685201E-9";
+        results[72][7]="2.701914158594232E-23";
+        results[72][8]="2.581177575212958E-15";
+        results[72][9]="2.518570098812429E-28";
+        results[72][10]="9.191680391610227E-20";
+        results[72][11]="3.052040915280100E-33";
+        results[72][12]="4.098060442286985E-25";
+        results[72][13]="3.839983552574039E-38";
+        results[72][14]="3.087630509658344E-30";
+        results[72][15]="3.316875579356586E-22";
+        results[72][16]="0.000003810428616608354";
+        results[72][17]="3.925628147575576E-27";
+        results[72][18]="2.990471429442005E-11";
+        results[72][19]="2.530249221550267E-32";
+        results[72][20]="1.011999052659421E-15";
+        results[72][21]="4.717659666868350E-37";
+        results[72][22]="5.813932545327873E-21";
+        results[72][23]="5.170592593983595E-42";
+        results[72][24]="3.079569343009031E-26";
+        results[72][25]="3.082853932375250E-26";
+        results[72][26]="0.08257341110354408";
+        results[72][27]="3.593925908686312E-31";
+        results[72][28]="0.000001273467427444617";
+        results[72][29]="6.134890097017279E-36";
+        results[72][30]="2.870041436084768E-12";
+        results[72][31]="7.485402571116811E-41";
+        results[72][32]="5.834944911902525E-17";
+        results[72][33]="3.220865063312414E-46";
+        results[72][34]="1.543667924750332E-21";
+        results[72][35]="3.789357924433339E-30";
+        results[72][36]="798.4861841537783";
+        results[72][37]="3.206095584682231E-35";
+        results[72][38]="0.003907843306661606";
+        results[72][39]="3.417051263652724E-40";
+        results[72][40]="7.085264122619546E-8";
+        results[72][41]="5.470640801598023E-45";
+        results[72][42]="2.558753129030992E-13";
+        results[72][43]="9.868848160504565E-50";
+        results[72][44]="6.721640971189435E-18";
+        results[72][45]="8.656472750188841E-34";
+        results[72][46]="4713094.241069868";
+        results[72][47]="3.146850222878877E-39";
+        results[72][48]="39.02723680071055";
+        results[72][49]="1.332711787062614E-43";
+        results[72][50]="0.001315274251052358";
+        results[72][51]="3.317233148902893E-49";
+        results[72][52]="2.356817484881160E-8";
+        results[72][53]="6.909814402554038E-54";
+        results[72][54]="9.611367708181607E-14";
+        results[72][55]="3.499611718478145E-38";
+        results[72][56]="40397622604.49307";
+        results[72][57]="3.510151871454961E-43";
+        results[72][58]="322892.9971569699";
+        results[72][59]="6.887456409020225E-48";
+        results[72][60]="16.67792487743833";
+        results[72][61]="3.183858755949381E-53";
+        results[72][62]="0.0001192374680822991";
+        results[72][63]="2.707989960417380E-58";
+        results[72][64]="1.245902658080421E-9";
+        results[72][65]="2.938078319842043E-42";
+        results[72][66]="261932862595217.9";
+        results[72][67]="9.484154587713828E-47";
+        results[72][68]="5587958200.718210";
+        results[72][69]="4.212412566013441E-52";
+        results[72][70]="41028.39807014366";
+        results[72][71]="2.574328091922103E-57";
+        results[72][72]="1";
+        results[72][73]="4.878071858901815E-62";
+        results[72][74]="0.000002792883743307747";
+        results[73][0]="4.610252322411714E+48";
+        results[73][1]="1.013739666829516E+43";
+        results[73][2]="2.274504434405050E+38";
+        results[73][3]="2.652320253137757E+33";
+        results[73][4]="1.851235257619769E+28";
+        results[73][5]="5.775739148057081E+43";
+        results[73][6]="3.589357425085942E+52";
+        results[73][7]="5.538897820177879E+38";
+        results[73][8]="5.291388995229049E+46";
+        results[73][9]="5.163044275816442E+33";
+        results[73][10]="1.884285565584005E+42";
+        results[73][11]="6.256654275624378E+28";
+        results[73][12]="8.400984161003253E+36";
+        results[73][13]="7.871929040091104E+23";
+        results[73][14]="6.329612598928488E+31";
+        results[73][15]="6.799562768440446E+39";
+        results[73][16]="7.811341708004652E+55";
+        results[73][17]="8.047499629206652E+34";
+        results[73][18]="6.130437426797644E+50";
+        results[73][19]="5.186986364157197E+29";
+        results[73][20]="2.074588242919507E+46";
+        results[73][21]="9.671156562114322E+24";
+        results[73][22]="1.191850533058106E+41";
+        results[73][23]="1.059966466985920E+20";
+        results[73][24]="6.313087285479891E+35";
+        results[73][25]="6.319820661824533E+35";
+        results[73][26]="1.692746919110240E+60";
+        results[73][27]="7.367513256550102E+30";
+        results[73][28]="2.610595875336918E+55";
+        results[73][29]="1.257646519868694E+26";
+        results[73][30]="5.883557108424581E+49";
+        results[73][31]="1.534500267243291E+21";
+        results[73][32]="1.196158047826734E+45";
+        results[73][33]="6602742141723014";
+        results[73][34]="3.164504274231525E+40";
+        results[73][35]="7.768146993403301E+31";
+        results[73][36]="1.636888933271145E+64";
+        results[73][37]="6.572464853775255E+26";
+        results[73][38]="8.011040877822095E+58";
+        results[73][39]="7.004921949677867E+21";
+        results[73][40]="1.452472273381932E+54";
+        results[73][41]="1.121476058540394E+17";
+        results[73][42]="5.245419098043044E+48";
+        results[73][43]="2023104301445.511";
+        results[73][44]="1.377929880004403E+44";
+        results[73][45]="1.774568518172187E+28";
+        results[73][46]="9.661797483505934E+67";
+        results[73][47]="6.451012436678859E+22";
+        results[73][48]="8.000545692964971E+62";
+        results[73][49]="2.732046237963053E+18";
+        results[73][50]="2.696299458262718E+58";
+        results[73][51]="6800295782542.430";
+        results[73][52]="4.831452986040559E+53";
+        results[73][53]="141650525.0931179";
+        results[73][54]="1.970321058440780E+48";
+        results[73][55]="7.174170081344397E+23";
+        results[73][56]="8.281473453650119E+71";
+        results[73][57]="7.195777292721534E+18";
+        results[73][58]="6.619275125431665E+66";
+        results[73][59]="141192188394099.9";
+        results[73][60]="3.418958424526566E+62";
+        results[73][61]="652687957.0540302";
+        results[73][62]="2.444356531253368E+57";
+        results[73][63]="5551.353154988210";
+        results[73][64]="2.554088365481576E+52";
+        results[73][65]="6.023032060260553E+19";
+        results[73][66]="5.369598279230475E+75";
+        results[73][67]="1944242492124535";
+        results[73][68]="1.145526011577904E+71";
+        results[73][69]="8635404905.580393";
+        results[73][70]="8.410781812340964E+65";
+        results[73][71]="52773.47620913591";
+        results[73][72]="2.049990301342397E+61";
+        results[73][73]="1";
+        results[73][74]="5.725384586557730E+55";
+        results[74][0]="8.052301557585906E-8";
+        results[74][1]="1.770605365462456E-13";
+        results[74][2]="3.972666639277327E-18";
+        results[74][3]="4.632562604379404E-23";
+        results[74][4]="3.233381495395381E-28";
+        results[74][5]="1.008794965777072E-12";
+        results[74][6]="0.0006269198812448631";
+        results[74][7]="9.674280804091849E-18";
+        results[74][8]="9.241980019390084E-10";
+        results[74][9]="9.017812162240471E-23";
+        results[74][10]="3.291107413129942E-14";
+        results[74][11]="1.092791965506384E-27";
+        results[74][12]="1.467322244295588E-19";
+        results[74][13]="1.374917076937174E-32";
+        results[74][14]="1.105534921407618E-24";
+        results[74][15]="1.187616773274011E-16";
+        results[74][16]="1.364334847713883";
+        results[74][17]="1.405582368754908E-21";
+        results[74][18]="0.00001070746835276518";
+        results[74][19]="9.059629594726956E-27";
+        results[74][20]="3.623491507959662E-10";
+        results[74][21]="1.689171516062104E-31";
+        results[74][22]="2.081695150848690E-15";
+        results[74][23]="1.851345444067719E-36";
+        results[74][24]="1.102648597668354E-20";
+        results[74][25]="1.103824654270814E-20";
+        results[74][26]="29565.64565260007";
+        results[74][27]="1.286815434870144E-25";
+        results[74][28]="0.4559686490696489";
+        results[74][29]="2.196614918797670E-30";
+        results[74][30]="0.000001027626532239985";
+        results[74][31]="2.680169766841597E-35";
+        results[74][32]="2.089218688706290E-11";
+        results[74][33]="1.153239933824738E-40";
+        results[74][34]="5.527147087483460E-16";
+        results[74][35]="1.356790426208511E-24";
+        results[74][36]="285900258.4934282";
+        results[74][37]="1.147951679823628E-29";
+        results[74][38]="1399.214455677041";
+        results[74][39]="1.223484963110475E-34";
+        results[74][40]="0.02536899052671676";
+        results[74][41]="1.958778561659312E-39";
+        results[74][42]="9.161688649454979E-8";
+        results[74][43]="3.533569266587664E-44";
+        results[74][44]="2.406702744894305E-12";
+        results[74][45]="3.099474788713032E-28";
+        results[74][46]="1687536852317.355";
+        results[74][47]="1.126738708841461E-33";
+        results[74][48]="13973813.58756047";
+        results[74][49]="4.771812612164872E-38";
+        results[74][50]="470.9377016512027";
+        results[74][51]="1.187744802071186E-43";
+        results[74][52]="0.008438652308849302";
+        results[74][53]="2.474078779366023E-48";
+        results[74][54]="3.441377655339997E-8";
+        results[74][55]="1.253045969730694E-32";
+        results[74][56]="1.446448413805017E+16";
+        results[74][57]="1.256819901603824E-37";
+        results[74][58]="115612759725.7422";
+        results[74][59]="2.466073435932954E-42";
+        results[74][60]="5971578.629938194";
+        results[74][61]="1.139989719793558E-47";
+        results[74][62]="42.69331595631704";
+        results[74][63]="9.696035386027837E-53";
+        results[74][64]="0.0004460990046813902";
+        results[74][65]="1.051987332763925E-36";
+        results[74][66]="9.378580946051059E+19";
+        results[74][67]="3.395828634270787E-41";
+        results[74][68]="2000784391440555";
+        results[74][69]="1.508266348754094E-46";
+        results[74][70]="14690335094.84779";
+        results[74][71]="9.217455248864755E-52";
+        results[74][72]="358052.8557252626";
+        results[74][73]="1.746607559512835E-56";
+        results[74][74]="1";
+    }
+
+    @Test
+    public void mcDivideTests() {
+        for(int i=0; i<value.length; i++) {
+            for(int j=0; j<value.length; j++) {
+                BigDecimal v1 = new BigDecimal(value[i]);
+                BigDecimal v2 = new BigDecimal(value[j]);
+                BigDecimal res1  = v1.divide(v2, MathContext.DECIMAL64);
+                Assert.assertEquals(res1.toString(), results[i][j],
+                    "Unexpected result from " + v1 + " / " + v2 +
+                        "; expected " + results[i][j] + " got " + res1);
+            }
+        }
+        for (int mpc = 1; mpc < 23; mpc++) {
+            for (int i = 0; i < value.length; i++) {
+                for (int j = 0; j < value.length; j++) {
+                    BigDecimal v1 = new BigDecimal(value[i]);
+                    BigDecimal v2 = new BigDecimal(value[j]);
+                    BigDecimal res1 = v1.divide(v2, new MathContext(mpc, RoundingMode.HALF_EVEN));
+                    BigDecimal res2 = v1.divide(v2, new MathContext(128, RoundingMode.HALF_EVEN)).round(new MathContext(mpc, RoundingMode.HALF_EVEN));
+                    Assert.assertEquals(res1, res2, "Unexpected result from " + v1 + " / " + v2 +
+                                           "; expected " + res2 + " got " + res1);
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/DivideTests.java b/ojluni/src/test/java/math/BigDecimal/DivideTests.java
new file mode 100644
index 0000000..57773ee
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/DivideTests.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4851776 4907265 6177836 6876282 8066842
+ * @summary Some tests for the divide methods.
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+import static java.math.BigDecimal.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class DivideTests {
+
+    // Preliminary exact divide method; could be used for comparison
+    // purposes.
+    BigDecimal anotherDivide(BigDecimal dividend, BigDecimal divisor) {
+        /*
+         * Handle zero cases first.
+         */
+        if (divisor.signum() == 0) {   // x/0
+            if (dividend.signum() == 0)    // 0/0
+                throw new ArithmeticException("Division undefined");  // NaN
+            throw new ArithmeticException("Division by zero");
+        }
+        if (dividend.signum() == 0)        // 0/y
+            return BigDecimal.ZERO;
+        else {
+            /*
+             * Determine if there is a result with a terminating
+             * decimal expansion.  Putting aside overflow and
+             * underflow considerations, the existance of an exact
+             * result only depends on the ratio of the intVal's of the
+             * dividend (i.e. this) and and divisor since the scales
+             * of the argument just affect where the decimal point
+             * lies.
+             *
+             * For the ratio of (a = this.intVal) and (b =
+             * divisor.intVal) to have a finite decimal expansion,
+             * once a/b is put in lowest terms, b must be equal to
+             * (2^i)*(5^j) for some integer i,j >= 0.  Therefore, we
+             * first compute to see if b_prime =(b/gcd(a,b)) is equal
+             * to (2^i)*(5^j).
+             */
+            BigInteger TWO  = BigInteger.valueOf(2);
+            BigInteger FIVE = BigInteger.valueOf(5);
+            BigInteger TEN  = BigInteger.valueOf(10);
+
+            BigInteger divisorIntvalue  = divisor.scaleByPowerOfTen(divisor.scale()).toBigInteger().abs();
+            BigInteger dividendIntvalue = dividend.scaleByPowerOfTen(dividend.scale()).toBigInteger().abs();
+
+            BigInteger b_prime = divisorIntvalue.divide(dividendIntvalue.gcd(divisorIntvalue));
+
+            boolean goodDivisor = false;
+            int i=0, j=0;
+
+            badDivisor: {
+                while(! b_prime.equals(BigInteger.ONE) ) {
+                    int b_primeModTen = b_prime.mod(TEN).intValue() ;
+
+                    switch(b_primeModTen) {
+                    case 0:
+                        // b_prime divisible by 10=2*5, increment i and j
+                        i++;
+                        j++;
+                        b_prime = b_prime.divide(TEN);
+                        break;
+
+                    case 5:
+                        // b_prime divisible by 5, increment j
+                        j++;
+                        b_prime = b_prime.divide(FIVE);
+                        break;
+
+                    case 2:
+                    case 4:
+                    case 6:
+                    case 8:
+                        // b_prime divisible by 2, increment i
+                        i++;
+                        b_prime = b_prime.divide(TWO);
+                        break;
+
+                    default: // hit something we shouldn't have
+                        b_prime = BigInteger.ONE; // terminate loop
+                        break badDivisor;
+                    }
+                }
+
+                goodDivisor = true;
+            }
+
+            if( ! goodDivisor ) {
+                throw new ArithmeticException("Non terminating decimal expansion");
+            }
+            else {
+                // What is a rule for determining how many digits are
+                // needed?  Once that is determined, cons up a new
+                // MathContext object and pass it on to the divide(bd,
+                // mc) method; precision == ?, roundingMode is unnecessary.
+
+                // Are we sure this is the right scale to use?  Should
+                // also determine a precision-based method.
+                MathContext mc = new MathContext(dividend.precision() +
+                                                 (int)Math.ceil(
+                                                      10.0*divisor.precision()/3.0),
+                                                 RoundingMode.UNNECESSARY);
+                // Should do some more work here to rescale, etc.
+                return dividend.divide(divisor, mc);
+            }
+        }
+    }
+
+    @Test
+    public void powersOf2and5() {
+        for(int i = 0; i < 6; i++) {
+            int powerOf2 = (int)StrictMath.pow(2.0, i);
+
+            for(int j = 0; j < 6; j++) {
+                int powerOf5 = (int)StrictMath.pow(5.0, j);
+                int product;
+
+                BigDecimal bd;
+
+                try {
+                    bd = BigDecimal.ONE.divide(new BigDecimal(product=powerOf2*powerOf5));
+                } catch (ArithmeticException e) {
+                    Assert.fail((new BigDecimal(powerOf2)).toString() + " / " +
+                                       (new BigDecimal(powerOf5)).toString() + " threw an exception.");
+                }
+
+                try {
+                    bd = new BigDecimal(powerOf2).divide(new BigDecimal(powerOf5));
+                } catch (ArithmeticException e) {
+                    Assert.fail((new BigDecimal(powerOf2)).toString() + " / " +
+                                       (new BigDecimal(powerOf5)).toString() + " threw an exception.");
+                }
+
+                try {
+                    bd = new BigDecimal(powerOf5).divide(new BigDecimal(powerOf2));
+                } catch (ArithmeticException e) {
+                    Assert.fail((new BigDecimal(powerOf5)).toString() + " / " +
+                                       (new BigDecimal(powerOf2)).toString() + " threw an exception.");
+                }
+
+            }
+        }
+    }
+
+    @Test
+    public void nonTerminating() {
+        int[] primes = {1, 3, 7, 13, 17};
+
+        // For each pair of prime products, verify the ratio of
+        // non-equal products has a non-terminating expansion.
+
+        for(int i = 0; i < primes.length; i++) {
+            for(int j = i+1; j < primes.length; j++) {
+
+                for(int m = 0; m < primes.length; m++) {
+                    for(int n = m+1; n < primes.length; n++) {
+                        int dividend = primes[i] * primes[j];
+                        int divisor  = primes[m] * primes[n];
+
+                        if ( ((dividend/divisor) * divisor) != dividend ) {
+                            try {
+                                BigDecimal quotient = (new BigDecimal(dividend).
+                                                       divide(new BigDecimal(divisor)));
+                                Assert.fail("Exact quotient " + quotient.toString() +
+                                                   " returned for non-terminating fraction " +
+                                                   dividend + " / " + divisor + ".");
+                            }
+                            catch (ArithmeticException e) {
+                                ; // Correct result
+                            }
+                        }
+
+                    }
+                }
+            }
+        }
+    }
+
+    @Test
+    public void properScaleTests(){
+        BigDecimal[][] testCases = {
+            {new BigDecimal("1"),       new BigDecimal("5"),            new BigDecimal("2e-1")},
+            {new BigDecimal("1"),       new BigDecimal("50e-1"),        new BigDecimal("2e-1")},
+            {new BigDecimal("10e-1"),   new BigDecimal("5"),            new BigDecimal("2e-1")},
+            {new BigDecimal("1"),       new BigDecimal("500e-2"),       new BigDecimal("2e-1")},
+            {new BigDecimal("100e-2"),  new BigDecimal("5"),            new BigDecimal("20e-2")},
+            {new BigDecimal("1"),       new BigDecimal("32"),           new BigDecimal("3125e-5")},
+            {new BigDecimal("1"),       new BigDecimal("64"),           new BigDecimal("15625e-6")},
+            {new BigDecimal("1.0000000"),       new BigDecimal("64"),   new BigDecimal("156250e-7")},
+        };
+
+
+        for(BigDecimal[] tc : testCases) {
+            BigDecimal quotient = tc[0].divide(tc[1]);
+            Assert.assertEquals(quotient, tc[2],
+                "Unexpected quotient from " + tc[0] + " / " + tc[1] +
+                                   "; expected " + tc[2] + " got " + quotient);
+        }
+    }
+
+    @Test
+    public void trailingZeroTests() {
+        MathContext mc = new MathContext(3, RoundingMode.FLOOR);
+        BigDecimal[][] testCases = {
+            {new BigDecimal("19"),      new BigDecimal("100"),          new BigDecimal("0.19")},
+            {new BigDecimal("21"),      new BigDecimal("110"),          new BigDecimal("0.190")},
+        };
+
+        for(BigDecimal[] tc : testCases) {
+            BigDecimal quotient = tc[0].divide(tc[1], mc);
+            Assert.assertEquals(quotient, tc[2],
+                "Unexpected quotient from " + tc[0] + " / " + tc[1] +
+                                   "; expected " + tc[2] + " got " + quotient);
+        }
+    }
+
+    @Test
+    public void scaledRoundedDivideTests() {
+        // Tests of the traditional scaled divide under different
+        // rounding modes.
+
+        // Encode rounding mode and scale for the divide in a
+        // BigDecimal with the significand equal to the rounding mode
+        // and the scale equal to the number's scale.
+
+        // {dividend, divisor, rounding, quotient}
+        BigDecimal a = new BigDecimal("31415");
+        BigDecimal a_minus = a.negate();
+        BigDecimal b = new BigDecimal("10000");
+
+        BigDecimal c = new BigDecimal("31425");
+        BigDecimal c_minus = c.negate();
+
+         // Ad hoc tests
+        BigDecimal d = new BigDecimal(new BigInteger("-37361671119238118911893939591735"), 10);
+        BigDecimal e = new BigDecimal(new BigInteger("74723342238476237823787879183470"), 15);
+
+        BigDecimal[][] testCases = {
+            {a,         b,      BigDecimal.valueOf(ROUND_UP, 3),        new BigDecimal("3.142")},
+            {a_minus,   b,      BigDecimal.valueOf(ROUND_UP, 3),        new BigDecimal("-3.142")},
+
+            {a,         b,      BigDecimal.valueOf(ROUND_DOWN, 3),      new BigDecimal("3.141")},
+            {a_minus,   b,      BigDecimal.valueOf(ROUND_DOWN, 3),      new BigDecimal("-3.141")},
+
+            {a,         b,      BigDecimal.valueOf(ROUND_CEILING, 3),   new BigDecimal("3.142")},
+            {a_minus,   b,      BigDecimal.valueOf(ROUND_CEILING, 3),   new BigDecimal("-3.141")},
+
+            {a,         b,      BigDecimal.valueOf(ROUND_FLOOR, 3),     new BigDecimal("3.141")},
+            {a_minus,   b,      BigDecimal.valueOf(ROUND_FLOOR, 3),     new BigDecimal("-3.142")},
+
+            {a,         b,      BigDecimal.valueOf(ROUND_HALF_UP, 3),   new BigDecimal("3.142")},
+            {a_minus,   b,      BigDecimal.valueOf(ROUND_HALF_UP, 3),   new BigDecimal("-3.142")},
+
+            {a,         b,      BigDecimal.valueOf(ROUND_DOWN, 3),      new BigDecimal("3.141")},
+            {a_minus,   b,      BigDecimal.valueOf(ROUND_DOWN, 3),      new BigDecimal("-3.141")},
+
+            {a,         b,      BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("3.142")},
+            {a_minus,   b,      BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("-3.142")},
+
+            {c,         b,      BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("3.142")},
+            {c_minus,   b,      BigDecimal.valueOf(ROUND_HALF_EVEN, 3), new BigDecimal("-3.142")},
+
+            {d,         e,      BigDecimal.valueOf(ROUND_HALF_UP, -5),   BigDecimal.valueOf(-1, -5)},
+            {d,         e,      BigDecimal.valueOf(ROUND_HALF_DOWN, -5), BigDecimal.valueOf(0, -5)},
+            {d,         e,      BigDecimal.valueOf(ROUND_HALF_EVEN, -5), BigDecimal.valueOf(0, -5)},
+        };
+
+        for(BigDecimal[] tc : testCases) {
+            int scale = tc[2].scale();
+            int rm = tc[2].unscaledValue().intValue();
+
+            BigDecimal quotient = tc[0].divide(tc[1], scale, rm);
+            Assert.assertEquals(quotient, tc[3],
+                "Unexpected quotient from " + tc[0] + " / " + tc[1] +
+                                   " scale " + scale + " rounding mode " + RoundingMode.valueOf(rm) +
+                                   "; expected " + tc[3] + " got " + quotient);
+        }
+
+        // 6876282
+        BigDecimal[][] testCases2 = {
+            // { dividend, divisor, expected quotient }
+            { new BigDecimal(3090), new BigDecimal(7), new BigDecimal(441) },
+            { new BigDecimal("309000000000000000000000"), new BigDecimal("700000000000000000000"),
+              new BigDecimal(441) },
+            { new BigDecimal("962.430000000000"), new BigDecimal("8346463.460000000000"),
+              new BigDecimal("0.000115309916") },
+            { new BigDecimal("18446744073709551631"), new BigDecimal("4611686018427387909"),
+              new BigDecimal(4) },
+            { new BigDecimal("18446744073709551630"), new BigDecimal("4611686018427387909"),
+              new BigDecimal(4) },
+            { new BigDecimal("23058430092136939523"), new BigDecimal("4611686018427387905"),
+              new BigDecimal(5) },
+            { new BigDecimal("-18446744073709551661"), new BigDecimal("-4611686018427387919"),
+              new BigDecimal(4) },
+            { new BigDecimal("-18446744073709551660"), new BigDecimal("-4611686018427387919"),
+              new BigDecimal(4) },
+        };
+
+        for (BigDecimal[] test : testCases2) {
+            BigDecimal quo = test[0].divide(test[1], RoundingMode.HALF_UP);
+            Assert.assertEquals(quo, test[2], "Unexpected quotient from " + test[0] + " / " + test[1] +
+                                   " rounding mode HALF_UP" +
+                                   "; expected " + test[2] + " got " + quo);
+        }
+    }
+
+    @Test
+    public void divideByOneTests() {
+        //problematic divisor: one with scale 17
+        BigDecimal one = BigDecimal.ONE.setScale(17);
+        RoundingMode rounding = RoundingMode.UNNECESSARY;
+
+        long[][] unscaledAndScale = new long[][] {
+            { Long.MAX_VALUE,  17},
+            {-Long.MAX_VALUE,  17},
+            { Long.MAX_VALUE,   0},
+            {-Long.MAX_VALUE,   0},
+            { Long.MAX_VALUE, 100},
+            {-Long.MAX_VALUE, 100}
+        };
+
+        for (long[] uas : unscaledAndScale) {
+            long unscaled = uas[0];
+            int scale = (int)uas[1];
+
+            BigDecimal noRound = null;
+            try {
+                noRound = BigDecimal.valueOf(unscaled, scale).
+                    divide(one, RoundingMode.UNNECESSARY);
+            } catch (ArithmeticException e) {
+                Assert.fail("ArithmeticException for value " + unscaled
+                    + " and scale " + scale + " without rounding");
+            }
+
+            BigDecimal roundDown = null;
+            try {
+                roundDown = BigDecimal.valueOf(unscaled, scale).
+                        divide(one, RoundingMode.DOWN);
+            } catch (ArithmeticException e) {
+                Assert.fail("ArithmeticException for value " + unscaled
+                    + " and scale " + scale + " with rounding down");
+            }
+
+            if (noRound != null && roundDown != null && noRound.compareTo(roundDown) != 0) {
+                Assert.fail("Equality failure for value " + unscaled
+                        + " and scale " + scale);
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/EqualsTests.java b/ojluni/src/test/java/math/BigDecimal/EqualsTests.java
new file mode 100644
index 0000000..c28249b
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/EqualsTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 1234567
+ * @summary Test BigDecimal.equals() method.
+ * @author xlu
+ */
+import java.math.*;
+import static java.math.BigDecimal.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class EqualsTests {
+
+    @Test
+    public void testEquals() {
+        BigDecimal[][] testValues = {
+            // The even index is supposed to return true for equals call and
+            // the odd index is supposed to return false, i.e. not equal.
+            {ZERO, ZERO},
+            {ONE, TEN},
+
+            {valueOf(Integer.MAX_VALUE), valueOf(Integer.MAX_VALUE)},
+            {valueOf(Long.MAX_VALUE), valueOf(-Long.MAX_VALUE)},
+
+            {valueOf(12345678), valueOf(12345678)},
+            {valueOf(123456789), valueOf(123456788)},
+
+            {new BigDecimal("123456789123456789123"),
+             new BigDecimal(new BigInteger("123456789123456789123"))},
+            {new BigDecimal("123456789123456789123"),
+             new BigDecimal(new BigInteger("123456789123456789124"))},
+
+            {valueOf(Long.MIN_VALUE), new BigDecimal("-9223372036854775808")},
+            {new BigDecimal("9223372036854775808"), valueOf(Long.MAX_VALUE)},
+
+            {valueOf(Math.round(Math.pow(2, 10))), new BigDecimal("1024")},
+            {new BigDecimal("1020"), valueOf(Math.pow(2, 11))},
+
+            {new BigDecimal(BigInteger.valueOf(2).pow(65)),
+             new BigDecimal("36893488147419103232")},
+            {new BigDecimal("36893488147419103231.81"),
+             new BigDecimal("36893488147419103231.811"),
+            }
+        };
+
+        boolean expected = Boolean.TRUE;
+        for (BigDecimal[] testValuePair : testValues) {
+            equalsTest(testValuePair[0], testValuePair[1], expected);
+            expected = !expected;
+        }
+    }
+
+    private static void equalsTest(BigDecimal l, BigDecimal r, boolean expected) {
+        boolean result = l.equals(r);
+        Assert.assertEquals(result, expected, l + " .equals(" + r + ") => " + result +
+                               "\n\tExpected " + expected);
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/FloatDoubleValueTests.java b/ojluni/src/test/java/math/BigDecimal/FloatDoubleValueTests.java
new file mode 100644
index 0000000..559ccc3
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/FloatDoubleValueTests.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6274390 7082971
+ * @summary Verify {float, double}Value methods work with condensed representation
+ * @run main FloatDoubleValueTests
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 FloatDoubleValueTests
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class FloatDoubleValueTests {
+    private static final long two2the24 = 1L<<23;
+    private static final long two2the53 = 1L<<52;
+
+    // Largest long that fits exactly in a float
+    private static final long maxFltLong = (long)(Integer.MAX_VALUE & ~(0xff));
+
+    // Largest long that fits exactly in a double
+    private static final long maxDblLong = Long.MAX_VALUE & ~(0x7ffL);
+
+    static void testDoubleValue0(long i, BigDecimal bd) {
+        Assert.assertFalse(bd.doubleValue() != i || bd.longValue()   != i,
+            "Unexpected equality failure for " + i + "\t" + bd);
+    }
+
+    static void testFloatValue0(long i, BigDecimal bd) {
+        Assert.assertFalse(bd.floatValue() != i || bd.longValue()   != i,
+            "Unexpected equality failure for " + i + "\t" + bd);
+    }
+
+    static void checkFloat(BigDecimal bd, float f) {
+        float fbd = bd.floatValue();
+        Assert.assertEquals(fbd, f, String.format("Bad conversion:"+
+                                           "got %g (%a)\texpected %g (%a)",
+                                           f, f, fbd, fbd));
+    }
+
+    static void checkDouble(BigDecimal bd, double d) {
+        double dbd = bd.doubleValue();
+
+        Assert.assertEquals(dbd, d, String.format("Bad conversion:"+
+                                           "got %g (%a)\texpected %g (%a)",
+                                           d, d, dbd, dbd));
+    }
+
+    // Test integral values that will convert exactly to both float
+    // and double.
+    @Test
+    public void testFloatDoubleValue() {
+        long[] longValues = {
+            Long.MIN_VALUE, // -2^63
+            0,
+            1,
+            2,
+
+            two2the24-1,
+            two2the24,
+            two2the24+1,
+
+            maxFltLong-1,
+            maxFltLong,
+            maxFltLong+1,
+        };
+
+        for(long i : longValues) {
+            BigDecimal bd1 = new BigDecimal(i);
+            BigDecimal bd2 = new BigDecimal(-i);
+
+            testDoubleValue0( i, bd1);
+            testDoubleValue0(-i, bd2);
+
+            testFloatValue0( i, bd1);
+            testFloatValue0(-i, bd2);
+        }
+
+    }
+
+    @Test
+    public void testDoubleValue() {
+        long[] longValues = {
+            Integer.MAX_VALUE-1,
+            Integer.MAX_VALUE,
+            (long)Integer.MAX_VALUE+1,
+
+            two2the53-1,
+            two2the53,
+            two2the53+1,
+
+            maxDblLong,
+        };
+
+        // Test integral values that will convert exactly to double
+        // but not float.
+        for(long i : longValues) {
+            BigDecimal bd1 = new BigDecimal(i);
+            BigDecimal bd2 = new BigDecimal(-i);
+
+            testDoubleValue0( i, bd1);
+            testDoubleValue0(-i, bd2);
+
+            checkFloat(bd1, (float)i);
+            checkFloat(bd2, -(float)i);
+        }
+
+        // Now check values that should not convert the same in double
+        for(long i = maxDblLong; i < Long.MAX_VALUE; i++) {
+            BigDecimal bd1 = new BigDecimal(i);
+            BigDecimal bd2 = new BigDecimal(-i);
+            checkDouble(bd1, (double)i);
+            checkDouble(bd2, -(double)i);
+
+            checkFloat(bd1, (float)i);
+            checkFloat(bd2, -(float)i);
+        }
+
+        checkDouble(new BigDecimal(Long.MIN_VALUE), (double)Long.MIN_VALUE);
+        checkDouble(new BigDecimal(Long.MAX_VALUE), (double)Long.MAX_VALUE);
+    }
+
+    @Test
+    public void testFloatValue() {
+        // Now check values that should not convert the same in float
+        for(long i = maxFltLong; i <= Integer.MAX_VALUE; i++) {
+            BigDecimal bd1 = new BigDecimal(i);
+            BigDecimal bd2 = new BigDecimal(-i);
+            checkFloat(bd1, (float)i);
+            checkFloat(bd2, -(float)i);
+
+            testDoubleValue0( i, bd1);
+            testDoubleValue0(-i, bd2);
+        }
+    }
+
+    @Test
+    public void testFloatValue1() {
+        checkFloat(new BigDecimal("85070591730234615847396907784232501249"), 8.507059e+37f);
+        checkFloat(new BigDecimal("7784232501249e12"), 7.7842326e24f);
+        checkFloat(new BigDecimal("907784232501249e-12"),907.78424f);
+        checkFloat(new BigDecimal("7784e8"),7.7839997e11f);
+        checkFloat(new BigDecimal("9077e-8"),9.077e-5f);
+    }
+
+    @Test
+    public void testDoubleValue1() {
+        checkDouble(new BigDecimal("85070591730234615847396907784232501249"), 8.507059173023462e37);
+        checkDouble(new BigDecimal("7784232501249e12"), 7.784232501249e24);
+        checkDouble(new BigDecimal("907784232501249e-12"), 907.784232501249);
+        checkDouble(new BigDecimal("7784e8"), 7.784e11);
+        checkDouble(new BigDecimal("9077e-8"), 9.077e-5);
+
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/IntegralDivisionTests.java b/ojluni/src/test/java/math/BigDecimal/IntegralDivisionTests.java
new file mode 100644
index 0000000..f5f1ade
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/IntegralDivisionTests.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4904082 4917089 6337226 6378503
+ * @summary Tests that integral division and related methods return the proper result and scale.
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class IntegralDivisionTests {
+
+    @Test
+    public void dividetoIntegralValueTests() {
+        // Exact integer quotient should have the same results from
+        // the exact divide and dividetoIntegralValue
+
+
+        // Rounded results
+        BigDecimal [][] moreTestCases = {
+            {new BigDecimal("11003"),   new BigDecimal("10"),   new BigDecimal("1100")},
+            {new BigDecimal("11003"),   new BigDecimal("1e1"),  new BigDecimal("1100.0")},
+            {new BigDecimal("1e9"),     new BigDecimal("1"),    new BigDecimal("1e9")},
+            {new BigDecimal("1e9"),     new BigDecimal("1.00"), new BigDecimal("1e9")},
+            {new BigDecimal("1e9"),     new BigDecimal("0.1"),  new BigDecimal("1e10")},
+            {new BigDecimal("10e8"),    new BigDecimal("0.1"),  new BigDecimal("10e9")},
+            {new BigDecimal("400e1"),   new BigDecimal("5"),    new BigDecimal("80e1")},
+            {new BigDecimal("400e1"),   new BigDecimal("4.999999999"),  new BigDecimal("8e2")},
+            {new BigDecimal("40e2"),    new BigDecimal("5"),    new BigDecimal("8e2")},
+            {BigDecimal.valueOf(1, Integer.MIN_VALUE),
+                BigDecimal.valueOf(1, -(Integer.MAX_VALUE & 0x7fffff00)),
+                BigDecimal.valueOf(1, -256)},
+        };
+
+        for(BigDecimal [] testCase: moreTestCases) {
+            BigDecimal quotient = testCase[0].divideToIntegralValue(testCase[1]);
+            Assert.assertEquals(quotient, testCase[2],
+                "dividend  = " + testCase[0] + " scale = " + testCase[0].scale() +
+                " divisor   = " + testCase[1] + " scale = " + testCase[1].scale() +
+                " quotient  = " + quotient    + " scale = " + quotient.scale() +
+                " expected  = " + testCase[2] + " scale = " + testCase[2].scale());
+        }
+    }
+
+    @Test
+    public void dividetoIntegralValueRoundedTests() {
+        BigDecimal dividend = new BigDecimal("11003");
+        BigDecimal divisor = new BigDecimal("10");
+        BigDecimal [] quotients = {     // Expected results with precision =
+            new BigDecimal("1100"),     // 0
+            null,                       // 1
+            new BigDecimal("11e2"),     // 2
+            new BigDecimal("110e1"),    // 3
+            new BigDecimal("1100"),     // 4
+        };
+        divideContextTestPrecs(dividend, divisor, quotients);
+
+        dividend = new BigDecimal("11003");
+        divisor = new BigDecimal("1e1");
+        BigDecimal [] quotients2 = {    // Expected results with precision =
+            new BigDecimal("1100.0"),   // 0
+            null,                       // 1
+            new BigDecimal("11e2"),     // 2
+            new BigDecimal("110e1"),    // 3
+            new BigDecimal("1100"),     // 4
+            new BigDecimal("1100.0"),   // 5
+        };
+        divideContextTestPrecs(dividend, divisor, quotients2);
+
+        dividend = new BigDecimal("1230000");
+        divisor = new BigDecimal("100");
+        BigDecimal [] quotients3 = {    // Expected results with precision =
+            new BigDecimal("12300"),    // 0
+            null,                       // 1
+            null,                       // 2
+            new BigDecimal("123e2"),    // 3
+            new BigDecimal("1230e1"),   // 4
+            new BigDecimal("12300"),    // 5
+        };
+        divideContextTestPrecs(dividend, divisor, quotients3);
+
+        dividend = new BigDecimal("33");
+        divisor  = new BigDecimal("3");
+        BigDecimal [] quotients4 = {    // Expected results with precision =
+            new BigDecimal("11"),       // 0
+            null,                       // 1
+            new BigDecimal("11"),       // 2
+            new BigDecimal("11"),       // 3
+        };
+        divideContextTestPrecs(dividend, divisor, quotients4);
+
+        dividend = new BigDecimal("34");
+        divisor  = new BigDecimal("3");
+        BigDecimal [] quotients5 = {    // Expected results with precision =
+            new BigDecimal("11"),       // 0
+            null,                       // 1
+            new BigDecimal("11"),       // 2
+            new BigDecimal("11"),       // 3
+        };
+        divideContextTestPrecs(dividend, divisor, quotients5);
+    }
+
+    static void divideContextTestPrecs(BigDecimal dividend,
+                                      BigDecimal divisor,
+                                      BigDecimal[] quotients) {
+        for(int i = 0; i < quotients.length; i++) {
+            BigDecimal result = null;
+            BigDecimal quotient = quotients[i];
+
+            try {
+                result = dividend.divideToIntegralValue(divisor,
+                                                        new MathContext(i, RoundingMode.DOWN));
+            } catch (ArithmeticException e) {
+                if (quotient != null) {
+                    Assert.fail("Unexpected exception:" +
+                            " dividend  = " + dividend     + " scale = " + dividend.scale() +
+                            " divisor   = " + divisor      + " scale = " + divisor.scale() +
+                            " expected  = " + quotient     + " scale = " + quotient.scale());
+                }
+            }
+
+            if (quotient != null) {
+                Assert.assertEquals(quotient, result, "Unexpected result: " +
+                    " dividend  = " + dividend     + " scale = " + dividend.scale() +
+                    " divisor   = " + divisor      + " scale = " + divisor.scale() +
+                    " quotient  = " + result       + " scale = " + result.scale() +
+                    " expected  = " + quotient     + " scale = " + quotient.scale() +
+                    " precision = " + i);
+            } else {
+                if (result != null) {
+                    Assert.fail("Unexpected unexceptional result:" +
+                    " dividend  = " + dividend     + " scale = " + dividend.scale() +
+                    " divisor   = " + divisor      + " scale = " + divisor.scale() +
+                    " quotient  = " + result       + " scale = " + result.scale() +
+                    " precision = " + i);
+                }
+            }
+        }
+    }
+
+
+    static void divideContextTests(BigDecimal dividend,
+                                  BigDecimal divisor,
+                                  BigDecimal expected,
+                                  MathContext mc) {
+        divideContextTest(dividend,              divisor,          expected,                mc);
+        divideContextTest(dividend.negate(),     divisor.negate(), expected,                mc);
+
+        if (expected != null) {
+            divideContextTest(dividend.negate(), divisor,          expected.negate(),       mc);
+            divideContextTest(dividend,          divisor.negate(), expected.negate(),       mc);
+        }
+    }
+
+
+    static void divideContextTest(BigDecimal dividend,
+                                 BigDecimal divisor,
+                                 BigDecimal expected,
+                                 MathContext mc) {
+        BigDecimal result = null;
+
+        try {
+            result = dividend.divideToIntegralValue(divisor, mc);
+        } catch (ArithmeticException e) {
+            if (expected != null) {
+                Assert.fail("Unexpected exception:" +
+                        " dividend  = " + dividend     + " scale = " + dividend.scale() +
+                        " divisor   = " + divisor      + " scale = " + divisor.scale() +
+                        " expected  = " + expected     + " scale = " + expected.scale() +
+                        " MathContext  = " + mc);
+            }
+        }
+
+        if (expected != null) {
+            Assert.assertEquals(result, expected, "Unexpected result:" +
+                    " dividend  = " + dividend     + " scale = " + dividend.scale() +
+                    " divisor   = " + divisor      + " scale = " + divisor.scale() +
+                    " expected  = " + expected     + " scale = " + expected.scale() +
+                    " result    = " + result       + " scale = " + result.scale() +
+                    " MathContext  = " + mc);
+        } else {
+            if (result != null) {
+                Assert.fail("Unexpected unexceptional result:" +
+                    "dividend  = " + dividend + " scale = " + dividend.scale() +
+                    "divisor   = " + divisor + " scale = " + divisor.scale() +
+                    "quotient  = " + result + " scale = " + result.scale() +
+                    "MathConext = " + mc);
+            }
+        }
+    }
+
+    @Test
+    public void dividetoIntegralValueScalingTests() {
+        BigDecimal dividend = new BigDecimal("123456789000");
+        BigDecimal divisor = BigDecimal.ONE;
+        BigDecimal expected = new BigDecimal("123456789e3");
+        MathContext mc = new MathContext(9,RoundingMode.DOWN);
+        divideContextTests(dividend, divisor, expected, mc);
+
+
+        // 100/3 = 33 remainder 1
+        int [] precisions = {0, 2, 3, 4};
+        dividend = new BigDecimal(100);
+        divisor  = new BigDecimal(3);
+        expected = new BigDecimal(33);
+
+        for(RoundingMode rm: RoundingMode.values())
+            for(int precision: precisions) {
+                divideContextTests(dividend, divisor, expected, new MathContext(precision, rm));
+            }
+
+        // 123000/10 = 12300 remainder 0
+        dividend = new BigDecimal(123000);
+        divisor  = new BigDecimal(10);
+        int[] precisions1 = {0, 1, 2, 3, 4, 5};
+        BigDecimal[] expected1 = {
+            new BigDecimal("12300"),
+            null,
+            null,
+            new BigDecimal("123e2"),
+            new BigDecimal("1230e1"),
+            new BigDecimal("12300"),
+        };
+
+        for(RoundingMode rm: RoundingMode.values())
+            for(int i = 0; i < precisions1.length; i++) {
+                divideContextTests(dividend, divisor,
+                                               expected1[i],
+                                               new MathContext(precisions1[i], rm));
+            }
+
+        // 123e3/10 = 123e2 remainder 0
+        dividend = new BigDecimal("123e3");
+        divisor  = new BigDecimal(10);
+        int[] precisions2 = {0, 1, 2, 3, 4, 5};
+        BigDecimal[] expected2 = {
+            new BigDecimal("123e2"),
+            null,
+            null,
+            new BigDecimal("123e2"),
+            new BigDecimal("123e2"),
+            new BigDecimal("123e2"),
+        };
+
+        for(RoundingMode rm: RoundingMode.values())
+            for(int i = 0; i < precisions2.length; i++) {
+                divideContextTests(dividend, divisor,
+                                               expected2[i],
+                                               new MathContext(precisions2[i], rm));
+            }
+
+
+        // 123000/1e1 = 12300.0 remainder 0
+        dividend = new BigDecimal("123000");
+        divisor  = new BigDecimal("1e1");
+        int[] precisions3 = {0, 1, 2, 3, 4, 5, 6};
+        BigDecimal[] expected3 = {
+            new BigDecimal("12300.0"),
+            null,
+            null,
+            new BigDecimal("123e2"),
+            new BigDecimal("1230e1"),
+            new BigDecimal("12300"),
+            new BigDecimal("12300.0"),
+        };
+
+        for(RoundingMode rm: RoundingMode.values())
+            for(int i = 0; i < precisions3.length; i++) {
+                divideContextTests(dividend, divisor,
+                                               expected3[i],
+                                               new MathContext(precisions3[i], rm));
+            }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/LongValueExactTests.java b/ojluni/src/test/java/math/BigDecimal/LongValueExactTests.java
new file mode 100644
index 0000000..4d53663
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/LongValueExactTests.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6806261
+ * @summary Tests of BigDecimal.longValueExact
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class LongValueExactTests {
+
+    @Test
+    public static void longValueExactTests() {
+        String[] testStrings = {
+            "9223372036854775807",
+            "9223372036854775807.0",
+            "9223372036854775807.00",
+            "-9223372036854775808",
+            "-9223372036854775808.0",
+            "-9223372036854775808.00",
+        };
+
+        for (String longValue : testStrings) {
+            try {
+                BigDecimal bd = new BigDecimal(longValue);
+                long longValueExact = bd.longValueExact();
+            } catch (Exception e) {
+                Assert.fail("Unexpected exception for longValueExact(" + longValue + "): " + e.getMessage());
+            }
+        }
+
+        // The following Strings are supposed to make longValueExact throw
+        // ArithmeticException.
+        String[] testStrings2 = {
+            "9223372036854775808",
+            "9223372036854775808.0",
+            "9223372036854775808.00",
+            "-9223372036854775809",
+            "-9223372036854775808.1",
+            "-9223372036854775808.01",
+        };
+
+        for (String bigValue : testStrings2) {
+            try {
+                BigDecimal bd = new BigDecimal(bigValue);
+                long longValueExact = bd.longValueExact();
+                Assert.fail("Unexpectedly no throw for longValueExact(" + bigValue + ")");
+            } catch (ArithmeticException e) {
+                // Success;
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/MultiplyTests.java b/ojluni/src/test/java/math/BigDecimal/MultiplyTests.java
new file mode 100644
index 0000000..a359e45
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/MultiplyTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6850606
+ * @summary Test BigDecimal.multiply(BigDecimal)
+ * @author xlu
+ */
+
+import java.math.*;
+import static java.math.BigDecimal.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class MultiplyTests {
+
+    @Test
+    public void multiplyTests() {
+        BigDecimal[] bd1 = {
+            new BigDecimal("123456789"),
+            new BigDecimal("1234567898"),
+            new BigDecimal("12345678987")
+        };
+
+        BigDecimal[] bd2 = {
+            new BigDecimal("987654321"),
+            new BigDecimal("8987654321"),
+            new BigDecimal("78987654321")
+        };
+
+        // Two dimensional array recording bd1[i] * bd2[j] &
+        // 0 <= i <= 2 && 0 <= j <= 2;
+        BigDecimal[][] expectedResults = {
+            {new BigDecimal("121932631112635269"),
+             new BigDecimal("1109586943112635269"),
+             new BigDecimal("9751562173112635269")
+            },
+            { new BigDecimal("1219326319027587258"),
+              new BigDecimal("11095869503027587258"),
+              new BigDecimal("97515622363027587258")
+            },
+            { new BigDecimal("12193263197189452827"),
+              new BigDecimal("110958695093189452827"),
+              new BigDecimal("975156224183189452827")
+            }
+        };
+
+        for (int i = 0; i < bd1.length; i++) {
+            for (int j = 0; j < bd2.length; j++) {
+                Assert.assertEquals(bd1[i].multiply(bd2[j]), expectedResults[i][j],
+                    bd1[i] + " * " + bd2[j] + " + is " + bd1[i].multiply(bd2[j]) +
+                        " but expected: " + expectedResults[i][j]);
+            }
+        }
+
+        BigDecimal x = BigDecimal.valueOf(8L, 1);
+        BigDecimal xPower = BigDecimal.valueOf(-1L);
+        try {
+            for (int i = 0; i < 100; i++) {
+                xPower = xPower.multiply(x);
+            }
+        } catch (Exception ex) {
+            Assert.fail("Unexpected exception: " + ex.getMessage());
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/NegateTests.java b/ojluni/src/test/java/math/BigDecimal/NegateTests.java
new file mode 100644
index 0000000..af5805b
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/NegateTests.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6325535
+ * @summary Test for the rounding behavior of negate(MathContext)
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class NegateTests {
+
+    static BigDecimal negateThenRound(BigDecimal bd, MathContext mc) {
+        return bd.negate().plus(mc);
+    }
+
+
+    static BigDecimal absThenRound(BigDecimal bd, MathContext mc) {
+        return bd.abs().plus(mc);
+    }
+
+
+    static void negateTest(BigDecimal[][] testCases,  MathContext mc) {
+        for (BigDecimal [] testCase : testCases) {
+
+            BigDecimal bd = testCase[0];
+            BigDecimal neg1 = bd.negate(mc);
+            BigDecimal neg2 = negateThenRound(bd, mc);
+            BigDecimal expected = testCase[1];
+
+            Assert.assertEquals(neg1, expected, "(" + bd + ").negate(" + mc + ") => " +
+                                   neg1 + " != expected " + expected);
+
+            Assert.assertEquals(neg1, neg2, "(" + bd + ").negate(" + mc + ")  => " +
+                                   neg1 + " != ntr " + neg2);
+
+            // Test abs consistency
+            BigDecimal abs = bd.abs(mc);
+            BigDecimal expectedAbs = absThenRound(bd,mc);
+            Assert.assertEquals(abs, expectedAbs, "(" + bd + ").abs(" + mc + ")  => " +
+                                   abs + " != atr " +  expectedAbs);
+        }
+    }
+
+    @Test
+    public void negateTests() {
+        BigDecimal [][] testCasesCeiling = {
+            {new BigDecimal("1.3"),     new BigDecimal("-1")},
+            {new BigDecimal("-1.3"),    new BigDecimal("2")},
+        };
+
+        negateTest(testCasesCeiling, new MathContext(1, RoundingMode.CEILING));
+
+        BigDecimal [][] testCasesFloor = {
+            {new BigDecimal("1.3"),     new BigDecimal("-2")},
+            {new BigDecimal("-1.3"),    new BigDecimal("1")},
+        };
+
+        negateTest(testCasesFloor, new MathContext(1, RoundingMode.FLOOR));
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/PowTests.java b/ojluni/src/test/java/math/BigDecimal/PowTests.java
new file mode 100644
index 0000000..5cc30cf
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/PowTests.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4916097
+ * @summary Some exponent over/undeflow tests for the pow method
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class PowTests {
+    @Test
+    public void zeroAndOneTests() {
+        BigDecimal[][] testCases = {
+            {BigDecimal.valueOf(0, Integer.MAX_VALUE),  new BigDecimal(0),              BigDecimal.valueOf(1, 0)},
+            {BigDecimal.valueOf(0, Integer.MAX_VALUE),  new BigDecimal(1),              BigDecimal.valueOf(0, Integer.MAX_VALUE)},
+            {BigDecimal.valueOf(0, Integer.MAX_VALUE),  new BigDecimal(2),              BigDecimal.valueOf(0, Integer.MAX_VALUE)},
+            {BigDecimal.valueOf(0, Integer.MAX_VALUE),  new BigDecimal(999999999),      BigDecimal.valueOf(0, Integer.MAX_VALUE)},
+
+            {BigDecimal.valueOf(0, Integer.MIN_VALUE),  new BigDecimal(0),              BigDecimal.valueOf(1, 0)},
+            {BigDecimal.valueOf(0, Integer.MIN_VALUE),  new BigDecimal(1),              BigDecimal.valueOf(0, Integer.MIN_VALUE)},
+            {BigDecimal.valueOf(0, Integer.MIN_VALUE),  new BigDecimal(2),              BigDecimal.valueOf(0, Integer.MIN_VALUE)},
+            {BigDecimal.valueOf(0, Integer.MIN_VALUE),  new BigDecimal(999999999),      BigDecimal.valueOf(0, Integer.MIN_VALUE)},
+
+            {BigDecimal.valueOf(1, Integer.MAX_VALUE),  new BigDecimal(0),              BigDecimal.valueOf(1, 0)},
+            {BigDecimal.valueOf(1, Integer.MAX_VALUE),  new BigDecimal(1),              BigDecimal.valueOf(1, Integer.MAX_VALUE)},
+            {BigDecimal.valueOf(1, Integer.MAX_VALUE),  new BigDecimal(2),              null}, // overflow
+            {BigDecimal.valueOf(1, Integer.MAX_VALUE),  new BigDecimal(999999999),      null}, // overflow
+
+            {BigDecimal.valueOf(1, Integer.MIN_VALUE),  new BigDecimal(0),              BigDecimal.valueOf(1, 0)},
+            {BigDecimal.valueOf(1, Integer.MIN_VALUE),  new BigDecimal(1),              BigDecimal.valueOf(1, Integer.MIN_VALUE)},
+            {BigDecimal.valueOf(1, Integer.MIN_VALUE),  new BigDecimal(2),              null}, // underflow
+            {BigDecimal.valueOf(1, Integer.MIN_VALUE),  new BigDecimal(999999999),      null}, // underflow
+        };
+
+        for(BigDecimal[] testCase: testCases) {
+            int exponent = testCase[1].intValueExact();
+            BigDecimal result;
+
+            try{
+                result = testCase[0].pow(exponent);
+                Assert.assertEquals(result, testCase[2], "Unexpected result while raising " +
+                                       testCase[0] +
+                                       " to the " + exponent + " power; expected " +
+                                       testCase[2] + ", got " + result + ".");
+            } catch (ArithmeticException e) {
+                if (testCase[2] != null) {
+                    Assert.fail("Unexpected exception while raising " + testCase[0] +
+                                       " to the " + exponent + " power.");
+
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/PrecisionTests.java b/ojluni/src/test/java/math/BigDecimal/PrecisionTests.java
new file mode 100644
index 0000000..be48794
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/PrecisionTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 1234567
+ * @summary Test that precision() is computed properly.
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+import static java.math.BigDecimal.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class PrecisionTests {
+    private static BigDecimal NINE = valueOf(9);
+
+    @Test
+    public void testPrecision() {
+        // Smallest and largest values of a given length
+        BigDecimal[] testValues = {
+            valueOf(1), valueOf(9),
+        };
+
+        testPrecision(new BigDecimal(0), 1);
+
+        for(int i = 1; i < 100; i++) {
+            for(BigDecimal bd : testValues) {
+                testPrecision(bd, i);
+                testPrecision(bd.negate(), i);
+            }
+
+            testValues[0] = testValues[0].multiply(TEN);
+            testValues[1] = testValues[1].multiply(TEN).add(NINE);
+        }
+
+        // The following test tries to cover testings for precision of long values
+        BigDecimal[] randomTestValues = {
+            valueOf(2147483648L),          // 2^31:       10 digits
+            valueOf(-2147483648L),         // -2^31:      10 digits
+            valueOf(98893745455L),         // random:     11 digits
+            valueOf(3455436789887L),       // random:     13 digits
+            valueOf(140737488355328L),     // 2^47:       15 digits
+            valueOf(-140737488355328L),    // -2^47:      15 digits
+            valueOf(7564232235739573L),    // random:     16 digits
+            valueOf(25335434990002322L),   // random:     17 digits
+            valueOf(9223372036854775807L), // 2^63 - 1:   19 digits
+            valueOf(-9223372036854775807L) // -2^63 + 1:  19 digits
+        };
+        // The array below contains the expected precision of the above numbers
+        int[] expectedPrecision = {10, 10, 11, 13, 15, 15, 16, 17, 19, 19};
+        for (int i = 0; i < randomTestValues.length; i++) {
+            testPrecision(randomTestValues[i], expectedPrecision[i]);
+        }
+    }
+
+    private static void testPrecision(BigDecimal bd, int expected) {
+        int precision = bd.precision();
+
+        Assert.assertEquals(precision, expected,
+                String.format("For (%s).precision expected %d, got %d%n", bd, expected, precision));
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/RangeTests.java b/ojluni/src/test/java/math/BigDecimal/RangeTests.java
new file mode 100644
index 0000000..07bcf75
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/RangeTests.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 7036582
+ * @summary Some new tests for the add method and constructor with MathContext.
+ * @run main RangeTests
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 RangeTests
+ * @author Sergey V. Kuksenko
+ */
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class RangeTests {
+
+    private static void addTest(BigDecimal arg1, BigDecimal arg2, BigDecimal expectedResult) {
+        BigDecimal result = arg1.add(arg2);
+        Assert.assertEquals(result, expectedResult, "Sum:" +
+                    arg1 + " + " +
+                    arg2 + " == " +
+                    result + "; expected  " +
+                    expectedResult
+            );
+        result = arg2.add(arg1);
+        Assert.assertEquals(result, expectedResult, "Sum:" +
+                    arg2 + " + " +
+                    arg1 + " == " +
+                    result + "; expected  " +
+                    expectedResult
+            );
+    }
+
+    /*
+     *  Test BigDecimal.add(BigDecimal) when values are withing different ranges:
+     *  1. within 32 bits
+     *  2. within 64 bits
+     *  3. outside 64 bits.
+     */
+    @Test
+    public void addBoundaryTest() {
+        addTest(
+                new BigDecimal("85070591730234615847396907784232501249"),
+                BigDecimal.valueOf(0),
+                new BigDecimal("85070591730234615847396907784232501249") );
+        addTest(
+                new BigDecimal("-85070591730234615847396907784232501249"),
+                BigDecimal.valueOf(0),
+                new BigDecimal("-85070591730234615847396907784232501249") );
+        addTest(
+                new BigDecimal("85070591730234615847396907784232501249"),
+                BigDecimal.valueOf(1),
+                new BigDecimal("85070591730234615847396907784232501250") );
+        addTest(
+                new BigDecimal("85070591730234615847396907784232501249"),
+                BigDecimal.valueOf(-1),
+                new BigDecimal("85070591730234615847396907784232501248") );
+        addTest(
+                new BigDecimal("-85070591730234615847396907784232501250"),
+                BigDecimal.valueOf(-1),
+                new BigDecimal("-85070591730234615847396907784232501251") );
+        addTest(
+                new BigDecimal("-85070591730234615847396907784232501249"),
+                BigDecimal.valueOf(1),
+                new BigDecimal("-85070591730234615847396907784232501248") );
+        addTest(
+                new BigDecimal("147573952589676412927"),
+                BigDecimal.valueOf(Integer.MAX_VALUE),
+                new BigDecimal("147573952591823896574") );
+        addTest(
+                new BigDecimal("-147573952589676412927"),
+                BigDecimal.valueOf(Integer.MAX_VALUE),
+                new BigDecimal("-147573952587528929280") );
+        addTest(
+                new BigDecimal("79228162514264337593543950335"),
+                BigDecimal.valueOf(999),
+                new BigDecimal("79228162514264337593543951334") );
+        addTest(
+                new BigDecimal("79228162514264337593543950335"),
+                BigDecimal.valueOf(Integer.MAX_VALUE/2),
+                new BigDecimal("79228162514264337594617692158") );
+        addTest(
+                new BigDecimal("79228162514264337593543950335"),
+                BigDecimal.valueOf(Integer.MIN_VALUE/2),
+                new BigDecimal("79228162514264337592470208511") );
+        addTest(
+                new BigDecimal("-79228162514264337593543950335"),
+                BigDecimal.valueOf(Integer.MAX_VALUE/2),
+                new BigDecimal("-79228162514264337592470208512") );
+        addTest(
+                new BigDecimal("79228162514264337593543950335"),
+                BigDecimal.valueOf(-(Integer.MIN_VALUE/2)),
+                new BigDecimal("79228162514264337594617692159") );
+        addTest(
+                new BigDecimal("79228162514264337593543950335"),
+                BigDecimal.valueOf(Long.MAX_VALUE/2),
+                new BigDecimal("79228162518876023611971338238") );
+        addTest(
+                new BigDecimal("79228162514264337593543950335"),
+                BigDecimal.valueOf(Long.MIN_VALUE/2),
+                new BigDecimal("79228162509652651575116562431") );
+        addTest(
+                new BigDecimal("-79228162514264337593543950335"),
+                BigDecimal.valueOf(Long.MAX_VALUE/2),
+                new BigDecimal("-79228162509652651575116562432") );
+        addTest(
+                new BigDecimal("79228162514264337593543950335"),
+                BigDecimal.valueOf(-(Long.MIN_VALUE/2)),
+                new BigDecimal("79228162518876023611971338239") );
+        addTest(
+                new BigDecimal("-9223372036854775808"),
+                BigDecimal.valueOf(1),
+                new BigDecimal("-9223372036854775807") );
+        addTest(
+                new BigDecimal("-9223372036854775808"),
+                BigDecimal.valueOf(Long.MAX_VALUE/2),
+                new BigDecimal("-4611686018427387905") );
+        addTest(
+                new BigDecimal("9223372036854775808"),
+                BigDecimal.valueOf(-1),
+                new BigDecimal("9223372036854775807") );
+        addTest(
+                new BigDecimal("9223372036854775808"),
+                BigDecimal.valueOf(-Long.MAX_VALUE/2),
+                new BigDecimal("4611686018427387905") );
+    }
+
+    private static void testRoundingFromBigInteger(BigInteger bi, int scale, MathContext mc) {
+        BigDecimal bd1 = new BigDecimal(bi,scale, mc);
+        BigDecimal bd2 = (new BigDecimal(bi,scale)).round(mc);
+        Assert.assertEquals(bd1, bd2, "new BigDecimal(BigInteger,int,MathContext):" +
+                    "BigInteger == " +
+                    bi + ";  scale == " + scale + "; result == " +
+                    bd1 + "; expected  == " +
+                    bd2
+            );
+    }
+
+    @Test
+    public void roundingConstructorTest() {
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                7, MathContext.DECIMAL64);
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                0, MathContext.DECIMAL64);
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                -7, MathContext.DECIMAL64);
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                7, MathContext.DECIMAL128);
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                177, MathContext.DECIMAL128);
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                177, MathContext.DECIMAL32);
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                177, MathContext.UNLIMITED);
+        testRoundingFromBigInteger(
+                new BigInteger("85070591730234615847396907784232501249"),
+                0, MathContext.UNLIMITED);
+    }
+
+    private static void minLongConstructorTest(MathContext mc) {
+        BigDecimal bd1 = new BigDecimal(Long.MIN_VALUE,mc);
+        BigDecimal bd2 = new BigDecimal(Long.MIN_VALUE).round(mc);
+        Assert.assertEquals(bd1, bd2, "new BigDecimal(long,MathContext):" +
+                    "long == " +
+                    Long.MIN_VALUE + "; result == " +
+                    bd1 + "; expected  == " +
+                    bd2
+            );
+    }
+
+    @Test
+    public void minLongConstructorTest() {
+        minLongConstructorTest(MathContext.UNLIMITED);
+        minLongConstructorTest(MathContext.DECIMAL32);
+        minLongConstructorTest(MathContext.DECIMAL64);
+        minLongConstructorTest(MathContext.DECIMAL128);
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/RoundingTests.java b/ojluni/src/test/java/math/BigDecimal/RoundingTests.java
new file mode 100644
index 0000000..1b4f258
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/RoundingTests.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6334849
+ * @summary Tests of dropping digits near the scale threshold
+ * @author Joseph D. Darcy
+ */
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class RoundingTests {
+
+    @Test
+    public void roundingTests() {
+        BigDecimal bd1 = BigDecimal.valueOf(11, Integer.MIN_VALUE);
+        BigDecimal bd2 = null;
+        MathContext mc = new MathContext(1);
+        try {
+                bd2 = bd1.round(mc); // should overflow here
+                Assert.fail(String.format("Did not get expected overflow rounding %s to %d digits, got %s%n",
+                                   bd1, mc.getPrecision(), bd2));
+        } catch(ArithmeticException e) {
+            ; // expected
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/ScaleByPowerOfTenTests.java b/ojluni/src/test/java/math/BigDecimal/ScaleByPowerOfTenTests.java
new file mode 100644
index 0000000..d70dcb0
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/ScaleByPowerOfTenTests.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4899722
+ * @summary Basic tests of scaleByPowerOfTen
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class ScaleByPowerOfTenTests {
+
+    @Test
+    public void testScaleByPowerOfTen() {
+        for (int i = -10; i < 10; i++) {
+            BigDecimal bd = BigDecimal.ONE.scaleByPowerOfTen(i);
+            BigDecimal expected;
+
+            expected = new BigDecimal(BigInteger.ONE, -i);
+            Assert.assertEquals(bd, expected, "Unexpected result " +
+                                           bd.toString() +
+                                           "; expected " +
+                                           expected);
+
+            bd = BigDecimal.ONE.negate().scaleByPowerOfTen(i);
+            expected = new BigDecimal(BigInteger.ONE.negate(), -i);
+            Assert.assertEquals(bd, expected, "Unexpected result " +
+                                           bd.toString() +
+                                           "; expected " +
+                                           expected);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/SerializationTests.java b/ojluni/src/test/java/math/BigDecimal/SerializationTests.java
new file mode 100644
index 0000000..d6b6499
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/SerializationTests.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 6177836
+ * @summary Verify BigDecimal objects with collapsed values are serialized properly.
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+import java.io.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class SerializationTests {
+
+    static void checkSerialForm(BigDecimal bd) throws Exception {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bos);
+        oos.writeObject(bd);
+        oos.flush();
+        oos.close();
+        ObjectInputStream ois = new
+            ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
+        BigDecimal tmp = (BigDecimal)ois.readObject();
+
+        if (!bd.equals(tmp) || bd.hashCode() != tmp.hashCode()) {
+            Assert.fail("  original : " + bd +
+                " (hash: 0x" + Integer.toHexString(bd.hashCode()) + ")" +
+                " serialized : " + tmp +
+                " (hash: 0x" + Integer.toHexString(tmp.hashCode()) + ")");
+        }
+    }
+
+    @Test
+    public void testSerialization() throws Exception {
+        BigDecimal values[] = {
+            BigDecimal.ZERO,
+            BigDecimal.ONE,
+            BigDecimal.TEN,
+            new BigDecimal(0),
+            new BigDecimal(1),
+            new BigDecimal(10),
+            new BigDecimal(Integer.MAX_VALUE),
+            new BigDecimal(Long.MAX_VALUE-1),
+            new BigDecimal(BigInteger.valueOf(1), 1),
+            new BigDecimal(BigInteger.valueOf(100), 50),
+        };
+
+        for(BigDecimal value : values) {
+            checkSerialForm(value);
+            checkSerialForm(value.negate());
+        }
+
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/SquareRootTests.java b/ojluni/src/test/java/math/BigDecimal/SquareRootTests.java
new file mode 100644
index 0000000..190ffb8
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/SquareRootTests.java
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4851777 8233452
+ * @summary Tests of BigDecimal.sqrt().
+ */
+
+import java.math.*;
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static java.math.BigDecimal.ONE;
+import static java.math.BigDecimal.TEN;
+import static java.math.BigDecimal.ZERO;
+import static java.math.BigDecimal.valueOf;
+
+// Android-changed: Replace error counting with asserts.
+public class SquareRootTests {
+    private static BigDecimal TWO = new BigDecimal(2);
+
+    /**
+     * The value 0.1, with a scale of 1.
+     */
+    private static final BigDecimal ONE_TENTH = valueOf(1L, 1);
+
+    @Test
+    public void negativeTests() {
+        for (long i = -10; i < 0; i++) {
+            for (int j = -5; j < 5; j++) {
+                try {
+                    BigDecimal input = BigDecimal.valueOf(i, j);
+                    BigDecimal result = input.sqrt(MathContext.DECIMAL64);
+                    Assert.fail("Unexpected sqrt of negative: (" +
+                                       input + ").sqrt()  = " + result );
+                } catch (ArithmeticException e) {
+                    ; // Expected
+                }
+            }
+        }
+    }
+
+    @Test
+    public void zeroTests() {
+        for (int i = -100; i < 100; i++) {
+            BigDecimal expected = BigDecimal.valueOf(0L, i/2);
+            // These results are independent of rounding mode
+            compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.UNLIMITED),
+                                expected, true, "zeros");
+
+            compare(BigDecimal.valueOf(0L, i).sqrt(MathContext.DECIMAL64),
+                                expected, true, "zeros");
+        }
+    }
+
+    /**
+     * Probe inputs with one digit of precision, 1 ... 9 and those
+     * values scaled by 10^-1, 0.1, ... 0.9.
+     */
+    @Test
+    public void oneDigitTests() {
+        int failures = 0;
+
+        List<BigDecimal> oneToNine =
+            List.of(ONE,        TWO,        valueOf(3),
+                    valueOf(4), valueOf(5), valueOf(6),
+                    valueOf(7), valueOf(8), valueOf(9));
+
+        List<RoundingMode> modes =
+            List.of(RoundingMode.UP,      RoundingMode.DOWN,
+                    RoundingMode.CEILING, RoundingMode.FLOOR,
+                    RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN);
+
+        for (int i = 1; i < 20; i++) {
+            for (RoundingMode rm : modes) {
+                for (BigDecimal bd  : oneToNine) {
+                    MathContext mc = new MathContext(i, rm);
+
+                    compareSqrtImplementations(bd, mc);
+                    bd = bd.multiply(ONE_TENTH);
+                    compareSqrtImplementations(bd, mc);
+                }
+            }
+        }
+
+        // return failures;
+    }
+
+    /**
+     * Probe inputs with two digits of precision, (10 ... 99) and
+     * those values scaled by 10^-1 (1, ... 9.9) and scaled by 10^-2
+     * (0.1 ... 0.99).
+     */
+    @Test
+    public void twoDigitTests() {
+        int failures = 0;
+
+        List<RoundingMode> modes =
+            List.of(RoundingMode.UP,      RoundingMode.DOWN,
+                    RoundingMode.CEILING, RoundingMode.FLOOR,
+                    RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN);
+
+        for (int i = 10; i < 100; i++) {
+            BigDecimal bd0 = BigDecimal.valueOf(i);
+            BigDecimal bd1 = bd0.multiply(ONE_TENTH);
+            BigDecimal bd2 = bd1.multiply(ONE_TENTH);
+
+            for (BigDecimal bd : List.of(bd0, bd1, bd2)) {
+                for (int precision = 1; i < 20; i++) {
+                    for (RoundingMode rm : modes) {
+                        MathContext mc = new MathContext(precision, rm);
+                        compareSqrtImplementations(bd, mc);
+                    }
+                }
+            }
+        }
+
+        // return failures;
+    }
+
+    private static void compareSqrtImplementations(BigDecimal bd, MathContext mc) {
+        equalNumerically(BigSquareRoot.sqrt(bd, mc),
+                                bd.sqrt(mc), "sqrt(" + bd + ") under " + mc);
+    }
+
+    /**
+     * sqrt(10^2N) is 10^N
+     * Both numerical value and representation should be verified
+     */
+    @Test
+    public void evenPowersOfTenTests() {
+        MathContext oneDigitExactly = new MathContext(1, RoundingMode.UNNECESSARY);
+
+        for (int scale = -100; scale <= 100; scale++) {
+            BigDecimal testValue               = BigDecimal.valueOf(1, 2*scale);
+            BigDecimal expectedNumericalResult = BigDecimal.valueOf(1,   scale);
+
+            BigDecimal result;
+
+
+            equalNumerically(expectedNumericalResult,
+                                           result = testValue.sqrt(MathContext.DECIMAL64),
+                                           "Even powers of 10, DECIMAL64");
+
+            // Can round to one digit of precision exactly
+            equalNumerically(expectedNumericalResult,
+                                           result = testValue.sqrt(oneDigitExactly),
+                                           "even powers of 10, 1 digit");
+            if (result.precision() > 1) {
+                Assert.fail("Excess precision for " + result);
+            }
+            // If rounding to more than one digit, do precision / scale checking...
+        }
+    }
+
+    @Test
+    public void squareRootTwoTests() {
+        BigDecimal TWO = new BigDecimal(2);
+
+        // Square root of 2 truncated to 65 digits
+        BigDecimal highPrecisionRoot2 =
+            new BigDecimal("1.41421356237309504880168872420969807856967187537694807317667973799");
+
+        RoundingMode[] modes = {
+            RoundingMode.UP,       RoundingMode.DOWN,
+            RoundingMode.CEILING, RoundingMode.FLOOR,
+            RoundingMode.HALF_UP, RoundingMode.HALF_DOWN, RoundingMode.HALF_EVEN
+        };
+
+
+        // For each interesting rounding mode, for precisions 1 to, say,
+        // 63 numerically compare TWO.sqrt(mc) to
+        // highPrecisionRoot2.round(mc) and the alternative internal high-precision
+        // implementation of square root.
+        for (RoundingMode mode : modes) {
+            for (int precision = 1; precision < 63; precision++) {
+                MathContext mc = new MathContext(precision, mode);
+                BigDecimal expected = highPrecisionRoot2.round(mc);
+                BigDecimal computed = TWO.sqrt(mc);
+                BigDecimal altComputed = BigSquareRoot.sqrt(TWO, mc);
+
+                equalNumerically(expected, computed, "sqrt(2)");
+                equalNumerically(computed, altComputed, "computed & altComputed");
+            }
+        }
+    }
+
+    @Test
+    public void lowPrecisionPerfectSquares() {
+        // For 5^2 through 9^2, if the input is rounded to one digit
+        // first before the root is computed, the wrong answer will
+        // result. Verify results and scale for different rounding
+        // modes and precisions.
+        long[][] squaresWithOneDigitRoot = {{ 4, 2},
+                                            { 9, 3},
+                                            {25, 5},
+                                            {36, 6},
+                                            {49, 7},
+                                            {64, 8},
+                                            {81, 9}};
+
+        for (long[] squareAndRoot : squaresWithOneDigitRoot) {
+            BigDecimal square     = new BigDecimal(squareAndRoot[0]);
+            BigDecimal expected   = new BigDecimal(squareAndRoot[1]);
+
+            for (int scale = 0; scale <= 4; scale++) {
+                BigDecimal scaledSquare = square.setScale(scale, RoundingMode.UNNECESSARY);
+                int expectedScale = scale/2;
+                for (int precision = 0; precision <= 5; precision++) {
+                    for (RoundingMode rm : RoundingMode.values()) {
+                        MathContext mc = new MathContext(precision, rm);
+                        BigDecimal computedRoot = scaledSquare.sqrt(mc);
+
+                        equalNumerically(expected, computedRoot, "simple squares");
+
+                        int computedScale = computedRoot.scale();
+                        if (precision >=  expectedScale + 1 && computedScale != expectedScale) {
+                            Assert.fail(String.format("%s\tprecision=%d\trm=%s%n",
+                                          computedRoot, precision, rm) +
+                                        String.format("\t%s does not have expected scale of %d%n.",
+                                              computedRoot, expectedScale));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Test around 3.9999 that the sqrt doesn't improperly round-up to
+     * a numerical value of 2.
+     */
+    @Test
+    public void almostFourRoundingDown() {
+        int failures = 0;
+        BigDecimal nearFour = new BigDecimal("3.999999999999999999999999999999");
+
+        // Sqrt is 1.9999...
+
+        for (int i = 1; i < 64; i++) {
+            MathContext mc = new MathContext(i, RoundingMode.FLOOR);
+            BigDecimal result = nearFour.sqrt(mc);
+            BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
+            equalNumerically(expected, result, "near four rounding down");
+            Assert.assertTrue(result.compareTo(TWO) < 0);
+        }
+
+        // return failures;
+    }
+
+    /**
+     * Test around 4.000...1 that the sqrt doesn't improperly
+     * round-down to a numerical value of 2.
+     */
+    @Test
+    public void almostFourRoundingUp() {
+        int failures = 0;
+        BigDecimal nearFour = new BigDecimal("4.000000000000000000000000000001");
+
+        // Sqrt is 2.0000....<non-zero digits>
+
+        for (int i = 1; i < 64; i++) {
+            MathContext mc = new MathContext(i, RoundingMode.CEILING);
+            BigDecimal result = nearFour.sqrt(mc);
+            BigDecimal expected = BigSquareRoot.sqrt(nearFour, mc);
+            equalNumerically(expected, result, "near four rounding up");
+            Assert.assertTrue(result.compareTo(TWO) > 0);
+        }
+
+        // return failures;
+    }
+
+    @Test
+    public void nearTen() {
+        int failures = 0;
+
+         BigDecimal near10 = new BigDecimal("9.99999999999999999999");
+
+         BigDecimal near10sq = near10.multiply(near10);
+
+         BigDecimal near10sq_ulp = near10sq.add(near10sq.ulp());
+
+        for (int i = 10; i < 23; i++) {
+            MathContext mc = new MathContext(i, RoundingMode.HALF_EVEN);
+
+            equalNumerically(BigSquareRoot.sqrt(near10sq_ulp, mc),
+                                         near10sq_ulp.sqrt(mc),
+                                         "near 10 rounding half even");
+        }
+
+        // return failures;
+    }
+
+
+    /*
+     * Probe for rounding failures near a power of ten, 1 = 10^0,
+     * where an ulp has a different size above and below the value.
+     */
+    @Test
+    public void nearOne() {
+        int failures = 0;
+
+         BigDecimal near1 = new BigDecimal(".999999999999999999999");
+         BigDecimal near1sq = near1.multiply(near1);
+         BigDecimal near1sq_ulp = near1sq.add(near1sq.ulp());
+
+         for (int i = 10; i < 23; i++) {
+             for (RoundingMode rm : List.of(RoundingMode.HALF_EVEN,
+                                            RoundingMode.UP,
+                                            RoundingMode.DOWN )) {
+                 MathContext mc = new MathContext(i, rm);
+                 equalNumerically(BigSquareRoot.sqrt(near1sq_ulp, mc),
+                                              near1sq_ulp.sqrt(mc),
+                                              mc.toString());
+             }
+         }
+
+         // return failures;
+    }
+
+
+
+    @Test
+    public void halfWay() {
+        int failures = 0;
+
+        /*
+         * Use enough digits that the exact result cannot be computed
+         * from the sqrt of a double.
+         */
+        BigDecimal[] halfWayCases = {
+            // Odd next digit, truncate on HALF_EVEN
+            new BigDecimal("123456789123456789.5"),
+
+             // Even next digit, round up on HALF_EVEN
+            new BigDecimal("123456789123456788.5"),
+        };
+
+        for (BigDecimal halfWayCase : halfWayCases) {
+            // Round result to next-to-last place
+            int precision = halfWayCase.precision() - 1;
+            BigDecimal square = halfWayCase.multiply(halfWayCase);
+
+            for (RoundingMode rm : List.of(RoundingMode.HALF_EVEN,
+                                           RoundingMode.HALF_UP,
+                                           RoundingMode.HALF_DOWN)) {
+                MathContext mc = new MathContext(precision, rm);
+
+                System.out.println("\nRounding mode " + rm);
+                System.out.println("\t" + halfWayCase.round(mc) + "\t" + halfWayCase);
+                System.out.println("\t" + BigSquareRoot.sqrt(square, mc));
+
+                equalNumerically(/*square.sqrt(mc),*/
+                                             BigSquareRoot.sqrt(square, mc),
+                                             halfWayCase.round(mc),
+                                             "Rounding halway " + rm);
+            }
+        }
+
+        // return failures;
+    }
+
+    private static void compare(BigDecimal a, BigDecimal b, boolean expected, String prefix) {
+        boolean result = a.equals(b);
+        Assert.assertEquals(result, expected, "Testing " + prefix +
+                               "(" + a + ").compareTo(" + b + ") => " + result +
+                               "\n\tExpected " + expected);
+    }
+
+    private static void equalNumerically(BigDecimal a, BigDecimal b, String prefix) {
+        compareNumerically(a, b, 0, prefix);
+    }
+
+    private static void compareNumerically(BigDecimal a, BigDecimal b,
+                                          int expected, String prefix) {
+        int result = a.compareTo(b);
+        Assert.assertEquals(result, expected, "Testing " + prefix +
+                               "(" + a + ").compareTo(" + b + ") => " + result +
+                               "\n\tExpected " + expected);
+    }
+
+    /**
+     * Alternative implementation of BigDecimal square root which uses
+     * higher-precision for a simpler set of termination conditions
+     * for the Newton iteration.
+     */
+    private static class BigSquareRoot {
+
+        /**
+         * The value 0.5, with a scale of 1.
+         */
+        private static final BigDecimal ONE_HALF = valueOf(5L, 1);
+
+        public static boolean isPowerOfTen(BigDecimal bd) {
+            return BigInteger.ONE.equals(bd.unscaledValue());
+        }
+
+        public static BigDecimal square(BigDecimal bd) {
+            return bd.multiply(bd);
+        }
+
+        public static BigDecimal sqrt(BigDecimal bd, MathContext mc) {
+            int signum = bd.signum();
+            if (signum == 1) {
+                /*
+                 * The following code draws on the algorithm presented in
+                 * "Properly Rounded Variable Precision Square Root," Hull and
+                 * Abrham, ACM Transactions on Mathematical Software, Vol 11,
+                 * No. 3, September 1985, Pages 229-237.
+                 *
+                 * The BigDecimal computational model differs from the one
+                 * presented in the paper in several ways: first BigDecimal
+                 * numbers aren't necessarily normalized, second many more
+                 * rounding modes are supported, including UNNECESSARY, and
+                 * exact results can be requested.
+                 *
+                 * The main steps of the algorithm below are as follows,
+                 * first argument reduce the value to the numerical range
+                 * [1, 10) using the following relations:
+                 *
+                 * x = y * 10 ^ exp
+                 * sqrt(x) = sqrt(y) * 10^(exp / 2) if exp is even
+                 * sqrt(x) = sqrt(y/10) * 10 ^((exp+1)/2) is exp is odd
+                 *
+                 * Then use Newton's iteration on the reduced value to compute
+                 * the numerical digits of the desired result.
+                 *
+                 * Finally, scale back to the desired exponent range and
+                 * perform any adjustment to get the preferred scale in the
+                 * representation.
+                 */
+
+                // The code below favors relative simplicity over checking
+                // for special cases that could run faster.
+
+                int preferredScale = bd.scale()/2;
+                BigDecimal zeroWithFinalPreferredScale =
+                    BigDecimal.valueOf(0L, preferredScale);
+
+                // First phase of numerical normalization, strip trailing
+                // zeros and check for even powers of 10.
+                BigDecimal stripped = bd.stripTrailingZeros();
+                int strippedScale = stripped.scale();
+
+                // Numerically sqrt(10^2N) = 10^N
+                if (isPowerOfTen(stripped) &&
+                    strippedScale % 2 == 0) {
+                    BigDecimal result = BigDecimal.valueOf(1L, strippedScale/2);
+                    if (result.scale() != preferredScale) {
+                        // Adjust to requested precision and preferred
+                        // scale as appropriate.
+                        result = result.add(zeroWithFinalPreferredScale, mc);
+                    }
+                    return result;
+                }
+
+                // After stripTrailingZeros, the representation is normalized as
+                //
+                // unscaledValue * 10^(-scale)
+                //
+                // where unscaledValue is an integer with the mimimum
+                // precision for the cohort of the numerical value. To
+                // allow binary floating-point hardware to be used to get
+                // approximately a 15 digit approximation to the square
+                // root, it is helpful to instead normalize this so that
+                // the significand portion is to right of the decimal
+                // point by roughly (scale() - precision() + 1).
+
+                // Now the precision / scale adjustment
+                int scaleAdjust = 0;
+                int scale = stripped.scale() - stripped.precision() + 1;
+                if (scale % 2 == 0) {
+                    scaleAdjust = scale;
+                } else {
+                    scaleAdjust = scale - 1;
+                }
+
+                BigDecimal working = stripped.scaleByPowerOfTen(scaleAdjust);
+
+                assert  // Verify 0.1 <= working < 10
+                    ONE_TENTH.compareTo(working) <= 0 && working.compareTo(TEN) < 0;
+
+                // Use good ole' Math.sqrt to get the initial guess for
+                // the Newton iteration, good to at least 15 decimal
+                // digits. This approach does incur the cost of a
+                //
+                // BigDecimal -> double -> BigDecimal
+                //
+                // conversion cycle, but it avoids the need for several
+                // Newton iterations in BigDecimal arithmetic to get the
+                // working answer to 15 digits of precision. If many fewer
+                // than 15 digits were needed, it might be faster to do
+                // the loop entirely in BigDecimal arithmetic.
+                //
+                // (A double value might have as much many as 17 decimal
+                // digits of precision; it depends on the relative density
+                // of binary and decimal numbers at different regions of
+                // the number line.)
+                //
+                // (It would be possible to check for certain special
+                // cases to avoid doing any Newton iterations. For
+                // example, if the BigDecimal -> double conversion was
+                // known to be exact and the rounding mode had a
+                // low-enough precision, the post-Newton rounding logic
+                // could be applied directly.)
+
+                BigDecimal guess = new BigDecimal(Math.sqrt(working.doubleValue()));
+                int guessPrecision = 15;
+                int originalPrecision = mc.getPrecision();
+                int targetPrecision;
+
+                // If an exact value is requested, it must only need
+                // about half of the input digits to represent since
+                // multiplying an N digit number by itself yield a (2N
+                // - 1) digit or 2N digit result.
+                if (originalPrecision == 0) {
+                    targetPrecision = stripped.precision()/2 + 1;
+                } else {
+                    targetPrecision = originalPrecision;
+                }
+
+                // When setting the precision to use inside the Newton
+                // iteration loop, take care to avoid the case where the
+                // precision of the input exceeds the requested precision
+                // and rounding the input value too soon.
+                BigDecimal approx = guess;
+                int workingPrecision = working.precision();
+                // Use "2p + 2" property to guarantee enough
+                // intermediate precision so that a double-rounding
+                // error does not occur when rounded to the final
+                // destination precision.
+                int loopPrecision =
+                    Math.max(2 * Math.max(targetPrecision, workingPrecision) + 2,
+                             34); // Force at least two Netwon
+                                  // iterations on the Math.sqrt
+                                  // result.
+                do {
+                    MathContext mcTmp = new MathContext(loopPrecision, RoundingMode.HALF_EVEN);
+                    // approx = 0.5 * (approx + fraction / approx)
+                    approx = ONE_HALF.multiply(approx.add(working.divide(approx, mcTmp), mcTmp));
+                    guessPrecision *= 2;
+                } while (guessPrecision < loopPrecision);
+
+                BigDecimal result;
+                RoundingMode targetRm = mc.getRoundingMode();
+                if (targetRm == RoundingMode.UNNECESSARY || originalPrecision == 0) {
+                    RoundingMode tmpRm =
+                        (targetRm == RoundingMode.UNNECESSARY) ? RoundingMode.DOWN : targetRm;
+                    MathContext mcTmp = new MathContext(targetPrecision, tmpRm);
+                    result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mcTmp);
+
+                    // If result*result != this numerically, the square
+                    // root isn't exact
+                    if (bd.subtract(square(result)).compareTo(ZERO) != 0) {
+                        throw new ArithmeticException("Computed square root not exact.");
+                    }
+                } else {
+                    result = approx.scaleByPowerOfTen(-scaleAdjust/2).round(mc);
+                }
+
+                assert squareRootResultAssertions(bd, result, mc);
+                if (result.scale() != preferredScale) {
+                    // The preferred scale of an add is
+                    // max(addend.scale(), augend.scale()). Therefore, if
+                    // the scale of the result is first minimized using
+                    // stripTrailingZeros(), adding a zero of the
+                    // preferred scale rounding the correct precision will
+                    // perform the proper scale vs precision tradeoffs.
+                    result = result.stripTrailingZeros().
+                        add(zeroWithFinalPreferredScale,
+                            new MathContext(originalPrecision, RoundingMode.UNNECESSARY));
+                }
+                return result;
+            } else {
+                switch (signum) {
+                case -1:
+                    throw new ArithmeticException("Attempted square root " +
+                                                  "of negative BigDecimal");
+                case 0:
+                    return valueOf(0L, bd.scale()/2);
+
+                default:
+                    throw new AssertionError("Bad value from signum");
+                }
+            }
+        }
+
+        /**
+         * For nonzero values, check numerical correctness properties of
+         * the computed result for the chosen rounding mode.
+         *
+         * For the directed roundings, for DOWN and FLOOR, result^2 must
+         * be {@code <=} the input and (result+ulp)^2 must be {@code >} the
+         * input. Conversely, for UP and CEIL, result^2 must be {@code >=} the
+         * input and (result-ulp)^2 must be {@code <} the input.
+         */
+        private static boolean squareRootResultAssertions(BigDecimal input, BigDecimal result, MathContext mc) {
+            if (result.signum() == 0) {
+                return squareRootZeroResultAssertions(input, result, mc);
+            } else {
+                RoundingMode rm = mc.getRoundingMode();
+                BigDecimal ulp = result.ulp();
+                BigDecimal neighborUp   = result.add(ulp);
+                // Make neighbor down accurate even for powers of ten
+                if (isPowerOfTen(result)) {
+                    ulp = ulp.divide(TEN);
+                }
+                BigDecimal neighborDown = result.subtract(ulp);
+
+                // Both the starting value and result should be nonzero and positive.
+                if (result.signum() != 1 ||
+                    input.signum() != 1) {
+                    return false;
+                }
+
+                switch (rm) {
+                case DOWN:
+                case FLOOR:
+                    assert
+                        square(result).compareTo(input)    <= 0 &&
+                        square(neighborUp).compareTo(input) > 0:
+                    "Square of result out for bounds rounding " + rm;
+                    return true;
+
+                case UP:
+                case CEILING:
+                    assert
+                        square(result).compareTo(input) >= 0 :
+                    "Square of result too small rounding " + rm;
+
+                    assert
+                        square(neighborDown).compareTo(input) < 0 :
+                    "Square of down neighbor too large rounding  " + rm + "\n" +
+                        "\t input: " + input + "\t neighborDown: " +  neighborDown +"\t sqrt: " + result +
+                        "\t" + mc;
+                    return true;
+
+
+                case HALF_DOWN:
+                case HALF_EVEN:
+                case HALF_UP:
+                    BigDecimal err = square(result).subtract(input).abs();
+                    BigDecimal errUp = square(neighborUp).subtract(input);
+                    BigDecimal errDown =  input.subtract(square(neighborDown));
+                    // All error values should be positive so don't need to
+                    // compare absolute values.
+
+                    int err_comp_errUp = err.compareTo(errUp);
+                    int err_comp_errDown = err.compareTo(errDown);
+
+                    assert
+                        errUp.signum()   == 1 &&
+                        errDown.signum() == 1 :
+                    "Errors of neighbors squared don't have correct signs";
+
+                    // At least one of these must be true, but not both
+//                     assert
+//                         err_comp_errUp   <= 0 : "Upper neighbor is closer than result: " + rm +
+//                         "\t" + input + "\t result" + result;
+//                     assert
+//                         err_comp_errDown <= 0 : "Lower neighbor is closer than result: " + rm +
+//                         "\t" + input + "\t result " + result + "\t lower neighbor: " + neighborDown;
+
+                    assert
+                        ((err_comp_errUp   == 0 ) ? err_comp_errDown < 0 : true) &&
+                        ((err_comp_errDown == 0 ) ? err_comp_errUp   < 0 : true) :
+                            "Incorrect error relationships";
+                        // && could check for digit conditions for ties too
+                        return true;
+
+                default: // Definition of UNNECESSARY already verified.
+                    return true;
+                }
+            }
+        }
+
+        private static boolean squareRootZeroResultAssertions(BigDecimal input,
+                                                              BigDecimal result,
+                                                              MathContext mc) {
+            return input.compareTo(ZERO) == 0;
+        }
+    }
+}
+
diff --git a/ojluni/src/test/java/math/BigDecimal/StringConstructor.java b/ojluni/src/test/java/math/BigDecimal/StringConstructor.java
new file mode 100644
index 0000000..a4f6dc6
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/StringConstructor.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main StringConstructor
+ * @bug 4103117 4331084 4488017 4490929 6255285 6268365 8074460 8078672
+ * @summary Tests the BigDecimal string constructor (use -Dseed=X to set PRNG seed).
+ * @key randomness
+ */
+
+import java.math.*;
+import java.util.Random;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class StringConstructor {
+
+    @Test
+    public void testBadStrings() {
+        constructWithError("");
+        constructWithError("+");
+        constructWithError("-");
+        constructWithError("+e");
+        constructWithError("-e");
+        constructWithError("e+");
+        constructWithError("1.-0");
+        constructWithError(".-123");
+        constructWithError("-");
+        constructWithError("--1.1");
+        constructWithError("-+1.1");
+        constructWithError("+-1.1");
+        constructWithError("1-.1");
+        constructWithError("1+.1");
+        constructWithError("1.111+1");
+        constructWithError("1.111-1");
+        constructWithError("11.e+");
+        constructWithError("11.e-");
+        constructWithError("11.e+-");
+        constructWithError("11.e-+");
+        constructWithError("11.e-+1");
+        constructWithError("11.e+-1");
+
+        // Range checks
+        constructWithError("1e" + Integer.MIN_VALUE);
+        constructWithError("10e" + Integer.MIN_VALUE);
+        constructWithError("0.01e" + Integer.MIN_VALUE);
+        constructWithError("1e" + ((long) Integer.MIN_VALUE - 1));
+        constructWithError("1e" + ((long) Integer.MAX_VALUE + 1));
+    }
+
+    @Test
+    public void testRoundtrip() {
+        // Roundtrip tests
+        Random random = new Random();
+        for (int i=0; i<100; i++) {
+            int size = random.nextInt(100) + 1;
+            BigInteger bi = new BigInteger(size, random);
+            if (random.nextBoolean())
+                bi = bi.negate();
+            int decimalLength = bi.toString().length();
+            int scale = random.nextInt(decimalLength);
+            BigDecimal bd = new BigDecimal(bi, scale);
+            String bdString = bd.toString();
+            BigDecimal bdDoppel = new BigDecimal(bdString);
+            Assert.assertEquals(bd, bdDoppel, "bd string: scale: " + bd.scale() +
+                                   "\t" + bdString + "\nbd doppel: scale: " + bdDoppel.scale() +
+                                   "\t" + bdDoppel.toString());
+        }
+    }
+
+    /*
+     * Verify precision is set properly if the significand has
+     * non-ASCII leading zeros.
+     */
+    @Test
+    public void nonAsciiZeroTest() {
+        String[] values = {
+            "00004e5",
+            "\u0660\u0660\u0660\u06604e5",
+        };
+
+        BigDecimal expected = new BigDecimal("4e5");
+
+        for(String s : values) {
+            BigDecimal tmp = new BigDecimal(s);
+            Assert.assertFalse(! expected.equals(tmp) || tmp.precision() != 1,
+                "Bad conversion of " + s + "got " +
+                                   tmp + "precision = " + tmp.precision());
+        }
+
+    }
+
+    @Test
+    public void testLeadingExponentZeroTest() {
+        BigDecimal twelve = new BigDecimal("12");
+        BigDecimal onePointTwo = new BigDecimal("1.2");
+
+        String start = "1.2e0";
+        String end = "1";
+        String middle = "";
+
+        // Test with more excess zeros than the largest number of
+        // decimal digits needed to represent a long
+        int limit  = ((int)Math.log10(Long.MAX_VALUE)) + 6;
+        for(int i = 0; i < limit; i++, middle += "0") {
+            String t1 = start + middle;
+            String t2 = t1 + end;
+
+            testString(t1, onePointTwo);
+            testString(t2, twelve);
+        }
+    }
+
+    private static void testString(String s, BigDecimal expected) {
+        testString0(s, expected);
+        testString0(switchZero(s), expected);
+    }
+
+    private static void testString0(String s, BigDecimal expected) {
+        Assert.assertEquals(new BigDecimal(s), expected, s + " is not equal to " + expected);
+    }
+
+    private static String switchZero(String s) {
+        return s.replace('0', '\u0660'); // Arabic-Indic zero
+    }
+
+    private static void constructWithError(String badString) {
+        try {
+            BigDecimal d = new BigDecimal(badString);
+            Assert.fail(badString + " accepted");
+        } catch(NumberFormatException e) {
+            // expected
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/StrippingZerosTest.java b/ojluni/src/test/java/math/BigDecimal/StrippingZerosTest.java
new file mode 100644
index 0000000..93084fd
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/StrippingZerosTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4108852
+ * @summary A few tests of stripTrailingZeros
+ * @run main StrippingZerosTest
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 StrippingZerosTest
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class StrippingZerosTest {
+
+    @Test
+    public void testStrippingZeros() {
+        BigDecimal [][] testCases = {
+            {new BigDecimal("1.00000"),         new BigDecimal("1")},
+            {new BigDecimal("1.000"),           new BigDecimal("1")},
+            {new BigDecimal("1"),               new BigDecimal("1")},
+            {new BigDecimal("0.1234"),          new BigDecimal("0.1234")},
+            {new BigDecimal("0.12340"),         new BigDecimal("0.1234")},
+            {new BigDecimal("0.12340000000"),   new BigDecimal("0.1234")},
+            {new BigDecimal("1234.5678"),       new BigDecimal("1234.5678")},
+            {new BigDecimal("1234.56780"),      new BigDecimal("1234.5678")},
+            {new BigDecimal("1234.567800000"),  new BigDecimal("1234.5678")},
+            {new BigDecimal("0"),               new BigDecimal("0")},
+            {new BigDecimal("0e2"),             BigDecimal.ZERO},
+            {new BigDecimal("0e-2"),            BigDecimal.ZERO},
+            {new BigDecimal("0e42"),            BigDecimal.ZERO},
+            {new BigDecimal("+0e42"),           BigDecimal.ZERO},
+            {new BigDecimal("-0e42"),           BigDecimal.ZERO},
+            {new BigDecimal("0e-42"),           BigDecimal.ZERO},
+            {new BigDecimal("+0e-42"),          BigDecimal.ZERO},
+            {new BigDecimal("-0e-42"),          BigDecimal.ZERO},
+            {new BigDecimal("0e-2"),            BigDecimal.ZERO},
+            {new BigDecimal("0e100"),           BigDecimal.ZERO},
+            {new BigDecimal("0e-100"),          BigDecimal.ZERO},
+            {new BigDecimal("10"),              new BigDecimal("1e1")},
+            {new BigDecimal("20"),              new BigDecimal("2e1")},
+            {new BigDecimal("100"),             new BigDecimal("1e2")},
+            {new BigDecimal("1000000000"),      new BigDecimal("1e9")},
+            {new BigDecimal("100000000e1"),     new BigDecimal("1e9")},
+            {new BigDecimal("10000000e2"),      new BigDecimal("1e9")},
+            {new BigDecimal("1000000e3"),       new BigDecimal("1e9")},
+            {new BigDecimal("100000e4"),        new BigDecimal("1e9")},
+            // BD value which larger than Long.MaxValue
+            {new BigDecimal("1.0000000000000000000000000000"),    new BigDecimal("1")},
+            {new BigDecimal("-1.0000000000000000000000000000"),   new BigDecimal("-1")},
+            {new BigDecimal("1.00000000000000000000000000001"),   new BigDecimal("1.00000000000000000000000000001")},
+            {new BigDecimal("1000000000000000000000000000000e4"), new BigDecimal("1e34")},
+        };
+
+        for(int i = 0; i < testCases.length; i++) {
+
+            BigDecimal stripped = testCases[i][0].stripTrailingZeros();
+            Assert.assertEquals(stripped, testCases[i][1],
+                "For input " + testCases[i][0].toString() +
+                           " did not received expected result " +
+                           testCases[i][1].toString() + ",  got " +
+                           testCases[i][0].stripTrailingZeros());
+
+            testCases[i][0] = testCases[i][0].negate();
+            testCases[i][1] = testCases[i][1].negate();
+
+            stripped = testCases[i][0].stripTrailingZeros();
+            Assert.assertEquals(stripped, testCases[i][1],
+                "For input " + testCases[i][0].toString() +
+                           " did not received expected result " +
+                           testCases[i][1].toString() + ",  got " +
+                           testCases[i][0].stripTrailingZeros());
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/ToPlainStringTests.java b/ojluni/src/test/java/math/BigDecimal/ToPlainStringTests.java
new file mode 100644
index 0000000..54a70af
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/ToPlainStringTests.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4984872
+ * @summary Basic tests of toPlainString method
+ * @run main ToPlainStringTests
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 ToPlainStringTests
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class ToPlainStringTests {
+
+    @Test
+    public void testToPlainString() {
+        String [][] testCases = {
+            {"0",                       "0"},
+            {"1",                       "1"},
+            {"10",                      "10"},
+            {"2e1",                     "20"},
+            {"3e2",                     "300"},
+            {"4e3",                     "4000"},
+            {"5e4",                     "50000"},
+            {"6e5",                     "600000"},
+            {"7e6",                     "7000000"},
+            {"8e7",                     "80000000"},
+            {"9e8",                     "900000000"},
+            {"1e9",                     "1000000000"},
+
+            {".0",                      "0.0"},
+            {".1",                      "0.1"},
+            {".10",                     "0.10"},
+            {"1e-1",                    "0.1"},
+            {"1e-1",                    "0.1"},
+            {"2e-2",                    "0.02"},
+            {"3e-3",                    "0.003"},
+            {"4e-4",                    "0.0004"},
+            {"5e-5",                    "0.00005"},
+            {"6e-6",                    "0.000006"},
+            {"7e-7",                    "0.0000007"},
+            {"8e-8",                    "0.00000008"},
+            {"9e-9",                    "0.000000009"},
+            {"9000e-12",                "0.000000009000"},
+
+            {"9000e-22",                 "0.0000000000000000009000"},
+            {"12345678901234567890",     "12345678901234567890"},
+            {"12345678901234567890e22",  "123456789012345678900000000000000000000000"},
+            {"12345678901234567890e-22", "0.0012345678901234567890"},
+        };
+
+        for(String[] testCase: testCases) {
+            BigDecimal bd = new BigDecimal(testCase[0]);
+            String s;
+
+            s = bd.toPlainString();
+            Assert.assertEquals(s, testCase[1],
+                "Unexpected plain result ``" + s + "'' from BigDecimal " + bd);
+
+            bd = new BigDecimal("-"+testCase[0]);
+            s = bd.toPlainString();
+            Assert.assertFalse(bd.signum()!=0 && !s.equals("-"+testCase[1]),
+                "Unexpected plain result ``" + s + "'' from BigDecimal " + bd);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigDecimal/ZeroScalingTests.java b/ojluni/src/test/java/math/BigDecimal/ZeroScalingTests.java
new file mode 100644
index 0000000..742abc3
--- /dev/null
+++ b/ojluni/src/test/java/math/BigDecimal/ZeroScalingTests.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigDecimal;
+
+/*
+ * @test
+ * @bug 4902952 4905407 4916149 8057793
+ * @summary Tests that the scale of zero is propagated properly and has the
+ * proper effect and that setting the scale to zero does not mutate the
+ * BigDecimal.
+ * @author Joseph D. Darcy
+ */
+
+import java.math.*;
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error counting with asserts.
+public class ZeroScalingTests {
+
+    static MathContext longEnough = new MathContext(50, RoundingMode.UNNECESSARY);
+
+    static BigDecimal[]  zeros = new BigDecimal[23];
+    static {
+        for(int i = 0; i < 21; i++) {
+            zeros[i] = new BigDecimal(BigInteger.ZERO, i-10);
+        }
+        zeros[21] = new BigDecimal(BigInteger.ZERO, Integer.MIN_VALUE);
+        zeros[22] = new BigDecimal(BigInteger.ZERO, Integer.MAX_VALUE);
+    }
+
+    static BigDecimal element = BigDecimal.valueOf(100, -2);
+
+    static MathContext[] contexts = {
+        new MathContext(0, RoundingMode.UNNECESSARY),
+        new MathContext(100, RoundingMode.UNNECESSARY),
+        new MathContext(5, RoundingMode.UNNECESSARY),
+        new MathContext(4, RoundingMode.UNNECESSARY),
+        new MathContext(3, RoundingMode.UNNECESSARY),
+        new MathContext(2, RoundingMode.UNNECESSARY),
+        new MathContext(1, RoundingMode.UNNECESSARY),
+    };
+
+
+    @Test
+    public void addTests() {
+        for(BigDecimal zero1: zeros) {
+            for(BigDecimal zero2: zeros) {
+                BigDecimal expected = new BigDecimal(BigInteger.ZERO,
+                                                     Math.max(zero1.scale(), zero2.scale()));
+                BigDecimal result = zero1.add(zero2);
+
+                Assert.assertEquals(result, expected, "For classic exact add, expected scale of " +
+                           expected.scale() + "; got " +
+                           result.scale() + ".");
+
+                result = zero1.add(zero2, MathContext.UNLIMITED);
+                Assert.assertEquals(result, expected, "For UNLIMITED math context add," +
+                           " expected scale of " +
+                           expected.scale() + "; got " +
+                           result.scale() + ".");
+
+                result = zero1.add(zero2, longEnough);
+                Assert.assertEquals(result, expected, "For longEnough math context add," +
+                           " expected scale of " +
+                           expected.scale() + "; got " +
+                           result.scale() + ".");
+            }
+        }
+
+        // Test effect of adding zero to a nonzero value.
+        for (MathContext mc: contexts) {
+            for (BigDecimal zero: zeros) {
+                if (Math.abs((long)zero.scale()) < 100 ) {
+
+                    int preferredScale = Math.max(zero.scale(), element.scale());
+                    if (mc.getPrecision() != 0) {
+                        if (preferredScale < -4 )
+                            preferredScale = -4;
+                        else if (preferredScale > -(5 - mc.getPrecision())) {
+                            preferredScale = -(5 - mc.getPrecision());
+                        }
+                    }
+
+                    BigDecimal result = element.add(zero, mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element) != 0,
+                        "Expected scale  " + preferredScale +
+                               " result scale was " + result.scale() +
+                               " ; value was " + result);
+
+                    result = zero.add(element, mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element) != 0,
+                        "Expected scale  " + preferredScale +
+                                   " result scale was " + result.scale() +
+                                   " ; value was " + result);
+
+                    result = element.negate().add(zero, mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element.negate()) != 0,
+                        "Expected scale  " + preferredScale +
+                                   " result scale was " + result.scale() +
+                                   " ; value was " + result);
+
+                    result = zero.add(element.negate(), mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element.negate()) != 0,
+                        "Expected scale  " + preferredScale +
+                                   " result scale was " + result.scale() +
+                                   " ; value was " + result);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void subtractTests() {
+        for(BigDecimal zero1: zeros) {
+            for(BigDecimal zero2: zeros) {
+                BigDecimal expected = new BigDecimal(BigInteger.ZERO,
+                                                     Math.max(zero1.scale(), zero2.scale()));
+                BigDecimal result = zero1.subtract(zero2);
+
+                Assert.assertEquals(result, expected,
+                    "For classic exact subtract, expected scale of " +
+                               expected.scale() + "; got " +
+                               result.scale() + ".");
+
+                result = zero1.subtract(zero2, MathContext.UNLIMITED);
+                Assert.assertEquals(result, expected, "For UNLIMITED math context subtract," +
+                           " expected scale of " +
+                           expected.scale() + "; got " +
+                           result.scale() + ".");
+
+                result = zero1.subtract(zero2, longEnough);
+                Assert.assertEquals(result, expected, "For longEnough math context subtract," +
+                           " expected scale of " +
+                           expected.scale() + "; got " +
+                           result.scale() + ".");
+            }
+        }
+
+
+        // Test effect of adding zero to a nonzero value.
+        for (MathContext mc: contexts) {
+            for (BigDecimal zero: zeros) {
+                if (Math.abs((long)zero.scale()) < 100 ) {
+
+                    int preferredScale = Math.max(zero.scale(), element.scale());
+                    if (mc.getPrecision() != 0) {
+                        if (preferredScale < -4 )
+                            preferredScale = -4;
+                        else if (preferredScale > -(5 - mc.getPrecision())) {
+                            preferredScale = -(5 - mc.getPrecision());
+                        }
+                    }
+
+                    BigDecimal result = element.subtract(zero, mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element) != 0,
+                        "Expected scale  " + preferredScale +
+                                           " result scale was " + result.scale() +
+                                           " ; value was " + result);
+
+                    result = zero.subtract(element, mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element.negate()) != 0,
+                        "Expected scale  " + preferredScale +
+                                   " result scale was " + result.scale() +
+                                   " ; value was " + result);
+
+                    result = element.negate().subtract(zero, mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element.negate()) != 0,
+                        "Expected scale  " + preferredScale +
+                                   " result scale was " + result.scale() +
+                                   " ; value was " + result);
+
+                    result = zero.subtract(element.negate(), mc);
+                    Assert.assertFalse(result.scale() != preferredScale ||
+                            result.compareTo(element) != 0,
+                        "Expected scale  " + preferredScale +
+                                   " result scale was " + result.scale() +
+                                   " ; value was " + result);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void multiplyTests() {
+        BigDecimal[] ones = {
+            BigDecimal.valueOf(1, 0),
+            BigDecimal.valueOf(10, 1),
+            BigDecimal.valueOf(1000, 3),
+            BigDecimal.valueOf(100000000, 8),
+        };
+
+        List<BigDecimal> values = new LinkedList<BigDecimal>();
+        values.addAll(Arrays.asList(zeros));
+        values.addAll(Arrays.asList(ones));
+
+        for(BigDecimal zero1: zeros) {
+            for(BigDecimal value: values) {
+                BigDecimal expected = new BigDecimal(BigInteger.ZERO,
+                                                     (int)Math.min(Math.max((long)zero1.scale()+value.scale(),
+                                                                            Integer.MIN_VALUE ),
+                                                                   Integer.MAX_VALUE ) );
+                BigDecimal result = zero1.multiply(value);
+
+                Assert.assertEquals(result, expected,
+                    "For classic exact multiply, expected scale of " +
+                               expected.scale() + "; got " +
+                               result.scale() + ".");
+
+                result = zero1.multiply(value, MathContext.UNLIMITED);
+                Assert.assertEquals(result, expected, "For UNLIMITED math context multiply," +
+                                       " expected scale of " +
+                                       expected.scale() + "; got " +
+                                       result.scale() + ".");
+
+                result = zero1.multiply(value, longEnough);
+                Assert.assertEquals(result, expected, "For longEnough math context multiply," +
+                           " expected scale of " +
+                           expected.scale() + "; got " +
+                           result.scale() + ".");
+            }
+        }
+    }
+
+    @Test
+    public void divideTests() {
+        BigDecimal [] ones = {
+            BigDecimal.valueOf(1, 0),
+            BigDecimal.valueOf(10, -1),
+            BigDecimal.valueOf(100, -2),
+            BigDecimal.valueOf(1000, -3),
+            BigDecimal.valueOf(1000000, -5),
+        };
+
+        for(BigDecimal one: ones) {
+            for(BigDecimal zero: zeros) {
+                BigDecimal expected = new BigDecimal(BigInteger.ZERO,
+                                                     (int)Math.min(Math.max((long)zero.scale() - one.scale(),
+                                                                            Integer.MIN_VALUE ),
+                                                                   Integer.MAX_VALUE ) );
+                BigDecimal result = zero.divide(one);
+
+                Assert.assertEquals(result, expected, "For classic exact divide, expected scale of " +
+                               expected.scale() + "; got " +
+                               result.scale() + ".");
+
+                result = zero.divide(one, MathContext.UNLIMITED);
+                Assert.assertEquals(result, expected, "For UNLIMITED math context divide," +
+                               " expected scale of " +
+                               expected.scale() + "; got " +
+                               result.scale() + ".");
+
+                result = zero.divide(one, longEnough);
+                Assert.assertEquals(result, expected, "For longEnough math context divide," +
+                               " expected scale of " +
+                               expected.scale() + "; got " +
+                               result.scale() + ".");
+            }
+        }
+    }
+
+    @Test
+    public void setScaleTests() {
+        int[] scales = {
+            Integer.MIN_VALUE,
+            Integer.MIN_VALUE+1,
+            -10000000,
+            -3,
+            -2,
+            -1,
+            0,
+            1,
+            2,
+            3,
+            10,
+            10000000,
+            Integer.MAX_VALUE-1,
+            Integer.MAX_VALUE
+        };
+
+        for(BigDecimal zero: zeros) {
+            for(int scale: scales) {
+                try {
+                    BigDecimal bd = zero.setScale(scale);
+                }
+                catch (ArithmeticException e) {
+                    Assert.fail("Exception when trying to set a scale of " + scale + " on " + zero);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void toEngineeringStringTests() {
+        String [][] testCases  = {
+            {"0E+10",   "0.00E+12"},
+            {"0E+9",    "0E+9"},
+            {"0E+8",    "0.0E+9"},
+            {"0E+7",    "0.00E+9"},
+
+            {"0E-10",   "0.0E-9"},
+            {"0E-9",    "0E-9"},
+            {"0E-8",    "0.00E-6"},
+            {"0E-7",    "0.0E-6"},
+        };
+
+        for(String[] testCase: testCases) {
+            BigDecimal bd = new BigDecimal(testCase[0]);
+            String result = bd.toEngineeringString();
+
+            Assert.assertFalse(!result.equals(testCase[1]) || !bd.equals(new BigDecimal(result)),
+                "From input ``" + testCase[0] + ",'' " +
+                           " bad engineering string output ``" + result +
+                           "''; expected ``" + testCase[1] + ".''");
+        }
+    }
+
+    @Test
+    public void ulpTests() {
+        for(BigDecimal zero: zeros) {
+            BigDecimal result;
+            BigDecimal expected = BigDecimal.valueOf(1, zero.scale());
+
+            result = zero.ulp();
+            Assert.assertEquals(result, expected, "Unexpected ulp value for zero value " +
+                       zero + "; expected " + expected +
+                       ", got " + result);
+        }
+    }
+
+    @Test
+    public void setScaleDoesNotMutateTest() {
+        BigDecimal total = new BigDecimal("258815507198903607775511093103396443816569106750031264155319238473795838680758514810110764742309284477206138527975952150289602995045050194333030191178778772026538699925775139201970526695485362661420908248887297829319881475178467494779683293036572059595504702727301324759997409522995072582369210284334718757260859794972695026582432867589093687280300148141501712013226636373167978223780290547640482160818746599330924736802844173226042389174403401903999447463440670236056324929325189403433689"
+                + ".426167432065785331444814035799717606745777287606858873045971898862329763544687891847664736523584843544347118836628373041412918374550458884706686730726101338872517021688769782894793734049819222924171842793485919753186993388451909096042127903835765393729547730953942175461146061715108701615615142134282261293656760570061554783195726716403304101469782303957325142638493327692352838806741611887655695029948975509680496573999174402058593454203190963443179532640446352828089016874853634851387762579319853267317320515941105912189838719919259277721994880193541634872882180184303434360412344059435559680494807415573269199203376126242271766939666939316648575065702750502798973418978204972336924254702551350654650573582614211506856383897692911422458286912085339575875324832979140870119455620532272318122103640233069115700020760625493816902806241630788230268031695140687964931377988962507263990468276009750998066442971308866347136022907166625330623130307555914930120150437900510530537258665172619821272937026713977709974434967165159545592482710663639966781678268622620229577009317698254134914742098420792313931843709810905414336383757407675429663714210967924767434203021205270369316797752411974617662200898086335322218191674846795163102021505555508444216708745911194321674887527227200297039471799580744303346354057273540730643842091810899490590914195225087593013834388801018488174855060306804024894292757613618190472234110859436472645203753139820658279559340251226992556744343475086923568365637919479462424794554522865559888240039662899509652221329892034706445253487898044421278283079233226845124525434586324657471286953226255430662125870993375281512713207125720748163498642795960457639954616530163959004770092547297392499137383176609646505351001304840762905826237024982330597805063521162285806541220110524989649256399233792799406995068469271941269511818994954109392839548141262324660472253632382325038836831429045617036015122388070240133760858500132713255407855625837956886349324981003917084922808187223285051144454915441134217743066575863563572152133978905444998209075763950909784148142018992367290485890072303179512881131769414783097454103103347826517701720263541869335631166977965013552647906729408522950996105479525445916501155305220090853891226367184989434453290788068397817927893708837722255115237672194162924260945492012622891770365546831236789867922136747819364833843397165107825773447549885351449899330007200651144003961228091210630807333236718793283427788965479074476288255387824982443633190938302785760754436525586544523339170400053128503337395428393881357669568532722167493096151221381017320147344991331421789379785964440840684363041795410525097564979585773948558651896834067324427900848255265001498890329859444233861478388742393060996236783742654761350763876989363052609107226398858310051497856931093693697981165801539060516895227818925342535261227134364063673285588256280386915163875872231395348293505967057794409379709079685798908660258077792158532257603211711587587586356431658240229896344639704");
+
+        Assert.assertEquals(total.setScale(0, RoundingMode.DOWN),
+             total.setScale(0, RoundingMode.DOWN));
+    }
+}
diff --git a/ojluni/src/test/java/math/BigInteger/BigIntegerTest.java b/ojluni/src/test/java/math/BigInteger/BigIntegerTest.java
new file mode 100644
index 0000000..0e8c4cd
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/BigIntegerTest.java
@@ -0,0 +1,1186 @@
+/*
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main BigIntegerTest
+ * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946 4026465 8074460 8078672 8032027
+ * @summary tests methods in BigInteger (use -Dseed=X to set PRNG seed)
+ * @run main/timeout=400 BigIntegerTest
+ * @author madbot
+ * @key randomness
+ */
+package test.java.math.BigInteger;
+
+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.util.Random;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * This is a simple test class created to ensure that the results
+ * generated by BigInteger adhere to certain identities. Passing
+ * this test is a strong assurance that the BigInteger operations
+ * are working correctly.
+ *
+ * Four arguments may be specified which give the number of
+ * decimal digits you desire in the four batches of test numbers.
+ *
+ * The tests are performed on arrays of random numbers which are
+ * generated by a Random class as well as special cases which
+ * throw in boundary numbers such as 0, 1, maximum sized, etc.
+ *
+ */
+
+// Android-changed: Replace error counting with asserts.
+public class BigIntegerTest {
+    //
+    // Bit large number thresholds based on the int thresholds
+    // defined in BigInteger itself:
+    //
+    // KARATSUBA_THRESHOLD        = 80  ints = 2560 bits
+    // TOOM_COOK_THRESHOLD        = 240 ints = 7680 bits
+    // KARATSUBA_SQUARE_THRESHOLD = 128 ints = 4096 bits
+    // TOOM_COOK_SQUARE_THRESHOLD = 216 ints = 6912 bits
+    //
+    // SCHOENHAGE_BASE_CONVERSION_THRESHOLD = 20 ints = 640 bits
+    //
+    // BURNIKEL_ZIEGLER_THRESHOLD = 80  ints = 2560 bits
+    //
+    static final int BITS_KARATSUBA = 2560;
+    static final int BITS_TOOM_COOK = 7680;
+    static final int BITS_KARATSUBA_SQUARE = 4096;
+    static final int BITS_TOOM_COOK_SQUARE = 6912;
+    static final int BITS_SCHOENHAGE_BASE = 640;
+    static final int BITS_BURNIKEL_ZIEGLER = 2560;
+    static final int BITS_BURNIKEL_ZIEGLER_OFFSET = 1280;
+
+    static final int ORDER_SMALL = 60;
+    static final int ORDER_MEDIUM = 100;
+    // #bits for testing Karatsuba
+    static final int ORDER_KARATSUBA = 2760;
+    // #bits for testing Toom-Cook and Burnikel-Ziegler
+    static final int ORDER_TOOM_COOK = 8000;
+    // #bits for testing Karatsuba squaring
+    static final int ORDER_KARATSUBA_SQUARE = 4200;
+    // #bits for testing Toom-Cook squaring
+    static final int ORDER_TOOM_COOK_SQUARE = 7000;
+
+    static final int SIZE = 1000; // numbers per batch
+
+    private static Random random = new Random();
+
+    static boolean failure = false;
+
+    private static void constructor() {
+        // --- guard condition tests for array indexing ---
+
+        int arrayLength = 23;
+        int halfLength = arrayLength/2;
+        byte[] array = new byte[arrayLength];
+        random.nextBytes(array);
+
+        int[][] offLen = new int[][] { // offset, length, num exceptions
+            {-1, arrayLength, 1},                         // negative offset
+            {0, arrayLength, 0},                          // OK
+            {1, arrayLength, 1},                          // length overflow
+            {arrayLength - 1, 1, 0},                      // OK
+            {arrayLength, 1, 1},                          // offset overflow
+            {0, -1, 1},                                   // negative length
+            {halfLength, arrayLength - halfLength + 1, 1} // length overflow
+        };
+
+        // two's complement
+        for (int[] ol : offLen) {
+            try {
+                BigInteger bi = new BigInteger(array, ol[0], ol[1]);
+                if (ol[2] == 1) {
+                    Assert.fail("IndexOutOfBoundsException did not occur for "
+                        + " two's complement constructor with parameters offset "
+                        + ol[0] + " and length " + ol[1]);
+                }
+            } catch (IndexOutOfBoundsException e) {
+                if (ol[2] == 0) {
+                    Assert.fail("Unexpected IndexOutOfBoundsException did occur for "
+                            + " two's complement constructor with parameters offset "
+                            + ol[0] + " and length " + ol[1]);
+                }
+            }
+        }
+
+        // sign-magnitude
+        for (int[] ol : offLen) {
+            try {
+                BigInteger bi = new BigInteger(1, array, ol[0], ol[1]);
+                if (ol[2] == 1) {
+                    Assert.fail("IndexOutOfBoundsException did not occur for "
+                        + " sign-magnitude constructor with parameters offset "
+                        + ol[0] + " and length " + ol[1]);
+                }
+            } catch (IndexOutOfBoundsException e) {
+                if (ol[2] == 0) {
+                    Assert.fail("Unexpected IndexOutOfBoundsException did occur for "
+                            + " two's complement constructor with parameters offset "
+                            + ol[0] + " and length " + ol[1]);
+                }
+            }
+        }
+
+        // --- tests for creation of zero-valued BigIntegers ---
+
+        byte[] magZeroLength = new byte[0];
+        for (int signum = -1; signum <= 1; signum++) {
+            BigInteger bi = new BigInteger(signum, magZeroLength);
+            Assert.assertEquals(bi.compareTo(BigInteger.ZERO), 0,
+                    "A: Zero length BigInteger != 0 for signum " + signum);
+        }
+
+        for (int signum = -1; signum <= 1; signum++) {
+            BigInteger bi = new BigInteger(signum, magZeroLength, 0, 0);
+            Assert.assertEquals(bi.compareTo(BigInteger.ZERO), 0,
+                    "B: Zero length BigInteger != 0 for signum " + signum);
+        }
+
+        byte[] magNonZeroLength = new byte[42];
+        random.nextBytes(magNonZeroLength);
+        for (int signum = -1; signum <= 1; signum++) {
+            BigInteger bi = new BigInteger(signum, magNonZeroLength, 0, 0);
+            Assert.assertEquals(bi.compareTo(BigInteger.ZERO), 0,
+                    "C: Zero length BigInteger != 0 for signum " + signum);
+        }
+
+        // --- tests for accurate creation of non-zero BigIntegers ---
+
+        for (int i = 0; i < SIZE; i++) {
+            // create reference value via a different code path from those tested
+            BigInteger reference = new BigInteger(2 + random.nextInt(336), 4, random);
+
+            byte[] refArray = reference.toByteArray();
+            int refLen = refArray.length;
+            int factor = random.nextInt(5);
+            int objLen = refArray.length + factor*random.nextInt(refArray.length) + 1;
+            int offset = random.nextInt(objLen - refLen);
+            byte[] objArray = new byte[objLen];
+            System.arraycopy(refArray, 0, objArray, offset, refLen);
+
+            BigInteger twosComp = new BigInteger(objArray, offset, refLen);
+            Assert.assertEquals(twosComp.compareTo(reference), 0,
+                    "Two's-complement BigInteger not equal for offset " +
+                        offset + " and length " + refLen);
+
+            boolean isNegative = random.nextBoolean();
+            BigInteger signMag = new BigInteger(isNegative ? -1 : 1, objArray, offset, refLen);
+            Assert.assertEquals(signMag.compareTo(isNegative ? reference.negate() : reference), 0,
+                    "Sign-magnitude BigInteger not equal for offset " +
+                        offset + " and length " + refLen);
+        }
+    }
+
+    private static void pow(int order) {
+        for (int i=0; i<SIZE; i++) {
+            // Test identity x^power == x*x*x ... *x
+            int power = random.nextInt(6) + 2;
+            BigInteger x = fetchNumber(order);
+            BigInteger y = x.pow(power);
+            BigInteger z = x;
+
+            for (int j=1; j<power; j++)
+                z = z.multiply(x);
+
+            Assert.assertEquals(y, z);
+        }
+    }
+
+    private static void square(int order) {
+        for (int i=0; i<SIZE; i++) {
+            // Test identity x^2 == x*x
+            BigInteger x  = fetchNumber(order);
+            BigInteger xx = x.multiply(x);
+            BigInteger x2 = x.pow(2);
+
+            Assert.assertEquals(x2, xx);
+        }
+    }
+
+    private static void checkResult(BigInteger expected, BigInteger actual, String failureMessage) {
+        Assert.assertEquals(expected.compareTo(actual), 0,
+                failureMessage + " - expected: " + expected + ", actual: " + actual);
+    }
+
+    private static void squareRootSmall() {
+        // A negative value should cause an exception.
+        BigInteger n = BigInteger.ONE.negate();
+        BigInteger s;
+        try {
+            s = n.sqrt();
+            // If sqrt() does not throw an exception that is a failure.
+            Assert.fail("sqrt() of negative number did not throw an exception");
+        } catch (ArithmeticException expected) {
+            // A negative value should cause an exception and is not a failure.
+        }
+
+        // A zero value should return BigInteger.ZERO.
+        checkResult(BigInteger.ZERO, BigInteger.ZERO.sqrt(), "sqrt(0) != BigInteger.ZERO");
+
+        // 1 <= value < 4 should return BigInteger.ONE.
+        long[] smalls = new long[] {1, 2, 3};
+        for (long small : smalls) {
+            checkResult(BigInteger.ONE, BigInteger.valueOf(small).sqrt(), "sqrt("+small+") != 1");
+        }
+    }
+
+    private static void squareRoot() {
+        squareRootSmall();
+
+
+        Function<BigInteger, Void> f = (n) -> {
+            // square root of n^2 -> n
+            BigInteger n2 = n.pow(2);
+            checkResult(n, n2.sqrt(), "sqrt() n^2 -> n");
+
+            // square root of n^2 + 1 -> n
+            BigInteger n2up = n2.add(BigInteger.ONE);
+            checkResult(n, n2up.sqrt(), "sqrt() n^2 + 1 -> n");
+
+            // square root of (n + 1)^2 - 1 -> n
+            BigInteger up = n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE);
+            checkResult(n, up.sqrt(), "sqrt() (n + 1)^2 - 1 -> n");
+
+            // sqrt(n)^2 <= n
+            BigInteger s = n.sqrt();
+            Assert.assertFalse(s.multiply(s).compareTo(n) > 0,
+                    "sqrt(n)^2 > n for n = " + n);
+
+            // (sqrt(n) + 1)^2 > n
+            Assert.assertFalse(s.add(BigInteger.ONE).pow(2).compareTo(n) <= 0,
+                    "(sqrt(n) + 1)^2 <= n for n = " + n);
+            return null;
+        };
+
+        Stream.Builder<BigInteger> sb = Stream.builder();
+        int maxExponent = Double.MAX_EXPONENT + 1;
+        for (int i = 1; i <= maxExponent; i++) {
+            BigInteger p2 = BigInteger.ONE.shiftLeft(i);
+            sb.add(p2.subtract(BigInteger.ONE));
+            sb.add(p2);
+            sb.add(p2.add(BigInteger.ONE));
+        }
+        sb.add((new BigDecimal(Double.MAX_VALUE)).toBigInteger());
+        sb.add((new BigDecimal(Double.MAX_VALUE)).toBigInteger().add(BigInteger.ONE));
+        // "squareRoot for 2^N and 2^N - 1, 1 <= N <= Double.MAX_EXPONENT"
+        sb.build().map(f).collect(Collectors.toList());
+
+        IntStream ints = random.ints(SIZE, 4, Integer.MAX_VALUE);
+        ints.mapToObj(BigInteger::valueOf).map(f).collect(Collectors.toList());
+
+        LongStream longs = random.longs(SIZE, (long)Integer.MAX_VALUE + 1L,
+            Long.MAX_VALUE);
+        longs.mapToObj(BigInteger::valueOf).map(f).collect(Collectors.toList());
+
+        DoubleStream doubles = random.doubles(SIZE,
+            (double) Long.MAX_VALUE + 1.0, Math.sqrt(Double.MAX_VALUE));
+        doubles.mapToObj(x -> BigDecimal.valueOf(x).toBigInteger()).map(f).collect(Collectors.toList());
+    }
+
+    private static void squareRootAndRemainder() {
+        Function<BigInteger, Void> g = (n) -> {
+            BigInteger n2 = n.pow(2);
+
+            // square root of n^2 -> n
+            BigInteger[] actual = n2.sqrtAndRemainder();
+            checkResult(n, actual[0], "sqrtAndRemainder()[0]");
+            checkResult(BigInteger.ZERO, actual[1], "sqrtAndRemainder()[1]");
+
+            // square root of n^2 + 1 -> n
+            BigInteger n2up = n2.add(BigInteger.ONE);
+            actual = n2up.sqrtAndRemainder();
+            checkResult(n, actual[0], "sqrtAndRemainder()[0]");
+            checkResult(BigInteger.ONE, actual[1], "sqrtAndRemainder()[1]");
+
+            // square root of (n + 1)^2 - 1 -> n
+            BigInteger up = n.add(BigInteger.ONE).pow(2).subtract(BigInteger.ONE);
+            actual = up.sqrtAndRemainder();
+            checkResult(n, actual[0], "sqrtAndRemainder()[0]");
+            BigInteger r = up.subtract(n2);
+            checkResult(r, actual[1], "sqrtAndRemainder()[1]");
+            return null;
+        };
+
+        IntStream bits = random.ints(SIZE, 3, Short.MAX_VALUE);
+        bits.mapToObj(BigInteger::valueOf).map(g).collect(Collectors.toList());
+    }
+
+    private static void arithmetic(int order) {
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(order);
+            while(x.compareTo(BigInteger.ZERO) != 1)
+                x = fetchNumber(order);
+            BigInteger y = fetchNumber(order/2);
+            while(x.compareTo(y) == -1)
+                y = fetchNumber(order/2);
+            if (y.equals(BigInteger.ZERO))
+                y = y.add(BigInteger.ONE);
+
+            // Test identity ((x/y))*y + x%y - x == 0
+            // using separate divide() and remainder()
+            BigInteger baz = x.divide(y);
+            baz = baz.multiply(y);
+            baz = baz.add(x.remainder(y));
+            baz = baz.subtract(x);
+            Assert.assertEquals(baz, BigInteger.ZERO);
+        }
+
+        for (int i=0; i<100; i++) {
+            BigInteger x = fetchNumber(order);
+            while(x.compareTo(BigInteger.ZERO) != 1)
+                x = fetchNumber(order);
+            BigInteger y = fetchNumber(order/2);
+            while(x.compareTo(y) == -1)
+                y = fetchNumber(order/2);
+            if (y.equals(BigInteger.ZERO))
+                y = y.add(BigInteger.ONE);
+
+            // Test identity ((x/y))*y + x%y - x == 0
+            // using divideAndRemainder()
+            BigInteger baz[] = x.divideAndRemainder(y);
+            baz[0] = baz[0].multiply(y);
+            baz[0] = baz[0].add(baz[1]);
+            baz[0] = baz[0].subtract(x);
+            Assert.assertEquals(baz[0], BigInteger.ZERO);
+        }
+    }
+
+    /**
+     * Sanity test for Karatsuba and 3-way Toom-Cook multiplication.
+     * For each of the Karatsuba and 3-way Toom-Cook multiplication thresholds,
+     * construct two factors each with a mag array one element shorter than the
+     * threshold, and with the most significant bit set and the rest of the bits
+     * random. Each of these numbers will therefore be below the threshold but
+     * if shifted left be above the threshold. Call the numbers 'u' and 'v' and
+     * define random shifts 'a' and 'b' in the range [1,32]. Then we have the
+     * identity
+     * <pre>
+     * (u << a)*(v << b) = (u*v) << (a + b)
+     * </pre>
+     * For Karatsuba multiplication, the right hand expression will be evaluated
+     * using the standard naive algorithm, and the left hand expression using
+     * the Karatsuba algorithm. For 3-way Toom-Cook multiplication, the right
+     * hand expression will be evaluated using Karatsuba multiplication, and the
+     * left hand expression using 3-way Toom-Cook multiplication.
+     */
+    private static void multiplyLarge() {
+        BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA - 32 - 1);
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(BITS_KARATSUBA - 32 - 1);
+            BigInteger u = base.add(x);
+            int a = 1 + random.nextInt(31);
+            BigInteger w = u.shiftLeft(a);
+
+            BigInteger y = fetchNumber(BITS_KARATSUBA - 32 - 1);
+            BigInteger v = base.add(y);
+            int b = 1 + random.nextInt(32);
+            BigInteger z = v.shiftLeft(b);
+
+            BigInteger multiplyResult = u.multiply(v).shiftLeft(a + b);
+            BigInteger karatsubaMultiplyResult = w.multiply(z);
+
+            Assert.assertEquals(karatsubaMultiplyResult, multiplyResult);
+        }
+
+        base = base.shiftLeft(BITS_TOOM_COOK - BITS_KARATSUBA);
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(BITS_TOOM_COOK - 32 - 1);
+            BigInteger u = base.add(x);
+            BigInteger u2 = u.shiftLeft(1);
+            BigInteger y = fetchNumber(BITS_TOOM_COOK - 32 - 1);
+            BigInteger v = base.add(y);
+            BigInteger v2 = v.shiftLeft(1);
+
+            BigInteger multiplyResult = u.multiply(v).shiftLeft(2);
+            BigInteger toomCookMultiplyResult = u2.multiply(v2);
+
+            Assert.assertEquals(toomCookMultiplyResult, multiplyResult);
+        }
+    }
+
+    /**
+     * Sanity test for Karatsuba and 3-way Toom-Cook squaring.
+     * This test is analogous to {@link AbstractMethodError#multiplyLarge}
+     * with both factors being equal. The squaring methods will not be tested
+     * unless the <code>bigInteger.multiply(bigInteger)</code> tests whether
+     * the parameter is the same instance on which the method is being invoked
+     * and calls <code>square()</code> accordingly.
+     */
+    private static void squareLarge() {
+        BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA_SQUARE - 32 - 1);
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(BITS_KARATSUBA_SQUARE - 32 - 1);
+            BigInteger u = base.add(x);
+            int a = 1 + random.nextInt(31);
+            BigInteger w = u.shiftLeft(a);
+
+            BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
+            BigInteger karatsubaSquareResult = w.multiply(w);
+
+            Assert.assertEquals(karatsubaSquareResult, squareResult);
+        }
+
+        base = base.shiftLeft(BITS_TOOM_COOK_SQUARE - BITS_KARATSUBA_SQUARE);
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(BITS_TOOM_COOK_SQUARE - 32 - 1);
+            BigInteger u = base.add(x);
+            int a = 1 + random.nextInt(31);
+            BigInteger w = u.shiftLeft(a);
+
+            BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
+            BigInteger toomCookSquareResult = w.multiply(w);
+
+            Assert.assertEquals(toomCookSquareResult, squareResult);
+        }
+    }
+
+    /**
+     * Sanity test for Burnikel-Ziegler division.  The Burnikel-Ziegler division
+     * algorithm is used when each of the dividend and the divisor has at least
+     * a specified number of ints in its representation.  This test is based on
+     * the observation that if {@code w = u*pow(2,a)} and {@code z = v*pow(2,b)}
+     * where {@code abs(u) > abs(v)} and {@code a > b && b > 0}, then if
+     * {@code w/z = q1*z + r1} and {@code u/v = q2*v + r2}, then
+     * {@code q1 = q2*pow(2,a-b)} and {@code r1 = r2*pow(2,b)}.  The test
+     * ensures that {@code v} is just under the B-Z threshold, that {@code z} is
+     * over the threshold and {@code w} is much larger than {@code z}. This
+     * implies that {@code u/v} uses the standard division algorithm and
+     * {@code w/z} uses the B-Z algorithm.  The results of the two algorithms
+     * are then compared using the observation described in the foregoing and
+     * if they are not equal a failure is logged.
+     */
+    private static void divideLarge() {
+        BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 33);
+        for (int i=0; i<SIZE; i++) {
+            BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 34, random);
+            BigInteger v = base.add(addend);
+
+            BigInteger u = v.multiply(BigInteger.valueOf(2 + random.nextInt(Short.MAX_VALUE - 1)));
+
+            if(random.nextBoolean()) {
+                u = u.negate();
+            }
+            if(random.nextBoolean()) {
+                v = v.negate();
+            }
+
+            int a = BITS_BURNIKEL_ZIEGLER_OFFSET + random.nextInt(16);
+            int b = 1 + random.nextInt(16);
+            BigInteger w = u.multiply(BigInteger.ONE.shiftLeft(a));
+            BigInteger z = v.multiply(BigInteger.ONE.shiftLeft(b));
+
+            BigInteger[] divideResult = u.divideAndRemainder(v);
+            divideResult[0] = divideResult[0].multiply(BigInteger.ONE.shiftLeft(a - b));
+            divideResult[1] = divideResult[1].multiply(BigInteger.ONE.shiftLeft(b));
+            BigInteger[] bzResult = w.divideAndRemainder(z);
+
+            Assert.assertEquals(divideResult[0].compareTo(bzResult[0]), 0);
+            Assert.assertEquals(divideResult[1].compareTo(bzResult[1]), 0);
+        }
+    }
+
+    private static void bitCount() {
+        for (int i=0; i<SIZE*10; i++) {
+            int x = random.nextInt();
+            BigInteger bigX = BigInteger.valueOf((long)x);
+            int bit = (x < 0 ? 0 : 1);
+            int tmp = x, bitCount = 0;
+            for (int j=0; j<32; j++) {
+                bitCount += ((tmp & 1) == bit ? 1 : 0);
+                tmp >>= 1;
+            }
+
+            Assert.assertEquals (bigX.bitCount(), bitCount);
+        }
+    }
+
+    private static void bitLength() {
+        for (int i=0; i<SIZE*10; i++) {
+            int x = random.nextInt();
+            BigInteger bigX = BigInteger.valueOf((long)x);
+            int signBit = (x < 0 ? 0x80000000 : 0);
+            int tmp = x, bitLength, j;
+            for (j=0; j<32 && (tmp & 0x80000000)==signBit; j++)
+                tmp <<= 1;
+            bitLength = 32 - j;
+
+            Assert.assertEquals(bigX.bitLength(), bitLength);
+        }
+    }
+
+    private static void bitOps(int order) {
+        for (int i=0; i<SIZE*5; i++) {
+            BigInteger x = fetchNumber(order);
+            BigInteger y;
+
+            // Test setBit and clearBit (and testBit)
+            if (x.signum() < 0) {
+                y = BigInteger.valueOf(-1);
+                for (int j=0; j<x.bitLength(); j++)
+                    if (!x.testBit(j))
+                        y = y.clearBit(j);
+            } else {
+                y = BigInteger.ZERO;
+                for (int j=0; j<x.bitLength(); j++)
+                    if (x.testBit(j))
+                        y = y.setBit(j);
+            }
+            Assert.assertEquals(y, x);
+
+            // Test flipBit (and testBit)
+            y = BigInteger.valueOf(x.signum()<0 ? -1 : 0);
+            for (int j=0; j<x.bitLength(); j++)
+                if (x.signum()<0  ^  x.testBit(j))
+                    y = y.flipBit(j);
+            Assert.assertEquals(y, x);
+        }
+
+        for (int i=0; i<SIZE*5; i++) {
+            BigInteger x = fetchNumber(order);
+
+            // Test getLowestSetBit()
+            int k = x.getLowestSetBit();
+            if (x.signum() == 0) {
+                Assert.assertEquals(k, -1);
+            } else {
+                BigInteger z = x.and(x.negate());
+                int j;
+                for (j=0; j<z.bitLength() && !z.testBit(j); j++)
+                    ;
+                Assert.assertEquals(k, j);
+            }
+        }
+    }
+
+    private static void bitwise(int order) {
+
+        // Test identity x^y == x|y &~ x&y
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(order);
+            BigInteger y = fetchNumber(order);
+            BigInteger z = x.xor(y);
+            BigInteger w = x.or(y).andNot(x.and(y));
+            Assert.assertEquals(z, w, "Test identity x^y == x|y &~ x&y");
+        }
+
+        // Test identity x &~ y == ~(~x | y)
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(order);
+            BigInteger y = fetchNumber(order);
+            BigInteger z = x.andNot(y);
+            BigInteger w = x.not().or(y).not();
+            Assert.assertEquals(z, w, "Test identity x &~ y == ~(~x | y)");
+        }
+    }
+
+    private static void shift(int order) {
+        for (int i=0; i<100; i++) {
+            BigInteger x = fetchNumber(order);
+            int n = Math.abs(random.nextInt()%200);
+
+            Assert.assertEquals(x.shiftLeft(n), x.multiply(BigInteger.valueOf(2L).pow(n)));
+
+            BigInteger y[] =x.divideAndRemainder(BigInteger.valueOf(2L).pow(n));
+            BigInteger z = (x.signum()<0 && y[1].signum()!=0
+                            ? y[0].subtract(BigInteger.ONE)
+                            : y[0]);
+
+            BigInteger b = x.shiftRight(n);
+
+            Assert.assertEquals(z, b);
+
+            Assert.assertEquals(x.shiftLeft(n).shiftRight(n), x);
+        }
+    }
+
+    private static void divideAndRemainder(int order) {
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(order).abs();
+            while(x.compareTo(BigInteger.valueOf(3L)) != 1)
+                x = fetchNumber(order).abs();
+            BigInteger z = x.divide(BigInteger.valueOf(2L));
+            BigInteger y[] = x.divideAndRemainder(x);
+
+            Assert.assertEquals(y[0], BigInteger.ONE);
+            Assert.assertEquals(y[1], BigInteger.ZERO);
+
+            y = x.divideAndRemainder(z);
+            Assert.assertEquals(y[0], BigInteger.valueOf(2));
+        }
+    }
+
+    private static void stringConv_generic() {
+        // Generic string conversion.
+        for (int i=0; i<100; i++) {
+            byte[] xBytes = new byte[Math.abs(random.nextInt())%100+1];
+            random.nextBytes(xBytes);
+            BigInteger x = new BigInteger(xBytes);
+
+            for (int radix=Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) {
+                String result = x.toString(radix);
+                BigInteger test = new BigInteger(result, radix);
+                Assert.assertEquals(test, x,
+                        "BigInteger toString: "+x+" Test: "+test+" radix: " + radix);
+            }
+        }
+    }
+
+    private static void stringConv_schoenhage(int k, int samples) {
+        // String conversion straddling the Schoenhage algorithm crossover
+        // threshold, and at twice and four times the threshold.
+        int factor = 1 << k;
+        int upper = factor * BITS_SCHOENHAGE_BASE + 33;
+        int lower = upper - 35;
+
+        for (int bits = upper; bits >= lower; bits--) {
+            for (int i = 0; i < samples; i++) {
+                BigInteger x = BigInteger.ONE.shiftLeft(bits - 1).or(new BigInteger(bits - 2, random));
+
+                for (int radix = Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) {
+                    String result = x.toString(radix);
+                    BigInteger test = new BigInteger(result, radix);
+                    Assert.assertEquals(test, x,
+                            "BigInteger toString: "+x+" Test: "+test+" radix: " + radix);
+                }
+            }
+        }
+    }
+
+    private static void byteArrayConv(int order) {
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(order);
+            while (x.equals(BigInteger.ZERO))
+                x = fetchNumber(order);
+            BigInteger y = new BigInteger(x.toByteArray());
+            Assert.assertEquals(y, x, "orig is " + x + ", new is " + y);
+        }
+    }
+
+    private static void modInv(int order) {
+        for (int i=0; i<SIZE; i++) {
+            BigInteger x = fetchNumber(order);
+            while(x.equals(BigInteger.ZERO))
+                x = fetchNumber(order);
+            BigInteger m = fetchNumber(order).abs();
+            while(m.compareTo(BigInteger.ONE) != 1)
+                m = fetchNumber(order).abs();
+
+            try {
+                BigInteger inv = x.modInverse(m);
+                BigInteger prod = inv.multiply(x).remainder(m);
+
+                if (prod.signum() == -1)
+                    prod = prod.add(m);
+
+                Assert.assertEquals(prod, BigInteger.ONE);
+            } catch(ArithmeticException ignored) {
+            }
+        }
+    }
+
+    private static void modExp(int order1, int order2) {
+        for (int i=0; i<SIZE/10; i++) {
+            BigInteger m = fetchNumber(order1).abs();
+            while(m.compareTo(BigInteger.ONE) != 1)
+                m = fetchNumber(order1).abs();
+            BigInteger base = fetchNumber(order2);
+            BigInteger exp = fetchNumber(8).abs();
+
+            BigInteger z = base.modPow(exp, m);
+            BigInteger w = base.pow(exp.intValue()).mod(m);
+
+            Assert.assertEquals(z, w, "z is "+z+" w is "+w+" mod is "+m+" base is "+base+" exp is "+exp);
+        }
+    }
+
+    // This test is based on Fermat's theorem
+    // which is not ideal because base must not be multiple of modulus
+    // and modulus must be a prime or pseudoprime (Carmichael number)
+    private static void modExp2(int order) {
+        for (int i=0; i<10; i++) {
+            BigInteger m = new BigInteger(100, 5, random);
+            while(m.compareTo(BigInteger.ONE) != 1)
+                m = new BigInteger(100, 5, random);
+            BigInteger exp = m.subtract(BigInteger.ONE);
+            BigInteger base = fetchNumber(order).abs();
+            while(base.compareTo(m) != -1)
+                base = fetchNumber(order).abs();
+            while(base.equals(BigInteger.ZERO))
+                base = fetchNumber(order).abs();
+
+            BigInteger one = base.modPow(exp, m);
+            Assert.assertEquals(one, BigInteger.ONE, "m is "+m+" base is "+base+" exp is "+exp);
+        }
+    }
+
+    private static final int[] mersenne_powers = {
+        521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937,
+        21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433,
+        1257787, 1398269, 2976221, 3021377, 6972593, 13466917 };
+
+    private static final long[] carmichaels = {
+      561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633,
+      62745,63973,75361,101101,115921,126217,162401,172081,188461,252601,
+      278545,294409,314821,334153,340561,399001,410041,449065,488881,512461,
+      225593397919L };
+
+    // Note: testing the larger ones takes too long.
+    private static final int NUM_MERSENNES_TO_TEST = 7;
+    // Note: this constant used for computed Carmichaels, not the array above
+    private static final int NUM_CARMICHAELS_TO_TEST = 5;
+
+    private static final String[] customer_primes = {
+        "120000000000000000000000000000000019",
+        "633825300114114700748351603131",
+        "1461501637330902918203684832716283019651637554291",
+        "779626057591079617852292862756047675913380626199",
+        "857591696176672809403750477631580323575362410491",
+        "910409242326391377348778281801166102059139832131",
+        "929857869954035706722619989283358182285540127919",
+        "961301750640481375785983980066592002055764391999",
+        "1267617700951005189537696547196156120148404630231",
+        "1326015641149969955786344600146607663033642528339" };
+
+    private static final BigInteger ZERO = BigInteger.ZERO;
+    private static final BigInteger ONE = BigInteger.ONE;
+    private static final BigInteger TWO = new BigInteger("2");
+    private static final BigInteger SIX = new BigInteger("6");
+    private static final BigInteger TWELVE = new BigInteger("12");
+    private static final BigInteger EIGHTEEN = new BigInteger("18");
+
+    private static void prime() {
+        BigInteger p1, p2, c1;
+
+        // Test consistency
+        for(int i=0; i<10; i++) {
+            p1 = BigInteger.probablePrime(100, random);
+            Assert.assertTrue(p1.isProbablePrime(100), p1.toString(16));
+        }
+
+        // Test some known Mersenne primes (2^n)-1
+        // The array holds the exponents, not the numbers being tested
+        for (int i=0; i<NUM_MERSENNES_TO_TEST; i++) {
+            p1 = new BigInteger("2");
+            p1 = p1.pow(mersenne_powers[i]);
+            p1 = p1.subtract(BigInteger.ONE);
+            Assert.assertTrue(p1.isProbablePrime(100), "Mersenne prime "+i+ " failed.");
+        }
+
+        // Test some primes reported by customers as failing in the past
+        for (int i=0; i<customer_primes.length; i++) {
+            p1 = new BigInteger(customer_primes[i]);
+            Assert.assertTrue(p1.isProbablePrime(100), "Customer prime "+i+ " failed.");
+        }
+
+        // Test some known Carmichael numbers.
+        for (int i=0; i<carmichaels.length; i++) {
+            c1 = BigInteger.valueOf(carmichaels[i]);
+            Assert.assertFalse(c1.isProbablePrime(100), "Carmichael "+i+ " reported as prime.");
+        }
+
+        // Test some computed Carmichael numbers.
+        // Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if
+        // each of the factors is prime
+        int found = 0;
+        BigInteger f1 = new BigInteger(40, 100, random);
+        while (found < NUM_CARMICHAELS_TO_TEST) {
+            BigInteger k = null;
+            BigInteger f2, f3;
+            f1 = f1.nextProbablePrime();
+            BigInteger[] result = f1.subtract(ONE).divideAndRemainder(SIX);
+            if (result[1].equals(ZERO)) {
+                k = result[0];
+                f2 = k.multiply(TWELVE).add(ONE);
+                if (f2.isProbablePrime(100)) {
+                    f3 = k.multiply(EIGHTEEN).add(ONE);
+                    if (f3.isProbablePrime(100)) {
+                        c1 = f1.multiply(f2).multiply(f3);
+                        Assert.assertFalse(c1.isProbablePrime(100), "Computed Carmichael "
+                                               +c1.toString(16));
+                        found++;
+                    }
+                }
+            }
+            f1 = f1.add(TWO);
+        }
+
+        // Test some composites that are products of 2 primes
+        for (int i=0; i<50; i++) {
+            p1 = BigInteger.probablePrime(100, random);
+            p2 = BigInteger.probablePrime(100, random);
+            c1 = p1.multiply(p2);
+            Assert.assertFalse(c1.isProbablePrime(100),
+                    "Composite failed "+c1.toString(16));
+        }
+
+        for (int i=0; i<4; i++) {
+            p1 = BigInteger.probablePrime(600, random);
+            p2 = BigInteger.probablePrime(600, random);
+            c1 = p1.multiply(p2);
+            Assert.assertFalse(c1.isProbablePrime(100),
+                    "Composite failed "+c1.toString(16));
+        }
+    }
+
+    private static final long[] primesTo100 = {
+        2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97
+    };
+
+    private static final long[] aPrimeSequence = {
+        1999999003L, 1999999013L, 1999999049L, 1999999061L, 1999999081L,
+        1999999087L, 1999999093L, 1999999097L, 1999999117L, 1999999121L,
+        1999999151L, 1999999171L, 1999999207L, 1999999219L, 1999999271L,
+        1999999321L, 1999999373L, 1999999423L, 1999999439L, 1999999499L,
+        1999999553L, 1999999559L, 1999999571L, 1999999609L, 1999999613L,
+        1999999621L, 1999999643L, 1999999649L, 1999999657L, 1999999747L,
+        1999999763L, 1999999777L, 1999999811L, 1999999817L, 1999999829L,
+        1999999853L, 1999999861L, 1999999871L, 1999999873
+    };
+
+    private static void nextProbablePrime() throws Exception {
+        BigInteger p1, p2, p3;
+        p1 = p2 = p3 = ZERO;
+
+        // First test nextProbablePrime on the low range starting at zero
+        for (long l : primesTo100) {
+            p1 = p1.nextProbablePrime();
+            Assert.assertEquals(p1.longValue(), l,
+                    "low range primes failed: p1 is " + p1 + ", expected " + l);
+        }
+
+        // Test nextProbablePrime on a relatively small, known prime sequence
+        p1 = BigInteger.valueOf(aPrimeSequence[0]);
+        for (int i=1; i<aPrimeSequence.length; i++) {
+            p1 = p1.nextProbablePrime();
+            Assert.assertEquals(p1.longValue(), aPrimeSequence[i], "prime sequence failed");
+        }
+
+        // Next, pick some large primes, use nextProbablePrime to find the
+        // next one, and make sure there are no primes in between
+        for (int i=0; i<100; i+=10) {
+            p1 = BigInteger.probablePrime(50 + i, random);
+            p2 = p1.add(ONE);
+            p3 = p1.nextProbablePrime();
+            while(p2.compareTo(p3) < 0) {
+                Assert.assertFalse(p2.isProbablePrime(100),
+                        "nextProbablePrime failed along range "+p1.toString(16)+" to "+p3.toString(16));
+                p2 = p2.add(ONE);
+            }
+        }
+    }
+
+    // Android-changed: Replace File streams with ByteArray
+    public static void serialize() throws Exception {
+        String[] bitPatterns = {
+             "ffffffff00000000ffffffff00000000ffffffff00000000",
+             "ffffffffffffffffffffffff000000000000000000000000",
+             "ffffffff0000000000000000000000000000000000000000",
+             "10000000ffffffffffffffffffffffffffffffffffffffff",
+             "100000000000000000000000000000000000000000000000",
+             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "-ffffffff00000000ffffffff00000000ffffffff00000000",
+            "-ffffffffffffffffffffffff000000000000000000000000",
+            "-ffffffff0000000000000000000000000000000000000000",
+            "-10000000ffffffffffffffffffffffffffffffffffffffff",
+            "-100000000000000000000000000000000000000000000000",
+            "-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+        };
+
+        for (String bitPattern : bitPatterns) {
+            BigInteger b1 = new BigInteger(bitPattern, 16);
+            BigInteger b2 = null;
+
+            try (ByteArrayOutputStream fos = new ByteArrayOutputStream()) {
+                try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
+                    oos.writeObject(b1);
+                    oos.flush();
+                }
+
+                try (ByteArrayInputStream fis = new ByteArrayInputStream(fos.toByteArray());
+                        ObjectInputStream ois = new ObjectInputStream(fis)) {
+                    b2 = (BigInteger) ois.readObject();
+                }
+
+                Assert.assertEquals(b1, b2, "Serialized failed for hex " + b1.toString(16));
+                Assert.assertEquals(b1.or(b2), b1, "Serialized failed for hex " + b1.toString(16));
+            }
+        }
+
+        for(int i=0; i<10; i++) {
+            BigInteger b1 = fetchNumber(random.nextInt(100));
+            BigInteger b2 = null;
+
+            try (ByteArrayOutputStream fos = new ByteArrayOutputStream()) {
+                try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
+                    oos.writeObject(b1);
+                    oos.flush();
+                }
+
+                try (ByteArrayInputStream fis = new ByteArrayInputStream(fos.toByteArray());
+                     ObjectInputStream ois = new ObjectInputStream(fis))
+                {
+                    b2 = (BigInteger)ois.readObject();
+                }
+            }
+
+            Assert.assertEquals(b1, b2, "Serialized failed for hex " + b1.toString(16));
+            Assert.assertEquals(b1.or(b2), b1, "Serialized failed for hex " + b1.toString(16));
+        }
+    }
+
+    private static final int ORDER_1 = ORDER_MEDIUM;
+    private static final int ORDER_2 = ORDER_SMALL;
+    private static final int ORDER_3 = ORDER_KARATSUBA;
+    private static final int ORDER_4 = ORDER_TOOM_COOK;
+
+    @Test
+    public void testConstructor() {
+        constructor();
+    }
+
+    @Test
+    public void testPrime() {
+        prime();
+    }
+
+    @Test
+    public void testNextProbablePrime() throws Exception {
+        nextProbablePrime();
+    }
+
+    @Test
+    public void testArithmetic() {
+        arithmetic(ORDER_1);   // small numbers
+        arithmetic(ORDER_3);   // Karatsuba range
+        arithmetic(ORDER_4);   // Toom-Cook / Burnikel-Ziegler range
+    }
+
+    @Test
+    public void testDivideAndReminder() {
+        divideAndRemainder(ORDER_1);   // small numbers
+        divideAndRemainder(ORDER_3);   // Karatsuba range
+        divideAndRemainder(ORDER_4);   // Toom-Cook / Burnikel-Ziegler range
+    }
+
+    @Test
+    public void testPow() {
+        pow(ORDER_1);
+        pow(ORDER_3);
+        pow(ORDER_4);
+    }
+
+    @Test
+    public void testSquare() {
+        square(ORDER_MEDIUM);
+        square(ORDER_KARATSUBA_SQUARE);
+        square(ORDER_TOOM_COOK_SQUARE);
+    }
+
+    @Test
+    public void testSquareRoot() {
+        squareRoot();
+    }
+
+    @Test
+    public void testSquareRootAndReminder() {
+        squareRootAndRemainder();
+    }
+
+    @Test
+    public void testBitCount() {
+        bitCount();
+    }
+
+    @Test
+    public void testBitLength() {
+        bitLength();
+    }
+
+    @Test
+    public void testBitOps() {
+        bitOps(ORDER_1);
+    }
+
+    @Test
+    public void testBitwise() {
+        bitwise(ORDER_1);
+    }
+
+    @Test
+    public void testShift() {
+        shift(ORDER_1);
+    }
+
+    @Test
+    public void testByteArrayConv() {
+        byteArrayConv(ORDER_1);
+    }
+
+    @Test
+    public void testModInv() {
+        modInv(ORDER_1);   // small numbers
+        modInv(ORDER_3);   // Karatsuba range
+        modInv(ORDER_4);   // Toom-Cook / Burnikel-Ziegler range
+    }
+
+    @Test
+    public void testModExp() {
+        modExp(ORDER_1, ORDER_2);
+        modExp2(ORDER_1);
+    }
+
+    @Test
+    public void testStringConv_generic() {
+        stringConv_generic();
+    }
+
+    // String conversion straddling the Schoenhage algorithm crossover
+    // threshold.
+    @Test
+    public void testStringConv_schoenhage_threshold_pow0() {
+        stringConv_schoenhage(0, 50);
+    }
+
+    // String conversion straddling the Schoenhage algorithm crossover
+    // at twice times the threshold.
+    @Test
+    public void testStringConv_schoenhage_threshold_pow1() {
+        stringConv_schoenhage(1, 50);
+    }
+
+    // String conversion straddling the Schoenhage algorithm crossover
+    // at four times the threshold.
+    @Test
+    public void testStringConv_schoenhage_threshold_pow2() {
+        stringConv_schoenhage(2, 15);
+    }
+
+    @Test
+    public void testSerialize() throws Exception {
+        serialize();
+    }
+
+    @Test
+    public void testMultiplyLarge() {
+        multiplyLarge();
+    }
+
+    @Test
+    public void testSquareLarge() {
+        squareLarge();
+    }
+
+    @Test
+    public void testDivideLarge() {
+        divideLarge();
+    }
+
+    /*
+     * Get a random or boundary-case number. This is designed to provide
+     * a lot of numbers that will find failure points, such as max sized
+     * numbers, empty BigIntegers, etc.
+     *
+     * If order is less than 2, order is changed to 2.
+     */
+    private static BigInteger fetchNumber(int order) {
+        boolean negative = random.nextBoolean();
+        int numType = random.nextInt(7);
+        BigInteger result = null;
+        if (order < 2) order = 2;
+
+        switch (numType) {
+            case 0: // Empty
+                result = BigInteger.ZERO;
+                break;
+
+            case 1: // One
+                result = BigInteger.ONE;
+                break;
+
+            case 2: // All bits set in number
+                int numBytes = (order+7)/8;
+                byte[] fullBits = new byte[numBytes];
+                for(int i=0; i<numBytes; i++)
+                    fullBits[i] = (byte)0xff;
+                int excessBits = 8*numBytes - order;
+                fullBits[0] &= (1 << (8-excessBits)) - 1;
+                result = new BigInteger(1, fullBits);
+                break;
+
+            case 3: // One bit in number
+                result = BigInteger.ONE.shiftLeft(random.nextInt(order));
+                break;
+
+            case 4: // Random bit density
+                byte[] val = new byte[(order+7)/8];
+                int iterations = random.nextInt(order);
+                for (int i=0; i<iterations; i++) {
+                    int bitIdx = random.nextInt(order);
+                    val[bitIdx/8] |= 1 << (bitIdx%8);
+                }
+                result = new BigInteger(1, val);
+                break;
+            case 5: // Runs of consecutive ones and zeros
+                result = ZERO;
+                int remaining = order;
+                int bit = random.nextInt(2);
+                while (remaining > 0) {
+                    int runLength = Math.min(remaining, random.nextInt(order));
+                    result = result.shiftLeft(runLength);
+                    if (bit > 0)
+                        result = result.add(ONE.shiftLeft(runLength).subtract(ONE));
+                    remaining -= runLength;
+                    bit = 1 - bit;
+                }
+                break;
+
+            default: // random bits
+                result = new BigInteger(order, random);
+        }
+
+        if (negative)
+            result = result.negate();
+
+        return result;
+    }
+
+}
diff --git a/ojluni/src/test/java/math/BigInteger/CompareToTests.java b/ojluni/src/test/java/math/BigInteger/CompareToTests.java
new file mode 100644
index 0000000..abb8b4c
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/CompareToTests.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigInteger;
+
+/*
+ * @test
+ * @bug 6473768
+ * @summary Tests of BigInteger.compareTo
+ * @author Joseph D. Darcy
+ */
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import static java.math.BigInteger.*;
+
+// Android-changed: Replace error printing with asserts.
+public class CompareToTests {
+
+    @Test
+    public void compareToTests() {
+        final BigInteger MINUS_ONE = BigInteger.ONE.negate();
+        final BigInteger TWO_POW_126 = ONE.shiftLeft(126);
+        final BigInteger TWO_POW_127 = ONE.shiftLeft(127);
+        final BigInteger TWO_POW_128 = ONE.shiftLeft(128);
+
+        // First operand, second operand, expected compareTo result
+        BigInteger [][] testCases = {
+            // Basics
+            {valueOf(0),        valueOf(0),     ZERO},
+            {valueOf(0),        valueOf(1),     MINUS_ONE},
+            {valueOf(1),        valueOf(2),     MINUS_ONE},
+            {valueOf(2),        valueOf(1),     ONE},
+            {valueOf(10),       valueOf(10),    ZERO},
+
+            // Various relative lengths of internal mag array.
+            {TWO_POW_127,                 TWO_POW_127,                 ZERO},
+            {TWO_POW_127.negate(),        TWO_POW_127,                 MINUS_ONE},
+
+            {TWO_POW_128.or(TWO_POW_126), TWO_POW_128,                 ONE},
+            {TWO_POW_128.or(TWO_POW_126), TWO_POW_128.negate(),        ONE},
+
+            {TWO_POW_128,                 TWO_POW_128.or(TWO_POW_126), MINUS_ONE},
+            {TWO_POW_128.negate(),        TWO_POW_128.or(TWO_POW_126), MINUS_ONE},
+
+            {TWO_POW_127,                 TWO_POW_128,                 MINUS_ONE},
+            {TWO_POW_127.negate(),        TWO_POW_128,                 MINUS_ONE},
+
+            {TWO_POW_128,                 TWO_POW_127,                 ONE},
+            {TWO_POW_128.negate(),        TWO_POW_127,                 MINUS_ONE},
+
+            // Long boundary and near boundary values
+            {valueOf(Long.MAX_VALUE),            valueOf(Long.MAX_VALUE), ZERO},
+            {valueOf(Long.MAX_VALUE).negate(),   valueOf(Long.MAX_VALUE), MINUS_ONE},
+
+            {valueOf(Long.MAX_VALUE-1),          valueOf(Long.MAX_VALUE), MINUS_ONE},
+            {valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MAX_VALUE), MINUS_ONE},
+
+            {valueOf(Long.MIN_VALUE),            valueOf(Long.MAX_VALUE), MINUS_ONE},
+            {valueOf(Long.MIN_VALUE).negate(),   valueOf(Long.MAX_VALUE), ONE},
+
+            {valueOf(Long.MIN_VALUE+1),          valueOf(Long.MAX_VALUE), MINUS_ONE},
+            {valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MAX_VALUE), ZERO},
+
+            {valueOf(Long.MAX_VALUE),            valueOf(Long.MIN_VALUE), ONE},
+            {valueOf(Long.MAX_VALUE).negate(),   valueOf(Long.MIN_VALUE), ONE},
+
+            {valueOf(Long.MAX_VALUE-1),          valueOf(Long.MIN_VALUE), ONE},
+            {valueOf(Long.MAX_VALUE-1).negate(), valueOf(Long.MIN_VALUE), ONE},
+
+            {valueOf(Long.MIN_VALUE),            valueOf(Long.MIN_VALUE), ZERO},
+            {valueOf(Long.MIN_VALUE).negate(),   valueOf(Long.MIN_VALUE), ONE},
+
+            {valueOf(Long.MIN_VALUE+1),          valueOf(Long.MIN_VALUE), ONE},
+            {valueOf(Long.MIN_VALUE+1).negate(), valueOf(Long.MIN_VALUE), ONE},
+        };
+
+        for (BigInteger[] testCase : testCases) {
+            BigInteger a = testCase[0];
+            BigInteger a_negate = a.negate();
+            BigInteger b = testCase[1];
+            BigInteger b_negate = b.negate();
+            int expected = testCase[2].intValue();
+
+            compareToTest(a,        b,         expected);
+            compareToTest(a_negate, b_negate, -expected);
+        }
+    }
+
+    private static void compareToTest(BigInteger a, BigInteger b, int expected) {
+        int result = a.compareTo(b);
+        int failed = (result==expected) ? 0 : 1;
+        if (failed == 1) {
+            Assert.fail("(" + a + ").compareTo(" + b + ") => " + result +
+                               "\n\tExpected " + expected);
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/math/BigInteger/ModPow.java b/ojluni/src/test/java/math/BigInteger/ModPow.java
new file mode 100644
index 0000000..b31c0f6
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/ModPow.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 4181191
+ * @summary test BigInteger modPow method
+ */
+package test.java.math.BigInteger;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error printing with asserts.
+public class ModPow {
+
+    @Test
+    public void testModPow() {
+        Random rnd = new Random(1234);
+
+        for (int i=0; i<2000; i++) {
+            BigInteger m = new BigInteger(800, rnd);
+            BigInteger base = new BigInteger(16, rnd);
+            if (rnd.nextInt() % 2 == 0)
+                base = base.negate();
+            BigInteger exp = new BigInteger(8, rnd);
+
+            BigInteger z = base.modPow(exp, m);
+            BigInteger w = base.pow(exp.intValue()).mod(m);
+            Assert.assertEquals(z, w,
+                    base +" ** " + exp + " mod "+ m + " modPow : " + z + "pow.mod: " + w);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigInteger/OperatorNpeTests.java b/ojluni/src/test/java/math/BigInteger/OperatorNpeTests.java
new file mode 100644
index 0000000..5940249
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/OperatorNpeTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6365176
+ * @summary Get NullPointerExceptions when expected
+ * @author Joseph D. Darcy
+ */
+package test.java.math.BigInteger;
+
+import java.math.*;
+import static java.math.BigInteger.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error printing with asserts.
+public class OperatorNpeTests {
+
+    @Test
+    public void testOperatorsNpe() throws NullPointerException {
+        BigInteger[] specialValues = {ZERO, ONE, TEN};
+
+        for (BigInteger bd : specialValues) {
+            BigInteger result;
+            try {
+                result = bd.multiply(null);
+                Assert.fail("Instead of NPE got " + result);
+            } catch (NullPointerException npe) {
+                ; // Expected
+            }
+
+            try {
+                result = bd.divide(null);
+                Assert.fail("Instead of NPE got " + result);
+            } catch (NullPointerException npe) {
+                ; // Expected
+            }
+
+            try {
+                result = bd.add(null);
+                Assert.fail("Instead of NPE got " + result);
+            } catch (NullPointerException npe) {
+                ; // Expected
+            }
+
+            try {
+                result = bd.subtract(null);
+                Assert.fail("Instead of NPE got " + result);
+            } catch (NullPointerException npe) {
+                ; // Expected
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigInteger/PrimeTest.java b/ojluni/src/test/java/math/BigInteger/PrimeTest.java
new file mode 100644
index 0000000..e0e4c88
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/PrimeTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main PrimeTest
+ * @bug 8026236 8074460 8078672
+ * @summary test primality verification methods in BigInteger (use -Dseed=X to set PRNG seed)
+ * @author bpb
+ * @key randomness
+ */
+package test.java.math.BigInteger;
+
+import java.math.BigInteger;
+import java.util.BitSet;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.SplittableRandom;
+import java.util.TreeSet;
+import static java.util.stream.Collectors.toCollection;
+import static java.util.stream.Collectors.toList;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error printing with asserts.
+public class PrimeTest {
+
+    private static final int DEFAULT_UPPER_BOUND = 1299709; // 100000th prime
+    private static final int DEFAULT_CERTAINTY = 100;
+    private static final int NUM_NON_PRIMES = 10000;
+
+    @Test
+    public void testPrimes() throws Exception {
+        // Get primes through specified bound (inclusive) and Integer.MAX_VALUE
+        NavigableSet<BigInteger> primes = getPrimes();
+
+        // Check whether known primes are identified as such
+        checkPrime(primes, DEFAULT_CERTAINTY);
+
+        // Check whether known non-primes are not identified as primes
+        checkNonPrime(primes, DEFAULT_CERTAINTY);
+
+        checkMersennePrimes(DEFAULT_CERTAINTY);
+    }
+
+    /**
+     * Create a {@code BitSet} wherein a set bit indicates the corresponding
+     * index plus 2 is prime. That is, if bit N is set, then the integer N + 2
+     * is prime. The values 0 and 1 are intentionally excluded. See the
+     * <a
+     * href="http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes#Algorithm_description">
+     * Sieve of Eratosthenes</a> algorithm description for more information.
+     *
+     * @return bits indicating which indexes represent primes
+     */
+    private static BitSet createPrimes() {
+        int nbits = PrimeTest.DEFAULT_UPPER_BOUND - 1;
+        BitSet bs = new BitSet(nbits);
+        for (int p = 2; p * p < PrimeTest.DEFAULT_UPPER_BOUND;) {
+            for (int i = p * p; i < nbits + 2; i += p) {
+                bs.set(i - 2, true);
+            }
+            do {
+                ++p;
+            } while (p > 1 && bs.get(p - 2));
+        }
+        bs.flip(0, nbits);
+        return bs;
+    }
+
+    /**
+     * Load the primes up to the specified bound (inclusive) into a
+     * {@code NavigableSet}, appending the prime {@code Integer.MAX_VALUE}.
+     *
+     * @return a set of primes
+     */
+    private static NavigableSet<BigInteger> getPrimes() {
+        BitSet bs = createPrimes();
+        NavigableSet<BigInteger> primes = bs.stream()
+                .mapToObj(p -> BigInteger.valueOf(p + 2))
+                .collect(toCollection(TreeSet::new));
+        primes.add(BigInteger.valueOf(Integer.MAX_VALUE));
+        return primes;
+    }
+
+    /**
+     * Verifies whether the fraction of probable primes detected is at least 1 -
+     * 1/2^certainty.
+     */
+    private static void checkPrime(Set<BigInteger> primes, int certainty) {
+        long probablePrimes = (primes.parallelStream())
+                .filter(bi -> bi.isProbablePrime(certainty))
+                .count();
+
+        // N = certainty / 2
+        // Success if p/t >= 1 - 1/4^N
+        // or (p/t)*4^N >= 4^N - 1
+        // or p*4^N >= t*(4^N - 1)
+        BigInteger p = BigInteger.valueOf(probablePrimes);
+        BigInteger t = BigInteger.valueOf(primes.size());
+        BigInteger fourToTheC = BigInteger.valueOf(4).pow(certainty / 2);
+        BigInteger fourToTheCMinusOne = fourToTheC.subtract(BigInteger.ONE);
+        BigInteger left = p.multiply(fourToTheC);
+        BigInteger right = t.multiply(fourToTheCMinusOne);
+
+        Assert.assertFalse(left.compareTo(right) < 0,
+                "Probable prime certainty test failed");
+    }
+
+    /**
+     * Verifies whether all {@code BigInteger}s in the tested range for which
+     * {@code isProbablePrime()} returns {@code false} are <i>not</i>
+     * prime numbers.
+     */
+    private static void checkNonPrime(NavigableSet<BigInteger> primes, int certainty) {
+        int maxPrime = DEFAULT_UPPER_BOUND;
+        try {
+            maxPrime = primes.last().intValueExact();
+        } catch (ArithmeticException e) {
+            // ignore it
+        }
+
+        // Create a list of non-prime BigIntegers.
+        SplittableRandom splitRandom = new SplittableRandom(0L);
+        List<BigInteger> nonPrimeBigInts = (splitRandom)
+                .ints(NUM_NON_PRIMES, 2, maxPrime).mapToObj(BigInteger::valueOf)
+                .filter(b -> !b.isProbablePrime(certainty)).collect(toList());
+
+        // If there are any non-probable primes also in the primes list then fail.
+        boolean failed = nonPrimeBigInts.stream().anyMatch(primes::contains);
+
+        // In the event, print which purported non-primes were actually prime.
+        if (failed) {
+            for (BigInteger bigInt : nonPrimeBigInts) {
+                if (primes.contains(bigInt)) {
+                    Assert.fail("Prime value thought to be non-prime: " + bigInt);
+                }
+            }
+        }
+    }
+
+    /**
+     * Verifies whether a specified subset of Mersenne primes are correctly
+     * identified as being prime. See
+     * <a href="https://en.wikipedia.org/wiki/Mersenne_prime">Mersenne prime</a>
+     * for more information.
+     */
+    private static void checkMersennePrimes(int certainty) {
+        int[] MERSENNE_EXPONENTS = {
+            2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203,
+            2281, 3217, 4253, // uncomment remaining array elements to make this test run a long time
+            /* 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497,
+            86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269,
+            2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951,
+            30402457, 32582657, 37156667, 42643801, 43112609, 57885161 */
+        };
+
+        for (int n : MERSENNE_EXPONENTS) {
+            BigInteger mp = BigInteger.ONE.shiftLeft(n).subtract(BigInteger.ONE);
+            Assert.assertTrue(mp.isProbablePrime(certainty),
+                    "Mp with p = "+n+" not classified as prime");
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigInteger/PrimitiveConversionTests.java b/ojluni/src/test/java/math/BigInteger/PrimitiveConversionTests.java
new file mode 100644
index 0000000..1b101fb
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/PrimitiveConversionTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.BigInteger;
+
+import static java.math.BigInteger.ONE;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 7131192
+ * @summary This test ensures that BigInteger.floatValue() and
+ *          BigInteger.doubleValue() behave correctly.
+ * @author Louis Wasserman
+ */
+
+// Android-changed: Replace error printing with asserts.
+public class PrimitiveConversionTests {
+    static final List<BigInteger> ALL_BIGINTEGER_CANDIDATES;
+
+    static {
+        List<BigInteger> samples = new ArrayList<>();
+        // Now add values near 2^N for lots of values of N.
+        for (int exponent : Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 31, 32, 33,
+                34, 62, 63, 64, 65, 71, 72, 73, 79, 80, 81, 255, 256, 257, 511,
+                512, 513, Double.MAX_EXPONENT - 1, Double.MAX_EXPONENT,
+                Double.MAX_EXPONENT + 1, 2000, 2001, 2002)) {
+            BigInteger x = ONE.shiftLeft(exponent);
+            for (BigInteger y : Arrays.asList(x, x.add(ONE), x.subtract(ONE))) {
+                samples.add(y);
+                samples.add(y.negate());
+            }
+        }
+
+        Random rng = new Random(1234567);
+        for (int i = 0; i < 2000; i++) {
+            samples.add(new BigInteger(rng.nextInt(2000), rng));
+        }
+
+        ALL_BIGINTEGER_CANDIDATES = Collections.unmodifiableList(samples);
+    }
+
+    @Test
+    public void testDoubleValue() {
+        for (BigInteger big : ALL_BIGINTEGER_CANDIDATES) {
+            double expected = Double.parseDouble(big.toString());
+            double actual = big.doubleValue();
+
+            // should be bitwise identical
+            Assert.assertEquals(Double.doubleToRawLongBits(actual),
+                    Double.doubleToRawLongBits(expected));
+        }
+    }
+
+    @Test
+    public void testFloatValue() {
+        for (BigInteger big : ALL_BIGINTEGER_CANDIDATES) {
+            float expected = Float.parseFloat(big.toString());
+            float actual = big.floatValue();
+
+            // should be bitwise identical
+            Assert.assertEquals(Float.floatToRawIntBits(actual),
+                    Float.floatToRawIntBits(expected));
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/math/BigInteger/ProbablePrime.java b/ojluni/src/test/java/math/BigInteger/ProbablePrime.java
new file mode 100644
index 0000000..158c0e8
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/ProbablePrime.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4654323
+ * @summary Tests functionality of isProbablePrime(Integer.MAX_VALUE)
+ */
+package test.java.math.BigInteger;
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error printing with asserts.
+public class ProbablePrime {
+
+    @Test
+    public void testProbablePrime() {
+        BigInteger num = new BigInteger("4");
+        int[] certainties = {-1, 0, 1, 2, 100, Integer.MAX_VALUE - 1, Integer.MAX_VALUE};
+        boolean[] expectations = {true, true, false, false, false, false, false};
+
+        for (int i = 0; i < certainties.length; i++) {
+            boolean b = num.isProbablePrime(certainties[i]);
+            Assert.assertEquals(b, expectations[i], "Unexpected answer " + b +
+                        " for certainty " +  certainties[i]);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigInteger/StringConstructor.java b/ojluni/src/test/java/math/BigInteger/StringConstructor.java
new file mode 100644
index 0000000..b7be11b
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/StringConstructor.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4489146 5017980
+ * @summary tests String constructors of BigInteger
+ * @author Joseph D. Darcy
+ */
+package test.java.math.BigInteger;
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error printing with asserts.
+public class StringConstructor {
+
+    @Test
+    public void testStringConstructor() {
+        // Good strings
+        constructWithoutError("0", 0L);
+        constructWithoutError("000000000000000000", 0L);
+        constructWithoutError("1", 1L);
+        constructWithoutError("-1", -1L);
+        constructWithoutError("+1", +1L);
+        constructWithoutError( "123456789123456789", 123456789123456789L);
+        constructWithoutError("+123456789123456789", 123456789123456789L);
+        constructWithoutError("-123456789123456789", -123456789123456789L);
+        constructWithoutError(Integer.toString(Integer.MIN_VALUE),
+                              (long)Integer.MIN_VALUE);
+        constructWithoutError(Integer.toString(Integer.MAX_VALUE),
+                              (long)Integer.MAX_VALUE);
+        constructWithoutError(Long.toString(Long.MIN_VALUE),
+                              Long.MIN_VALUE);
+        constructWithoutError(Long.toString(Long.MAX_VALUE),
+                              Long.MAX_VALUE);
+
+        // Bad strings
+        constructWithError("");
+        constructWithError("-");
+        constructWithError("+");
+        constructWithError("--");
+        constructWithError("++");
+        constructWithError("-000-0");
+        constructWithError("+000+0");
+        constructWithError("+000-0");
+        constructWithError("--1234567890");
+        constructWithError("++1234567890");
+        constructWithError("-0-12345678");
+        constructWithError("+0+12345678");
+        constructWithError("--12345678-12345678-12345678");
+        constructWithError("++12345678+12345678+12345678");
+        constructWithError("12345-");
+        constructWithError("12345+");
+    }
+
+    // this method adapted from ../BigDecimal/StringConstructor.java
+    private static void constructWithError(String badString) {
+        try {
+            BigInteger bi = new BigInteger(badString);
+            Assert.fail(badString + " accepted");
+        } catch(NumberFormatException e) {
+            // expected
+        }
+    }
+
+    private static void constructWithoutError(String goodString, long value) {
+        BigInteger bi = new BigInteger(goodString);
+        Assert.assertEquals(bi.longValue(), value,
+                String.format("From ``%s'' expected %d, got %s.\n", goodString, value, bi));
+    }
+
+}
diff --git a/ojluni/src/test/java/math/BigInteger/TestValueExact.java b/ojluni/src/test/java/math/BigInteger/TestValueExact.java
new file mode 100644
index 0000000..92e49783
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/TestValueExact.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6371401
+ * @summary Tests of fooValueExact methods
+ * @author Joseph D. Darcy
+ */
+package test.java.math.BigInteger;
+
+import java.math.BigInteger;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error printing with asserts.
+public class TestValueExact {
+
+    @Test
+    public void testLongValueExact() {
+        BigInteger[] inRange = {
+            BigInteger.valueOf(Long.MIN_VALUE),
+            BigInteger.ZERO,
+            BigInteger.valueOf(Long.MAX_VALUE)
+        };
+
+        BigInteger[] outOfRange = {
+            BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE),
+            BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE)
+        };
+
+        for (BigInteger bi : inRange) {
+            Assert.assertEquals(bi.longValueExact(), bi.longValue(),
+                    "Mismatching int conversion for " + bi);
+        }
+
+        for (BigInteger bi : outOfRange) {
+            try {
+                long value = bi.longValueExact();
+                Assert.fail("Failed to get expected exception on " + bi + " got " + value);
+            } catch(ArithmeticException ae) {
+                ; // Expected
+            }
+        }
+    }
+
+    @Test
+    public void testIntValueExact() {
+        BigInteger[] inRange = {
+            BigInteger.valueOf(Integer.MIN_VALUE),
+            BigInteger.ZERO,
+            BigInteger.ONE,
+            BigInteger.TEN,
+            BigInteger.valueOf(Integer.MAX_VALUE)
+        };
+
+        BigInteger[] outOfRange = {
+            BigInteger.valueOf((long)Integer.MIN_VALUE - 1),
+            BigInteger.valueOf((long)Integer.MAX_VALUE + 1)
+        };
+
+        for (BigInteger bi : inRange) {
+            Assert.assertEquals(bi.intValueExact(), bi.intValue(),
+                    "Mismatching int conversion for " + bi);
+        }
+
+        for (BigInteger bi : outOfRange) {
+            try {
+                int value = bi.intValueExact();
+                Assert.fail("Failed to get expected exception on " + bi + " got " + value);
+            } catch(ArithmeticException ae) {
+                ; // Expected
+            }
+        }
+    }
+
+    @Test
+    public void testShortValueExact() {
+        BigInteger[] inRange = {
+            BigInteger.valueOf(Short.MIN_VALUE),
+            BigInteger.ZERO,
+            BigInteger.ONE,
+            BigInteger.TEN,
+            BigInteger.valueOf(Short.MAX_VALUE)
+        };
+
+        BigInteger[] outOfRange = {
+            BigInteger.valueOf((long)Integer.MIN_VALUE - 1),
+            BigInteger.valueOf((long)Integer.MIN_VALUE),
+            BigInteger.valueOf(   (int)Short.MIN_VALUE - 1),
+            BigInteger.valueOf(   (int)Short.MAX_VALUE + 1),
+            BigInteger.valueOf((long)Integer.MAX_VALUE),
+            BigInteger.valueOf((long)Integer.MAX_VALUE + 1)
+        };
+
+        for (BigInteger bi : inRange) {
+            Assert.assertEquals(bi.shortValueExact(), bi.intValue(),
+                    "Mismatching int conversion for " + bi);
+        }
+
+        for (BigInteger bi : outOfRange) {
+            try {
+                int value = bi.shortValueExact();
+                Assert.fail("Failed to get expected exception on " + bi + " got " + value);
+            } catch(ArithmeticException ae) {
+                ; // Expected
+            }
+        }
+    }
+
+    @Test
+    public void testByteValueExact() {
+        BigInteger[] inRange = {
+            BigInteger.valueOf(Byte.MIN_VALUE),
+            BigInteger.valueOf(0),
+            BigInteger.ONE,
+            BigInteger.TEN,
+            BigInteger.valueOf(Byte.MAX_VALUE)
+        };
+
+        BigInteger[] outOfRange = {
+            BigInteger.valueOf((long)Integer.MIN_VALUE - 1),
+            BigInteger.valueOf((long)Integer.MIN_VALUE),
+            BigInteger.valueOf(   (int)Short.MIN_VALUE - 1),
+            BigInteger.valueOf(   (int)Short.MIN_VALUE),
+            BigInteger.valueOf(    (int)Byte.MIN_VALUE - 1),
+            BigInteger.valueOf(    (int)Byte.MAX_VALUE + 1),
+            BigInteger.valueOf(   (int)Short.MAX_VALUE + 1),
+            BigInteger.valueOf(   (int)Short.MAX_VALUE),
+            BigInteger.valueOf((long)Integer.MAX_VALUE),
+            BigInteger.valueOf((long)Integer.MAX_VALUE + 1)
+        };
+
+        for (BigInteger bi : inRange) {
+            Assert.assertEquals(bi.byteValueExact(), bi.intValue(),
+                    "Mismatching int conversion for " + bi);
+        }
+
+        for (BigInteger bi : outOfRange) {
+            try {
+                int value = bi.byteValueExact();
+                Assert.fail("Failed to get expected exception on " + bi + " got " + value);
+            } catch(ArithmeticException ae) {
+                ; // Expected
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/math/BigInteger/UnicodeConstructor.java b/ojluni/src/test/java/math/BigInteger/UnicodeConstructor.java
new file mode 100644
index 0000000..b6b18e8
--- /dev/null
+++ b/ojluni/src/test/java/math/BigInteger/UnicodeConstructor.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4040456
+ * @summary Test biginteger constructor with i18n string
+ */
+package test.java.math.BigInteger;
+
+import java.math.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * This class tests to see if creating a biginteger with an unicode japanese zero and one succeeds
+ */
+
+// Android-changed: Replace error printing with asserts.
+public class UnicodeConstructor {
+
+    @Test
+    public void testUnicodeConstructor() {
+
+        try {
+            // the code for japanese zero
+            BigInteger b1 = new BigInteger("\uff10");
+
+            // Japanese 1010
+            BigInteger b2 = new BigInteger("\uff11\uff10\uff11\uff10");
+
+            // Android-added: more valid inputs
+            final Object[][] inputs = {
+                { "\u0030", 0 },                      // ASCII "0"
+                { "\u0031\u0030\u0031\u0030", 1010 }, // ASCII "1010"
+                { "\u0660", 0 },                      // Arabic-Indic Digit Zero
+                { "\u0661\u0660\u0661\u0660", 1010 }, // Arabic-Indic Digit, "1010"
+                { "\u09e6", 0 },                      // Bengali Digit Zero
+                { "\u09e7\u09e6\u09e7\u09e6", 1010 }, // Bengali Digit, "1010"
+            };
+            for (Object[] test : inputs) {
+                BigInteger b = new BigInteger((String)test[0]);
+                Assert.assertEquals(b.intValue(), (int)test[1]);
+            }
+        } catch (ArrayIndexOutOfBoundsException e) {
+            Assert.fail("BigInteger is not accepting unicode initializers.");
+        }
+
+    }
+
+}
diff --git a/ojluni/src/test/java/math/RoundingMode/RoundingModeTests.java b/ojluni/src/test/java/math/RoundingMode/RoundingModeTests.java
new file mode 100644
index 0000000..0221709
--- /dev/null
+++ b/ojluni/src/test/java/math/RoundingMode/RoundingModeTests.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.math.RoundingMode;
+
+/*
+ * @test
+ * @bug 4851776 4891522 4905335
+ * @summary Basic tests for the RoundingMode class.
+ * @author Joseph D. Darcy
+ */
+
+import java.math.RoundingMode;
+import java.math.BigDecimal;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+// Android-changed: Replace error throws with asserts.
+public class RoundingModeTests {
+
+    @Test
+    public void testRoundingMode() {
+
+        // For each member of the family, make sure
+        // rm == valueOf(rm.toString())
+
+        for(RoundingMode rm: RoundingMode.values()) {
+            Assert.assertEquals(RoundingMode.valueOf(rm.toString()), rm,
+                    "Bad roundtrip conversion of " + rm);
+        }
+
+        // Test that mapping of old integers to new values is correct
+        Assert.assertEquals(RoundingMode.CEILING, RoundingMode.valueOf(BigDecimal.ROUND_CEILING),
+                "Bad mapping for ROUND_CEILING");
+
+        Assert.assertEquals(RoundingMode.DOWN, RoundingMode.valueOf(BigDecimal.ROUND_DOWN),
+                "Bad mapping for ROUND_DOWN");
+
+        Assert.assertEquals(RoundingMode.FLOOR, RoundingMode.valueOf(BigDecimal.ROUND_FLOOR),
+                "Bad mapping for ROUND_FLOOR");
+
+        Assert.assertEquals(RoundingMode.HALF_DOWN, RoundingMode.valueOf(BigDecimal.ROUND_HALF_DOWN),
+                "Bad mapping for ROUND_HALF_DOWN");
+
+        Assert.assertEquals(RoundingMode.HALF_EVEN, RoundingMode.valueOf(BigDecimal.ROUND_HALF_EVEN),
+                "Bad mapping for ROUND_HALF_EVEN");
+
+        Assert.assertEquals(RoundingMode.HALF_UP, RoundingMode.valueOf(BigDecimal.ROUND_HALF_UP),
+                "Bad mapping for ROUND_HALF_UP");
+
+        Assert.assertEquals(RoundingMode.UNNECESSARY, RoundingMode.valueOf(BigDecimal.ROUND_UNNECESSARY),
+                "Bad mapping for ROUND_UNNECESSARY");
+    }
+}
diff --git a/ojluni/src/test/java/net/DatagramSocket/ReuseAddressTest.java b/ojluni/src/test/java/net/DatagramSocket/ReuseAddressTest.java
new file mode 100644
index 0000000..13fe8b0
--- /dev/null
+++ b/ojluni/src/test/java/net/DatagramSocket/ReuseAddressTest.java
@@ -0,0 +1,383 @@
+/* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.net.DatagramSocket;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.MulticastSocket;
+import java.net.SocketException;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+/*
+ * @test
+ * @bug 8153674
+ * @key intermittent
+ * @summary This test might fail intermittently as it needs a UDP socket that
+ *          binds to the wildcard address.
+ * @summary Expected SocketException not thrown when calling bind() with
+ *   setReuseAddress(false)
+ * @run main/othervm ReuseAddressTest
+ */
+
+public class ReuseAddressTest {
+
+    String getInfo(DatagramSocket soc) {
+        if (soc == null) {
+            return null;
+        }
+
+        return "localPort: " + soc.getLocalPort()
+                + "; localAddress: " + soc.getLocalAddress()
+                + "; remotePort: " + soc.getPort()
+                + "; remoteAddress: " + soc.getInetAddress()
+                + "; isClosed: " + soc.isClosed()
+                + "; isBound: " + soc.isBound();
+    }
+
+    static InetSocketAddress createSocketAddress(int testMcastPort) throws Exception {
+        InetAddress localAddress = InetAddress.getLocalHost();
+        InetSocketAddress localSocketAddress = new InetSocketAddress(localAddress, testMcastPort);
+        return localSocketAddress;
+    }
+
+    /* standalone interface */
+    @Test
+    public void testReuseAddress() throws Exception {
+        ReuseAddressTest test = new ReuseAddressTest();
+        test.DatagramSocket0029();
+        test.DatagramSocket0030();
+        test.DatagramSocket0031();
+        test.DatagramSocket0032();
+        test.DatagramSocket0034();
+        test.DatagramSocket0035();
+        test.DatagramSocket2028();
+        test.DatagramSocket2029();
+        test.DatagramSocket2030();
+
+    }
+
+    /**
+     * Equivalence class partitioning with input values orientation for public
+     * void setReuseAddress(boolean on) throws SocketException,
+     * <br><b>on</b>: false.
+     * <br><b>Expected results</b>: getReuseAddress() will return false
+     */
+    public void DatagramSocket0029() throws Exception {
+        DatagramSocket ds = null;
+        try {
+            ds = new DatagramSocket(null);
+            ds.setReuseAddress(false);
+            if (ds.getReuseAddress() == true) {
+                fail("SO_REUSEADDR is not set to false");
+            }
+        } catch (IOException e) {
+            fail("unexpected: " + e);
+        } catch (SecurityException e) {
+        } finally {
+            if (ds != null) {
+                ds.close();
+            }
+        }
+    }
+
+    /**
+     * Equivalence class partitioning with input values orientation for public
+     * void setReuseAddress(boolean on) throws SocketException,
+     * <br><b>on</b>: true.
+     * <br><b>Expected results</b>: Allows completely duplicate bindings (same
+     * address and port) on multicast sockets
+     */
+    public void DatagramSocket0030() throws Exception {
+        MulticastSocket ms1 = null;
+        MulticastSocket ms2 = null;
+        try {
+            InetSocketAddress addr = createSocketAddress(0);
+
+            ms1 = new MulticastSocket(null);
+            ms1.setReuseAddress(true);
+
+            try {
+                ms1.bind(addr);
+            } catch (SocketException e) {
+                fail("cannot bind first socket to " + addr
+                        + " unexpected " + e);
+            }
+
+            addr = createSocketAddress(ms1.getLocalPort());
+            ms2 = new MulticastSocket(null);
+            ms2.setReuseAddress(true);
+
+            try {
+                ms2.bind(addr);
+            } catch (SocketException e) {
+                fail("cannot bind second socket to " + addr
+                        + " unexpected " + e);
+            }
+
+            if (ms1.getLocalPort() != addr.getPort() || !ms1.isBound()
+                    || ms2.getLocalPort() != addr.getPort() || !ms2.isBound()) {
+                fail("bind() fails with: " + addr);
+            }
+
+        } catch (IOException e) {
+            e.printStackTrace(System.out);
+            fail("unexpected: " + e);
+        } catch (SecurityException e) {
+        } finally {
+            if (ms1 != null) {
+                ms1.close();
+            }
+            if (ms2 != null) {
+                ms2.close();
+            }
+        }
+    }
+
+    /**
+     * Equivalence class partitioning with input values orientation for public
+     * void setReuseAddress(boolean on) throws SocketException,
+     * <br><b>on</b>: false.
+     * <br><b>Expected results</b>: The second bind will throw SocketException,
+     * when SO_REUSEADDR disable
+     */
+    public void DatagramSocket0031() throws Exception {
+        MulticastSocket ms1 = null;
+        MulticastSocket ms2 = null;
+        try {
+            InetSocketAddress addr = createSocketAddress(0);
+
+            ms1 = new MulticastSocket(null);
+            try {
+                ms1.bind(addr);
+            } catch (SocketException e) {
+                fail("cannot bind first socket to " + addr
+                        + " unexpected " + e);
+            }
+
+            addr = createSocketAddress(ms1.getLocalPort());
+            ms2 = new MulticastSocket(null);
+            ms2.setReuseAddress(false);  // method under test
+
+            try {
+                ms2.bind(addr);
+                fail("no exceptions from bind() with " + addr);
+            } catch (SocketException e) {
+            }
+
+        } catch (IOException e) {
+            e.printStackTrace(System.out);
+            fail("unexpected: " + e);
+        } catch (SecurityException e) {
+        } finally {
+            if (ms1 != null) {
+                ms1.close();
+            }
+            if (ms2 != null) {
+                ms2.close();
+            }
+        }
+    }
+
+    /**
+     * Equivalence class partitioning with input values orientation for public
+     * void setReuseAddress(boolean on) throws SocketException,
+     * <br><b>on</b>: true.
+     * <br><b>Expected results</b>: Allows a single process to bind the same
+     * port to multiple sockets as long as each bind specifies a different local
+     * IP address
+     */
+    public void DatagramSocket0032() throws Exception {
+        DatagramSocket ds1 = null;
+        DatagramSocket ds2 = null;
+        try {
+
+            InetSocketAddress isa1 = createSocketAddress(0);
+            InetAddress addr = isa1.getAddress();
+            InetAddress wildcard = InetAddress.getByName("0.0.0.0");
+
+
+            ds1 = new DatagramSocket(null);
+            ds1.setReuseAddress(true);    // method under test
+            ds1.bind(isa1);
+
+            InetSocketAddress isa2 = new InetSocketAddress(wildcard, ds1.getLocalPort());
+
+            ds2 = new DatagramSocket(null);
+            ds2.setReuseAddress(true);    // method under test
+            if (!ds2.getReuseAddress()) {
+            }
+
+            try {
+                ds2.bind(isa2);
+            } catch (SocketException e) {
+                fail("cannot bind second socket to " + isa2
+                        + " unexpected " + e);
+            }
+
+            if (ds1.getLocalPort() != ds2.getLocalPort() || !ds1.isBound()
+                    || !ds2.isBound()) {
+                fail("bind() fails with: " + addr);
+            }
+
+        } catch (IOException e) {
+            e.printStackTrace(System.out);
+            fail("unexpected: " + e);
+        } catch (SecurityException e) {
+        } finally {
+            if (ds1 != null) {
+                ds1.close();
+            }
+            if (ds2 != null) {
+                ds2.close();
+            }
+        }
+    }
+
+    /**
+     * Assertion testing for public int getTrafficClass() throws
+     * SocketException, will return a number in range from 0 to 255 or throw
+     * SocketException.
+     */
+    public void DatagramSocket2028() throws Exception {
+        DatagramSocket ds = null;
+        try {
+            ds = new DatagramSocket();
+            int tc = ds.getTrafficClass();
+            if (tc < 0 || tc > 255) {
+                fail("getTrafficClass() returns: " + tc);
+            }
+        } catch (SecurityException e) {
+        } catch (SocketException e) {
+            e.printStackTrace(System.out);
+            fail("Unexpected exception : " + e);
+        } finally {
+            if (ds != null) {
+                ds.close();
+            }
+        }
+    }
+
+    /**
+     * Assertion testing for public void setTrafficClass(int tc) throws
+     * SocketException, IAE will be thrown with tc less than 0 or greater than
+     * 255.
+     */
+    public void DatagramSocket2029() throws Exception {
+        DatagramSocket ds = null;
+        try {
+            ds = new DatagramSocket();
+        } catch (SecurityException e) {
+        } catch (IOException e) {
+            fail("cannot create socket: " + e);
+        }
+
+        int[] values = {
+                Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1000, -2, -1,
+                256, 257, 1000, 50000, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
+        };
+
+        for (int i = 0; i < values.length; i++) {
+            try {
+                ds.setTrafficClass(values[i]);
+                ds.close();
+                fail("setTrafficClass() fails with : " + values[i]);
+            } catch (SocketException e) {
+                ds.close();
+                fail("setTrafficClass() throws : " + e);
+            } catch (IllegalArgumentException e) {
+            }
+        }
+    }
+
+    /**
+     * Assertion testing for public void setTrafficClass(int tc) throws
+     * SocketException, only SocketException may be thrown with tc in range from
+     * 0 to 255.
+     */
+    public void DatagramSocket2030() throws Exception {
+        DatagramSocket ds = null;
+        try {
+            ds = new DatagramSocket();
+        } catch (SecurityException e) {
+        } catch (IOException e) {
+            fail("cannot create socket: " + e);
+        }
+
+        for (int i = 0; i <= 255; i++) {
+            try {
+                ds.setTrafficClass(i);
+            } catch (SocketException e) {
+            }
+        }
+    }
+
+    /**
+     * Equivalence class partitioning with input values orientation for public
+     * void setBroadcast(boolean on) throws SocketException,
+     * <br><b>on</b>: false.
+     * <br><b>Expected results</b>: getBroadcast() will return false
+     */
+    public void DatagramSocket0034() throws Exception {
+        DatagramSocket ds = null;
+        try {
+            ds = new DatagramSocket();
+            ds.setBroadcast(false);
+            if (ds.getBroadcast() == true) {
+                fail("SO_BROADCAST is not set to false");
+            }
+        } catch (IOException e) {
+            fail("unexpected: " + e);
+        } catch (SecurityException e) {
+        } finally {
+            if (ds != null) {
+                ds.close();
+            }
+        }
+    }
+
+    /**
+     * Equivalence class partitioning with input values orientation for public
+     * void setBroadcast(boolean on) throws SocketException,
+     * <br><b>on</b>: true.
+     * <br><b>Expected results</b>: getBroadcast() will return true
+     */
+    public void DatagramSocket0035() throws Exception {
+        DatagramSocket ds = null;
+        try {
+            ds = new DatagramSocket();
+            ds.setBroadcast(true);
+            if (ds.getBroadcast() == false) {
+                fail("SO_BROADCAST is not set to true");
+            }
+        } catch (IOException e) {
+            fail("unexpected: " + e);
+        } catch (SecurityException e) {
+        } finally {
+            if (ds != null) {
+                ds.close();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/SocketOptions/MinimumRcvBufferSize.java b/ojluni/src/test/java/net/SocketOptions/MinimumRcvBufferSize.java
new file mode 100644
index 0000000..a2f333e
--- /dev/null
+++ b/ojluni/src/test/java/net/SocketOptions/MinimumRcvBufferSize.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8170920
+ * @run main MinimumRcvBufferSize
+ * @run main/othervm -Djava.net.preferIPv4Stack=true MinimumRcvBufferSize
+ */
+package test.java.net.SocketOptions;
+
+import java.nio.channels.*;
+import java.net.*;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class MinimumRcvBufferSize {
+
+    @Test
+    public void testBufferSize() throws Exception {
+        ServerSocketChannel channel = ServerSocketChannel.open();
+        // Android-added: set initial buffersize to zero (b/218814458)
+        channel.setOption(StandardSocketOptions.SO_RCVBUF, 0);
+        int before = channel.getOption(StandardSocketOptions.SO_RCVBUF);
+        channel.setOption(StandardSocketOptions.SO_RCVBUF, Integer.MAX_VALUE);
+        int after = channel.getOption(StandardSocketOptions.SO_RCVBUF);
+        if (before > after) {
+            fail("Test failed: SO_RCVBUF: " + before + " " + after);
+        }
+
+        SocketChannel channel1 = SocketChannel.open();
+        // Android-added: set initial buffersize to zero (b/218814458)
+        channel1.setOption(StandardSocketOptions.SO_SNDBUF, 0);
+        before = channel1.getOption(StandardSocketOptions.SO_SNDBUF);
+        channel1.setOption(StandardSocketOptions.SO_SNDBUF, Integer.MAX_VALUE);
+        after = channel1.getOption(StandardSocketOptions.SO_SNDBUF);
+        if (before > after) {
+            fail("Test failed: SO_SNDBUF: " + before + " " + after);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/SocketOptions/OptionsTest.java b/ojluni/src/test/java/net/SocketOptions/OptionsTest.java
new file mode 100644
index 0000000..a306283
--- /dev/null
+++ b/ojluni/src/test/java/net/SocketOptions/OptionsTest.java
@@ -0,0 +1,295 @@
+
+
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8036979 8072384 8044773
+ * @requires !vm.graal.enabled
+ * @run main/othervm -Xcheck:jni OptionsTest
+ * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest
+ * @run main/othervm --limit-modules=java.base OptionsTest
+ */
+package test.java.net.SocketOptions;
+
+import java.lang.reflect.Method;
+import java.net.*;
+import java.util.*;
+
+import org.testng.annotations.Test;
+
+public class OptionsTest {
+
+    static class TestClass {
+        TestClass(SocketOption<?> option, Object testValue) {
+            this.option = option;
+            this.testValue = testValue;
+        }
+        static TestClass create(SocketOption<?> option, Object testValue) {
+            return new TestClass(option, testValue);
+        }
+        Object option;
+        Object testValue;
+    }
+
+    // The tests set the option using the new API, read back the set value
+    // which could be diferent, and then use the legacy get API to check
+    // these values are the same
+
+    static TestClass[] socketTests = new TestClass[] {
+            TestClass.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE),
+            TestClass.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
+            TestClass.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+            TestClass.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+            TestClass.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
+            TestClass.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)),
+            TestClass.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
+    };
+
+    static TestClass[] serverSocketTests = new TestClass[] {
+            TestClass.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+            TestClass.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+            TestClass.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
+            TestClass.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
+    };
+
+    static TestClass[] dgSocketTests = new TestClass[] {
+            TestClass.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
+            TestClass.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
+            TestClass.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+            TestClass.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
+            TestClass.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
+    };
+
+    static TestClass[] mcSocketTests = new TestClass[] {
+            // Android-removed: unused in Android
+            // TestClass.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()),
+            TestClass.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)),
+            TestClass.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE)
+    };
+
+    static void doSocketTests() throws Exception {
+        try (
+                ServerSocket srv = new ServerSocket(0);
+                Socket c = new Socket("127.0.0.1", srv.getLocalPort());
+                Socket s = srv.accept();
+        ) {
+            Set<SocketOption<?>> options = c.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+            for (int i=0; i<socketTests.length; i++) {
+                TestClass test = socketTests[i];
+                if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
+                    c.setOption((SocketOption)test.option, test.testValue);
+                    Object getval = c.getOption((SocketOption)test.option);
+                    Object legacyget = legacyGetOption(Socket.class, c,test.option);
+                    if (!getval.equals(legacyget)) {
+                        Formatter f = new Formatter();
+                        f.format("S Err %d: %s/%s", i, getval, legacyget);
+                        throw new RuntimeException(f.toString());
+                    }
+                }
+            }
+        }
+    }
+
+    static void doDgSocketTests() throws Exception {
+        try (
+                DatagramSocket c = new DatagramSocket(0);
+        ) {
+            Set<SocketOption<?>> options = c.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+            for (int i=0; i<dgSocketTests.length; i++) {
+                TestClass test = dgSocketTests[i];
+                if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
+                    c.setOption((SocketOption)test.option, test.testValue);
+                    Object getval = c.getOption((SocketOption)test.option);
+                    Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option);
+                    if (!getval.equals(legacyget)) {
+                        Formatter f = new Formatter();
+                        f.format("DG Err %d: %s/%s", i, getval, legacyget);
+                        throw new RuntimeException(f.toString());
+                    }
+                }
+            }
+        }
+    }
+
+    static void doMcSocketTests() throws Exception {
+        try (
+                MulticastSocket c = new MulticastSocket(0);
+        ) {
+            for (int i=0; i<mcSocketTests.length; i++) {
+                TestClass test = mcSocketTests[i];
+                c.setOption((SocketOption)test.option, test.testValue);
+                Object getval = c.getOption((SocketOption)test.option);
+                Object legacyget = legacyGetOption(MulticastSocket.class, c,test.option);
+                if (!getval.equals(legacyget)) {
+                    Formatter f = new Formatter();
+                    f.format("MC Err %d: %s/%s", i, getval, legacyget);
+                    throw new RuntimeException(f.toString());
+                }
+            }
+        }
+    }
+
+    static void doServerSocketTests() throws Exception {
+        try (
+                ServerSocket c = new ServerSocket(0);
+        ) {
+            Set<SocketOption<?>> options = c.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+            for (int i=0; i<serverSocketTests.length; i++) {
+                TestClass test = serverSocketTests[i];
+                if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
+                    c.setOption((SocketOption)test.option, test.testValue);
+                    Object getval = c.getOption((SocketOption)test.option);
+                    Object legacyget = legacyGetOption(
+                            ServerSocket.class, c, test.option
+                    );
+                    if (!getval.equals(legacyget)) {
+                        Formatter f = new Formatter();
+                        f.format("SS Err %d: %s/%s", i, getval, legacyget);
+                        throw new RuntimeException(f.toString());
+                    }
+                }
+            }
+        }
+    }
+
+    static Object legacyGetOption(
+            Class<?> type, Object s, Object option)
+
+            throws Exception
+    {
+        if (type.equals(Socket.class)) {
+            Socket socket = (Socket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+
+            if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) {
+                return Boolean.valueOf(socket.getKeepAlive());
+            } else if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
+                return Integer.valueOf(socket.getSendBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
+            } else if (option.equals(StandardSocketOptions.SO_LINGER)) {
+                return Integer.valueOf(socket.getSoLinger());
+            } else if (option.equals(StandardSocketOptions.IP_TOS)) {
+                return Integer.valueOf(socket.getTrafficClass());
+            } else if (option.equals(StandardSocketOptions.TCP_NODELAY)) {
+                return Boolean.valueOf(socket.getTcpNoDelay());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        } else if  (type.equals(ServerSocket.class)) {
+            ServerSocket socket = (ServerSocket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+
+            if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
+            } else if (option.equals(StandardSocketOptions.IP_TOS)) {
+                return getServerSocketTrafficClass(socket);
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        } else if  (type.equals(DatagramSocket.class)) {
+            DatagramSocket socket = (DatagramSocket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+
+            if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
+                return Integer.valueOf(socket.getSendBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
+            } else if (option.equals(StandardSocketOptions.IP_TOS)) {
+                return Integer.valueOf(socket.getTrafficClass());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+
+        } else if  (type.equals(MulticastSocket.class)) {
+            MulticastSocket socket = (MulticastSocket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+
+            if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
+                return Integer.valueOf(socket.getSendBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
+                return Integer.valueOf(socket.getReceiveBufferSize());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
+                return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
+            } else if (option.equals(StandardSocketOptions.IP_TOS)) {
+                return Integer.valueOf(socket.getTrafficClass());
+            } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) {
+                return socket.getNetworkInterface();
+            } else if (option.equals(StandardSocketOptions.IP_MULTICAST_TTL)) {
+                return Integer.valueOf(socket.getTimeToLive());
+            } else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) {
+                return Boolean.valueOf(socket.getLoopbackMode());
+            } else {
+                throw new RuntimeException("unexecpted socket option");
+            }
+        }
+        throw new RuntimeException("unexecpted socket type");
+    }
+
+    @Test
+    public void testOptions() throws Exception {
+        doSocketTests();
+        doServerSocketTests();
+        doDgSocketTests();
+        doMcSocketTests();
+    }
+
+    // Reflectively access jdk.net.Sockets.getOption so that the test can run
+    // without the jdk.net module.
+    static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception {
+        try {
+            Class<?> c = Class.forName("jdk.net.Sockets");
+            Method m = c.getDeclaredMethod("getOption", ServerSocket.class, SocketOption.class);
+            return m.invoke(null, ss, StandardSocketOptions.IP_TOS);
+        } catch (ClassNotFoundException e) {
+            // Ok, jdk.net module not present, just fall back
+            System.out.println("jdk.net module not present, falling back.");
+            return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS));
+        } catch (ReflectiveOperationException e) {
+            throw new AssertionError(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/SocketOptions/QuickAckTest.java b/ojluni/src/test/java/net/SocketOptions/QuickAckTest.java
new file mode 100644
index 0000000..1a68189
--- /dev/null
+++ b/ojluni/src/test/java/net/SocketOptions/QuickAckTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8145635
+ * @summary Add TCP_QUICKACK socket option
+ * @modules jdk.net
+ * @run main QuickAckTest
+ */
+package test.java.net.SocketOptions;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.MulticastSocket;
+import java.net.ServerSocket;
+import java.net.Socket;
+import jdk.net.ExtendedSocketOptions;
+import jdk.net.Sockets;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class QuickAckTest {
+
+    private static final String LOCAL_HOST = "127.0.0.1";
+
+    @Test
+    public void TestQuickAck() throws IOException {
+
+        try (ServerSocket ss = new ServerSocket(0);
+             Socket s = new Socket(LOCAL_HOST, ss.getLocalPort());
+             DatagramSocket ds = new DatagramSocket(0);
+             MulticastSocket mc = new MulticastSocket(0)) {
+
+            if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) {
+                Sockets.setOption(ss, ExtendedSocketOptions.TCP_QUICKACK, true);
+                if (!ss.getOption(ExtendedSocketOptions.TCP_QUICKACK)) {
+                    Assert.fail("Test failed, TCP_QUICKACK should"
+                            + " have been set");
+                }
+            }
+            if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) {
+                Sockets.setOption(s, ExtendedSocketOptions.TCP_QUICKACK, true);
+                if (!s.getOption(ExtendedSocketOptions.TCP_QUICKACK)) {
+                    Assert.fail("Test failed, TCP_QUICKACK should"
+                            + " have been set");
+                }
+            }
+            if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) {
+                Assert.fail("Test failed, TCP_QUICKACK is applicable"
+                        + " for TCP Sockets only.");
+            }
+            if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_QUICKACK)) {
+                Assert.fail("Test failed, TCP_QUICKACK is applicable"
+                        + " for TCP Sockets only");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/SocketOptions/SupportedOptionsSet.java b/ojluni/src/test/java/net/SocketOptions/SupportedOptionsSet.java
new file mode 100644
index 0000000..8cc030a
--- /dev/null
+++ b/ojluni/src/test/java/net/SocketOptions/SupportedOptionsSet.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.net.SocketOptions;
+
+import java.io.IOException;
+import java.net.*;
+import java.util.Set;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8143923
+ * @summary java.net socket supportedOptions set depends on call order
+ * @run main/othervm SupportedOptionsSet first
+ * @run main/othervm SupportedOptionsSet second
+ * @run main/othervm -Djava.net.preferIPv4Stack=true SupportedOptionsSet first
+ * @run main/othervm -Djava.net.preferIPv4Stack=true SupportedOptionsSet second
+ */
+
+// Run with othervm as the implementation of the supported options sets, once
+// calculated, stores them in a private static fields.
+
+public class SupportedOptionsSet {
+
+    @Test
+    public void testSupportedOptionsSet() throws IOException {
+        first();
+        second();
+    }
+
+    static void first() throws IOException {
+        try (Socket s = new Socket();
+             ServerSocket ss = new ServerSocket();
+             DatagramSocket ds = new DatagramSocket();
+             MulticastSocket ms = new MulticastSocket()) {
+
+            Set<?> first = s.supportedOptions();
+            Set<?> second = ss.supportedOptions();
+            assertNotEqual(first, second,
+                    "Socket and ServerSocket should have different options.");
+
+            first = ds.supportedOptions();
+            second = ms.supportedOptions();
+            assertNotEqual(first, second,
+                    "DatagramSocket and MulticastSocket should have different options.");
+        }
+    }
+
+    /** Tests with the order of access to supportedOptions reversed.  */
+    static void second() throws IOException {
+        try (ServerSocket ss = new ServerSocket();
+             Socket s = new Socket();
+             DatagramSocket ds = new DatagramSocket();
+             MulticastSocket ms = new MulticastSocket()) {
+
+            Set<?> first = ss.supportedOptions();
+            Set<?> second = s.supportedOptions();
+            assertNotEqual(first, second,
+                    "ServerSocket and Socket should have different options.");
+
+            first = ms.supportedOptions();
+            second = ds.supportedOptions();
+            assertNotEqual(first, second,
+                    "MulticastSocket and DatagramSocket should have different options.");
+
+        }
+    }
+
+    static void assertNotEqual(Set<?> s1, Set<?> s2, String message) {
+        if (s1.equals(s2)) {
+            throw new RuntimeException(message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/SocketOptions/TcpKeepAliveTest.java b/ojluni/src/test/java/net/SocketOptions/TcpKeepAliveTest.java
new file mode 100644
index 0000000..8aabe4d
--- /dev/null
+++ b/ojluni/src/test/java/net/SocketOptions/TcpKeepAliveTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8194298
+ * @summary Add support for per Socket configuration of TCP keepalive
+ * @modules jdk.net
+ * @run main TcpKeepAliveTest
+ */
+package test.java.net.SocketOptions;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.MulticastSocket;
+import java.net.ServerSocket;
+import java.net.Socket;
+import jdk.net.ExtendedSocketOptions;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class TcpKeepAliveTest {
+
+    private static final String LOCAL_HOST = "127.0.0.1";
+    private static final int DEFAULT_KEEP_ALIVE_PROBES = 7;
+    private static final int DEFAULT_KEEP_ALIVE_TIME = 1973;
+    private static final int DEFAULT_KEEP_ALIVE_INTVL = 53;
+
+    @Test
+    public void testTcpKeepAlive() throws IOException {
+
+        try (ServerSocket ss = new ServerSocket(0);
+             Socket s = new Socket(LOCAL_HOST, ss.getLocalPort());
+             DatagramSocket ds = new DatagramSocket(0);
+             MulticastSocket mc = new MulticastSocket(0)) {
+            if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
+                ss.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME);
+                if (ss.getOption(ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) {
+                    Assert.fail("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME);
+                }
+            }
+            if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
+                ss.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES);
+                if (ss.getOption(ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) {
+                    Assert.fail("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES);
+                }
+            }
+            if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
+                ss.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL);
+                if (ss.getOption(ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) {
+                    Assert.fail("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL);
+                }
+            }
+            if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
+                s.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME);
+                if (s.getOption(ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) {
+                    Assert.fail("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME);
+                }
+            }
+            if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
+                s.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES);
+                if (s.getOption(ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) {
+                    Assert.fail("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES);
+                }
+            }
+            if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
+                s.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL);
+                if (s.getOption(ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) {
+                    Assert.fail("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL);
+                }
+            }
+            if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
+                Assert.fail("Test failed, TCP_KEEPCOUNT is applicable"
+                        + " for TCP Sockets only.");
+            }
+            if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
+                Assert.fail("Test failed, TCP_KEEPIDLE is applicable"
+                        + " for TCP Sockets only.");
+            }
+            if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
+                Assert.fail("Test failed, TCP_KEEPINTERVAL is applicable"
+                        + " for TCP Sockets only.");
+            }
+            if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
+                Assert.fail("Test failed, TCP_KEEPCOUNT is applicable"
+                        + " for TCP Sockets only");
+            }
+            if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
+                Assert.fail("Test failed, TCP_KEEPIDLE is applicable"
+                        + " for TCP Sockets only");
+            }
+            if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
+                Assert.fail("Test failed, TCP_KEEPINTERVAL is applicable"
+                        + " for TCP Sockets only");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLDecoder/B6463990.java b/ojluni/src/test/java/net/URLDecoder/B6463990.java
new file mode 100644
index 0000000..88e4ddf
--- /dev/null
+++ b/ojluni/src/test/java/net/URLDecoder/B6463990.java
@@ -0,0 +1,45 @@
+ /*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 6463990
+ * @summary java.net.URLDecoder.decode accepts negative hex numbers %-1 to %-f
+ */
+package test.java.net.URLDecoder;
+
+import java.net.URLDecoder;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class B6463990 {
+
+    @Test
+    public void testB6463990() throws Exception {
+        try {
+            URLDecoder ud = new java.net.URLDecoder();
+            String s = ud.decode("%-1", "iso-8859-1");
+            Assert.fail("IllegalArgumentException not thrown!");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLDecoder/EncodeDecode.java b/ojluni/src/test/java/net/URLDecoder/EncodeDecode.java
new file mode 100644
index 0000000..1469ca9
--- /dev/null
+++ b/ojluni/src/test/java/net/URLDecoder/EncodeDecode.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4402326
+ * @summary  URLDecoder fails with certain input
+ */
+package test.java.net.URLDecoder;
+
+import java.net.*;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class EncodeDecode {
+
+    @Test
+    public void testEncodeDecode() {
+        String str = "fds@$";
+        String encStr = URLEncoder.encode(str);
+        String decStr = URLDecoder.decode(encStr);
+        Assert.assertEquals(str, decStr);
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLDecoder/EncodingTest.java b/ojluni/src/test/java/net/URLDecoder/EncodingTest.java
new file mode 100644
index 0000000..ec65de3
--- /dev/null
+++ b/ojluni/src/test/java/net/URLDecoder/EncodingTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.net.URLDecoder;
+
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183743
+ * @summary Test to verify the new overload method with Charset functions the
+ * same as the existing method that takes a charset name.
+ * @run testng EncodingTest
+ */
+public class EncodingTest {
+    public static enum ParameterType {
+        STRING,
+        CHARSET
+    }
+
+    @DataProvider(name = "illegalArgument")
+    public Object[][] getParameters() {
+        return new Object[][]{
+                {ParameterType.STRING},
+                {ParameterType.CHARSET}
+        };
+    }
+
+    @DataProvider(name = "decode")
+    public Object[][] getDecodeParameters() {
+        return new Object[][]{
+                {"The string \u00FC@foo-bar"},
+                // the string from javadoc example
+
+                {""}, // an empty string
+
+                {"x"}, // a string of length 1
+
+                {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.*"},
+                // the string of characters should remain the same
+
+                {charactersRange('\u0000', '\u007F')},
+                // a string of characters from 0 to 127
+
+                {charactersRange('\u0080', '\u00FF')},
+                // a string of characters from 128 to 255
+
+                {"\u0100 \u0101 \u0555 \u07FD \u07FF"},
+                // a string of Unicode values can be expressed as 2 bytes
+
+                {"\u8000 \u8001 \uA000 \uFFFD \uFFFF"}, // a string of Unicode values can be expressed as 3 bytes
+        };
+    }
+
+    /**
+     * Verifies that IAE is thrown when decoding an invalid string using the
+     * existing method or the new overload method.
+     *
+     * @param type the type of the argument, e.g. a String charset name or
+     * charset
+     */
+    @Test(dataProvider = "illegalArgument", expectedExceptions = IllegalArgumentException.class)
+    public void testIllegalArgument(ParameterType type) throws Exception {
+        String encoded = URLEncoder.encode("http://www.xyz.com/find?key=\u0100\u0101",
+                StandardCharsets.UTF_8.name());
+        String illegal = "%" + encoded;
+        String returned;
+        if (type == ParameterType.STRING) {
+            returned = URLDecoder.decode(illegal, StandardCharsets.UTF_8.name());
+        } else {
+            returned = URLDecoder.decode(illegal, StandardCharsets.UTF_8);
+        }
+    }
+
+    /**
+     * Verifies that the returned values of decoding with the existing
+     * and the overload methods match.
+     *
+     * @param s the string to be encoded and then decoded with both existing
+     * and the overload methods.
+     * @throws Exception
+     */
+    @Test(dataProvider = "decode")
+    public void decode(String s) throws Exception {
+        String encoded = URLEncoder.encode(s, StandardCharsets.UTF_8.name());
+        String returned1 = URLDecoder.decode(encoded, StandardCharsets.UTF_8.name());
+        String returned2 = URLDecoder.decode(encoded, StandardCharsets.UTF_8);
+        Assert.assertEquals(returned1, returned2);
+    }
+
+    String charactersRange(char c1, char c2) {
+        StringBuilder sb = new StringBuilder(c2 - c1);
+        for (char c = c1; c < c2; c++) {
+            sb.append(c);
+        }
+
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLDecoder/URLDecoderArgs.java b/ojluni/src/test/java/net/URLDecoder/URLDecoderArgs.java
new file mode 100644
index 0000000..71b24ef
--- /dev/null
+++ b/ojluni/src/test/java/net/URLDecoder/URLDecoderArgs.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4444194 8190577
+ * @summary  java.net.URLDecoder.decode(s, enc) treats an empty encoding name as "UTF-8"
+ */
+package test.java.net.URLDecoder;
+
+import java.net.URLDecoder;
+import java.io.UnsupportedEncodingException;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class URLDecoderArgs {
+
+    @Test
+    public void testDecodeNull() throws Exception {
+        try {
+            String s1 = URLDecoder.decode ("Hello World", (String) null);
+            Assert.fail("NPE should have been thrown");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @Test
+    public  void testDecodeEmpty() {
+        try {
+            String s2 = URLDecoder.decode ("Hello World", "");
+            Assert.fail("empty string was accepted as encoding name");
+        } catch (UnsupportedEncodingException ee) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLEncoder/DecodeNonEncoded.java b/ojluni/src/test/java/net/URLEncoder/DecodeNonEncoded.java
new file mode 100644
index 0000000..94d76c5
--- /dev/null
+++ b/ojluni/src/test/java/net/URLEncoder/DecodeNonEncoded.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4307323
+ * @summary Test URLDecoder on strings that are not legally
+ * encoded. Incomplete escape patterns or illegal hex characters will cause
+ * an exception to be thrown. Otherwise, illegal characters will be
+ * silently accepted.
+ *
+ */
+package test.java.net.URLEncoder;
+
+import java.net.URLDecoder;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+
+public class DecodeNonEncoded {
+
+    static String[] errorStrings
+            = {"%", "%A", "Hello%", "%xy", "%az", "%ab%q"};
+    static String[] ignoreStrings = {"#", "X@Y", "Hello There"};
+
+    @Test
+    public void testDecodeNonEncoded() throws Exception {
+
+        for (int i = 0; i < errorStrings.length; i++) {
+            try {
+                URLDecoder.decode(errorStrings[i]);
+                Assert.fail("String \"" + errorStrings[i]
+                        + "\" should have failed in URLDecoder.decode!");
+            } catch (IllegalArgumentException e) {
+            }
+        }
+
+        String temp;
+        for (int i = 0; i < ignoreStrings.length; i++) {
+            temp = URLDecoder.decode(ignoreStrings[i]);
+            if (!temp.equals(ignoreStrings[i]))
+                Assert.fail("String \"" + ignoreStrings[i]
+                        + "\" was converted to " + temp
+                        +" by URLDecoder.decode to ");
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLEncoder/Decoder.java b/ojluni/src/test/java/net/URLEncoder/Decoder.java
new file mode 100644
index 0000000..1e4deab
--- /dev/null
+++ b/ojluni/src/test/java/net/URLEncoder/Decoder.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4407610
+ * @summary java.net.URLDecode.decode(st,"UTF-16")
+ */
+package test.java.net.URLEncoder;
+
+import java.net.*;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class Decoder {
+
+    @Test
+    public void testDecoder() throws Exception {
+
+        String enc = "UTF-16";
+        String strings[] = {
+                "\u0100\u0101",
+                "\u0100 \u0101",
+                "\u0100 \u0101\u0102",
+                "\u0100 \u0101 \u0102",
+                "\u0100C\u0101 \u0102",
+                "\u0100\u0101\u0102",
+                "?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&?&",
+                "foobar",
+                "foo?bar"
+        };
+
+        for (int i = 0; i < strings.length; i++) {
+            String encoded = URLEncoder.encode(strings[i], enc);
+            String decoded = URLDecoder.decode(encoded, enc);
+            Assert.assertEquals(strings[i], (decoded));
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLEncoder/EncodingTest.java b/ojluni/src/test/java/net/URLEncoder/EncodingTest.java
new file mode 100644
index 0000000..ab4b686
--- /dev/null
+++ b/ojluni/src/test/java/net/URLEncoder/EncodingTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.net.URLEncoder;
+
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183743
+ * @summary Test to verify the new overload method with Charset functions the same
+ * as the existing method that takes a charset name.
+ * @run testng EncodingTest
+ */
+public class EncodingTest {
+
+    @DataProvider(name = "encode")
+    public Object[][] getDecodeParameters() {
+        return new Object[][]{
+                {"The string \u00FC@foo-bar"},
+                // the string from javadoc example
+
+                {""}, // an empty string
+
+                {"x"}, // a string of length 1
+
+                {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-.*"},
+                // the string of characters should remain the same
+
+                {charactersRange('\u0000', '\u007F')},
+                // a string of characters from 0 to 127
+
+                {charactersRange('\u0080', '\u00FF')},
+                // a string of characters from 128 to 255
+
+                {"\u0100 \u0101 \u0555 \u07FD \u07FF"},
+                // a string of Unicode values can be expressed as 2 bytes
+
+                {"\u8000 \u8001 \uA000 \uFFFD \uFFFF"}, // a string of Unicode values can be expressed as 3 bytes
+        };
+    }
+
+    /**
+     * Verifies that the new overload method returns the same result as the
+     * existing method.
+     *
+     * @param s the string to be encoded
+     * @throws Exception if the test fails
+     */
+    @Test(dataProvider = "encode")
+    public void encode(String s) throws Exception {
+        String encoded1 = URLEncoder.encode(s, StandardCharsets.UTF_8.name());
+        String encoded2 = URLEncoder.encode(s, StandardCharsets.UTF_8);
+        Assert.assertEquals(encoded1, encoded2);
+
+        // cross check
+        String returned1 = URLDecoder.decode(encoded1, StandardCharsets.UTF_8.name());
+        String returned2 = URLDecoder.decode(encoded2, StandardCharsets.UTF_8);
+        Assert.assertEquals(returned1, returned2);
+    }
+
+    String charactersRange(char c1, char c2) {
+        StringBuilder sb = new StringBuilder(c2 - c1);
+        for (char c = c1; c < c2; c++) {
+            sb.append(c);
+        }
+
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLEncoder/SurrogatePairs.java b/ojluni/src/test/java/net/URLEncoder/SurrogatePairs.java
new file mode 100644
index 0000000..ed15cc7
--- /dev/null
+++ b/ojluni/src/test/java/net/URLEncoder/SurrogatePairs.java
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test
+ * @bug 4396708
+ * @summary Test URL encoder and decoder on a string that contains
+ * surrogate pairs.
+ *
+ */
+package test.java.net.URLEncoder;
+
+import java.io.*;
+import java.net.*;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/*
+ * Surrogate pairs are two character Unicode sequences where the first
+ * character lies in the range [d800, dbff] and the second character lies
+ * in the range [dc00, dfff]. They are used as an escaping mechanism to add
+ * 1M more characters to Unicode.
+ */
+public class SurrogatePairs {
+
+    static String[] testStrings = {"\uD800\uDC00",
+            "\uD800\uDFFF",
+            "\uDBFF\uDC00",
+            "\uDBFF\uDFFF",
+            "1\uDBFF\uDC00",
+            "@\uDBFF\uDC00",
+            "\uDBFF\uDC001",
+            "\uDBFF\uDC00@",
+            "\u0101\uDBFF\uDC00",
+            "\uDBFF\uDC00\u0101"
+    };
+
+    static String[] correctEncodings = {"%F0%90%80%80",
+            "%F0%90%8F%BF",
+            "%F4%8F%B0%80",
+            "%F4%8F%BF%BF",
+            "1%F4%8F%B0%80",
+            "%40%F4%8F%B0%80",
+            "%F4%8F%B0%801",
+            "%F4%8F%B0%80%40",
+            "%C4%81%F4%8F%B0%80",
+            "%F4%8F%B0%80%C4%81"
+    };
+
+    @Test
+    public void testSurrogatePairs() throws Exception {
+        for (int i=0; i < testStrings.length; i++) {
+            test(testStrings[i], correctEncodings[i]);
+        }
+    }
+
+    private static void test(String str, String correctEncoding)
+            throws Exception {
+        String encoded = URLEncoder.encode(str, "UTF-8");
+
+        Assert.assertEquals(encoded, correctEncoding);
+
+        String decoded = URLDecoder.decode(encoded, "UTF-8");
+
+        Assert.assertEquals(str, decoded);
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLEncoder/URLEncodeDecode.java b/ojluni/src/test/java/net/URLEncoder/URLEncodeDecode.java
new file mode 100644
index 0000000..4b514be
--- /dev/null
+++ b/ojluni/src/test/java/net/URLEncoder/URLEncodeDecode.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4257115
+ * @summary Test URL encoder and decoder on a string that contains
+ * characters within and beyond the 8859-1 range.
+ *
+ */
+package test.java.net.URLEncoder;
+
+import java.io.*;
+import java.net.*;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class URLEncodeDecode {
+
+    static char chars[] = {'H', 'e', 'l', 'l', 'o',
+            ' ', '+', '%',
+            '-', '_', '.',       '!', '~', '*', '\'', '(',
+            ')',
+            '@',
+            '\u00ae', '\u0101', '\u10a0'};
+
+    static String str = new String(chars);
+
+    static String correctEncodedUTF8 =
+            "Hello+%2B%25-_.%21%7E*%27%28%29%40%C2%AE%C4%81%E1%82%A0";
+
+    @Test
+    public void testURLEncodeDecode() throws Exception {
+        String enc = "UTF-8";
+        String encoded;
+
+        if (enc == null) {
+            encoded = URLEncoder.encode(str);
+        }
+        else {
+            encoded = URLEncoder.encode(str, enc);
+        }
+        Assert.assertEquals(encoded, correctEncodedUTF8);
+
+        String decoded;
+
+        if (enc == null)
+            decoded = URLDecoder.decode(encoded);
+        else
+            decoded = URLDecoder.decode(encoded, enc);
+
+        Assert.assertEquals(str, decoded);
+
+    }
+
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/net/URLEncoder/URLEncoderEncodeArgs.java b/ojluni/src/test/java/net/URLEncoder/URLEncoderEncodeArgs.java
new file mode 100644
index 0000000..c25a7eb
--- /dev/null
+++ b/ojluni/src/test/java/net/URLEncoder/URLEncoderEncodeArgs.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4395472
+ * @summary  java.net.URLEncode.encode(s, enc) treats an empty encoding name as "UTF-8"
+ */
+package test.java.net.URLEncoder;
+
+import java.net.URLEncoder;
+import java.io.UnsupportedEncodingException;
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class URLEncoderEncodeArgs {
+
+    @Test
+    public void testEncodeNull() throws Exception {
+        try {
+            String s1 = URLEncoder.encode ("Hello World", (String) null);
+            Assert.fail("null reference was accepted as encoding name");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @Test
+    public void testEncodeEmpty() {
+        try {
+            String s2 = URLEncoder.encode ("Hello World", "");
+            Assert.fail("empty string was accepted as encoding name");
+        } catch (UnsupportedEncodingException ee) {
+            return;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/Basic.java b/ojluni/src/test/java/nio/channels/Channels/Basic.java
new file mode 100644
index 0000000..1b31be0
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/Basic.java
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+/* @test
+ * @bug 4417152 4481572 6248930 6725399 6884800
+ * @summary Test Channels basic functionality
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.charset.*;
+import java.nio.channels.*;
+import org.testng.annotations.Test;
+
+
+public class Basic {
+
+    static String message;
+
+    static String encoding;
+
+    static File blah;
+
+    static int ITERATIONS = 500;
+
+    @Test
+    public void basicTest() throws Exception {
+        message = "ascii data for a test";
+        encoding = "ISO-8859-1";
+        test();
+        message = "\ucafe\ubabe\ucafe\ubabe\ucafe\ubabe";
+        encoding = "UTF-8";
+        test();
+    }
+
+    static void failNpeExpected() {
+        throw new RuntimeException("Did not get the expected NullPointerException.");
+    }
+
+    private static void test() throws Exception {
+        //Test if methods of Channels throw NPE with null argument(s)
+        try {
+            Channels.newInputStream((ReadableByteChannel)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newOutputStream((WritableByteChannel)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            ReadableByteChannel channel = Channels.newChannel((InputStream)null);
+            failNpeExpected();
+        } catch (NullPointerException ne) {}  // OK. As expected.
+
+        try {
+            WritableByteChannel channel = Channels.newChannel((OutputStream)null);
+            failNpeExpected();
+        } catch (NullPointerException ne) {}  // OK. As expected.
+
+        WritableByteChannel wbc = new WritableByteChannel() {
+            public int write(ByteBuffer src) { return 0; }
+            public void close() throws IOException { }
+            public boolean isOpen() { return true; }
+        };
+
+        ReadableByteChannel rbc = new ReadableByteChannel() {
+            public int read(ByteBuffer dst) { return 0; }
+            public void close() {}
+            public boolean isOpen() { return true; }
+        };
+
+        try {
+            Channels.newReader((ReadableByteChannel)null,
+                    Charset.defaultCharset().newDecoder(),
+                    -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newReader(rbc, (CharsetDecoder)null, -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newReader((ReadableByteChannel)null,
+                    Charset.defaultCharset().name());
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newReader(rbc, (String)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+
+        try {
+            Channels.newReader(null, (String)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newReader(rbc, (Charset)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+
+        try {
+            Channels.newReader(null, (Charset)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter((WritableByteChannel)null,
+                    Charset.defaultCharset().newEncoder(),
+                    -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(null, null, -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(wbc, null, -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter((WritableByteChannel)null,
+                    Charset.defaultCharset().name());
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(wbc, (String)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(null, (String)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(wbc, (Charset)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(null, (Charset)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            blah = File.createTempFile("blah", null);
+
+            testNewOutputStream(blah);
+            readAndCheck(blah);
+            blah.delete();
+
+            writeOut(blah, ITERATIONS);
+            testNewInputStream(blah);
+            blah.delete();
+
+            testNewChannelOut(blah);
+            readAndCheck(blah);
+            blah.delete();
+
+            testNewChannelWriteAfterClose(blah);
+
+            testNewChannelReadAfterClose(blah);
+            blah.delete();
+
+            writeOut(blah, ITERATIONS);
+            testNewChannelIn(blah);
+            test4481572(blah);
+            blah.delete();
+
+            testNewWriter(blah);
+            readAndCheck(blah);
+            blah.delete();
+
+            writeOut(blah, ITERATIONS);
+            testNewReader(blah);
+
+        } finally {
+            blah.delete();
+        }
+    }
+
+    private static void readAndCheck(File blah) throws Exception {
+        FileInputStream fis = new FileInputStream(blah);
+        int messageSize = message.length() * ITERATIONS * 3 + 1;
+        byte bb[] = new byte[messageSize];
+        int bytesRead = 0;
+        int totalRead = 0;
+        while (bytesRead != -1) {
+            totalRead += bytesRead;
+            bytesRead = fis.read(bb, totalRead, messageSize - totalRead);
+        }
+        String result = new String(bb, 0, totalRead, encoding);
+        int len = message.length();
+        for (int i=0; i<ITERATIONS; i++) {
+            String segment = result.substring(i++ * len, i * len);
+            if (!segment.equals(message))
+                throw new RuntimeException("Test failed");
+        }
+        fis.close();
+    }
+
+    private static void writeOut(File blah, int limit) throws Exception {
+        FileOutputStream fos = new FileOutputStream(blah);
+        for (int i=0; i<limit; i++)
+            fos.write(message.getBytes(encoding));
+        fos.close();
+    }
+
+    private static void testNewOutputStream(File blah) throws Exception {
+        FileOutputStream fos = new FileOutputStream(blah);
+        FileChannel fc = fos.getChannel();
+        WritableByteChannel wbc = (WritableByteChannel)fc;
+        OutputStream os = Channels.newOutputStream(wbc);
+        for (int i=0; i<ITERATIONS; i++)
+            os.write(message.getBytes(encoding));
+        os.close();
+        fos.close();
+    }
+
+    private static void testNewInputStream(File blah) throws Exception {
+        FileInputStream fis = new FileInputStream(blah);
+        FileChannel fc = fis.getChannel();
+        InputStream is = Channels.newInputStream(fc);
+        int messageSize = message.length() * ITERATIONS * 3 + 1;
+        byte bb[] = new byte[messageSize];
+
+        int bytesRead = 0;
+        int totalRead = 0;
+        while (bytesRead != -1) {
+            totalRead += bytesRead;
+            long rem = Math.min(fc.size() - totalRead, (long)Integer.MAX_VALUE);
+            if (is.available() != (int)rem)
+                throw new RuntimeException("available not useful or not maximally useful");
+            bytesRead = is.read(bb, totalRead, messageSize - totalRead);
+        }
+        if (is.available() != 0)
+            throw new RuntimeException("available() should return 0 at EOF");
+
+        String result = new String(bb, 0, totalRead, encoding);
+        int len = message.length();
+        for (int i=0; i<ITERATIONS; i++) {
+            String segment = result.substring(i++ * len, i * len);
+            if (!segment.equals(message))
+                throw new RuntimeException("Test failed");
+        }
+        is.close();
+        fis.close();
+    }
+
+    private static void testNewChannelOut(File blah) throws Exception {
+        ExtendedFileOutputStream fos = new ExtendedFileOutputStream(blah);
+        WritableByteChannel wbc = Channels.newChannel(fos);
+
+        for (int i=0; i<ITERATIONS; i++)
+            wbc.write(ByteBuffer.wrap(message.getBytes(encoding)));
+        wbc.close();
+        fos.close();
+    }
+
+    private static void testNewChannelIn(File blah) throws Exception {
+        ExtendedFileInputStream fis = new ExtendedFileInputStream(blah);
+        ReadableByteChannel rbc = Channels.newChannel(fis);
+
+        int messageSize = message.length() * ITERATIONS * 3;
+        byte data[] = new byte[messageSize+1];
+        ByteBuffer bb = ByteBuffer.wrap(data);
+
+        int bytesRead = 0;
+        int totalRead = 0;
+        while (bytesRead != -1) {
+            totalRead += bytesRead;
+            bytesRead = rbc.read(bb);
+        }
+
+        String result = new String(data, 0, totalRead, encoding);
+        int len = message.length();
+        for (int i=0; i<ITERATIONS; i++) {
+            String segment = result.substring(i++ * len, i * len);
+            if (!segment.equals(message))
+                throw new RuntimeException("Test failed");
+        }
+        rbc.close();
+        fis.close();
+    }
+
+    private static void testNewChannelWriteAfterClose(File blah)
+            throws Exception {
+        try (ExtendedFileOutputStream fos =
+                     new ExtendedFileOutputStream(blah)) {
+            WritableByteChannel wbc = Channels.newChannel(fos);
+
+            wbc.close();
+            try {
+                wbc.write(ByteBuffer.allocate(0));
+                throw new RuntimeException
+                        ("No ClosedChannelException on WritableByteChannel::write");
+            } catch (ClosedChannelException expected) {
+            }
+        }
+    }
+
+    private static void testNewChannelReadAfterClose(File blah)
+            throws Exception {
+        try (ExtendedFileInputStream fis = new ExtendedFileInputStream(blah)) {
+            ReadableByteChannel rbc = Channels.newChannel(fis);
+
+            rbc.close();
+            try {
+                rbc.read(ByteBuffer.allocate(0));
+                throw new RuntimeException
+                        ("No ClosedChannelException on ReadableByteChannel::read");
+            } catch (ClosedChannelException expected) {
+            }
+        }
+    }
+
+    // Causes BufferOverflowException if bug 4481572 is present.
+    private static void test4481572(File blah) throws Exception {
+        ExtendedFileInputStream fis = new ExtendedFileInputStream(blah);
+        ReadableByteChannel rbc = Channels.newChannel(fis);
+
+        byte data[] = new byte[9000];
+        ByteBuffer bb = ByteBuffer.wrap(data);
+
+        int bytesRead = 1;
+        int totalRead = 0;
+        while (bytesRead > 0) {
+            totalRead += bytesRead;
+            bytesRead = rbc.read(bb);
+        }
+        rbc.close();
+        fis.close();
+    }
+
+    private static void testNewWriter(File blah) throws Exception {
+        FileOutputStream fos = new FileOutputStream(blah);
+        WritableByteChannel wbc = (WritableByteChannel)fos.getChannel();
+        Writer w = Channels.newWriter(wbc, encoding);
+        char data[] = new char[40];
+        message.getChars(0, message.length(), data, 0);
+        for (int i=0; i<ITERATIONS; i++)
+            w.write(data, 0, message.length());
+        w.flush();
+        w.close();
+        fos.close();
+    }
+
+    private static void testNewReader(File blah) throws Exception {
+        FileInputStream fis = new FileInputStream(blah);
+        ReadableByteChannel rbc = (ReadableByteChannel)fis.getChannel();
+        Reader r = Channels.newReader(rbc, encoding);
+
+        int messageSize = message.length() * ITERATIONS;
+        char data[] = new char[messageSize];
+
+        int totalRead = 0;
+        int charsRead = 0;
+        while (totalRead < messageSize) {
+            totalRead += charsRead;
+            charsRead = r.read(data, totalRead, messageSize - totalRead);
+        }
+        String result = new String(data, 0, totalRead);
+        int len = message.length();
+        for (int i=0; i<ITERATIONS; i++) {
+            String segment = result.substring(i++ * len, i * len);
+            if (!segment.equals(message))
+                throw new RuntimeException("Test failed");
+        }
+        r.close();
+        fis.close();
+    }
+}
+
+class ExtendedFileInputStream extends java.io.FileInputStream {
+    ExtendedFileInputStream(File file) throws FileNotFoundException {
+        super(file);
+    }
+}
+
+class ExtendedFileOutputStream extends java.io.FileOutputStream {
+    ExtendedFileOutputStream(File file) throws FileNotFoundException {
+        super(file);
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/Basic2.java b/ojluni/src/test/java/nio/channels/Channels/Basic2.java
new file mode 100644
index 0000000..b3e2849
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/Basic2.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+/* @test
+ * @bug 4607272
+ * @summary Test Channels methods for interoperability between streams and
+ *     asynchronous byte channels
+ * @key randomness
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Random;
+import org.testng.annotations.Test;
+
+public class Basic2 {
+
+    static final Random rand = new Random();
+
+    @Test
+    public void basic2Test() throws Exception {
+        // establish loopback connection
+        AsynchronousServerSocketChannel listener =
+                AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(0));
+        int port = ((InetSocketAddress)(listener.getLocalAddress())).getPort();
+        InetSocketAddress isa =
+                new InetSocketAddress(InetAddress.getLocalHost(), port);
+        AsynchronousSocketChannel ch1 = AsynchronousSocketChannel.open();
+        ch1.connect(isa).get();
+        AsynchronousSocketChannel ch2 = listener.accept().get();
+
+        // start thread to write to stream
+        Writer writer = new Writer(Channels.newOutputStream(ch1));
+        Thread writerThread = new Thread(writer);
+        writerThread.start();
+
+        // start thread to read from stream
+        Reader reader = new Reader(Channels.newInputStream(ch2));
+        Thread readerThread = new Thread(reader);
+        readerThread.start();
+
+        // wait for threads to complete
+        writerThread.join();
+        readerThread.join();
+
+        // shutdown listener
+        listener.close();
+
+        // check that reader received what we expected
+        if (reader.total() != writer.total())
+            throw new RuntimeException("Unexpected number of bytes read");
+        if (reader.hash() != writer.hash())
+            throw new RuntimeException("Hash incorrect for bytes read");
+
+        // channels should be closed
+        if (ch1.isOpen() || ch2.isOpen())
+            throw new RuntimeException("Channels should be closed");
+    }
+
+    static class Reader implements Runnable {
+        private final InputStream in;
+        private volatile int total;
+        private volatile int hash;
+
+        Reader(InputStream in) {
+            this.in = in;
+        }
+
+        public void run() {
+            try {
+                int n;
+                do {
+                    // random offset/len
+                    byte[] buf = new byte[128 + rand.nextInt(128)];
+                    int len, off;
+                    if (rand.nextBoolean()) {
+                        len = buf.length;
+                        off = 0;
+                        n = in.read(buf);
+                    } else {
+                        len = 1 + rand.nextInt(64);
+                        off = rand.nextInt(64);
+                        n = in.read(buf, off, len);
+                    }
+                    if (n > len)
+                        throw new RuntimeException("Too many bytes read");
+                    if (n > 0) {
+                        total += n;
+                        for (int i=0; i<n; i++) {
+                            int value = buf[off + i];
+                            hash = hash ^ value;
+                        }
+                    }
+                } while (n > 0);
+                in.close();
+
+            } catch (IOException x) {
+                x.printStackTrace();
+            }
+        }
+
+        int total() { return total; }
+        int hash() { return hash; }
+    }
+
+    static class Writer implements Runnable {
+        private final OutputStream out;
+        private final int total;
+        private volatile int hash;
+
+        Writer(OutputStream out) {
+            this.out = out;
+            this.total = 50*1000 + rand.nextInt(50*1000);
+        }
+
+        public void run() {
+            hash = 0;
+            int rem = total;
+            try {
+                do {
+                    byte[] buf = new byte[1 + rand.nextInt(rem)];
+                    int off, len;
+
+                    // write random bytes
+                    if (rand.nextBoolean()) {
+                        off = 0;
+                        len = buf.length;
+                    } else {
+                        off = rand.nextInt(buf.length);
+                        int r = buf.length - off;
+                        len = (r <= 1) ? 1 : (1 + rand.nextInt(r));
+                    }
+                    for (int i=0; i<len; i++) {
+                        byte value = (byte)rand.nextInt(256);
+                        buf[off + i] = value;
+                        hash = hash ^ value;
+                    }
+                    if ((off == 0) && (len == buf.length)) {
+                        out.write(buf);
+                    } else {
+                        out.write(buf, off, len);
+                    }
+                    rem -= len;
+                } while (rem > 0);
+
+                // close stream when done
+                out.close();
+
+            } catch (IOException x) {
+                x.printStackTrace();
+            }
+        }
+
+        int total() { return total; }
+        int hash() { return hash; }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/EncodingTest.java b/ojluni/src/test/java/nio/channels/Channels/EncodingTest.java
new file mode 100644
index 0000000..ec9324f
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/EncodingTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.StandardCharsets;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8183743
+ * @summary Test to verify the new overload method with Charset functions the same
+ * as the existing method that takes a charset name.
+ * @run testng EncodingTest
+ */
+public class EncodingTest {
+    static final int ITERATIONS = 2;
+    public static final String CS_UTF8 = StandardCharsets.UTF_8.name();
+    public static final String CS_ISO8859 = StandardCharsets.ISO_8859_1.name();
+    // Android-removed: Using temp file instead of user.dir
+    // static String USER_DIR = System.getProperty("user.dir", ".");
+
+    // malformed input: a high surrogate without the low surrogate
+    static char[] illChars = {
+            '\u00fa', '\ud800'
+    };
+
+    static byte[] data = getData();
+
+    static byte[] getData() {
+        try {
+            String str1 = "A string that contains ";
+            String str2 = " , an invalid character for UTF-8.";
+
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            baos.write(str1.getBytes());
+            baos.write(0xFA);
+            baos.write(str2.getBytes());
+            return baos.toByteArray();
+        } catch (IOException ex) {
+            return null; //shouldn't happen
+        }
+    }
+
+    // BEGIN Android-changed: Using temp file instead of user.dir
+    // String testFile = Paths.get(USER_DIR, "channelsEncodingTest.txt").toString();
+    // String testIllegalInput = Paths.get(USER_DIR, "channelsIllegalInputTest.txt").toString();
+    // String testIllegalOutput = Paths.get(USER_DIR, "channelsIllegalOutputTest.txt").toString();
+    private final String testFile;
+    private final String testIllegalInput;
+    private final String testIllegalOutput;
+
+    private final File testFileHandle;
+    private final File testIllegalInputHandle;
+    private final File testIllegalOutputHandle;
+
+    public EncodingTest() throws IOException {
+        testFileHandle = File.createTempFile("channelsEncodingTest", "txt");
+        testIllegalInputHandle = File.createTempFile("channelsIllegalInputTest", "txt");
+        testIllegalOutputHandle = File.createTempFile("channelsIllegalOutputTest", "txt");
+        testFile = testFileHandle.getAbsolutePath();
+        testIllegalInput = testIllegalInputHandle.getAbsolutePath();
+        testIllegalOutput = testIllegalOutputHandle.getAbsolutePath();
+    }
+    // BEGIN Android-changed: Using temp file instead of user.dir
+
+    /*
+     * DataProvider for read and write test.
+     * Writes and reads with the same encoding
+     */
+    @DataProvider(name = "writeAndRead")
+    public Object[][] getWRParameters() {
+        return new Object[][]{
+                {testFile, StandardCharsets.ISO_8859_1.name(), null,
+                        StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1},
+                {testFile, null, StandardCharsets.ISO_8859_1,
+                        StandardCharsets.ISO_8859_1.name(), StandardCharsets.ISO_8859_1},
+                {testFile, StandardCharsets.UTF_8.name(), null,
+                        StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8},
+                {testFile, null, StandardCharsets.UTF_8,
+                        StandardCharsets.UTF_8.name(), StandardCharsets.UTF_8}
+        };
+    }
+
+    /*
+     * DataProvider for illegal input test
+     * Writes the data in ISO8859 and reads with UTF8, expects MalformedInputException
+     */
+    @DataProvider(name = "illegalInput")
+    public Object[][] getParameters() {
+        return new Object[][]{
+                {testIllegalInput, StandardCharsets.ISO_8859_1.name(), null, StandardCharsets.UTF_8.name(), null},
+                {testIllegalInput, StandardCharsets.ISO_8859_1.name(), null, null, StandardCharsets.UTF_8},
+                {testIllegalInput, null, StandardCharsets.ISO_8859_1, StandardCharsets.UTF_8.name(), null},
+                {testIllegalInput, null, StandardCharsets.ISO_8859_1, null, StandardCharsets.UTF_8},
+        };
+    }
+
+    /*
+     * DataProvider for illegal output test
+     * Attempts to write some malformed chars, expects MalformedInputException
+     */
+    @DataProvider(name = "illegalOutput")
+    public Object[][] getWriteParameters() {
+        return new Object[][]{
+                {testIllegalOutput, StandardCharsets.UTF_8.name(), null},
+                {testIllegalOutput, null, StandardCharsets.UTF_8}
+        };
+    }
+
+    /**
+     * Verifies that the Readers created with the following methods are
+     * equivalent:
+     * newReader(ReadableByteChannel ch, String csName)
+     * newReader(ReadableByteChannel ch, Charset charset)
+     *
+     * The verification follows the following steps:
+     * Writes a file with a writer created with the specified charset
+     * Reads it with a reader created with newReader using the same charset;
+     * Compares that the results are the same.
+     *
+     * @param file the file name
+     * @param csnWriter the charset name for creating the writer
+     * @param charsetWriter the charset for creating the writer
+     * @param csnReader the charset name for creating the reader
+     * @param charsetReader the charset for creating the reader
+     * @throws Exception
+     */
+    @Test(dataProvider = "writeAndRead")
+    public void testWriteAndRead(String file, String csnWriter, Charset charsetWriter,
+            String csnReader, Charset charsetReader) throws Exception {
+        writeToFile(data, file, csnWriter, charsetWriter);
+        // read using charset name
+        String result1 = readFileToString(file, csnReader, null);
+        String result2 = readFileToString(file, null, charsetReader);
+
+        Assert.assertEquals(result1, result2);
+    }
+
+    /**
+     * Verifies that MalformedInputException is thrown when an input byte sequence
+     * is illegal for given charset that is configured for the reader.
+     *
+     * @param file the file to be read
+     * @param csnWriter the charset name for creating the writer
+     * @param charsetWriter the charset for creating the writer
+     * @param csnReader the charset name for creating the reader
+     * @param charsetReader the charset for creating the reader
+     * @throws Exception
+     */
+    @Test(dataProvider = "illegalInput", expectedExceptions = MalformedInputException.class)
+    void testMalformedInput(String file, String csnWriter, Charset charsetWriter,
+            String csnReader, Charset charsetReader) throws Exception {
+        writeToFile(data, file, csnWriter, charsetWriter);
+        readFileToString(file, csnReader, charsetReader);
+    }
+
+    /**
+     * Attempts to write illegal characters using a writer created by calling
+     * the newWriter method and expects a MalformedInputException.
+     *
+     * @param fileName the file name
+     * @param csn the charset name
+     * @param charset the charset
+     * @throws Exception
+     */
+    @Test(dataProvider = "illegalOutput", expectedExceptions = MalformedInputException.class)
+    public void testMalformedOutput(String fileName, String csn, Charset charset)
+            throws Exception {
+        try (FileOutputStream fos = new FileOutputStream(fileName);
+             WritableByteChannel wbc = (WritableByteChannel) fos.getChannel();) {
+            Writer writer;
+            if (csn != null) {
+                writer = Channels.newWriter(wbc, csn);
+            } else {
+                writer = Channels.newWriter(wbc, charset);
+            }
+
+            for (int i = 0; i < ITERATIONS; i++) {
+                writer.write(illChars);
+            }
+            writer.flush();
+            writer.close();
+        }
+    }
+
+    /**
+     * Writes the data to a file using a writer created by calling the newWriter
+     * method.
+     *
+     * @param data the data to be written
+     * @param fileName the file name
+     * @param csn the charset name
+     * @param charset the charset
+     * @throws Exception
+     */
+    private void writeToFile(byte[] data, String fileName, String csn, Charset charset) throws Exception {
+        try (FileOutputStream fos = new FileOutputStream(fileName);
+             WritableByteChannel wbc = (WritableByteChannel) fos.getChannel()) {
+            Writer writer;
+            String temp;
+            if (csn != null) {
+                writer = Channels.newWriter(wbc, csn);
+                temp = new String(data, csn);
+            } else {
+                writer = Channels.newWriter(wbc, charset);
+                temp = new String(data, charset);
+            }
+
+            for (int i = 0; i < ITERATIONS; i++) {
+                writer.write(temp);
+            }
+            writer.flush();
+            writer.close();
+        }
+    }
+
+    /**
+     * Reads a file into a String.
+     *
+     * @param file the file to be read
+     * @param csn the charset name
+     * @param charset the charset
+     * @throws Exception
+     */
+    String readFileToString(String file, String csn, Charset charset) throws Exception {
+        String result;
+        try (FileInputStream fis = new FileInputStream(file);
+             ReadableByteChannel rbc = (ReadableByteChannel) fis.getChannel()) {
+            Reader reader;
+            if (csn != null) {
+                reader = Channels.newReader(rbc, csn);
+            } else {
+                reader = Channels.newReader(rbc, charset);
+            }
+
+            int messageSize = data.length * ITERATIONS;
+            char data1[] = new char[messageSize];
+            int totalRead = 0;
+            int charsRead = 0;
+            while (totalRead < messageSize) {
+                totalRead += charsRead;
+                charsRead = reader.read(data1, totalRead, messageSize - totalRead);
+            }
+
+            result = new String(data1, 0, totalRead);
+            reader.close();
+        }
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/ReadByte.java b/ojluni/src/test/java/nio/channels/Channels/ReadByte.java
new file mode 100644
index 0000000..9f56154
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/ReadByte.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+/* @test
+ * @bug 4773447
+ * @summary Test Channels.newInputStream.read() method
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.Channels;
+import java.io.InputStream;
+import java.io.IOException;
+import org.testng.annotations.Test;
+
+public class ReadByte {
+
+    @Test
+    public void main() throws IOException {
+        ReadableByteChannel channel = new ReadableByteChannel() {
+            public int read(ByteBuffer dst) {
+                dst.put((byte) 129);
+                return 1;
+            }
+
+            public boolean isOpen() {
+                return true;
+            }
+
+            public void close() {
+            }
+        };
+
+        InputStream in = Channels.newInputStream(channel);
+        int data = in.read();
+        if (data < 0)
+            throw new RuntimeException(
+                    "InputStream.read() spec'd to return 0-255");
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/ReadOffset.java b/ojluni/src/test/java/nio/channels/Channels/ReadOffset.java
new file mode 100644
index 0000000..a76f7fb
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/ReadOffset.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+/* @test
+ * @bug 6545054
+ * @summary Channels.newInputStream.read throws IAE when invoked with
+ *          different offsets.
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.Channels;
+import java.io.InputStream;
+import java.io.IOException;
+import org.testng.annotations.Test;
+
+public class ReadOffset {
+
+    @Test
+    public void testReadOffset() throws IOException {
+        ReadableByteChannel rbc = new ReadableByteChannel() {
+            public int read(ByteBuffer dst) {
+                dst.put((byte)0);
+                return 1;
+            }
+            public boolean isOpen() {
+                return true;
+            }
+            public void close() {
+            }
+        };
+
+        InputStream in = Channels.newInputStream(rbc);
+
+        byte[] b = new byte[3];
+        in.read(b, 0, 1);
+        in.read(b, 2, 1);       // throws IAE
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/ShortWrite.java b/ojluni/src/test/java/nio/channels/Channels/ShortWrite.java
new file mode 100644
index 0000000..809500c
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/ShortWrite.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+/* @test
+ * @bug 6448457
+ * @summary Test Channels.newOutputStream returns OutputStream that handles
+ *     short writes from the underlying channel
+ * @key randomness
+ */
+
+import java.io.OutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.*;
+import java.util.Random;
+import org.testng.annotations.Test;
+
+public class ShortWrite {
+
+    static Random rand = new Random();
+    static int bytesWritten = 0;
+
+    @Test
+    public void testShortWrite() throws IOException {
+
+        WritableByteChannel wbc = new WritableByteChannel() {
+            public int write(ByteBuffer src) {
+                int rem = src.remaining();
+                if (rem > 0) {
+                    // short write
+                    int n = rand.nextInt(rem) + 1;
+                    src.position(src.position() + n);
+                    bytesWritten += n;
+                    return n;
+                } else {
+                    return 0;
+                }
+            }
+            public void close() throws IOException {
+                throw new RuntimeException("not implemented");
+            }
+            public boolean isOpen() {
+                throw new RuntimeException("not implemented");
+            }
+        };
+
+        // wrap Channel with OutputStream
+        OutputStream out = Channels.newOutputStream(wbc);
+
+
+        // write 100, 99, 98, ... 1
+        // and check that the expected number of bytes is written
+        int expected = 0;
+        byte[] buf = new byte[100];
+        for (int i=0; i<buf.length; i++) {
+            int len = buf.length-i;
+            out.write(buf, i, len);
+            expected += len;
+        }
+        System.out.format("Bytes written: %d, expected: %d\n", bytesWritten,
+                expected);
+        if (bytesWritten != expected)
+            throw new RuntimeException("incorrect number of bytes written");
+
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/TinyBuffers.java b/ojluni/src/test/java/nio/channels/Channels/TinyBuffers.java
new file mode 100644
index 0000000..9320ac5
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/TinyBuffers.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+/* @test
+ * @bug 4654722
+ * @summary Ensure that ridiculously tiny buffers work with
+ *          Channels.newReader
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.charset.*;
+import org.testng.annotations.Test;
+
+
+public class TinyBuffers {
+
+    private static Charset cs = Charset.forName("UTF-16");
+
+    private static void test(int sz) throws Exception {
+        ByteArrayInputStream bis = new ByteArrayInputStream(new byte[100]);
+        ReadableByteChannel ch = Channels.newChannel(bis);
+        Reader r = Channels.newReader(ch, cs.newDecoder(), sz);
+        char [] arr = new char[100];
+        System.out.println(r.read(arr, 0, arr.length));
+    }
+
+    @Test
+    public void testTinyBuffers() throws Exception {
+        for (int i = -2; i < 10; i++)
+            test(i);
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Channels/Write.java b/ojluni/src/test/java/nio/channels/Channels/Write.java
new file mode 100644
index 0000000..c2bba58
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Channels/Write.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Channels;
+
+/* @test
+ * @bug 4712766
+ * @summary Test Channels.newOutputStream.write
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import org.testng.annotations.Test;
+
+public class Write {
+
+    @Test
+    public void testWrite() throws Exception {
+        byte[] bb = new byte[3];
+        File testFile = File.createTempFile("test1", null);
+        testFile.deleteOnExit();
+
+        FileOutputStream fos = new FileOutputStream(testFile);
+        FileChannel fc = fos.getChannel();
+        OutputStream out = Channels.newOutputStream(fc);
+
+        out.write(bb,0,1);
+        out.write(bb,2,1);
+
+        out.close();
+        fc.close();
+        fos.close();
+        testFile.delete();
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/SelectionKey/AtomicUpdates.java b/ojluni/src/test/java/nio/channels/SelectionKey/AtomicUpdates.java
new file mode 100644
index 0000000..c25f585
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/SelectionKey/AtomicUpdates.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.SelectionKey;
+
+/* @test
+ * @bug 6350055
+ * @run testng AtomicUpdates
+ * @summary Unit test for SelectionKey interestOpsOr and interestOpsAnd
+ */
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.channels.CancelledKeyException;
+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 org.testng.annotations.Test;
+
+import static java.nio.channels.SelectionKey.OP_READ;
+import static java.nio.channels.SelectionKey.OP_WRITE;
+import static java.nio.channels.SelectionKey.OP_CONNECT;
+import static java.nio.channels.SelectionKey.OP_ACCEPT;
+import static org.testng.Assert.*;
+
+@Test
+public class AtomicUpdates {
+
+    private SelectionKey keyFor(SocketChannel sc) {
+        return new SelectionKey() {
+            private int ops;
+            private boolean invalid;
+            private void ensureValid() {
+                if (!isValid())
+                    throw new CancelledKeyException();
+            }
+            @Override
+            public SelectableChannel channel() {
+                return sc;
+            }
+            @Override
+            public Selector selector() {
+                throw new RuntimeException();
+            }
+            @Override
+            public boolean isValid() {
+                return !invalid;
+            }
+            @Override
+            public void cancel() {
+                invalid = true;
+            }
+            @Override
+            public int interestOps() {
+                ensureValid();
+                return ops;
+            }
+            @Override
+            public SelectionKey interestOps(int ops) {
+                ensureValid();
+                if ((ops & ~channel().validOps()) != 0)
+                    throw new IllegalArgumentException();
+                this.ops = ops;
+                return this;
+            }
+            @Override
+            public int readyOps() {
+                ensureValid();
+                return 0;
+            }
+        };
+    }
+
+    private void test(SelectionKey key) {
+        assertTrue(key.channel() instanceof SocketChannel);
+        key.interestOps(0);
+
+        // 0 -> 0
+        int previous = key.interestOpsOr(0);
+        assertTrue(previous == 0);
+        assertTrue(key.interestOps() == 0);
+
+        // 0 -> OP_CONNECT
+        previous = key.interestOpsOr(OP_CONNECT);
+        assertTrue(previous == 0);
+        assertTrue(key.interestOps() == OP_CONNECT);
+
+        // OP_CONNECT -> OP_CONNECT
+        previous = key.interestOpsOr(0);
+        assertTrue(previous == OP_CONNECT);
+        assertTrue(key.interestOps() == OP_CONNECT);
+
+        // OP_CONNECT -> OP_CONNECT | OP_READ | OP_WRITE
+        previous = key.interestOpsOr(OP_READ | OP_WRITE);
+        assertTrue(previous == OP_CONNECT);
+        assertTrue(key.interestOps() == (OP_CONNECT | OP_READ | OP_WRITE));
+
+        // OP_CONNECT | OP_READ | OP_WRITE -> OP_CONNECT
+        previous = key.interestOpsAnd(~(OP_READ | OP_WRITE));
+        assertTrue(previous == (OP_CONNECT | OP_READ | OP_WRITE));
+        assertTrue(key.interestOps() == OP_CONNECT);
+
+        // OP_CONNECT -> 0
+        previous = key.interestOpsAnd(~OP_CONNECT);
+        assertTrue(previous == OP_CONNECT);
+        assertTrue(key.interestOps() == 0);
+
+        // OP_READ | OP_WRITE -> OP_READ | OP_WRITE
+        key.interestOps(OP_READ | OP_WRITE);
+        previous = key.interestOpsAnd(~OP_ACCEPT);
+        assertTrue(previous == (OP_READ | OP_WRITE));
+        assertTrue(key.interestOps() == (OP_READ | OP_WRITE));
+
+        // OP_READ | OP_WRITE -> 0
+        previous = key.interestOpsAnd(0);
+        assertTrue(previous == (OP_READ | OP_WRITE));
+        assertTrue(key.interestOps() == 0);
+
+        // 0 -> 0
+        previous = key.interestOpsAnd(0);
+        assertTrue(previous == 0);
+        assertTrue(key.interestOps() == 0);
+
+        try {
+            key.interestOpsOr(OP_ACCEPT);
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException expected) { }
+
+        key.cancel();
+        try {
+            key.interestOpsOr(OP_READ);
+            fail("CancelledKeyException expected");
+        } catch (CancelledKeyException expected) { }
+        try {
+            key.interestOpsAnd(~OP_READ);
+            fail("CancelledKeyException expected");
+        } catch (CancelledKeyException expected) { }
+    }
+
+    /**
+     * Test default implementation of interestOpsOr/interestOpsAnd
+     */
+    public void testDefaultImplementation() throws Exception {
+        try (SocketChannel sc = SocketChannel.open()) {
+            SelectionKey key = keyFor(sc);
+            test(key);
+        }
+    }
+
+    /**
+     * Test the default provider implementation of SelectionKey.
+     */
+    public void testNioImplementation() throws Exception {
+        try (SocketChannel sc = SocketChannel.open();
+             Selector sel = Selector.open()) {
+            sc.configureBlocking(false);
+            SelectionKey key = sc.register(sel, 0);
+            test(key);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Selector/ByteServer.java b/ojluni/src/test/java/nio/channels/Selector/ByteServer.java
new file mode 100644
index 0000000..86b154b
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Selector/ByteServer.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Selector;
+
+/**
+ * Utility class for tests. A simple "in-thread" server to accept connections
+ * and write bytes.
+ * @author kladko
+ */
+
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+import java.io.IOException;
+import java.io.Closeable;
+
+public class ByteServer implements Closeable {
+
+    private final ServerSocket ss;
+    private Socket s;
+
+    ByteServer() throws IOException {
+        this.ss = new ServerSocket(0);
+    }
+
+    SocketAddress address() {
+        return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort());
+    }
+
+    void acceptConnection() throws IOException {
+        if (s != null)
+            throw new IllegalStateException("already connected");
+        this.s = ss.accept();
+    }
+
+    void closeConnection() throws IOException {
+        Socket s = this.s;
+        if (s != null) {
+            this.s = null;
+            s.close();
+        }
+    }
+
+    void write(int count) throws IOException {
+        if (s == null)
+            throw new IllegalStateException("no connection");
+        s.getOutputStream().write(new byte[count]);
+    }
+
+    public void close() throws IOException {
+        if (s != null)
+            s.close();
+        ss.close();
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Selector/SelectAfterRead.java b/ojluni/src/test/java/nio/channels/Selector/SelectAfterRead.java
new file mode 100644
index 0000000..1a322d0
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Selector/SelectAfterRead.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Selector;
+
+/* @test
+ * @bug 4639943
+ * @summary  Checks that Windows behavior matches Solaris for
+ *           various read/select combinations.
+ * @author kladko
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import org.testng.annotations.Test;
+
+public class SelectAfterRead {
+
+    private static final int TIMEOUT = 1000;
+
+    @Test
+    public void testSelectAfterRead() throws Exception {
+
+        // server: accept connection and write one byte
+        try (ByteServer server = new ByteServer();
+             SocketChannel sc = SocketChannel.open(server.address())) {
+
+            server.acceptConnection();
+            server.write(1);
+
+            try (Selector sel = Selector.open()) {
+                sc.read(ByteBuffer.allocate(1));
+                sc.configureBlocking(false);
+                sc.register(sel, SelectionKey.OP_READ);
+                // previously on Windows select would select channel here, although there was
+                // nothing to read
+                if (sel.selectNow() != 0)
+                    throw new Exception("Select returned nonzero value");
+            }
+        }
+
+        // Now we will test a two reads combination
+        // server: accept connection and write two bytes
+        try (ByteServer server = new ByteServer();
+             SocketChannel sc = SocketChannel.open(server.address())) {
+
+            server.acceptConnection();
+            server.write(2);
+
+            try (Selector sel = Selector.open()) {
+                sc.configureBlocking(false);
+                sc.register(sel, SelectionKey.OP_READ);
+                if (sel.select(TIMEOUT) != 1)
+                    throw new Exception("One selected key expected");
+                sel.selectedKeys().clear();
+                // previously on Windows a channel would get selected only once
+                if (sel.selectNow() != 1)
+                    throw new Exception("One selected key expected");
+                // Previously on Windows two consequent reads would cause select()
+                // to select a channel, although there was nothing remaining to
+                // read in the channel
+                if (sc.read(ByteBuffer.allocate(1)) != 1)
+                    throw new Exception("One byte expected");
+                if (sc.read(ByteBuffer.allocate(1)) != 1)
+                    throw new Exception("One byte expected");
+                if (sel.selectNow() != 0)
+                    throw new Exception("Select returned nonzero value");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/nio/channels/Selector/SelectWithConsumer.java b/ojluni/src/test/java/nio/channels/Selector/SelectWithConsumer.java
new file mode 100644
index 0000000..c027ad8
--- /dev/null
+++ b/ojluni/src/test/java/nio/channels/Selector/SelectWithConsumer.java
@@ -0,0 +1,764 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.nio.channels.Selector;
+
+/* @test
+ * @bug 8199433 8208780
+ * @run testng SelectWithConsumer
+ * @summary Unit test for Selector select(Consumer), select(Consumer,long) and
+ *          selectNow(Consumer)
+ */
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+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.WritableByteChannel;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import static java.util.concurrent.TimeUnit.*;
+
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class SelectWithConsumer {
+
+    /**
+     * Invoke the select methods that take an action and check that the
+     * accumulated ready ops notified to the action matches the expected ops.
+     */
+    void testActionInvoked(SelectionKey key, int expectedOps) throws Exception {
+        Thread callerThread = Thread.currentThread();
+        Selector sel = key.selector();
+        int interestOps = key.interestOps();
+        AtomicInteger notifiedOps = new AtomicInteger();
+
+        if (expectedOps == 0) {
+            // ensure select(Consumer) does not block indefinitely
+            sel.wakeup();
+        } else {
+            // ensure that the channel is ready for all expected operations
+            sel.select();
+            while ((key.readyOps() & interestOps) != expectedOps) {
+                Thread.sleep(100);
+                sel.select();
+            }
+        }
+
+        // select(Consumer)
+        notifiedOps.set(0);
+        int n = sel.select(k -> {
+            assertTrue(Thread.currentThread() == callerThread);
+            assertTrue(k == key);
+            int readyOps = key.readyOps();
+            assertTrue((readyOps & interestOps) != 0);
+            assertTrue((readyOps & notifiedOps.get()) == 0);
+            notifiedOps.set(notifiedOps.get() | readyOps);
+        });
+        assertTrue((n == 1) ^ (expectedOps == 0));
+        assertTrue(notifiedOps.get() == expectedOps);
+
+        // select(Consumer, timeout)
+        notifiedOps.set(0);
+        n = sel.select(k -> {
+            assertTrue(Thread.currentThread() == callerThread);
+            assertTrue(k == key);
+            int readyOps = key.readyOps();
+            assertTrue((readyOps & interestOps) != 0);
+            assertTrue((readyOps & notifiedOps.get()) == 0);
+            notifiedOps.set(notifiedOps.get() | readyOps);
+        }, 1000);
+        assertTrue((n == 1) ^ (expectedOps == 0));
+        assertTrue(notifiedOps.get() == expectedOps);
+
+        // selectNow(Consumer)
+        notifiedOps.set(0);
+        n = sel.selectNow(k -> {
+            assertTrue(Thread.currentThread() == callerThread);
+            assertTrue(k == key);
+            int readyOps = key.readyOps();
+            assertTrue((readyOps & interestOps) != 0);
+            assertTrue((readyOps & notifiedOps.get()) == 0);
+            notifiedOps.set(notifiedOps.get() | readyOps);
+        });
+        assertTrue((n == 1) ^ (expectedOps == 0));
+        assertTrue(notifiedOps.get() == expectedOps);
+    }
+
+    /**
+     * Test that an action is performed when a channel is ready for reading.
+     */
+    public void testReadable() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SinkChannel sink = p.sink();
+            Pipe.SourceChannel source = p.source();
+            source.configureBlocking(false);
+            SelectionKey key = source.register(sel, SelectionKey.OP_READ);
+
+            // write to sink to ensure source is readable
+            scheduleWrite(sink, messageBuffer(), 100, MILLISECONDS);
+
+            // test that action is invoked
+            testActionInvoked(key, SelectionKey.OP_READ);
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test that an action is performed when a channel is ready for writing.
+     */
+    public void testWritable() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SourceChannel source = p.source();
+            Pipe.SinkChannel sink = p.sink();
+            sink.configureBlocking(false);
+            SelectionKey key = sink.register(sel, SelectionKey.OP_WRITE);
+
+            // test that action is invoked
+            testActionInvoked(key, SelectionKey.OP_WRITE);
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test that an action is performed when a channel is ready for both
+     * reading and writing.
+     */
+    public void testReadableAndWriteable() throws Exception {
+        ServerSocketChannel ssc = null;
+        SocketChannel sc = null;
+        SocketChannel peer = null;
+        try (Selector sel = Selector.open()) {
+            ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
+            sc = SocketChannel.open(ssc.getLocalAddress());
+            sc.configureBlocking(false);
+            SelectionKey key = sc.register(sel, (SelectionKey.OP_READ |
+                    SelectionKey.OP_WRITE));
+
+            // accept connection and write data so the source is readable
+            peer = ssc.accept();
+            peer.write(messageBuffer());
+
+            // test that action is invoked
+            testActionInvoked(key, (SelectionKey.OP_READ | SelectionKey.OP_WRITE));
+        } finally {
+            if (ssc != null) ssc.close();
+            if (sc != null) sc.close();
+            if (peer != null) peer.close();
+        }
+    }
+
+    /**
+     * Test that the action is called for two selected channels
+     */
+    public void testTwoChannels() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SourceChannel source = p.source();
+            Pipe.SinkChannel sink = p.sink();
+            source.configureBlocking(false);
+            sink.configureBlocking(false);
+            SelectionKey key1 = source.register(sel, SelectionKey.OP_READ);
+            SelectionKey key2 = sink.register(sel, SelectionKey.OP_WRITE);
+
+            // write to sink to ensure that the source is readable
+            sink.write(messageBuffer());
+
+            // wait for key1 to be readable
+            sel.select();
+            assertTrue(key2.isWritable());
+            while (!key1.isReadable()) {
+                Thread.sleep(20);
+                sel.select();
+            }
+
+            var counter = new AtomicInteger();
+
+            // select(Consumer)
+            counter.set(0);
+            int n = sel.select(k -> {
+                assertTrue(k == key1 || k == key2);
+                counter.incrementAndGet();
+            });
+            assertTrue(n == 2);
+            assertTrue(counter.get() == 2);
+
+            // select(Consumer, timeout)
+            counter.set(0);
+            n = sel.select(k -> {
+                assertTrue(k == key1 || k == key2);
+                counter.incrementAndGet();
+            }, 1000);
+            assertTrue(n == 2);
+            assertTrue(counter.get() == 2);
+
+            // selectNow(Consumer)
+            counter.set(0);
+            n = sel.selectNow(k -> {
+                assertTrue(k == key1 || k == key2);
+                counter.incrementAndGet();
+            });
+            assertTrue(n == 2);
+            assertTrue(counter.get() == 2);
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test calling select twice, the action should be invoked each time
+     */
+    public void testRepeatedSelect1() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SourceChannel source = p.source();
+            Pipe.SinkChannel sink = p.sink();
+            source.configureBlocking(false);
+            SelectionKey key = source.register(sel, SelectionKey.OP_READ);
+
+            // write to sink to ensure that the source is readable
+            sink.write(messageBuffer());
+
+            // test that action is invoked
+            testActionInvoked(key, SelectionKey.OP_READ);
+            testActionInvoked(key, SelectionKey.OP_READ);
+
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test calling select twice. An I/O operation is performed after the
+     * first select so the channel will not be selected by the second select.
+     */
+    public void testRepeatedSelect2() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SourceChannel source = p.source();
+            Pipe.SinkChannel sink = p.sink();
+            source.configureBlocking(false);
+            SelectionKey key = source.register(sel, SelectionKey.OP_READ);
+
+            // write to sink to ensure that the source is readable
+            sink.write(messageBuffer());
+
+            // test that action is invoked
+            testActionInvoked(key, SelectionKey.OP_READ);
+
+            // read all bytes
+            int n;
+            ByteBuffer bb = ByteBuffer.allocate(100);
+            do {
+                n = source.read(bb);
+                bb.clear();
+            } while (n > 0);
+
+            // test that action is not invoked
+            testActionInvoked(key, 0);
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test timeout
+     */
+    public void testTimeout() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SourceChannel source = p.source();
+            Pipe.SinkChannel sink = p.sink();
+            source.configureBlocking(false);
+            source.register(sel, SelectionKey.OP_READ);
+            long start = System.currentTimeMillis();
+            int n = sel.select(k -> assertTrue(false), 1000L);
+            long duration = System.currentTimeMillis() - start;
+            assertTrue(n == 0);
+            assertTrue(duration > 500, "select took " + duration + " ms");
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test wakeup prior to select
+     */
+    public void testWakeupBeforeSelect() throws Exception {
+        // select(Consumer)
+        try (Selector sel = Selector.open()) {
+            sel.wakeup();
+            int n = sel.select(k -> assertTrue(false));
+            assertTrue(n == 0);
+        }
+
+        // select(Consumer, timeout)
+        try (Selector sel = Selector.open()) {
+            sel.wakeup();
+            long start = System.currentTimeMillis();
+            int n = sel.select(k -> assertTrue(false), 60*1000);
+            long duration = System.currentTimeMillis() - start;
+            assertTrue(n == 0);
+            assertTrue(duration < 5000, "select took " + duration + " ms");
+        }
+    }
+
+    /**
+     * Test wakeup during select
+     */
+    public void testWakeupDuringSelect() throws Exception {
+        // select(Consumer)
+        try (Selector sel = Selector.open()) {
+            scheduleWakeup(sel, 1, SECONDS);
+            int n = sel.select(k -> assertTrue(false));
+            assertTrue(n == 0);
+        }
+
+        // select(Consumer, timeout)
+        try (Selector sel = Selector.open()) {
+            scheduleWakeup(sel, 1, SECONDS);
+            long start = System.currentTimeMillis();
+            int n = sel.select(k -> assertTrue(false), 60*1000);
+            long duration = System.currentTimeMillis() - start;
+            assertTrue(n == 0);
+            assertTrue(duration > 500 && duration < 10*1000,
+                    "select took " + duration + " ms");
+        }
+    }
+
+    /**
+     * Test invoking select with interrupt status set
+     */
+    public void testInterruptBeforeSelect() throws Exception {
+        // select(Consumer)
+        try (Selector sel = Selector.open()) {
+            Thread.currentThread().interrupt();
+            int n = sel.select(k -> assertTrue(false));
+            assertTrue(n == 0);
+            assertTrue(Thread.currentThread().isInterrupted());
+            assertTrue(sel.isOpen());
+        } finally {
+            Thread.currentThread().interrupted();  // clear interrupt status
+        }
+
+        // select(Consumer, timeout)
+        try (Selector sel = Selector.open()) {
+            Thread.currentThread().interrupt();
+            long start = System.currentTimeMillis();
+            int n = sel.select(k -> assertTrue(false), 60*1000);
+            long duration = System.currentTimeMillis() - start;
+            assertTrue(n == 0);
+            assertTrue(duration < 5000, "select took " + duration + " ms");
+            assertTrue(Thread.currentThread().isInterrupted());
+            assertTrue(sel.isOpen());
+        } finally {
+            Thread.currentThread().interrupted();  // clear interrupt status
+        }
+    }
+
+    /**
+     * Test interrupt thread during select
+     */
+    public void testInterruptDuringSelect() throws Exception {
+        // select(Consumer)
+        try (Selector sel = Selector.open()) {
+            scheduleInterrupt(Thread.currentThread(), 1, SECONDS);
+            int n = sel.select(k -> assertTrue(false));
+            assertTrue(n == 0);
+            assertTrue(Thread.currentThread().isInterrupted());
+            assertTrue(sel.isOpen());
+        } finally {
+            Thread.currentThread().interrupted();  // clear interrupt status
+        }
+
+        // select(Consumer, timeout)
+        try (Selector sel = Selector.open()) {
+            scheduleInterrupt(Thread.currentThread(), 1, SECONDS);
+            long start = System.currentTimeMillis();
+            int n = sel.select(k -> assertTrue(false), 60*1000);
+            long duration = System.currentTimeMillis() - start;
+            assertTrue(n == 0);
+            assertTrue(Thread.currentThread().isInterrupted());
+            assertTrue(sel.isOpen());
+        } finally {
+            Thread.currentThread().interrupted();  // clear interrupt status
+        }
+    }
+
+    /**
+     * Test invoking select on a closed selector
+     */
+    @Test(expectedExceptions = ClosedSelectorException.class)
+    public void testClosedSelector1() throws Exception {
+        Selector sel = Selector.open();
+        sel.close();
+        sel.select(k -> assertTrue(false));
+    }
+    @Test(expectedExceptions = ClosedSelectorException.class)
+    public void testClosedSelector2() throws Exception {
+        Selector sel = Selector.open();
+        sel.close();
+        sel.select(k -> assertTrue(false), 1000);
+    }
+    @Test(expectedExceptions = ClosedSelectorException.class)
+    public void testClosedSelector3() throws Exception {
+        Selector sel = Selector.open();
+        sel.close();
+        sel.selectNow(k -> assertTrue(false));
+    }
+
+    /**
+     * Test closing selector while in a selection operation
+     */
+    public void testCloseDuringSelect() throws Exception {
+        // select(Consumer)
+        try (Selector sel = Selector.open()) {
+            scheduleClose(sel, 3, SECONDS);
+            int n = sel.select(k -> assertTrue(false));
+            assertTrue(n == 0);
+            assertFalse(sel.isOpen());
+        }
+
+        // select(Consumer, timeout)
+        try (Selector sel = Selector.open()) {
+            scheduleClose(sel, 3, SECONDS);
+            long start = System.currentTimeMillis();
+            int n = sel.select(k -> assertTrue(false), 60*1000);
+            long duration = System.currentTimeMillis() - start;
+            assertTrue(n == 0);
+            assertTrue(duration > 2000 && duration < 10*1000,
+                    "select took " + duration + " ms");
+            assertFalse(sel.isOpen());
+        }
+    }
+
+    /**
+     * Test action closing selector
+     */
+    @Test(expectedExceptions = ClosedSelectorException.class)
+    public void testActionClosingSelector() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SourceChannel source = p.source();
+            Pipe.SinkChannel sink = p.sink();
+            source.configureBlocking(false);
+            SelectionKey key = source.register(sel, SelectionKey.OP_READ);
+
+            // write to sink to ensure that the source is readable
+            sink.write(messageBuffer());
+
+            // should relay ClosedSelectorException
+            sel.select(k -> {
+                assertTrue(k == key);
+                try {
+                    sel.close();
+                } catch (IOException ioe) { }
+            });
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test that the action is invoked while synchronized on the selector and
+     * its selected-key set.
+     */
+    public void testLocks() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SourceChannel source = p.source();
+            Pipe.SinkChannel sink = p.sink();
+            source.configureBlocking(false);
+            SelectionKey key = source.register(sel, SelectionKey.OP_READ);
+
+            // write to sink to ensure that the source is readable
+            sink.write(messageBuffer());
+
+            // select(Consumer)
+            sel.select(k -> {
+                assertTrue(k == key);
+                assertTrue(Thread.holdsLock(sel));
+                assertFalse(Thread.holdsLock(sel.keys()));
+                assertTrue(Thread.holdsLock(sel.selectedKeys()));
+            });
+
+            // select(Consumer, timeout)
+            sel.select(k -> {
+                assertTrue(k == key);
+                assertTrue(Thread.holdsLock(sel));
+                assertFalse(Thread.holdsLock(sel.keys()));
+                assertTrue(Thread.holdsLock(sel.selectedKeys()));
+            }, 1000L);
+
+            // selectNow(Consumer)
+            sel.selectNow(k -> {
+                assertTrue(k == key);
+                assertTrue(Thread.holdsLock(sel));
+                assertFalse(Thread.holdsLock(sel.keys()));
+                assertTrue(Thread.holdsLock(sel.selectedKeys()));
+            });
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test that selection operations remove cancelled keys from the selector's
+     * key and selected-key sets.
+     */
+    public void testCancel() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SinkChannel sink = p.sink();
+            Pipe.SourceChannel source = p.source();
+
+            // write to sink to ensure that the source is readable
+            sink.write(messageBuffer());
+
+            source.configureBlocking(false);
+            SelectionKey key1 = source.register(sel, SelectionKey.OP_READ);
+            // make sure pipe source is readable before we do following checks.
+            // this is sometime necessary on windows where pipe is implemented
+            // as a pair of connected socket, so there is no guarantee that written
+            // bytes on sink side is immediately available on source side.
+            sel.select();
+
+            sink.configureBlocking(false);
+            SelectionKey key2 = sink.register(sel, SelectionKey.OP_WRITE);
+            sel.selectNow();
+
+            assertTrue(sel.keys().contains(key1));
+            assertTrue(sel.keys().contains(key2));
+            assertTrue(sel.selectedKeys().contains(key1));
+            assertTrue(sel.selectedKeys().contains(key2));
+
+            // cancel key1
+            key1.cancel();
+            int n = sel.selectNow(k -> assertTrue(k == key2));
+            assertTrue(n == 1);
+            assertFalse(sel.keys().contains(key1));
+            assertTrue(sel.keys().contains(key2));
+            sel.selectNow();
+            assertFalse(sel.selectedKeys().contains(key1));
+            assertTrue(sel.selectedKeys().contains(key2));
+
+            // cancel key2
+            key2.cancel();
+            n = sel.selectNow(k -> assertTrue(false));
+            assertTrue(n == 0);
+            assertFalse(sel.keys().contains(key1));
+            assertFalse(sel.keys().contains(key2));
+            assertFalse(sel.selectedKeys().contains(key1));
+            assertFalse(sel.selectedKeys().contains(key2));
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test an action invoking select()
+     */
+    @Test(enabled = false)
+    public void testReentrantSelect1() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SinkChannel sink = p.sink();
+            Pipe.SourceChannel source = p.source();
+            source.configureBlocking(false);
+            source.register(sel, SelectionKey.OP_READ);
+
+            // write to sink to ensure that the source is readable
+            scheduleWrite(sink, messageBuffer(), 100, MILLISECONDS);
+
+            int n = sel.select(k -> {
+                try {
+                    sel.select();
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    throw new RuntimeException(ioe);
+                } catch (IllegalStateException expected) {
+                }
+            });
+            assertTrue(n == 1);
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test an action invoking selectNow()
+     */
+    @Test(enabled = false)
+    public void testReentrantSelect2() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SinkChannel sink = p.sink();
+            Pipe.SourceChannel source = p.source();
+
+            // write to sink to ensure that the source is readable
+            scheduleWrite(sink, messageBuffer(), 100, MILLISECONDS);
+
+            source.configureBlocking(false);
+            source.register(sel, SelectionKey.OP_READ);
+            int n = sel.select(k -> {
+                try {
+                    sel.selectNow();
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    throw new RuntimeException(ioe);
+                } catch (IllegalStateException expected) {
+                }
+            });
+            assertTrue(n == 1);
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Test an action invoking select(Consumer)
+     */
+    @Test(enabled = false)
+    public void testReentrantSelect3() throws Exception {
+        Pipe p = Pipe.open();
+        try (Selector sel = Selector.open()) {
+            Pipe.SinkChannel sink = p.sink();
+            Pipe.SourceChannel source = p.source();
+
+            // write to sink to ensure that the source is readable
+            scheduleWrite(sink, messageBuffer(), 100, MILLISECONDS);
+
+            source.configureBlocking(false);
+            source.register(sel, SelectionKey.OP_READ);
+            int n = sel.select(k -> {
+                try {
+                    sel.select(x -> assertTrue(false));
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    throw new RuntimeException(ioe);
+                } catch (IllegalStateException expected) {
+                }
+            });
+            assertTrue(n == 1);
+        } finally {
+            closePipe(p);
+        }
+    }
+
+    /**
+     * Negative timeout
+     */
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testNegativeTimeout() throws Exception {
+        try (Selector sel = Selector.open()) {
+            sel.select(k -> { }, -1L);
+        }
+    }
+
+    /**
+     * Null action
+     */
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNull1() throws Exception {
+        try (Selector sel = Selector.open()) {
+            sel.select(null);
+        }
+    }
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNull2() throws Exception {
+        try (Selector sel = Selector.open()) {
+            sel.select(null, 1000);
+        }
+    }
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNull3() throws Exception {
+        try (Selector sel = Selector.open()) {
+            sel.selectNow(null);
+        }
+    }
+
+
+    // -- support methods ---
+
+    private final ScheduledExecutorService POOL = Executors.newScheduledThreadPool(1);
+
+    @AfterTest
+    void shutdownThreadPool() {
+        POOL.shutdown();
+    }
+
+    void scheduleWakeup(Selector sel, long delay, TimeUnit unit) {
+        POOL.schedule(() -> sel.wakeup(), delay, unit);
+    }
+
+    void scheduleInterrupt(Thread t, long delay, TimeUnit unit) {
+        POOL.schedule(() -> t.interrupt(), delay, unit);
+    }
+
+    void scheduleClose(Closeable c, long delay, TimeUnit unit) {
+        POOL.schedule(() -> {
+            try {
+                c.close();
+            } catch (IOException ioe) {
+                ioe.printStackTrace();
+            }
+        }, delay, unit);
+    }
+
+    void scheduleWrite(WritableByteChannel sink, ByteBuffer buf, long delay, TimeUnit unit) {
+        POOL.schedule(() -> {
+            try {
+                sink.write(buf);
+            } catch (IOException ioe) {
+                ioe.printStackTrace();
+            }
+        }, delay, unit);
+    }
+
+    static void closePipe(Pipe p) {
+        try { p.sink().close(); } catch (IOException ignore) { }
+        try { p.source().close(); } catch (IOException ignore) { }
+    }
+
+    static ByteBuffer messageBuffer() {
+        try {
+            return ByteBuffer.wrap("message".getBytes("UTF-8"));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/KeyAgreementTest.java b/ojluni/src/test/java/security/KeyAgreement/KeyAgreementTest.java
new file mode 100644
index 0000000..7b126a3
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/KeyAgreementTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4936763 8184359
+ * @summary KeyAgreement Test with all supported algorithms from JCE.
+ *          Arguments order <KeyExchangeAlgorithm> <KeyGenAlgorithm> <Provider>
+ *          It removes com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java
+ *          as the same functionality for DiffieHellman is covered along with
+ *          this test file was covered before with JDK-4936763.
+ */
+package test.java.security.KeyAgreement;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.DHGenParameterSpec;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class KeyAgreementTest {
+
+    List<String> kaAlgos = Arrays.asList("DiffieHellman", "ECDH");
+    List<String> kpgAlgos = Arrays.asList("DH", "EC");
+    List<String> providers = Arrays.asList("BC", "AndroidOpenSSL");
+
+    @Test
+    public void testKeyAgreement() throws Exception {
+        for (int i = 0; i <  kaAlgos.size(); i++) {
+            AlgoSpec aSpec = AlgoSpec.valueOf(AlgoSpec.class, kaAlgos.get(i));
+            List<AlgorithmParameterSpec> specs = aSpec.getAlgorithmParameterSpecs();
+            for (AlgorithmParameterSpec spec : specs) {
+                testKeyAgreement(providers.get(i), kaAlgos.get(i), kpgAlgos.get(i), spec);
+            }
+        }
+    }
+
+    /**
+     * Generate AlgorithmParameterSpec using all possible supported curve for
+     * KeyExchangeAlgorithm.
+     */
+    private enum AlgoSpec {
+        // EC curve supported for KeyGeneration can found between intersection
+        // of curves define in
+        // "java.base/share/classes/sun/security/util/CurveDB.java"
+        // and
+        // "jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c"
+        ECDH( "secp224r1", "secp256r1", "secp384r1", "secp521r1"
+        ),
+        XDH("X25519", "X448"),
+        // There is no curve for DiffieHellman
+        DiffieHellman(new String[]{});
+
+        private final List<AlgorithmParameterSpec> specs = new ArrayList<>();
+
+        private AlgoSpec(String... curves) {
+            // Generate AlgorithmParameterSpec for each KeyExchangeAlgorithm
+            for (String crv : curves) {
+                switch (this.name()) {
+                    case "ECDH":
+                        specs.add(new ECGenParameterSpec(crv));
+                        break;
+                    case "XDH":
+                        specs.add(new NamedParameterSpec(crv));
+                        break;
+                    case "DiffieHellman":
+                        specs.add(new DHGenParameterSpec(512, 64));
+                        break;
+                    default:
+                        fail("Invalid Algo name "
+                                + this.name());
+                }
+            }
+        }
+
+        public List<AlgorithmParameterSpec> getAlgorithmParameterSpecs() {
+            return this.specs;
+        }
+    }
+
+    /**
+     * Perform KeyAgreement operation using native as well as JCE provider.
+     */
+    private static void testKeyAgreement(String provider, String kaAlgo,
+            String kpgAlgo, AlgorithmParameterSpec spec) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+        kpg.initialize(spec);
+        KeyPair kp1 = kpg.generateKeyPair();
+        KeyPair kp2 = kpg.generateKeyPair();
+
+        // Uses KeyAgreement based on Provider search order.
+        KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo);
+        ka1.init(kp1.getPrivate());
+        ka1.doPhase(kp2.getPublic(), true);
+        byte[] secret1 = ka1.generateSecret();
+
+        // Uses SunJCE provider
+        KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider);
+        ka2.init(kp2.getPrivate());
+        ka2.doPhase(kp1.getPublic(), true);
+        // Keeping the legacy generateSecret method for DiffieHellman as it was
+        // defined in removed Test file from JDK-4936763,
+        // com/sun/crypto/provider/KeyAgreement/DHGenSecretKey.java.
+        byte[] secret2 = "DiffieHellman".equals(kaAlgo)
+                ? ka2.generateSecret("AES").getEncoded() : ka2.generateSecret();
+
+        // With related keypairs, each provider should generate same
+        // KeyAgreement secret.
+        if (!Arrays.equals(secret1, secret2)) {
+            fail("KeyAgreement secret mismatch.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/KeySizeTest.java b/ojluni/src/test/java/security/KeyAgreement/KeySizeTest.java
new file mode 100644
index 0000000..9ab73a5
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/KeySizeTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8184359
+ * @summary KeyLength support test for DiffieHellman, EC, XDH.
+ *  Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <keyLen>
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 512
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 768
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 832
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 1024
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 2048
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 3072
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 4096
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 6144
+ * @run main KeySizeTest DiffieHellman SunJCE DiffieHellman 8192
+ * @run main KeySizeTest ECDH SunEC EC 128
+ * @run main KeySizeTest ECDH SunEC EC 192
+ * @run main KeySizeTest ECDH SunEC EC 256
+ * @run main KeySizeTest XDH SunEC XDH 255
+ * @run main KeySizeTest XDH SunEC XDH 448
+ */
+package test.java.security.KeyAgreement;
+
+import java.math.BigInteger;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.XECPrivateKey;
+import java.security.interfaces.XECPublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.NamedParameterSpec;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class KeySizeTest {
+
+    List<Integer> sizesDH = Arrays.asList(512, 768, 832, 1024, 2048);
+    List<Integer> sizesECDH = Arrays.asList(224, 256, 384, 521);
+    List<Integer> sizesXDH = Arrays.asList(512, 768, 832, 1024, 2048, 3072, 4096, 6144, 8192);
+
+    @Test
+    public void testDHKeySize() throws Exception {
+        for (int i = 0; i < sizesDH.size(); i++) {
+            testKeyAgreement("BC", "DiffieHellman", "DiffieHellman", sizesDH.get(i));
+        }
+    }
+
+    @Test
+    public void testECDHKeySize() throws Exception {
+        for (int i = 0; i < sizesECDH.size(); i++) {
+            testKeyAgreement("AndroidOpenSSL", "ECDH", "EC", sizesECDH.get(i));
+        }
+    }
+
+    // BEGIN Android-removed: XDH is not yet supported
+    /*
+    @Test
+    public void testXDHKeySize() throws Exception {
+        for (int i = 0; i < sizesXDH.size(); i++) {
+            testKeyAgreement("AndroidOpenSSL", "XDH", "XDH", sizesXDH.get(i));
+        }
+    }
+     */
+    // END Android-removed: XDH is not yet supported
+
+    /**
+     * Perform KeyAgreement operation.
+     */
+    private static void testKeyAgreement(String provider, String kaAlgo,
+            String kpgAlgo, int keySize) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+        kpg.initialize(keySize);
+        KeyPair kp = kpg.generateKeyPair();
+        // Test standard Key attributes.
+        testKeyAttributes(provider, kpgAlgo, kp, keySize);
+        // Test KeyAgreement.
+        KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);
+        ka.init(kp.getPrivate());
+        ka.doPhase(kp.getPublic(), true);
+        ka.generateSecret();
+    }
+
+    /**
+     * Test standard Key attributes.
+     */
+    private static void testKeyAttributes(String provider, String kpgAlgo,
+            KeyPair kp, int keySize) throws Exception {
+
+        KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+        switch (kpgAlgo) {
+            case "DiffieHellman":
+                // Verify PrivateKey attributes.
+                DHPrivateKey dhPri = (DHPrivateKey) kp.getPrivate();
+                BigInteger p = dhPri.getParams().getP();
+                if (p.bitLength() != keySize) {
+                    fail(String.format("Invalid modulus size: "
+                            + "%s/%s", p.bitLength(), keySize));
+                }
+                if (!p.isProbablePrime(128)) {
+                    fail("The modulus is composite!");
+                }
+                PKCS8EncodedKeySpec dhPriSpec
+                        = new PKCS8EncodedKeySpec(dhPri.getEncoded());
+                DHPrivateKey dhPriDecod
+                        = (DHPrivateKey) kf.generatePrivate(dhPriSpec);
+                equals(dhPri.getX(), dhPriDecod.getX());
+                equals(dhPri.getFormat(), dhPriDecod.getFormat());
+                equals(dhPri.getEncoded(), dhPriDecod.getEncoded());
+                equals(dhPri.getParams().getG(), dhPriDecod.getParams().getG());
+                equals(dhPri.getParams().getL(), dhPriDecod.getParams().getL());
+                equals(dhPri.getParams().getP(), dhPriDecod.getParams().getP());
+
+                // Verify PublicKey attributes.
+                DHPublicKey dhPub = (DHPublicKey) kp.getPublic();
+                p = dhPub.getParams().getP();
+                if (p.bitLength() != keySize) {
+                   fail(String.format("Invalid modulus size: "
+                            + "%s/%s", p.bitLength(), keySize));
+                }
+                X509EncodedKeySpec dhPubSpec
+                        = new X509EncodedKeySpec(dhPub.getEncoded());
+                DHPublicKey dhPubDecod
+                        = (DHPublicKey) kf.generatePublic(dhPubSpec);
+                equals(dhPub.getY(), dhPubDecod.getY());
+                equals(dhPub.getFormat(), dhPubDecod.getFormat());
+                equals(dhPub.getEncoded(), dhPubDecod.getEncoded());
+                equals(dhPub.getParams().getG(), dhPubDecod.getParams().getG());
+                equals(dhPub.getParams().getL(), dhPubDecod.getParams().getL());
+                equals(dhPub.getParams().getP(), dhPubDecod.getParams().getP());
+
+                BigInteger left = BigInteger.ONE;
+                BigInteger right = p.subtract(BigInteger.ONE);
+                BigInteger x = dhPri.getX();
+                if ((x.compareTo(left) <= 0) || (x.compareTo(right) >= 0)) {
+                    fail(
+                            "X outside range [2, p - 2]: x: " + x + " p: " + p);
+                }
+                BigInteger y = dhPub.getY();
+                if ((y.compareTo(left) <= 0) || (y.compareTo(right) >= 0)) {
+                    fail(
+                            "Y outside range [2, p - 2]: x: " + x + " p: " + p);
+                }
+                break;
+            case "EC":
+                // Verify PrivateKey attributes.
+                ECPrivateKey ecPriv = (ECPrivateKey) kp.getPrivate();
+                PKCS8EncodedKeySpec ecPriSpec
+                        = new PKCS8EncodedKeySpec(ecPriv.getEncoded());
+                ECPrivateKey ecPriDecod
+                        = (ECPrivateKey) kf.generatePrivate(ecPriSpec);
+                equals(ecPriv.getS(), ecPriDecod.getS());
+                equals(ecPriv.getFormat(), ecPriDecod.getFormat());
+                equals(ecPriv.getEncoded(), ecPriDecod.getEncoded());
+                equals(ecPriv.getParams().getCofactor(),
+                        ecPriDecod.getParams().getCofactor());
+                equals(ecPriv.getParams().getCurve(),
+                        ecPriDecod.getParams().getCurve());
+                equals(ecPriv.getParams().getGenerator(),
+                        ecPriDecod.getParams().getGenerator());
+                equals(ecPriv.getParams().getOrder(),
+                        ecPriDecod.getParams().getOrder());
+
+                // Verify PublicKey attributes.
+                ECPublicKey ecPub = (ECPublicKey) kp.getPublic();
+                X509EncodedKeySpec ecPubSpec
+                        = new X509EncodedKeySpec(ecPub.getEncoded());
+                ECPublicKey ecPubDecod
+                        = (ECPublicKey) kf.generatePublic(ecPubSpec);
+                equals(ecPub.getW(), ecPubDecod.getW());
+                equals(ecPub.getFormat(), ecPubDecod.getFormat());
+                equals(ecPub.getEncoded(), ecPubDecod.getEncoded());
+                equals(ecPub.getParams().getCofactor(),
+                        ecPubDecod.getParams().getCofactor());
+                equals(ecPub.getParams().getCurve(),
+                        ecPubDecod.getParams().getCurve());
+                equals(ecPub.getParams().getGenerator(),
+                        ecPubDecod.getParams().getGenerator());
+                equals(ecPub.getParams().getOrder(),
+                        ecPubDecod.getParams().getOrder());
+                break;
+            case "XDH":
+                // Verify PrivateKey attributes.
+                XECPrivateKey xdhPri = (XECPrivateKey) kp.getPrivate();
+                PKCS8EncodedKeySpec xdhPriSpec
+                        = new PKCS8EncodedKeySpec(xdhPri.getEncoded());
+                XECPrivateKey xdhPriDec
+                        = (XECPrivateKey) kf.generatePrivate(xdhPriSpec);
+                equals(xdhPri.getScalar().get(), xdhPriDec.getScalar().get());
+                equals(xdhPri.getFormat(), xdhPriDec.getFormat());
+                equals(xdhPri.getEncoded(), xdhPriDec.getEncoded());
+                equals(((NamedParameterSpec) xdhPri.getParams()).getName(),
+                        ((NamedParameterSpec) xdhPriDec.getParams()).getName());
+
+                // Verify PublicKey attributes.
+                XECPublicKey xdhPub = (XECPublicKey) kp.getPublic();
+                X509EncodedKeySpec xdhPubSpec
+                        = new X509EncodedKeySpec(xdhPub.getEncoded());
+                XECPublicKey xdhPubDec
+                        = (XECPublicKey) kf.generatePublic(xdhPubSpec);
+                equals(xdhPub.getU(), xdhPubDec.getU());
+                equals(xdhPub.getFormat(), xdhPubDec.getFormat());
+                equals(xdhPub.getEncoded(), xdhPubDec.getEncoded());
+                equals(((NamedParameterSpec) xdhPub.getParams()).getName(),
+                        ((NamedParameterSpec) xdhPubDec.getParams()).getName());
+                break;
+            default:
+                fail("Invalid Algo name " + kpgAlgo);
+        }
+    }
+
+    private static boolean equals(Object actual, Object expected) {
+        boolean equals = actual.equals(expected);
+        if (!equals) {
+            fail(String.format("Actual: %s, Expected: %s",
+                    actual, expected));
+        }
+        return equals;
+    }
+
+    private static boolean equals(byte[] actual, byte[] expected) {
+        boolean equals = Arrays.equals(actual, expected);
+        if (!equals) {
+            fail("Actual array does not equal Expected array");
+        }
+        return equals;
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/KeySpecTest.java b/ojluni/src/test/java/security/KeyAgreement/KeySpecTest.java
new file mode 100644
index 0000000..0ca3816
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/KeySpecTest.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8184359
+ * @summary Standard tests on KeySpec, KeyFactory, KeyPairs and Keys.
+ *  Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*>
+ * @run main KeySpecTest DiffieHellman SunJCE DiffieHellman
+ * @run main KeySpecTest ECDH SunEC EC
+ * @run main KeySpecTest XDH SunEC XDH X25519
+ * @run main KeySpecTest XDH SunEC XDH X448
+ */
+package test.java.security.KeyAgreement;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.ECPrivateKeySpec;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.XECPublicKeySpec;
+import java.security.spec.XECPrivateKeySpec;
+import java.security.spec.KeySpec;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Arrays;
+import javax.crypto.KeyAgreement;
+import javax.crypto.spec.DHPrivateKeySpec;
+import javax.crypto.spec.DHPublicKeySpec;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class KeySpecTest {
+
+    @Test
+    public void testDHKeySpecs() throws Exception {
+        KeyPair kp = genKeyPair("BC","DiffieHellman",
+                "DiffieHellman");
+        testKeySpecs("BC", "DiffieHellman", "DiffieHellman", kp);
+        testEncodedKeySpecs("BC", "DiffieHellman", "DiffieHellman", kp);
+    }
+
+    @Test
+    public void testECDHKeySpecs() throws Exception {
+        KeyPair kp = genKeyPair("AndroidOpenSSL","EC",
+                "EC");
+        testKeySpecs("AndroidOpenSSL", "ECDH", "EC", kp);
+        testEncodedKeySpecs("AndroidOpenSSL", "ECDH", "EC", kp);
+    }
+
+    // BEGIN Android-removed: XDH is not yet supported
+    /*
+    @Test
+    public void testXDHKeySpecs() throws Exception {
+        KeyPair kp1 = genKeyPair("AndroidOpenSSL","XDH",
+                "X25519");
+        KeyPair kp2 = genKeyPair("AndroidOpenSSL","XDH",
+                "X25519");
+        testKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp1);
+        testEncodedKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp1);
+        testKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp2);
+        testEncodedKeySpecs("AndroidOpenSSL", "XDH", "XDH", kp2);
+    }
+     */
+    // END Android-removed: XDH is not yet supported
+
+    /**
+     * Generate keyPair based on KeyPairGenerator algorithm.
+     */
+    private static KeyPair genKeyPair(String provider, String kpgAlgo,
+            String kpgInit) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+        switch (kpgInit) {
+            case "DiffieHellman":
+                kpg.initialize(512);
+                break;
+            case "EC":
+                kpg.initialize(256);
+                break;
+            case "X25519":
+                kpg.initialize(255);
+                break;
+            case "X448":
+                kpg.initialize(448);
+                break;
+            default:
+                fail("Invalid Algo name " + kpgInit);
+        }
+        return kpg.generateKeyPair();
+    }
+
+    /**
+     * Standard Test with Keys and the one generated through Spec.
+     */
+    private static void testKeySpecs(String provider, String kaAlgo,
+            String kpgAlgo, KeyPair kp) throws Exception {
+
+        KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+        // For each public KeySpec supported by KeyPairGenerator
+        for (Class pubSpecType
+                : getCompatibleKeySpecs(kpgAlgo, KeyType.PUBLIC)) {
+            //For each private KeySpec supported by KeyPairGenerator
+            for (Class priSpecType
+                    : getCompatibleKeySpecs(kpgAlgo, KeyType.PRIVATE)) {
+                // Transform original PublicKey through KeySpec
+                KeySpec pubSpec = kf.getKeySpec(kp.getPublic(), pubSpecType);
+                PublicKey pubKey = kf.generatePublic(pubSpec);
+                // Transform original PrivateKey through KeySpec
+                KeySpec priSpec = kf.getKeySpec(kp.getPrivate(), priSpecType);
+                PrivateKey priKey = kf.generatePrivate(priSpec);
+
+                // Test the keys are equal after transformation through KeySpec.
+                testKeyEquals(kp, pubKey, priKey);
+                // Test the keys are serializable.
+                testSerialize(kp);
+                // Test Parameter name.
+                if (!kaAlgo.equals("DiffieHellman")) {
+                    testParamName(priSpec, pubSpec);
+                }
+                // Compare KeyAgreement secret generated from original keys
+                // and by the keys after transformed through KeySpec.
+                if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo,
+                        kp.getPublic(), kp.getPrivate()),
+                        getKeyAgreementSecret(provider, kaAlgo,
+                                pubKey, priKey))) {
+                    fail("KeyAgreement secret mismatch.");
+                }
+            }
+        }
+    }
+
+    /**
+     * Standard Test with Keys and the one generated from encoded bytes.
+     */
+    private static void testEncodedKeySpecs(String provider, String kaAlgo,
+            String kpgAlgo, KeyPair kp) throws Exception {
+
+        KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+        PKCS8EncodedKeySpec priSpec
+                = new PKCS8EncodedKeySpec(kp.getPrivate().getEncoded());
+        PrivateKey priKey = kf.generatePrivate(priSpec);
+
+        X509EncodedKeySpec pubSpec
+                = new X509EncodedKeySpec(kp.getPublic().getEncoded());
+        PublicKey pubKey = kf.generatePublic(pubSpec);
+
+        // Test the keys are equal after transformation through KeySpec.
+        testKeyEquals(kp, pubKey, priKey);
+        // Test the keys are serializable.
+        testSerialize(kp);
+        // Test Parameter name.
+        if (!kaAlgo.equals("DiffieHellman")) {
+            testParamName(priSpec, pubSpec);
+        }
+        // Compare KeyAgreement secret generated from original keys
+        // and by the keys after transformed through KeySpec.
+        if (!Arrays.equals(getKeyAgreementSecret(provider, kaAlgo,
+                kp.getPublic(), kp.getPrivate()),
+                getKeyAgreementSecret(provider, kaAlgo, pubKey, priKey))) {
+            fail("KeyAgreement secret mismatch.");
+        }
+    }
+
+    private enum KeyType {
+        PUBLIC, PRIVATE;
+    }
+
+    /**
+     * Provides Compatible KeySpec Type list for KeyPairGenerator algorithm.
+     */
+    private static List<Class> getCompatibleKeySpecs(String kpgAlgo,
+            KeyType type) {
+
+        List<Class> specs = new ArrayList<>();
+        switch (kpgAlgo) {
+            case "DiffieHellman":
+                if (type == KeyType.PUBLIC) {
+                    return Arrays.asList(X509EncodedKeySpec.class,
+                            DHPublicKeySpec.class);
+                } else {
+                    return Arrays.asList(PKCS8EncodedKeySpec.class,
+                            DHPrivateKeySpec.class);
+                }
+            case "EC":
+                if (type == KeyType.PUBLIC) {
+                    return Arrays.asList(X509EncodedKeySpec.class,
+                            ECPublicKeySpec.class);
+                } else {
+                    return Arrays.asList(PKCS8EncodedKeySpec.class,
+                            ECPrivateKeySpec.class);
+                }
+            case "XDH":
+                if (type == KeyType.PUBLIC) {
+                    return Arrays.asList(X509EncodedKeySpec.class,
+                            XECPublicKeySpec.class);
+                } else {
+                    return Arrays.asList(PKCS8EncodedKeySpec.class,
+                            XECPrivateKeySpec.class);
+                }
+        }
+        return specs;
+    }
+
+    /**
+     * Generate KeyAgreement Secret.
+     */
+    private static byte[] getKeyAgreementSecret(String provider, String kaAlgo,
+            PublicKey pubKey, PrivateKey priKey) throws Exception {
+
+        KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);
+        ka.init(priKey);
+        ka.doPhase(pubKey, true);
+        return ka.generateSecret();
+    }
+
+    /**
+     * Compare original KeyPair with transformed ones.
+     */
+    private static void testKeyEquals(KeyPair kp, PublicKey pubKey,
+            PrivateKey priKey) {
+
+        if (!kp.getPrivate().equals(priKey)
+                && kp.getPrivate().hashCode() != priKey.hashCode()) {
+            fail("PrivateKey is not equal with PrivateKey"
+                    + " generated through KeySpec");
+        }
+        if (!kp.getPublic().equals(pubKey)
+                && kp.getPublic().hashCode() != pubKey.hashCode()) {
+            fail("PublicKey is not equal with PublicKey"
+                    + " generated through KeySpec");
+        }
+    }
+
+    /**
+     * Compare the parameter names of Public/Private KeySpec from a pair.
+     */
+    private static void testParamName(KeySpec priSpec, KeySpec pubSpec) {
+
+        if (priSpec instanceof XECPrivateKeySpec
+                && pubSpec instanceof XECPublicKeySpec) {
+            if (((NamedParameterSpec) ((XECPrivateKeySpec) priSpec)
+                    .getParams()).getName()
+                    != ((NamedParameterSpec) ((XECPublicKeySpec) pubSpec)
+                    .getParams()).getName()) {
+                fail("Curve name mismatch found");
+            }
+        }
+    }
+
+    /**
+     * Test serialization of KeyPair and Keys it holds.
+     */
+    private static void testSerialize(KeyPair keyPair) throws Exception {
+
+        // Verify Serialized PrivateKey instance.
+        if (!keyPair.getPrivate().equals(
+                deserializedCopy(keyPair.getPrivate(), PrivateKey.class))) {
+            fail("PrivateKey is not equal with PrivateKey"
+                    + " generated through Serialization");
+        }
+        // Verify Serialized PublicKey instance.
+        if (!keyPair.getPublic().equals(
+                deserializedCopy(keyPair.getPublic(), PublicKey.class))) {
+            fail("PublicKey is not equal with PublicKey"
+                    + " generated through Serialization");
+        }
+        // Verify Serialized KeyPair instance.
+        KeyPair copy = deserializedCopy(keyPair, KeyPair.class);
+        if (!keyPair.getPrivate().equals(copy.getPrivate())) {
+            fail("PrivateKey is not equal with PrivateKey"
+                    + " generated through Serialized KeyPair");
+        }
+        if (!keyPair.getPublic().equals(copy.getPublic())) {
+            fail("PublicKey is not equal with PublicKey"
+                    + " generated through Serialized KeyPair");
+        }
+    }
+
+    private static <T extends Object> T deserializedCopy(T orig, Class<T> type)
+            throws IOException, ClassNotFoundException {
+        return deserialize(serialize(orig), type);
+    }
+
+    /**
+     * Deserialize the Key object.
+     */
+    private static <T extends Object> T deserialize(byte[] serialized,
+            Class<T> type) throws IOException, ClassNotFoundException {
+
+        T key = null;
+        try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized);
+             ObjectInputStream ois = new ObjectInputStream(bis)) {
+            key = (T) ois.readObject();
+        }
+        return key;
+    }
+
+    /**
+     * Serialize the given Key object.
+     */
+    private static <T extends Object> byte[] serialize(T key)
+            throws IOException {
+
+        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+             ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+            oos.writeObject(key);
+            return bos.toByteArray();
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/MultiThreadTest.java b/ojluni/src/test/java/security/KeyAgreement/MultiThreadTest.java
new file mode 100644
index 0000000..b773320
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/MultiThreadTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8184359
+ * @summary KeyPairGenerator Test with multiple threads.
+ *  Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm> <Curve*>
+ * @run main MultiThreadTest DiffieHellman SunJCE DiffieHellman
+ * @run main MultiThreadTest ECDH SunEC EC
+ * @run main MultiThreadTest XDH SunEC XDH X25519
+ * @run main MultiThreadTest XDH SunEC XDH X448
+ */
+package test.java.security.KeyAgreement;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import javax.crypto.KeyAgreement;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+/**
+ * This test targets KeyPairGenerator API related issue in a multi threaded
+ * context.
+ */
+public class MultiThreadTest {
+
+    // Tested a shared KeyPairGenerator with 100 number of threads.
+    private static final int THREAD_COUNT = 100;
+
+    @Test
+    public void testDHKeySpecs() throws Exception {
+        KeyPairGenerator kpg = genKeyGenerator("BC","DiffieHellman",
+                "DiffieHellman");
+        new MultiThreadTest().runTest("BC", "DiffieHellman", kpg);
+    }
+
+    @Test
+    public void testECDHKeySpecs() throws Exception {
+        KeyPairGenerator kpg = genKeyGenerator("AndroidOpenSSL","EC",
+                "EC");
+        new MultiThreadTest().runTest("AndroidOpenSSL", "ECDH", kpg);
+    }
+
+
+    // BEGIN Android-removed: XDH is not yet supported
+    /*
+    @Test
+    public void testXDHKeySpecs() throws Exception {
+        KeyPairGenerator kpg1 = genKeyGenerator("AndroidOpenSSL","XDH",
+                "X25519");
+        new MultiThreadTest().runTest("AndroidOpenSSL", "XDH", kpg1);
+        KeyPairGenerator kpg2 = genKeyGenerator("AndroidOpenSSL","XDH",
+                "X25519");
+        new MultiThreadTest().runTest("AndroidOpenSSL", "XDH", kpg2);
+    }
+     */
+    // END Android-removed: XDH is not yet supported
+
+    /**
+     * Initialize KeyPairGenerator based on different algorithm names.
+     */
+    private static KeyPairGenerator genKeyGenerator(String provider,
+            String kpgAlgo, String kpgInit) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+        switch (kpgInit) {
+            case "DiffieHellman":
+                kpg.initialize(512);
+                break;
+            case "EC":
+                kpg.initialize(256);
+                break;
+            case "X25519":
+                kpg.initialize(255);
+                break;
+            case "X448":
+                kpg.initialize(448);
+                break;
+            default:
+                fail("Invalid Algo name " + kpgInit);
+        }
+        return kpg;
+    }
+
+    private void runTest(String provider, String kaAlgo, KeyPairGenerator kpg)
+            throws Exception {
+
+        ExecutorService executor = null;
+        try {
+            executor = Executors.newCachedThreadPool(new ThreadFactory() {
+                @Override
+                public Thread newThread(Runnable r) {
+                    Thread t = Executors.defaultThreadFactory().newThread(r);
+                    t.setDaemon(true);
+                    return t;
+                }
+            });
+            CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
+
+            for (int i = 0; i < THREAD_COUNT; i++) {
+                executor.execute(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            testKeyAgreement(provider, kaAlgo, kpg);
+                        } catch (Exception e) {
+                            throw new RuntimeException(e);
+                        } finally {
+                            // Indicate a task completed.
+                            latch.countDown();
+                        }
+                    }
+                });
+            }
+            // Wait till all tasks get complete.
+            latch.await();
+        } finally {
+            if (executor != null) {
+                executor.shutdown();
+            }
+        }
+    }
+
+    /**
+     * Perform KeyAgreement operation with a shared KeyPairGenerator instance.
+     */
+    private static void testKeyAgreement(String provider, String kaAlgo,
+            KeyPairGenerator kpg) throws Exception {
+
+        KeyPair kp1 = kpg.generateKeyPair();
+        KeyPair kp2 = kpg.generateKeyPair();
+
+        KeyAgreement ka1 = KeyAgreement.getInstance(kaAlgo, provider);
+        ka1.init(kp1.getPrivate());
+        ka1.doPhase(kp2.getPublic(), true);
+        byte[] secret1 = ka1.generateSecret();
+        KeyAgreement ka2 = KeyAgreement.getInstance(kaAlgo, provider);
+        ka2.init(kp2.getPrivate());
+        ka2.doPhase(kp1.getPublic(), true);
+        byte[] secret2 = ka2.generateSecret();
+
+        // With related keypairs, generated KeyAgreement secret should be same.
+        if (!Arrays.equals(secret1, secret2)) {
+            fail("KeyAgreement secret mismatch.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyAgreement/NegativeTest.java b/ojluni/src/test/java/security/KeyAgreement/NegativeTest.java
new file mode 100644
index 0000000..5f97d1c
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyAgreement/NegativeTest.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8200219
+ * @summary Negative tests for Key related Test with DiffieHellman, ECDH, XDH.
+ *          It Tests,
+ *          Use modified encoding while generating Public/Private Keys
+ *          Short, long, unsupported keysize
+ *          Invalid Algo names including Null
+ *          Invalid provider names including Null
+ *          Invalid curve names
+ *          Invalid spec usage
+ *  Arguments order <KeyExchangeAlgorithm> <Provider> <KeyGenAlgorithm>
+ *                  <keySize> <Curve*>
+ * @library /test/lib
+ * @run main NegativeTest DiffieHellman SunJCE DiffieHellman 1024
+ * @run main NegativeTest ECDH SunEC EC 256
+ * @run main NegativeTest XDH SunEC XDH 255 X25519
+ * @run main NegativeTest XDH SunEC XDH 448 X448
+ */
+package test.java.security.KeyAgreement;
+
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidParameterException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Security;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.NamedParameterSpec;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.security.spec.XECPrivateKeySpec;
+import java.security.spec.XECPublicKeySpec;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.crypto.KeyAgreement;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class NegativeTest {
+
+    @Test
+    public void testDHNegative() throws Exception {
+        String kaAlgo = "DiffieHellman";
+        String provider = "BC";
+        String kpgAlgo = "DiffieHellman";
+        int keySize = 1024;
+        String kpgInit = "DiffieHellman";
+        testModifiedKeyEncodingTest(provider, kpgAlgo, kpgInit);
+        testInvalidKeyLen(provider, kaAlgo, kpgAlgo, kpgInit);
+        testInvalidKpgAlgo(provider, kaAlgo, keySize);
+        testInvalidKaAlgo(provider, kpgAlgo, keySize);
+        testInvalidProvider(kaAlgo, kpgAlgo, keySize);
+    }
+
+    @Test
+    public void testECDHNegative() throws Exception {
+        String kaAlgo = "ECDH";
+        String provider = "AndroidOpenSSL";
+        String kpgAlgo = "EC";
+        int keySize = 256;
+        String kpgInit = "EC";
+        testModifiedKeyEncodingTest(provider, kpgAlgo, kpgInit);
+        testInvalidKeyLen(provider, kaAlgo, kpgAlgo, kpgInit);
+        testInvalidKpgAlgo(provider, kaAlgo, keySize);
+        testInvalidKaAlgo(provider, kpgAlgo, keySize);
+        testInvalidProvider(kaAlgo, kpgAlgo, keySize);
+        testNamedParameter(provider, kpgAlgo);
+    }
+
+    // BEGIN Android-removed: XDH is not yet supported
+    /*
+    @Test
+    public void testXDHNegative() throws Exception {
+        String kaAlgo = "XDH";
+        String provider = "AndroidOpenSSL";
+        String kpgAlgo = "XDH";
+        List<Integer> keySizes = Arrays.asList(256, 448);
+        List<String> kpgInits = Arrays.asList("X25519", "X448");
+        for (int i = 0; i < keySizes.size(); i++){
+            testModifiedKeyEncodingTest(provider, kpgAlgo, kpgInits.get(i));
+            testInvalidKeyLen(provider, kaAlgo, kpgAlgo, kpgInits.get(i));
+            testInvalidKpgAlgo(provider, kaAlgo, keySizes.get(i));
+            testInvalidKaAlgo(provider, kpgAlgo, keySizes.get(i));
+            testInvalidProvider(kaAlgo, kpgAlgo, keySizes.get(i));
+            testInvalidSpec(provider, kpgAlgo, kpgInits.get(i));
+            testInCompatibleSpec(provider, kpgAlgo, kpgInits.get(i));
+        }
+        testNamedParameter(provider, kpgAlgo);
+    }
+     */
+    // END Android-removed: XDH is not yet supported
+
+    /**
+     * Generate keyPair based on KeyPairGenerator algorithm.
+     */
+    private static KeyPair genKeyPair(String provider, String kpgAlgo,
+            String kpgInit) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo,
+                Security.getProvider(provider));
+        switch (kpgInit) {
+            case "DiffieHellman":
+                kpg.initialize(512);
+                break;
+            case "EC":
+                kpg.initialize(256);
+                break;
+            case "X25519":
+                kpg.initialize(255);
+                break;
+            case "X448":
+                kpg.initialize(448);
+                break;
+            default:
+                fail("Invalid Algo name " + kpgInit);
+        }
+        return kpg.generateKeyPair();
+    }
+
+    private static void testModifiedKeyEncodingTest(String provider,
+            String kpgAlgo, String kpgInit) throws Exception {
+
+        KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+        KeyPair kp = genKeyPair(provider, kpgAlgo, kpgInit);
+        // Test modified PrivateKey encoding
+        byte[] encoded = kp.getPrivate().getEncoded();
+        byte[] modified = modifyEncoded(encoded);
+        PKCS8EncodedKeySpec priSpec = new PKCS8EncodedKeySpec(modified);
+        try {
+            // Generate PrivateKey with modified encoding
+            kf.generatePrivate(priSpec);
+            fail("testModifiedKeyTest should fail but passed.");
+        } catch (InvalidKeySpecException e) {
+        }
+        // Test modified PublicKey encoding
+        encoded = kp.getPublic().getEncoded();
+        modified = modifyEncoded(encoded);
+        X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(modified);
+        try {
+            // Generate PublicKey with modified encoding
+            kf.generatePublic(pubSpec);
+            fail("testModifiedKeyTest should fail but passed.");
+        } catch (InvalidKeySpecException e) {
+        }
+    }
+
+    /**
+     * Test with all Invalid key length.
+     */
+    private static void testInvalidKeyLen(String provider, String kaAlgo,
+            String kpgAlgo, String kpgInit) throws Exception {
+
+        for (int keySize : selectInvalidKeylength(kpgInit)) {
+            try {
+                startKeyAgreement(provider, kaAlgo, kpgAlgo, keySize);
+                fail("testInvalidKeyLen should fail but passed: " + kaAlgo + ", " + Integer.toString(keySize));
+            } catch (InvalidParameterException e) {
+            } catch (IllegalArgumentException e) {
+            }
+        }
+    }
+
+    /**
+     * Test with all Invalid KeyPairGenerator algorithms.
+     */
+    private static void testInvalidKpgAlgo(String provider, String algo,
+            int keySize) throws Exception {
+
+        for (String kpgAlgo : new String[]{null, " ", "", "NoSuchAlgorithm"}) {
+            try {
+                startKeyAgreement(provider, algo, kpgAlgo, keySize);
+                fail("testInvalidKpgAlgo should fail but passed.");
+            } catch (NoSuchAlgorithmException e) {
+            } catch (NullPointerException e) {
+                if (kpgAlgo == null) {
+                    continue;
+                }
+                fail("Unknown failure in testInvalidKpgAlgo.");
+            }
+        }
+    }
+
+    /**
+     * Test with all Invalid KeyAgreement algorithms.
+     */
+    private static void testInvalidKaAlgo(String provider, String kpgAlgo,
+            int keySize) throws Exception {
+
+        for (String algo : new String[]{null, " ", "", "NoSuchAlgorithm"}) {
+            try {
+                startKeyAgreement(provider, algo, kpgAlgo, keySize);
+                fail("testInvalidKaAlgo should fail but passed.");
+            } catch (NoSuchAlgorithmException e) {
+            } catch (NullPointerException e) {
+                if (algo == null) {
+                    continue;
+                }
+                fail("Unknown failure in testInvalidKaAlgo.");
+            }
+        }
+    }
+
+    /**
+     * Test with all Invalid Provider names.
+     */
+    private static void testInvalidProvider(String kaAlgo, String kpgAlgo,
+            int keySize) throws Exception {
+
+        for (String provider : new String[]{null, " ", "", "NoSuchProvider"}) {
+            try {
+                startKeyAgreement(provider, kaAlgo, kpgAlgo, keySize);
+                fail("testInvalidProvider should fail but passed.");
+            } catch (NoSuchProviderException e) {
+            } catch (IllegalArgumentException e) {
+            }
+        }
+    }
+
+    /**
+     * Test for (in)valid curve names as argument to NamedParameterSpec
+     */
+    private static void testNamedParameter(String provider, String kpgAlgo)
+            throws Exception {
+
+        for (String name : new String[]{null, " ", "", "NoSuchCurve"}) {
+            try {
+                NamedParameterSpec spec = new NamedParameterSpec(name);
+                KeyPairGenerator kpg
+                        = KeyPairGenerator.getInstance(kpgAlgo, provider);
+                kpg.initialize(spec);
+                kpg.generateKeyPair();
+                fail("testNamedParameter should fail but passed.");
+            } catch (NullPointerException e) {
+                if (name == null) {
+                    continue;
+                }
+                fail("Unknown failure in testNamedParameter.");
+            } catch (InvalidAlgorithmParameterException e) {
+            }
+        }
+    }
+
+    /**
+     * Test to generate Public/Private keys using (in)valid coordinate/scalar.
+     */
+    private static void testInvalidSpec(String provider,
+            String kpgAlgo, String curve) throws Exception {
+
+        NamedParameterSpec spec = new NamedParameterSpec(curve);
+        KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+        int validLen = curve.equalsIgnoreCase("X448") ? 56 : 32;
+        for (byte[] scalarBytes : new byte[][]{null, new byte[]{},
+                new byte[32], new byte[56], new byte[65535]}) {
+            try {
+                KeySpec privateSpec = new XECPrivateKeySpec(spec, scalarBytes);
+                kf.generatePrivate(privateSpec);
+                if (scalarBytes.length != validLen) {
+                    fail(String.format("testInvalidSpec "
+                            + "should fail but passed when Scalar bytes length "
+                            + "!= %s for curve %s", validLen, curve));
+                }
+            } catch (NullPointerException e) {
+                if (scalarBytes == null) {
+                    continue;
+                }
+                fail(e.getMessage());
+            } catch (InvalidKeySpecException e) {
+                if (scalarBytes.length != validLen) {
+                    continue;
+                }
+                fail(e.getMessage());
+            }
+        }
+        for (BigInteger coordinate : new BigInteger[]{null, BigInteger.ZERO,
+                BigInteger.ONE, new BigInteger("2").pow(255),
+                new BigInteger("2").pow(448)}) {
+            try {
+                KeySpec publicSpec = new XECPublicKeySpec(spec, coordinate);
+                kf.generatePublic(publicSpec);
+            } catch (NullPointerException e) {
+                if (coordinate == null) {
+                    continue;
+                }
+                fail(e.getMessage());
+            }
+        }
+    }
+
+    private static void testInCompatibleSpec(String provider,
+            String kpgAlgo, String curve) throws Exception {
+
+        int validLen = curve.equalsIgnoreCase("X448") ? 56 : 32;
+        NamedParameterSpec spec = new NamedParameterSpec(curve);
+        KeyFactory kf = KeyFactory.getInstance(kpgAlgo, provider);
+        KeySpec privateSpec = new XECPrivateKeySpec(spec, new byte[validLen]);
+        KeySpec publicSpec = new XECPublicKeySpec(spec, BigInteger.ONE);
+        try {
+            kf.generatePrivate(publicSpec);
+            fail("testInCompatibleSpec should fail but passed.");
+        } catch (InvalidKeySpecException e) {
+        }
+        try {
+            kf.generatePublic(privateSpec);
+            fail("testInCompatibleSpec should fail but passed.");
+        } catch (InvalidKeySpecException e) {
+        }
+    }
+
+    /**
+     * Perform KeyAgreement operation.
+     */
+    private static void startKeyAgreement(String provider, String kaAlgo,
+            String kpgAlgo, int keySize) throws Exception {
+
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance(kpgAlgo, provider);
+        kpg.initialize(keySize);
+        KeyPair kp = kpg.generateKeyPair();
+        KeyAgreement ka = KeyAgreement.getInstance(kaAlgo, provider);
+        ka.init(kp.getPrivate());
+        ka.doPhase(kp.getPublic(), true);
+        ka.generateSecret();
+    }
+
+    /**
+     * Return manipulated encoded bytes.
+     */
+    private static byte[] modifyEncoded(byte[] encoded) {
+
+        byte[] copy = Arrays.copyOf(encoded, encoded.length);
+        for (int i = 0; i < copy.length; i++) {
+            copy[i] = (byte) ~copy[i];
+        }
+        return copy;
+    }
+
+    /**
+     * Select invalid key sizes for different Key generation algorithms.
+     */
+    private static int[] selectInvalidKeylength(String kpgInit) {
+
+        int[] keySize = new int[]{};
+        switch (kpgInit) {
+            case "DiffieHellman":
+                keySize = new int[]{100};
+                break;
+            case "EC":
+            case "X25519":
+                keySize = new int[]{100, 300};
+                break;
+            case "X448":
+                keySize = new int[]{100, 500};
+                break;
+            default:
+                fail("Invalid Algo name " + kpgInit);
+        }
+        return keySize;
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyStore/DefaultEntryType.java b/ojluni/src/test/java/security/KeyStore/DefaultEntryType.java
new file mode 100644
index 0000000..4bad488
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyStore/DefaultEntryType.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test 1.1, 03/06/24
+ * @bug 4850376
+ * @summary Provide generic storage KeyStore storage facilities
+ */
+package test.java.security.KeyStore;
+
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Principal;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Set;
+import java.util.HashSet;
+import java.math.BigInteger;
+import javax.security.auth.x500.X500Principal;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class DefaultEntryType {
+
+    private static class PrivKey1 implements PrivateKey {
+        public String getAlgorithm() { return ("matching_alg"); }
+        public String getFormat() { return "privkey1"; }
+        public byte[] getEncoded() { return (byte[])null; }
+    }
+
+    private static class PubKey1 implements PublicKey {
+        public String getAlgorithm() { return ("non_matching_alg"); }
+        public String getFormat() { return "pubkey1"; }
+        public byte[] getEncoded() { return (byte[])null; }
+    }
+
+    private static class PubKey2 implements PublicKey {
+        public String getAlgorithm() { return ("matching_alg"); }
+        public String getFormat() { return "pubkey2"; }
+        public byte[] getEncoded() { return (byte[])null; }
+    }
+
+    private static class Cert extends Certificate {
+        public Cert() { super("cert"); }
+        public byte[] getEncoded()
+                throws CertificateEncodingException { return (byte[])null; }
+        public void verify(PublicKey key)
+                throws CertificateException, NoSuchAlgorithmException,
+                InvalidKeyException, NoSuchProviderException,
+                SignatureException { }
+        public void verify(PublicKey key, String sigProvider)
+                throws CertificateException, NoSuchAlgorithmException,
+                InvalidKeyException, NoSuchProviderException,
+                SignatureException { }
+        public String toString() { return "cert"; }
+        public PublicKey getPublicKey() { return new PubKey1(); }
+    }
+
+    private static class X509Cert extends X509Certificate {
+        public byte[] getEncoded()
+                throws CertificateEncodingException { return (byte[])null; }
+        public void verify(PublicKey key)
+                throws CertificateException, NoSuchAlgorithmException,
+                InvalidKeyException, NoSuchProviderException,
+                SignatureException { }
+        public void verify(PublicKey key, String sigProvider)
+                throws CertificateException, NoSuchAlgorithmException,
+                InvalidKeyException, NoSuchProviderException,
+                SignatureException { }
+        public String toString() { return "x509cert"; }
+        public PublicKey getPublicKey() { return new PubKey2(); }
+
+        public void checkValidity()
+                throws CertificateExpiredException,
+                CertificateNotYetValidException { }
+        public void checkValidity(java.util.Date date)
+                throws CertificateExpiredException,
+                CertificateNotYetValidException { }
+        public int getVersion() { return 1; }
+        public BigInteger getSerialNumber() { return new BigInteger("5", 10); }
+        public Principal getIssuerDN()
+        { return new X500Principal("cn=x509cert"); }
+        public X500Principal getIssuerX500Principal()
+        { return new X500Principal("cn=x509cert"); }
+        public Principal getSubjectDN()
+        { return new X500Principal("cn=x509cert"); }
+        public X500Principal getSubjectX500Principal()
+        { return new X500Principal("cn=x509cert"); }
+        public Date getNotBefore() { return new Date(); }
+        public Date getNotAfter() { return new Date(); }
+        public byte[] getTBSCertificate() throws CertificateEncodingException
+        { return (byte[])null; }
+        public byte[] getSignature() { return (byte[])null; }
+        public String getSigAlgName() { return "x509cert"; }
+        public String getSigAlgOID() { return "x509cert"; }
+        public byte[] getSigAlgParams() { return (byte[])null; }
+
+        public boolean[] getIssuerUniqueID() { return (boolean[])null; }
+        public boolean[] getSubjectUniqueID() { return (boolean[])null; }
+        public boolean[] getKeyUsage() { return (boolean[]) null; }
+        public int getBasicConstraints() { return 1; }
+
+        public boolean hasUnsupportedCriticalExtension() { return true; }
+        public Set getCriticalExtensionOIDs() { return new HashSet(); }
+        public Set getNonCriticalExtensionOIDs() { return new HashSet(); }
+        public byte[] getExtensionValue(String oid) { return (byte[])null; }
+    }
+
+    @Test
+    public void testPrivateKeyEntry() throws Exception {
+        // TEST null private key
+        try {
+            Certificate[] chain = new Certificate[0];
+            KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
+                    (null, chain);
+            fail("test 1 failed");
+        } catch (NullPointerException npe) {
+        }
+
+        // TEST null chain
+        try {
+            KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
+                    (new PrivKey1(), null);
+            fail("test 2 failed");
+        } catch (NullPointerException npe) {
+        }
+
+        // TEST empty chain
+        try {
+            Certificate[] chain = new Certificate[0];
+            KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
+                    (new PrivKey1(), chain);
+            fail("test 3 failed");
+        } catch (IllegalArgumentException npe) {
+        }
+
+        // TEST non-homogenous chain
+        try {
+            Certificate[] chain = new Certificate[2];
+            chain[0] = new Cert();
+            chain[1] = new X509Cert();
+            KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
+                    (new PrivKey1(), chain);
+            fail("test 4 failed");
+        } catch (IllegalArgumentException npe) {
+        }
+
+        // TEST non matching algorithms
+        try {
+            Certificate[] chain = new Certificate[1];
+            chain[0] = new Cert();
+            KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
+                    (new PrivKey1(), chain);
+            fail("test 5 failed");
+        } catch (IllegalArgumentException npe) {
+        }
+
+        // TEST correct behavior
+        Certificate[] chain = new Certificate[2];
+        chain[0] = new X509Cert();
+        chain[1] = new X509Cert();
+        PrivateKey pkey = new PrivKey1();
+        KeyStore.PrivateKeyEntry pke = new KeyStore.PrivateKeyEntry
+                (pkey, chain);
+        Certificate[] gotChain = pke.getCertificateChain();
+        if (gotChain instanceof X509Certificate[]) {
+        } else {
+            fail("test 6 failed");
+        }
+
+        if (gotChain.length == 2 &&
+                gotChain[0] == chain[0] &&
+                gotChain[1] == chain[1]) {
+        } else {
+            fail("test 7 failed");
+        }
+
+        if (pke.getPrivateKey() == pkey) {
+        } else {
+            fail("test 8 failed");
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyStore/KeyStoreBuilder.java b/ojluni/src/test/java/security/KeyStore/KeyStoreBuilder.java
new file mode 100644
index 0000000..0e76252
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyStore/KeyStoreBuilder.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4938922 4961104 5071293 6236533 8130181
+ * @summary verify that the KeyStore.Builder API works
+ * @author Andreas Sterbenz
+ */
+package test.java.security.KeyStore;
+
+import java.io.*;
+import java.net.URL;
+import java.util.*;
+
+import java.security.*;
+import java.security.KeyStore.*;
+import java.security.cert.*;
+import java.security.cert.Certificate;
+
+import javax.security.auth.callback.*;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class KeyStoreBuilder {
+
+    private static final char[] password = "passphrase".toCharArray();
+
+    private static final char[] wrongPassword = "wrong".toCharArray();
+
+    @Test
+    public void testBuilder() throws Exception {
+        Builder builder;
+        int k;
+        KeyStore ks;
+
+        builder = Builder.newInstance("PKCS12", null, new PasswordProtection(password));
+        ks = builder.getKeyStore();
+        k = ks.size();
+        if (k != 0) {
+            throw new Exception("Size not zero: " + k);
+        }
+
+        builder = Builder.newInstance("BouncyCastle", null, new PasswordProtection(password));
+        ks = builder.getKeyStore();
+        k = ks.size();
+        if (k != 0) {
+            throw new Exception("Size not zero: " + k);
+        }
+
+        Provider p = new MyProvider();
+
+        DummyHandler handler = new DummyHandler();
+
+        handler.useWrongPassword = 2;
+        builder = Builder.newInstance("My", p, new CallbackHandlerProtection(handler));
+        ks = builder.getKeyStore();
+        k = ks.size();
+        if (k != 0) {
+            throw new Exception("Size not zero: " + k);
+        }
+
+        handler.useWrongPassword = 3;
+        builder = Builder.newInstance("My", p, new CallbackHandlerProtection(handler));
+        try {
+            ks = builder.getKeyStore();
+            throw new Exception("should not succeed");
+        } catch (KeyStoreException e) {
+        }
+        try {
+            ks = builder.getKeyStore();
+            throw new Exception("should not succeed");
+        } catch (KeyStoreException e) {
+        }
+    }
+
+    private static class DummyHandler implements CallbackHandler {
+
+        int useWrongPassword;
+
+        public void handle(Callback[] callbacks)
+                throws IOException, UnsupportedCallbackException {
+            for (int i = 0; i < callbacks.length; i++) {
+                Callback cb = callbacks[i];
+                if (cb instanceof PasswordCallback) {
+                    PasswordCallback pcb = (PasswordCallback)cb;
+                    if (useWrongPassword == 0) {
+                        pcb.setPassword(password);
+                    } else {
+                        pcb.setPassword(wrongPassword);
+                        useWrongPassword--;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    private static class BaseKeyStoreSpi extends KeyStoreSpi {
+        public Key engineGetKey(String alias, char[] password) {
+            return null;
+        }
+        public Certificate[] engineGetCertificateChain(String alias) {
+            return null;
+        }
+        public Certificate engineGetCertificate(String alias) {
+            return null;
+        }
+        public Date engineGetCreationDate(String alias) {
+            return null;
+        }
+        public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] certs) {
+            //
+        }
+        public void engineSetKeyEntry(String alias, byte[] key, Certificate[] certs) {
+            //
+        }
+        public void engineSetCertificateEntry(String alias, Certificate cert) {
+            //
+        }
+        public void engineDeleteEntry(String alias) {
+            //
+        }
+        public Enumeration<String> engineAliases() {
+            return new Vector<String>().elements();
+        }
+        public boolean engineContainsAlias(String alias) {
+            return false;
+        }
+        public int engineSize() {
+            return 0;
+        }
+        public boolean engineIsKeyEntry(String alias) {
+            return false;
+        }
+        public boolean engineIsCertificateEntry(String alias) {
+            return false;
+        }
+        public String engineGetCertificateAlias(Certificate cert) {
+            return null;
+        }
+        public void engineStore(OutputStream stream, char[] password) {
+            //
+        }
+        public void engineLoad(InputStream stream, char[] password) throws IOException {
+            //
+        }
+    }
+
+    public static class MyKeyStoreSpi extends BaseKeyStoreSpi {
+        public void engineLoad(InputStream stream, char[] pw) throws IOException {
+            if (Arrays.equals(password, pw) == false) {
+                Throwable t = new UnrecoverableKeyException("Wrong password: " + new String(pw));
+                throw (IOException)new IOException("load() failed").initCause(t);
+            }
+        }
+    }
+
+    private static class MyProvider extends Provider {
+        MyProvider() {
+            super("MyProvider", 1, null);
+            put("KeyStore.My", MyKeyStoreSpi.class.getName());
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyStore/ProbeKeystores.java b/ojluni/src/test/java/security/KeyStore/ProbeKeystores.java
new file mode 100644
index 0000000..6e7efca
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyStore/ProbeKeystores.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8044445 8194307 8207318
+ * @summary test new methods from JEP-229: Create PKCS12 Keystores by Default
+ */
+package test.java.security.KeyStore;
+
+import java.io.*;
+import java.security.*;
+import java.security.KeyStore.*;
+import java.security.cert.*;
+import javax.crypto.*;
+import javax.security.auth.callback.*;
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+public class ProbeKeystores {
+    // BEGIN Android-changed: adjusted tests to account for multiple implementation details.
+
+    private static final char[] PASSWORD = "changeit".toCharArray();
+    private static final char[] BAD_PASSWORD = "badpasword".toCharArray();
+    private static final LoadStoreParameter LOAD_STORE_PARAM =
+            new MyLoadStoreParameter(new PasswordProtection(PASSWORD));
+
+    private static class MyLoadStoreParameter implements LoadStoreParameter {
+
+        private ProtectionParameter protection;
+
+        MyLoadStoreParameter(ProtectionParameter protection) {
+            this.protection = protection;
+        }
+
+        public ProtectionParameter getProtectionParameter() {
+            return protection;
+        }
+    }
+
+    @Test
+    public void testKeystores() throws Exception {
+        File bcFile = File.createTempFile("empty", "bc");
+        File p12File = File.createTempFile("empty", "p12");
+
+        // Testing empty keystores
+
+        init(bcFile, "BouncyCastle");
+        init(p12File, "PKCS12");
+
+
+        load(bcFile, "BouncyCastle");
+        load(p12File, "PKCS12");
+        loadNonCompat(bcFile, "PKCS12"); // test compatibility mode
+        loadNonCompat(p12File, "BouncyCastle"); // test compatibility mode
+
+        probe(bcFile, "BOUNCYCASTLE");
+        probeFails(p12File);
+
+        build(bcFile, "BOUNCYCASTLE", true);
+        build(bcFile, "BOUNCYCASTLE", false);
+        // engineProbe does not work for PKCS12
+
+        // PKCS12 does not support keys
+        File onekeyBcFile = File.createTempFile("onekey", "bc");
+        SecretKey key = generateSecretKey("AES", 128);
+        init(onekeyBcFile, "BouncyCastle", key);
+
+        load(onekeyBcFile, "BouncyCastle");
+
+        probe(onekeyBcFile, "BOUNCYCASTLE");
+
+        build(onekeyBcFile, "BOUNCYCASTLE", true);
+        build(onekeyBcFile, "BOUNCYCASTLE", false);
+    }
+
+    // Instantiate an empty keystore using the supplied keystore type
+    private static void init(File file, String type) throws Exception {
+        KeyStore ks = KeyStore.getInstance(type);
+        ks.load(null, null);
+        try (OutputStream stream = new FileOutputStream(file)) {
+            ks.store(stream, PASSWORD);
+        }
+    }
+
+    // Instantiate a keystore using the supplied keystore type & create an entry
+    private static void init(File file, String type, SecretKey key)
+            throws Exception {
+        KeyStore ks = KeyStore.getInstance(type);
+        ks.load(null, null);
+        ks.setEntry("mykey", new KeyStore.SecretKeyEntry(key),
+                new PasswordProtection(PASSWORD));
+        try (OutputStream stream = new FileOutputStream(file)) {
+            ks.store(stream, PASSWORD);
+        }
+    }
+
+    // Instantiate a keystore by probing the supplied file for the keystore type
+    private static void probe(File file, String type) throws Exception {
+        KeyStore ks;
+        // First try with the correct password
+        ks = KeyStore.getInstance(file, PASSWORD);
+        if (!type.equalsIgnoreCase(ks.getType())) {
+            throw new Exception("ERROR: expected a " + type + " keystore, " +
+                    "got a " + ks.getType() + " keystore instead");
+        }
+
+        // Next try with an incorrect password
+        try {
+            ks = KeyStore.getInstance(file, BAD_PASSWORD);
+            fail("ERROR: expected an exception but got success");
+        } catch (IOException e) {
+            // Expected
+        }
+
+        // Next try with a password within a LoadStoreParameter (still unsupported)
+        try {
+            ks = KeyStore.getInstance(file, LOAD_STORE_PARAM);
+            fail("ERROR: expected an exception but got success");
+        } catch (UnsupportedOperationException e) {
+            // Expected
+        }
+    }
+    // Instantiate a keystore by probing the supplied file for the keystore type
+    private static void probeFails(File file) throws Exception {
+        KeyStore ks;
+        // Next try with an incorrect password
+        try {
+            ks = KeyStore.getInstance(file, PASSWORD);
+            fail("ERROR: expected an exception but got success");
+        } catch (KeyStoreException e) {
+            // Expected
+        }
+    }
+
+    // Instantiate a keystore by probing the supplied file for the keystore type
+    private static void build(File file, String type, boolean usePassword) throws Exception {
+        Builder builder;
+        if (usePassword) {
+            builder = Builder.newInstance(file,
+                    new PasswordProtection(PASSWORD));
+        } else {
+            builder = Builder.newInstance(file,
+                    new CallbackHandlerProtection(new DummyHandler()));
+        }
+        KeyStore ks = builder.getKeyStore();
+        if (!type.equalsIgnoreCase(ks.getType())) {
+            throw new Exception("ERROR: expected a " + type + " keystore, " +
+                    "got a " + ks.getType() + " keystore instead");
+        }
+    }
+
+    // Load the keystore entries
+    private static void load(File file, String type) throws Exception {
+        Security.setProperty("keystore.type.compat", "true");
+        KeyStore ks = KeyStore.getInstance(type);
+        try (InputStream stream = new FileInputStream(file)) {
+            ks.load(stream, PASSWORD);
+        }
+    }
+
+    // Load the keystore entries (with compatibility mode disabled)
+    private static void loadNonCompat(File file, String type)
+            throws Exception {
+        try {
+            load(file, type);
+            fail("ERROR: expected load to fail but it didn't");
+        } catch (IOException e) {
+            // Expected
+        }
+    }
+
+    // END Android-changed:  adjusted tests to account for multiple implementation details.
+
+    // Generate a secret key using the supplied algorithm name and key size
+    private static SecretKey generateSecretKey(String algorithm, int size)
+            throws NoSuchAlgorithmException {
+        KeyGenerator generator = KeyGenerator.getInstance(algorithm);
+        generator.init(size);
+        return generator.generateKey();
+    }
+
+    private static class DummyHandler implements CallbackHandler {
+        public void handle(Callback[] callbacks)
+                throws IOException, UnsupportedCallbackException {
+            for (int i = 0; i < callbacks.length; i++) {
+                Callback cb = callbacks[i];
+                if (cb instanceof PasswordCallback) {
+                    PasswordCallback pcb = (PasswordCallback)cb;
+                    pcb.setPassword(PASSWORD);
+                    break;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyStore/TestKeystoreBasic.java b/ojluni/src/test/java/security/KeyStore/TestKeystoreBasic.java
new file mode 100644
index 0000000..ee9704f
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyStore/TestKeystoreBasic.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.security.KeyStore;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.Base64;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+/*
+ * @test
+ * @bug 8048621 8133090 8167371
+ * @summary Test basic operations with keystores (jks, jceks, pkcs12)
+ * @author Yu-Ching Valerie PENG
+ */
+public class TestKeystoreBasic {
+
+    private static final String PRIVATE_KEY_PKCS8_BASE64 = ""
+            + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpyz97liuWPDYcLH9TX8BiT78o"
+            + "lCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgKmLhuczF3M9VIcWr+"
+            + "JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz7leikne7KmclHvTfvFd0WDI7Gb9v"
+            + "o4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXRv5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfF"
+            + "e1DDsMg/KpKGiILYZ+g2qtVMZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e"
+            + "+sO6H24w2F19AgMBAAECggEBAId/12187dO6wUPCjumuJA1QrrBnbKdKONyai36uoc1Od4s5QFj7"
+            + "+hEIeS7rbGNYQuBvnkgusAbzkW0FIpxpHce3EJez/emux6pEOKoP77BwMt9gy+txyu0+BHi91FQg"
+            + "AGvrnQDO5EYVY4Cz/WjOsJzKu8zVLg+DS0Toa2qRFwmUe9mVAXPNOCZ3Oae/Q6tCDsaINNw0fmjj"
+            + "jn6uohPbS+n6xENG3FkQXB36getXy310xTGED2J27cmAQH6gLR6Kl2iROzNPbbpBqbuemI9kbcld"
+            + "EwBS1jRfZWeaPstYA1niVrE9UgUBzemnoh4TDkG076sYthHMr5QFGjPswnwtJ4ECgYEA0sURQ5+v"
+            + "baH4tdaemI3qpnknXTlzSpuZZmAoyvY0Id0mlduwKwmZ3Y5989wHfnnhFfyNO4IkTKjI2Wp97qP5"
+            + "4eqUNpA7FtNU7KUzMcFDTtwtNZuRYMrKlqo2lLbA+gVrAYpYZFL4b7tcwtX4DnYorDsmude6W8sG"
+            + "4Mx2VdFJC9UCgYEAzjsdXCYH5doWUHb0dvn9ID7IikffEMRM720MRjrnnnVbpzx6ACntkPDNZg7p"
+            + "TRE/mx7iBz81ZaUWE+V0wd0JvCHEdpAz3mksyvDFhU4Bgs6xzf2pSul5muhsx3hHcvvPezz5Bnxs"
+            + "faJlzkxfwotyGmvWN15GA/pyfsZjsbbTpwkCgYAO6NnbysQCIV8SnegCKqfatt9N/O5m7LLhRxQb"
+            + "p2bwrlA4cZ34rWkw/w9x3LK7A6wkfgUPnJkswxPSLXJTG05l6M4rPfCwIKr1Qopojp9QSMr569NQ"
+            + "4YeLOOc7heIIzbFQHpU6I5Rncv2Q2sn9W+ZsqJKIuvX34FjQNiZ406EzMQKBgHSxOGS61D84DuZK"
+            + "2Ps1awhC3kB4eHzJRms3vflDPWoJJ+pSKwpKrzUTPHXiPBqyhtYkPGszVeiE6CAr9sv3YZnFVaBs"
+            + "6hyQUJsob+uE/w/gGvXe8VsFDx0bJOodYfhrCbTHBHWqE81nBcocpxayxsayfAzqWB3KKd0YLrMR"
+            + "K2PZAoGAcZa8915R2m0KZ6HVJUt/JDR85jCbN71kcVDFY2XSFkOJvOdFoHNfRckfLzjq9Y2MSSTV"
+            + "+QDWbDo2doUQCejJUTaN8nP79tfyir24X5uVPvQaeVoGTKYb+LfUqK0F60lStmjuddIGSZH55y3v"
+            + "+9XjmxbVERtd1lqgQg3VlmKlEXY=";
+
+    /*
+     * Certificate:
+     * Data:
+     *     Version: 3 (0x2)
+     *     Serial Number: 7 (0x7)
+     * Signature Algorithm: sha512WithRSAEncryption
+     *     Issuer: CN=Root
+     *     Validity
+     *         Not Before: Sep  1 18:03:59 2015 GMT
+     *         Not After : Jan 17 18:03:59 2043 GMT
+     *     Subject: CN=EE
+     */
+    private static final String CERTIFICATE = ""
+            + "-----BEGIN CERTIFICATE-----\n"
+            + "MIIDHTCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAPMQ0wCwYDVQQDDARSb290\n"
+            + "MB4XDTE1MDkwMTE4MDM1OVoXDTQzMDExNzE4MDM1OVowDTELMAkGA1UEAwwCRUUw\n"
+            + "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyz97liuWPDYcLH9TX8Bi\n"
+            + "T78olCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgK\n"
+            + "mLhuczF3M9VIcWr+JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz\n"
+            + "7leikne7KmclHvTfvFd0WDI7Gb9vo4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXR\n"
+            + "v5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfFe1DDsMg/KpKGiILYZ+g2qtVM\n"
+            + "ZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e+sO6H24w2F19\n"
+            + "AgMBAAGjgYUwgYIwNAYDVR0fBC0wKzApoCegJYYjbGRhcDovL2xkYXAuaG9zdC5m\n"
+            + "b3IuY3JsZHAvbWFpbi5jcmwwSgYIKwYBBQUHAQEEPjA8MDoGCCsGAQUFBzAChi5s\n"
+            + "ZGFwOi8vbGRhcC5ob3N0LmZvci5haWEvZGM9Um9vdD9jQUNlcnRpZmljYXRlMA0G\n"
+            + "CSqGSIb3DQEBDQUAA4IBAQBWDfZHpuUx0yn5d3+BuztFqoks1MkGdk+USlH0TB1/\n"
+            + "gWWBd+4S4PCKlpSur0gj2rMW4fP5HQfNlHci8JV8/bG4KuKRAXW56dg1818Hl3pc\n"
+            + "iIrUSRn8uUjH3p9qb+Rb/u3mmVQRyJjN2t/zceNsO8/+Dd808OB9aEwGs8lMT0nn\n"
+            + "ZYaaAqYz1GIY/Ecyx1vfEZEQ1ljo6i/r70C3igbypBUShxSiGsleiVTLOGNA+MN1\n"
+            + "/a/Qh0bkaQyTGqK3bwvzzMeQVqWu2EWTBD/PmND5ExkpRICdv8LBVXfLnpoBr4lL\n"
+            + "hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY\n"
+            + "-----END CERTIFICATE-----\n";
+
+    private static final char[] PASSWD2 = new char[] {
+            'b', 'o', 'r', 'e', 'd'
+    };
+    private static final char[] PASSWDK = "cannot be null"
+            .toCharArray();
+    private static final String[] KS_Type = {
+            "jks", "jceks", "pkcs12", "PKCS11KeyStore"
+    };
+    private static final String[] PROVIDERS = {
+            "SunPKCS11-Solaris"
+    };
+    private static final String ALIAS_HEAD = "test";
+
+    private static final String CRYPTO_ALG = "PBEWithHmacSHA256AndAES_128";
+
+    @Test
+    public void testBasic() throws Exception {
+        TestKeystoreBasic jstest = new TestKeystoreBasic();
+        jstest.run();
+    }
+
+    public void run() throws Exception {
+        for (String provider : PROVIDERS) {
+            try {
+                runTest(provider);
+            } catch (java.security.KeyStoreException e) {
+                if (!provider.equals("SunPKCS11-Solaris")) {
+                    throw e;
+                }
+            } catch (NoSuchProviderException e) {
+                if (!provider.equals("SunPKCS11-Solaris")) {
+                    throw e;
+                }
+            }
+        }
+    }
+
+    public void runTest(String provider) throws Exception {
+
+        // load private key
+        // all keystore types should support private keys
+        KeySpec spec = new PKCS8EncodedKeySpec(
+                Base64.getMimeDecoder().decode(PRIVATE_KEY_PKCS8_BASE64));
+        PrivateKey privateKey = KeyFactory.getInstance("RSA")
+                .generatePrivate(spec);
+
+        // load x509 certificate
+        Certificate cert;
+        try (InputStream is = new BufferedInputStream(
+                new ByteArrayInputStream(CERTIFICATE.getBytes()))) {
+            cert = CertificateFactory.getInstance("X.509")
+                    .generateCertificate(is);
+        }
+
+        int numEntries = 5;
+        String type = null;
+        for (int i = 0; i < PROVIDERS.length; i++) {
+            if (provider.compareTo(PROVIDERS[i]) == 0) {
+                type = KS_Type[i];
+                break;
+            }
+        }
+
+        KeyStore ks = KeyStore.getInstance(type, provider);
+        KeyStore ks2 = KeyStore.getInstance(type, ks.getProvider().getName());
+
+        // create an empty key store
+        ks.load(null, null);
+
+        // store the secret keys
+        for (int j = 0; j < numEntries; j++) {
+            ks.setKeyEntry(ALIAS_HEAD + j, privateKey, PASSWDK,
+                    new Certificate[] { cert });
+        }
+
+        // initialize the 2nd key store object with the 1st one
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ks.store(baos, PASSWDK);
+        byte[] bArr = baos.toByteArray();
+        ByteArrayInputStream bais = new ByteArrayInputStream(bArr);
+        ks2.load(bais, null);
+
+        // check 2nd key store type
+        checkType(ks2, type);
+        // check the existing aliases for the 2nd key store
+        checkAlias(ks2, numEntries);
+
+        // compare the creation date of the 2 key stores for all aliases
+        compareCreationDate(ks, ks2, numEntries);
+        // remove the last entry from the 2nd key store
+        numEntries--;
+        ks2.deleteEntry(ALIAS_HEAD + numEntries);
+
+        // re-initialize the 1st key store with the 2nd key store
+        baos.reset();
+        ks2.store(baos, PASSWD2);
+        bais = new ByteArrayInputStream(baos.toByteArray());
+        try {
+            // expect an exception since the password is incorrect
+            ks.load(bais, PASSWDK);
+            fail("ERROR: passed the loading with incorrect password");
+        } catch (IOException ex) {
+            if (!causedBy(ex, UnrecoverableKeyException.class)) {
+                throw new RuntimeException("Unexpected cause");
+            }
+
+            bais.reset();
+            ks.load(bais, PASSWD2);
+            bais.reset();
+            ks.load(bais, null);
+        }
+
+        // check key store type
+        checkType(ks, type);
+
+        // check the existing aliases
+        checkAlias(ks, numEntries);
+
+        // compare the creation date of the 2 key stores for all aliases
+        compareCreationDate(ks, ks2, numEntries);
+
+        // check setEntry/getEntry with a password protection algorithm
+        if ("PKCS12".equalsIgnoreCase(ks.getType())) {
+            return;
+        }
+        String alias = ALIAS_HEAD + ALIAS_HEAD;
+        KeyStore.PasswordProtection pw =
+                new KeyStore.PasswordProtection(PASSWD2, CRYPTO_ALG, null);
+        KeyStore.PrivateKeyEntry entry =
+                new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{ cert });
+        checkSetEntry(ks, alias, pw, entry);
+        ks.setEntry(alias, entry, new KeyStore.PasswordProtection(PASSWD2));
+        checkGetEntry(ks, alias, pw);
+    }
+
+    // check setEntry with a password protection algorithm
+    private void checkSetEntry(KeyStore ks, String alias,
+            KeyStore.PasswordProtection pw, KeyStore.Entry entry) throws Exception {
+        try {
+            ks.setEntry(alias, entry, pw);
+            fail("ERROR: expected KeyStore.setEntry to throw an exception");
+        } catch (KeyStoreException e) {
+            // ignore the expected exception
+        }
+    }
+
+    // check getEntry with a password protection algorithm
+    private void checkGetEntry(KeyStore ks, String alias,
+            KeyStore.PasswordProtection pw) throws Exception {
+        try {
+            ks.getEntry(alias, pw);
+            fail("ERROR: expected KeyStore.getEntry to throw an exception");
+        } catch (KeyStoreException e) {
+            // ignore the expected exception
+        }
+    }
+
+    // check key store type
+    private void checkType(KeyStore obj, String type) {
+        if (!obj.getType().equals(type)) {
+            fail("ERROR: wrong key store type");
+        }
+    }
+
+    // check the existing aliases
+    private void checkAlias(KeyStore obj, int range) throws KeyStoreException {
+        for (int k = 0; k < range; k++) {
+            if (!obj.containsAlias(ALIAS_HEAD + k)) {
+                fail("ERROR: alias (" + k + ") should exist");
+            }
+        }
+    }
+
+    // compare the creation dates - true if all the same
+    private void compareCreationDate(KeyStore o1, KeyStore o2, int range)
+            throws KeyStoreException {
+        String alias;
+        for (int k = 0; k < range; k++) {
+            alias = ALIAS_HEAD + k;
+            if (!o1.getCreationDate(alias).equals(o2.getCreationDate(alias))) {
+                fail("ERROR: entry creation time (" + k + ") differs");
+            }
+        }
+    }
+
+    // checks if an exception was caused by specified exception class
+    private static boolean causedBy(Exception e, Class klass) {
+        Throwable cause = e;
+        while ((cause = cause.getCause()) != null) {
+            if (cause.getClass().equals(klass)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/KeyStore/TestKeystoreEntry.java b/ojluni/src/test/java/security/KeyStore/TestKeystoreEntry.java
new file mode 100644
index 0000000..31e8cd8
--- /dev/null
+++ b/ojluni/src/test/java/security/KeyStore/TestKeystoreEntry.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.security.KeyStore;
+
+import static java.lang.System.out;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.Provider;
+import java.security.Security;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import org.testng.annotations.Test;
+import static org.junit.Assert.fail;
+
+/*
+ * @test
+ * @bug 8048621
+ * @summary Test the basic operations of KeyStore entry, provided by SunJCE
+ *  (jceks), and SunPKCS11-Solaris(PKCS11KeyStore)
+ * @author Yu-Ching Valerie PENG
+ */
+
+public class TestKeystoreEntry {
+    private static final char[] PASSWDK = new char[] {
+            't', 'e', 'r', 'c', 'e', 's'
+    };
+    private static final char[] PASSWDF = new String("guardian Angel")
+            .toCharArray();
+    private static final String[] KS_ALGOS = {
+            "DES", "DESede", "Blowfish"
+    };
+    private static final int NUM_ALGOS = KS_ALGOS.length;
+
+    private final SecretKey[] sks = new SecretKey[NUM_ALGOS];
+
+    TestKeystoreEntry() throws Exception {
+        // generate secret keys which are to be stored in the jce
+        // key store object
+        KeyGenerator[] kgs = new KeyGenerator[NUM_ALGOS];
+        for (int i = 0; i < NUM_ALGOS; i++) {
+            kgs[i] = KeyGenerator.getInstance(KS_ALGOS[i]);
+            sks[i] = kgs[i].generateKey();
+        }
+
+    }
+
+    @Test
+    public void testEntry() throws Exception {
+        TestKeystoreEntry jstest = new TestKeystoreEntry();
+        jstest.run();
+    }
+
+    public void run() throws Exception {
+        Provider[] providers = Security.getProviders();
+        for (Provider p: providers) {
+            String prvName = p.getName();
+            if (prvName.startsWith("SunJCE")
+                    || prvName.startsWith("SunPKCS11-Solaris")) {
+                try {
+                    runTest(p);
+
+                } catch (java.security.KeyStoreException e) {
+                    if (!prvName.startsWith("SunPKCS11-Solaris")) {
+                        throw e;
+                    }
+                }
+            }
+        }
+    }
+
+    public void runTest(Provider p) throws Exception {
+        try (FileOutputStream fos = new FileOutputStream("jceks");
+             FileInputStream fis = new FileInputStream("jceks");) {
+
+            KeyStore ks = KeyStore.getInstance("jceks", p);
+            // create an empty key store
+            ks.load(null, null);
+
+            // store the secret keys
+            String aliasHead = new String("secretKey");
+            for (int j = 0; j < NUM_ALGOS; j++) {
+                ks.setKeyEntry(aliasHead + j, sks[j], PASSWDK, null);
+            }
+
+            // write the key store out to a file
+            ks.store(fos, PASSWDF);
+            // wipe clean the existing key store
+            for (int k = 0; k < NUM_ALGOS; k++) {
+                ks.deleteEntry(aliasHead + k);
+            }
+            if (ks.size() != 0) {
+                fail("ERROR: re-initialization failed");
+            }
+
+            // reload the key store with the file
+            ks.load(fis, PASSWDF);
+
+            // check the integrity/validaty of the key store
+            Key temp = null;
+            String alias = null;
+            if (ks.size() != NUM_ALGOS) {
+                fail("ERROR: wrong number of key"
+                        + " entries");
+            }
+
+            for (int m = 0; m < ks.size(); m++) {
+                alias = aliasHead + m;
+                temp = ks.getKey(alias, PASSWDK);
+                // compare the keys
+                if (!temp.equals(sks[m])) {
+                    fail("ERROR: key comparison (" + m
+                            + ") failed");
+                }
+                // check the type of key
+                if (ks.isCertificateEntry(alias) || !ks.isKeyEntry(alias)) {
+                    fail("ERROR: type identification ("
+                            + m + ") failed");
+                }
+            }
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/security/Provider/ProvidersTest.java b/ojluni/src/test/java/security/Provider/ProvidersTest.java
new file mode 100644
index 0000000..44d2714
--- /dev/null
+++ b/ojluni/src/test/java/security/Provider/ProvidersTest.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2017 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 test.java.security.Provider;
+
+import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import dalvik.system.VMRuntime;
+
+import java.lang.reflect.Method;
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.KeyPairGenerator;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.Signature;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import javax.crypto.Cipher;
+import javax.crypto.KeyAgreement;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKeyFactory;
+
+import sun.security.jca.Providers;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import org.testng.annotations.Test;
+
+/**
+ * Tests that the deprecation of algorithms from the BC provider works as expected.  Requests
+ * from an application targeting an API level before the deprecation should receive them,
+ * but those targeting an API level after the deprecation should cause an exception.  Tests
+ * a representative sample of services and algorithms and various ways of naming them.
+ */
+public class ProvidersTest {
+
+    /**
+     * An object that can be called to call an appropriate getInstance method.  Since
+     * each type of object has its own class that the method should be called on,
+     * it's either this or reflection, and this seems more straightforward.
+     */
+    private interface Algorithm {
+        Object getInstance() throws GeneralSecurityException;
+    }
+
+    // getInstance calls that result in requests to BC
+    private static final List<Algorithm> BC_ALGORITHMS = new ArrayList<>();
+    // getInstance calls that result in requests to Conscrypt
+    private static final List<Algorithm> CONSCRYPT_ALGORITHMS = new ArrayList<>();
+    static {
+        // All the same algorithms as for BC, but with no provider, which should produce
+        // the Conscrypt implementation
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                return Signature.getInstance("sha224withrsa");
+            }
+        });
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                return KeyFactory.getInstance("EC");
+            }
+        });
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                return Signature.getInstance("MD5withRSAEncryption");
+            }
+        });
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                return KeyGenerator.getInstance("HMAC-MD5");
+            }
+        });
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                return Mac.getInstance("Hmac/sha256");
+            }
+        });
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                return Signature.getInstance("SHA384/rsA");
+            }
+        });
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                // OID for SHA-256
+                return MessageDigest.getInstance("2.16.840.1.101.3.4.2.1");
+            }
+        });
+        CONSCRYPT_ALGORITHMS.add(new Algorithm() {
+            @Override
+            public Object getInstance() throws GeneralSecurityException {
+                // OID for AES-128
+                return AlgorithmParameters.getInstance("2.16.840.1.101.3.4.1.2");
+            }
+        });
+    }
+
+    private static final Set<String> REMOVED_BC_ALGORITHMS = new HashSet<String>();
+    static {
+        REMOVED_BC_ALGORITHMS.addAll(Arrays.asList(
+                "ALGORITHMPARAMETERS.1.2.840.113549.3.7",
+                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.2",
+                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.22",
+                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.26",
+                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.42",
+                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.46",
+                "ALGORITHMPARAMETERS.2.16.840.1.101.3.4.1.6",
+                "ALGORITHMPARAMETERS.AES",
+                "ALGORITHMPARAMETERS.DESEDE",
+                "ALGORITHMPARAMETERS.EC",
+                "ALGORITHMPARAMETERS.GCM",
+                "ALGORITHMPARAMETERS.OAEP",
+                "ALGORITHMPARAMETERS.TDEA",
+                "CERTIFICATEFACTORY.X.509",
+                "CERTIFICATEFACTORY.X509",
+                // List of Ciphers produced by ProviderOverlap:
+                "CIPHER.1.2.840.113549.3.4",
+                "CIPHER.2.16.840.1.101.3.4.1.26",
+                "CIPHER.2.16.840.1.101.3.4.1.46",
+                "CIPHER.2.16.840.1.101.3.4.1.6",
+                "CIPHER.AES/GCM/NOPADDING",
+                "CIPHER.ARC4",
+                "CIPHER.ARCFOUR",
+                "CIPHER.OID.1.2.840.113549.3.4",
+                "CIPHER.RC4",
+                // End of Ciphers produced by ProviderOverlap
+                // Additional ciphers transformations that will resolve to the same things as
+                // the automatically-produced overlap due to the Cipher transformation rules.
+                // These have been added manually.
+                "CIPHER.ARC4/ECB/NOPADDING",
+                "CIPHER.ARC4/NONE/NOPADDING",
+                "CIPHER.ARCFOUR/ECB/NOPADDING",
+                "CIPHER.ARCFOUR/NONE/NOPADDING",
+                "CIPHER.RC4/ECB/NOPADDING",
+                "CIPHER.RC4/NONE/NOPADDING",
+                // End of additional Ciphers
+                "KEYAGREEMENT.ECDH",
+                "KEYFACTORY.1.2.840.10045.2.1",
+                "KEYFACTORY.1.2.840.113549.1.1.1",
+                "KEYFACTORY.1.2.840.113549.1.1.7",
+                "KEYFACTORY.1.3.133.16.840.63.0.2",
+                "KEYFACTORY.2.5.8.1.1",
+                "KEYFACTORY.EC",
+                "KEYGENERATOR.1.2.840.113549.2.10",
+                "KEYGENERATOR.1.2.840.113549.2.11",
+                "KEYGENERATOR.1.2.840.113549.2.7",
+                "KEYGENERATOR.1.2.840.113549.2.8",
+                "KEYGENERATOR.1.2.840.113549.2.9",
+                "KEYGENERATOR.1.3.6.1.5.5.8.1.1",
+                "KEYGENERATOR.1.3.6.1.5.5.8.1.2",
+                "KEYGENERATOR.2.16.840.1.101.3.4.2.1",
+                "KEYGENERATOR.AES",
+                "KEYGENERATOR.DESEDE",
+                "KEYGENERATOR.HMAC-MD5",
+                "KEYGENERATOR.HMAC-SHA1",
+                "KEYGENERATOR.HMAC-SHA224",
+                "KEYGENERATOR.HMAC-SHA256",
+                "KEYGENERATOR.HMAC-SHA384",
+                "KEYGENERATOR.HMAC-SHA512",
+                "KEYGENERATOR.HMAC/MD5",
+                "KEYGENERATOR.HMAC/SHA1",
+                "KEYGENERATOR.HMAC/SHA224",
+                "KEYGENERATOR.HMAC/SHA256",
+                "KEYGENERATOR.HMAC/SHA384",
+                "KEYGENERATOR.HMAC/SHA512",
+                "KEYGENERATOR.HMACMD5",
+                "KEYGENERATOR.HMACSHA1",
+                "KEYGENERATOR.HMACSHA224",
+                "KEYGENERATOR.HMACSHA256",
+                "KEYGENERATOR.HMACSHA384",
+                "KEYGENERATOR.HMACSHA512",
+                "KEYGENERATOR.TDEA",
+                "KEYPAIRGENERATOR.1.2.840.10045.2.1",
+                "KEYPAIRGENERATOR.1.2.840.113549.1.1.1",
+                "KEYPAIRGENERATOR.1.2.840.113549.1.1.7",
+                "KEYPAIRGENERATOR.1.3.133.16.840.63.0.2",
+                "KEYPAIRGENERATOR.2.5.8.1.1",
+                "KEYPAIRGENERATOR.EC",
+                "KEYPAIRGENERATOR.RSA",
+                "MAC.1.2.840.113549.2.10",
+                "MAC.1.2.840.113549.2.11",
+                "MAC.1.2.840.113549.2.7",
+                "MAC.1.2.840.113549.2.8",
+                "MAC.1.2.840.113549.2.9",
+                "MAC.1.3.6.1.5.5.8.1.1",
+                "MAC.1.3.6.1.5.5.8.1.2",
+                "MAC.2.16.840.1.101.3.4.2.1",
+                "MAC.HMAC-MD5",
+                "MAC.HMAC-SHA1",
+                "MAC.HMAC-SHA224",
+                "MAC.HMAC-SHA256",
+                "MAC.HMAC-SHA384",
+                "MAC.HMAC-SHA512",
+                "MAC.HMAC/MD5",
+                "MAC.HMAC/SHA1",
+                "MAC.HMAC/SHA224",
+                "MAC.HMAC/SHA256",
+                "MAC.HMAC/SHA384",
+                "MAC.HMAC/SHA512",
+                "MAC.HMACMD5",
+                "MAC.HMACSHA1",
+                "MAC.HMACSHA224",
+                "MAC.HMACSHA256",
+                "MAC.HMACSHA384",
+                "MAC.HMACSHA512",
+                "MAC.PBEWITHHMACSHA224",
+                "MAC.PBEWITHHMACSHA256",
+                "MAC.PBEWITHHMACSHA384",
+                "MAC.PBEWITHHMACSHA512",
+                "MESSAGEDIGEST.1.2.840.113549.2.5",
+                "MESSAGEDIGEST.1.3.14.3.2.26",
+                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.1",
+                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.2",
+                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.3",
+                "MESSAGEDIGEST.2.16.840.1.101.3.4.2.4",
+                "MESSAGEDIGEST.MD5",
+                "MESSAGEDIGEST.SHA",
+                "MESSAGEDIGEST.SHA-1",
+                "MESSAGEDIGEST.SHA-224",
+                "MESSAGEDIGEST.SHA-256",
+                "MESSAGEDIGEST.SHA-384",
+                "MESSAGEDIGEST.SHA-512",
+                "MESSAGEDIGEST.SHA1",
+                "MESSAGEDIGEST.SHA224",
+                "MESSAGEDIGEST.SHA256",
+                "MESSAGEDIGEST.SHA384",
+                "MESSAGEDIGEST.SHA512",
+                "SECRETKEYFACTORY.DESEDE",
+                "SECRETKEYFACTORY.TDEA",
+                "SIGNATURE.1.2.840.10045.4.1",
+                "SIGNATURE.1.2.840.10045.4.3.1",
+                "SIGNATURE.1.2.840.10045.4.3.2",
+                "SIGNATURE.1.2.840.10045.4.3.3",
+                "SIGNATURE.1.2.840.10045.4.3.4",
+                "SIGNATURE.1.2.840.113549.1.1.11",
+                "SIGNATURE.1.2.840.113549.1.1.12",
+                "SIGNATURE.1.2.840.113549.1.1.13",
+                "SIGNATURE.1.2.840.113549.1.1.14",
+                "SIGNATURE.1.2.840.113549.1.1.4",
+                "SIGNATURE.1.2.840.113549.1.1.5",
+                "SIGNATURE.1.3.14.3.2.29",
+                "SIGNATURE.ECDSA",
+                "SIGNATURE.ECDSAWITHSHA1",
+                "SIGNATURE.MD5/RSA",
+                "SIGNATURE.MD5WITHRSA",
+                "SIGNATURE.MD5WITHRSAENCRYPTION",
+                "SIGNATURE.NONEWITHECDSA",
+                "SIGNATURE.OID.1.2.840.10045.4.3.1",
+                "SIGNATURE.OID.1.2.840.10045.4.3.2",
+                "SIGNATURE.OID.1.2.840.10045.4.3.3",
+                "SIGNATURE.OID.1.2.840.10045.4.3.4",
+                "SIGNATURE.OID.1.2.840.113549.1.1.11",
+                "SIGNATURE.OID.1.2.840.113549.1.1.12",
+                "SIGNATURE.OID.1.2.840.113549.1.1.13",
+                "SIGNATURE.OID.1.2.840.113549.1.1.14",
+                "SIGNATURE.OID.1.2.840.113549.1.1.4",
+                "SIGNATURE.OID.1.2.840.113549.1.1.5",
+                "SIGNATURE.OID.1.3.14.3.2.29",
+                "SIGNATURE.SHA1/RSA",
+                "SIGNATURE.SHA1WITHECDSA",
+                "SIGNATURE.SHA1WITHRSA",
+                "SIGNATURE.SHA1WITHRSAENCRYPTION",
+                "SIGNATURE.SHA224/ECDSA",
+                "SIGNATURE.SHA224/RSA",
+                "SIGNATURE.SHA224WITHECDSA",
+                "SIGNATURE.SHA224WITHRSA",
+                "SIGNATURE.SHA224WITHRSAENCRYPTION",
+                "SIGNATURE.SHA256/ECDSA",
+                "SIGNATURE.SHA256/RSA",
+                "SIGNATURE.SHA256WITHECDSA",
+                "SIGNATURE.SHA256WITHRSA",
+                "SIGNATURE.SHA256WITHRSAENCRYPTION",
+                "SIGNATURE.SHA384/ECDSA",
+                "SIGNATURE.SHA384/RSA",
+                "SIGNATURE.SHA384WITHECDSA",
+                "SIGNATURE.SHA384WITHRSA",
+                "SIGNATURE.SHA384WITHRSAENCRYPTION",
+                "SIGNATURE.SHA512/ECDSA",
+                "SIGNATURE.SHA512/RSA",
+                "SIGNATURE.SHA512WITHECDSA",
+                "SIGNATURE.SHA512WITHRSA",
+                "SIGNATURE.SHA512WITHRSAENCRYPTION"
+        ));
+    }
+
+    private static Provider getProvider(Object object) throws Exception {
+        // Every JCA object has a getProvider() method
+        Method m = object.getClass().getMethod("getProvider");
+        return (Provider) m.invoke(object);
+    }
+
+    @Test
+    public void testBeforeLimit() throws Exception {
+        // When we're before the limit of the target API, all calls should succeed
+        try {
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    VMRuntime.getRuntime().getTargetSdkVersion() + 1);
+            for (Algorithm a : BC_ALGORITHMS) {
+                Object result = a.getInstance();
+                assertEquals("BC", getProvider(result).getName());
+            }
+            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
+                Object result = a.getInstance();
+                assertEquals("AndroidOpenSSL", getProvider(result).getName());
+            }
+        } finally {
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
+        }
+    }
+
+    @Test
+    public void testAtLimit() throws Exception {
+        // When we're at the limit of the target API, all calls should still succeed
+        try {
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    VMRuntime.getRuntime().getTargetSdkVersion());
+            for (Algorithm a : BC_ALGORITHMS) {
+                Object result = a.getInstance();
+                assertEquals("BC", getProvider(result).getName());
+            }
+            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
+                Object result = a.getInstance();
+                assertEquals("AndroidOpenSSL", getProvider(result).getName());
+            }
+        } finally {
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
+        }
+    }
+
+    @Test
+    public void testPastLimit() throws Exception {
+        // When we're beyond the limit of the target API, the Conscrypt calls should succeed
+        // but the BC calls should throw NoSuchAlgorithmException
+        try {
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    VMRuntime.getRuntime().getTargetSdkVersion() - 1);
+            for (Algorithm a : BC_ALGORITHMS) {
+                try {
+                    a.getInstance();
+                    fail("getInstance should have thrown");
+                } catch (NoSuchAlgorithmException expected) {
+                }
+            }
+            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
+                Object result = a.getInstance();
+                assertEquals("AndroidOpenSSL", getProvider(result).getName());
+            }
+        } finally {
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
+        }
+    }
+
+    @Test
+    public void testCustomProvider() throws Exception {
+        // When we install our own separate instance of Bouncy Castle, the system should
+        // respect that and allow us to use its implementation.
+        Provider originalBouncyCastle = null;
+        int originalBouncyCastleIndex = -1;
+        for (int i = 0; i < Security.getProviders().length; i++) {
+            if (Security.getProviders()[i].getName().equals("BC")) {
+                originalBouncyCastle = Security.getProviders()[i];
+                originalBouncyCastleIndex = i;
+                break;
+            }
+        }
+        assertNotNull(originalBouncyCastle);
+        Provider newBouncyCastle = new BouncyCastleProvider();
+        assertEquals("BC", newBouncyCastle.getName());
+        try {
+            // Remove the existing BC provider and replace it with a different one
+            Security.removeProvider("BC");
+            Security.insertProviderAt(newBouncyCastle, originalBouncyCastleIndex);
+            // Set the target API limit such that the BC algorithms are disallowed
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    VMRuntime.getRuntime().getTargetSdkVersion() - 1);
+            for (Algorithm a : BC_ALGORITHMS) {
+                Object result = a.getInstance();
+                assertEquals("BC", getProvider(result).getName());
+            }
+            for (Algorithm a : CONSCRYPT_ALGORITHMS) {
+                Object result = a.getInstance();
+                assertEquals("AndroidOpenSSL", getProvider(result).getName());
+            }
+        } finally {
+            Providers.setMaximumAllowableApiLevelForBcDeprecation(
+                    Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
+            Security.removeProvider("BC");
+            Security.insertProviderAt(originalBouncyCastle, originalBouncyCastleIndex);
+        }
+    }
+    
+    @Test
+    public void testRemovedBCAlgorithms() throws Exception {
+        for (String fullAlgorithm : REMOVED_BC_ALGORITHMS) {
+            String[] parts = fullAlgorithm.split("\\.", 2);
+            assertEquals("Algortihm names are expected to be of format Type.Name",
+                2, parts.length);
+
+            Provider bcProvider = Security.getProvider("BC");
+            String type = parts[0];
+            String algorithm = parts[1];
+            try {
+                switch (parts[0]) {
+                    case "ALGORITHMPARAMETERS":
+                        AlgorithmParameters.getInstance(algorithm, bcProvider);
+                    case "CERTIFICATEFACTORY":
+                        CertificateFactory.getInstance(algorithm, bcProvider);
+                    case "CIPHER":
+                        Cipher.getInstance(algorithm, bcProvider);
+                    case "KEYAGREEMENT":
+                        KeyAgreement.getInstance(algorithm, bcProvider);
+                    case "KEYFACTORY":
+                        KeyFactory.getInstance(algorithm, bcProvider);
+                    case "KEYGENERATOR":
+                        KeyGenerator.getInstance(algorithm, bcProvider);
+                    case "KEYPAIRGENERATOR":
+                        KeyPairGenerator.getInstance(algorithm, bcProvider);
+                    case "MAC":
+                        Mac.getInstance(algorithm, bcProvider);
+                    case "MESSAGEDIGEST":
+                        MessageDigest.getInstance(algorithm, bcProvider);
+                    case "SECRETKEYFACTORY":
+                        SecretKeyFactory.getInstance(algorithm, bcProvider);
+                    case "SIGNATURE":
+                        Signature.getInstance(algorithm, bcProvider);
+                    default:
+                        fail("unhandled algorithm type " + parts[0]);
+                }
+                fail("getInstance should have thrown for type: " + parts[0] + ", name: " + algorithm);
+            } catch(CertificateException | NoSuchAlgorithmException expected) {
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/security/cert/CertPathEncodingTest.java b/ojluni/src/test/java/security/cert/CertPathEncodingTest.java
new file mode 100644
index 0000000..0b74525
--- /dev/null
+++ b/ojluni/src/test/java/security/cert/CertPathEncodingTest.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.security.cert;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertPath;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.List;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8074931
+ * @summary CertPathEncodingTest tests the ability of the CertPath and
+ *          CertificateFactory to encode and decode CertPaths.
+ */
+public final class CertPathEncodingTest {
+    /*
+            Certificate:
+                Data:
+                    Version: 3 (0x2)
+                    Serial Number: 935438132 (0x37c1a734)
+                Signature Algorithm: dsaWithSHA1
+                    Issuer: C=us, O=sun, OU=east, OU=bcn, CN=yassir
+                    Validity
+                        Not Before: Aug 23 19:55:32 1999 GMT
+                        Not After : Aug 22 19:55:32 2000 GMT
+                    Subject: C=us, O=sun, OU=east, OU=bcn
+                    Subject Public Key Info:
+                        Public Key Algorithm: dsaEncryption
+                            pub:
+                                63:47:4f:f6:29:e5:98:a2:21:fd:da:97:9e:3f:ca:
+                                b0:17:49:8d:8a:a7:06:0d:a6:78:97:39:59:33:72:
+                                a2:a5:74:d5:3a:ef:e6:7c:07:d7:8e:8e:d1:66:73:
+                                99:14:04:96:f5:31:d6:72:ee:d2:53:f8:90:b5:f3:
+                                c3:f1:64:ba:1a:9e:c0:0a:da:92:48:c5:d3:84:7e:
+                                48:09:66:d9:51:ba:74:56:5a:77:8a:8c:9a:9c:f6:
+                                84:12:61:12:51:dc:c6:4f:84:94:ec:cb:78:51:83:
+                                8c:20:8a:53:7b:d2:b6:36:df:50:35:95:1f:cb:50:
+                                55:8b:3f:fb:e2:77:cb
+                            P:
+                                00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                                e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                                51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                                c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                                6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                                10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                                c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                                54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                                f2:22:03:19:9d:d1:48:01:c7
+                            Q:
+                                00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                                84:0b:f0:58:1c:f5
+                            G:
+                                00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                                57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                                07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                                81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                                32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                                ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                                f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                                a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                                25:64:01:4c:3b:fe:cf:49:2a
+                    X509v3 extensions:
+                        X509v3 Key Usage: critical
+                            Digital Signature, Key Encipherment, Certificate Sign
+                Signature Algorithm: dsaWithSHA1
+                     r:
+                         52:80:52:2b:2c:3d:02:66:58:b4:dc:ef:52:26:70:
+                         1b:53:ca:b3:7d
+                     s:
+                         62:03:b2:ab:3e:18:2a:66:09:b6:ce:d4:05:a5:8e:
+                         a5:7a:0d:55:67
+    */
+    private static final String cert1 =
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIICzTCCAougAwIBAgIEN8GnNDALBgcqhkjOOAQDBQAwSTELMAkGA1UEBhMCdXMx\n" +
+            "DDAKBgNVBAoTA3N1bjENMAsGA1UECxMEZWFzdDEMMAoGA1UECxMDYmNuMQ8wDQYD\n" +
+            "VQQDEwZ5YXNzaXIwHhcNOTkwODIzMTk1NTMyWhcNMDAwODIyMTk1NTMyWjA4MQsw\n" +
+            "CQYDVQQGEwJ1czEMMAoGA1UEChMDc3VuMQ0wCwYDVQQLEwRlYXN0MQwwCgYDVQQL\n" +
+            "EwNiY24wggG1MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YR\n" +
+            "t1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZ\n" +
+            "UKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOu\n" +
+            "K2HXKu/yIgMZndFIAccCFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps9\n" +
+            "3su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV4661FlP5nEHEIGAtEkWcSPoTCgW\n" +
+            "E7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoBJDvMpPG+qFGQ\n" +
+            "iaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBggACf2NHT/Yp5ZiiIf3al54/yrAX\n" +
+            "SY2KpwYNpniXOVkzcqKldNU67+Z8B9eOjtFmc5kUBJb1MdZy7tJT+JC188PxZLoa\n" +
+            "nsAK2pJIxdOEfkgJZtlRunRWWneKjJqc9oQSYRJR3MZPhJTsy3hRg4wgilN70rY2\n" +
+            "31A1lR/LUFWLP/vid8ujEzARMA8GA1UdDwEB/wQFAwMHpAAwCwYHKoZIzjgEAwUA\n" +
+            "Ay8AMCwCFFKAUissPQJmWLTc71ImcBtTyrN9AhRiA7KrPhgqZgm2ztQFpY6leg1V\n" +
+            "Zw==\n" +
+            "-----END CERTIFICATE-----\n" +
+            "";
+
+    /*
+            Certificate:
+                Data:
+                    Version: 3 (0x2)
+                    Serial Number: 935095671 (0x37bc6d77)
+                Signature Algorithm: dsaWithSHA1
+                    Issuer: C=us, O=sun, OU=east, OU=bcn, CN=yassir
+                    Validity
+                        Not Before: Aug 19 20:47:51 1999 GMT
+                        Not After : Aug 18 20:47:51 2000 GMT
+                    Subject: C=us, O=sun, OU=east, OU=bcn, CN=yassir
+                    Subject Public Key Info:
+                        Public Key Algorithm: dsaEncryption
+                            pub:
+                                0a:cc:a4:ec:d6:88:45:c2:24:6b:0d:78:f1:82:f3:
+                                5e:3e:31:5d:fb:64:d5:06:5e:39:16:f1:0a:85:d1:
+                                ff:d1:a4:74:c5:e6:b0:ba:93:1c:ee:69:51:be:3b:
+                                a6:66:44:50:b4:f0:5e:0e:dd:9f:08:71:fe:a1:91:
+                                2e:d4:9e:6b:b2:c0:82:3c:91:6c:18:b0:d9:bc:a3:
+                                48:91:3f:8b:59:01:61:00:02:ab:22:31:bc:7c:6c:
+                                0d:9f:ed:be:33:e6:5c:44:9e:62:30:95:f8:6d:22:
+                                d7:e5:85:4c:b0:98:6e:ad:cc:ca:3b:ad:cb:fa:f7:
+                                9f:37:13:f7:ca:e2:22:ba
+                            P:
+                                00:fd:7f:53:81:1d:75:12:29:52:df:4a:9c:2e:ec:
+                                e4:e7:f6:11:b7:52:3c:ef:44:00:c3:1e:3f:80:b6:
+                                51:26:69:45:5d:40:22:51:fb:59:3d:8d:58:fa:bf:
+                                c5:f5:ba:30:f6:cb:9b:55:6c:d7:81:3b:80:1d:34:
+                                6f:f2:66:60:b7:6b:99:50:a5:a4:9f:9f:e8:04:7b:
+                                10:22:c2:4f:bb:a9:d7:fe:b7:c6:1b:f8:3b:57:e7:
+                                c6:a8:a6:15:0f:04:fb:83:f6:d3:c5:1e:c3:02:35:
+                                54:13:5a:16:91:32:f6:75:f3:ae:2b:61:d7:2a:ef:
+                                f2:22:03:19:9d:d1:48:01:c7
+                            Q:
+                                00:97:60:50:8f:15:23:0b:cc:b2:92:b9:82:a2:eb:
+                                84:0b:f0:58:1c:f5
+                            G:
+                                00:f7:e1:a0:85:d6:9b:3d:de:cb:bc:ab:5c:36:b8:
+                                57:b9:79:94:af:bb:fa:3a:ea:82:f9:57:4c:0b:3d:
+                                07:82:67:51:59:57:8e:ba:d4:59:4f:e6:71:07:10:
+                                81:80:b4:49:16:71:23:e8:4c:28:16:13:b7:cf:09:
+                                32:8c:c8:a6:e1:3c:16:7a:8b:54:7c:8d:28:e0:a3:
+                                ae:1e:2b:b3:a6:75:91:6e:a3:7f:0b:fa:21:35:62:
+                                f1:fb:62:7a:01:24:3b:cc:a4:f1:be:a8:51:90:89:
+                                a8:83:df:e1:5a:e5:9f:06:92:8b:66:5e:80:7b:55:
+                                25:64:01:4c:3b:fe:cf:49:2a
+                    X509v3 extensions:
+                        X509v3 Key Usage: critical
+                            Digital Signature, Key Encipherment, Certificate Sign
+                        X509v3 Basic Constraints: critical
+                            CA:TRUE, pathlen:5
+                Signature Algorithm: dsaWithSHA1
+                     r:
+                         2f:88:46:37:94:92:b2:02:07:5b:8d:76:e5:81:23:
+                         85:7f:bc:8d:b9
+                     s:
+                         00:8b:d7:41:fa:11:c7:ab:27:92:5d:0a:03:98:56:
+                         36:42:5f:f5:1f:9d
+    */
+    private static final String cert2 =
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIIC9TCCArKgAwIBAgIEN7xtdzALBgcqhkjOOAQDBQAwSTELMAkGA1UEBhMCdXMx\n" +
+            "DDAKBgNVBAoTA3N1bjENMAsGA1UECxMEZWFzdDEMMAoGA1UECxMDYmNuMQ8wDQYD\n" +
+            "VQQDEwZ5YXNzaXIwHhcNOTkwODE5MjA0NzUxWhcNMDAwODE4MjA0NzUxWjBJMQsw\n" +
+            "CQYDVQQGEwJ1czEMMAoGA1UEChMDc3VuMQ0wCwYDVQQLEwRlYXN0MQwwCgYDVQQL\n" +
+            "EwNiY24xDzANBgNVBAMTBnlhc3NpcjCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQD9\n" +
+            "f1OBHXUSKVLfSpwu7OTn9hG3UjzvRADDHj+AtlEmaUVdQCJR+1k9jVj6v8X1ujD2\n" +
+            "y5tVbNeBO4AdNG/yZmC3a5lQpaSfn+gEexAiwk+7qdf+t8Yb+DtX58aophUPBPuD\n" +
+            "9tPFHsMCNVQTWhaRMvZ1864rYdcq7/IiAxmd0UgBxwIVAJdgUI8VIwvMspK5gqLr\n" +
+            "hAvwWBz1AoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlXjrrU\n" +
+            "WU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6jfwv6\n" +
+            "ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqA4GEAAKB\n" +
+            "gArMpOzWiEXCJGsNePGC814+MV37ZNUGXjkW8QqF0f/RpHTF5rC6kxzuaVG+O6Zm\n" +
+            "RFC08F4O3Z8Icf6hkS7UnmuywII8kWwYsNm8o0iRP4tZAWEAAqsiMbx8bA2f7b4z\n" +
+            "5lxEnmIwlfhtItflhUywmG6tzMo7rcv69583E/fK4iK6oycwJTAPBgNVHQ8BAf8E\n" +
+            "BQMDB6QAMBIGA1UdEwEB/wQIMAYBAf8CAQUwCwYHKoZIzjgEAwUAAzAAMC0CFC+I\n" +
+            "RjeUkrICB1uNduWBI4V/vI25AhUAi9dB+hHHqyeSXQoDmFY2Ql/1H50=\n" +
+            "-----END CERTIFICATE-----\n" +
+            "";
+
+    private static final String pkcs7path =
+            "MIIF9QYJKoZIhvcNAQcCoIIF5jCCBeICAQExADALBgkqhkiG9w0BBwGgggXKMIICzTCCAougAwIB\n" +
+            "AgIEN8GnNDALBgcqhkjOOAQDBQAwSTELMAkGA1UEBhMCdXMxDDAKBgNVBAoTA3N1bjENMAsGA1UE\n" +
+            "CxMEZWFzdDEMMAoGA1UECxMDYmNuMQ8wDQYDVQQDEwZ5YXNzaXIwHhcNOTkwODIzMTk1NTMyWhcN\n" +
+            "MDAwODIyMTk1NTMyWjA4MQswCQYDVQQGEwJ1czEMMAoGA1UEChMDc3VuMQ0wCwYDVQQLEwRlYXN0\n" +
+            "MQwwCgYDVQQLEwNiY24wggG1MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YR\n" +
+            "t1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQ\n" +
+            "IsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCX\n" +
+            "YFCPFSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZ\n" +
+            "V4661FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7\n" +
+            "YnoBJDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBggACf2NHT/Yp5ZiiIf3al54/\n" +
+            "yrAXSY2KpwYNpniXOVkzcqKldNU67+Z8B9eOjtFmc5kUBJb1MdZy7tJT+JC188PxZLoansAK2pJI\n" +
+            "xdOEfkgJZtlRunRWWneKjJqc9oQSYRJR3MZPhJTsy3hRg4wgilN70rY231A1lR/LUFWLP/vid8uj\n" +
+            "EzARMA8GA1UdDwEB/wQFAwMHpAAwCwYHKoZIzjgEAwUAAy8AMCwCFFKAUissPQJmWLTc71ImcBtT\n" +
+            "yrN9AhRiA7KrPhgqZgm2ztQFpY6leg1VZzCCAvUwggKyoAMCAQICBDe8bXcwCwYHKoZIzjgEAwUA\n" +
+            "MEkxCzAJBgNVBAYTAnVzMQwwCgYDVQQKEwNzdW4xDTALBgNVBAsTBGVhc3QxDDAKBgNVBAsTA2Jj\n" +
+            "bjEPMA0GA1UEAxMGeWFzc2lyMB4XDTk5MDgxOTIwNDc1MVoXDTAwMDgxODIwNDc1MVowSTELMAkG\n" +
+            "A1UEBhMCdXMxDDAKBgNVBAoTA3N1bjENMAsGA1UECxMEZWFzdDEMMAoGA1UECxMDYmNuMQ8wDQYD\n" +
+            "VQQDEwZ5YXNzaXIwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA/X9TgR11EilS30qcLuzk5/YRt1I8\n" +
+            "70QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJP\n" +
+            "u6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCFQCXYFCP\n" +
+            "FSMLzLKSuYKi64QL8Fgc9QKBgQD34aCF1ps93su8q1w2uFe5eZSvu/o66oL5V0wLPQeCZ1FZV466\n" +
+            "1FlP5nEHEIGAtEkWcSPoTCgWE7fPCTKMyKbhPBZ6i1R8jSjgo64eK7OmdZFuo38L+iE1YvH7YnoB\n" +
+            "JDvMpPG+qFGQiaiD3+Fa5Z8GkotmXoB7VSVkAUw7/s9JKgOBhAACgYAKzKTs1ohFwiRrDXjxgvNe\n" +
+            "PjFd+2TVBl45FvEKhdH/0aR0xeawupMc7mlRvjumZkRQtPBeDt2fCHH+oZEu1J5rssCCPJFsGLDZ\n" +
+            "vKNIkT+LWQFhAAKrIjG8fGwNn+2+M+ZcRJ5iMJX4bSLX5YVMsJhurczKO63L+vefNxP3yuIiuqMn\n" +
+            "MCUwDwYDVR0PAQH/BAUDAwekADASBgNVHRMBAf8ECDAGAQH/AgEFMAsGByqGSM44BAMFAAMwADAt\n" +
+            "AhQviEY3lJKyAgdbjXblgSOFf7yNuQIVAIvXQfoRx6snkl0KA5hWNkJf9R+dMQA=\n" +
+            "";
+
+    // Runs test of CertPath encoding and decoding.
+    @Test
+    public static void testCertPathEncoding(String[] args) throws Exception {
+        // Make the CertPath whose encoded form has already been stored
+        CertificateFactory certFac = CertificateFactory.getInstance("X509");
+
+        final List<Certificate> certs = new ArrayList<>();
+        certs.add(certFac.generateCertificate(new ByteArrayInputStream(cert1.getBytes())));
+        certs.add(certFac.generateCertificate(new ByteArrayInputStream(cert2.getBytes())));
+
+        CertPath cp = certFac.generateCertPath(certs);
+
+        // Get the encoded form of the CertPath we made
+        byte[] encoded = cp.getEncoded("PKCS7");
+        // check if it matches the encoded value
+        assertEquals(Base64.getMimeDecoder().decode(pkcs7path.getBytes()), encoded,
+            "PKCS#7 encoding doesn't match stored value");
+
+        // Generate a CertPath from the encoded value and check if it equals
+        // the CertPath generated from the certificates
+        CertPath decodedCP = certFac.generateCertPath(new ByteArrayInputStream(encoded), "PKCS7");
+        assertEquals(decodedCP, cp, "CertPath decoded from PKCS#7 isn't equal to original");
+    }
+}
diff --git a/ojluni/src/test/java/security/cert/GetInstance.java b/ojluni/src/test/java/security/cert/GetInstance.java
new file mode 100644
index 0000000..c4b0284
--- /dev/null
+++ b/ojluni/src/test/java/security/cert/GetInstance.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 4416946
+ * @summary Make sure {CertStore,CertPathBuilder,CertPathValidator,
+ * CertificateFactory}.getInstance throws InvalidAlgorithmParameterException
+ * if invalid params are specified and NoSuchAlgorithmException (or
+ * CertificateException for CertificateFactory) if bogus type is specified
+ */
+package test.java.security.cert;
+
+import static org.testng.Assert.assertThrows;
+
+import java.security.*;
+import java.security.cert.*;
+import java.util.*;
+import org.testng.annotations.Test;
+
+public class GetInstance {
+
+    @Test
+    public static void testGetInstance(String[] args) throws Exception {
+
+        CollectionCertStoreParameters ccsp
+            = new CollectionCertStoreParameters(new ArrayList<>());
+        assertThrows(InvalidAlgorithmParameterException.class,
+            () -> CertStore.getInstance("LDAP", ccsp));
+
+        assertThrows(NoSuchAlgorithmException.class,
+            () -> CertStore.getInstance("BOGUS", null));
+
+        assertThrows(NoSuchAlgorithmException.class,
+            () -> CertPathBuilder.getInstance("BOGUS"));
+
+        assertThrows(NoSuchAlgorithmException.class,
+            () -> CertPathValidator.getInstance("BOGUS"));
+
+        assertThrows(CertificateException.class,
+            () -> CertificateFactory.getInstance("BOGUS"));
+    }
+}
diff --git a/ojluni/src/test/java/security/cert/URICertStoreParameters/TestBasic.java b/ojluni/src/test/java/security/cert/URICertStoreParameters/TestBasic.java
new file mode 100644
index 0000000..baa44d5
--- /dev/null
+++ b/ojluni/src/test/java/security/cert/URICertStoreParameters/TestBasic.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.security.cert.URICertStoreParameters;
+
+
+import java.security.cert.CertStore;
+import java.security.cert.URICertStoreParameters;
+import java.net.URI;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+
+/*
+ * @test
+ * @bug 8038084
+ * @summary Basic testing for URICertStoreParameters
+ * @run main TestBasic
+ */
+public class TestBasic {
+
+    @Test
+    public static void testURICertStoreParameters(String[] args) throws Exception {
+        String str1 = "ldap://myownhost:5000/";
+        String str2 = "ldap://myownhost:5000/cn=foo";
+        test(str1, str2);
+        System.out.println("Test passed");
+    }
+
+    private static void test(String str1, String str2) throws Exception {
+        URICertStoreParameters p1 = new URICertStoreParameters(new URI(str1));
+        URICertStoreParameters p1Too = p1.clone();
+        assertEquals(p1Too, p1);
+        assertEquals(p1Too.getURI(), p1.getURI());
+
+        p1Too = new URICertStoreParameters(new URI(str1));
+        URICertStoreParameters p2 = new URICertStoreParameters(new URI(str2));
+
+        assertNotNull(p1);
+        assertEquals(p1, p1);
+        assertEquals(p1.hashCode(), p1.hashCode());
+        assertEquals(p1Too, p1);
+        assertEquals(p1, p1Too);
+        assertEquals(p1Too.hashCode(), p1.hashCode());
+        assertEquals(p1, p2);
+        assertEquals(p1Too, p2);
+    }
+}
diff --git a/ojluni/src/test/java/security/cert/X509CertSelectorTest.java b/ojluni/src/test/java/security/cert/X509CertSelectorTest.java
new file mode 100644
index 0000000..f3c0088
--- /dev/null
+++ b/ojluni/src/test/java/security/cert/X509CertSelectorTest.java
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.security.cert;
+
+import static org.testng.Assert.assertEquals;
+import static sun.security.x509.GeneralNameInterface.NAME_DIRECTORY;
+import static sun.security.x509.NameConstraintsExtension.EXCLUDED_SUBTREES;
+import static sun.security.x509.NameConstraintsExtension.PERMITTED_SUBTREES;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509Certificate;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+import sun.security.util.DerInputStream;
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
+import sun.security.x509.AuthorityKeyIdentifierExtension;
+import sun.security.x509.CertificatePoliciesExtension;
+import sun.security.x509.DNSName;
+import sun.security.x509.GeneralName;
+import sun.security.x509.GeneralNameInterface;
+import sun.security.x509.GeneralNames;
+import sun.security.x509.GeneralSubtree;
+import sun.security.x509.GeneralSubtrees;
+import sun.security.x509.KeyIdentifier;
+import sun.security.x509.NameConstraintsExtension;
+import sun.security.x509.PolicyInformation;
+import sun.security.x509.PrivateKeyUsageExtension;
+import sun.security.x509.SubjectAlternativeNameExtension;
+import sun.security.x509.X500Name;
+
+/*
+ * @test
+ * @bug 8074931
+ * @summary This class tests the X509CertSelector. The tests check particular criteria
+ *          by setting them to a value that should match our test certificate and
+ *          ensuring that they do match, then setting them to a value that should not
+ *          match our test certificate and ensuring that they do not match.
+ * @modules java.base/sun.security.x509
+ *          java.base/sun.security.util
+ */
+public class X509CertSelectorTest {
+    /*
+            Certificate:
+                Data:
+                    Version: 3 (0x2)
+                    Serial Number: 954172088 (0x38df82b8)
+                Signature Algorithm: dsaWithSHA1
+                    Issuer: C=us, O=sun, OU=testing
+                    Validity
+                        Not Before: Mar 27 15:48:08 2000 GMT
+                        Not After : Jun 25 14:48:08 2000 GMT
+                    Subject: C=us, O=sun, OU=testing, CN=mullan
+                    Subject Public Key Info:
+                        Public Key Algorithm: dsaEncryption
+                            pub:  0
+                            P:    0
+                            Q:    0
+                            G:    0
+                    X509v3 extensions:
+                        X509v3 Name Constraints: critical
+                            0D.B0@.>1.0...U....us1.0
+            ..U.
+            ..sun1.0...U....testing1.0
+            ..U....mullan
+                        X509v3 Subject Key Identifier:
+                            56:E8:88:AE:9D:B5:3F:2B:CB:A0:4C:4B:E2:87:53:07:33:77:1B:DF
+                        X509v3 Authority Key Identifier:
+                            keyid:8E:DD:AF:6F:EE:02:12:F4:61:E9:2F:E3:64:1A:6F:71:32:25:20:C0
+
+                        X509v3 Subject Alternative Name:
+                            email:mullan@east.sun.com
+                        X509v3 Private Key Usage Period:
+                            Not Before: Jan  1 05:00:00 2000 GMT, Not After: Jan  1 05:00:00 2001 GMT
+                        X509v3 Key Usage: critical
+                            Digital Signature
+                        X509v3 Certificate Policies:
+                            0$0\..*...0.0...+.......0..
+            Testing...
+                Signature Algorithm: dsaWithSHA1
+                     r:
+                         44:c7:35:40:5d:6c:28:75:7f:73:b2:f8:0d:72:6c:
+                         09:65:b8:81:14
+                     s:
+                         76:79:f5:c7:37:3b:0d:9b:db:70:2f:20:80:36:e3:
+                         80:e8:a6:c6:71
+    */
+    private static final String testCert =
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIICLjCCAeygAwIBAgIEON+CuDALBgcqhkjOOAQDBQAwLTELMAkGA1UEBhMCdXMx\n" +
+            "DDAKBgNVBAoTA3N1bjEQMA4GA1UECxMHdGVzdGluZzAeFw0wMDAzMjcxNTQ4MDha\n" +
+            "Fw0wMDA2MjUxNDQ4MDhaMD4xCzAJBgNVBAYTAnVzMQwwCgYDVQQKEwNzdW4xEDAO\n" +
+            "BgNVBAsTB3Rlc3RpbmcxDzANBgNVBAMTBm11bGxhbjAcMBQGByqGSM44BAEwCQIB\n" +
+            "AAIBAAIBAAMEAAIBAKOCASMwggEfMFAGA1UdHgEB/wRGMESgQjBApD4xCzAJBgNV\n" +
+            "BAYTAnVzMQwwCgYDVQQKEwNzdW4xEDAOBgNVBAsTB3Rlc3RpbmcxDzANBgNVBAMT\n" +
+            "Bm11bGxhbjAdBgNVHQ4EFgQUVuiIrp21PyvLoExL4odTBzN3G98wHwYDVR0jBBgw\n" +
+            "FoAUjt2vb+4CEvRh6S/jZBpvcTIlIMAwHgYDVR0RBBcwFYETbXVsbGFuQGVhc3Qu\n" +
+            "c3VuLmNvbTArBgNVHRAEJDAigA8yMDAwMDEwMTA1MDAwMFqBDzIwMDEwMTAxMDUw\n" +
+            "MDAwWjAPBgNVHQ8BAf8EBQMDB4AAMC0GA1UdIAQmMCQwIgYEKoSAADAaMBgGCCsG\n" +
+            "AQUFBwICMAwSClRlc3RpbmcuLi4wCwYHKoZIzjgEAwUAAy8AMCwCFETHNUBdbCh1\n" +
+            "f3Oy+A1ybAlluIEUAhR2efXHNzsNm9twLyCANuOA6KbGcQ==\n" +
+            "-----END CERTIFICATE-----\n" +
+            "";
+
+    private static final String testKey =
+            "MIIBtjCCASsGByqGSM44BAEwggEeAoGBAIVWPEkcxbxhQRCqVzg55tNqbP5j0K4kdu4bkmXvfqC5\n" +
+            "+qA75DvnfzsOJseb+9AuKXWk/DvCzFDmrY1YaU3scZC3OQEO9lEO3F4VDKOaudY6OT1SI22pAIwz\n" +
+            "j5pvq+i7zOp4xUqkQUeh/4iQSfxOT5UrFGjkcbnbpVkCXD/GxAz7AhUAjtnm3dVIddUUHl6wxpZ7\n" +
+            "GcA6gSsCgYAf/PXzQtemgIDjpFrNNSgTEKkLposBXKatAM+gUKlMUjf8SQvquqPxDtRrscGjXkoL\n" +
+            "oTkaR7/akULYFpBvUcFkeIFiCnJg8M9XhCWdLvn9MPt+jR2oxookvCb9xLtD6WvIM/wd/nZ1iK4u\n" +
+            "iY1+q85xvns/Awbtwl7oZDAwE2TUKAOBhAACgYBDc9UZ+3xsZubUZvRG5cpyJceYpJp2exOPVJXn\n" +
+            "jR4CcR+cT9bAJpFSxqE/8KtNHXxHdu4f3DU67IMOVDpugzihyzXJvNm3w2H9x+6xczHG2wjvAJeh\n" +
+            "X62EWbUatxPXFAoVKZWuUbaYaZzdWBDtNRrCuKKsLo0GFy8g2BZISuD3jw==\n" +
+            "";
+
+    // Certificate to run tests on
+    private final X509Certificate cert;
+
+    // BEGIN Android-removed: Not needed with testng
+    /*
+    public static void main(String[] args) throws Exception {
+        X509CertSelectorTest test = new X509CertSelectorTest();
+        test.doTest();
+    }
+    */
+    // END Android-removed: Not needed with testng
+
+    public X509CertSelectorTest() throws CertificateException, IOException {
+        cert = (X509Certificate) CertificateFactory.getInstance("X.509")
+                .generateCertificate(new ByteArrayInputStream(testCert.getBytes()));
+    }
+
+    // Runs the test.
+    // BEGIN Android-removed: Not needed with testng
+    /*
+    private void doTest() throws Exception {
+        System.out.println("START OF TESTS FOR " + "X509CertSelector");
+
+        testSerialNumber();
+        testIssuer();
+        testSubjectKeyIdentifier();
+        testAuthorityKeyIdentifier();
+        testCertificateValid();
+        testPrivateKeyValid();
+        testSubjectPublicKeyAlgID();
+        testKeyUsage();
+        testSubjectAltName();
+        testPolicy();
+        testPathToName();
+        testSubject();
+        testSubjectPublicKey();
+        testNameConstraints();
+        testBasicConstraints();
+        testCertificate();
+    }
+    */
+    // END Android-removed: Not needed with testng
+
+    // Tests matching on the serial number contained in the certificate.
+    @Test
+    public void testSerialNumber() {
+        System.out.println("X.509 Certificate Match on serialNumber");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        selector.setSerialNumber(new BigInteger("999999999"));
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setSerialNumber(cert.getSerialNumber());
+        checkMatch(selector, cert, true);
+    }
+
+    // Tests matching on the issuer name contained in the certificate.
+    @Test
+    public void testIssuer() throws IOException {
+        System.out.println("X.509 Certificate Match on issuer");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        selector.setIssuer("ou=bogus,ou=east,o=sun,c=us");
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setIssuer((cert.getIssuerX500Principal()).getName("RFC2253"));
+        checkMatch(selector, cert, true);
+    }
+
+    /*
+     * Tests matching on the subject key identifier contained in the
+     * certificate.
+     */
+    @Test
+    public void testSubjectKeyIdentifier() throws IOException {
+        System.out.println("X.509 Certificate Match on subjectKeyIdentifier");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+        selector.setSubjectKeyIdentifier(b);
+        checkMatch(selector, cert, false);
+
+        // good match
+        DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.14"));
+        byte[] encoded = in.getOctetString();
+        selector.setSubjectKeyIdentifier(encoded);
+        checkMatch(selector, cert, true);
+    }
+
+    /*
+     * Tests matching on the authority key identifier contained in the
+     * certificate.
+     */
+    @Test
+    public void testAuthorityKeyIdentifier() throws IOException {
+        System.out.println("X.509 Certificate Match on authorityKeyIdentifier");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+        AuthorityKeyIdentifierExtension a = new AuthorityKeyIdentifierExtension(new KeyIdentifier(b), null, null);
+        selector.setAuthorityKeyIdentifier(a.getExtensionValue());
+        checkMatch(selector, cert, false);
+
+        // good match
+        DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.35"));
+        byte[] encoded = in.getOctetString();
+        selector.setAuthorityKeyIdentifier(encoded);
+        checkMatch(selector, cert, true);
+    }
+
+    /*
+     * Tests matching on the certificate validity component contained in the
+     * certificate.
+     */
+    @Test
+    public void testCertificateValid() {
+        System.out.println("X.509 Certificate Match on certificateValid");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        Calendar cal = Calendar.getInstance();
+        cal.set(1968, 12, 31);
+        selector.setCertificateValid(cal.getTime());
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setCertificateValid(cert.getNotBefore());
+        checkMatch(selector, cert, true);
+    }
+
+    /*
+     * Tests matching on the private key validity component contained in the
+     * certificate.
+     */
+    @Test
+    public void testPrivateKeyValid() throws IOException, CertificateException {
+        System.out.println("X.509 Certificate Match on privateKeyValid");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        Calendar cal = Calendar.getInstance();
+        cal.set(1968, 12, 31);
+        selector.setPrivateKeyValid(cal.getTime());
+        checkMatch(selector, cert, false);
+
+        // good match
+        DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.16"));
+        byte[] encoded = in.getOctetString();
+        PrivateKeyUsageExtension ext = new PrivateKeyUsageExtension(false, encoded);
+        Date validDate = (Date) ext.get(PrivateKeyUsageExtension.NOT_BEFORE);
+        selector.setPrivateKeyValid(validDate);
+        checkMatch(selector, cert, true);
+
+    }
+
+    private ObjectIdentifier getCertPubKeyAlgOID(X509Certificate xcert) throws IOException {
+        byte[] encodedKey = xcert.getPublicKey().getEncoded();
+        DerValue val = new DerValue(encodedKey);
+        if (val.tag != DerValue.tag_Sequence) {
+            throw new RuntimeException("invalid key format");
+        }
+
+        return AlgorithmId.parse(val.data.getDerValue()).getOID();
+    }
+
+    /*
+     * Tests matching on the subject public key algorithm ID component contained
+     * in the certificate.
+     */
+    @Test
+    public void testSubjectPublicKeyAlgID() throws IOException {
+        System.out.println("X.509 Certificate Match on subjectPublicKeyAlgID");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        selector.setSubjectPublicKeyAlgID("2.5.29.14");
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setSubjectPublicKeyAlgID(getCertPubKeyAlgOID(cert).toString());
+        checkMatch(selector, cert, true);
+
+    }
+
+    // Tests matching on the key usage extension contained in the certificate.
+    @Test
+    public void testKeyUsage() {
+        System.out.println("X.509 Certificate Match on keyUsage");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        boolean[] keyUsage = { true, false, true, false, true, false, true, false };
+        selector.setKeyUsage(keyUsage);
+        System.out.println("Selector = " + selector.toString());
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setKeyUsage(cert.getKeyUsage());
+        System.out.println("Selector = " + selector.toString());
+        checkMatch(selector, cert, true);
+    }
+
+    /*
+     * Tests matching on the subject alternative name extension contained in the
+     * certificate.
+     */
+    @Test
+    public void testSubjectAltName() throws IOException {
+        System.out.println("X.509 Certificate Match on subjectAltName");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        GeneralNameInterface dnsName = new DNSName("foo.com");
+        DerOutputStream tmp = new DerOutputStream();
+        dnsName.encode(tmp);
+        selector.addSubjectAlternativeName(2, tmp.toByteArray());
+        checkMatch(selector, cert, false);
+
+        // good match
+        DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.17"));
+        byte[] encoded = in.getOctetString();
+        SubjectAlternativeNameExtension ext = new SubjectAlternativeNameExtension(false, encoded);
+        GeneralNames names = (GeneralNames) ext.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
+        GeneralName name = (GeneralName) names.get(0);
+        selector.setSubjectAlternativeNames(null);
+        DerOutputStream tmp2 = new DerOutputStream();
+        name.getName().encode(tmp2);
+        selector.addSubjectAlternativeName(name.getType(), tmp2.toByteArray());
+        checkMatch(selector, cert, true);
+
+        // good match 2 (matches at least one)
+        selector.setMatchAllSubjectAltNames(false);
+        selector.addSubjectAlternativeName(2, "foo.com");
+        checkMatch(selector, cert, true);
+    }
+
+    /*
+     * Tests matching on the policy constraints extension contained in the
+     * certificate.
+     */
+    @Test
+    public void testPolicy() throws IOException {
+        System.out.println("X.509 Certificate Match on certificatePolicies");
+        // test encoding of CertificatePoliciesExtension because we wrote the
+        // code
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        Set<String> s = new HashSet<>();
+        s.add(new String("1.2.5.7.68"));
+        selector.setPolicy(s);
+        checkMatch(selector, cert, false);
+
+        // good match
+        DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.32"));
+        CertificatePoliciesExtension ext = new CertificatePoliciesExtension(false, in.getOctetString());
+        List<PolicyInformation> policies = ext.get(CertificatePoliciesExtension.POLICIES);
+        // match on the first policy id
+        PolicyInformation policyInfo = (PolicyInformation) policies.get(0);
+        s.clear();
+        s.add(policyInfo.getPolicyIdentifier().getIdentifier().toString());
+        selector.setPolicy(s);
+        checkMatch(selector, cert, true);
+    }
+
+    /*
+     * Tests matching on the name constraints extension contained in the
+     * certificate.
+     */
+    @Test
+    public void testPathToName() throws IOException {
+        System.out.println("X.509 Certificate Match on pathToName");
+
+        X509CertSelector selector = null;
+        DerInputStream in = new DerInputStream(cert.getExtensionValue("2.5.29.30"));
+        byte[] encoded = in.getOctetString();
+        NameConstraintsExtension ext = new NameConstraintsExtension(false, encoded);
+        GeneralSubtrees permitted = (GeneralSubtrees) ext.get(PERMITTED_SUBTREES);
+        GeneralSubtrees excluded = (GeneralSubtrees) ext.get(EXCLUDED_SUBTREES);
+
+        // bad matches on pathToName within excluded subtrees
+        if (excluded != null) {
+            Iterator<GeneralSubtree> e = excluded.iterator();
+            while (e.hasNext()) {
+                GeneralSubtree tree = e.next();
+                if (tree.getName().getType() == NAME_DIRECTORY) {
+                    X500Name excludedDN1 = new X500Name(tree.getName().toString());
+                    X500Name excludedDN2 = new X500Name("CN=Bogus, " + tree.getName().toString());
+                    DerOutputStream derDN1 = new DerOutputStream();
+                    DerOutputStream derDN2 = new DerOutputStream();
+                    excludedDN1.encode(derDN1);
+                    excludedDN2.encode(derDN2);
+                    selector = new X509CertSelector();
+                    selector.addPathToName(NAME_DIRECTORY, derDN1.toByteArray());
+                    checkMatch(selector, cert, false);
+                    selector.setPathToNames(null);
+                    selector.addPathToName(NAME_DIRECTORY, derDN2.toByteArray());
+                    checkMatch(selector, cert, false);
+                }
+            }
+        }
+
+        // good matches on pathToName within permitted subtrees
+        if (permitted != null) {
+            Iterator<GeneralSubtree> e = permitted.iterator();
+            while (e.hasNext()) {
+                GeneralSubtree tree = e.next();
+                if (tree.getName().getType() == NAME_DIRECTORY) {
+                    X500Name permittedDN1 = new X500Name(tree.getName().toString());
+                    X500Name permittedDN2 = new X500Name("CN=good, " + tree.getName().toString());
+                    DerOutputStream derDN1 = new DerOutputStream();
+                    DerOutputStream derDN2 = new DerOutputStream();
+                    permittedDN1.encode(derDN1);
+                    permittedDN2.encode(derDN2);
+                    selector = new X509CertSelector();
+                    selector.addPathToName(NAME_DIRECTORY, derDN1.toByteArray());
+                    checkMatch(selector, cert, true);
+                    selector.setPathToNames(null);
+                    selector.addPathToName(NAME_DIRECTORY, derDN2.toByteArray());
+                    checkMatch(selector, cert, true);
+                }
+            }
+        }
+    }
+
+    // Tests matching on the subject name contained in the certificate.
+    @Test
+    public void testSubject() throws IOException {
+        System.out.println("X.509 Certificate Match on subject");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        selector.setSubject("ou=bogus,ou=east,o=sun,c=us");
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setSubject(cert.getSubjectX500Principal().getName("RFC2253"));
+        checkMatch(selector, cert, true);
+    }
+
+    // Tests matching on the subject public key contained in the certificate.
+    @Test
+    public void testSubjectPublicKey() throws IOException, GeneralSecurityException {
+        System.out.println("X.509 Certificate Match on subject public key");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(
+                Base64.getMimeDecoder().decode(testKey.getBytes()));
+        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+        PublicKey pubKey = keyFactory.generatePublic(keySpec);
+        selector.setSubjectPublicKey(pubKey);
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setSubjectPublicKey(cert.getPublicKey());
+        checkMatch(selector, cert, true);
+    }
+
+    // Tests matching on the name constraints contained in the certificate.
+    // TODO(b/203769066): Depends on updated X509Certificate implementation
+    private void testNameConstraints() throws IOException {
+        System.out.println("X.509 Certificate Match on name constraints");
+        // bad match
+        GeneralSubtrees subjectTree = new GeneralSubtrees();
+        subjectTree.add(getGeneralSubtree((X500Name) cert.getSubjectDN()));
+        NameConstraintsExtension ext = new NameConstraintsExtension((GeneralSubtrees) null, subjectTree);
+        X509CertSelector selector = new X509CertSelector();
+        selector.setNameConstraints(ext.getExtensionValue());
+        checkMatch(selector, cert, false);
+
+        // good match
+        ext = new NameConstraintsExtension(subjectTree, null);
+        selector.setNameConstraints(ext.getExtensionValue());
+        checkMatch(selector, cert, true);
+    }
+
+    // Tests matching on basic constraints.
+    @Test
+    public void testBasicConstraints() {
+        System.out.println("X.509 Certificate Match on basic constraints");
+        // bad match
+        X509CertSelector selector = new X509CertSelector();
+        int mpl = cert.getBasicConstraints();
+        selector.setBasicConstraints(0);
+        checkMatch(selector, cert, false);
+
+        // good match
+        selector.setBasicConstraints(mpl);
+        checkMatch(selector, cert, true);
+    }
+
+    // Tests certificateEquals criterion
+    @Test
+    public void testCertificate() {
+        System.out.println("X.509 Certificate Match on certificateEquals criterion");
+
+        X509CertSelector selector = new X509CertSelector();
+        // good match
+        selector.setCertificate(cert);
+        checkMatch(selector, cert, true);
+    }
+
+    private void checkMatch(X509CertSelector selector, X509Certificate cert, boolean match) {
+        boolean result = selector.match(cert);
+        assertEquals(result, match,
+            selector + " match " + cert + " is " + result + ", but expect " + match);
+    }
+
+    private static GeneralSubtree getGeneralSubtree(GeneralNameInterface gni) {
+        // Create a new GeneralSubtree with the specified name, 0 base, and
+        // unlimited length
+        GeneralName gn = new GeneralName(gni);
+        GeneralSubtree subTree = new GeneralSubtree(gn, 0, -1);
+        return subTree;
+    }
+}
diff --git a/ojluni/src/test/java/time/jdk/testlibrary/RandomFactory.java b/ojluni/src/test/java/time/jdk/testlibrary/RandomFactory.java
index 0951d11..8930a38 100644
--- a/ojluni/src/test/java/time/jdk/testlibrary/RandomFactory.java
+++ b/ojluni/src/test/java/time/jdk/testlibrary/RandomFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,7 +21,7 @@
  * questions.
  */
 
-package jdk.testlibrary;
+package jdk.test.lib;
 
 import java.util.Random;
 import java.util.SplittableRandom;
diff --git a/ojluni/src/test/java/time/tck/java/time/AbstractTCKTest.java b/ojluni/src/test/java/time/tck/java/time/AbstractTCKTest.java
index d960114..6272ea7 100644
--- a/ojluni/src/test/java/time/tck/java/time/AbstractTCKTest.java
+++ b/ojluni/src/test/java/time/tck/java/time/AbstractTCKTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,14 +69,35 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamConstants;
 import java.io.Serializable;
-import java.lang.reflect.Field;
 import java.util.Formatter;
+import java.util.Map;
 
 /**
  * Base test class.
  */
 public abstract class AbstractTCKTest {
 
+    /**
+     * Map from package name to the serialVersionUID of the .Ser class for the package.
+     */
+    private static Map<String, Long> serialVersionUIDs = Map.of(
+                "java.time",        -7683839454370182990L,
+                "java.time.chrono", -6103370247208168577L,
+                "java.time.zone",   -8885321777449118786L
+                );
+
+    /**
+     * Returns the serialVersionUID for the class.
+     * The SUIDs are defined by the specification for each class.
+     * @param serClass the class to return the SUID of
+     * @return returns the serialVersionUID for the class
+     */
+    public final static long getSUID(Class<?> serClass) {
+        String pkgName = serClass.getPackageName();
+        return serialVersionUIDs.get(pkgName);
+    }
+
+
     protected static boolean isIsoLeap(long year) {
         if (year % 4 != 0) {
             return false;
@@ -111,10 +132,8 @@
 
     protected static void assertSerializedBySer(Object object, byte[] expectedBytes, byte[]... matches) throws Exception {
         String serClass = object.getClass().getPackage().getName() + ".Ser";
-        Class<?> serCls = Class.forName(serClass);
-        Field field = serCls.getDeclaredField("serialVersionUID");
-        field.setAccessible(true);
-        long serVer = (Long) field.get(null);
+        long serVer = getSUID(object.getClass());
+
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         try (ObjectOutputStream oos = new ObjectOutputStream(baos) ) {
             oos.writeObject(object);
@@ -172,9 +191,8 @@
      * @throws Exception if an unexpected condition occurs
      */
     protected static void assertNotSerializable(Class<?> serClass) throws Exception {
-        Field field = serClass.getDeclaredField("serialVersionUID");
-        field.setAccessible(true);
-        long serVer = (Long) field.get(null);
+        long serVer = getSUID(serClass);
+
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         try (DataOutputStream out = new DataOutputStream(baos)) {
             out.writeShort(ObjectStreamConstants.STREAM_MAGIC);
@@ -201,7 +219,6 @@
         fail("Class should not be deserializable " + serClass.getName());
     }
 
-
     /**
      * Utility method to dump a byte array in a java syntax.
      * @param bytes and array of bytes
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKClock_Tick.java b/ojluni/src/test/java/time/tck/java/time/TCKClock_Tick.java
index c221237..08b0a52 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKClock_Tick.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKClock_Tick.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -160,6 +160,17 @@
     }
 
     //-----------------------------------------------------------------------
+    public void test_tickMillis_ZoneId() throws Exception {
+        Clock test = Clock.tickMillis(PARIS);
+        assertEquals(test.getZone(), PARIS);
+        assertEquals(test.instant().getNano() % 1000_000, 0);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void test_tickMillis_ZoneId_nullZoneId() {
+        Clock.tickMillis(null);
+    }
+    //-----------------------------------------------------------------------
     public void test_tickSeconds_ZoneId() throws Exception {
         Clock test = Clock.tickSeconds(PARIS);
         assertEquals(test.getZone(), PARIS);
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKDuration.java b/ojluni/src/test/java/time/tck/java/time/TCKDuration.java
index fb11a30..d72e4a6 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKDuration.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKDuration.java
@@ -523,6 +523,8 @@
                 {"PT-123456789S", -123456789, 0},
                 {"PT" + Long.MIN_VALUE + "S", Long.MIN_VALUE, 0},
 
+
+                {"PT0.1S", 0, 100000000},
                 {"PT1.1S", 1, 100000000},
                 {"PT1.12S", 1, 120000000},
                 {"PT1.123S", 1, 123000000},
@@ -533,6 +535,8 @@
                 {"PT1.12345678S", 1, 123456780},
                 {"PT1.123456789S", 1, 123456789},
 
+                // Android-removed: Disable this OpenJDK 11 test until java.time synced to 11. http://b/180577079
+                // {"PT-0.1S", -1, 1000000000 - 100000000},
                 {"PT-1.1S", -2, 1000000000 - 100000000},
                 {"PT-1.12S", -2, 1000000000 - 120000000},
                 {"PT-1.123S", -2, 1000000000 - 123000000},
@@ -546,6 +550,27 @@
                 {"PT" + Long.MAX_VALUE + ".123456789S", Long.MAX_VALUE, 123456789},
                 {"PT" + Long.MIN_VALUE + ".000000000S", Long.MIN_VALUE, 0},
 
+                // Android-removed: Disable this OpenJDK 11 test until java.time synced to 11. http://b/180577079
+                /*
+                {"PT12M", 12 * 60, 0},
+                {"PT12M0.35S", 12 * 60, 350000000},
+                {"PT12M1.35S", 12 * 60 + 1, 350000000},
+                {"PT12M-0.35S", 12 * 60 - 1, 1000000000 - 350000000},
+                {"PT12M-1.35S", 12 * 60 - 2, 1000000000 - 350000000},
+
+                {"PT12H", 12 * 3600, 0},
+                {"PT12H0.35S", 12 * 3600, 350000000},
+                {"PT12H1.35S", 12 * 3600 + 1, 350000000},
+                {"PT12H-0.35S", 12 * 3600 - 1, 1000000000 - 350000000},
+                {"PT12H-1.35S", 12 * 3600 - 2, 1000000000 - 350000000},
+
+                {"P12D", 12 * 24 * 3600, 0},
+                {"P12DT0.35S", 12 * 24 * 3600, 350000000},
+                {"P12DT1.35S", 12 * 24 * 3600 + 1, 350000000},
+                {"P12DT-0.35S", 12 * 24 * 3600 - 1, 1000000000 - 350000000},
+                {"P12DT-1.35S", 12 * 24 * 3600 - 2, 1000000000 - 350000000},
+                 */
+
                 {"PT01S", 1, 0},
                 {"PT001S", 1, 0},
                 {"PT000S", 0, 0},
@@ -2602,10 +2627,12 @@
     //-----------------------------------------------------------------------
     // toNanos()
     //-----------------------------------------------------------------------
-    @Test
+    // Android-changed: Disable this OpenJDK 11 test until java.time synced to 11. http://b/180577079
+    @Test(enabled = false)
     public void test_toNanos() {
-        Duration test = Duration.ofSeconds(321, 123456789);
-        assertEquals(test.toNanos(), 321123456789L);
+        assertEquals(Duration.ofSeconds(321, 123456789).toNanos(), 321123456789L);
+        assertEquals(Duration.ofNanos(Long.MAX_VALUE).toNanos(), 9223372036854775807L);
+        assertEquals(Duration.ofNanos(Long.MIN_VALUE).toNanos(), -9223372036854775808L);
     }
 
     @Test
@@ -2620,13 +2647,28 @@
         test.toNanos();
     }
 
+    // Android-changed: Disable this OpenJDK 11 test until java.time synced to 11. http://b/180577079
+    @Test(enabled = false)
+    public void test_toNanos_min() {
+        Duration test = Duration.ofSeconds(0, Long.MIN_VALUE);
+        assertEquals(test.toNanos(), Long.MIN_VALUE);
+    }
+
+    @Test(expectedExceptions=ArithmeticException.class)
+    public void test_toNanos_tooSmall() {
+        Duration test = Duration.ofSeconds(0, Long.MIN_VALUE).minusNanos(1);
+        test.toNanos();
+    }
+
     //-----------------------------------------------------------------------
     // toMillis()
     //-----------------------------------------------------------------------
-    @Test
+    // Android-changed: Disable this OpenJDK 11 test until java.time synced to 11. http://b/180577079
+    @Test(enabled = false)
     public void test_toMillis() {
-        Duration test = Duration.ofSeconds(321, 123456789);
-        assertEquals(test.toMillis(), 321000 + 123);
+        assertEquals(Duration.ofSeconds(321, 123456789).toMillis(), 321000 + 123);
+        assertEquals(Duration.ofMillis(Long.MAX_VALUE).toMillis(), 9223372036854775807L);
+        assertEquals(Duration.ofMillis(Long.MIN_VALUE).toMillis(), -9223372036854775808L);
     }
 
     @Test
@@ -2641,6 +2683,19 @@
         test.toMillis();
     }
 
+    // Android-changed: Disable this OpenJDK 11 test until java.time synced to 11. http://b/180577079
+    @Test(enabled = false)
+    public void test_toMillis_min() {
+        Duration test = Duration.ofSeconds(Long.MIN_VALUE / 1000, (Long.MIN_VALUE % 1000) * 1000000);
+        assertEquals(test.toMillis(), Long.MIN_VALUE);
+    }
+
+    @Test(expectedExceptions=ArithmeticException.class)
+    public void test_toMillis_tooSmall() {
+        Duration test = Duration.ofSeconds(Long.MIN_VALUE / 1000, ((Long.MIN_VALUE % 1000) - 1) * 1000000);
+        test.toMillis();
+    }
+
     //-----------------------------------------------------------------------
     // toSeconds()
     //-----------------------------------------------------------------------
@@ -3001,6 +3056,10 @@
             {-1, 0, "PT-1S"},
             {-1, 1000, "PT-0.999999S"},
             {-1, 900000000, "PT-0.1S"},
+            // Android-removed: Disable this OpenJDK 11 test until java.time synced to 11. http://b/180577079
+            // {-60, 100_000_000, "PT-59.9S"},
+            // {-59, -900_000_000, "PT-59.9S"},
+            // {-60, -100_000_000, "PT-1M-0.1S"},
             {Long.MAX_VALUE, 0, "PT" + (Long.MAX_VALUE / 3600) + "H" +
                     ((Long.MAX_VALUE % 3600) / 60) + "M" + (Long.MAX_VALUE % 60) + "S"},
             {Long.MIN_VALUE, 0, "PT" + (Long.MIN_VALUE / 3600) + "H" +
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKInstant.java b/ojluni/src/test/java/time/tck/java/time/TCKInstant.java
index 862f7549..90a79027 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKInstant.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKInstant.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -639,6 +639,12 @@
                 {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 123_456_789), NINETY_MINS, Instant.ofEpochSecond(86400 + 0, 0)},
                 {Instant.ofEpochSecond(86400 + 7200 + 60 + 1, 123_456_789), NINETY_MINS, Instant.ofEpochSecond(86400 + 5400, 0)},
                 {Instant.ofEpochSecond(86400 + 10800 + 60 + 1, 123_456_789), NINETY_MINS, Instant.ofEpochSecond(86400 + 10800, 0)},
+
+                {Instant.ofEpochSecond(-86400 - 3600 - 60 - 1, 123_456_789), MINUTES, Instant.ofEpochSecond(-86400 - 3600 - 120, 0 )},
+                {Instant.ofEpochSecond(-86400 - 3600 - 60 - 1, 123_456_789), MICROS, Instant.ofEpochSecond(-86400 - 3600 - 60 - 1, 123_456_000)},
+
+                {Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 0), SECONDS, Instant.ofEpochSecond(86400 + 3600 + 60 + 1, 0)},
+                {Instant.ofEpochSecond(-86400 - 3600 - 120, 0), MINUTES, Instant.ofEpochSecond(-86400 - 3600 - 120, 0)},
         };
     }
     @Test(dataProvider="truncatedToValid")
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java b/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java
index 7de2e02..faf81d1 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKLocalDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -86,8 +86,6 @@
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
 
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.DayOfWeek;
@@ -103,7 +101,9 @@
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
+import java.time.chrono.Era;
 import java.time.chrono.IsoChronology;
+import java.time.chrono.IsoEra;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
@@ -120,6 +120,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
@@ -135,6 +137,7 @@
 
     private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
     private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
+    private static final ZoneOffset OFFSET_MTWO = ZoneOffset.ofHours(-2);
     private static final ZoneId ZONE_PARIS = ZoneId.of("Europe/Paris");
     private static final ZoneId ZONE_GAZA = ZoneId.of("Asia/Gaza");
 
@@ -478,6 +481,48 @@
         return date.withDayOfMonth(date.getMonth().length(isIsoLeap(date.getYear())));
     }
 
+     //-----------------------------------------------------------------------
+     // ofInstant()
+     //-----------------------------------------------------------------------
+     @DataProvider(name="instantFactory")
+     Object[][] data_instantFactory() {
+         return new Object[][] {
+                 {Instant.ofEpochSecond(86400 + 3600 + 120 + 4, 500), ZONE_PARIS, LocalDate.of(1970, 1, 2)},
+                 {Instant.ofEpochSecond(86400 + 3600 + 120 + 4, 500), OFFSET_MTWO, LocalDate.of(1970, 1, 1)},
+                 {Instant.ofEpochSecond(-86400 + 4, 500), OFFSET_PTWO, LocalDate.of(1969, 12, 31)},
+                 {OffsetDateTime.of(LocalDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0), ZoneOffset.UTC).toInstant(),
+                         ZoneOffset.UTC, LocalDate.MIN},
+                 {OffsetDateTime.of(LocalDateTime.of(Year.MAX_VALUE, 12, 31, 23, 59, 59, 999_999_999), ZoneOffset.UTC).toInstant(),
+                         ZoneOffset.UTC, LocalDate.MAX},
+         };
+     }
+
+     @Test(dataProvider="instantFactory")
+     public void factory_ofInstant(Instant instant, ZoneId zone, LocalDate expected) {
+         LocalDate test = LocalDate.ofInstant(instant, zone);
+         assertEquals(test, expected);
+     }
+
+     @Test(expectedExceptions=DateTimeException.class)
+     public void factory_ofInstant_instantTooBig() {
+         LocalDate.ofInstant(Instant.MAX, OFFSET_PONE);
+     }
+
+     @Test(expectedExceptions=DateTimeException.class)
+     public void factory_ofInstant_instantTooSmall() {
+         LocalDate.ofInstant(Instant.MIN, OFFSET_PONE);
+     }
+
+     @Test(expectedExceptions=NullPointerException.class)
+     public void factory_ofInstant_nullInstant() {
+         LocalDate.ofInstant((Instant) null, ZONE_GAZA);
+     }
+
+     @Test(expectedExceptions=NullPointerException.class)
+     public void factory_ofInstant_nullZone() {
+         LocalDate.ofInstant(Instant.EPOCH, (ZoneId) null);
+     }
+
     //-----------------------------------------------------------------------
     // ofEpochDay()
     //-----------------------------------------------------------------------
@@ -1246,13 +1291,37 @@
     public void test_plusWeeks_invalidMaxMinusMin() {
         LocalDate.of(Year.MAX_VALUE, 12, 25).plusWeeks(Long.MIN_VALUE);
     }
-
-    @Test
-    public void test_plusDays_normal() {
-        LocalDate t = TEST_2007_07_15.plusDays(1);
-        assertEquals(t, LocalDate.of(2007, 7, 16));
+    //-----------------------------------------------------------------------
+    @DataProvider(name="PlusDays")
+    Object[][] provider_plusDays() {
+        return new Object[][] {
+                {LocalDate.of(2007, 7, 15), 1, LocalDate.of(2007, 7, 16)},
+                {LocalDate.of(2007, 7, 15), 17, LocalDate.of(2007, 8, 1)},
+                {LocalDate.of(2007, 12, 31), 1, LocalDate.of(2008, 1, 1)},
+                {LocalDate.of(2007, 1, 1), 58, LocalDate.of(2007, 2, 28)},
+                {LocalDate.of(2007, 1, 1), 59, LocalDate.of(2007, 3, 1)},
+                {LocalDate.of(2008, 1, 1), 60, LocalDate.of(2008, 3, 1)},
+                {LocalDate.of(2007, 2, 1), 27, LocalDate.of(2007, 2, 28)},
+                {LocalDate.of(2007, 2, 1), 28, LocalDate.of(2007, 3, 1)},
+                {LocalDate.of(2007, 1, 1), 29, LocalDate.of(2007, 1, 30)},
+                {LocalDate.of(2007, 1, 1), 30, LocalDate.of(2007, 1, 31)},
+                {LocalDate.of(2007, 1, 15), 13, LocalDate.of(2007, 1, 28)},
+                {LocalDate.of(2007, 1, 15), 14, LocalDate.of(2007, 1, 29)},
+                {LocalDate.of(2007, 1, 15), 15, LocalDate.of(2007, 1, 30)},
+                {LocalDate.of(2007, 1, 15), 16, LocalDate.of(2007, 1, 31)},
+                {LocalDate.of(2007, 2, 15), 13, LocalDate.of(2007, 2, 28)},
+                {LocalDate.of(2007, 2, 15), 14, LocalDate.of(2007, 3, 1)},
+                {LocalDate.of(2007, 2, 15), 15, LocalDate.of(2007, 3, 2)},
+                {LocalDate.of(2007, 2, 15), 16, LocalDate.of(2007, 3, 3)},
+        };
     }
 
+    @Test(dataProvider="PlusDays")
+    public void test_plusDays_normal(LocalDate input, int amountsToAdd, LocalDate expected) {
+        LocalDate actual = input.plusDays(amountsToAdd);
+        assertEquals(actual, expected);
+     }
+
     @Test
     public void test_plusDays_overMonths() {
         LocalDate t = TEST_2007_07_15.plusDays(62);
@@ -2118,6 +2187,31 @@
     }
 
     //-----------------------------------------------------------------------
+    // toEpochSecond
+    //-----------------------------------------------------------------------
+    @DataProvider(name="epochSecond")
+    Object[][] provider_toEpochSecond() {
+        return new Object[][] {
+            {LocalDate.of(1858, 11, 17).toEpochSecond(LocalTime.MIDNIGHT, OFFSET_PONE), -3506720400L},
+            {LocalDate.of(1, 1, 1).toEpochSecond(LocalTime.NOON, OFFSET_PONE), -62135557200L},
+            {LocalDate.of(1995, 9, 27).toEpochSecond(LocalTime.of(5, 30), OFFSET_PTWO), 812172600L},
+            {LocalDate.of(1970, 1, 1).toEpochSecond(LocalTime.MIDNIGHT, OFFSET_MTWO), 7200L},
+            {LocalDate.of(-1, 12, 31).toEpochSecond(LocalTime.NOON, OFFSET_PONE), -62167266000L},
+            {LocalDate.of(1, 1, 1).toEpochSecond(LocalTime.MIDNIGHT, OFFSET_PONE),
+                    Instant.ofEpochSecond(-62135600400L).getEpochSecond()},
+            {LocalDate.of(1995, 9, 27).toEpochSecond(LocalTime.NOON, OFFSET_PTWO),
+                    Instant.ofEpochSecond(812196000L).getEpochSecond()},
+            {LocalDate.of(1995, 9, 27).toEpochSecond(LocalTime.of(5, 30), OFFSET_MTWO),
+                    LocalDateTime.of(1995, 9, 27, 5, 30).toEpochSecond(OFFSET_MTWO)},
+        };
+    }
+
+    @Test(dataProvider="epochSecond")
+    public void test_toEpochSecond(long actual, long expected) {
+        assertEquals(actual, expected);
+    }
+
+    //-----------------------------------------------------------------------
     // compareTo()
     //-----------------------------------------------------------------------
     @Test
@@ -2288,4 +2382,227 @@
         return LocalDate.of(year, month, day);
     }
 
+    //-----------------------------------------------------------------
+    // getEra()
+    // ----------------------------------------------------------------
+    @Test
+    public void test_getEra() {
+        // Android-changed: getEra() returns Era for backward compatibility.
+        // IsoEra isoEra = LocalDate.MAX.getEra();
+        Era isoEra = LocalDate.MAX.getEra();
+        assertSame(isoEra,IsoEra.CE);
+        assertSame(LocalDate.MIN.getEra(),IsoEra.BCE);
+    }
+
+    //-----------------------------------------------------------------
+    // datesUntil()
+    // ----------------------------------------------------------------
+    @Test
+    public void test_datesUntil() {
+        assertEquals(
+                date(2015, 9, 29).datesUntil(date(2015, 10, 3)).collect(
+                        Collectors.toList()), Arrays.asList(date(2015, 9, 29),
+                        date(2015, 9, 30), date(2015, 10, 1), date(2015, 10, 2)));
+        assertEquals(date(2015, 9, 29).datesUntil(date(2015, 10, 3), Period.ofDays(2))
+                .collect(Collectors.toList()), Arrays.asList(date(2015, 9, 29),
+                date(2015, 10, 1)));
+        assertEquals(date(2015, 1, 31).datesUntil(date(2015, 6, 1), Period.ofMonths(1))
+                .collect(Collectors.toList()), Arrays.asList(date(2015, 1, 31),
+                date(2015, 2, 28), date(2015, 3, 31), date(2015, 4, 30),
+                date(2015, 5, 31)));
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void test_datesUntil_nullEnd() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void test_datesUntil_nullEndStep() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(null, Period.ofDays(1));
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void test_datesUntil_nullStep() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, null);
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void test_datesUntil_endBeforeStart() {
+        date(2015, 1, 31).datesUntil(date(2015, 1, 30));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void test_datesUntil_endBeforeStartPositiveStep() {
+        date(2015, 1, 31).datesUntil(date(2015, 1, 30), Period.of(1, 0, 0));
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void test_datesUntil_endAfterStartNegativeStep() {
+        date(2015, 1, 30).datesUntil(date(2015, 1, 31), Period.of(0, -1, -1));
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void test_datesUntil_zeroStep() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, Period.ZERO);
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void test_datesUntil_oppositeSign() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, Period.of(1, 0, -1));
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void test_datesUntil_oppositeSign2() {
+        LocalDate date = date(2015, 1, 31);
+        date.datesUntil(date, Period.of(0, -1, 1));
+    }
+
+    @DataProvider(name="datesUntil")
+    public Object[][] provider_datesUntil() {
+        return new Object[][] {
+                // Android-removed: The range to max date takes too much memory and time.
+                /*
+                {MIN_DATE, MIN_DATE},
+                {MIN_DATE, MAX_DATE},
+                {MAX_DATE, MAX_DATE},
+                */
+                {date(2015,10,1), date(2015,10,2)},
+                {date(2015,10,1), date(2015,11,1)},
+                {date(2015,10,31), date(2015,11,1)},
+                // Android-removed: The range to max date takes too much memory and time.
+                /*
+                {date(2015,10,1), MAX_DATE},
+                {MIN_DATE, date(2015,10,1)}
+                */
+        };
+    }
+
+    @Test(dataProvider = "datesUntil")
+    public void test_datesUntil_count(LocalDate start, LocalDate end) {
+        assertEquals(start.datesUntil(end).count(), start.until(end, ChronoUnit.DAYS));
+        assertEquals(start.datesUntil(end, Period.ofDays(1)).count(),
+                start.until(end, ChronoUnit.DAYS));
+    }
+
+    @DataProvider(name="datesUntilSteps")
+    public Object[][] provider_datesUntil_steps() {
+        List<Object[]> data = new ArrayList<>(Arrays.asList(new Object[][] {
+            // Android-removed: The range to max date takes too much memory and time.
+            /*
+            {MIN_DATE, MAX_DATE, Period.ofYears(Year.MAX_VALUE)},
+            {MIN_DATE, MAX_DATE, Period.ofDays(2)},
+            {MIN_DATE, MAX_DATE, Period.of(1,2,3)},
+            {MIN_DATE, MAX_DATE, Period.of(1,2,1000000)},
+            {MIN_DATE, MAX_DATE, Period.of(1,1000000,3)},
+            {MIN_DATE, MAX_DATE, Period.of(1000000,2,3)},
+            {MIN_DATE, MIN_DATE.plusMonths(1), Period.ofMonths(1)},
+            {MIN_DATE, date(Year.MIN_VALUE, 2, 2), Period.ofMonths(1)},
+            {MIN_DATE, date(Year.MIN_VALUE, 8, 9), Period.of(0, 1, 1)},
+            {MIN_DATE, MAX_DATE.minusYears(1), Period.ofYears(Year.MAX_VALUE)},
+            {MAX_DATE.minusMonths(1), MAX_DATE, Period.ofMonths(1)},
+            {date(Year.MAX_VALUE, 2, 20), MAX_DATE, Period.of(0, 1, 1)},
+            */
+            {date(2015,1,1), date(2016,1,1), Period.ofYears(1)},
+            {date(2015,1,1), date(2016,1,1), Period.ofDays(365)},
+            {date(2015,1,1), date(2016,1,1), Period.ofDays(366)},
+            {date(2015,1,1), date(2016,1,1), Period.ofDays(4)},
+            {date(2015,1,1), date(2016,1,1), Period.of(0,1,2)},
+            {date(2015,1,1), date(2016,1,1), Period.ofMonths(1)},
+            {date(2015,1,1), date(2016,1,1), Period.ofMonths(12)},
+            {date(2015,1,1), date(2016,1,2), Period.ofMonths(12)},
+            {date(2015,1,1), date(2016,1,1), Period.of(0, 11, 30)},
+            {date(2015,1,1), date(2015,12,31), Period.of(0, 11, 30)},
+            {date(2015,1,31), date(2015,12,31), Period.ofMonths(2)},
+            {date(2015,1,31), date(2015,12,1), Period.ofMonths(2)},
+            {date(2015,1,31), date(2015,11,30), Period.ofMonths(2)},
+            {date(2015,1,31), date(2030,11,30), Period.of(1,30,365)},
+            {date(2015,1,31), date(2043,1,31), Period.of(4,0,0)},
+            {date(2015,1,31), date(2043,2,1), Period.of(4,0,0)},
+            {date(2015,1,31), date(2043,1,31), Period.of(3,11,30)},
+            {date(2015,1,31), date(2043,2,1), Period.of(3,11,30)},
+            {date(2015,1,31), date(2043,1,31), Period.of(0,0,1460)},
+            {date(2015,1,31), date(2043,1,31), Period.of(0,0,1461)},
+            {date(2015,1,31), date(2043,2,1), Period.of(0,0,1461)},
+            // Android-removed: The range to max date takes too much memory and time.
+            /*
+            {date(2015,1,31), MAX_DATE, Period.of(10,100,1000)},
+            {date(2015,1,31), MAX_DATE, Period.of(1000000,10000,100000)},
+            {date(2015,1,31), MAX_DATE, Period.ofDays(10000000)},
+            {date(2015,1,31), MAX_DATE, Period.ofDays(Integer.MAX_VALUE)},
+            {date(2015,1,31), MAX_DATE, Period.ofMonths(Integer.MAX_VALUE)},
+            {date(2015,1,31), MAX_DATE, Period.ofYears(Integer.MAX_VALUE)}
+            */
+        }));
+        LocalDate start = date(2014, 1, 15);
+        LocalDate end = date(2015, 3, 4);
+        for (int months : new int[] { 0, 1, 2, 3, 5, 7, 12, 13 }) {
+            for (int days : new int[] { 0, 1, 2, 3, 5, 10, 17, 27, 28, 29, 30, 31, 32, 57, 58, 59,
+                    60, 61, 62, 70, 80, 90 }) {
+                if (months > 0 || days > 0)
+                    data.add(new Object[] { start, end, Period.of(0, months, days) });
+            }
+        }
+        for (int days = 27; days < 100; days++) {
+            data.add(new Object[] { start, start.plusDays(days), Period.ofMonths(1) });
+        }
+        return data.toArray(new Object[data.size()][]);
+    }
+
+    @Test(dataProvider="datesUntilSteps")
+    public void test_datesUntil_step(LocalDate start, LocalDate end, Period step) {
+        assertEquals(start.datesUntil(start, step).count(), 0);
+        long count = start.datesUntil(end, step).count();
+        assertTrue(count > 0);
+        // the last value must be before the end date
+        assertTrue(start.plusMonths(step.toTotalMonths()*(count-1)).plusDays(step.getDays()*(count-1)).isBefore(end));
+        try {
+            // the next after the last value must be either invalid or not before the end date
+            assertFalse(start.plusMonths(step.toTotalMonths()*count).plusDays(step.getDays()*count).isBefore(end));
+        } catch (ArithmeticException | DateTimeException e) {
+            // ignore: possible overflow for the next value is ok
+        }
+        if(count < 1000) {
+            assertTrue(start.datesUntil(end, step).allMatch(date -> !date.isBefore(start) && date.isBefore(end)));
+            List<LocalDate> list = new ArrayList<>();
+            for(long i=0; i<count; i++) {
+                list.add(start.plusMonths(step.toTotalMonths()*i).plusDays(step.getDays()*i));
+            }
+            assertEquals(start.datesUntil(end, step).collect(Collectors.toList()), list);
+        }
+
+        // swap end and start and negate the Period
+        count = end.datesUntil(start, step.negated()).count();
+        assertTrue(count > 0);
+        // the last value must be after the start date
+        assertTrue(end.minusMonths(step.toTotalMonths()*(count-1)).minusDays(step.getDays()*(count-1)).isAfter(start));
+        try {
+            // the next after the last value must be either invalid or not after the start date
+            assertFalse(end.minusMonths(step.toTotalMonths()*count).minusDays(step.getDays()*count).isAfter(start));
+        } catch (ArithmeticException | DateTimeException e) {
+            // ignore: possible overflow for the next value is ok
+        }
+        if(count < 1000) {
+            assertTrue(end.datesUntil(start, step.negated()).allMatch(date -> date.isAfter(start) && !date.isAfter(end)));
+            List<LocalDate> list = new ArrayList<>();
+            for(long i=0; i<count; i++) {
+                list.add(end.minusMonths(step.toTotalMonths()*i).minusDays(step.getDays()*i));
+            }
+            assertEquals(end.datesUntil(start, step.negated()).collect(Collectors.toList()), list);
+        }
+    }
+
+    @Test
+    public void test_datesUntil_staticType() {
+        // Test the types of the Stream and elements of the stream
+        LocalDate date = date(2015, 2, 10);
+        Stream<LocalDate> stream = date.datesUntil(date.plusDays(5));
+        long sum = stream.mapToInt(LocalDate::getDayOfMonth).sum();
+        assertEquals(sum, 60, "sum of 10, 11, 12, 13, 14 is wrong");
+    }
 }
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKLocalDateTime.java b/ojluni/src/test/java/time/tck/java/time/TCKLocalDateTime.java
index 40ed534..487cd80 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKLocalDateTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKLocalDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -107,11 +107,10 @@
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.DayOfWeek;
+import java.time.Duration;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -260,16 +259,17 @@
     //-----------------------------------------------------------------------
     @Test(timeOut=30000)  // TODO: remove when time zone loading is faster
     public void now() {
+        final long DELTA = 20_000_000_000L;    // 20 seconds of nanos leeway
         LocalDateTime expected = LocalDateTime.now(Clock.systemDefaultZone());
         LocalDateTime test = LocalDateTime.now();
         long diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay());
-        if (diff >= 100000000) {
+        if (diff >= DELTA) {
             // may be date change
             expected = LocalDateTime.now(Clock.systemDefaultZone());
             test = LocalDateTime.now();
             diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay());
         }
-        assertTrue(diff < 100000000);  // less than 0.1 secs
+        assertTrue(diff < DELTA);
     }
 
     //-----------------------------------------------------------------------
@@ -285,14 +285,8 @@
         ZoneId zone = ZoneId.of("UTC+01:02:03");
         LocalDateTime expected = LocalDateTime.now(Clock.system(zone));
         LocalDateTime test = LocalDateTime.now(zone);
-        for (int i = 0; i < 100; i++) {
-            if (expected.equals(test)) {
-                return;
-            }
-            expected = LocalDateTime.now(Clock.system(zone));
-            test = LocalDateTime.now(zone);
-        }
-        assertEquals(test, expected);
+        assertEquals(Duration.between(expected, test).truncatedTo(ChronoUnit.SECONDS),
+                Duration.ZERO);
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java b/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java
index f669a7c..8477b29 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKLocalTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -244,14 +244,8 @@
         ZoneId zone = ZoneId.of("UTC+01:02:03");
         LocalTime expected = LocalTime.now(Clock.system(zone));
         LocalTime test = LocalTime.now(zone);
-        for (int i = 0; i < 100; i++) {
-            if (expected.equals(test)) {
-                return;
-            }
-            expected = LocalTime.now(Clock.system(zone));
-            test = LocalTime.now(zone);
-        }
-        assertEquals(test, expected);
+        assertEquals(Duration.between(expected, test).truncatedTo(ChronoUnit.SECONDS),
+                Duration.ZERO);
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java b/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java
index b2f8024..c940ed6 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKOffsetDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -104,10 +104,6 @@
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.Duration;
@@ -239,16 +235,17 @@
     //-----------------------------------------------------------------------
     @Test
     public void now() {
+        final long DELTA = 20_000_000_000L;    // 20 seconds of nanos leeway
         OffsetDateTime expected = OffsetDateTime.now(Clock.systemDefaultZone());
         OffsetDateTime test = OffsetDateTime.now();
         long diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay());
-        if (diff >= 100000000) {
+        if (diff >= DELTA) {
             // may be date change
             expected = OffsetDateTime.now(Clock.systemDefaultZone());
             test = OffsetDateTime.now();
             diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay());
         }
-        assertTrue(diff < 100000000);  // less than 0.1 secs
+        assertTrue(diff < DELTA);
     }
 
     //-----------------------------------------------------------------------
@@ -475,24 +472,12 @@
     //-----------------------------------------------------------------------
     @Test(expectedExceptions=NullPointerException.class)
     public void constructor_nullTime() throws Throwable  {
-        Constructor<OffsetDateTime> con = OffsetDateTime.class.getDeclaredConstructor(LocalDateTime.class, ZoneOffset.class);
-        con.setAccessible(true);
-        try {
-            con.newInstance(null, OFFSET_PONE);
-        } catch (InvocationTargetException ex) {
-            throw ex.getCause();
-        }
+        OffsetDateTime.of(null, OFFSET_PONE);
     }
 
     @Test(expectedExceptions=NullPointerException.class)
     public void constructor_nullOffset() throws Throwable  {
-        Constructor<OffsetDateTime> con = OffsetDateTime.class.getDeclaredConstructor(LocalDateTime.class, ZoneOffset.class);
-        con.setAccessible(true);
-        try {
-            con.newInstance(LocalDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30)), null);
-        } catch (InvocationTargetException ex) {
-            throw ex.getCause();
-        }
+        OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2008, 6, 30), LocalTime.of(11, 30)), null);
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java b/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java
index e3bb590..fde9bd0 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKOffsetTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -89,10 +89,6 @@
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.Instant;
@@ -136,6 +132,7 @@
     private static final ZoneId ZONE_GAZA = ZoneId.of("Asia/Gaza");
     private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
     private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
+    private static final ZoneOffset OFFSET_MTWO = ZoneOffset.ofHours(-2);
     private static final LocalDate DATE = LocalDate.of(2008, 12, 3);
 
     // Android-changed: This was originally non-static and initialized in @BeforeMethod,
@@ -206,12 +203,19 @@
     //-----------------------------------------------------------------------
     @Test
     public void now() {
+        final long DELTA = 20_000_000_000L;    // 20 seconds of nanos leeway
         ZonedDateTime nowDT = ZonedDateTime.now();
 
         OffsetTime expected = OffsetTime.now(Clock.systemDefaultZone());
         OffsetTime test = OffsetTime.now();
         long diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay());
-        assertTrue(diff < 100000000);  // less than 0.1 secs
+        if (diff >= DELTA) {
+            // may be date change
+            expected = OffsetTime.now(Clock.systemDefaultZone());
+            test = OffsetTime.now();
+            diff = Math.abs(test.toLocalTime().toNanoOfDay() - expected.toLocalTime().toNanoOfDay());
+        }
+        assertTrue(diff < DELTA);
         assertEquals(test.getOffset(), nowDT.getOffset());
     }
 
@@ -463,28 +467,16 @@
     }
 
     //-----------------------------------------------------------------------
-    // constructor
+    // constructor via factory
     //-----------------------------------------------------------------------
     @Test(expectedExceptions=NullPointerException.class)
     public void constructor_nullTime() throws Throwable  {
-        Constructor<OffsetTime> con = OffsetTime.class.getDeclaredConstructor(LocalTime.class, ZoneOffset.class);
-        con.setAccessible(true);
-        try {
-            con.newInstance(null, OFFSET_PONE);
-        } catch (InvocationTargetException ex) {
-            throw ex.getCause();
-        }
+        OffsetTime.of(null, OFFSET_PONE);
     }
 
     @Test(expectedExceptions=NullPointerException.class)
     public void constructor_nullOffset() throws Throwable  {
-        Constructor<OffsetTime> con = OffsetTime.class.getDeclaredConstructor(LocalTime.class, ZoneOffset.class);
-        con.setAccessible(true);
-        try {
-            con.newInstance(LocalTime.of(11, 30, 0, 0), null);
-        } catch (InvocationTargetException ex) {
-            throw ex.getCause();
-        }
+       OffsetTime.of(LocalTime.of(11, 30, 0, 0), null);
     }
 
     //-----------------------------------------------------------------------
@@ -1148,6 +1140,29 @@
     }
 
     //-----------------------------------------------------------------------
+    // toEpochSecond()
+    //-----------------------------------------------------------------------
+    @DataProvider(name="epochSecond")
+    Object[][] provider_toEpochSecond() {
+        return new Object[][] {
+        {OffsetTime.of(0, 0, 0, 0, OFFSET_PTWO).toEpochSecond(LocalDate.of(1970, 1, 1)), -7200L},
+        {OffsetTime.of(11, 30, 0, 0, OFFSET_MTWO).toEpochSecond(LocalDate.of(1995, 9, 27)), 812208600L},
+        {OffsetTime.of(0, 0, 0, 0, OFFSET_PONE).toEpochSecond(LocalDate.of(1970, 1, 1)),
+                Instant.ofEpochSecond(-3600).getEpochSecond()},
+        {OffsetTime.of(11, 30, 0, 0, OFFSET_PTWO).toEpochSecond(LocalDate.of(1965, 12, 31)),
+                Instant.ofEpochSecond(-126282600L).getEpochSecond()},
+        {OffsetTime.of(11, 30, 0, 0, OFFSET_MTWO).toEpochSecond(LocalDate.of(1970, 1, 1)),
+                OffsetDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.of(11, 30), OFFSET_MTWO)
+                              .toEpochSecond()},
+        };
+    }
+
+    @Test(dataProvider="epochSecond")
+    public void test_toEpochSecond(long actual, long expected) {
+        assertEquals(actual, expected);
+    }
+
+    //-----------------------------------------------------------------------
     // compareTo()
     //-----------------------------------------------------------------------
     @Test
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKZoneOffset.java b/ojluni/src/test/java/time/tck/java/time/TCKZoneOffset.java
index c121079..7646643 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKZoneOffset.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKZoneOffset.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -419,6 +419,21 @@
         ZoneOffset.ofHoursMinutesSeconds(-19, 0, 0);
     }
 
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_int_hours_minutes_seconds_minutesMinValue() {
+        ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, -1);
+    }
+
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_int_hours_minutes_seconds_secondsMinValue() {
+        ZoneOffset.ofHoursMinutesSeconds(0, 0, Integer.MIN_VALUE);
+    }
+
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_int_hours_minutes_seconds_minutesAndSecondsMinValue() {
+        ZoneOffset.ofHoursMinutesSeconds(0, Integer.MIN_VALUE, Integer.MIN_VALUE);
+    }
+
     //-----------------------------------------------------------------------
     @Test
     public void test_factory_ofTotalSeconds() {
@@ -437,6 +452,11 @@
         ZoneOffset.ofTotalSeconds(-18 * 60 * 60 - 1);
     }
 
+    @Test(expectedExceptions=DateTimeException.class)
+    public void test_factory_ofTotalSeconds_minValue() {
+        ZoneOffset.ofTotalSeconds(Integer.MIN_VALUE);
+    }
+
     //-----------------------------------------------------------------------
     // from()
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/test/java/time/tck/java/time/TCKZonedDateTime.java b/ojluni/src/test/java/time/tck/java/time/TCKZonedDateTime.java
index fb743e8..8ca935c 100644
--- a/ojluni/src/test/java/time/tck/java/time/TCKZonedDateTime.java
+++ b/ojluni/src/test/java/time/tck/java/time/TCKZonedDateTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -253,14 +253,8 @@
         ZoneId zone = ZoneId.of("UTC+01:02:03");
         ZonedDateTime expected = ZonedDateTime.now(Clock.system(zone));
         ZonedDateTime test = ZonedDateTime.now(zone);
-        for (int i = 0; i < 100; i++) {
-            if (expected.equals(test)) {
-                return;
-            }
-            expected = ZonedDateTime.now(Clock.system(zone));
-            test = ZonedDateTime.now(zone);
-        }
-        assertEquals(test, expected);
+        assertEquals(Duration.between(expected, test).truncatedTo(ChronoUnit.SECONDS),
+                Duration.ZERO);
     }
 
     //-----------------------------------------------------------------------
@@ -750,7 +744,7 @@
                 {"2012-06-30T12:30:40Z[GMT]", 2012, 6, 30, 12, 30, 40, 0, "GMT"},
                 {"2012-06-30T12:30:40Z[UT]", 2012, 6, 30, 12, 30, 40, 0, "UT"},
                 {"2012-06-30T12:30:40Z[UTC]", 2012, 6, 30, 12, 30, 40, 0, "UTC"},
-                {"2012-06-30T12:30:40+01:00[Z]", 2012, 6, 30, 12, 30, 40, 0, "Z"},
+                {"2012-06-30T12:30:40+01:00[Z]", 2012, 6, 30, 11, 30, 40, 0, "Z"},
                 {"2012-06-30T12:30:40+01:00[+01:00]", 2012, 6, 30, 12, 30, 40, 0, "+01:00"},
                 {"2012-06-30T12:30:40+01:00[GMT+01:00]", 2012, 6, 30, 12, 30, 40, 0, "GMT+01:00"},
                 {"2012-06-30T12:30:40+01:00[UT+01:00]", 2012, 6, 30, 12, 30, 40, 0, "UT+01:00"},
@@ -760,6 +754,7 @@
                 {"2012-06-30T12:30:40-01:00[UT-01:00]", 2012, 6, 30, 12, 30, 40, 0, "UT-01:00"},
                 {"2012-06-30T12:30:40-01:00[UTC-01:00]", 2012, 6, 30, 12, 30, 40, 0, "UTC-01:00"},
                 {"2012-06-30T12:30:40+01:00[Europe/London]", 2012, 6, 30, 12, 30, 40, 0, "Europe/London"},
+                {"2012-06-30T12:30:40+01", 2012, 6, 30, 12, 30, 40, 0, "+01:00"},
         };
     }
 
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/CopticChronology.java b/ojluni/src/test/java/time/tck/java/time/chrono/CopticChronology.java
index c72b737..626b286 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/CopticChronology.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/CopticChronology.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/CopticDate.java b/ojluni/src/test/java/time/tck/java/time/chrono/CopticDate.java
index a296c59..09e2e47 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/CopticDate.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/CopticDate.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/CopticEra.java b/ojluni/src/test/java/time/tck/java/time/chrono/CopticEra.java
index c1d7f56..be78ff5 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/CopticEra.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/CopticEra.java
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoPeriod.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoPeriod.java
index 58a1c35..b8b1bd2 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoPeriod.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronoPeriod.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,7 @@
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+@Test
 public class TCKChronoPeriod {
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronology.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronology.java
index 5164182..e9b2d37 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronology.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,11 +68,16 @@
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
-import java.time.ZoneId;
 import java.time.Clock;
 import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.chrono.ChronoLocalDate;
 import java.time.chrono.Chronology;
+import java.time.chrono.Era;
 import java.time.chrono.HijrahChronology;
 import java.time.chrono.HijrahEra;
 import java.time.chrono.IsoChronology;
@@ -97,6 +102,14 @@
 @Test
 public class TCKChronology {
 
+    private static final ZoneOffset OFFSET_P0100 = ZoneOffset.ofHours(1);
+    private static final ZoneOffset OFFSET_M0100 = ZoneOffset.ofHours(-1);
+
+    private static final int YDIFF_MEIJI = 1867;
+    private static final int YDIFF_SHOWA = 1925;
+    private static final int YDIFF_HEISEI = 1988;
+    private static final int YDIFF_MINGUO = 1911;
+    private static final int YDIFF_THAIBUDDHIST = 543;
     //-----------------------------------------------------------------------
     // regular data factory for ID and calendarType of available calendars
     //-----------------------------------------------------------------------
@@ -325,7 +338,7 @@
         }
     }
 
-    @Test(expectedExceptions=DateTimeException.class)
+    @Test(expectedExceptions = DateTimeException.class)
     public void test_lookupLocale() {
         Locale.Builder builder = new Locale.Builder().setLanguage("en").setRegion("CA");
         builder.setUnicodeLocaleKeyword("ca", "xxx");
@@ -339,4 +352,78 @@
         Chronology chrono = Chronology.of("FooFoo");
     }
 
+    @DataProvider(name = "epochSecond_dataProvider")
+    Object[][]  data_epochSecond() {
+        return new Object[][] {
+                {JapaneseChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {JapaneseChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {JapaneseChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {HijrahChronology.INSTANCE, 1434, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {MinguoChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {ThaiBuddhistChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+
+        };
+    }
+
+    @Test(dataProvider = "epochSecond_dataProvider")
+    public void test_epochSecond(Chronology chrono, int y, int m, int d, int h, int min, int s, ZoneOffset offset) {
+        ChronoLocalDate chronoLd = chrono.date(y, m, d);
+        assertEquals(chrono.epochSecond(y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(LocalDate.from(chronoLd), LocalTime.of(h, min, s), offset)
+                                   .toEpochSecond());
+    }
+
+    @DataProvider(name = "era_epochSecond_dataProvider")
+    Object[][]  data_era_epochSecond() {
+        return new Object[][] {
+                {JapaneseChronology.INSTANCE, JapaneseEra.MEIJI, 1873 - YDIFF_MEIJI, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {JapaneseChronology.INSTANCE, JapaneseEra.SHOWA, 1928 - YDIFF_SHOWA, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {JapaneseChronology.INSTANCE, JapaneseEra.HEISEI, 1989 - YDIFF_HEISEI, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {HijrahChronology.INSTANCE, HijrahEra.AH, 1434, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, MinguoEra.BEFORE_ROC, 1873 - YDIFF_MINGUO, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, MinguoEra.ROC, 1928 - YDIFF_MINGUO, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {MinguoChronology.INSTANCE, MinguoEra.ROC, 1989 - YDIFF_MINGUO, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1873 + YDIFF_THAIBUDDHIST, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1928 + YDIFF_THAIBUDDHIST, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {ThaiBuddhistChronology.INSTANCE, ThaiBuddhistEra.BE, 1989 + YDIFF_THAIBUDDHIST, 1, 8, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, IsoEra.CE, 1873, 9, 7, 1, 2, 2, OFFSET_P0100},
+                {IsoChronology.INSTANCE, IsoEra.CE, 1928, 2, 28, 1, 2, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, IsoEra.CE, 1989, 1, 8, 1, 2, 2, OFFSET_P0100},
+
+        };
+    }
+
+    @Test(dataProvider = "era_epochSecond_dataProvider")
+    public void test_epochSecond(Chronology chrono, Era era, int y, int m, int d, int h, int min, int s, ZoneOffset offset) {
+        ChronoLocalDate chronoLd = chrono.date(era, y, m, d);
+        assertEquals(chrono.epochSecond(era, y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(LocalDate.from(chronoLd), LocalTime.of(h, min, s), offset)
+                                   .toEpochSecond());
+    }
+
+    @DataProvider(name = "bad_epochSecond_dataProvider")
+    Object[][]  bad_data_epochSecond() {
+        return new Object[][] {
+                {JapaneseChronology.INSTANCE, 1873, 13, 7, 1, 2, 2, OFFSET_P0100},
+                {HijrahChronology.INSTANCE, 1434, 9, 32, 1, 2, 2, OFFSET_P0100},
+                {MinguoChronology.INSTANCE, 1873, 9, 7, 31, 2, 2, OFFSET_P0100},
+                {ThaiBuddhistChronology.INSTANCE, 1928, 2, 28, -1, 2, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, 1928, 2, 28, 1, 60, 2, OFFSET_M0100},
+                {IsoChronology.INSTANCE, 1989, 1, 8, 1, 2, -2, OFFSET_P0100},
+
+        };
+    }
+
+    @Test(dataProvider = "bad_epochSecond_dataProvider", expectedExceptions = DateTimeException.class)
+    public void test_bad_epochSecond(Chronology chrono, int y, int m, int d, int h, int min, int s, ZoneOffset offset) {
+        chrono.epochSecond(y, m, d, h, min, s, offset);
+    }
+
 }
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKIsoChronology.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKIsoChronology.java
index 0cd8eed..d753917 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKIsoChronology.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKIsoChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,10 +63,16 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.time.ZoneId;
+import java.time.OffsetDateTime;
+import java.time.Year;
 import java.time.ZonedDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
 import java.time.chrono.Chronology;
+import java.time.chrono.Era;
+import java.time.chrono.HijrahEra;
 import java.time.chrono.IsoChronology;
+import java.time.chrono.IsoEra;
 import java.time.format.ResolverStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalAccessor;
@@ -87,6 +93,8 @@
 public class TCKIsoChronology {
     // Can only work with IsoChronology here
     // others may be in separate module
+    private static final ZoneOffset OFFSET_P0100 = ZoneOffset.ofHours(1);
+    private static final ZoneOffset OFFSET_M0100 = ZoneOffset.ofHours(-1);
 
     @Test
     public void factory_from_TemporalAccessor_dateWithChronlogy() {
@@ -675,9 +683,114 @@
         }
     }
 
+    @DataProvider(name = "epochSecond_dataProvider")
+    Object[][] data_epochSecond() {
+        return new Object[][] {
+                {2008, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {2008, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {2008, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {2009, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {2009, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {2009, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {1968, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {1968, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {1968, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {1969, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {1969, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {1969, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {1970, 1, 1, 1, 2, 2, OFFSET_P0100},
+                {1970, 1, 1, 1, 2, 2, OFFSET_M0100},
+                {-4, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {-1, 3, 3 , 1, 2, 2, OFFSET_P0100},
+        };
+    }
+
+    @Test(dataProvider = "epochSecond_dataProvider")
+    public void test_epochSecond_1(int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(y, m, d, h, min, s, 0, offset).toEpochSecond());
+    }
+
+    @Test
+    public void test_epochSecond_2() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(2008, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+        assertEquals(IsoChronology.INSTANCE.epochSecond(1969, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+    }
+
+    @Test
+    public void test_epochSecond_max() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(Year.MAX_VALUE, 12, 31, 23, 59, 59, ZoneOffset.MIN),
+                     OffsetDateTime.of(Year.MAX_VALUE, 12, 31, 23, 59, 59, 0, ZoneOffset.MIN).toEpochSecond());
+    }
+
+    @Test
+    public void test_epochSecond_min() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(Year.MIN_VALUE, 1, 1, 0, 0, 0, ZoneOffset.MAX),
+                     OffsetDateTime.of(Year.MIN_VALUE, 1, 1, 0, 0, 0, 0, ZoneOffset.MAX).toEpochSecond());
+    }
+
+    @DataProvider(name = "bad_epochSecond_dataProvider")
+    Object[][]  bad_data_epochSecond() {
+        return new Object[][] {
+            {2009, 13, 1, 1, 1, 1, OFFSET_P0100},
+            {2009, 2, 29, 1, 1, 1, OFFSET_P0100},
+            {2009, 1, 1, 25, 1, 1, OFFSET_P0100},
+            {2009, 1, 1, 1, 60, 1, OFFSET_P0100},
+            {2009, 1, 1, 1, 1, -11, OFFSET_P0100},
+        };
+    }
+    @Test(dataProvider = "bad_epochSecond_dataProvider", expectedExceptions = DateTimeException.class)
+    public void test_epochSecond_bad(int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
+        IsoChronology.INSTANCE.epochSecond(y, m, d, h, min, s, offset);
+    }
+
+    @DataProvider(name = "era_epochSecond_dataProvider")
+    Object[][] data_era_epochSecond() {
+        return new Object[][] {
+                {IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 2008, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 2009, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 2009, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 2009, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1968, 3, 3, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1968, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 1968, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1969, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1969, 3, 3, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.CE, 1969, 2, 28, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1970, 1, 1, 1, 2, 2, OFFSET_P0100},
+                {IsoEra.CE, 1970, 1, 1, 1, 2, 2, OFFSET_M0100},
+                {IsoEra.BCE, 5, 3, 3 , 1, 2, 2, OFFSET_P0100},
+                {IsoEra.BCE, 2, 3, 3 , 1, 2, 2, OFFSET_P0100},
+        };
+    }
+
+    @Test(dataProvider = "era_epochSecond_dataProvider")
+    public void test_era_epochSecond_1(Era era, int y, int m, int d, int h , int min, int s, ZoneOffset offset) {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(era, y, m, d, h, min, s, offset),
+                     OffsetDateTime.of(IsoChronology.INSTANCE.date(era, y, m, d), LocalTime.of(h, min, s), offset)
+                                   .toEpochSecond());
+    }
+
+    @Test
+    public void test_era_epochSecond_2() {
+        assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 2008, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(2008, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+        assertEquals(IsoChronology.INSTANCE.epochSecond(IsoEra.CE, 1969, 3, 3, 1, 2, 2, OFFSET_P0100),
+                     ZonedDateTime.of(1969, 3, 3, 1, 2, 2, 0, ZoneId.of("+01:00")).toEpochSecond());
+    }
+
+    @Test(expectedExceptions = ClassCastException.class)
+    public void test_era_epochSecond_bad() {
+        IsoChronology.INSTANCE.epochSecond(HijrahEra.AH, 2009, 2, 29, 1, 2, 2, OFFSET_P0100);
+    }
+
+
     //-----------------------------------------------------------------------
     private static LocalDate date(int y, int m, int d) {
         return LocalDate.of(y, m, d);
     }
-
 }
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
index c45cd96..b5650ee 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ o Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java
index afe2586..0fbeab3 100644
--- a/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java
+++ b/ojluni/src/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java
@@ -59,6 +59,7 @@
 import static java.time.temporal.ChronoField.ERA;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import java.time.chrono.Era;
 import java.time.chrono.JapaneseChronology;
@@ -69,7 +70,8 @@
 import org.testng.annotations.Test;
 
 /**
- * Test.
+ * Tests for JapaneseEra
+ * @bug 8068278
  */
 @Test
 public class TCKJapaneseEra {
@@ -87,6 +89,20 @@
         };
     }
 
+    @DataProvider(name = "InvalidJapaneseEras")
+    Object[][] data_of_invalid_eras() {
+        return new Object[][] {
+                {-2},
+                {-3},
+                {4},
+                {Integer.MIN_VALUE},
+                {Integer.MAX_VALUE},
+        };
+    }
+
+    //-----------------------------------------------------------------------
+    // JapaneseEra value test
+    //-----------------------------------------------------------------------
     @Test(dataProvider="JapaneseEras")
     public void test_valueOf(JapaneseEra era , String eraName, int eraValue) {
         assertEquals(era.getValue(), eraValue);
@@ -121,4 +137,11 @@
         }
     }
 
+    //-----------------------------------------------------------------------
+    // JapaneseChronology.INSTANCE.eraOf invalid era test
+    //-----------------------------------------------------------------------
+    @Test(dataProvider="InvalidJapaneseEras", expectedExceptions=java.time.DateTimeException.class)
+    public void test_outofrange(int era) {
+        JapaneseChronology.INSTANCE.eraOf(era);
+    }
 }
diff --git a/ojluni/src/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java b/ojluni/src/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java
new file mode 100644
index 0000000..ec60f0f
--- /dev/null
+++ b/ojluni/src/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tck.java.time.format;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Testing DateTimeFormatter Parsing with 4 different test conditions:
+ * 1. When Zone and Offset not provided
+ * 2. When Zone and Offset provided
+ * 3. When Offset is not provided and Zone is provided
+ * 4. When Zone is not provided and Offset is provided
+ */
+
+@Test
+public class TCKDTFParsedInstant {
+
+    private static final ZoneId EUROPE_BERLIN = ZoneId.of("Europe/Berlin");
+    private static final ZoneId ASIA_ISTANBUL = ZoneId.of("Asia/Istanbul");
+
+    private DateTimeFormatter dtFormatter;
+    private ZonedDateTime zdt1, zdt2;
+    private LocalDateTime ldt1;
+    private OffsetDateTime odt1;
+
+    @BeforeMethod
+    public void setUp() throws Exception {
+        dtFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
+    }
+
+    @DataProvider(name="parseWithoutZoneWithoutOffset")
+    Object[][] data_parse_WithoutOffset_WithoutZone() {
+        return new Object[][] {
+            {"1966-12-31T00:01:10", LocalDateTime.of(1966, 12, 31, 0, 1, 10)},
+            {"1970-01-01T00:00:00", LocalDateTime.of(1970, 1, 1, 0, 0, 0)},
+            {"2004-02-29T00:30:00", LocalDateTime.of(2004, 2, 29, 0, 30, 0)},
+            {"2015-12-31T23:59:59", LocalDateTime.of(2015, 12, 31, 23, 59, 59)}
+        };
+    }
+
+    @Test(dataProvider="parseWithoutZoneWithoutOffset")
+    public void testWithoutZoneWithoutOffset(String ldtString, LocalDateTime expectedLDT) {
+        dtFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
+        ldt1 = LocalDateTime.parse(ldtString, dtFormatter);
+        assertEquals(expectedLDT, ldt1);
+    }
+
+    @DataProvider(name="parseWithZoneWithOffset")
+    Object[][] data_parse_WithZone_WithOffset() {
+        return new Object[][] {
+            {"2012-10-28T01:45:00-02:30[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("-02:30"), EUROPE_BERLIN},
+            {"2012-10-28T01:45:00-01:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("-01:00"), EUROPE_BERLIN},
+            {"2012-10-28T01:45:00-00:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("-00:00"), EUROPE_BERLIN},
+            {"2012-10-28T01:45:00+00:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+00:00"), EUROPE_BERLIN},
+            {"2012-10-28T01:45:00+01:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+01:00"), EUROPE_BERLIN},
+            {"2012-10-28T01:45:00+02:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+02:00"), EUROPE_BERLIN},
+            {"2012-10-28T01:45:00+03:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+03:00"), EUROPE_BERLIN},
+            {"2012-10-28T02:45:00-02:30[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-02:30"), EUROPE_BERLIN},
+            {"2012-10-28T02:45:00-01:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-01:00"), EUROPE_BERLIN},
+            {"2012-10-28T02:45:00-00:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-00:00"), EUROPE_BERLIN},
+            {"2012-10-28T02:45:00+00:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+00:00"), EUROPE_BERLIN},
+            {"2012-10-28T02:45:00+01:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+01:00"), EUROPE_BERLIN},
+            {"2012-10-28T02:45:00+02:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+02:00"), EUROPE_BERLIN},
+            {"2012-10-28T02:45:00+03:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+03:00"), EUROPE_BERLIN},
+            {"2012-10-28T03:45:00-02:30[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-02:30"), EUROPE_BERLIN},
+            {"2012-10-28T03:45:00-01:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-01:00"), EUROPE_BERLIN},
+            {"2012-10-28T03:45:00-00:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-00:00"), EUROPE_BERLIN},
+            {"2012-10-28T03:45:00+00:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+00:00"), EUROPE_BERLIN},
+            {"2012-10-28T03:45:00+01:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+01:00"), EUROPE_BERLIN},
+            {"2012-10-28T03:45:00+02:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+02:00"), EUROPE_BERLIN},
+            {"2012-10-28T03:45:00+03:00[Europe/Berlin]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+03:00"), EUROPE_BERLIN},
+
+            {"2012-10-28T02:45:00-02:30[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-02:30"), ASIA_ISTANBUL},
+            {"2012-10-28T02:45:00-01:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-01:00"), ASIA_ISTANBUL},
+            {"2012-10-28T02:45:00-00:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-00:00"), ASIA_ISTANBUL},
+            {"2012-10-28T02:45:00+00:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+00:00"), ASIA_ISTANBUL},
+            {"2012-10-28T02:45:00+01:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+01:00"), ASIA_ISTANBUL},
+            {"2012-10-28T02:45:00+02:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+02:00"), ASIA_ISTANBUL},
+            {"2012-10-28T02:45:00+03:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+03:00"), ASIA_ISTANBUL},
+            {"2012-10-28T03:45:00-02:30[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-02:30"), ASIA_ISTANBUL},
+            {"2012-10-28T03:45:00-01:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-01:00"), ASIA_ISTANBUL},
+            {"2012-10-28T03:45:00-00:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-00:00"), ASIA_ISTANBUL},
+            {"2012-10-28T03:45:00+00:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+00:00"), ASIA_ISTANBUL},
+            {"2012-10-28T03:45:00+01:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+01:00"), ASIA_ISTANBUL},
+            {"2012-10-28T03:45:00+02:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+02:00"), ASIA_ISTANBUL},
+            {"2012-10-28T03:45:00+03:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+03:00"), ASIA_ISTANBUL},
+            {"2012-10-28T04:45:00-02:30[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("-02:30"), ASIA_ISTANBUL},
+            {"2012-10-28T04:45:00-01:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("-01:00"), ASIA_ISTANBUL},
+            {"2012-10-28T04:45:00-00:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("-00:00"), ASIA_ISTANBUL},
+            {"2012-10-28T04:45:00+00:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+00:00"), ASIA_ISTANBUL},
+            {"2012-10-28T04:45:00+01:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+01:00"), ASIA_ISTANBUL},
+            {"2012-10-28T04:45:00+02:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+02:00"), ASIA_ISTANBUL},
+            {"2012-10-28T04:45:00+03:00[Asia/Istanbul]",
+                LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+03:00"), ASIA_ISTANBUL}
+        };
+    }
+
+    @Test(dataProvider="parseWithZoneWithOffset")
+    public void testWithZoneWithOffset(String zdtString, LocalDateTime ldt, ZoneOffset offset, ZoneId zone) {
+        dtFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
+        zdt1 = ZonedDateTime.ofInstant(ldt, offset, zone);
+        zdt2 = ZonedDateTime.parse(zdtString, dtFormatter);
+        assertEquals(zdt1, zdt2);
+    }
+
+    @DataProvider(name="parseWithZoneWithoutOffset")
+    Object[][] data_parse_WithZone_WithoutOffset() {
+        return new Object[][] {
+            {"28 Oct 00:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 0, 45, 0, 0, EUROPE_BERLIN)},
+            {"28 Oct 01:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 1, 45, 0, 0, EUROPE_BERLIN)},
+            {"28 Oct 02:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 2, 45, 0, 0, EUROPE_BERLIN)},
+            {"28 Oct 03:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 3, 45, 0, 0, EUROPE_BERLIN)},
+            {"28 Oct 04:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 4, 45, 0, 0, EUROPE_BERLIN)},
+
+            {"28 Oct 01:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 1, 45, 0, 0, ASIA_ISTANBUL)},
+            {"28 Oct 02:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 2, 45, 0, 0, ASIA_ISTANBUL)},
+            {"28 Oct 03:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 3, 45, 0, 0, ASIA_ISTANBUL)},
+            {"28 Oct 04:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 4, 45, 0, 0, ASIA_ISTANBUL)},
+            {"28 Oct 05:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 5, 45, 0, 0, ASIA_ISTANBUL)}
+        };
+    }
+
+    @Test(dataProvider="parseWithZoneWithoutOffset")
+    public void testWithZoneWithoutOffset(String withZoneWithoutOffset, ZonedDateTime expectedZDT) {
+        dtFormatter = DateTimeFormatter.ofPattern("d MMM HH:mm:ss uuuu VV").withLocale(Locale.ENGLISH);
+        zdt1 = ZonedDateTime.parse(withZoneWithoutOffset, dtFormatter);
+        assertEquals(expectedZDT, zdt1);
+    }
+
+    @DataProvider(name="parseWithOffsetWithoutZone")
+    Object[][] data_parse_WithOffset_WithoutZone() {
+        return new Object[][] {
+            {"2015-12-14T00:45:00-11:30", OffsetDateTime.of(2015, 12, 14, 0, 45, 0, 0, ZoneOffset.of("-11:30"))},
+            {"2015-12-14T01:45:00-05:00", OffsetDateTime.of(2015, 12, 14, 1, 45, 0, 0, ZoneOffset.of("-05:00"))},
+            {"2015-12-14T02:45:00-00:00", OffsetDateTime.of(2015, 12, 14, 2, 45, 0, 0, ZoneOffset.of("-00:00"))},
+            {"2015-12-14T03:45:00+00:00", OffsetDateTime.of(2015, 12, 14, 3, 45, 0, 0, ZoneOffset.of("+00:00"))},
+            {"2015-12-14T04:45:00+03:30", OffsetDateTime.of(2015, 12, 14, 4, 45, 0, 0, ZoneOffset.of("+03:30"))},
+            {"2015-12-14T05:45:00+10:00", OffsetDateTime.of(2015, 12, 14, 5, 45, 0, 0, ZoneOffset.of("+10:00"))}
+        };
+    }
+
+    @Test(dataProvider="parseWithOffsetWithoutZone")
+    public void testWithOffsetWithoutZone(String odtString, OffsetDateTime expectedOTD) {
+        dtFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+        odt1 = OffsetDateTime.parse(odtString, dtFormatter);
+        assertEquals(expectedOTD, odt1);
+    }
+}
diff --git a/ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java b/ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
index c5a017c..7429f01 100644
--- a/ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
+++ b/ojluni/src/test/java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,20 +59,28 @@
  */
 package tck.java.time.format;
 
+import static java.time.format.DateTimeFormatter.BASIC_ISO_DATE;
 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
 import static java.time.temporal.ChronoField.HOUR_OF_DAY;
 import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
+import static java.time.temporal.ChronoField.OFFSET_SECONDS;
 import static java.time.temporal.ChronoField.YEAR;
 import static org.testng.Assert.assertEquals;
 
 import java.text.ParsePosition;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.Month;
 import java.time.YearMonth;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
 import java.time.format.SignStyle;
 import java.time.format.TextStyle;
 import java.time.temporal.Temporal;
@@ -339,6 +347,18 @@
                 {"+HH", 2, 0, 45, "+02"},
                 {"+HH", 2, 30, 45, "+02"},
 
+                {"+HHmm", 2, 0, 0, "+02"},
+                {"+HHmm", -2, 0, 0, "-02"},
+                {"+HHmm", 2, 30, 0, "+0230"},
+                {"+HHmm", 2, 0, 45, "+02"},
+                {"+HHmm", 2, 30, 45, "+0230"},
+
+                {"+HH:mm", 2, 0, 0, "+02"},
+                {"+HH:mm", -2, 0, 0, "-02"},
+                {"+HH:mm", 2, 30, 0, "+02:30"},
+                {"+HH:mm", 2, 0, 45, "+02"},
+                {"+HH:mm", 2, 30, 45, "+02:30"},
+
                 {"+HHMM", 2, 0, 0, "+0200"},
                 {"+HHMM", -2, 0, 0, "-0200"},
                 {"+HHMM", 2, 30, 0, "+0230"},
@@ -374,6 +394,141 @@
                 {"+HH:MM:SS", 2, 30, 0, "+02:30:00"},
                 {"+HH:MM:SS", 2, 0, 45, "+02:00:45"},
                 {"+HH:MM:SS", 2, 30, 45, "+02:30:45"},
+
+                {"+HHmmss", 2, 0, 0, "+02"},
+                {"+HHmmss", -2, 0, 0, "-02"},
+                {"+HHmmss", 2, 30, 0, "+0230"},
+                {"+HHmmss", 2, 0, 45, "+020045"},
+                {"+HHmmss", 2, 30, 45, "+023045"},
+
+                {"+HH:mm:ss", 2, 0, 0, "+02"},
+                {"+HH:mm:ss", -2, 0, 0, "-02"},
+                {"+HH:mm:ss", 2, 30, 0, "+02:30"},
+                {"+HH:mm:ss", 2, 0, 45, "+02:00:45"},
+                {"+HH:mm:ss", 2, 30, 45, "+02:30:45"},
+
+                {"+H", 2, 0, 0, "+2"},
+                {"+H", -2, 0, 0, "-2"},
+                {"+H", 2, 30, 0, "+2"},
+                {"+H", 2, 0, 45, "+2"},
+                {"+H", 2, 30, 45, "+2"},
+                {"+H", 12, 0, 0, "+12"},
+                {"+H", -12, 0, 0, "-12"},
+                {"+H", 12, 30, 0, "+12"},
+                {"+H", 12, 0, 45, "+12"},
+                {"+H", 12, 30, 45, "+12"},
+
+                {"+Hmm", 2, 0, 0, "+2"},
+                {"+Hmm", -2, 0, 0, "-2"},
+                {"+Hmm", 2, 30, 0, "+230"},
+                {"+Hmm", 2, 0, 45, "+2"},
+                {"+Hmm", 2, 30, 45, "+230"},
+                {"+Hmm", 12, 0, 0, "+12"},
+                {"+Hmm", -12, 0, 0, "-12"},
+                {"+Hmm", 12, 30, 0, "+1230"},
+                {"+Hmm", 12, 0, 45, "+12"},
+                {"+Hmm", 12, 30, 45, "+1230"},
+
+                {"+H:mm", 2, 0, 0, "+2"},
+                {"+H:mm", -2, 0, 0, "-2"},
+                {"+H:mm", 2, 30, 0, "+2:30"},
+                {"+H:mm", 2, 0, 45, "+2"},
+                {"+H:mm", 2, 30, 45, "+2:30"},
+                {"+H:mm", 12, 0, 0, "+12"},
+                {"+H:mm", -12, 0, 0, "-12"},
+                {"+H:mm", 12, 30, 0, "+12:30"},
+                {"+H:mm", 12, 0, 45, "+12"},
+                {"+H:mm", 12, 30, 45, "+12:30"},
+
+                {"+HMM", 2, 0, 0, "+200"},
+                {"+HMM", -2, 0, 0, "-200"},
+                {"+HMM", 2, 30, 0, "+230"},
+                {"+HMM", 2, 0, 45, "+200"},
+                {"+HMM", 2, 30, 45, "+230"},
+                {"+HMM", 12, 0, 0, "+1200"},
+                {"+HMM", -12, 0, 0, "-1200"},
+                {"+HMM", 12, 30, 0, "+1230"},
+                {"+HMM", 12, 0, 45, "+1200"},
+                {"+HMM", 12, 30, 45, "+1230"},
+
+                {"+H:MM", 2, 0, 0, "+2:00"},
+                {"+H:MM", -2, 0, 0, "-2:00"},
+                {"+H:MM", 2, 30, 0, "+2:30"},
+                {"+H:MM", 2, 0, 45, "+2:00"},
+                {"+H:MM", 2, 30, 45, "+2:30"},
+                {"+H:MM", 12, 0, 0, "+12:00"},
+                {"+H:MM", -12, 0, 0, "-12:00"},
+                {"+H:MM", 12, 30, 0, "+12:30"},
+                {"+H:MM", 12, 0, 45, "+12:00"},
+                {"+H:MM", 12, 30, 45, "+12:30"},
+
+                {"+HMMss", 2, 0, 0, "+200"},
+                {"+HMMss", -2, 0, 0, "-200"},
+                {"+HMMss", 2, 30, 0, "+230"},
+                {"+HMMss", 2, 0, 45, "+20045"},
+                {"+HMMss", 2, 30, 45, "+23045"},
+                {"+HMMss", 12, 0, 0, "+1200"},
+                {"+HMMss", -12, 0, 0, "-1200"},
+                {"+HMMss", 12, 30, 0, "+1230"},
+                {"+HMMss", 12, 0, 45, "+120045"},
+                {"+HMMss", 12, 30, 45, "+123045"},
+
+                {"+H:MM:ss", 2, 0, 0, "+2:00"},
+                {"+H:MM:ss", -2, 0, 0, "-2:00"},
+                {"+H:MM:ss", 2, 30, 0, "+2:30"},
+                {"+H:MM:ss", 2, 0, 45, "+2:00:45"},
+                {"+H:MM:ss", 2, 30, 45, "+2:30:45"},
+                {"+H:MM:ss", 12, 0, 0, "+12:00"},
+                {"+H:MM:ss", -12, 0, 0, "-12:00"},
+                {"+H:MM:ss", 12, 30, 0, "+12:30"},
+                {"+H:MM:ss", 12, 0, 45, "+12:00:45"},
+                {"+H:MM:ss", 12, 30, 45, "+12:30:45"},
+
+                {"+HMMSS", 2, 0, 0, "+20000"},
+                {"+HMMSS", -2, 0, 0, "-20000"},
+                {"+HMMSS", 2, 30, 0, "+23000"},
+                {"+HMMSS", 2, 0, 45, "+20045"},
+                {"+HMMSS", 2, 30, 45, "+23045"},
+                {"+HMMSS", 12, 0, 0, "+120000"},
+                {"+HMMSS", -12, 0, 0, "-120000"},
+                {"+HMMSS", 12, 30, 0, "+123000"},
+                {"+HMMSS", 12, 0, 45, "+120045"},
+                {"+HMMSS", 12, 30, 45, "+123045"},
+
+                {"+H:MM:SS", 2, 0, 0, "+2:00:00"},
+                {"+H:MM:SS", -2, 0, 0, "-2:00:00"},
+                {"+H:MM:SS", 2, 30, 0, "+2:30:00"},
+                {"+H:MM:SS", 2, 0, 45, "+2:00:45"},
+                {"+H:MM:SS", 2, 30, 45, "+2:30:45"},
+                {"+H:MM:SS", 12, 0, 0, "+12:00:00"},
+                {"+H:MM:SS", -12, 0, 0, "-12:00:00"},
+                {"+H:MM:SS", 12, 30, 0, "+12:30:00"},
+                {"+H:MM:SS", 12, 0, 45, "+12:00:45"},
+                {"+H:MM:SS", 12, 30, 45, "+12:30:45"},
+
+                {"+Hmmss", 2, 0, 0, "+2"},
+                {"+Hmmss", -2, 0, 0, "-2"},
+                {"+Hmmss", 2, 30, 0, "+230"},
+                {"+Hmmss", 2, 0, 45, "+20045"},
+                {"+Hmmss", 2, 30, 45, "+23045"},
+                {"+Hmmss", 12, 0, 0, "+12"},
+                {"+Hmmss", -12, 0, 0, "-12"},
+                {"+Hmmss", 12, 30, 0, "+1230"},
+                {"+Hmmss", 12, 0, 45, "+120045"},
+                {"+Hmmss", 12, 30, 45, "+123045"},
+
+                {"+H:mm:ss", 2, 0, 0, "+2"},
+                {"+H:mm:ss", -2, 0, 0, "-2"},
+                {"+H:mm:ss", 2, 30, 0, "+2:30"},
+                {"+H:mm:ss", 2, 0, 45, "+2:00:45"},
+                {"+H:mm:ss", 2, 30, 45, "+2:30:45"},
+                {"+H:mm:ss", 12, 0, 0, "+12"},
+                {"+H:mm:ss", -12, 0, 0, "-12"},
+                {"+H:mm:ss", 12, 30, 0, "+12:30"},
+                {"+H:mm:ss", 12, 0, 45, "+12:00:45"},
+                {"+H:mm:ss", 12, 30, 45, "+12:30:45"},
+
+
         };
     }
 
@@ -403,8 +558,6 @@
             {"HH:MM:ss"},
             {"HHMMSS"},
             {"HH:MM:SS"},
-            {"+H"},
-            {"+HMM"},
             {"+HHM"},
             {"+A"},
         };
@@ -428,6 +581,98 @@
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
+    @DataProvider(name = "formatGenericTimeZonePatterns")
+    Object[][] data_formatGenericNonLocationPatterns() {
+        return new Object[][] {
+                {"v", "America/Los_Angeles", "PT"},
+                {"vvvv", "America/Los_Angeles", "Pacific Time"},
+                {"v", "America/New_York", "ET"},
+                {"vvvv", "America/New_York", "Eastern Time"},
+        };
+    }
+
+    @Test(dataProvider = "formatGenericTimeZonePatterns")
+    public void test_appendZoneText_formatGenericTimeZonePatterns(String pattern, String input, String expected) {
+        ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of(input));
+        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern, Locale.US);
+        assertEquals(zdt.format(df), expected);
+    }
+
+    @DataProvider(name = "parseGenericTimeZonePatterns")
+    Object[][]  data_parseGenericTimeZonePatterns() {
+        return new Object[][] {
+                {"yyyy DDD HH mm v", LocalDateTime.of(2015, Month.MARCH, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 069 12 13 PT"},
+                {"yyyy DDD HH mm vvvv", LocalDateTime.of(2015, Month.MARCH, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 069 12 13 Pacific Time"},
+                {"yyyy DDD HH mm v", LocalDateTime.of(2015, Month.NOVEMBER, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 314 12 13 PT"},
+                {"yyyy DDD HH mm vvvv", LocalDateTime.of(2015, Month.NOVEMBER, 10, 12, 13), ZoneId.of("America/Los_Angeles"),
+                 "2015 314 12 13 Pacific Time"},
+        };
+    }
+
+    @Test(dataProvider = "parseGenericTimeZonePatterns")
+    public void test_appendZoneText_parseGenericTimeZonePatterns(String pattern, LocalDateTime ldt, ZoneId zId, String input) {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
+        ZonedDateTime expected = ZonedDateTime.parse(input, df);
+        ZonedDateTime actual = ZonedDateTime.of(ldt, zId);
+        assertEquals(actual, expected);
+    }
+
+    @DataProvider(name = "formatNonGenericTimeZonePatterns_1")
+    Object[][]  data_formatNonGenericTimeZonePatterns_1() {
+        return new Object[][] {
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 PDT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 PDT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 PST"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 Pacific Daylight Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 Pacific Daylight Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 Pacific Standard Time"},
+        };
+    }
+
+    @Test(dataProvider = "formatNonGenericTimeZonePatterns_1")
+    public void test_appendZoneText_parseNonGenricTimeZonePatterns_1(String pattern, LocalDateTime ldt, String expected) {
+        ZoneId  zId = ZoneId.of("America/Los_Angeles");
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(Locale.US);
+        ZonedDateTime zdt = ZonedDateTime.of(ldt, zId);
+        String actual = df.format(zdt);
+        assertEquals(actual, expected);
+    }
+
+    @DataProvider(name = "formatNonGenericTimeZonePatterns_2")
+    Object[][]  data_formatNonGenericTimeZonePatterns_2() {
+        return new Object[][] {
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 PDT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 PT"},
+                {"yyyy-MM-dd HH:mm:ss z", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 PST"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 0, 30),
+                 "2015-11-01 00:30:00 Pacific Daylight Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 1, 30),
+                 "2015-11-01 01:30:00 Pacific Time"},
+                {"yyyy-MM-dd HH:mm:ss zzzz", LocalDateTime.of(2015, Month.NOVEMBER, 1, 2, 30),
+                 "2015-11-01 02:30:00 Pacific Standard Time"},
+        };
+    }
+
+    @Test(dataProvider = "formatNonGenericTimeZonePatterns_2")
+    public void test_appendZoneText_parseNonGenricTimeZonePatterns_2(String pattern, LocalDateTime ldt, String expected) {
+        ZoneId  zId = ZoneId.of("America/Los_Angeles");
+        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern, Locale.US).withZone(zId);
+        String actual = df.format(ldt);
+        assertEquals(actual, expected);
+    }
+
     @Test(expectedExceptions=NullPointerException.class)
     public void test_appendZoneText_1arg_nullText() throws Exception {
         builder.appendZoneText(null);
@@ -632,6 +877,8 @@
             {"W"},
             {"W"},
 
+            {"g"},
+            {"ggggg"},
         };
     }
 
@@ -701,6 +948,9 @@
 
             {"www"},
             {"WW"},
+
+            {"vv"},
+            {"vvv"},
         };
     }
 
@@ -733,6 +983,131 @@
     }
 
     //-----------------------------------------------------------------------
+    @DataProvider(name="modJulianFieldPattern")
+    Object[][] data_modJuilanFieldPattern() {
+        return new Object[][] {
+            {"g", "1"},
+            {"g", "123456"},
+            {"gggggg", "123456"},
+        };
+    }
+
+    @Test(dataProvider="modJulianFieldPattern")
+    public void test_modJulianFieldPattern(String pattern, String input) throws Exception {
+        DateTimeFormatter.ofPattern(pattern).parse(input);
+    }
+
+    @DataProvider(name="modJulianFieldValues")
+    Object[][] data_modJuilanFieldValues() {
+        return new Object[][] {
+            {1970, 1, 1, "40587"},
+            {1858, 11, 17, "0"},
+            {1858, 11, 16, "-1"},
+        };
+    }
+
+    @Test(dataProvider="modJulianFieldValues")
+    public void test_modJulianFieldValues(int y, int m, int d, String expected) throws Exception {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("g").toFormatter();
+         assertEquals(LocalDate.of(y, m, d).format(df), expected);
+    }
+    //----------------------------------------------------------------------
+    @DataProvider(name="dayOfYearFieldValues")
+    Object[][] data_dayOfYearFieldValues() {
+        return new Object[][] {
+                {2016, 1, 1, "D", "1"},
+                {2016, 1, 31, "D", "31"},
+                {2016, 1, 1, "DD", "01"},
+                {2016, 1, 31, "DD", "31"},
+                {2016, 4, 9, "DD", "100"},
+                {2016, 1, 1, "DDD", "001"},
+                {2016, 1, 31, "DDD", "031"},
+                {2016, 4, 9, "DDD", "100"},
+        };
+    }
+
+    @Test(dataProvider="dayOfYearFieldValues")
+    public void test_dayOfYearFieldValues(int y, int m, int d, String pattern, String expected) throws Exception {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
+        assertEquals(LocalDate.of(y, m, d).format(df), expected);
+    }
+
+    @DataProvider(name="dayOfYearFieldAdjacentParsingValues")
+    Object[][] data_dayOfYearFieldAdjacentParsingValues() {
+        return new Object[][] {
+            {"20160281015", LocalDateTime.of(2016, 1, 28, 10, 15)},
+            {"20161001015", LocalDateTime.of(2016, 4, 9, 10, 15)},
+        };
+    }
+
+    @Test(dataProvider="dayOfYearFieldAdjacentParsingValues")
+    public void test_dayOfYearFieldAdjacentValueParsing(String input, LocalDateTime expected) {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern("yyyyDDDHHmm").toFormatter();
+        LocalDateTime actual = LocalDateTime.parse(input, df);
+        assertEquals(actual, expected);
+    }
+
+    @Test(expectedExceptions = DateTimeParseException.class)
+    public void test_dayOfYearFieldInvalidValue() {
+        DateTimeFormatter.ofPattern("DDD").parse("1234");
+    }
+
+    @Test(expectedExceptions = DateTimeParseException.class)
+    public void test_dayOfYearFieldInvalidAdacentValueParsingPattern() {
+        // patterns D and DD will not take part in adjacent value parsing
+        DateTimeFormatter.ofPattern("yyyyDDHHmmss").parse("201610123456");
+    }
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="secondsPattern")
+    Object[][] data_secondsPattern() {
+        return new Object[][] {
+                {"A", "1", LocalTime.ofNanoOfDay(1_000_000)},
+                {"A", "100000", LocalTime.ofSecondOfDay(100)},
+                {"AA", "01", LocalTime.ofNanoOfDay(1_000_000)},
+                {"AA", "100000", LocalTime.ofSecondOfDay(100)},
+                {"AAAAAA", "100000", LocalTime.ofSecondOfDay(100)},
+                {"HHmmssn", "0000001", LocalTime.ofNanoOfDay(1)},
+                {"HHmmssn", "000000111", LocalTime.ofNanoOfDay(111)},
+                {"HHmmssnn", "00000001", LocalTime.ofNanoOfDay(1)},
+                {"HHmmssnn", "0000001111", LocalTime.ofNanoOfDay(1111)},
+                {"HHmmssnnnnnn", "000000111111", LocalTime.ofNanoOfDay(111_111)},
+                {"N", "1", LocalTime.ofNanoOfDay(1)},
+                {"N", "100000", LocalTime.ofNanoOfDay(100_000)},
+                {"NN", "01", LocalTime.ofNanoOfDay(1)},
+                {"NN", "100000", LocalTime.ofNanoOfDay(100_000)},
+                {"NNNNNN", "100000", LocalTime.ofNanoOfDay(100_000)},
+        };
+    }
+
+    @Test(dataProvider="secondsPattern")
+    public void test_secondsPattern(String pattern, String input, LocalTime expected) throws Exception {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
+        assertEquals(LocalTime.parse(input, df), expected);
+    }
+
+    @DataProvider(name="secondsValues")
+    Object[][] data_secondsValues() {
+        return new Object[][] {
+                {"A", 1, "1000"},
+                {"n", 1, "0"},
+                {"N", 1, "1000000000"},
+        };
+    }
+
+    @Test(dataProvider="secondsValues")
+    public void test_secondsValues(String pattern, int seconds , String expected) throws Exception {
+        DateTimeFormatter df = new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
+        assertEquals(LocalTime.ofSecondOfDay(seconds).format(df), expected);
+    }
+
+    @Test(expectedExceptions = DateTimeParseException.class)
+    public void test_secondsPatternInvalidAdacentValueParsingPattern() {
+        // patterns A*, N*, n* will not take part in adjacent value parsing
+        DateTimeFormatter.ofPattern("yyyyAA").parse("201610");
+    }
+
+    //-----------------------------------------------------------------------
     @Test
     public void test_adjacent_strict_firstFixedWidth() throws Exception {
         // succeeds because both number elements are fixed width
@@ -868,7 +1243,7 @@
 
     @Test
     public void test_adjacent_lenient_fractionFollows_0digit() throws Exception {
-        // succeeds because hour/min are fixed width
+        // succeeds because hour, min and fraction of seconds are fixed width
         DateTimeFormatter f = builder.parseLenient().appendValue(HOUR_OF_DAY, 2).appendValue(MINUTE_OF_HOUR, 2).appendFraction(NANO_OF_SECOND, 3, 3, false).toFormatter(Locale.UK);
         ParsePosition pp = new ParsePosition(0);
         TemporalAccessor parsed = f.parseUnresolved("1230", pp);
@@ -878,4 +1253,441 @@
         assertEquals(parsed.getLong(MINUTE_OF_HOUR), 30L);
     }
 
+    @DataProvider(name="adjacentFractionParseData")
+    Object[][] data_adjacent_fraction_parse() {
+        return new Object[][] {
+            {"20130812214600025", "yyyyMMddHHmmssSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25000000)},
+            {"201308122146000256", "yyyyMMddHHmmssSSSS", LocalDateTime.of(2013, 8, 12, 21, 46, 00, 25600000)},
+        };
+    }
+
+    @Test(dataProvider = "adjacentFractionParseData")
+    public void test_adjacent_fraction(String input, String pattern, LocalDateTime expected) {
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
+        LocalDateTime actual = LocalDateTime.parse(input, dtf);
+        assertEquals(actual, expected);
+    }
+
+    @DataProvider(name="lenientOffsetParseData")
+    Object[][] data_lenient_offset_parse() {
+        return new Object[][] {
+            {"+HH", "+01", 3600},
+            {"+HH", "+0101", 3660},
+            {"+HH", "+010101", 3661},
+            {"+HH", "+01", 3600},
+            {"+HH", "+01:01", 3660},
+            {"+HH", "+01:01:01", 3661},
+            {"+HHmm", "+01", 3600},
+            {"+HHmm", "+0101", 3660},
+            {"+HHmm", "+010101", 3661},
+            {"+HH:mm", "+01", 3600},
+            {"+HH:mm", "+01:01", 3660},
+            {"+HH:mm", "+01:01:01", 3661},
+            {"+HHMM", "+01", 3600},
+            {"+HHMM", "+0101", 3660},
+            {"+HHMM", "+010101", 3661},
+            {"+HH:MM", "+01", 3600},
+            {"+HH:MM", "+01:01", 3660},
+            {"+HH:MM", "+01:01:01", 3661},
+            {"+HHMMss", "+01", 3600},
+            {"+HHMMss", "+0101", 3660},
+            {"+HHMMss", "+010101", 3661},
+            {"+HH:MM:ss", "+01", 3600},
+            {"+HH:MM:ss", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01:01", 3661},
+            {"+HHMMSS", "+01", 3600},
+            {"+HHMMSS", "+0101", 3660},
+            {"+HHMMSS", "+010101", 3661},
+            {"+HH:MM:SS", "+01", 3600},
+            {"+HH:MM:SS", "+01:01", 3660},
+            {"+HH:MM:SS", "+01:01:01", 3661},
+            {"+HHmmss", "+01", 3600},
+            {"+HHmmss", "+0101", 3660},
+            {"+HHmmss", "+010101", 3661},
+            {"+HH:mm:ss", "+01", 3600},
+            {"+HH:mm:ss", "+01:01", 3660},
+            {"+HH:mm:ss", "+01:01:01", 3661},
+
+            {"+H", "+1", 3600},
+            {"+H", "+101", 3660},
+            {"+H", "+10101", 3661},
+            {"+H", "+1:01", 3660},
+            {"+H", "+1:01:01", 3661},
+            {"+H", "+01", 3600},
+            {"+H", "+0101", 3660},
+            {"+H", "+010101", 3661},
+            {"+H", "+01:01", 3660},
+            {"+H", "+01:01:01", 3661},
+            {"+Hmm", "+1", 3600},
+            {"+Hmm", "+101", 3660},
+            {"+Hmm", "+10101", 3661},
+            {"+Hmm", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+Hmm", "+010101", 3661},
+            {"+H:mm", "+1", 3600},
+            {"+H:mm", "+1:01", 3660},
+            {"+H:mm", "+1:01:01", 3661},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+01:01:01", 3661},
+            {"+HMM", "+1", 3600},
+            {"+HMM", "+101", 3660},
+            {"+HMM", "+10101", 3661},
+            {"+HMM", "+01", 3600},
+            {"+HMM", "+0101", 3660},
+            {"+HMM", "+010101", 3661},
+            {"+H:MM", "+1", 3600},
+            {"+H:MM", "+1:01", 3660},
+            {"+H:MM", "+1:01:01", 3661},
+            {"+H:MM", "+01", 3600},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+01:01:01", 3661},
+            {"+HMMss", "+1", 3600},
+            {"+HMMss", "+101", 3660},
+            {"+HMMss", "+10101", 3661},
+            {"+HMMss", "+01", 3600},
+            {"+HMMss", "+0101", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+H:MM:ss", "+1", 3600},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+H:MM:ss", "+01", 3600},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+HMMSS", "+1", 3600},
+            {"+HMMSS", "+101", 3660},
+            {"+HMMSS", "+10101", 3661},
+            {"+HMMSS", "+01", 3600},
+            {"+HMMSS", "+0101", 3660},
+            {"+HMMSS", "+010101", 3661},
+            {"+H:MM:SS", "+1", 3600},
+            {"+H:MM:SS", "+1:01", 3660},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+H:MM:SS", "+01", 3600},
+            {"+H:MM:SS", "+01:01", 3660},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+Hmmss", "+1", 3600},
+            {"+Hmmss", "+101", 3660},
+            {"+Hmmss", "+10101", 3661},
+            {"+Hmmss", "+01", 3600},
+            {"+Hmmss", "+0101", 3660},
+            {"+Hmmss", "+010101", 3661},
+            {"+H:mm:ss", "+1", 3600},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+        };
+    }
+
+    @DataProvider(name="strictDoubleDigitHourOffsetParseData")
+    Object[][] data_strictDoubleDigitHour_offset_parse() {
+        return new Object[][] {
+            {"+HH", "+01", 3600},
+            {"+HHmm", "+01", 3600},
+            {"+HHmm", "+0101", 3660},
+            {"+HH:mm", "+01", 3600},
+            {"+HH:mm", "+01:01", 3660},
+            {"+HHMM", "+0101", 3660},
+            {"+HH:MM", "+01:01", 3660},
+            {"+HHMMss", "+0101", 3660},
+            {"+HHMMss", "+010101", 3661},
+            {"+HH:MM:ss", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01:01", 3661},
+            {"+HHMMSS", "+010101", 3661},
+            {"+HH:MM:SS", "+01:01:01", 3661},
+            {"+HHmmss", "+01", 3600},
+            {"+HHmmss", "+0101", 3660},
+            {"+HHmmss", "+010101", 3661},
+            {"+HH:mm:ss", "+01", 3600},
+            {"+HH:mm:ss", "+01:01", 3660},
+            {"+HH:mm:ss", "+01:01:01", 3661},
+        };
+    }
+
+    @DataProvider(name="strictSingleDigitHourOffsetParseData")
+    Object[][] data_strictSingleDigitHour_offset_parse() {
+        return new Object[][] {
+            {"+H", "+01", 3600},
+            {"+H", "+1", 3600},
+            {"+Hmm", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+Hmm", "+1", 3600},
+            {"+Hmm", "+101", 3660},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+1", 3600},
+            {"+H:mm", "+1:01", 3660},
+            {"+HMM", "+0101", 3660},
+            {"+HMM", "+101", 3660},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+1:01", 3660},
+            {"+HMMss", "+0101", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+HMMss", "+101", 3660},
+            {"+HMMss", "+10101", 3661},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+HMMSS", "+010101", 3661},
+            {"+HMMSS", "+10101", 3661},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+Hmmss", "+01", 3600},
+            {"+Hmmss", "+0101", 3660},
+            {"+Hmmss", "+010101", 3661},
+            {"+Hmmss", "+1", 3600},
+            {"+Hmmss", "+101", 3660},
+            {"+Hmmss", "+10101", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+            {"+H:mm:ss", "+1", 3600},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
+        };
+    }
+
+    @Test(dataProvider="lenientOffsetParseData")
+    public void test_lenient_offset_parse_1(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().parseLenient().appendOffset(pattern, "Z").toFormatter().parse(offset).get(OFFSET_SECONDS),
+                     offsetSeconds);
+    }
+
+    @Test
+    public void test_lenient_offset_parse_2() {
+        assertEquals(new DateTimeFormatterBuilder().parseLenient().appendOffsetId().toFormatter().parse("+01").get(OFFSET_SECONDS),
+                     3600);
+    }
+
+    @Test(dataProvider="strictDoubleDigitHourOffsetParseData")
+    public void test_strictDoubleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter()
+                .parse(offset).get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @Test(dataProvider="strictDoubleDigitHourOffsetParseData")
+    public void test_strictDoubleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
+                .appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @Test(dataProvider="strictSingleDigitHourOffsetParseData")
+    public void test_strictSingleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter()
+                .parse(offset).get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @Test(dataProvider="strictSingleDigitHourOffsetParseData")
+    public void test_strictSingleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) {
+        assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
+                .appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds);
+    }
+
+    @DataProvider(name="strictOffsetAdjacentParseValidPatternData")
+    Object[][] data_strict_offset_adjacentParse_validPattern() {
+        return new Object[][] {
+            {"+HH", "+01", 3600},
+            {"+HHmm", "+0101", 3660},
+            {"+HH:mm", "+01", 3600},
+            {"+HH:mm", "+01:01", 3660},
+            {"+HHMM", "+0101", 3660},
+            {"+HH:MM", "+01:01", 3660},
+            {"+HHMMss", "+010101", 3661},
+            {"+HH:MM:ss", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01:01", 3661},
+            {"+HHMMSS", "+010101", 3661},
+            {"+HH:MM:SS", "+01:01:01", 3661},
+            {"+HHmmss", "+010101", 3661},
+            {"+HH:mm:ss", "+01", 3600},
+            {"+HH:mm:ss", "+01:01", 3660},
+            {"+HH:mm:ss", "+01:01:01", 3661},
+
+            {"+H", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+1:01", 3660},
+            {"+HMM", "+0101", 3660},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+1:01", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+HMMSS", "+010101", 3661},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+Hmmss", "+010101", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
+        };
+    }
+
+    @Test(dataProvider="strictOffsetAdjacentParseValidPatternData")
+    public void test_strict_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) {
+        TemporalAccessor tmp = new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
+                .appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
+        assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds);
+        assertEquals(tmp.get(HOUR_OF_DAY), 12);
+    }
+
+    @DataProvider(name="strictOffsetAdjacentParseInvalidPatternData")
+    Object[][] data_strict_offset_adjacentParse_invalidPattern() {
+        return new Object[][] {
+            {"+HHmm", "+01", 3600},
+            {"+HHMMss", "+0101", 3660},
+            {"+HHmmss", "+01", 3600},
+            {"+HHmmss", "+0101", 3660},
+            {"+H", "+1", 3600},
+            {"+Hmm", "+01", 3600},
+            {"+H:mm", "+1", 3600},
+            {"+Hmm", "+1", 3600},
+            {"+Hmm", "+101", 3660},
+            {"+HMM", "+101", 3660},
+            {"+HMMss", "+0101", 3660},
+            {"+HMMss", "+101", 3660},
+            {"+HMMss", "+10101", 3661},
+            {"+HMMSS", "+10101", 3661},
+            {"+Hmmss", "+01", 3600},
+            {"+Hmmss", "+0101", 3660},
+            {"+Hmmss", "+1", 3600},
+            {"+Hmmss", "+101", 3660},
+            {"+Hmmss", "+10101", 3661},
+            {"+H:mm:ss", "+1", 3600},
+        };
+    }
+
+    @Test(dataProvider="strictOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class)
+    public void test_strict_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) {
+       new DateTimeFormatterBuilder().appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2)
+               .toFormatter().parse(offset + "12");
+    }
+
+    @DataProvider(name="lenientOffsetAdjacentParseValidPatternData")
+    Object[][] data_lenient_offset_adjacentParse_validPattern() {
+        return new Object[][] {
+            {"+HH:mm", "+01", 3600},
+            {"+HH:mm", "+01:01", 3660},
+            {"+HH:MM", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01", 3660},
+            {"+HH:MM:ss", "+01:01:01", 3661},
+            {"+HHMMSS", "+010101", 3661},
+            {"+HH:MM:SS", "+01:01:01", 3661},
+            {"+HHmmss", "+010101", 3661},
+            {"+HH:mm:ss", "+01", 3600},
+            {"+HH:mm:ss", "+01:01", 3660},
+            {"+HH:mm:ss", "+01:01:01", 3661},
+            {"+H:mm", "+01", 3600},
+            {"+H:mm", "+01:01", 3660},
+            {"+H:mm", "+1:01", 3660},
+            {"+H:MM", "+01:01", 3660},
+            {"+H:MM", "+1:01", 3660},
+            {"+HMMss", "+010101", 3661},
+            {"+H:MM:ss", "+01:01", 3660},
+            {"+H:MM:ss", "+01:01:01", 3661},
+            {"+H:MM:ss", "+1:01", 3660},
+            {"+H:MM:ss", "+1:01:01", 3661},
+            {"+HMMSS", "+010101", 3661},
+            {"+H:MM:SS", "+01:01:01", 3661},
+            {"+H:MM:SS", "+1:01:01", 3661},
+            {"+Hmmss", "+010101", 3661},
+            {"+H:mm:ss", "+01", 3600},
+            {"+H:mm:ss", "+01:01", 3660},
+            {"+H:mm:ss", "+01:01:01", 3661},
+            {"+H:mm:ss", "+1:01", 3660},
+            {"+H:mm:ss", "+1:01:01", 3661},
+        };
+    }
+
+    @Test(dataProvider="lenientOffsetAdjacentParseValidPatternData")
+    public void test_lenient_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) {
+        TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient()
+                .appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
+        assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds);
+        assertEquals(tmp.get(HOUR_OF_DAY), 12);
+    }
+
+    @Test
+    public void test_lenient_offset_adjacentValidPattern_parse1() {
+        TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient()
+                .appendOffset("+HMMSS", "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse("+10101" + "12");
+        //Equivalent to +101011. In lenient mode, offset will parse upto 6 digit if possible.
+        //It will take 1 digit from HOUR_OF_DAY.
+        assertEquals(tmp.get(OFFSET_SECONDS), 36611);
+        assertEquals(tmp.get(HOUR_OF_DAY), 2);
+    }
+
+  @DataProvider(name="lenientOffsetAdjacentParseInvalidPatternData")
+    Object[][] data_lenient_offset_adjacentParse_invalidPattern() {
+        return new Object[][] {
+            {"+HH", "+01", 3600},
+            {"+HHmm", "+0101", 3660},
+            {"+HHMM", "+0101", 3660},
+            {"+H", "+01", 3600},
+            {"+Hmm", "+0101", 3660},
+            {"+HMM", "+0101", 3660},
+        };
+    }
+
+    @Test(dataProvider="lenientOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class)
+    public void test_lenient_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) {
+       new DateTimeFormatterBuilder().parseLenient().appendOffset(pattern, "Z")
+               .appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
+    }
+
+    @DataProvider(name="badValues")
+    Object[][] data_badOffsetValues() {
+        return new Object[][] {
+            {"+HH", "+24"},
+            {"+HHMM", "-1361"},
+            {"+HH:MM:ss", "+13:12:66"},
+            {"+HH:MM:SS", "+24:60:60"},
+            {"+HHMMSS", "369999"},
+            {"+H:MM", "+28:12"},
+        };
+    }
+
+    @Test(dataProvider="badValues", expectedExceptions=DateTimeParseException.class)
+    public void test_badOffset_parse(String pattern, String offset) {
+        new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter().parse(offset);
+    }
+
+    @Test(expectedExceptions=DateTimeParseException.class)
+    public void test_strict_appendOffsetId() {
+        new DateTimeFormatterBuilder().appendOffsetId().toFormatter().parse("+01");
+    }
+
+    @Test(expectedExceptions=DateTimeParseException.class)
+    public void test_strict_appendOffset_1() {
+        new DateTimeFormatterBuilder().appendOffset("+HH:MM:ss", "Z").toFormatter().parse("+01");
+    }
+
+    @Test(expectedExceptions=DateTimeParseException.class)
+    public void test_strict_appendOffset_2() {
+        new DateTimeFormatterBuilder().appendOffset("+HHMMss", "Z").toFormatter().parse("+01");
+    }
+
+    @Test(expectedExceptions=DateTimeParseException.class)
+    public void test_strict_appendOffset_3() {
+        new DateTimeFormatterBuilder().appendOffset("+H:MM:ss", "Z").toFormatter().parse("+1");
+    }
+
+    @Test(expectedExceptions=DateTimeParseException.class)
+    public void test_strict_appendOffset_4() {
+        new DateTimeFormatterBuilder().appendOffset("+HMMss", "Z").toFormatter().parse("+1");
+    }
+
+    @Test
+    public void test_basic_iso_date() {
+        assertEquals(BASIC_ISO_DATE.parse("20021231+01").get(OFFSET_SECONDS), 3600);
+        assertEquals(BASIC_ISO_DATE.parse("20021231+0101").get(OFFSET_SECONDS), 3660);
+    }
+
 }
diff --git a/ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java b/ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java
index eef99fc..6286a1d 100644
--- a/ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java
+++ b/ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedFieldParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,9 +66,11 @@
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DateTimeParseException;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.WeekFields;
+import java.util.Locale;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
@@ -79,12 +81,17 @@
  */
 @Test
 public class TCKLocalizedFieldParser extends AbstractTestPrinterParser {
-
+    public static final WeekFields WEEKDEF = WeekFields.of(Locale.US);
+    public static final TemporalField WEEK_BASED_YEAR = WEEKDEF.weekBasedYear();
+    public static final TemporalField WEEK_OF_WEEK_BASED_YEAR = WEEKDEF.weekOfWeekBasedYear();
+    public static final TemporalField DAY_OF_WEEK = WEEKDEF.dayOfWeek();
     //-----------------------------------------------------------------------
     @DataProvider(name="FieldPatterns")
     Object[][] provider_fieldPatterns() {
         return new Object[][] {
-            {"e",  "6", 0, 1, 6},
+            {"e", "6", 0, 1, 6},
+            {"ee", "06", 0, 2, 6},
+            {"c",  "6", 0, 1 , 6},
             {"W",  "3", 0, 1, 3},
             {"w",  "29", 0, 2, 29},
             {"ww", "29", 0, 2, 29},
@@ -99,6 +106,7 @@
         WeekFields weekDef = WeekFields.of(locale);
         TemporalField field = null;
         switch(pattern.charAt(0)) {
+            case 'c' :
             case 'e' :
                 field = weekDef.dayOfWeek();
                 break;
@@ -176,9 +184,9 @@
             {"Y-w-e",  "2008-01-1", 0, 9, LocalDate.of(2007, 12, 30)},
             {"Y-w-e",  "2008-52-1", 0, 9, LocalDate.of(2008, 12, 21)},
             {"Y-w-e",  "2008-52-7", 0, 9, LocalDate.of(2008, 12, 27)},
-            {"Y-w-e",  "2009-01-01", 0, 10, LocalDate.of(2008, 12, 28)},
-            {"Y-w-e",  "2009-01-04", 0, 10, LocalDate.of(2008, 12, 31)},
-            {"Y-w-e",  "2009-01-05", 0, 10, LocalDate.of(2009, 1, 1)},
+            {"Y-w-e",  "2009-01-1", 0, 9, LocalDate.of(2008, 12, 28)},
+            {"Y-w-e",  "2009-01-4", 0, 9, LocalDate.of(2008, 12, 31)},
+            {"Y-w-e",  "2009-01-5", 0, 9, LocalDate.of(2009, 1, 1)},
        };
     }
 
@@ -202,4 +210,77 @@
         }
     }
 
+    //-----------------------------------------------------------------------
+    @DataProvider(name = "adjacentValuePatterns1")
+    Object[][] provider_adjacentValuePatterns1() {
+        return new Object[][] {
+                {"YYww", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, "1612", 2016, 12},
+                {"YYYYww", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, "201612", 2016, 12},
+        };
+    }
+
+    @Test(dataProvider = "adjacentValuePatterns1")
+    public void test_adjacentValuePatterns1(String pattern, TemporalField field1, TemporalField field2,
+            String text, int expected1, int expected2) {
+        DateTimeFormatter df = new DateTimeFormatterBuilder()
+                .appendPattern(pattern).toFormatter(Locale.US);
+        ParsePosition ppos = new ParsePosition(0);
+        TemporalAccessor parsed = df.parseUnresolved(text, ppos);
+        assertEquals(parsed.get(field1), expected1);
+        assertEquals(parsed.get(field2), expected2);
+    }
+
+    @DataProvider(name = "adjacentValuePatterns2")
+    Object[][] provider_adjacentValuePatterns2() {
+        return new Object[][] {
+                {"YYYYwwc", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, DAY_OF_WEEK,
+                        "2016121", 2016, 12, 1},
+                {"YYYYwwee", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, DAY_OF_WEEK,
+                        "20161201", 2016, 12, 1},
+                {"YYYYwwe", WEEK_BASED_YEAR, WEEK_OF_WEEK_BASED_YEAR, DAY_OF_WEEK,
+                        "2016121", 2016, 12, 1},
+        };
+    }
+
+    @Test(dataProvider = "adjacentValuePatterns2")
+    public void test_adjacentValuePatterns2(String pattern, TemporalField field1, TemporalField field2,
+            TemporalField field3, String text, int expected1, int expected2, int expected3) {
+        DateTimeFormatter df = new DateTimeFormatterBuilder()
+                .appendPattern(pattern).toFormatter(Locale.US);
+        ParsePosition ppos = new ParsePosition(0);
+        TemporalAccessor parsed = df.parseUnresolved(text, ppos);
+        assertEquals(parsed.get(field1), expected1);
+        assertEquals(parsed.get(field2), expected2);
+        assertEquals(parsed.get(field3), expected3);
+    }
+
+    @Test
+    public void test_adjacentValuePatterns3() {
+        String pattern = "yyyyMMddwwc";
+        String text =  "20120720296";
+        DateTimeFormatter df = new DateTimeFormatterBuilder()
+                .appendPattern(pattern).toFormatter(Locale.US);
+        ParsePosition ppos = new ParsePosition(0);
+        TemporalAccessor parsed = df.parseUnresolved(text, ppos);
+        assertEquals(parsed.get(DAY_OF_WEEK), 6);
+        assertEquals(parsed.get(WEEK_OF_WEEK_BASED_YEAR), 29);
+        LocalDate result = LocalDate.parse(text, df);
+        LocalDate expectedValue = LocalDate.of(2012, 07, 20);
+        assertEquals(result, expectedValue, "LocalDate incorrect for " + pattern);
+    }
+
+    @DataProvider(name = "invalidPatterns")
+    Object[][] provider_invalidPatterns() {
+        return new Object[][] {
+            {"W", "01"},
+            {"c", "01"},
+            {"e", "01"},
+            {"yyyyMMddwwc", "201207202906"}, //  1 extra digit in the input
+        };
+    }
+
+    @Test(dataProvider = "invalidPatterns", expectedExceptions = DateTimeParseException.class)
+    public void test_invalidPatterns(String pattern, String value) {
+        DateTimeFormatter.ofPattern(pattern).parse(value);
+    }
 }
diff --git a/ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java b/ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java
new file mode 100644
index 0000000..d0a1f18
--- /dev/null
+++ b/ojluni/src/test/java/time/tck/java/time/format/TCKLocalizedOffsetIdPrinterParser.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package tck.java.time.format;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+import org.testng.annotations.Test;
+
+/**
+ * Test localized behavior of formatter.
+ */
+@Test
+public class TCKLocalizedOffsetIdPrinterParser {
+    @Test
+    public void test_localized_offset_parse() {
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.S O")
+                                                       .withLocale(Locale.ENGLISH);
+        String date = formatter.format(ZonedDateTime.now(ZoneOffset.UTC));
+        formatter.parse(date) ;
+     }
+}
diff --git a/ojluni/src/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java b/ojluni/src/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java
index 76cfa56..704e240 100644
--- a/ojluni/src/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java
+++ b/ojluni/src/test/java/time/tck/java/time/format/TCKOffsetPrinterParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,6 +93,14 @@
     private static final ZoneOffset OFFSET_M000045 = ZoneOffset.ofHoursMinutesSeconds(0, 0, -45);
     private static final LocalDateTime DT_2012_06_30_12_30_40 = LocalDateTime.of(2012, 6, 30, 12, 30, 40);
 
+    private static final ZoneOffset OFFSET_P1100 = ZoneOffset.ofHours(11);
+    private static final ZoneOffset OFFSET_P1123 = ZoneOffset.ofHoursMinutes(11, 23);
+    private static final ZoneOffset OFFSET_P1023 = ZoneOffset.ofHoursMinutes(10, 23);
+    private static final ZoneOffset OFFSET_P112345 = ZoneOffset.ofHoursMinutesSeconds(11, 23, 45);
+    private static final ZoneOffset OFFSET_P100045 = ZoneOffset.ofHoursMinutesSeconds(10, 0, 45);
+    private static final ZoneOffset OFFSET_M1100 = ZoneOffset.ofHours(-11);
+    private static final ZoneOffset OFFSET_M1123 = ZoneOffset.ofHoursMinutes(-11, -23);
+    private static final ZoneOffset OFFSET_M112345 = ZoneOffset.ofHoursMinutesSeconds(-11, -23, -45);
     private DateTimeFormatterBuilder builder;
 
     @BeforeMethod
@@ -199,6 +207,236 @@
                 {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23:00"},
                 {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23:45"},
                 {"+HH:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"},
+
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+01:23"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+00:23"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+01:23:45"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-01:23"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-00:23"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-01:23:45"},
+                {"+HH:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00:00:45"},
+
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+01"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+0123"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0023"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+012345"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+000045"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-01"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-0123"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0023"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-012345"},
+                {"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-000045"},
+
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "Z"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
+
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+00045"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+10000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+12300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+02300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-10000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-12300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-02300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
+
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+00045"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
+
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11"},
+                {"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11"},
+
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+1123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-1123"},
+
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+1100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+1123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+1000"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-1100"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-1123"},
+
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
+                {"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23"},
+
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+1100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+100045"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-1100"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
+
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
+                {"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
+
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+110000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+112300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+102300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-110000"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-112300"},
+                {"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
+
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23:00"},
+                {"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
+
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
+                {"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
+
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+100045"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
+                {"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
         };
     }
 
diff --git a/ojluni/src/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java b/ojluni/src/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java
index 122da86..c165688 100644
--- a/ojluni/src/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java
+++ b/ojluni/src/test/java/time/tck/java/time/format/TCKZoneIdPrinterParser.java
@@ -152,144 +152,182 @@
     @DataProvider(name="parseSuccess")
     Object[][] data_parseSuccess() {
         return new Object[][] {
-                {"Z", 1, -1, ZoneId.of("Z")},
-                {"UTC", 3, -1, ZoneId.of("UTC")},
-                {"UT", 2, -1, ZoneId.of("UT")},
-                {"GMT", 3, -1, ZoneId.of("GMT")},
+                {"Z", 1, -1, ZoneId.of("Z"), true},
+                {"UTC", 3, -1, ZoneId.of("UTC"), false},
+                {"UT", 2, -1, ZoneId.of("UT"), false},
+                {"GMT", 3, -1, ZoneId.of("GMT"), false},
+                {"GMT0", 4, -1, ZoneId.of("GMT0"), false},
 
-                {"+00:00", 6, -1, ZoneOffset.UTC},
-                {"UTC+00:00", 9, -1, ZoneId.of("UTC")},
-                {"UT+00:00", 8, -1, ZoneId.of("UT")},
-                {"GMT+00:00", 9, -1, ZoneId.of("GMT")},
-                {"-00:00", 6, -1, ZoneOffset.UTC},
-                {"UTC-00:00", 9, -1, ZoneId.of("UTC")},
-                {"UT-00:00", 8, -1, ZoneId.of("UT")},
-                {"GMT-00:00", 9, -1, ZoneId.of("GMT")},
+                {"+00:00", 6, -1, ZoneOffset.UTC, true},
+                {"UTC+00:00", 9, -1, ZoneId.of("UTC"), false},
+                {"UT+00:00", 8, -1, ZoneId.of("UT"), false},
+                {"GMT+00:00", 9, -1, ZoneId.of("GMT"), false},
+                {"-00:00", 6, -1, ZoneOffset.UTC, true},
+                {"UTC-00:00", 9, -1, ZoneId.of("UTC"), false},
+                {"UT-00:00", 8, -1, ZoneId.of("UT"), false},
+                {"GMT-00:00", 9, -1, ZoneId.of("GMT"), false},
 
-                {"+01:30", 6, -1, ZoneOffset.ofHoursMinutes(1, 30)},
-                {"UTC+01:30", 9, -1, ZoneId.of("UTC+01:30")},
-                {"UT+02:30", 8, -1, ZoneId.of("UT+02:30")},
-                {"GMT+03:30", 9, -1, ZoneId.of("GMT+03:30")},
-                {"-01:30", 6, -1, ZoneOffset.ofHoursMinutes(-1, -30)},
-                {"UTC-01:30", 9, -1, ZoneId.of("UTC-01:30")},
-                {"UT-02:30", 8, -1, ZoneId.of("UT-02:30")},
-                {"GMT-03:30", 9, -1, ZoneId.of("GMT-03:30")},
+                {"+01:30", 6, -1, ZoneOffset.ofHoursMinutes(1, 30), true},
+                {"UTC+01:30", 9, -1, ZoneId.of("UTC+01:30"), false},
+                {"UT+02:30", 8, -1, ZoneId.of("UT+02:30"), false},
+                {"GMT+03:30", 9, -1, ZoneId.of("GMT+03:30"), false},
+                {"-01:30", 6, -1, ZoneOffset.ofHoursMinutes(-1, -30), true},
+                {"UTC-01:30", 9, -1, ZoneId.of("UTC-01:30"), false},
+                {"UT-02:30", 8, -1, ZoneId.of("UT-02:30"), false},
+                {"GMT-03:30", 9, -1, ZoneId.of("GMT-03:30"), false},
 
                 // fallback to UTC
-                {"UTC-01:WW", 3, -1, ZoneId.of("UTC")},
-                {"UT-02:WW", 2, -1, ZoneId.of("UT")},
-                {"GMT-03:WW", 3, -1, ZoneId.of("GMT")},
-                {"Z0", 1, -1, ZoneOffset.UTC},
-                {"UTC1", 3, -1, ZoneId.of("UTC")},
+                {"UTC-01:WW", 3, -1, ZoneId.of("UTC"), false},
+                {"UT-02:WW", 2, -1, ZoneId.of("UT"), false},
+                {"GMT-03:WW", 3, -1, ZoneId.of("GMT"), false},
+                {"Z0", 1, -1, ZoneOffset.UTC, true},
+                {"UTC1", 3, -1, ZoneId.of("UTC"), false},
 
                 // Z not parsed as zero
-                {"UTCZ", 3, -1, ZoneId.of("UTC")},
-                {"UTZ", 2, -1, ZoneId.of("UT")},
-                {"GMTZ", 3, -1, ZoneId.of("GMT")},
+                {"UTCZ", 3, -1, ZoneId.of("UTC"), false},
+                {"UTZ", 2, -1, ZoneId.of("UT"), false},
+                {"GMTZ", 3, -1, ZoneId.of("GMT"), false},
 
                 // 0 not parsed
-                {"UTC0", 3, -1, ZoneId.of("UTC")},
-                {"UT0", 2, -1, ZoneId.of("UT")},
+                {"UTC0", 3, -1, ZoneId.of("UTC"), false},
+                {"UT0", 2, -1, ZoneId.of("UT"), false},
 
                 // fail to parse
-                {"", 0, 0, null},
-                {"A", 0, 0, null},
-                {"UZ", 0, 0, null},
-                {"GMA", 0, 0, null},
-                {"0", 0, 0, null},
-                {"+", 0, 0, null},
-                {"-", 0, 0, null},
+                {"", 0, 0, null, false},
+                {"A", 0, 0, null, false},
+                {"UZ", 0, 0, null, false},
+                {"GMA", 0, 0, null, false},
+                {"0", 0, 0, null, false},
+                {"+", 0, 0, null, false},
+                {"-", 0, 0, null, false},
 
                 // zone IDs
-                {"Europe/London", 13, -1, ZoneId.of("Europe/London")},
-                {"America/New_York", 16, -1, ZoneId.of("America/New_York")},
-                {"America/Bogusville", 0, 0, null},
+                {"Europe/London", 13, -1, ZoneId.of("Europe/London"), false},
+                {"America/New_York", 16, -1, ZoneId.of("America/New_York"), false},
+                {"America/Bogusville", 0, 0, null, false},
         };
     }
 
     @Test(dataProvider="parseSuccess")
-    public void test_parseSuccess_plain(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) {
+    public void test_ZoneId_parseSuccess_plain(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
         builder.appendZoneId();
-        TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text, pos);
-        assertEquals(pos.getErrorIndex(), expectedErrorIndex, "Incorrect error index parsing: " + text);
-        assertEquals(pos.getIndex(), expectedIndex, "Incorrect index parsing: " + text);
-        if (expected != null) {
-            assertEquals(parsed.query(TemporalQueries.zoneId()), expected, "Incorrect zoneId parsing: " + text);
-            assertEquals(parsed.query(TemporalQueries.offset()), null, "Incorrect offset parsing: " + text);
-            assertEquals(parsed.query(TemporalQueries.zone()), expected, "Incorrect zone parsing: " + text);
-        } else {
-            assertEquals(parsed, null);
-        }
+        test(text, expectedIndex, expectedErrorIndex, expected, isZoneOffset);
     }
 
     @Test(dataProvider="parseSuccess")
-    public void test_parseSuccess_prefix(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) {
+    public void test_ZoneId_parseSuccess_prefix(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
         builder.appendZoneId();
         pos.setIndex(3);
-        String prefixText = "XXX" + text;
-        TemporalAccessor parsed = builder.toFormatter().parseUnresolved(prefixText, pos);
-        assertEquals(pos.getErrorIndex(), expectedErrorIndex >= 0  ? expectedErrorIndex + 3 : expectedErrorIndex, "Incorrect error index parsing: " + prefixText);
-        assertEquals(pos.getIndex(), expectedIndex + 3, "Incorrect index parsing: " + prefixText);
-        if (expected != null) {
-            assertEquals(parsed.query(TemporalQueries.zoneId()), expected, "Incorrect zoneId parsing: " + prefixText);
-            assertEquals(parsed.query(TemporalQueries.offset()), null, "Incorrect offset parsing: " + prefixText);
-            assertEquals(parsed.query(TemporalQueries.zone()), expected, "Incorrect zone parsing: " + prefixText);
-        } else {
-            assertEquals(parsed, null);
-        }
+        test("XXX" + text,
+             expectedIndex + 3,
+             expectedErrorIndex >= 0 ? expectedErrorIndex + 3 : expectedErrorIndex,
+             expected, isZoneOffset);
     }
 
     @Test(dataProvider="parseSuccess")
-    public void test_parseSuccess_suffix(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) {
+    public void test_ZoneId_parseSuccess_suffix(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
         builder.appendZoneId();
-        String suffixText = text + "XXX";
-        TemporalAccessor parsed = builder.toFormatter().parseUnresolved(suffixText, pos);
-        assertEquals(pos.getErrorIndex(), expectedErrorIndex, "Incorrect error index parsing: " + suffixText);
-        assertEquals(pos.getIndex(), expectedIndex, "Incorrect index parsing: " + suffixText);
-        if (expected != null) {
-            assertEquals(parsed.query(TemporalQueries.zoneId()), expected, "Incorrect zoneId parsing: " + suffixText);
-            assertEquals(parsed.query(TemporalQueries.offset()), null, "Incorrect offset parsing: " + suffixText);
-            assertEquals(parsed.query(TemporalQueries.zone()), expected, "Incorrect zone parsing: " + suffixText);
-        } else {
-            assertEquals(parsed, null);
-        }
+        test(text + "XXX", expectedIndex, expectedErrorIndex, expected, isZoneOffset);
     }
 
     @Test(dataProvider="parseSuccess")
-    public void test_parseSuccess_caseSensitive(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) {
+    public void test_ZoneId_parseSuccess_caseSensitive(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
         builder.parseCaseSensitive().appendZoneId();
-        String lcText = text.toLowerCase(Locale.ENGLISH);
-        TemporalAccessor parsed = builder.toFormatter().parseUnresolved(lcText, pos);
+
         if (text.matches("[^A-Z]*[A-Z].*")) {  // if input has letters
+            String lcText = text.toLowerCase(Locale.ENGLISH);
+            TemporalAccessor parsed = builder.toFormatter().parseUnresolved(lcText, pos);
             assertEquals(pos.getErrorIndex() >= 0, true);
             assertEquals(pos.getIndex(), 0);
             assertEquals(parsed, null);
         } else {
-            // case sensitive made no difference
-            assertEquals(pos.getIndex(), expectedIndex, "Incorrect index parsing: " + lcText);
-            assertEquals(pos.getErrorIndex(), expectedErrorIndex, "Incorrect error index parsing: " + lcText);
-            if (expected != null) {
-                assertEquals(parsed.query(TemporalQueries.zoneId()), expected);
-                assertEquals(parsed.query(TemporalQueries.offset()), null);
-                assertEquals(parsed.query(TemporalQueries.zone()), expected);
-            } else {
-                assertEquals(parsed, null);
-            }
+            test(text.toLowerCase(Locale.ENGLISH), expectedIndex, expectedErrorIndex, expected, isZoneOffset);
         }
     }
 
     @Test(dataProvider="parseSuccess")
-    public void test_parseSuccess_caseInsensitive(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected) {
+    public void test_ZoneId_parseSuccess_caseInsensitive(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
         builder.parseCaseInsensitive().appendZoneId();
-        String lcText = text.toLowerCase(Locale.ENGLISH);
-        TemporalAccessor parsed = builder.toFormatter().parseUnresolved(lcText, pos);
-        assertEquals(pos.getErrorIndex(), expectedErrorIndex, "Incorrect error index parsing: " + lcText);
-        assertEquals(pos.getIndex(), expectedIndex, "Incorrect index parsing: " + lcText);
+        test(text.toLowerCase(Locale.ENGLISH), expectedIndex, expectedErrorIndex, expected, isZoneOffset);
+    }
+
+    @Test(dataProvider="parseSuccess")
+    public void test_ZoneOrOffsetId_parseSuccess_plain(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
+        builder.appendZoneOrOffsetId();
+        test(text, expectedIndex, expectedErrorIndex, expected, isZoneOffset);
+    }
+
+    @Test(dataProvider="parseSuccess")
+    public void test_ZoneOrOffsetId_parseSuccess_prefix(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
+        builder.appendZoneOrOffsetId();
+        pos.setIndex(3);
+        test("XXX" + text,
+             expectedIndex + 3,
+             expectedErrorIndex >= 0 ? expectedErrorIndex + 3 : expectedErrorIndex,
+             expected, isZoneOffset);
+    }
+
+    @Test(dataProvider="parseSuccess")
+    public void test_ZoneOrOffsetId_parseSuccess_suffix(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
+        builder.appendZoneOrOffsetId();
+        test(text + "XXX", expectedIndex, expectedErrorIndex, expected, isZoneOffset);
+    }
+
+    @Test(dataProvider="parseSuccess")
+    public void test_ZoneOrOffsetId_parseSuccess_caseSensitive(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
+        builder.parseCaseSensitive().appendZoneOrOffsetId();
+        if (text.matches("[^A-Z]*[A-Z].*")) {  // if input has letters
+            String lcText = text.toLowerCase(Locale.ENGLISH);
+            TemporalAccessor parsed = builder.toFormatter().parseUnresolved(lcText, pos);
+            assertEquals(pos.getErrorIndex() >= 0, true);
+            assertEquals(pos.getIndex(), 0);
+            assertEquals(parsed, null);
+        } else {
+            test(text.toLowerCase(Locale.ENGLISH), expectedIndex, expectedErrorIndex, expected, isZoneOffset);
+        }
+    }
+
+    @Test(dataProvider="parseSuccess")
+    public void test_ZoneOrOffsetIdparseSuccess_caseInsensitive(
+        String text, int expectedIndex, int expectedErrorIndex, ZoneId expected, boolean isZoneOffset)
+    {
+        builder.parseCaseInsensitive().appendZoneOrOffsetId();
+        test(text.toLowerCase(Locale.ENGLISH), expectedIndex, expectedErrorIndex, expected, isZoneOffset);
+    }
+
+    private void test(String text, int expectedIndex, int expectedErrorIndex, ZoneId expected,
+                      boolean isZoneOffset) {
+        TemporalAccessor parsed = builder.toFormatter().parseUnresolved(text, pos);
+        assertEquals(pos.getErrorIndex(), expectedErrorIndex, "Incorrect error index parsing: " + text);
+        assertEquals(pos.getIndex(), expectedIndex, "Incorrect index parsing: " + text);
         if (expected != null) {
-            ZoneId zid = parsed.query(TemporalQueries.zoneId());
-            assertEquals(parsed.query(TemporalQueries.zoneId()), expected, "Incorrect zoneId parsing: " + lcText);
-            assertEquals(parsed.query(TemporalQueries.offset()), null, "Incorrect offset parsing: " + lcText);
-            assertEquals(parsed.query(TemporalQueries.zone()), expected, "Incorrect zone parsing: " + lcText);
+            assertEquals(parsed.query(TemporalQueries.zoneId()),
+                         expected,
+                         "Incorrect zoneId parsing: " + text);
+            assertEquals(parsed.query(TemporalQueries.offset()),
+                         isZoneOffset ? expected : null,
+                         "Incorrect offset parsing: " + text);
+            assertEquals(parsed.query(TemporalQueries.zone()),
+                         expected,
+                         "Incorrect zone parsing: " + text);
         } else {
             assertEquals(parsed, null);
         }
diff --git a/ojluni/src/test/java/time/tck/java/time/serial/TCKZoneIdSerialization.java b/ojluni/src/test/java/time/tck/java/time/serial/TCKZoneIdSerialization.java
index c6f3abe..34c79c3 100644
--- a/ojluni/src/test/java/time/tck/java/time/serial/TCKZoneIdSerialization.java
+++ b/ojluni/src/test/java/time/tck/java/time/serial/TCKZoneIdSerialization.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,8 +63,11 @@
 import org.testng.annotations.Test;
 import tck.java.time.AbstractTCKTest;
 
-import java.io.*;
-import java.lang.reflect.Field;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamConstants;
 import java.time.DateTimeException;
 import java.time.ZoneId;
 import java.time.zone.ZoneRulesException;
@@ -153,10 +156,8 @@
 
     private ZoneId deserialize(String id) throws Exception {
         String serClass = ZoneId.class.getPackage().getName() + ".Ser";
-        Class<?> serCls = Class.forName(serClass);
-        Field field = serCls.getDeclaredField("serialVersionUID");
-        field.setAccessible(true);
-        long serVer = (Long) field.get(null);
+        long serVer = getSUID(ZoneId.class);
+
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         try (DataOutputStream dos = new DataOutputStream(baos)) {
             dos.writeShort(ObjectStreamConstants.STREAM_MAGIC);
diff --git a/ojluni/src/test/java/time/tck/java/time/temporal/TCKIsoFields.java b/ojluni/src/test/java/time/tck/java/time/temporal/TCKIsoFields.java
index d607571..c86805f 100644
--- a/ojluni/src/test/java/time/tck/java/time/temporal/TCKIsoFields.java
+++ b/ojluni/src/test/java/time/tck/java/time/temporal/TCKIsoFields.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,12 +71,15 @@
 import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.chrono.ThaiBuddhistDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.DateTimeParseException;
 import java.time.format.ResolverStyle;
 import java.time.temporal.IsoFields;
 import java.time.temporal.Temporal;
+import java.time.temporal.TemporalField;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 
 import org.testng.annotations.DataProvider;
@@ -439,6 +442,45 @@
     }
 
     //-----------------------------------------------------------------------
+    // rangeRefinedBy
+    //-----------------------------------------------------------------------
+    @DataProvider(name="isofields")
+    Object[][] data_isofields() {
+        return new Object[][] {
+               {IsoFields.DAY_OF_QUARTER, 49, ValueRange.of(1, 91)},
+               {IsoFields.QUARTER_OF_YEAR, 2, ValueRange.of(1, 4)},
+               {IsoFields.WEEK_OF_WEEK_BASED_YEAR, 20, ValueRange.of(1, 52)},
+               {IsoFields.WEEK_BASED_YEAR, 2016, ValueRange.of(LocalDate.MIN.getYear(),
+                                                               LocalDate.MAX.getYear())},
+        };
+    }
+
+    @Test(dataProvider = "isofields")
+    public void test_isofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) {
+        LocalDate date = LocalDate.of(2016, 5, 19);
+        assertEquals(field.rangeRefinedBy(date), valueRange);
+    }
+
+    @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class)
+    public void test_nonisofields_rangerefinedby(TemporalField field, int value, ValueRange valueRange) {
+        field.rangeRefinedBy(ThaiBuddhistDate.now());
+    }
+
+    //-----------------------------------------------------------------------
+    // getFrom
+    //-----------------------------------------------------------------------
+    @Test(dataProvider = "isofields")
+    public void test_isofields_getFrom(TemporalField field, int value, ValueRange valueRange) {
+        LocalDate date = LocalDate.of(2016, 5, 19);
+        assertEquals(field.getFrom(date), value);
+    }
+
+    @Test(dataProvider = "isofields", expectedExceptions = UnsupportedTemporalTypeException.class)
+    public void test_nonisofields_getFrom(TemporalField field, int value, ValueRange valueRange) {
+        field.getFrom(ThaiBuddhistDate.now());
+    }
+
+    //-----------------------------------------------------------------------
     public void test_loop() {
         // loop round at least one 400 year cycle, including before 1970
         LocalDate date = LocalDate.of(1960, 1, 5);  // Tuseday of week 1 1960
diff --git a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java
index 58e2ff5..3c0c14c 100644
--- a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java
+++ b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneOffsetTransitionRule.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -156,6 +156,13 @@
                 OFFSET_0200, OFFSET_0200, OFFSET_0300);
     }
 
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void test_factory_nonZeroTimeNanos() {
+        ZoneOffsetTransitionRule.of(
+            Month.MARCH, 20, DayOfWeek.SUNDAY, LocalTime.of(1, 2, 3, 400_000_000),
+            false, TimeDefinition.WALL, OFFSET_0200, OFFSET_0200, OFFSET_0300);
+    }
+
     //-----------------------------------------------------------------------
     // getters
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java
index 2781ca5..9eae05e 100644
--- a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java
+++ b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRules.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -112,11 +112,13 @@
         return ZoneId.of("Europe/London").getRules();
     }
 
+    @Test
     public void test_London() {
         ZoneRules test = europeLondon();
         assertEquals(test.isFixedOffset(), false);
     }
 
+    @Test
     public void test_London_preTimeZones() {
         ZoneRules test = europeLondon();
         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
@@ -129,6 +131,7 @@
         assertEquals(test.isDaylightSavings(instant), false);
     }
 
+    @Test
     public void test_London_getOffset() {
         ZoneRules test = europeLondon();
         assertEquals(test.getOffset(createInstant(2008, 1, 1, ZoneOffset.UTC)), OFFSET_ZERO);
@@ -145,6 +148,7 @@
         assertEquals(test.getOffset(createInstant(2008, 12, 1, ZoneOffset.UTC)), OFFSET_ZERO);
     }
 
+    @Test
     public void test_London_getOffset_toDST() {
         ZoneRules test = europeLondon();
         assertEquals(test.getOffset(createInstant(2008, 3, 24, ZoneOffset.UTC)), OFFSET_ZERO);
@@ -160,6 +164,7 @@
         assertEquals(test.getOffset(createInstant(2008, 3, 30, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PONE);
     }
 
+    @Test
     public void test_London_getOffset_fromDST() {
         ZoneRules test = europeLondon();
         assertEquals(test.getOffset(createInstant(2008, 10, 24, ZoneOffset.UTC)), OFFSET_PONE);
@@ -175,6 +180,7 @@
         assertEquals(test.getOffset(createInstant(2008, 10, 26, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_ZERO);
     }
 
+    @Test
     public void test_London_getOffsetInfo() {
         ZoneRules test = europeLondon();
         checkOffset(test, createLDT(2008, 1, 1), OFFSET_ZERO, 1);
@@ -191,6 +197,7 @@
         checkOffset(test, createLDT(2008, 12, 1), OFFSET_ZERO, 1);
     }
 
+    @Test
     public void test_London_getOffsetInfo_toDST() {
         ZoneRules test = europeLondon();
         checkOffset(test, createLDT(2008, 3, 24), OFFSET_ZERO, 1);
@@ -206,6 +213,7 @@
         checkOffset(test, LocalDateTime.of(2008, 3, 30, 2, 0, 0, 0), OFFSET_PONE, 1);
     }
 
+    @Test
     public void test_London_getOffsetInfo_fromDST() {
         ZoneRules test = europeLondon();
         checkOffset(test, createLDT(2008, 10, 24), OFFSET_PONE, 1);
@@ -221,6 +229,7 @@
         checkOffset(test, LocalDateTime.of(2008, 10, 26, 2, 0, 0, 0), OFFSET_ZERO, 1);
     }
 
+    @Test
     public void test_London_getOffsetInfo_gap() {
         ZoneRules test = europeLondon();
         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 30, 1, 0, 0, 0);
@@ -246,6 +255,7 @@
         assertEquals(trans.hashCode(), otherTrans.hashCode());
     }
 
+    @Test
     public void test_London_getOffsetInfo_overlap() {
         ZoneRules test = europeLondon();
         final LocalDateTime dateTime = LocalDateTime.of(2008, 10, 26, 1, 0, 0, 0);
@@ -272,6 +282,7 @@
         assertEquals(trans.hashCode(), otherTrans.hashCode());
     }
 
+    @Test
     public void test_London_getStandardOffset() {
         ZoneRules test = europeLondon();
         ZonedDateTime zdt = createZDT(1840, 1, 1, ZoneOffset.UTC);
@@ -288,6 +299,7 @@
         }
     }
 
+    @Test
     public void test_London_getTransitions() {
         ZoneRules test = europeLondon();
         List<ZoneOffsetTransition> trans = test.getTransitions();
@@ -365,6 +377,7 @@
         assertEquals(it.hasNext(), false);
     }
 
+    @Test
     public void test_London_getTransitionRules() {
         ZoneRules test = europeLondon();
         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
@@ -394,6 +407,7 @@
     }
 
     //-----------------------------------------------------------------------
+    @Test
     public void test_London_nextTransition_historic() {
         ZoneRules test = europeLondon();
         List<ZoneOffsetTransition> trans = test.getTransitions();
@@ -410,6 +424,7 @@
         }
     }
 
+    @Test
     public void test_London_nextTransition_rulesBased() {
         ZoneRules test = europeLondon();
         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
@@ -431,6 +446,7 @@
         }
     }
 
+    @Test
     public void test_London_nextTransition_lastYear() {
         ZoneRules test = europeLondon();
         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
@@ -439,6 +455,7 @@
     }
 
     //-----------------------------------------------------------------------
+    @Test
     public void test_London_previousTransition_historic() {
         ZoneRules test = europeLondon();
         List<ZoneOffsetTransition> trans = test.getTransitions();
@@ -457,6 +474,7 @@
         }
     }
 
+    @Test
     public void test_London_previousTransition_rulesBased() {
         ZoneRules test = europeLondon();
         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
@@ -494,11 +512,13 @@
         return ZoneId.of("Europe/Paris").getRules();
     }
 
+    @Test
     public void test_Paris() {
         ZoneRules test = europeParis();
         assertEquals(test.isFixedOffset(), false);
     }
 
+    @Test
     public void test_Paris_preTimeZones() {
         ZoneRules test = europeParis();
         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
@@ -511,6 +531,7 @@
         assertEquals(test.isDaylightSavings(instant), false);
     }
 
+    @Test
     public void test_Paris_getOffset() {
         ZoneRules test = europeParis();
         assertEquals(test.getOffset(createInstant(2008, 1, 1, ZoneOffset.UTC)), OFFSET_PONE);
@@ -527,6 +548,7 @@
         assertEquals(test.getOffset(createInstant(2008, 12, 1, ZoneOffset.UTC)), OFFSET_PONE);
     }
 
+    @Test
     public void test_Paris_getOffset_toDST() {
         ZoneRules test = europeParis();
         assertEquals(test.getOffset(createInstant(2008, 3, 24, ZoneOffset.UTC)), OFFSET_PONE);
@@ -542,6 +564,7 @@
         assertEquals(test.getOffset(createInstant(2008, 3, 30, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PTWO);
     }
 
+    @Test
     public void test_Paris_getOffset_fromDST() {
         ZoneRules test = europeParis();
         assertEquals(test.getOffset(createInstant(2008, 10, 24, ZoneOffset.UTC)), OFFSET_PTWO);
@@ -557,6 +580,7 @@
         assertEquals(test.getOffset(createInstant(2008, 10, 26, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PONE);
     }
 
+    @Test
     public void test_Paris_getOffsetInfo() {
         ZoneRules test = europeParis();
         checkOffset(test, createLDT(2008, 1, 1), OFFSET_PONE, 1);
@@ -573,6 +597,7 @@
         checkOffset(test, createLDT(2008, 12, 1), OFFSET_PONE, 1);
     }
 
+    @Test
     public void test_Paris_getOffsetInfo_toDST() {
         ZoneRules test = europeParis();
         checkOffset(test, createLDT(2008, 3, 24), OFFSET_PONE, 1);
@@ -588,6 +613,7 @@
         checkOffset(test, LocalDateTime.of(2008, 3, 30, 3, 0, 0, 0), OFFSET_PTWO, 1);
     }
 
+    @Test
     public void test_Paris_getOffsetInfo_fromDST() {
         ZoneRules test = europeParis();
         checkOffset(test, createLDT(2008, 10, 24), OFFSET_PTWO, 1);
@@ -603,6 +629,7 @@
         checkOffset(test, LocalDateTime.of(2008, 10, 26, 3, 0, 0, 0), OFFSET_PONE, 1);
     }
 
+    @Test
     public void test_Paris_getOffsetInfo_gap() {
         ZoneRules test = europeParis();
         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 30, 2, 0, 0, 0);
@@ -626,6 +653,7 @@
         assertEquals(trans.hashCode(), otherTrans.hashCode());
     }
 
+    @Test
     public void test_Paris_getOffsetInfo_overlap() {
         ZoneRules test = europeParis();
         final LocalDateTime dateTime = LocalDateTime.of(2008, 10, 26, 2, 0, 0, 0);
@@ -650,6 +678,7 @@
         assertEquals(trans.hashCode(), otherTrans.hashCode());
     }
 
+    @Test
     public void test_Paris_getStandardOffset() {
         ZoneRules test = europeParis();
         ZonedDateTime zdt = createZDT(1840, 1, 1, ZoneOffset.UTC);
@@ -677,11 +706,13 @@
         return ZoneId.of("America/New_York").getRules();
     }
 
+    @Test
     public void test_NewYork() {
         ZoneRules test = americaNewYork();
         assertEquals(test.isFixedOffset(), false);
     }
 
+    @Test
     public void test_NewYork_preTimeZones() {
         ZoneRules test = americaNewYork();
         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
@@ -694,6 +725,7 @@
         assertEquals(test.isDaylightSavings(instant), false);
     }
 
+    @Test
     public void test_NewYork_getOffset() {
         ZoneRules test = americaNewYork();
         ZoneOffset offset = ZoneOffset.ofHours(-5);
@@ -723,6 +755,7 @@
         assertEquals(test.getOffset(createInstant(2008, 12, 28, offset)), ZoneOffset.ofHours(-5));
     }
 
+    @Test
     public void test_NewYork_getOffset_toDST() {
         ZoneRules test = americaNewYork();
         ZoneOffset offset = ZoneOffset.ofHours(-5);
@@ -738,6 +771,7 @@
         assertEquals(test.getOffset(createInstant(2008, 3, 9, 2, 0, 0, 0, offset)), ZoneOffset.ofHours(-4));
     }
 
+    @Test
     public void test_NewYork_getOffset_fromDST() {
         ZoneRules test = americaNewYork();
         ZoneOffset offset = ZoneOffset.ofHours(-4);
@@ -753,6 +787,7 @@
         assertEquals(test.getOffset(createInstant(2008, 11, 2, 2, 0, 0, 0, offset)), ZoneOffset.ofHours(-5));
     }
 
+    @Test
     public void test_NewYork_getOffsetInfo() {
         ZoneRules test = americaNewYork();
         checkOffset(test, createLDT(2008, 1, 1), ZoneOffset.ofHours(-5), 1);
@@ -781,6 +816,7 @@
         checkOffset(test, createLDT(2008, 12, 28), ZoneOffset.ofHours(-5), 1);
     }
 
+    @Test
     public void test_NewYork_getOffsetInfo_toDST() {
         ZoneRules test = americaNewYork();
         checkOffset(test, createLDT(2008, 3, 8), ZoneOffset.ofHours(-5), 1);
@@ -795,6 +831,7 @@
         checkOffset(test, LocalDateTime.of(2008, 3, 9, 3, 0, 0, 0), ZoneOffset.ofHours(-4), 1);
     }
 
+    @Test
     public void test_NewYork_getOffsetInfo_fromDST() {
         ZoneRules test = americaNewYork();
         checkOffset(test, createLDT(2008, 11, 1), ZoneOffset.ofHours(-4), 1);
@@ -809,6 +846,7 @@
         checkOffset(test, LocalDateTime.of(2008, 11, 2, 2, 0, 0, 0), ZoneOffset.ofHours(-5), 1);
     }
 
+    @Test
     public void test_NewYork_getOffsetInfo_gap() {
         ZoneRules test = americaNewYork();
         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 9, 2, 0, 0, 0);
@@ -832,6 +870,7 @@
         assertEquals(trans.hashCode(), otherTrans.hashCode());
     }
 
+    @Test
     public void test_NewYork_getOffsetInfo_overlap() {
         ZoneRules test = americaNewYork();
         final LocalDateTime dateTime = LocalDateTime.of(2008, 11, 2, 1, 0, 0, 0);
@@ -856,6 +895,7 @@
         assertEquals(trans.hashCode(), otherTrans.hashCode());
     }
 
+    @Test
     public void test_NewYork_getStandardOffset() {
         ZoneRules test = americaNewYork();
         ZonedDateTime dateTime = createZDT(1860, 1, 1, ZoneOffset.UTC);
@@ -877,6 +917,7 @@
         return ZoneId.of("Asia/Kathmandu").getRules();
     }
 
+    @Test
     public void test_Kathmandu_nextTransition_historic() {
         ZoneRules test = asiaKathmandu();
         List<ZoneOffsetTransition> trans = test.getTransitions();
@@ -893,6 +934,7 @@
         }
     }
 
+    @Test
     public void test_Kathmandu_nextTransition_noRules() {
         ZoneRules test = asiaKathmandu();
         List<ZoneOffsetTransition> trans = test.getTransitions();
@@ -908,6 +950,7 @@
         return ZoneId.of("Pacific/Apia").getRules();
     }
 
+    @Test
     public void test_Apia_nextTransition_historic() {
         ZoneRules test = pacificApia();
         List<ZoneOffsetTransition> trans = test.getTransitions();
@@ -924,6 +967,7 @@
         }
     }
 
+    @Test
     public void test_Apia_jumpOverInternationalDateLine_M10_to_P14() {
         // transition occurred at 2011-12-30T00:00-10:00
         ZoneRules test = pacificApia();
@@ -942,9 +986,8 @@
         assertEquals(zdt.plusHours(2).toLocalDateTime(), LocalDateTime.of(2011, 12, 31, 1, 0));
     }
 
+    @Test
     public void test_Apia_jumpForwardOverInternationalDateLine_P12_to_M12() {
-        // Android-changed: 1879 changed to 1892 in this test due to 2017c IANA update. Upstream
-        // will probably do the same. See https://bugs.openjdk.java.net/browse/JDK-8190259
         // transition occurred at 1892-07-04T00:00+12:33:04
         ZoneRules test = pacificApia();
         Instant instantBefore = LocalDate.of(1892, 7, 2).atStartOfDay(ZoneOffset.UTC).toInstant();
@@ -978,6 +1021,7 @@
     //-----------------------------------------------------------------------
     // of()
     //-----------------------------------------------------------------------
+    @Test
     public void test_of(){
         //used for standard offset
         ZoneOffset stdOffset1 = ZoneOffset.UTC;
@@ -1053,6 +1097,7 @@
     //-----------------------------------------------------------------------
     // equals() / hashCode()
     //-----------------------------------------------------------------------
+    @Test
     public void test_equals() {
         ZoneRules test1 = europeLondon();
         ZoneRules test2 = europeParis();
@@ -1069,14 +1114,17 @@
         assertEquals(test2.hashCode() == test2b.hashCode(), true);
     }
 
+    @Test
     public void test_equals_null() {
         assertEquals(europeLondon().equals(null), false);
     }
 
+    @Test
     public void test_equals_notZoneRules() {
         assertEquals(europeLondon().equals("Europe/London"), false);
     }
 
+    @Test
     public void test_toString() {
         assertEquals(europeLondon().toString().contains("ZoneRules"), true);
     }
diff --git a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java
index a30424f..f51bb39 100644
--- a/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java
+++ b/ojluni/src/test/java/time/tck/java/time/zone/TCKZoneRulesProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,10 +91,11 @@
     public void test_getAvailableGroupIds() {
         Set<String> zoneIds = ZoneRulesProvider.getAvailableZoneIds();
         assertEquals(zoneIds.contains("Europe/London"), true);
-        zoneIds.clear();
-        assertEquals(zoneIds.size(), 0);
-        Set<String> zoneIds2 = ZoneRulesProvider.getAvailableZoneIds();
-        assertEquals(zoneIds2.contains("Europe/London"), true);
+    }
+
+    @Test(expectedExceptions=UnsupportedOperationException.class)
+    public void test_getAvailableGroupIds_modifyZoneId() {
+        ZoneRulesProvider.getAvailableZoneIds().clear();
     }
 
     //-----------------------------------------------------------------------
diff --git a/ojluni/src/test/java/time/test/java/time/TestClock_System.java b/ojluni/src/test/java/time/test/java/time/TestClock_System.java
index 881a760..55ef1cd 100644
--- a/ojluni/src/test/java/time/test/java/time/TestClock_System.java
+++ b/ojluni/src/test/java/time/test/java/time/TestClock_System.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,10 +62,14 @@
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertSame;
 
+import java.lang.reflect.Field;
 import java.time.Clock;
+import java.time.Instant;
 import java.time.ZoneId;
+import java.time.ZoneOffset;
 
 import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
 
 /**
  * Test system clock.
@@ -74,6 +78,7 @@
 public class TestClock_System {
 
     private static final ZoneId PARIS = ZoneId.of("Europe/Paris");
+    private static final Clock systemUTC = Clock.systemUTC();
 
     public void test_withZone_same() {
         Clock test = Clock.system(PARIS);
@@ -87,4 +92,330 @@
         assertEquals(test.toString(), "SystemClock[Europe/Paris]");
     }
 
+    //-----------------------------------------------------------------------
+    @DataProvider(name="sampleSystemUTC")
+    Object[][] provider_sampleSystemUTC() {
+        return new Object[][] {
+            {"Clock.systemUTC()#1",  Clock.systemUTC()},
+            {"Clock.systemUTC()#2",  Clock.systemUTC()},
+            {"Clock.system(ZoneOffset.UTC)#1",  Clock.system(ZoneOffset.UTC)},
+            {"Clock.system(ZoneOffset.UTC)#2",  Clock.system(ZoneOffset.UTC)}
+        };
+    }
+
+    // Test for 8073394
+    @Test(dataProvider="sampleSystemUTC")
+    public void test_systemUTC(String s, Clock clock) {
+        if (clock != systemUTC) {
+            throw new RuntimeException("Unexpected clock instance for " + s + ": "
+                + "\n\texpected: " + toString(systemUTC)
+                + "\n\tactual:   " + toString(clock));
+        }
+    }
+
+    private static String toString(Clock c) {
+        return c == null ? null :
+               c + " " + c.getClass().getName() + "@" + System.identityHashCode(c);
+    }
+
+    //-----------------------------------------------------------------------
+
+    private static String formatTime(String prefix, Instant time) {
+        return prefix + ": " + time + " - seconds: "
+                        + time.getEpochSecond() + ", nanos: "
+                        + time.getNano();
+    }
+
+    public void test_ClockResolution() {
+        Clock highestUTC = Clock.systemUTC();
+
+        Instant start = Instant.ofEpochMilli(System.currentTimeMillis());
+
+        try {
+            // smoke test
+            Instant system1 = Instant.ofEpochMilli(System.currentTimeMillis());
+            Instant system2 = Instant.ofEpochMilli(System.currentTimeMillis());
+            Instant highest1 = highestUTC.instant();
+            Instant highest2 = highestUTC.instant();
+            System.out.println(formatTime("\nsystemUTC #1            ", system1));
+            System.out.println(formatTime("systemUTC #2            ", system2));
+            System.out.println(formatTime("highestResolutionUTC #1 ", highest1));
+            System.out.println(formatTime("highestResolutionUTC #2 ", highest2));
+
+            if (system2.isBefore(system1)) {
+                System.err.println("system2 is before system1!");
+                System.err.println(formatTime("\n\tsystem1", system1));
+                System.err.println(formatTime("\n\tsystem2", system2));
+                throw new RuntimeException("system2 is before system1!"
+                        + formatTime("\n\tsystem1", system1)
+                        + formatTime("\n\tsystem2", system2));
+            }
+            if (highest2.isBefore(highest1)) {
+                System.err.println("highest2 is before highest1!");
+                System.err.println(formatTime("\n\thighest1", system1));
+                System.err.println(formatTime("\n\tsystem2", highest2));
+                throw new RuntimeException("highest2 is before system1!"
+                        + formatTime("\n\thighest1", system1)
+                        + formatTime("\n\tsystem2", highest2));
+            }
+
+            // better test - but depends on implementation details.
+            // we're not rounding - so highest1 should be greater or equal to
+            // system1
+            system1 = Instant.ofEpochMilli(System.currentTimeMillis());
+            highest1 = highestUTC.instant();
+
+            System.out.println(formatTime("\nsystemUTC            ", system1));
+            System.out.println(formatTime("highestResolutionUTC ", highest1));
+
+            if (highest1.isBefore(system1)) {
+                System.err.println("highest1 is before system1!");
+                System.err.println(formatTime("\n\tsystem1", system1));
+                System.err.println(formatTime("\n\thighest1", highest1));
+                throw new RuntimeException("highest1 is before system1!"
+                        + formatTime("\n\tsystem1", system1)
+                        + formatTime("\n\thighest1", highest1));
+            }
+
+            int count=0;
+            // let's preheat the system a bit:
+            int lastNanos = 0;
+            for (int i = 0; i < 1000 ; i++) {
+                system1 = Instant.ofEpochMilli(System.currentTimeMillis());
+                final int sysnan = system1.getNano();
+                int nanos;
+                do {
+                    highest1 = highestUTC.instant();
+                    nanos = highest1.getNano();
+                } while (nanos == lastNanos); // Repeat to get a different value
+                lastNanos = nanos;
+
+                if ((nanos % 1000000) > 0) {
+                    count++; // we have micro seconds
+                }
+                if ((sysnan % 1000000) > 0) {
+                    throw new RuntimeException("Expected only millisecconds "
+                            + "precision for systemUTC, found "
+                            + (sysnan % 1000000) + " remainder.");
+                }
+            }
+            System.out.println("\nNumber of time stamps which had better than"
+                    + " millisecond precision: "+count+"/"+1000);
+            System.out.println(formatTime("\nsystemUTC            ", system1));
+            System.out.println(formatTime("highestResolutionUTC ", highest1));
+            if (count == 0) {
+                System.err.println("Something is strange: no microsecond "
+                        + "precision with highestResolutionUTC?");
+                throw new RuntimeException("Micro second preccision not reached");
+            }
+
+            // check again
+            if (highest1.isBefore(system1)) {
+                System.err.println("highest1 is before system1!");
+                System.err.println(formatTime("\n\tsystem1", system1));
+                System.err.println(formatTime("\n\thighest1", highest1));
+                throw new RuntimeException("highest1 is before system1!"
+                        + formatTime("\n\tsystem1", system1)
+                        + formatTime("\n\thighest1", highest1));
+            }
+
+            // leap of faith: ensure that highest1 is from within 10 secs of
+            //   system1
+            if (highest1.toEpochMilli() != system1.toEpochMilli()) {
+                long delta = highest1.getEpochSecond() - system1.getEpochSecond();
+                if (delta > 10) {
+                    throw new RuntimeException("Unexpected long delay between two clocks ("
+                            + delta + " seconds)"
+                            + formatTime("\n\t system1", system1)
+                            + formatTime("\n\t highest1", highest1));
+
+                }
+            } else {
+                System.out.println("You won the lottery: the two dates are within 1 millisecond!\n");
+            }
+
+        } finally {
+            Instant stop = Instant.ofEpochMilli(System.currentTimeMillis());
+            if (start.isAfter(stop)) {
+                // This should not happen - but can (un)probably be observed
+                // when switching to summer time, or if another application
+                // is switching the system date...
+                System.err.println("Cannot test - date was setback: "
+                        + formatTime("\n\tstarted at", start)
+                        + formatTime("\n\tstopped at", stop) + "\n");
+                return; // will prevent exceptions from being propagated.
+            }
+        }
+    }
+
+    static final long MAX_OFFSET = 0x0100000000L;
+    static final long MIN_OFFSET = -MAX_OFFSET;
+
+    // A helper class to test that SystemClock correctly recomputes
+    // its offset.
+    static class SystemClockOffset {
+
+        static final int MILLIS_IN_SECOND = 1000;
+        static final int NANOS_IN_MILLI = 1000_000;
+        static final int NANOS_IN_MICRO = 1000;
+        static final int NANOS_IN_SECOND = 1000_000_000;
+
+        static final boolean verbose = true;
+        static final Clock systemUTC = Clock.systemUTC();
+        static final Field offsetField;
+
+        static {
+            try {
+                offsetField = Class.forName("java.time.Clock$SystemClock").getDeclaredField("offset");
+                offsetField.setAccessible(true);
+            } catch (ClassNotFoundException | NoSuchFieldException ex) {
+                throw new ExceptionInInitializerError(ex);
+            }
+        }
+
+        static enum Answer {
+
+            YES, // isOffLimit = YES:   we must get -1
+            NO, // isOffLimit = NO:    we must not not get -1
+            MAYBE  // isOffLimit = MAYBE: we might get -1 or a valid adjustment.
+        };
+
+        static long distance(long one, long two) {
+            return one > two ? Math.subtractExact(one, two)
+                    : Math.subtractExact(two, one);
+        }
+
+        static Answer isOffLimits(long before, long after, long offset) {
+            long relativeDistanceBefore = distance(before, offset);
+            long relativeDistanceAfter = distance(after, offset);
+            if (relativeDistanceBefore >= MAX_OFFSET && relativeDistanceAfter >= MAX_OFFSET) {
+                return Answer.YES;
+            }
+            if (relativeDistanceBefore < MAX_OFFSET && relativeDistanceAfter < MAX_OFFSET) {
+                if (relativeDistanceBefore == 0 || relativeDistanceAfter == 0) {
+                    return Answer.MAYBE; // unlucky case where
+                }
+                return Answer.NO;
+            }
+            return Answer.MAYBE;
+        }
+
+        static void testWithOffset(String name, long offset)
+                throws IllegalAccessException {
+            testWithOffset(name, offset, systemUTC);
+        }
+
+        static void testWithOffset(String name, long offset, Clock clock)
+                throws IllegalAccessException {
+            offsetField.set(clock, offset);
+            long beforeMillis = System.currentTimeMillis();
+            final Instant instant = clock.instant();
+            long afterMillis = System.currentTimeMillis();
+            long actualOffset = offsetField.getLong(clock);
+            long instantMillis = instant.getEpochSecond() * MILLIS_IN_SECOND
+                    + instant.getNano() / NANOS_IN_MILLI;
+            if (instantMillis < beforeMillis || instantMillis > afterMillis) {
+                throw new RuntimeException(name
+                        + ": Invalid instant: " + instant
+                        + " (~" + instantMillis + "ms)"
+                        + " when time in millis is in ["
+                        + beforeMillis + ", " + afterMillis
+                        + "] and offset in seconds is " + offset);
+            }
+            Answer isOffLimits = isOffLimits(beforeMillis / MILLIS_IN_SECOND,
+                    afterMillis / MILLIS_IN_SECOND, offset);
+            switch (isOffLimits) {
+                case YES:
+                    if (actualOffset == offset) {
+                        throw new RuntimeException(name
+                                + ": offset was offlimit but was not recomputed "
+                                + " when time in millis is in ["
+                                + beforeMillis + ", " + afterMillis
+                                + "] and offset in seconds was " + offset);
+                    }
+                    break;
+                case NO:
+                    if (actualOffset != offset) {
+                        throw new RuntimeException(name
+                                + ": offset was not offlimit but was recomputed.");
+                    }
+                    break;
+                default:
+                    break;
+            }
+            if (distance(actualOffset, instant.getEpochSecond()) >= MAX_OFFSET) {
+                throw new RuntimeException(name + ": Actual offset is too far off:"
+                        + " offset=" + actualOffset
+                        + "instant.seconds=" + instant.getEpochSecond());
+            }
+            long adjustment = (instant.getEpochSecond() - actualOffset) * NANOS_IN_SECOND
+                    + instant.getNano();
+            validateAdjustment(name, actualOffset, beforeMillis, afterMillis, adjustment);
+        }
+
+        static void validateAdjustment(String name, long offset, long beforeMillis,
+                long afterMillis, long adjustment) {
+            System.out.println("Validating adjustment: " + adjustment);
+            long expectedMax = distance(offset, beforeMillis / MILLIS_IN_SECOND)
+                    * NANOS_IN_SECOND
+                    + (beforeMillis % MILLIS_IN_SECOND) * NANOS_IN_MILLI
+                    + (afterMillis - beforeMillis + 1) * NANOS_IN_MILLI;
+            long absoluteAdjustment = distance(0, adjustment);
+            if (absoluteAdjustment > expectedMax) {
+                long adjSec = absoluteAdjustment / NANOS_IN_SECOND;
+                long adjMil = (absoluteAdjustment % NANOS_IN_SECOND) / NANOS_IN_MILLI;
+                long adjMic = (absoluteAdjustment % NANOS_IN_MILLI) / NANOS_IN_MICRO;
+                long adjNan = (absoluteAdjustment % NANOS_IN_MICRO);
+                long expSec = expectedMax / NANOS_IN_SECOND;
+                long expMil = (expectedMax % NANOS_IN_SECOND) / NANOS_IN_MILLI;
+                long expMic = (expectedMax % NANOS_IN_MILLI) / NANOS_IN_MICRO;
+                long expNan = (expectedMax % NANOS_IN_MICRO);
+                System.err.println("Excessive adjustment: " + adjSec + "s, "
+                        + adjMil + "ms, " + adjMic + "mics, " + adjNan + "ns");
+                System.err.println("Epected max: " + expSec + "s, "
+                        + expMil + "ms, " + expMic + "mics, " + expNan + "ns");
+
+                throw new RuntimeException(name
+                        + ": Excessive adjustment: " + adjustment
+                        + " when time in millis is in ["
+                        + beforeMillis + ", " + afterMillis
+                        + "] and offset in seconds is " + offset);
+            }
+        }
+    }
+
+    public void test_OffsetRegular() throws IllegalAccessException {
+        System.out.println("*** Testing regular cases ***");
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000",
+                System.currentTimeMillis()/1000);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - 1024",
+                System.currentTimeMillis()/1000 - 1024);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + 1024",
+                System.currentTimeMillis()/1000 + 1024);
+    }
+
+    public void test_OffsetLimits() throws IllegalAccessException {
+        System.out.println("*** Testing limits ***");
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET + 1",
+                System.currentTimeMillis()/1000 - MAX_OFFSET + 1);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET - 1",
+                System.currentTimeMillis()/1000 + MAX_OFFSET - 1);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET",
+                System.currentTimeMillis()/1000 - MAX_OFFSET);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET",
+                System.currentTimeMillis()/1000 + MAX_OFFSET);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET - 1024",
+                System.currentTimeMillis()/1000 - MAX_OFFSET - 1024);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET + 1024",
+                System.currentTimeMillis()/1000 + MAX_OFFSET + 1024);
+        SystemClockOffset.testWithOffset("0", 0);
+        SystemClockOffset.testWithOffset("-1", -1);
+        SystemClockOffset.testWithOffset("Integer.MAX_VALUE + System.currentTimeMillis()/1000",
+                ((long)Integer.MAX_VALUE) + System.currentTimeMillis()/1000);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - Integer.MIN_VALUE",
+                System.currentTimeMillis()/1000 - Integer.MIN_VALUE);
+        SystemClockOffset.testWithOffset("Long.MAX_VALUE", Long.MAX_VALUE);
+        SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - Long.MIN_VALUE",
+                (Long.MIN_VALUE + System.currentTimeMillis()/1000)*-1);
+    }
 }
diff --git a/ojluni/src/test/java/time/test/java/time/TestLocalDate.java b/ojluni/src/test/java/time/test/java/time/TestLocalDate.java
index a6bd18c..91eb2a4 100644
--- a/ojluni/src/test/java/time/test/java/time/TestLocalDate.java
+++ b/ojluni/src/test/java/time/test/java/time/TestLocalDate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,6 +67,7 @@
 import java.time.LocalDate;
 import java.time.Month;
 import java.time.temporal.ChronoUnit;
+import java.time.temporal.IsoFields;
 
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
@@ -444,4 +445,40 @@
         }
     }
 
+    @DataProvider(name="quarterYearsToAdd")
+    Object[][] provider_quarterYearsToAdd() {
+        return new Object[][] {
+            {Long.valueOf(-1000000000)},
+            {Long.valueOf(-256)},
+            {Long.valueOf(-255)},
+            {Long.valueOf(-1)},
+            {Long.valueOf(0)},
+            {Long.valueOf(1)},
+            {Long.valueOf(255)},
+            {Long.valueOf(256)},
+            {Long.valueOf(1000000000)},
+        };
+    }
+
+    @Test(dataProvider="quarterYearsToAdd")
+    public void test_plus_QuarterYears(long quarterYears) {
+        LocalDate t0 = TEST_2007_07_15
+                .plus(quarterYears, IsoFields.QUARTER_YEARS);
+        LocalDate t1 = TEST_2007_07_15
+                .plus(quarterYears, ChronoUnit.MONTHS)
+                .plus(quarterYears, ChronoUnit.MONTHS)
+                .plus(quarterYears, ChronoUnit.MONTHS);
+        assertEquals(t0, t1);
+    }
+
+    @Test(dataProvider="quarterYearsToAdd")
+    public void test_minus_QuarterYears(long quarterYears) {
+        LocalDate t0 = TEST_2007_07_15
+                .minus(quarterYears, IsoFields.QUARTER_YEARS);
+        LocalDate t1 = TEST_2007_07_15
+                .minus(quarterYears, ChronoUnit.MONTHS)
+                .minus(quarterYears, ChronoUnit.MONTHS)
+                .minus(quarterYears, ChronoUnit.MONTHS);
+        assertEquals(t0, t1);
+    }
 }
diff --git a/ojluni/src/test/java/time/test/java/time/chrono/TestEraDisplayName.java b/ojluni/src/test/java/time/test/java/time/chrono/TestEraDisplayName.java
new file mode 100644
index 0000000..409f975
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/chrono/TestEraDisplayName.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.time.chrono;
+
+import android.icu.util.VersionInfo;
+import java.time.*;
+import java.time.chrono.*;
+import java.time.format.*;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tests Era.getDisplayName() correctly returns the name based on each
+ * chrono implementation.
+ * Note: The exact result may depend on locale data provider's implementation.
+ *
+ * @bug 8171049
+ */
+@Test
+public class TestEraDisplayName {
+    private static final Locale THAI = Locale.forLanguageTag("th-TH");
+    private static final Locale EGYPT = Locale.forLanguageTag("ar-EG");
+
+    @DataProvider(name="eraDisplayName")
+    Object[][] eraDisplayName() {
+        return new Object[][] {
+            // Era, text style, displyay locale, expected name
+            // IsoEra
+            { IsoEra.BCE,   TextStyle.FULL,     Locale.US,      "Before Christ" },
+            { IsoEra.CE,    TextStyle.FULL,     Locale.US,      "Anno Domini" },
+            { IsoEra.BCE,   TextStyle.FULL,     Locale.JAPAN,   "\u7d00\u5143\u524d" },
+            { IsoEra.CE,    TextStyle.FULL,     Locale.JAPAN,   "\u897f\u66a6" },
+            { IsoEra.BCE,   TextStyle.SHORT,    Locale.US,      "BC" },
+            { IsoEra.CE,    TextStyle.SHORT,    Locale.US,      "AD" },
+            { IsoEra.BCE,   TextStyle.SHORT,    Locale.JAPAN,   "\u7d00\u5143\u524d" },
+            { IsoEra.CE,    TextStyle.SHORT,    Locale.JAPAN,   "\u897f\u66a6" },
+            { IsoEra.BCE,   TextStyle.NARROW,   Locale.US,      "B" },
+            { IsoEra.CE,    TextStyle.NARROW,   Locale.US,      "A" },
+            { IsoEra.BCE,   TextStyle.NARROW,   Locale.JAPAN,   "BC" },
+            { IsoEra.CE,    TextStyle.NARROW,   Locale.JAPAN,   "AD" },
+
+            // JapaneseEra
+            { JapaneseEra.MEIJI,    TextStyle.FULL,     Locale.US,      "Meiji" },
+            // Android-changed: Android uses CLDR data.
+            // { JapaneseEra.TAISHO,   TextStyle.FULL,     Locale.US,      "Taisho" },
+            // { JapaneseEra.SHOWA,    TextStyle.FULL,     Locale.US,      "Showa" },
+            { JapaneseEra.TAISHO,   TextStyle.FULL,     Locale.US,      "Taishō" },
+            { JapaneseEra.SHOWA,    TextStyle.FULL,     Locale.US,      "Shōwa" },
+            { JapaneseEra.HEISEI,   TextStyle.FULL,     Locale.US,      "Heisei" },
+            { JapaneseEra.MEIJI,    TextStyle.FULL,     Locale.JAPAN,   "\u660e\u6cbb" },
+            { JapaneseEra.TAISHO,   TextStyle.FULL,     Locale.JAPAN,   "\u5927\u6b63" },
+            { JapaneseEra.SHOWA,    TextStyle.FULL,     Locale.JAPAN,   "\u662d\u548c" },
+            { JapaneseEra.HEISEI,   TextStyle.FULL,     Locale.JAPAN,   "\u5e73\u6210" },
+            { JapaneseEra.MEIJI,    TextStyle.SHORT,    Locale.US,      "Meiji" },
+            // Android-changed: Android uses CLDR data.
+            // { JapaneseEra.TAISHO,   TextStyle.SHORT,    Locale.US,      "Taisho" },
+            // { JapaneseEra.SHOWA,    TextStyle.SHORT,    Locale.US,      "Showa" },
+            { JapaneseEra.TAISHO,   TextStyle.SHORT,    Locale.US,      "Taishō" },
+            { JapaneseEra.SHOWA,    TextStyle.SHORT,    Locale.US,      "Shōwa" },
+            { JapaneseEra.HEISEI,   TextStyle.SHORT,    Locale.US,      "Heisei" },
+            { JapaneseEra.MEIJI,    TextStyle.SHORT,    Locale.JAPAN,   "\u660e\u6cbb" },
+            { JapaneseEra.TAISHO,   TextStyle.SHORT,    Locale.JAPAN,   "\u5927\u6b63" },
+            { JapaneseEra.SHOWA,    TextStyle.SHORT,    Locale.JAPAN,   "\u662d\u548c" },
+            { JapaneseEra.HEISEI,   TextStyle.SHORT,    Locale.JAPAN,   "\u5e73\u6210" },
+            { JapaneseEra.MEIJI,    TextStyle.NARROW,   Locale.US,      "M" },
+            { JapaneseEra.TAISHO,   TextStyle.NARROW,   Locale.US,      "T" },
+            { JapaneseEra.SHOWA,    TextStyle.NARROW,   Locale.US,      "S" },
+            { JapaneseEra.HEISEI,   TextStyle.NARROW,   Locale.US,      "H" },
+            { JapaneseEra.MEIJI,    TextStyle.NARROW,   Locale.JAPAN,   "M" },
+            { JapaneseEra.TAISHO,   TextStyle.NARROW,   Locale.JAPAN,   "T" },
+            { JapaneseEra.SHOWA,    TextStyle.NARROW,   Locale.JAPAN,   "S" },
+            { JapaneseEra.HEISEI,   TextStyle.NARROW,   Locale.JAPAN,   "H" },
+
+            // ThaiBuddhistEra
+            // Android-changed: Android uses CLDR data.
+            // { ThaiBuddhistEra.BEFORE_BE,    TextStyle.FULL, Locale.US,      "BC" },
+            // { ThaiBuddhistEra.BE,           TextStyle.FULL, Locale.US,      "BE" },
+            // { ThaiBuddhistEra.BEFORE_BE,    TextStyle.FULL, THAI,           "BC" },
+            // { ThaiBuddhistEra.BE,           TextStyle.FULL, THAI,
+            //   "\u0e1e\u0e38\u0e17\u0e18\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a" },
+            // { ThaiBuddhistEra.BEFORE_BE,    TextStyle.SHORT, Locale.US,     "BC" },
+            // { ThaiBuddhistEra.BE,           TextStyle.SHORT, Locale.US,     "BE" },
+            // { ThaiBuddhistEra.BEFORE_BE,    TextStyle.SHORT, THAI,
+            //   "\u0e1b\u0e35\u0e01\u0e48\u0e2d\u0e19\u0e04\u0e23\u0e34\u0e2a" +
+            //     "\u0e15\u0e4c\u0e01\u0e32\u0e25\u0e17\u0e35\u0e48" },
+            // { ThaiBuddhistEra.BE,           TextStyle.SHORT, THAI,  "\u0e1e.\u0e28." },
+            // { ThaiBuddhistEra.BEFORE_BE,    TextStyle.NARROW, Locale.US,    "BC" },
+            // { ThaiBuddhistEra.BE,           TextStyle.NARROW, Locale.US,    "BE" },
+            // { ThaiBuddhistEra.BEFORE_BE,    TextStyle.NARROW, THAI,         "BC" },
+            // { ThaiBuddhistEra.BE,           TextStyle.NARROW, THAI,         "\u0e1e.\u0e28." },
+            { ThaiBuddhistEra.BEFORE_BE,    TextStyle.FULL, Locale.US,      "0" },
+            { ThaiBuddhistEra.BE,           TextStyle.FULL, Locale.US,      "BE" },
+            { ThaiBuddhistEra.BEFORE_BE,    TextStyle.FULL, THAI,           "0" },
+            { ThaiBuddhistEra.BE,           TextStyle.FULL, THAI,
+                "\u0e1e\u0e38\u0e17\u0e18\u0e28\u0e31\u0e01\u0e23\u0e32\u0e0a" },
+            { ThaiBuddhistEra.BEFORE_BE,    TextStyle.SHORT, Locale.US,     "0" },
+            { ThaiBuddhistEra.BE,           TextStyle.SHORT, Locale.US,     "BE" },
+            { ThaiBuddhistEra.BEFORE_BE,    TextStyle.SHORT, THAI,          "0" },
+            { ThaiBuddhistEra.BE,           TextStyle.SHORT, THAI,  "\u0e1e.\u0e28." },
+            { ThaiBuddhistEra.BEFORE_BE,    TextStyle.NARROW, Locale.US,    "0" },
+            { ThaiBuddhistEra.BE,           TextStyle.NARROW, Locale.US,    "BE" },
+            { ThaiBuddhistEra.BEFORE_BE,    TextStyle.NARROW, THAI,         "0" },
+            { ThaiBuddhistEra.BE,           TextStyle.NARROW, THAI,         "\u0e1e.\u0e28." },
+
+            // MinguoEra
+            // Android-changed: Android uses CLDR data.
+            // { MinguoEra.BEFORE_ROC, TextStyle.FULL,     Locale.US,      "Before R.O.C." },
+            // { MinguoEra.ROC,        TextStyle.FULL,     Locale.US,      "Minguo" },
+            // { MinguoEra.BEFORE_ROC, TextStyle.FULL,     Locale.TAIWAN,  "\u6c11\u570b\u524d" },
+            // { MinguoEra.ROC,        TextStyle.FULL,     Locale.TAIWAN,  "\u6c11\u570b" },
+            // { MinguoEra.BEFORE_ROC, TextStyle.SHORT,    Locale.US,      "Before R.O.C." },
+            // { MinguoEra.ROC,        TextStyle.SHORT,    Locale.US,      "Minguo" },
+            // { MinguoEra.BEFORE_ROC, TextStyle.SHORT,    Locale.TAIWAN,  "\u6c11\u570b\u524d" },
+            // { MinguoEra.ROC,        TextStyle.SHORT,    Locale.TAIWAN,  "\u6c11\u570b" },
+            // { MinguoEra.BEFORE_ROC, TextStyle.NARROW,   Locale.US,      "Before R.O.C." },
+            // { MinguoEra.ROC,        TextStyle.NARROW,   Locale.US,      "Minguo" },
+            // { MinguoEra.BEFORE_ROC, TextStyle.NARROW,   Locale.TAIWAN,  "\u6c11\u570b\u524d" },
+            // { MinguoEra.ROC,        TextStyle.NARROW,   Locale.TAIWAN,  "\u6c11\u570b" },
+            { MinguoEra.BEFORE_ROC, TextStyle.FULL,     Locale.US,      "B.R.O.C." },
+            { MinguoEra.ROC,        TextStyle.FULL,     Locale.US,      "Minguo" },
+            { MinguoEra.BEFORE_ROC, TextStyle.FULL,     Locale.TAIWAN,  "\u6c11\u570b\u524d" },
+            { MinguoEra.ROC,        TextStyle.FULL,     Locale.TAIWAN,  "\u6c11\u570b" },
+            { MinguoEra.BEFORE_ROC, TextStyle.SHORT,    Locale.US,      "B.R.O.C." },
+            { MinguoEra.ROC,        TextStyle.SHORT,    Locale.US,      "Minguo" },
+            { MinguoEra.BEFORE_ROC, TextStyle.SHORT,    Locale.TAIWAN,  "\u6c11\u570b\u524d" },
+            { MinguoEra.ROC,        TextStyle.SHORT,    Locale.TAIWAN,  "\u6c11\u570b" },
+            { MinguoEra.BEFORE_ROC, TextStyle.NARROW,   Locale.US,      "B.R.O.C." },
+            { MinguoEra.ROC,        TextStyle.NARROW,   Locale.US,      "Minguo" },
+            { MinguoEra.BEFORE_ROC, TextStyle.NARROW,   Locale.TAIWAN,  "\u6c11\u570b\u524d" },
+            { MinguoEra.ROC,        TextStyle.NARROW,   Locale.TAIWAN,  "\u6c11\u570b" },
+
+            // HijrahEra
+            { HijrahEra.AH, TextStyle.FULL,     Locale.US,  "AH" },
+            { HijrahEra.AH, TextStyle.FULL,     EGYPT,      "\u0647\u0640" },
+            { HijrahEra.AH, TextStyle.SHORT,    Locale.US,  "AH" },
+            { HijrahEra.AH, TextStyle.SHORT,    EGYPT,      "\u0647\u0640" },
+            { HijrahEra.AH, TextStyle.NARROW,   Locale.US,  "AH" },
+            { HijrahEra.AH, TextStyle.NARROW,   EGYPT,      "\u0647\u0640" },
+        };
+    }
+
+    @Test(dataProvider="eraDisplayName")
+    public void test_eraDisplayName(Era era, TextStyle style, Locale locale, String expected) {
+        // Android-added: The ICU data is different before ICU version 70. http://b/229960530
+        if (VersionInfo.ICU_VERSION.getMajor() < 70) {
+            return;
+        }
+        assertEquals(era.getDisplayName(style, locale), expected);
+    }
+}
diff --git a/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java b/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
index 7c6e25d..0d122b9 100644
--- a/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
+++ b/ojluni/src/test/java/time/test/java/time/chrono/TestJapaneseChronology.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java b/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java
index f86f144..7bd8a6d 100644
--- a/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java
+++ b/ojluni/src/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java
@@ -624,7 +624,7 @@
     @Test
     public void test_chronoFields() {
         ChronoLocalDate hdate = HijrahChronology.INSTANCE.date(1434, 6, 28);
-        assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), 3);
+        assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), 7);
         assertEquals(hdate.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR), 7);
         assertEquals(hdate.get(ChronoField.ALIGNED_WEEK_OF_MONTH), 4);
         assertEquals(hdate.get(ChronoField.ALIGNED_WEEK_OF_YEAR), 25);
@@ -787,4 +787,32 @@
       public void test_hijrahToJapanese(HijrahDate hijrah, String japanese) {
           assertEquals(JapaneseChronology.INSTANCE.date(hijrah).toString(), japanese);
     }
+
+    @DataProvider(name="alignedDayOfWeekInMonthTestDates")
+    Object[][] data_alignedDayOfWeekInMonth() {
+        return new Object[][] {
+            {1437, 9, 1, 1, 1},
+            {1437, 10, 1, 1, 1},
+            {1437, 10, 11, 2, 4},
+            {1437, 10, 29, 5, 1},
+        };
+    }
+
+    //-----------------------------------------------------------------------
+    // Test for aligned-week-of-month calculation based on the day-of-month
+    //-----------------------------------------------------------------------
+    @Test(dataProvider="alignedDayOfWeekInMonthTestDates")
+    public void test_alignedWeekOfMonth(int year, int month, int dom, int wom, int dowm) {
+        HijrahDate date = HijrahChronology.INSTANCE.date(year, month, dom);
+        assertEquals(date.getLong(ChronoField.ALIGNED_WEEK_OF_MONTH), wom);
+    }
+
+    //-----------------------------------------------------------------------
+    // Test for aligned-day-of-week calculation based on the day-of-month
+    //-----------------------------------------------------------------------
+    @Test(dataProvider="alignedDayOfWeekInMonthTestDates")
+    public void test_alignedDayOfWeekInMonth(int year, int month, int dom, int wom, int dowm) {
+        HijrahDate date = HijrahChronology.INSTANCE.date(year, month, dom);
+        assertEquals(date.getLong(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH), dowm);
+    }
 }
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatter.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatter.java
index 1bfa479..c9c513f 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatter.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatter.java
@@ -79,19 +79,24 @@
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
+import java.time.chrono.Chronology;
 import java.time.chrono.ThaiBuddhistChronology;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.DecimalStyle;
 import java.time.format.SignStyle;
+import java.time.format.TextStyle;
+import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.util.Locale;
 import java.util.function.Function;
 
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 /**
  * Test DateTimeFormatter.
+ * @bug 8085887
  */
 @Test
 public class TestDateTimeFormatter {
@@ -196,4 +201,75 @@
         assertTrue(msg.contains("11:30:56"), msg);
     }
 
+    @DataProvider(name="nozone_exception_cases")
+    Object[][] exceptionCases() {
+        return new Object[][] {
+                {LocalDateTime.of(2000, 1, 1, 1, 1), "z", "ZoneId"},
+                {OffsetDateTime.of(2000, 1, 1, 3, 3, 3, 0, ZoneOffset.ofTotalSeconds(60)), "z", "ZoneId"},
+        };
+    }
+
+    // Test cases that should throw an exception with a cogent message
+    // containing the Type being queried and the Temporal being queried.
+    @Test(dataProvider="nozone_exception_cases")
+    public void test_throws_message(Temporal temporal, String pattern, String queryName) {
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern);
+        try {
+            fmt.format(temporal);
+            fail("Format using \"" + pattern + "\" with " +
+                    temporal + " should have failed");
+        } catch (DateTimeException dte) {
+            String msg = dte.getMessage();
+            // Verify message contains the type that is missing and the temporal value
+            assertTrue(msg.contains(queryName),
+                    String.format("\"%s\" missing from %s", queryName, msg));
+            String s = temporal.toString();
+            assertTrue(msg.contains(s),
+                    String.format("\"%s\" missing from %s", s, msg));
+        }
+
+    }
+
+    // Test cases that should throw an exception with a cogent message when missing the Chronology
+    @Test
+    public void test_throws_message_chrono() {
+        Chronology chrono = ThaiBuddhistChronology.INSTANCE;
+        DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendZoneId().toFormatter()
+                .withChronology(chrono);
+        LocalTime now = LocalTime.now();
+        try {
+            fmt.format(now);
+            fail("Format using appendZoneId() should have failed");
+        } catch (DateTimeException dte) {
+            String msg = dte.getMessage();
+            // Verify message contains the type that is missing and the temporal value
+            assertTrue(msg.contains("ZoneId"),
+                    String.format("\"%s\" missing from %s", "ZoneId", msg));
+            assertTrue(msg.contains(chrono.toString()),
+                    String.format("\"%s\" missing from %s", chrono.toString(), msg));
+        }
+
+    }
+
+    // Test cases that should throw an exception with a cogent message when missing the ZoneId
+    @Test
+    public void test_throws_message_zone() {
+        ZoneId zone = ZoneId.of("Pacific/Honolulu");
+        DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendChronologyId().toFormatter()
+                .withZone(zone);
+        LocalTime now = LocalTime.now();
+        try {
+            fmt.format(now);
+            fail("Format using appendChronologyId() should have failed");
+        } catch (DateTimeException dte) {
+            String msg = dte.getMessage();
+            // Verify message contains the type that is missing and the temporal value
+            assertTrue(msg.contains("Chronology"),
+                    String.format("\"%s\" missing from %s", "Chronology", msg));
+            assertTrue(msg.contains(zone.toString()),
+                    String.format("\"%s\" missing from %s", zone.toString(), msg));
+        }
+
+    }
+
 }
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
index 326aed9..5c62921 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,6 +67,7 @@
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
+import android.icu.util.VersionInfo;
 import java.text.ParsePosition;
 import java.time.LocalDate;
 import java.time.YearMonth;
@@ -484,8 +485,6 @@
             {"HH:MM:ss"},
             {"HHMMSS"},
             {"HH:MM:SS"},
-            {"+H"},
-            {"+HMM"},
             {"+HHM"},
             {"+A"},
         };
@@ -684,7 +683,7 @@
             {"LLLLL", "Text(MonthOfYear,NARROW_STANDALONE)"},
 
             {"D", "Value(DayOfYear)"},
-            {"DD", "Value(DayOfYear,2)"},
+            {"DD", "Value(DayOfYear,2,3,NOT_NEGATIVE)"},
             {"DDD", "Value(DayOfYear,3)"},
 
             {"d", "Value(DayOfMonth)"},
@@ -746,17 +745,17 @@
             {"SSS", "Fraction(NanoOfSecond,3,3)"},
             {"SSSSSSSSS", "Fraction(NanoOfSecond,9,9)"},
 
-            {"A", "Value(MilliOfDay)"},
-            {"AA", "Value(MilliOfDay,2)"},
-            {"AAA", "Value(MilliOfDay,3)"},
+            {"A", "Value(MilliOfDay,1,19,NOT_NEGATIVE)"},
+            {"AA", "Value(MilliOfDay,2,19,NOT_NEGATIVE)"},
+            {"AAA", "Value(MilliOfDay,3,19,NOT_NEGATIVE)"},
 
-            {"n", "Value(NanoOfSecond)"},
-            {"nn", "Value(NanoOfSecond,2)"},
-            {"nnn", "Value(NanoOfSecond,3)"},
+            {"n", "Value(NanoOfSecond,1,19,NOT_NEGATIVE)"},
+            {"nn", "Value(NanoOfSecond,2,19,NOT_NEGATIVE)"},
+            {"nnn", "Value(NanoOfSecond,3,19,NOT_NEGATIVE)"},
 
-            {"N", "Value(NanoOfDay)"},
-            {"NN", "Value(NanoOfDay,2)"},
-            {"NNN", "Value(NanoOfDay,3)"},
+            {"N", "Value(NanoOfDay,1,19,NOT_NEGATIVE)"},
+            {"NN", "Value(NanoOfDay,2,19,NOT_NEGATIVE)"},
+            {"NNN", "Value(NanoOfDay,3,19,NOT_NEGATIVE)"},
 
             {"z", "ZoneText(SHORT)"},
             {"zz", "ZoneText(SHORT)"},
@@ -782,7 +781,7 @@
             {"xxxxx", "Offset(+HH:MM:ss,'+00:00')"},  // LDML
 
             {"ppH", "Pad(Value(HourOfDay),2)"},
-            {"pppDD", "Pad(Value(DayOfYear,2),3)"},
+            {"pppDD", "Pad(Value(DayOfYear,2,3,NOT_NEGATIVE),3)"},
 
             {"yyyy[-MM[-dd", "Value(YearOfEra,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"},
             {"yyyy[-MM[-dd]]", "Value(YearOfEra,4,19,EXCEEDS_PAD)['-'Value(MonthOfYear,2)['-'Value(DayOfMonth,2)]]"},
@@ -882,25 +881,6 @@
     }
 
     //-----------------------------------------------------------------------
-    @DataProvider(name="patternPrint")
-    Object[][] data_patternPrint() {
-        return new Object[][] {
-            {"Q", date(2012, 2, 10), "1"},
-            {"QQ", date(2012, 2, 10), "01"},
-            {"QQQ", date(2012, 2, 10), "Q1"},
-            {"QQQQ", date(2012, 2, 10), "1st quarter"},
-            {"QQQQQ", date(2012, 2, 10), "1"},
-        };
-    }
-
-    @Test(dataProvider="patternPrint")
-    public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception {
-        DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK);
-        String test = f.format(temporal);
-        assertEquals(test, expected);
-    }
-
-    //-----------------------------------------------------------------------
     @DataProvider(name="localePatterns")
     Object[][] localizedDateTimePatterns() {
         // Android-changed: Adapt for changes since old CLDR version this tests were written for.
@@ -917,60 +897,16 @@
             {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a z"},
             {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.US, "h:mm:ss a"},
             {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.US, "h:mm a"},
-
-            // French Locale and ISO Chronology
-            {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y 'à' HH:mm:ss zzzz"},
-            {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y 'à' HH:mm:ss z"},
-            // Android-changed: Since ICU 68, medium format uses ',' instead of 'à', to separate the date and time in French.
-            // {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y 'à' HH:mm:ss"},
-            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y, HH:mm:ss"},
-            {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"},
-            {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"},
-            {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"},
-            {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"},
-            {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"},
-            {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"},
-            {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"},
-            {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"},
-            {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"},
-
-            // Japanese Locale and JapaneseChronology
-            {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"},
-            {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"},
-            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"},
-            {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"},
-            {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
-            {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
-            {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
-            {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"},
-            {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"},
-            {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"},
-            {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"},
-            {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"},
-
-            // Chinese Local and Chronology
-            {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"},
-            {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"},
-            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"},
-            // Android-changed: Since ICU 68, use single 'y' to represent year in short form like other format styles
-            // {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"},
-            {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy/M/d ah:mm"},
-            {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
-            {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
-            {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
-            // Android-changed: Since ICU 68, use single 'y' to represent year in short form like other format styles
-            // {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"},
-            {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy/M/d"},
-            {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"},
-            {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"},
-            {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"},
-            {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"},
         };
     }
 
     @Test(dataProvider="localePatterns")
     public void test_getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle,
             Chronology chrono, Locale locale, String expected) {
+        // Android-changed: Require ICU 70 to pass the test due to CLDR data change
+        if (VersionInfo.ICU_VERSION.getMajor() < 70) {
+            return;
+        }
         String actual = DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale);
         assertEquals(actual, expected, "Pattern " + convertNonAscii(actual));
     }
@@ -1013,5 +949,4 @@
     private static Temporal date(int y, int m, int d) {
         return LocalDate.of(y, m, d);
     }
-
 }
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java
new file mode 100644
index 0000000..2f73f59
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeFormatterBuilderWithLocale.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+package test.java.time.format;
+
+import android.icu.util.VersionInfo;
+import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.JapaneseEra;
+import java.time.chrono.MinguoChronology;
+import java.time.chrono.ThaiBuddhistChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.FormatStyle;
+import java.time.format.ResolverStyle;
+import java.time.LocalDate;
+import java.time.temporal.ChronoField;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAccessor;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Test DateTimeFormatterBuilder.
+ */
+@Test
+public class TestDateTimeFormatterBuilderWithLocale {
+
+    private DateTimeFormatterBuilder builder;
+
+    @BeforeMethod
+    public void setUp() {
+        builder = new DateTimeFormatterBuilder();
+    }
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="patternPrint")
+    Object[][] data_patternPrint() {
+        return new Object[][] {
+            {"Q", date(2012, 2, 10), "1"},
+            {"QQ", date(2012, 2, 10), "01"},
+            {"QQQ", date(2012, 2, 10), "Q1"},
+            {"QQQQ", date(2012, 2, 10), "1st quarter"},
+            {"QQQQQ", date(2012, 2, 10), "1"},
+        };
+    }
+
+    @Test(dataProvider="patternPrint")
+    public void test_appendPattern_patternPrint(String input, Temporal temporal, String expected) throws Exception {
+        DateTimeFormatter f = builder.appendPattern(input).toFormatter(Locale.UK);
+        String test = f.format(temporal);
+        assertEquals(test, expected);
+    }
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="mapTextLookup")
+    Object[][] data_mapTextLookup() {
+        return new Object[][] {
+            {IsoChronology.INSTANCE.date(1, 1, 1), Locale.ENGLISH},
+            {JapaneseChronology.INSTANCE.date(JapaneseEra.HEISEI, 1, 1, 8), Locale.ENGLISH},
+            {MinguoChronology.INSTANCE.date(1, 1, 1), Locale.ENGLISH},
+            {ThaiBuddhistChronology.INSTANCE.date(1, 1, 1), Locale.ENGLISH},
+        };
+    }
+
+    @Test(dataProvider="mapTextLookup")
+    public void test_appendText_mapTextLookup(ChronoLocalDate date, Locale locale) {
+        final String firstYear = "firstYear";
+        final String firstMonth = "firstMonth";
+        final String firstYearMonth = firstYear + firstMonth;
+        final long first = 1L;
+
+        DateTimeFormatter formatter = builder
+            .appendText(ChronoField.YEAR_OF_ERA, Map.of(first, firstYear))
+            .appendText(ChronoField.MONTH_OF_YEAR, Map.of(first, firstMonth))
+            .toFormatter(locale)
+            .withResolverStyle(ResolverStyle.STRICT);
+
+        assertEquals(date.format(formatter), firstYearMonth);
+
+        TemporalAccessor ta = formatter.parse(firstYearMonth);
+        assertEquals(ta.getLong(ChronoField.YEAR_OF_ERA), first);
+        assertEquals(ta.getLong(ChronoField.MONTH_OF_YEAR), first);
+    }
+
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="localePatterns")
+    Object[][] localizedDateTimePatterns() {
+        // Android-changed: Adapt for changes since old CLDR version this tests were written for.
+        return new Object[][] {
+            // French Locale and ISO Chronology
+            {FormatStyle.FULL, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y '\u00e0' HH:mm:ss zzzz"},
+            {FormatStyle.LONG, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y '\u00e0' HH:mm:ss z"},
+            // Android-changed: Since ICU 68, medium format uses ',' instead of '\u00e0', to separate the date and time in French.
+            // {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y '\u00e0' HH:mm:ss"},
+            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y, HH:mm:ss"},
+            {FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y HH:mm"},
+            {FormatStyle.FULL, null, IsoChronology.INSTANCE, Locale.FRENCH, "EEEE d MMMM y"},
+            {FormatStyle.LONG, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMMM y"},
+            {FormatStyle.MEDIUM, null, IsoChronology.INSTANCE, Locale.FRENCH, "d MMM y"},
+            {FormatStyle.SHORT, null, IsoChronology.INSTANCE, Locale.FRENCH, "dd/MM/y"},
+            {null, FormatStyle.FULL, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss zzzz"},
+            {null, FormatStyle.LONG, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss z"},
+            {null, FormatStyle.MEDIUM, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm:ss"},
+            {null, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.FRENCH, "HH:mm"},
+
+            // Japanese Locale and JapaneseChronology
+            {FormatStyle.FULL, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE H\u6642mm\u5206ss\u79d2 zzzz"},
+            {FormatStyle.LONG, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss z"},
+            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5 H:mm:ss"},
+            {FormatStyle.SHORT, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d H:mm"},
+            {FormatStyle.FULL, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
+            {FormatStyle.LONG, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
+            {FormatStyle.MEDIUM, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "Gy\u5e74M\u6708d\u65e5"},
+            {FormatStyle.SHORT, null, JapaneseChronology.INSTANCE, Locale.JAPANESE, "GGGGGy/M/d"},
+            {null, FormatStyle.FULL, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H\u6642mm\u5206ss\u79d2 zzzz"},
+            {null, FormatStyle.LONG, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss z"},
+            {null, FormatStyle.MEDIUM, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm:ss"},
+            {null, FormatStyle.SHORT, JapaneseChronology.INSTANCE, Locale.JAPANESE, "H:mm"},
+
+            // Chinese Local and Chronology
+            // Android-changed: Since ICU 70, use 24-hour time format
+            // {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz ah:mm:ss"},
+            // {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z ah:mm:ss"},
+            // {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 ah:mm:ss"},
+            {FormatStyle.FULL, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE zzzz HH:mm:ss"},
+            {FormatStyle.LONG, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 z HH:mm:ss"},
+            {FormatStyle.MEDIUM, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5 HH:mm:ss"},
+            // Android-changed: Since ICU 68, use single 'y' to represent year in short form like other format styles
+            // {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d ah:mm"},
+            {FormatStyle.SHORT, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy/M/d HH:mm"},
+            {FormatStyle.FULL, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5EEEE"},
+            {FormatStyle.LONG, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
+            {FormatStyle.MEDIUM, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy\u5e74M\u6708d\u65e5"},
+            // Android-changed: Since ICU 68, use single 'y' to represent year in short form like other format styles
+            // {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gyy/M/d"},
+            // {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz ah:mm:ss"},
+            // {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z ah:mm:ss"},
+            // {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm:ss"},
+            // {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "ah:mm"},
+            {FormatStyle.SHORT, null, MinguoChronology.INSTANCE, Locale.CHINESE, "Gy/M/d"},
+            {null, FormatStyle.FULL, MinguoChronology.INSTANCE, Locale.CHINESE, "zzzz HH:mm:ss"},
+            {null, FormatStyle.LONG, MinguoChronology.INSTANCE, Locale.CHINESE, "z HH:mm:ss"},
+            {null, FormatStyle.MEDIUM, MinguoChronology.INSTANCE, Locale.CHINESE, "HH:mm:ss"},
+            {null, FormatStyle.SHORT, MinguoChronology.INSTANCE, Locale.CHINESE, "HH:mm"},
+        };
+    }
+
+    @Test(dataProvider="localePatterns")
+    public void test_getLocalizedDateTimePattern(FormatStyle dateStyle, FormatStyle timeStyle,
+            Chronology chrono, Locale locale, String expected) {
+        // Android-added: The ICU data is different before ICU version 70. http://b/229960530
+        if (VersionInfo.ICU_VERSION.getMajor() < 70) {
+            return;
+        }
+        String actual = DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle, chrono, locale);
+        assertEquals(actual, expected, "Pattern " + convertNonAscii(actual));
+    }
+
+    /**
+     * Returns a string that includes non-ascii characters after expanding
+     * the non-ascii characters to their Java language \\uxxxx form.
+     * @param input an input string
+     * @return the encoded string.
+     */
+    private String convertNonAscii(String input) {
+        StringBuilder sb = new StringBuilder(input.length() * 6);
+        for (int i = 0; i < input.length(); i++) {
+            char ch = input.charAt(i);
+            if (ch < 255) {
+                sb.append(ch);
+            } else {
+                sb.append("\\u");
+                sb.append(Integer.toHexString(ch));
+            }
+        }
+        return sb.toString();
+    }
+
+    private static Temporal date(int y, int m, int d) {
+        return LocalDate.of(y, m, d);
+    }
+}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java
index 76296df..da4a276 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,6 @@
 public class TestDateTimeTextProvider extends AbstractTestPrinterParser {
 
     Locale enUS = new Locale("en", "US");
-    Locale ptBR = new Locale("pt", "BR");
 
     //-----------------------------------------------------------------------
     @DataProvider(name = "Text")
@@ -94,15 +93,6 @@
             {DAY_OF_WEEK, 6, TextStyle.SHORT, enUS, "Sat"},
             {DAY_OF_WEEK, 7, TextStyle.SHORT, enUS, "Sun"},
 
-            // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower with dot
-            {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg."},
-            {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter."},
-            {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua."},
-            {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui."},
-            {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex."},
-            {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b."},
-            {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom."},
-
             {DAY_OF_WEEK, 1, TextStyle.FULL, enUS, "Monday"},
             {DAY_OF_WEEK, 2, TextStyle.FULL, enUS, "Tuesday"},
             {DAY_OF_WEEK, 3, TextStyle.FULL, enUS, "Wednesday"},
@@ -111,15 +101,6 @@
             {DAY_OF_WEEK, 6, TextStyle.FULL, enUS, "Saturday"},
             {DAY_OF_WEEK, 7, TextStyle.FULL, enUS, "Sunday"},
 
-            // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower
-            {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "segunda-feira"},
-            {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "ter\u00E7a-feira"},
-            {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "quarta-feira"},
-            {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "quinta-feira"},
-            {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "sexta-feira"},
-            {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "s\u00E1bado"},
-            {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "domingo"},
-
             {MONTH_OF_YEAR, 1, TextStyle.SHORT, enUS, "Jan"},
             {MONTH_OF_YEAR, 2, TextStyle.SHORT, enUS, "Feb"},
             {MONTH_OF_YEAR, 3, TextStyle.SHORT, enUS, "Mar"},
@@ -133,20 +114,6 @@
             {MONTH_OF_YEAR, 11, TextStyle.SHORT, enUS, "Nov"},
             {MONTH_OF_YEAR, 12, TextStyle.SHORT, enUS, "Dec"},
 
-            // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower with dot
-            {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan."},
-            {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev."},
-            {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar."},
-            {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr."},
-            {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai."},
-            {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun."},
-            {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul."},
-            {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago."},
-            {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set."},
-            {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out."},
-            {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov."},
-            {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez."},
-
             {MONTH_OF_YEAR, 1, TextStyle.FULL, enUS, "January"},
             {MONTH_OF_YEAR, 2, TextStyle.FULL, enUS, "February"},
             {MONTH_OF_YEAR, 3, TextStyle.FULL, enUS, "March"},
@@ -160,20 +127,6 @@
             {MONTH_OF_YEAR, 11, TextStyle.FULL, enUS, "November"},
             {MONTH_OF_YEAR, 12, TextStyle.FULL, enUS, "December"},
 
-            // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower
-            {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "janeiro"},
-            {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "fevereiro"},
-            {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "mar\u00E7o"},
-            {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "abril"},
-            {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "maio"},
-            {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "junho"},
-            {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "julho"},
-            {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "agosto"},
-            {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "setembro"},
-            {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "outubro"},
-            {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "novembro"},
-            {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "dezembro"},
-
             {AMPM_OF_DAY, 0, TextStyle.SHORT, enUS, "AM"},
             {AMPM_OF_DAY, 1, TextStyle.SHORT, enUS, "PM"},
 
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java
new file mode 100644
index 0000000..7c90357
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/format/TestDateTimeTextProviderWithLocale.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+
+package test.java.time.format;
+
+import static java.time.temporal.ChronoField.AMPM_OF_DAY;
+import static java.time.temporal.ChronoField.DAY_OF_WEEK;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static org.testng.Assert.assertEquals;
+
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.TextStyle;
+import java.time.temporal.TemporalField;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Test SimpleDateTimeTextProviderWithLocale.
+ */
+@Test
+public class TestDateTimeTextProviderWithLocale extends AbstractTestPrinterParser {
+
+    Locale enUS = new Locale("en", "US");
+    Locale ptBR = new Locale("pt", "BR");
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name = "Text")
+    Object[][] data_text() {
+        return new Object[][] {
+            // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower with dot
+            // {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg"},
+            // {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter"},
+            // {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua"},
+            // {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui"},
+            // {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex"},
+            // {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b"},
+            // {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom"},
+            {DAY_OF_WEEK, 1, TextStyle.SHORT, ptBR, "seg."},
+            {DAY_OF_WEEK, 2, TextStyle.SHORT, ptBR, "ter."},
+            {DAY_OF_WEEK, 3, TextStyle.SHORT, ptBR, "qua."},
+            {DAY_OF_WEEK, 4, TextStyle.SHORT, ptBR, "qui."},
+            {DAY_OF_WEEK, 5, TextStyle.SHORT, ptBR, "sex."},
+            {DAY_OF_WEEK, 6, TextStyle.SHORT, ptBR, "s\u00E1b."},
+            {DAY_OF_WEEK, 7, TextStyle.SHORT, ptBR, "dom."},
+
+            {DAY_OF_WEEK, 1, TextStyle.FULL, ptBR, "segunda-feira"},
+            {DAY_OF_WEEK, 2, TextStyle.FULL, ptBR, "ter\u00E7a-feira"},
+            {DAY_OF_WEEK, 3, TextStyle.FULL, ptBR, "quarta-feira"},
+            {DAY_OF_WEEK, 4, TextStyle.FULL, ptBR, "quinta-feira"},
+            {DAY_OF_WEEK, 5, TextStyle.FULL, ptBR, "sexta-feira"},
+            {DAY_OF_WEEK, 6, TextStyle.FULL, ptBR, "s\u00E1bado"},
+            {DAY_OF_WEEK, 7, TextStyle.FULL, ptBR, "domingo"},
+
+            // Android-changed: upstream tests expect title case names for pt_BR, but CLDR has lower with dot
+            // {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan"},
+            // {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev"},
+            // {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar"},
+            // {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr"},
+            // {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai"},
+            // {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun"},
+            // {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul"},
+            // {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago"},
+            // {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set"},
+            // {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out"},
+            // {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov"},
+            // {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez"},
+            {MONTH_OF_YEAR, 1, TextStyle.SHORT, ptBR, "jan."},
+            {MONTH_OF_YEAR, 2, TextStyle.SHORT, ptBR, "fev."},
+            {MONTH_OF_YEAR, 3, TextStyle.SHORT, ptBR, "mar."},
+            {MONTH_OF_YEAR, 4, TextStyle.SHORT, ptBR, "abr."},
+            {MONTH_OF_YEAR, 5, TextStyle.SHORT, ptBR, "mai."},
+            {MONTH_OF_YEAR, 6, TextStyle.SHORT, ptBR, "jun."},
+            {MONTH_OF_YEAR, 7, TextStyle.SHORT, ptBR, "jul."},
+            {MONTH_OF_YEAR, 8, TextStyle.SHORT, ptBR, "ago."},
+            {MONTH_OF_YEAR, 9, TextStyle.SHORT, ptBR, "set."},
+            {MONTH_OF_YEAR, 10, TextStyle.SHORT, ptBR, "out."},
+            {MONTH_OF_YEAR, 11, TextStyle.SHORT, ptBR, "nov."},
+            {MONTH_OF_YEAR, 12, TextStyle.SHORT, ptBR, "dez."},
+
+            {MONTH_OF_YEAR, 1, TextStyle.FULL, ptBR, "janeiro"},
+            {MONTH_OF_YEAR, 2, TextStyle.FULL, ptBR, "fevereiro"},
+            {MONTH_OF_YEAR, 3, TextStyle.FULL, ptBR, "mar\u00E7o"},
+            {MONTH_OF_YEAR, 4, TextStyle.FULL, ptBR, "abril"},
+            {MONTH_OF_YEAR, 5, TextStyle.FULL, ptBR, "maio"},
+            {MONTH_OF_YEAR, 6, TextStyle.FULL, ptBR, "junho"},
+            {MONTH_OF_YEAR, 7, TextStyle.FULL, ptBR, "julho"},
+            {MONTH_OF_YEAR, 8, TextStyle.FULL, ptBR, "agosto"},
+            {MONTH_OF_YEAR, 9, TextStyle.FULL, ptBR, "setembro"},
+            {MONTH_OF_YEAR, 10, TextStyle.FULL, ptBR, "outubro"},
+            {MONTH_OF_YEAR, 11, TextStyle.FULL, ptBR, "novembro"},
+            {MONTH_OF_YEAR, 12, TextStyle.FULL, ptBR, "dezembro"},
+
+        };
+    }
+
+    @Test(dataProvider = "Text")
+    public void test_getText(TemporalField field, Number value, TextStyle style, Locale locale, String expected) {
+          DateTimeFormatter fmt = getFormatter(field, style).withLocale(locale);
+          assertEquals(fmt.format(ZonedDateTime.now().with(field, value.longValue())), expected);
+    }
+
+}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java b/ojluni/src/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java
new file mode 100644
index 0000000..07eb6f6
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/format/TestNarrowMonthNamesAndDayNames.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @modules jdk.localedata
+ * @bug 8146750
+ * @summary Test Narrow and NarrowStandalone month names are retrieved correctly.
+ */
+package test.java.time.format;
+
+import static org.testng.Assert.assertEquals;
+
+import java.time.DayOfWeek;
+import java.time.Month;
+import java.time.format.TextStyle;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class TestNarrowMonthNamesAndDayNames {
+
+    static {
+        System.setProperty("java.locale.providers", "COMPAT");
+    }
+
+    private static final List<Month> MONTHVALUES = Arrays.asList(Month.values());
+    private static final List<DayOfWeek> DAYVALUES = Arrays.asList(DayOfWeek.values());
+    private static final List<TextStyle> TEXTSTYLELIST = Arrays.asList(TextStyle.NARROW,
+            TextStyle.NARROW_STANDALONE);
+    private static final List<Locale> LOCARR = Arrays.asList(Locale.US,
+            Locale.GERMANY,
+            Locale.FRANCE,
+            new Locale("no", "NO"));
+
+    /**
+     * Locale en_US, de_DE, fr_FR, no_NO will have same Narrow and
+     * Narrow_Standalone month Names for COMPAT Provider.
+     */
+    @DataProvider(name = "MonthNarrows")
+    public Object[][] monthNameData() {
+        return new Object[][]{{new String[]{
+            "J",
+            "F",
+            "M",
+            "A",
+            "M",
+            "J",
+            "J",
+            "A",
+            "S",
+            "O",
+            "N",
+            "D"
+        }},};
+    }
+
+    //-----------------------------------------------------------------------
+    // Check Narrow and Narrow_standalone month name values
+    //-----------------------------------------------------------------------
+    @Test(dataProvider = "MonthNarrows")
+    public void compareMonthNarrowValues(String[] monthNarrowExpected) {
+        LOCARR.forEach((loc) -> {
+            TEXTSTYLELIST.forEach((style) -> {
+                MONTHVALUES.forEach((value) -> {
+                    String result = value.getDisplayName(style, loc);
+                    int index = value.ordinal();
+                    assertEquals(result, monthNarrowExpected[index], "Test failed"
+                            + " for COMPAT Provider for locale "
+                            + loc + " for style " + style.name()
+                            + " with Month value " + value.name());
+                });
+            });
+        });
+    }
+
+    /**
+     * Locale en_US, de_DE, fr_FR, no_NO will have different Narrow and
+     * Narrow_Standalone Day Names for COMPAT Provider.
+     */
+    @DataProvider(name = "DayNarrows")
+    public Object[][] dayNameData() {
+        return new Object[][]{
+            {Locale.US, new String[]{"M", "T", "W", "T", "F", "S", "S"}},
+            {Locale.GERMANY, new String[]{"M", "D", "M", "D", "F", "S", "S"}},
+            {Locale.FRANCE, new String[]{"L", "M", "M", "J", "V", "S", "D"}},
+            {new Locale("no", "NO"), new String[]{"M", "T", "O", "T", "F", "L", "S"}},};
+    }
+
+    //-----------------------------------------------------------------------
+    // Check Narrow and Narrow_standalone Day name values
+    //-----------------------------------------------------------------------
+    @Test(dataProvider = "DayNarrows")
+    public void compareDayNarrowValues(Locale locale, String[] dayNarrowExpected) {
+        TEXTSTYLELIST.forEach((style) -> {
+            DAYVALUES.forEach((value) -> {
+                String result = value.getDisplayName(style, locale);
+                int index = value.ordinal();
+                assertEquals(result, dayNarrowExpected[index], "Test failed"
+                        + " for COMPAT Provider for locale "
+                        + locale + " for style " + style.name()
+                        + " with Day value " + value.name());
+            });
+        });
+    }
+}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java b/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
index 310f008..95b4a6b 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestNonIsoFormatter.java
@@ -25,6 +25,7 @@
  *
  * @test
  * @bug 8206120
+ * @modules jdk.localedata
  */
 
 package test.java.time.format;
@@ -85,14 +86,9 @@
             // Chronology, Format Locale, Numbering Locale, ChronoLocalDate, expected string
             { JAPANESE, Locale.JAPANESE, Locale.JAPANESE, JAPANESE.date(IsoDate),
               "\u5e73\u621025\u5e742\u670811\u65e5\u6708\u66dc\u65e5" }, // Japanese Heisei 25-02-11
-            // Android-changed: requesting arabic numbering actually produces arabic digits. Also
-            // new CLDR patterns include the era. Test Arabic locale with ASCII digits below.
             { HIJRAH, ARABIC, ARABIC, HIJRAH.date(IsoDate),
               "\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c \u0661 \u0631\u0628\u064a\u0639 "
               + "\u0627\u0644\u0622\u062e\u0631 \u0661\u0664\u0663\u0664 \u0647\u0640" }, // Hijrah AH 1434-04-01 (Mon)
-            { HIJRAH, ARABIC, Locale.ENGLISH, HIJRAH.date(IsoDate),
-              "\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c 1 \u0631\u0628\u064a\u0639 "
-              + "\u0627\u0644\u0622\u062e\u0631 1434 \u0647\u0640" }, // Hijrah AH 1434-04-01 (Mon)
             { MINGUO, Locale.TAIWAN, Locale.TAIWAN, MINGUO.date(IsoDate),
               "\u6c11\u570b102\u5e742\u670811\u65e5 \u661f\u671f\u4e00" }, // Minguo ROC 102-02-11 (Mon)
             { BUDDHIST, thTH, thTH, BUDDHIST.date(IsoDate),
@@ -138,7 +134,7 @@
 
             { HIJRAH,   ARABIC, "\u0627\u0644\u062a\u0642\u0648\u064a\u0645 "
                                 + "\u0627\u0644\u0625\u0633\u0644\u0627\u0645\u064a "
-                                + "(\u0623\u0645 \u0627\u0644\u0642\u0631\u0649)" }, // JDK-8015986
+                                + "(\u0623\u0645 \u0627\u0644\u0642\u0631\u0649)" },
         };
     }
 
@@ -198,7 +194,7 @@
         String mdStr = "-01-01";
         DateTimeFormatter dtf = new DateTimeFormatterBuilder()
             .appendPattern("GGGG y-M-d")
-            .toFormatter()
+            .toFormatter(Locale.ROOT)
             .withChronology(chrono);
         DateTimeFormatter dtfLenient = dtf.withResolverStyle(ResolverStyle.LENIENT);
         assertEquals(LocalDate.parse(lenient+mdStr, dtfLenient), LocalDate.parse(strict+mdStr, dtf));
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java b/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java
index 721f337..b6126a6 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestTextParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,9 +69,12 @@
 import java.text.ParsePosition;
 import java.time.DayOfWeek;
 import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.TextStyle;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
+import java.time.temporal.TemporalQueries;
+import java.time.temporal.ChronoField;
 import java.util.Locale;
 
 import org.testng.annotations.DataProvider;
@@ -82,8 +85,6 @@
  */
 @Test
 public class TestTextParser extends AbstractTestPrinterParser {
-    static final Locale RUSSIAN = new Locale("ru");
-    static final Locale FINNISH = new Locale("fi");
 
     //-----------------------------------------------------------------------
     @DataProvider(name="error")
@@ -203,21 +204,6 @@
        };
     }
 
-    // Test data is dependent on localized resources.
-    @DataProvider(name="parseStandaloneText")
-    Object[][] providerStandaloneText() {
-        // Locale, TemporalField, TextStyle, expected value, input text
-        return new Object[][] {
-            // Android-changed: CLDR provides russian days/months in lower-case and with a fullstop.
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,   1, "\u044f\u043d\u0432\u0430\u0440\u044c" },
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  12, "\u0434\u0435\u043a\u0430\u0431\u0440\u044c" },
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE,  1, "\u044f\u043d\u0432." },
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0434\u0435\u043a." },
-            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,   2, "tiistai"},
-            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE,  2, "ti"},
-        };
-    }
-
     @DataProvider(name="parseDayOfWeekText")
     Object[][] providerDayOfWeekData() {
         return new Object[][] {
@@ -225,25 +211,9 @@
             {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
             {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
             {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
-
-            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
-            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
-            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
         };
     }
 
-    // Test data is dependent on localized resources.
-    @DataProvider(name="parseLenientText")
-    Object[][] providerLenientText() {
-        // Locale, TemporalField, expected value, input text
-        return new Object[][] {
-            // Android-changed: CLDR provides russian months in lower-case and with a fullstop.
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f" }, // full format
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044c" }, // full standalone
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432." },  // short format
-            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432." }, // short standalone
-        };
-    }
 
     @Test(dataProvider="parseText")
     public void test_parseText(TemporalField field, TextStyle style, int value, String input) throws Exception {
@@ -259,14 +229,6 @@
         assertEquals(pos.getIndex(), input.length());
     }
 
-    @Test(dataProvider="parseStandaloneText")
-    public void test_parseStandaloneText(Locale locale, TemporalField field, TextStyle style, int expectedValue, String input) {
-        DateTimeFormatter formatter = getFormatter(field, style).withLocale(locale);
-        ParsePosition pos = new ParsePosition(0);
-        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
-        assertEquals(pos.getIndex(), input.length());
-    }
-
     @Test(dataProvider="parseDayOfWeekText")
     public void test_parseDayOfWeekText(Locale locale, String pattern, String input, DayOfWeek expected) {
         DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale);
@@ -364,25 +326,6 @@
     }
 
     //-----------------------------------------------------------------------
-    public void test_parse_french_short_strict_full_noMatch() throws Exception {
-        setStrict(true);
-        ParsePosition pos = new ParsePosition(0);
-        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
-                                                    .parseUnresolved("janvier", pos);
-        assertEquals(pos.getErrorIndex(), 0);
-    }
-
-    public void test_parse_french_short_strict_short_match() throws Exception {
-        setStrict(true);
-        ParsePosition pos = new ParsePosition(0);
-        assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
-                                                                 .parseUnresolved("janv.", pos)
-                                                                 .getLong(MONTH_OF_YEAR),
-                     1L);
-        assertEquals(pos.getIndex(), 5);
-    }
-
-    //-----------------------------------------------------------------------
     public void test_parse_full_lenient_full_match() throws Exception {
         setStrict(false);
         ParsePosition pos = new ParsePosition(0);
@@ -426,13 +369,4 @@
         assertEquals(pos.getIndex(), 1);
     }
 
-    @Test(dataProvider="parseLenientText")
-    public void test_parseLenientText(Locale locale, TemporalField field, int expectedValue, String input) {
-        setStrict(false);
-        ParsePosition pos = new ParsePosition(0);
-        DateTimeFormatter formatter = getFormatter(field).withLocale(locale);
-        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
-        assertEquals(pos.getIndex(), input.length());
-    }
-
 }
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestTextParserWithLocale.java b/ojluni/src/test/java/time/test/java/time/format/TestTextParserWithLocale.java
new file mode 100644
index 0000000..ab5bdf2
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/format/TestTextParserWithLocale.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+
+package test.java.time.format;
+
+import java.text.ParsePosition;
+import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.HijrahDate;
+import java.time.chrono.JapaneseDate;
+import java.time.chrono.MinguoDate;
+import java.time.chrono.ThaiBuddhistDate;
+import java.time.DayOfWeek;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.TextStyle;
+import java.time.format.SignStyle;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalField;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
+import static java.time.temporal.ChronoField.DAY_OF_WEEK;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Test TextPrinterParser.
+ */
+@Test
+public class TestTextParserWithLocale extends AbstractTestPrinterParser {
+    static final Locale RUSSIAN = new Locale("ru");
+    static final Locale FINNISH = new Locale("fi");
+
+    @DataProvider(name="parseDayOfWeekText")
+    Object[][] providerDayOfWeekData() {
+        return new Object[][] {
+            // Locale, pattern, input text, expected DayOfWeek
+            {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
+            {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
+            {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
+
+            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
+            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
+            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
+        };
+    }
+
+    @Test(dataProvider="parseDayOfWeekText")
+    public void test_parseDayOfWeekText(Locale locale, String pattern, String input, DayOfWeek expected) {
+        DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale);
+        ParsePosition pos = new ParsePosition(0);
+        assertEquals(DayOfWeek.from(formatter.parse(input, pos)), expected);
+        assertEquals(pos.getIndex(), input.length());
+    }
+
+    //--------------------------------------------------------------------
+    // Test data is dependent on localized resources.
+    @DataProvider(name="parseStandaloneText")
+    Object[][] providerStandaloneText() {
+        // Locale, TemporalField, TextStyle, expected value, input text
+        return new Object[][] {
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,   1, "\u044f\u043d\u0432\u0430\u0440\u044c"},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  12, "\u0434\u0435\u043a\u0430\u0431\u0440\u044c"},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE,  1, "\u044f\u043d\u0432."},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, 12, "\u0434\u0435\u043a."},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,   2, "tiistai"},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE,  2, "ti"},
+        };
+    }
+
+    // Test data is dependent on localized resources.
+    @DataProvider(name="parseLenientText")
+    Object[][] providerLenientText() {
+        // Locale, TemporalField, expected value, input text
+        return new Object[][] {
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044f"}, // full format
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432\u0430\u0440\u044c"}, // full standalone
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short format
+            {RUSSIAN, MONTH_OF_YEAR, 1, "\u044f\u043d\u0432."}, // short standalone
+        };
+    }
+
+    @Test(dataProvider="parseStandaloneText")
+    public void test_parseStandaloneText(Locale locale, TemporalField field, TextStyle style, int expectedValue, String input) {
+        DateTimeFormatter formatter = getFormatter(field, style).withLocale(locale);
+        ParsePosition pos = new ParsePosition(0);
+        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
+        assertEquals(pos.getIndex(), input.length());
+    }
+
+    //-----------------------------------------------------------------------
+    public void test_parse_french_short_strict_full_noMatch() throws Exception {
+        setStrict(true);
+        ParsePosition pos = new ParsePosition(0);
+        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
+                                                    .parseUnresolved("janvier", pos);
+        assertEquals(pos.getErrorIndex(), 0);
+    }
+
+    public void test_parse_french_short_strict_short_match() throws Exception {
+        setStrict(true);
+        ParsePosition pos = new ParsePosition(0);
+        assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH)
+                                                                 .parseUnresolved("janv.", pos)
+                                                                 .getLong(MONTH_OF_YEAR),
+                     1L);
+        assertEquals(pos.getIndex(), 5);
+    }
+
+    //-----------------------------------------------------------------------
+
+    @Test(dataProvider="parseLenientText")
+    public void test_parseLenientText(Locale locale, TemporalField field, int expectedValue, String input) {
+        setStrict(false);
+        ParsePosition pos = new ParsePosition(0);
+        DateTimeFormatter formatter = getFormatter(field).withLocale(locale);
+        assertEquals(formatter.parseUnresolved(input, pos).getLong(field), (long) expectedValue);
+        assertEquals(pos.getIndex(), input.length());
+    }
+
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="parseChronoLocalDate")
+    Object[][] provider_chronoLocalDate() {
+        return new Object[][] {
+            { HijrahDate.now() },
+            { JapaneseDate.now() },
+            { MinguoDate.now() },
+            { ThaiBuddhistDate.now() }};
+    }
+
+    private static final DateTimeFormatter fmt_chrono =
+        new DateTimeFormatterBuilder()
+            .optionalStart()
+            .appendChronologyId()
+            .appendLiteral(' ')
+            .optionalEnd()
+            .optionalStart()
+            .appendText(ChronoField.ERA, TextStyle.SHORT)
+            .appendLiteral(' ')
+            .optionalEnd()
+            .appendValue(ChronoField.YEAR_OF_ERA, 1, 9, SignStyle.NORMAL)
+            .appendLiteral('-')
+            .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, SignStyle.NEVER)
+            .appendLiteral('-')
+            .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, SignStyle.NEVER)
+            .toFormatter();
+
+    @Test(dataProvider="parseChronoLocalDate")
+    public void test_chronoLocalDate(ChronoLocalDate date) throws Exception {
+        System.out.printf(" %s, [fmt=%s]%n", date, fmt_chrono.format(date));
+        assertEquals(date, fmt_chrono.parse(fmt_chrono.format(date), ChronoLocalDate::from));
+
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("[GGG ]yyy-MM-dd")
+                                                 .withChronology(date.getChronology());
+        System.out.printf(" %s, [fmt=%s]%n", date.toString(), fmt.format(date));
+        assertEquals(date, fmt.parse(fmt.format(date), ChronoLocalDate::from));
+    }
+}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java b/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java
index 19e6421..379d6a2 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestTextPrinter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -84,8 +84,6 @@
  */
 @Test
 public class TestTextPrinter extends AbstractTestPrinterParser {
-    static final Locale RUSSIAN = new Locale("ru");
-    static final Locale FINNISH = new Locale("fi");
 
     //-----------------------------------------------------------------------
     @Test(expectedExceptions=DateTimeException.class)
@@ -213,33 +211,6 @@
             {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
             {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
             {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
-
-            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
-            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
-            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
-        };
-    }
-
-    @DataProvider(name="print_JapaneseChronology")
-    Object[][] provider_japaneseEra() {
-       return new Object[][] {
-            {ERA,           TextStyle.FULL, 2, "Heisei"}, // Note: CLDR doesn't define "wide" Japanese era names.
-            {ERA,           TextStyle.SHORT, 2, "Heisei"},
-            {ERA,           TextStyle.NARROW, 2, "H"},
-       };
-    };
-
-    // Test data is dependent on localized resources.
-    @DataProvider(name="print_standalone")
-    Object[][] provider_StandaloneNames() {
-        return new Object[][] {
-            // standalone names for 2013-01-01 (Tue)
-            // Locale, TemporalField, TextStyle, expected text
-            // Android-changed: CLDR uses lower case for russian month names.
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  "\u044f\u043d\u0432\u0430\u0440\u044c"},
-            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u044f\u043d\u0432."},
-            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,  "tiistai"},
-            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE, "ti"},
         };
     }
 
@@ -256,30 +227,6 @@
         assertEquals(text, expected);
     }
 
-    @Test(dataProvider="print_JapaneseChronology")
-    public void test_formatJapaneseEra(TemporalField field, TextStyle style, int value, String expected) throws Exception {
-        LocalDate ld = LocalDate.of(2013, 1, 31);
-        getFormatter(field, style).withChronology(JapaneseChronology.INSTANCE).formatTo(ld, buf);
-        assertEquals(buf.toString(), expected);
-    }
-
-    @Test(dataProvider="print_standalone")
-    public void test_standaloneNames(Locale locale, TemporalField field, TextStyle style, String expected) {
-        getFormatter(field, style).withLocale(locale).formatTo(LocalDate.of(2013, 1, 1), buf);
-        assertEquals(buf.toString(), expected);
-    }
-
-    //-----------------------------------------------------------------------
-    public void test_print_french_long() throws Exception {
-        getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
-        assertEquals(buf.toString(), "janvier");
-    }
-
-    public void test_print_french_short() throws Exception {
-        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
-        assertEquals(buf.toString(), "janv.");
-    }
-
     //-----------------------------------------------------------------------
     public void test_toString1() throws Exception {
         assertEquals(getFormatter(MONTH_OF_YEAR, TextStyle.FULL).toString(), "Text(MonthOfYear)");
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java b/ojluni/src/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java
new file mode 100644
index 0000000..9c4d7d9
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/format/TestTextPrinterWithLocale.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ *  * Neither the name of JSR-310 nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * @test
+ * @modules jdk.localedata
+ */
+
+package test.java.time.format;
+
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
+import static java.time.temporal.ChronoField.DAY_OF_WEEK;
+import static java.time.temporal.ChronoField.ERA;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.IsoFields.QUARTER_OF_YEAR;
+import static org.testng.Assert.assertEquals;
+
+import java.time.DateTimeException;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.chrono.JapaneseChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.TextStyle;
+import java.time.temporal.TemporalField;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import test.java.time.temporal.MockFieldValue;
+
+/**
+ * Test TextPrinterParserWithLocale.
+ */
+@Test
+public class TestTextPrinterWithLocale extends AbstractTestPrinterParser {
+    static final Locale RUSSIAN = new Locale("ru");
+    static final Locale FINNISH = new Locale("fi");
+
+    //-----------------------------------------------------------------------
+    @DataProvider(name="print_DayOfWeekData")
+    Object[][] providerDayOfWeekData() {
+        return new Object[][] {
+            // Locale, pattern, expected text, input DayOfWeek
+            {Locale.US, "e",  "1",  DayOfWeek.SUNDAY},
+            {Locale.US, "ee", "01", DayOfWeek.SUNDAY},
+            {Locale.US, "c",  "1",  DayOfWeek.SUNDAY},
+
+            {Locale.UK, "e",  "1",  DayOfWeek.MONDAY},
+            {Locale.UK, "ee", "01", DayOfWeek.MONDAY},
+            {Locale.UK, "c",  "1",  DayOfWeek.MONDAY},
+        };
+    }
+
+    // Test data is dependent on localized resources.
+    @DataProvider(name="print_standalone")
+    Object[][] provider_StandaloneNames() {
+        return new Object[][] {
+            // standalone names for 2013-01-01 (Tue)
+            // Locale, TemporalField, TextStyle, expected text
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.FULL_STANDALONE,  "\u044f\u043d\u0432\u0430\u0440\u044c"},
+            {RUSSIAN, MONTH_OF_YEAR, TextStyle.SHORT_STANDALONE, "\u044f\u043d\u0432."},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.FULL_STANDALONE,  "tiistai"},
+            {FINNISH, DAY_OF_WEEK,   TextStyle.SHORT_STANDALONE, "ti"},
+        };
+    }
+
+    @Test(dataProvider="print_DayOfWeekData")
+    public void test_formatDayOfWeek(Locale locale, String pattern, String expected, DayOfWeek dayOfWeek) {
+        DateTimeFormatter formatter = getPatternFormatter(pattern).withLocale(locale);
+        String text = formatter.format(dayOfWeek);
+        assertEquals(text, expected);
+    }
+
+    @Test(dataProvider="print_standalone")
+    public void test_standaloneNames(Locale locale, TemporalField field, TextStyle style, String expected) {
+        getFormatter(field, style).withLocale(locale).formatTo(LocalDate.of(2013, 1, 1), buf);
+        assertEquals(buf.toString(), expected);
+    }
+
+    //-----------------------------------------------------------------------
+    public void test_print_french_long() throws Exception {
+        getFormatter(MONTH_OF_YEAR, TextStyle.FULL).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
+        assertEquals(buf.toString(), "janvier");
+    }
+
+    public void test_print_french_short() throws Exception {
+        getFormatter(MONTH_OF_YEAR, TextStyle.SHORT).withLocale(Locale.FRENCH).formatTo(LocalDate.of(2012, 1, 1), buf);
+        assertEquals(buf.toString(), "janv.");
+    }
+
+    @DataProvider(name="print_JapaneseChronology")
+    Object[][] provider_japaneseEra() {
+       return new Object[][] {
+            {ERA,           TextStyle.FULL, 2, "Heisei"}, // Note: CLDR doesn't define "wide" Japanese era names.
+            {ERA,           TextStyle.SHORT, 2, "Heisei"},
+            {ERA,           TextStyle.NARROW, 2, "H"},
+       };
+    };
+
+    @Test(dataProvider="print_JapaneseChronology")
+    public void test_formatJapaneseEra(TemporalField field, TextStyle style, int value, String expected) throws Exception {
+        LocalDate ld = LocalDate.of(2013, 1, 31);
+        getFormatter(field, style).withChronology(JapaneseChronology.INSTANCE).formatTo(ld, buf);
+        assertEquals(buf.toString(), expected);
+    }
+}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestUnicodeExtension.java b/ojluni/src/test/java/time/test/java/time/format/TestUnicodeExtension.java
new file mode 100644
index 0000000..4b71f06
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/format/TestUnicodeExtension.java
@@ -0,0 +1,859 @@
+/*
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8176841 8202537
+ * @summary Tests java.time classes deals with Unicode extensions
+ *      correctly.
+ * @modules jdk.localedata
+ */
+package test.java.time.format;
+
+import static org.testng.Assert.assertEquals;
+
+import java.time.DayOfWeek;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
+import java.time.chrono.Chronology;
+import java.time.chrono.HijrahChronology;
+import java.time.chrono.IsoChronology;
+import java.time.chrono.JapaneseChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.FormatStyle;
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalField;
+import java.time.temporal.WeekFields;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Test JavaTime with BCP47 U extensions
+ */
+@Test
+public class TestUnicodeExtension {
+    private static TimeZone defaultTZ;
+
+    private static final Chronology JAPANESE = JapaneseChronology.INSTANCE;
+    private static final Chronology HIJRAH = HijrahChronology.INSTANCE;
+
+    private static final ZoneId ASIATOKYO = ZoneId.of("Asia/Tokyo");
+    private static final ZoneId AMLA = ZoneId.of("America/Los_Angeles");
+
+    private static final Locale JPTYO = Locale.forLanguageTag("en-u-tz-jptyo");
+    private static final Locale JCAL = Locale.forLanguageTag("en-u-ca-japanese");
+    private static final Locale HCAL = Locale.forLanguageTag("en-u-ca-islamic-umalqura");
+
+    private static final Locale FW_SUN = Locale.forLanguageTag("en-US-u-fw-sun");
+    private static final Locale FW_MON = Locale.forLanguageTag("en-US-u-fw-mon");
+    private static final Locale FW_TUE = Locale.forLanguageTag("en-US-u-fw-tue");
+    private static final Locale FW_WED = Locale.forLanguageTag("en-US-u-fw-wed");
+    private static final Locale FW_THU = Locale.forLanguageTag("en-US-u-fw-thu");
+    private static final Locale FW_FRI = Locale.forLanguageTag("en-US-u-fw-fri");
+    private static final Locale FW_SAT = Locale.forLanguageTag("en-US-u-fw-sat");
+
+    private static final Locale RG_GB = Locale.forLanguageTag("en-US-u-rg-gbzzzz");
+
+    private static final ZonedDateTime ZDT = ZonedDateTime.of(2017, 8, 10, 15, 15, 0, 0, AMLA);
+
+    private static final String PATTERN = "GGGG MMMM-dd-uu HH:mm:ss zzzz";
+
+    @BeforeTest
+    public void beforeTest() {
+        defaultTZ = TimeZone.getDefault();
+        TimeZone.setDefault(TimeZone.getTimeZone(AMLA));
+    }
+
+    @AfterTest
+    public void afterTest() {
+        TimeZone.setDefault(defaultTZ);
+    }
+
+    @DataProvider(name="localizedBy")
+    Object[][] localizedBy() {
+        return new Object[][] {
+            // Locale, Chrono override, Zone override, Expected Chrono, Expected Zone,
+            // Expected formatted string
+            {Locale.JAPAN, null, null, null, null,
+            "2017\u5e748\u670810\u65e5\u6728\u66dc\u65e5 15\u664215\u520600\u79d2 \u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593"
+            },
+            {Locale.JAPAN, JAPANESE, null, JAPANESE, null,
+            "\u5e73\u621029\u5e748\u670810\u65e5\u6728\u66dc\u65e5 15\u664215\u520600\u79d2 \u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593"
+            },
+            {Locale.JAPAN, JAPANESE, ASIATOKYO, JAPANESE, ASIATOKYO,
+            "\u5e73\u621029\u5e748\u670811\u65e5\u91d1\u66dc\u65e5 7\u664215\u520600\u79d2 \u65e5\u672c\u6a19\u6e96\u6642"
+            },
+
+            {JCAL, null, null, JAPANESE, null,
+            "Thursday, August 10, 29 Heisei at 3:15:00 PM Pacific Daylight Time"
+            },
+            {JCAL, HIJRAH, null, JAPANESE, null,
+            "Thursday, August 10, 29 Heisei at 3:15:00 PM Pacific Daylight Time"
+            },
+            {HCAL, JAPANESE, null, HIJRAH, null,
+            "Thursday, Dhu\u02bbl-Qi\u02bbdah 18, 1438 AH at 3:15:00 PM Pacific Daylight Time"
+            },
+
+
+            {JPTYO, null, null, null, ASIATOKYO,
+            "Friday, August 11, 2017 at 7:15:00 AM Japan Standard Time"
+            },
+            {JPTYO, null, AMLA, null, ASIATOKYO,
+            "Friday, August 11, 2017 at 7:15:00 AM Japan Standard Time"
+            },
+            // invalid tz
+            {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+            {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, AMLA, null, AMLA,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+
+            {RG_GB, null, null, null, null,
+            // Android-changed: Android doesn't support "rg" extension yet.
+            // "Thursday, 10 August 2017 at 15:15:00 Pacific Daylight Time"
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+
+            // DecimalStyle
+            {Locale.forLanguageTag("en-US-u-nu-thai"), null, null, null, null,
+            "Thursday, August \u0e51\u0e50, \u0e52\u0e50\u0e51\u0e57 at \u0e53:\u0e51\u0e55:\u0e50\u0e50 PM Pacific Daylight Time"
+            },
+            // DecimalStyle, "nu" vs "rg"
+            {Locale.forLanguageTag("en-US-u-nu-thai-rg-uszzzz"), null, null, null, null,
+            "Thursday, August \u0e51\u0e50, \u0e52\u0e50\u0e51\u0e57 at \u0e53:\u0e51\u0e55:\u0e50\u0e50 PM Pacific Daylight Time"
+            },
+            // DecimalStyle, invalid
+            {Locale.forLanguageTag("en-US-u-nu-foo"), null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+        };
+    }
+
+    @DataProvider(name="withLocale")
+    Object[][] withLocale() {
+        return new Object[][] {
+            // Locale, Chrono override, Zone override, Expected Chrono, Expected Zone,
+            // Expected formatted string
+            {Locale.JAPAN, null, null, null, null,
+            "2017\u5e748\u670810\u65e5\u6728\u66dc\u65e5 15\u664215\u520600\u79d2 \u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593"
+            },
+            {Locale.JAPAN, JAPANESE, null, JAPANESE, null,
+            "\u5e73\u621029\u5e748\u670810\u65e5\u6728\u66dc\u65e5 15\u664215\u520600\u79d2 \u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593"
+            },
+            {Locale.JAPAN, JAPANESE, ASIATOKYO, JAPANESE, ASIATOKYO,
+            "\u5e73\u621029\u5e748\u670811\u65e5\u91d1\u66dc\u65e5 7\u664215\u520600\u79d2 \u65e5\u672c\u6a19\u6e96\u6642"
+            },
+
+            {JCAL, null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+            {JCAL, HIJRAH, null, HIJRAH, null,
+            "Thursday, Dhu\u02bbl-Qi\u02bbdah 18, 1438 AH at 3:15:00 PM Pacific Daylight Time"
+            },
+            {HCAL, JAPANESE, null, JAPANESE, null,
+            "Thursday, August 10, 29 Heisei at 3:15:00 PM Pacific Daylight Time"
+            },
+
+
+            {JPTYO, null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+            {JPTYO, null, AMLA, null, AMLA,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+            // invalid tz
+            {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+            {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+
+            {RG_GB, null, null, null, null,
+            // Android-changed: Android doesn't support "rg" extension yet.
+            // "Thursday, 10 August 2017 at 15:15:00 Pacific Daylight Time"
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+
+            // DecimalStyle
+            {Locale.forLanguageTag("en-US-u-nu-thai"), null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+            // DecimalStyle, "nu" vs "rg"
+            {Locale.forLanguageTag("en-US-u-nu-thai-rg-uszzzz"), null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+            // DecimalStyle, invalid
+            {Locale.forLanguageTag("en-US-u-nu-foo"), null, null, null, null,
+            "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time"
+            },
+        };
+    }
+
+    @DataProvider(name="firstDayOfWeek")
+    Object[][] firstDayOfWeek () {
+        return new Object[][] {
+            // Locale, Expected DayOfWeek,
+            {Locale.US, DayOfWeek.SUNDAY},
+            {FW_SUN, DayOfWeek.SUNDAY},
+            {FW_MON, DayOfWeek.MONDAY},
+            {FW_TUE, DayOfWeek.TUESDAY},
+            {FW_WED, DayOfWeek.WEDNESDAY},
+            {FW_THU, DayOfWeek.THURSDAY},
+            {FW_FRI, DayOfWeek.FRIDAY},
+            {FW_SAT, DayOfWeek.SATURDAY},
+
+            // invalid case
+            {Locale.forLanguageTag("en-US-u-fw-xxx"), DayOfWeek.SUNDAY},
+
+            // region override
+            {RG_GB, DayOfWeek.MONDAY},
+            {Locale.forLanguageTag("zh-CN-u-rg-eszzzz"), DayOfWeek.MONDAY},
+
+            // "fw" and "rg".
+            {Locale.forLanguageTag("en-US-u-fw-wed-rg-gbzzzz"), DayOfWeek.WEDNESDAY},
+            {Locale.forLanguageTag("en-US-u-fw-xxx-rg-gbzzzz"), DayOfWeek.MONDAY},
+            {Locale.forLanguageTag("en-US-u-fw-xxx-rg-zzzz"), DayOfWeek.SUNDAY},
+        };
+    }
+
+    @DataProvider(name="minDaysInFirstWeek")
+    Object[][] minDaysInFrstWeek () {
+        return new Object[][] {
+            // Locale, Expected minDay,
+            {Locale.US, 1},
+
+            // region override
+            {RG_GB, 4},
+            {Locale.forLanguageTag("zh-CN-u-rg-eszzzz"), 4},
+        };
+    }
+
+    @DataProvider(name="ofPattern")
+    Object[][] ofPattern() {
+        return new Object[][] {
+            // Locale, Expected Chrono, Expected Zone,
+            // Expected formatted string
+            {JCAL, null, null,
+            "Anno Domini August-10-17 15:15:00 Pacific Daylight Time"
+            },
+            {HCAL, null, null,
+            "Anno Domini August-10-17 15:15:00 Pacific Daylight Time"
+            },
+
+            {JPTYO, null, null,
+            "Anno Domini August-10-17 15:15:00 Pacific Daylight Time"
+            },
+            {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, null,
+            "Anno Domini August-10-17 15:15:00 Pacific Daylight Time"
+            },
+
+            {RG_GB, null, null,
+            "Anno Domini August-10-17 15:15:00 Pacific Daylight Time"
+            },
+
+        };
+    }
+
+    @DataProvider(name="shortTZID")
+    Object[][] shortTZID() {
+        return new Object[][] {
+            // LDML's short ID, Expected Zone,
+            {"adalv", "Europe/Andorra"},
+            {"aedxb", "Asia/Dubai"},
+            {"afkbl", "Asia/Kabul"},
+            {"aganu", "America/Antigua"},
+            {"aiaxa", "America/Anguilla"},
+            {"altia", "Europe/Tirane"},
+            {"amevn", "Asia/Yerevan"},
+            {"ancur", "America/Curacao"},
+            {"aolad", "Africa/Luanda"},
+            {"aqcas", "Antarctica/Casey"},
+            {"aqdav", "Antarctica/Davis"},
+            {"aqddu", "Antarctica/DumontDUrville"},
+            {"aqmaw", "Antarctica/Mawson"},
+            {"aqmcm", "Antarctica/McMurdo"},
+            {"aqplm", "Antarctica/Palmer"},
+            {"aqrot", "Antarctica/Rothera"},
+            {"aqsyw", "Antarctica/Syowa"},
+            {"aqtrl", "Antarctica/Troll"},
+            {"aqvos", "Antarctica/Vostok"},
+            {"arbue", "America/Buenos_Aires"},
+            {"arcor", "America/Cordoba"},
+            {"arctc", "America/Catamarca"},
+            {"arirj", "America/Argentina/La_Rioja"},
+            {"arjuj", "America/Jujuy"},
+            {"arluq", "America/Argentina/San_Luis"},
+            {"armdz", "America/Mendoza"},
+            {"arrgl", "America/Argentina/Rio_Gallegos"},
+            {"arsla", "America/Argentina/Salta"},
+            {"artuc", "America/Argentina/Tucuman"},
+            {"aruaq", "America/Argentina/San_Juan"},
+            {"arush", "America/Argentina/Ushuaia"},
+            {"asppg", "Pacific/Pago_Pago"},
+            {"atvie", "Europe/Vienna"},
+            {"auadl", "Australia/Adelaide"},
+            {"aubhq", "Australia/Broken_Hill"},
+            {"aubne", "Australia/Brisbane"},
+            {"audrw", "Australia/Darwin"},
+            {"aueuc", "Australia/Eucla"},
+            {"auhba", "Australia/Hobart"},
+            {"aukns", "Australia/Currie"},
+            {"auldc", "Australia/Lindeman"},
+            {"auldh", "Australia/Lord_Howe"},
+            {"aumel", "Australia/Melbourne"},
+            {"aumqi", "Antarctica/Macquarie"},
+            {"auper", "Australia/Perth"},
+            {"ausyd", "Australia/Sydney"},
+            {"awaua", "America/Aruba"},
+            {"azbak", "Asia/Baku"},
+            {"basjj", "Europe/Sarajevo"},
+            {"bbbgi", "America/Barbados"},
+            {"bddac", "Asia/Dhaka"},
+            {"bebru", "Europe/Brussels"},
+            {"bfoua", "Africa/Ouagadougou"},
+            {"bgsof", "Europe/Sofia"},
+            {"bhbah", "Asia/Bahrain"},
+            {"bibjm", "Africa/Bujumbura"},
+            {"bjptn", "Africa/Porto-Novo"},
+            {"bmbda", "Atlantic/Bermuda"},
+            {"bnbwn", "Asia/Brunei"},
+            {"bolpb", "America/La_Paz"},
+            {"bqkra", "America/Kralendijk"},
+            {"braux", "America/Araguaina"},
+            {"brbel", "America/Belem"},
+            {"brbvb", "America/Boa_Vista"},
+            {"brcgb", "America/Cuiaba"},
+            {"brcgr", "America/Campo_Grande"},
+            {"brern", "America/Eirunepe"},
+            {"brfen", "America/Noronha"},
+            {"brfor", "America/Fortaleza"},
+            {"brmao", "America/Manaus"},
+            {"brmcz", "America/Maceio"},
+            {"brpvh", "America/Porto_Velho"},
+            {"brrbr", "America/Rio_Branco"},
+            {"brrec", "America/Recife"},
+            {"brsao", "America/Sao_Paulo"},
+            {"brssa", "America/Bahia"},
+            {"brstm", "America/Santarem"},
+            {"bsnas", "America/Nassau"},
+            {"btthi", "Asia/Thimphu"},
+            {"bwgbe", "Africa/Gaborone"},
+            {"bymsq", "Europe/Minsk"},
+            {"bzbze", "America/Belize"},
+            {"cacfq", "America/Creston"},
+            {"caedm", "America/Edmonton"},
+            {"caffs", "America/Rainy_River"},
+            {"cafne", "America/Fort_Nelson"},
+            {"caglb", "America/Glace_Bay"},
+            {"cagoo", "America/Goose_Bay"},
+            {"cahal", "America/Halifax"},
+            {"caiql", "America/Iqaluit"},
+            {"camon", "America/Moncton"},
+            {"capnt", "America/Pangnirtung"},
+            {"careb", "America/Resolute"},
+            {"careg", "America/Regina"},
+            {"casjf", "America/St_Johns"},
+            {"canpg", "America/Nipigon"},
+            {"cathu", "America/Thunder_Bay"},
+            {"cator", "America/Toronto"},
+            {"cavan", "America/Vancouver"},
+            {"cawnp", "America/Winnipeg"},
+            {"caybx", "America/Blanc-Sablon"},
+            {"caycb", "America/Cambridge_Bay"},
+            {"cayda", "America/Dawson"},
+            {"caydq", "America/Dawson_Creek"},
+            {"cayek", "America/Rankin_Inlet"},
+            {"cayev", "America/Inuvik"},
+            {"cayxy", "America/Whitehorse"},
+            {"cayyn", "America/Swift_Current"},
+            {"cayzf", "America/Yellowknife"},
+            {"cayzs", "America/Coral_Harbour"},
+            {"cccck", "Indian/Cocos"},
+            {"cdfbm", "Africa/Lubumbashi"},
+            {"cdfih", "Africa/Kinshasa"},
+            {"cfbgf", "Africa/Bangui"},
+            {"cgbzv", "Africa/Brazzaville"},
+            {"chzrh", "Europe/Zurich"},
+            {"ciabj", "Africa/Abidjan"},
+            {"ckrar", "Pacific/Rarotonga"},
+            {"clipc", "Pacific/Easter"},
+            {"clscl", "America/Santiago"},
+            {"cmdla", "Africa/Douala"},
+            {"cnsha", "Asia/Shanghai"},
+            {"cnurc", "Asia/Urumqi"},
+            {"cobog", "America/Bogota"},
+            {"crsjo", "America/Costa_Rica"},
+            {"cst6cdt", "CST6CDT"},
+            {"cuhav", "America/Havana"},
+            {"cvrai", "Atlantic/Cape_Verde"},
+            {"cxxch", "Indian/Christmas"},
+            {"cynic", "Asia/Nicosia"},
+            {"czprg", "Europe/Prague"},
+            {"deber", "Europe/Berlin"},
+            {"debsngn", "Europe/Busingen"},
+            {"djjib", "Africa/Djibouti"},
+            {"dkcph", "Europe/Copenhagen"},
+            {"dmdom", "America/Dominica"},
+            {"dosdq", "America/Santo_Domingo"},
+            {"dzalg", "Africa/Algiers"},
+            {"ecgps", "Pacific/Galapagos"},
+            {"ecgye", "America/Guayaquil"},
+            {"eetll", "Europe/Tallinn"},
+            {"egcai", "Africa/Cairo"},
+            {"eheai", "Africa/El_Aaiun"},
+            {"erasm", "Africa/Asmera"},
+            {"esceu", "Africa/Ceuta"},
+            {"eslpa", "Atlantic/Canary"},
+            {"esmad", "Europe/Madrid"},
+            {"est5edt", "EST5EDT"},
+            {"etadd", "Africa/Addis_Ababa"},
+            {"fihel", "Europe/Helsinki"},
+            {"fimhq", "Europe/Mariehamn"},
+            {"fjsuv", "Pacific/Fiji"},
+            {"fkpsy", "Atlantic/Stanley"},
+            {"fmksa", "Pacific/Kosrae"},
+            {"fmpni", "Pacific/Ponape"},
+            {"fmtkk", "Pacific/Truk"},
+            {"fotho", "Atlantic/Faeroe"},
+            {"frpar", "Europe/Paris"},
+            {"galbv", "Africa/Libreville"},
+            {"gaza", "Asia/Gaza"},
+            {"gblon", "Europe/London"},
+            {"gdgnd", "America/Grenada"},
+            {"getbs", "Asia/Tbilisi"},
+            {"gfcay", "America/Cayenne"},
+            {"gggci", "Europe/Guernsey"},
+            {"ghacc", "Africa/Accra"},
+            {"gigib", "Europe/Gibraltar"},
+            {"gldkshvn", "America/Danmarkshavn"},
+            {"glgoh", "America/Godthab"},
+            {"globy", "America/Scoresbysund"},
+            {"glthu", "America/Thule"},
+            {"gmbjl", "Africa/Banjul"},
+            {"gncky", "Africa/Conakry"},
+            {"gpbbr", "America/Guadeloupe"},
+            {"gpmsb", "America/Marigot"},
+            {"gpsbh", "America/St_Barthelemy"},
+            {"gqssg", "Africa/Malabo"},
+            {"grath", "Europe/Athens"},
+            {"gsgrv", "Atlantic/South_Georgia"},
+            {"gtgua", "America/Guatemala"},
+            {"gugum", "Pacific/Guam"},
+            {"gwoxb", "Africa/Bissau"},
+            {"gygeo", "America/Guyana"},
+            {"hebron", "Asia/Hebron"},
+            {"hkhkg", "Asia/Hong_Kong"},
+            {"hntgu", "America/Tegucigalpa"},
+            {"hrzag", "Europe/Zagreb"},
+            {"htpap", "America/Port-au-Prince"},
+            {"hubud", "Europe/Budapest"},
+            {"iddjj", "Asia/Jayapura"},
+            {"idjkt", "Asia/Jakarta"},
+            {"idmak", "Asia/Makassar"},
+            {"idpnk", "Asia/Pontianak"},
+            {"iedub", "Europe/Dublin"},
+            {"imdgs", "Europe/Isle_of_Man"},
+            {"inccu", "Asia/Calcutta"},
+            {"iodga", "Indian/Chagos"},
+            {"iqbgw", "Asia/Baghdad"},
+            {"irthr", "Asia/Tehran"},
+            {"isrey", "Atlantic/Reykjavik"},
+            {"itrom", "Europe/Rome"},
+            {"jeruslm", "Asia/Jerusalem"},
+            {"jesth", "Europe/Jersey"},
+            {"jmkin", "America/Jamaica"},
+            {"joamm", "Asia/Amman"},
+            {"jptyo", "Asia/Tokyo"},
+            {"kenbo", "Africa/Nairobi"},
+            {"kgfru", "Asia/Bishkek"},
+            {"khpnh", "Asia/Phnom_Penh"},
+            {"kicxi", "Pacific/Kiritimati"},
+            {"kipho", "Pacific/Enderbury"},
+            {"kitrw", "Pacific/Tarawa"},
+            {"kmyva", "Indian/Comoro"},
+            {"knbas", "America/St_Kitts"},
+            {"kpfnj", "Asia/Pyongyang"},
+            {"krsel", "Asia/Seoul"},
+            {"kwkwi", "Asia/Kuwait"},
+            {"kygec", "America/Cayman"},
+            {"kzaau", "Asia/Aqtau"},
+            {"kzakx", "Asia/Aqtobe"},
+            {"kzala", "Asia/Almaty"},
+            {"kzkzo", "Asia/Qyzylorda"},
+            {"kzura", "Asia/Oral"},
+            {"lavte", "Asia/Vientiane"},
+            {"lbbey", "Asia/Beirut"},
+            {"lccas", "America/St_Lucia"},
+            {"livdz", "Europe/Vaduz"},
+            {"lkcmb", "Asia/Colombo"},
+            {"lrmlw", "Africa/Monrovia"},
+            {"lsmsu", "Africa/Maseru"},
+            {"ltvno", "Europe/Vilnius"},
+            {"lulux", "Europe/Luxembourg"},
+            {"lvrix", "Europe/Riga"},
+            {"lytip", "Africa/Tripoli"},
+            {"macas", "Africa/Casablanca"},
+            {"mcmon", "Europe/Monaco"},
+            {"mdkiv", "Europe/Chisinau"},
+            {"metgd", "Europe/Podgorica"},
+            {"mgtnr", "Indian/Antananarivo"},
+            {"mhkwa", "Pacific/Kwajalein"},
+            {"mhmaj", "Pacific/Majuro"},
+            {"mkskp", "Europe/Skopje"},
+            {"mlbko", "Africa/Bamako"},
+            {"mmrgn", "Asia/Rangoon"},
+            {"mncoq", "Asia/Choibalsan"},
+            {"mnhvd", "Asia/Hovd"},
+            {"mnuln", "Asia/Ulaanbaatar"},
+            {"momfm", "Asia/Macau"},
+            {"mpspn", "Pacific/Saipan"},
+            {"mqfdf", "America/Martinique"},
+            {"mrnkc", "Africa/Nouakchott"},
+            {"msmni", "America/Montserrat"},
+            {"mst7mdt", "MST7MDT"},
+            {"mtmla", "Europe/Malta"},
+            {"muplu", "Indian/Mauritius"},
+            {"mvmle", "Indian/Maldives"},
+            {"mwblz", "Africa/Blantyre"},
+            {"mxchi", "America/Chihuahua"},
+            {"mxcun", "America/Cancun"},
+            {"mxhmo", "America/Hermosillo"},
+            {"mxmam", "America/Matamoros"},
+            {"mxmex", "America/Mexico_City"},
+            {"mxmid", "America/Merida"},
+            {"mxmty", "America/Monterrey"},
+            {"mxmzt", "America/Mazatlan"},
+            {"mxoji", "America/Ojinaga"},
+            {"mxpvr", "America/Bahia_Banderas"},
+            {"mxstis", "America/Santa_Isabel"},
+            {"mxtij", "America/Tijuana"},
+            {"mykch", "Asia/Kuching"},
+            {"mykul", "Asia/Kuala_Lumpur"},
+            {"mzmpm", "Africa/Maputo"},
+            {"nawdh", "Africa/Windhoek"},
+            {"ncnou", "Pacific/Noumea"},
+            {"nenim", "Africa/Niamey"},
+            {"nfnlk", "Pacific/Norfolk"},
+            {"nglos", "Africa/Lagos"},
+            {"nimga", "America/Managua"},
+            {"nlams", "Europe/Amsterdam"},
+            {"noosl", "Europe/Oslo"},
+            {"npktm", "Asia/Katmandu"},
+            {"nrinu", "Pacific/Nauru"},
+            {"nuiue", "Pacific/Niue"},
+            {"nzakl", "Pacific/Auckland"},
+            {"nzcht", "Pacific/Chatham"},
+            {"ommct", "Asia/Muscat"},
+            {"papty", "America/Panama"},
+            {"pelim", "America/Lima"},
+            {"pfgmr", "Pacific/Gambier"},
+            {"pfnhv", "Pacific/Marquesas"},
+            {"pfppt", "Pacific/Tahiti"},
+            {"pgpom", "Pacific/Port_Moresby"},
+            {"pgraw", "Pacific/Bougainville"},
+            {"phmnl", "Asia/Manila"},
+            {"pkkhi", "Asia/Karachi"},
+            {"plwaw", "Europe/Warsaw"},
+            {"pmmqc", "America/Miquelon"},
+            {"pnpcn", "Pacific/Pitcairn"},
+            {"prsju", "America/Puerto_Rico"},
+            {"pst8pdt", "PST8PDT"},
+            {"ptfnc", "Atlantic/Madeira"},
+            {"ptlis", "Europe/Lisbon"},
+            {"ptpdl", "Atlantic/Azores"},
+            {"pwror", "Pacific/Palau"},
+            {"pyasu", "America/Asuncion"},
+            {"qadoh", "Asia/Qatar"},
+            {"rereu", "Indian/Reunion"},
+            {"robuh", "Europe/Bucharest"},
+            {"rsbeg", "Europe/Belgrade"},
+            {"ruchita", "Asia/Chita"},
+            {"rudyr", "Asia/Anadyr"},
+            {"rugdx", "Asia/Magadan"},
+            {"ruikt", "Asia/Irkutsk"},
+            {"rukgd", "Europe/Kaliningrad"},
+            {"rukhndg", "Asia/Khandyga"},
+            {"rukra", "Asia/Krasnoyarsk"},
+            {"rukuf", "Europe/Samara"},
+            {"rumow", "Europe/Moscow"},
+            {"runoz", "Asia/Novokuznetsk"},
+            {"ruoms", "Asia/Omsk"},
+            {"ruovb", "Asia/Novosibirsk"},
+            {"rupkc", "Asia/Kamchatka"},
+            {"rusred", "Asia/Srednekolymsk"},
+            {"ruunera", "Asia/Ust-Nera"},
+            {"ruuus", "Asia/Sakhalin"},
+            {"ruvog", "Europe/Volgograd"},
+            {"ruvvo", "Asia/Vladivostok"},
+            {"ruyek", "Asia/Yekaterinburg"},
+            {"ruyks", "Asia/Yakutsk"},
+            {"rwkgl", "Africa/Kigali"},
+            {"saruh", "Asia/Riyadh"},
+            {"sbhir", "Pacific/Guadalcanal"},
+            {"scmaw", "Indian/Mahe"},
+            {"sdkrt", "Africa/Khartoum"},
+            {"sesto", "Europe/Stockholm"},
+            {"sgsin", "Asia/Singapore"},
+            {"shshn", "Atlantic/St_Helena"},
+            {"silju", "Europe/Ljubljana"},
+            {"sjlyr", "Arctic/Longyearbyen"},
+            {"skbts", "Europe/Bratislava"},
+            {"slfna", "Africa/Freetown"},
+            {"smsai", "Europe/San_Marino"},
+            {"sndkr", "Africa/Dakar"},
+            {"somgq", "Africa/Mogadishu"},
+            {"srpbm", "America/Paramaribo"},
+            {"ssjub", "Africa/Juba"},
+            {"sttms", "Africa/Sao_Tome"},
+            {"svsal", "America/El_Salvador"},
+            {"sxphi", "America/Lower_Princes"},
+            {"sydam", "Asia/Damascus"},
+            {"szqmn", "Africa/Mbabane"},
+            {"tcgdt", "America/Grand_Turk"},
+            {"tdndj", "Africa/Ndjamena"},
+            {"tfpfr", "Indian/Kerguelen"},
+            {"tglfw", "Africa/Lome"},
+            {"thbkk", "Asia/Bangkok"},
+            {"tjdyu", "Asia/Dushanbe"},
+            {"tkfko", "Pacific/Fakaofo"},
+            {"tldil", "Asia/Dili"},
+            {"tmasb", "Asia/Ashgabat"},
+            {"tntun", "Africa/Tunis"},
+            {"totbu", "Pacific/Tongatapu"},
+            {"trist", "Europe/Istanbul"},
+            {"ttpos", "America/Port_of_Spain"},
+            {"tvfun", "Pacific/Funafuti"},
+            {"twtpe", "Asia/Taipei"},
+            {"tzdar", "Africa/Dar_es_Salaam"},
+            {"uaiev", "Europe/Kiev"},
+            {"uaozh", "Europe/Zaporozhye"},
+            {"uasip", "Europe/Simferopol"},
+            {"uauzh", "Europe/Uzhgorod"},
+            {"ugkla", "Africa/Kampala"},
+            {"umawk", "Pacific/Wake"},
+            {"umjon", "Pacific/Johnston"},
+            {"ummdy", "Pacific/Midway"},
+//            {"unk", "Etc/Unknown"},
+            {"usadk", "America/Adak"},
+            {"usaeg", "America/Indiana/Marengo"},
+            {"usanc", "America/Anchorage"},
+            {"usboi", "America/Boise"},
+            {"uschi", "America/Chicago"},
+            {"usden", "America/Denver"},
+            {"usdet", "America/Detroit"},
+            {"ushnl", "Pacific/Honolulu"},
+            {"usind", "America/Indianapolis"},
+            {"usinvev", "America/Indiana/Vevay"},
+            {"usjnu", "America/Juneau"},
+            {"usknx", "America/Indiana/Knox"},
+            {"uslax", "America/Los_Angeles"},
+            {"uslui", "America/Louisville"},
+            {"usmnm", "America/Menominee"},
+            {"usmtm", "America/Metlakatla"},
+            {"usmoc", "America/Kentucky/Monticello"},
+            {"usndcnt", "America/North_Dakota/Center"},
+            {"usndnsl", "America/North_Dakota/New_Salem"},
+            {"usnyc", "America/New_York"},
+            {"usoea", "America/Indiana/Vincennes"},
+            {"usome", "America/Nome"},
+            {"usphx", "America/Phoenix"},
+            {"ussit", "America/Sitka"},
+            {"ustel", "America/Indiana/Tell_City"},
+            {"uswlz", "America/Indiana/Winamac"},
+            {"uswsq", "America/Indiana/Petersburg"},
+            {"usxul", "America/North_Dakota/Beulah"},
+            {"usyak", "America/Yakutat"},
+            {"utc", "Etc/UTC"},
+            {"utce01", "Etc/GMT-1"},
+            {"utce02", "Etc/GMT-2"},
+            {"utce03", "Etc/GMT-3"},
+            {"utce04", "Etc/GMT-4"},
+            {"utce05", "Etc/GMT-5"},
+            {"utce06", "Etc/GMT-6"},
+            {"utce07", "Etc/GMT-7"},
+            {"utce08", "Etc/GMT-8"},
+            {"utce09", "Etc/GMT-9"},
+            {"utce10", "Etc/GMT-10"},
+            {"utce11", "Etc/GMT-11"},
+            {"utce12", "Etc/GMT-12"},
+            {"utce13", "Etc/GMT-13"},
+            {"utce14", "Etc/GMT-14"},
+            {"utcw01", "Etc/GMT+1"},
+            {"utcw02", "Etc/GMT+2"},
+            {"utcw03", "Etc/GMT+3"},
+            {"utcw04", "Etc/GMT+4"},
+            {"utcw05", "Etc/GMT+5"},
+            {"utcw06", "Etc/GMT+6"},
+            {"utcw07", "Etc/GMT+7"},
+            {"utcw08", "Etc/GMT+8"},
+            {"utcw09", "Etc/GMT+9"},
+            {"utcw10", "Etc/GMT+10"},
+            {"utcw11", "Etc/GMT+11"},
+            {"utcw12", "Etc/GMT+12"},
+            {"uymvd", "America/Montevideo"},
+            {"uzskd", "Asia/Samarkand"},
+            {"uztas", "Asia/Tashkent"},
+            {"vavat", "Europe/Vatican"},
+            {"vcsvd", "America/St_Vincent"},
+            {"veccs", "America/Caracas"},
+            {"vgtov", "America/Tortola"},
+            {"vistt", "America/St_Thomas"},
+            {"vnsgn", "Asia/Saigon"},
+            {"vuvli", "Pacific/Efate"},
+            {"wfmau", "Pacific/Wallis"},
+            {"wsapw", "Pacific/Apia"},
+            {"yeade", "Asia/Aden"},
+            {"ytmam", "Indian/Mayotte"},
+            {"zajnb", "Africa/Johannesburg"},
+            {"zmlun", "Africa/Lusaka"},
+            {"zwhre", "Africa/Harare"},
+
+        };
+    }
+
+    @DataProvider(name="getLocalizedDateTimePattern")
+    Object[][] getLocalizedDateTimePattern() {
+        return new Object[][] {
+            // Locale, Expected pattern,
+            {Locale.US, FormatStyle.FULL, "EEEE, MMMM d, y 'at' h:mm:ss a zzzz"},
+            {Locale.US, FormatStyle.LONG, "MMMM d, y 'at' h:mm:ss a z"},
+            {Locale.US, FormatStyle.MEDIUM, "MMM d, y, h:mm:ss a"},
+            {Locale.US, FormatStyle.SHORT, "M/d/yy, h:mm a"},
+            {RG_GB, FormatStyle.FULL, "EEEE, d MMMM y 'at' HH:mm:ss zzzz"},
+            {RG_GB, FormatStyle.LONG, "d MMMM y 'at' HH:mm:ss z"},
+            {RG_GB, FormatStyle.MEDIUM, "d MMM y, HH:mm:ss"},
+            {RG_GB, FormatStyle.SHORT, "dd/MM/y, HH:mm"},
+        };
+    }
+
+    @DataProvider(name="getDisplayName")
+    Object[][] getDisplayName() {
+        return new Object[][] {
+            // Locale, field, Expected name,
+            {Locale.US, ChronoField.AMPM_OF_DAY, "AM/PM"},
+            // Android-changed: Android uses CLDR data.
+            // {RG_GB, ChronoField.AMPM_OF_DAY, "am/pm"},
+            {RG_GB, ChronoField.AMPM_OF_DAY, "AM/PM"},
+        };
+    }
+
+    @Test(dataProvider="localizedBy")
+    public void test_localizedBy(Locale locale, Chronology chrono, ZoneId zone,
+                                Chronology chronoExpected, ZoneId zoneExpected,
+                                String formatExpected) {
+        DateTimeFormatter dtf =
+            DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.FULL)
+                .withChronology(chrono).withZone(zone).localizedBy(locale);
+        assertEquals(dtf.getChronology(), chronoExpected);
+        assertEquals(dtf.getZone(), zoneExpected);
+        String formatted = dtf.format(ZDT);
+        assertEquals(formatted, formatExpected);
+        assertEquals(dtf.parse(formatted, ZonedDateTime::from),
+            zoneExpected != null ? ZDT.withZoneSameInstant(zoneExpected) : ZDT);
+    }
+
+    @Test(dataProvider="withLocale")
+    public void test_withLocale(Locale locale, Chronology chrono, ZoneId zone,
+                                Chronology chronoExpected, ZoneId zoneExpected,
+                                String formatExpected) {
+        DateTimeFormatter dtf =
+            DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.FULL)
+                .withChronology(chrono).withZone(zone).withLocale(locale);
+        assertEquals(dtf.getChronology(), chronoExpected);
+        assertEquals(dtf.getZone(), zoneExpected);
+        String formatted = dtf.format(ZDT);
+        assertEquals(formatted, formatExpected);
+        assertEquals(dtf.parse(formatted, ZonedDateTime::from),
+            zoneExpected != null ? ZDT.withZoneSameInstant(zoneExpected) : ZDT);
+    }
+
+    @Test(dataProvider="firstDayOfWeek")
+    public void test_firstDayOfWeek(Locale locale, DayOfWeek dowExpected) {
+        DayOfWeek dow = WeekFields.of(locale).getFirstDayOfWeek();
+        assertEquals(dow, dowExpected);
+    }
+
+    @Test(dataProvider="minDaysInFirstWeek")
+    public void test_minDaysInFirstWeek(Locale locale, int minDaysExpected) {
+        int minDays = WeekFields.of(locale).getMinimalDaysInFirstWeek();
+        assertEquals(minDays, minDaysExpected);
+    }
+
+    @Test(dataProvider="ofPattern")
+    public void test_ofPattern(Locale locale,
+                                Chronology chronoExpected, ZoneId zoneExpected,
+                                String formatExpected) {
+        DateTimeFormatter dtf =
+            DateTimeFormatter.ofPattern(PATTERN, locale);
+        assertEquals(dtf.getChronology(), chronoExpected);
+        assertEquals(dtf.getZone(), zoneExpected);
+        String formatted = dtf.format(ZDT);
+        assertEquals(formatted, formatExpected);
+        assertEquals(dtf.parse(formatted, ZonedDateTime::from),
+            zoneExpected != null ? ZDT.withZoneSameInstant(zoneExpected) : ZDT);
+    }
+
+    @Test(dataProvider="ofPattern")
+    public void test_toFormatter(Locale locale,
+                                Chronology chronoExpected, ZoneId zoneExpected,
+                                String formatExpected) {
+        DateTimeFormatter dtf =
+            new DateTimeFormatterBuilder().appendPattern(PATTERN).toFormatter(locale);
+        assertEquals(dtf.getChronology(), chronoExpected);
+        assertEquals(dtf.getZone(), zoneExpected);
+        String formatted = dtf.format(ZDT);
+        assertEquals(formatted, formatExpected);
+        assertEquals(dtf.parse(formatted, ZonedDateTime::from),
+            zoneExpected != null ? ZDT.withZoneSameInstant(zoneExpected) : ZDT);
+    }
+
+    @Test(dataProvider="shortTZID")
+    public void test_shortTZID(String shortID, String expectedZone) {
+        Locale l = Locale.forLanguageTag("en-US-u-tz-" + shortID);
+        DateTimeFormatter dtf =
+            DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.FULL)
+                .localizedBy(l);
+        assertEquals(dtf.getZone(), ZoneId.of(expectedZone));
+    }
+
+    // Android-changed: Android doesn't support "rg" extension yet.
+    @Test(dataProvider="getLocalizedDateTimePattern", enabled = false)
+    public void test_getLocalizedDateTimePattern(Locale l, FormatStyle s, String expectedPattern) {
+        DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
+        assertEquals(dtfb.getLocalizedDateTimePattern(s, s, IsoChronology.INSTANCE, l),
+            expectedPattern);
+    }
+
+    @Test(dataProvider="getDisplayName")
+    public void test_getDisplayName(Locale l, TemporalField f, String expectedName) {
+        assertEquals(f.getDisplayName(l), expectedName);
+    }
+}
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestZoneOffsetParser.java b/ojluni/src/test/java/time/test/java/time/format/TestZoneOffsetParser.java
index 68e84a2..3242554 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestZoneOffsetParser.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestZoneOffsetParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -296,7 +296,7 @@
     @DataProvider(name="bigOffsets")
     Object[][] provider_bigOffsets() {
         return new Object[][] {
-            {"+HH", "+59", 59 * 3600},
+            {"+HH", "+19", 19 * 3600},
             {"+HH", "-19", -(19 * 3600)},
 
             {"+HHMM", "+1801", 18 * 3600 + 1 * 60},
diff --git a/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java b/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
index 619889b..03a2f2e 100644
--- a/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
+++ b/ojluni/src/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,14 +42,14 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.TimeZone;
-import jdk.testlibrary.RandomFactory;
+import jdk.test.lib.RandomFactory;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 /*
  * @test
- * @bug 8081022
+ * @bug 8081022 8151876 8166875 8189784 8206980
  * @key randomness
  */
 
@@ -79,6 +79,25 @@
                      .with(ChronoField.SECOND_OF_DAY, r.nextInt(86400));
             // Android-changed: loop over locales first to speed up test. TimeZoneNames are cached
             // per locale, but the cache only holds the most recently used locales.
+            /*
+            for (String zid : zids) {
+                if (zid.equals("ROC") || zid.startsWith("Etc/GMT")) {
+                    continue;      // TBD: match jdk behavior?
+                }
+                zdt = zdt.withZoneSameLocal(ZoneId.of(zid));
+                TimeZone tz = TimeZone.getTimeZone(zid);
+                boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli()));
+                for (Locale locale : locales) {
+                    boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli()));
+                    String longDisplayName = tz.getDisplayName(isDST, TimeZone.LONG, locale);
+                    String shortDisplayName = tz.getDisplayName(isDST, TimeZone.SHORT, locale);
+                    if ((longDisplayName.startsWith("GMT+") && shortDisplayName.startsWith("GMT+"))
+                            || (longDisplayName.startsWith("GMT-") && shortDisplayName.startsWith("GMT-"))) {
+                        printText(locale, zdt, TextStyle.FULL, tz, tz.getID());
+                        printText(locale, zdt, TextStyle.SHORT, tz, tz.getID());
+                        continue;
+                    }
+             */
             for (Locale locale : locales) {
                 // Android-changed: "ji" isn't correctly aliased to "yi", see http//b/8634320.
                 if (locale.getLanguage().equals("ji")) {
@@ -101,9 +120,9 @@
                     }
                     boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli()));
                     printText(locale, zdt, TextStyle.FULL, tz,
-                            tz.getDisplayName(isDST, TimeZone.LONG, locale));
+                        tz.getDisplayName(isDST, TimeZone.LONG, locale));
                     printText(locale, zdt, TextStyle.SHORT, tz,
-                            tz.getDisplayName(isDST, TimeZone.SHORT, locale));
+                        tz.getDisplayName(isDST, TimeZone.SHORT, locale));
                 }
             }
         }
@@ -157,6 +176,7 @@
     private static Set<ZoneId> preferred = new HashSet<>(Arrays.asList(new ZoneId[] {
         ZoneId.of("EST", ZoneId.SHORT_IDS),
         ZoneId.of("Asia/Taipei"),
+        ZoneId.of("Asia/Macau"),
         ZoneId.of("CET"),
     }));
 
@@ -188,8 +208,9 @@
             // {"America/New_York", "Eastern Standard Time", none,      Locale.ENGLISH, TextStyle.FULL},
 //          {"EST",              "Eastern Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL},
             // {"Europe/Paris",     "Central European Time", none,      Locale.ENGLISH, TextStyle.FULL},
-            // {"CET",              "Central European Time", preferred, Locale.UK, TextStyle.FULL},
+//          {"CET",              "Central European Time", preferred, Locale.ENGLISH, TextStyle.FULL}, no three-letter ID in CLDR
             // {"Asia/Shanghai",    "China Standard Time",   none,      Locale.ENGLISH, TextStyle.FULL},
+            {"Asia/Macau",       "China Standard Time",   preferred, Locale.ENGLISH, TextStyle.FULL},
             // {"Asia/Taipei",      "China Standard Time",   preferred, Locale.ENGLISH, TextStyle.FULL},
             // {"America/Chicago",  "CST",                   none,      Locale.ENGLISH, TextStyle.SHORT},
             // {"Asia/Taipei",      "CST",                   preferred, Locale.ENGLISH, TextStyle.SHORT},
@@ -197,6 +218,13 @@
             {"Australia/South",  "ACST",                  preferred_s, new Locale("en", "AU"), TextStyle.SHORT},
             // {"America/Chicago",  "CDT",                   none,        Locale.ENGLISH, TextStyle.SHORT},
             // {"Asia/Shanghai",    "CDT",                   preferred_s, Locale.ENGLISH, TextStyle.SHORT},
+            // {"America/Juneau",   "AKST",                  none,      Locale.ENGLISH, TextStyle.SHORT},
+            // {"America/Juneau",   "AKDT",                  none,      Locale.ENGLISH, TextStyle.SHORT},
+            {"Pacific/Honolulu", "HST",                   none,      Locale.ENGLISH, TextStyle.SHORT},
+            // {"America/Halifax",  "AST",                   none,      Locale.ENGLISH, TextStyle.SHORT},
+            {"Z",                "Z",                     none,      Locale.ENGLISH, TextStyle.SHORT},
+            {"Z",                "Z",                     none,      Locale.US,      TextStyle.SHORT},
+            {"Z",                "Z",                     none,      Locale.CANADA,  TextStyle.SHORT},
        };
     }
 
diff --git a/ojluni/src/test/java/time/test/java/time/format/ZoneName.java b/ojluni/src/test/java/time/test/java/time/format/ZoneName.java
index 2c49446..35a2a08 100644
--- a/ojluni/src/test/java/time/test/java/time/format/ZoneName.java
+++ b/ojluni/src/test/java/time/test/java/time/format/ZoneName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,13 +20,20 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package test.java.time.format;
 
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
+/**
+ * A helper class to map a zone name to metazone and back to the
+ * appropriate zone id for the particular locale.
+ * <p>
+ * The zid<->metazone mappings are based on CLDR metaZones.xml.
+ * The alias mappings are based on Link entries in tzdb data files and
+ * CLDR's supplementalMetadata.xml.
+ */
 class ZoneName {
 
     public static String toZid(String zid, Locale locale) {
@@ -54,699 +61,922 @@
     }
 
     private static final String[] zidMap = new String[] {
-        "Asia/Bangkok", "Indochina", "Asia/Saigon",
-        "Pacific/Pago_Pago", "Samoa", "Pacific/Apia",
-        "Africa/Blantyre", "Africa_Central", "Africa/Maputo",
-        "America/Argentina/San_Juan", "Argentina", "America/Buenos_Aires",
-        "America/Cancun", "America_Central", "America/Chicago",
-        "Pacific/Nauru", "Nauru", "Pacific/Nauru",
-        "America/Atikokan", "America_Eastern", "America/New_York",
-        "Africa/Asmara", "Africa_Eastern", "Africa/Nairobi",
-        "Europe/Berlin", "Europe_Central", "Europe/Paris",
-        "Asia/Kolkata", "India", "Asia/Calcutta",
-        "Australia/Darwin", "Australia_Central", "Australia/Adelaide",
-        "America/Guayaquil", "Ecuador", "America/Guayaquil",
-        "Europe/Vienna", "Europe_Central", "Europe/Paris",
-        "Atlantic/St_Helena", "GMT", "Atlantic/Reykjavik",
-        "Europe/London", "GMT", "Atlantic/Reykjavik",
-        "Europe/Moscow", "Moscow", "Europe/Moscow",
-        "America/St_Vincent", "Atlantic", "America/Halifax",
-        "America/Bogota", "Colombia", "America/Bogota",
-        "America/Marigot", "Atlantic", "America/Halifax",
-        "Europe/Sarajevo", "Europe_Central", "Europe/Paris",
-        "America/Hermosillo", "America_Mountain", "America/Denver",
-        "America/Winnipeg", "America_Central", "America/Chicago",
-        "America/Rainy_River", "America_Central", "America/Chicago",
-        "Indian/Mahe", "Seychelles", "Indian/Mahe",
-        "Africa/Freetown", "GMT", "Atlantic/Reykjavik",
-        "America/Grand_Turk", "America_Eastern", "America/New_York",
-        "America/Argentina/Ushuaia", "Argentina", "America/Buenos_Aires",
-        "Atlantic/Azores", "Azores", "Atlantic/Azores",
-        "Asia/Harbin", "China", "Asia/Shanghai",
-        "America/Cuiaba", "Amazon", "America/Manaus",
-        "Asia/Bahrain", "Arabian", "Asia/Riyadh",
-        "Asia/Katmandu", "Nepal", "Asia/Katmandu",
-        "Pacific/Galapagos", "Galapagos", "Pacific/Galapagos",
-        "Asia/Brunei", "Brunei", "Asia/Brunei",
-        "Africa/Kigali", "Africa_Central", "Africa/Maputo",
-        "Asia/Makassar", "Indonesia_Central", "Asia/Makassar",
-        "Africa/Maputo", "Africa_Central", "Africa/Maputo",
-        "Asia/Kamchatka", "Magadan", "Asia/Magadan",
-        "Atlantic/Faroe", "Europe_Western", "Atlantic/Canary",
-        "America/El_Salvador", "America_Central", "America/Chicago",
-        "Asia/Saigon", "Indochina", "Asia/Saigon",
-        "Africa/Kinshasa", "Africa_Western", "Africa/Lagos",
-        "Europe/Oslo", "Europe_Central", "Europe/Paris",
-        "Asia/Hong_Kong", "Hong_Kong", "Asia/Hong_Kong",
-        "Pacific/Midway", "Samoa", "Pacific/Apia",
-        "Africa/Douala", "Africa_Western", "Africa/Lagos",
-        "Europe/San_Marino", "Europe_Central", "Europe/Paris",
-        "Pacific/Chuuk", "Truk", "Pacific/Truk",
-        "Africa/Gaborone", "Africa_Central", "Africa/Maputo",
-        "Africa/Tunis", "Europe_Central", "Europe/Paris",
-        "Africa/Khartoum", "Africa_Eastern", "Africa/Nairobi",
-        "Europe/Isle_of_Man", "GMT", "Atlantic/Reykjavik",
-        "Europe/Skopje", "Europe_Central", "Europe/Paris",
-        "America/Merida", "America_Central", "America/Chicago",
-        "Antarctica/DumontDUrville", "DumontDUrville", "Antarctica/DumontDUrville",
-        "Atlantic/Reykjavik", "GMT", "Atlantic/Reykjavik",
-        "Indian/Mauritius", "Mauritius", "Indian/Mauritius",
-        "Africa/Malabo", "Africa_Western", "Africa/Lagos",
-        "Africa/Juba", "Africa_Eastern", "Africa/Nairobi",
-        "America/Resolute", "America_Central", "America/Chicago",
+        // From metaZones.xml
         "Africa/Abidjan", "GMT", "Atlantic/Reykjavik",
-        "Antarctica/McMurdo", "New_Zealand", "Pacific/Auckland",
-        "Asia/Thimphu", "Bhutan", "Asia/Thimphu",
-        "Europe/Zaporozhye", "Europe_Eastern", "Europe/Bucharest",
-        "Antarctica/Davis", "Davis", "Antarctica/Davis",
-        "Indian/Antananarivo", "Africa_Eastern", "Africa/Nairobi",
-        "Africa/Harare", "Africa_Central", "Africa/Maputo",
-        "Pacific/Marquesas", "Marquesas", "Pacific/Marquesas",
-        "Africa/Tripoli", "Europe_Eastern", "Europe/Bucharest",
-        "America/North_Dakota/Beulah", "America_Central", "America/Chicago",
-        "America/Buenos_Aires", "Argentina", "America/Buenos_Aires",
-        "America/Tortola", "Atlantic", "America/Halifax",
-        "Asia/Kuwait", "Arabian", "Asia/Riyadh",
-        "Europe/Rome", "Europe_Central", "Europe/Paris",
-        "America/Eirunepe", "Amazon", "America/Manaus",
-        "Australia/Hobart", "Australia_Eastern", "Australia/Sydney",
-        "America/Thule", "Atlantic", "America/Halifax",
-        "Asia/Beirut", "Europe_Eastern", "Europe/Bucharest",
-        "America/Bahia_Banderas", "America_Central", "America/Chicago",
-        "Africa/Dar_es_Salaam", "Africa_Eastern", "Africa/Nairobi",
-        "America/Argentina/Tucuman", "Argentina", "America/Buenos_Aires",
-        "America/Paramaribo", "Suriname", "America/Paramaribo",
-        "Africa/Kampala", "Africa_Eastern", "Africa/Nairobi",
-        "Pacific/Port_Moresby", "Papua_New_Guinea", "Pacific/Port_Moresby",
-        "America/Mendoza", "Argentina", "America/Buenos_Aires",
-        "Asia/Dushanbe", "Tajikistan", "Asia/Dushanbe",
-        "Asia/Qyzylorda", "Kazakhstan_Eastern", "Asia/Almaty",
-        "Antarctica/Vostok", "Vostok", "Antarctica/Vostok",
-        "Pacific/Majuro", "Marshall_Islands", "Pacific/Majuro",
-        "Asia/Tehran", "Iran", "Asia/Tehran",
-        "Asia/Hovd", "Hovd", "Asia/Hovd",
-        "Antarctica/Rothera", "Rothera", "Antarctica/Rothera",
-        "Africa/Brazzaville", "Africa_Western", "Africa/Lagos",
-        "Europe/Tirane", "Europe_Central", "Europe/Paris",
-        "Asia/Urumqi", "China", "Asia/Shanghai",
-        "Asia/Krasnoyarsk", "Krasnoyarsk", "Asia/Krasnoyarsk",
-        "America/Tegucigalpa", "America_Central", "America/Chicago",
-        "Asia/Vientiane", "Indochina", "Asia/Saigon",
-        "Asia/Pontianak", "Indonesia_Western", "Asia/Jakarta",
-        "America/Bahia", "Brasilia", "America/Sao_Paulo",
-        "Asia/Choibalsan", "Choibalsan", "Asia/Choibalsan",
-        "America/Regina", "America_Central", "America/Chicago",
-        "Africa/Cairo", "Europe_Eastern", "Europe/Bucharest",
-        "Asia/Irkutsk", "Irkutsk", "Asia/Irkutsk",
-        "Europe/Luxembourg", "Europe_Central", "Europe/Paris",
-        "America/St_Kitts", "Atlantic", "America/Halifax",
-        "America/Manaus", "Amazon", "America/Manaus",
-        "America/Noronha", "Noronha", "America/Noronha",
-        "Pacific/Gambier", "Gambier", "Pacific/Gambier",
-        "America/Edmonton", "America_Mountain", "America/Denver",
-        "Pacific/Palau", "Palau", "Pacific/Palau",
-        "America/Lower_Princes", "Atlantic", "America/Halifax",
-        "Africa/Ouagadougou", "GMT", "Atlantic/Reykjavik",
-        "Asia/Yerevan", "Armenia", "Asia/Yerevan",
-        "America/Montevideo", "Uruguay", "America/Montevideo",
-        "Europe/Minsk", "Europe_Eastern", "Europe/Bucharest",
-        "Europe/Amsterdam", "Europe_Central", "Europe/Paris",
-        "Pacific/Efate", "Vanuatu", "Pacific/Efate",
-        "Asia/Manila", "Philippines", "Asia/Manila",
-        "America/Dawson", "America_Pacific", "America/Los_Angeles",
-        "America/Argentina/Cordoba", "Argentina", "America/Buenos_Aires",
-        "Australia/Melbourne", "Australia_Eastern", "Australia/Sydney",
-        "Asia/Rangoon", "Myanmar", "Asia/Rangoon",
-        "America/Los_Angeles", "America_Pacific", "America/Los_Angeles",
-        "Africa/Casablanca", "Europe_Western", "Atlantic/Canary",
-        "Africa/Porto-Novo", "Africa_Western", "Africa/Lagos",
-        "Asia/Macau", "China", "Asia/Shanghai",
-        "America/Boa_Vista", "Amazon", "America/Manaus",
-        "Europe/Guernsey", "GMT", "Atlantic/Reykjavik",
-        "Africa/Monrovia", "GMT", "Atlantic/Reykjavik",
-        "America/Godthab", "Greenland_Western", "America/Godthab",
-        "Africa/Ceuta", "Europe_Central", "Europe/Paris",
-        "Asia/Oral", "Kazakhstan_Western", "Asia/Aqtobe",
-        "America/Yakutat", "Alaska", "America/Juneau",
-        "Indian/Mayotte", "Africa_Eastern", "Africa/Nairobi",
-        "America/Denver", "America_Mountain", "America/Denver",
-        "America/New_York", "America_Eastern", "America/New_York",
-        "Pacific/Rarotonga", "Cook", "Pacific/Rarotonga",
-        "America/Louisville", "America_Eastern", "America/New_York",
-        "Africa/El_Aaiun", "Europe_Western", "Atlantic/Canary",
-        "Africa/Sao_Tome", "GMT", "Atlantic/Reykjavik",
-        "Pacific/Fiji", "Fiji", "Pacific/Fiji",
-        "Asia/Damascus", "Europe_Eastern", "Europe/Bucharest",
-        "Asia/Ulaanbaatar", "Mongolia", "Asia/Ulaanbaatar",
-        "America/Cayman", "America_Eastern", "America/New_York",
-        "America/Tijuana", "America_Pacific", "America/Los_Angeles",
-        "Atlantic/Bermuda", "Atlantic", "America/Halifax",
-        "Australia/Sydney", "Australia_Eastern", "Australia/Sydney",
-        "Asia/Aden", "Arabian", "Asia/Riyadh",
-        "Australia/Eucla", "Australia_CentralWestern", "Australia/Eucla",
-        "America/Indiana/Petersburg", "America_Eastern", "America/New_York",
-        "America/Panama", "America_Eastern", "America/New_York",
-        "Europe/Istanbul", "Europe_Eastern", "Europe/Bucharest",
-        "America/Kralendijk", "Atlantic", "America/Halifax",
-        "America/Catamarca", "Argentina", "America/Buenos_Aires",
-        "America/Nassau", "America_Eastern", "America/New_York",
-        "Europe/Paris", "Europe_Central", "Europe/Paris",
-        "Asia/Jakarta", "Indonesia_Western", "Asia/Jakarta",
-        "Australia/Lindeman", "Australia_Eastern", "Australia/Sydney",
-        "America/Sao_Paulo", "Brasilia", "America/Sao_Paulo",
-        "America/Juneau", "Alaska", "America/Juneau",
-        "America/Grenada", "Atlantic", "America/Halifax",
-        "America/Cayenne", "French_Guiana", "America/Cayenne",
-        "Antarctica/Casey", "Australia_Western", "Australia/Perth",
-        "Africa/Algiers", "Europe_Central", "Europe/Paris",
-        "America/Miquelon", "Pierre_Miquelon", "America/Miquelon",
-        "Asia/Tokyo", "Japan", "Asia/Tokyo",
-        "Africa/Windhoek", "Africa_Western", "Africa/Lagos",
-        "Africa/Bujumbura", "Africa_Central", "Africa/Maputo",
-        "America/Guatemala", "America_Central", "America/Chicago",
-        "Africa/Dakar", "GMT", "Atlantic/Reykjavik",
-        "Asia/Bishkek", "Kyrgystan", "Asia/Bishkek",
-        "America/Guadeloupe", "Atlantic", "America/Halifax",
-        "Africa/Ndjamena", "Africa_Western", "Africa/Lagos",
-        "Europe/Simferopol", "Europe_Eastern", "Europe/Bucharest",
-        "America/Santa_Isabel", "America_Pacific", "America/Los_Angeles",
-        "Asia/Dubai", "Gulf", "Asia/Dubai",
-        "America/Maceio", "Brasilia", "America/Sao_Paulo",
-        "America/Anchorage", "Alaska", "America/Juneau",
-        "Australia/Currie", "Australia_Eastern", "Australia/Sydney",
-        "Africa/Djibouti", "Africa_Eastern", "Africa/Nairobi",
-        "Europe/Budapest", "Europe_Central", "Europe/Paris",
-        "America/Argentina/Salta", "Argentina", "America/Buenos_Aires",
-        "Asia/Calcutta", "India", "Asia/Calcutta",
-        "America/Indiana/Winamac", "America_Eastern", "America/New_York",
-        "Asia/Yekaterinburg", "Yekaterinburg", "Asia/Yekaterinburg",
-        "America/Santiago", "Chile", "America/Santiago",
-        "Asia/Aqtobe", "Kazakhstan_Western", "Asia/Aqtobe",
-        "Asia/Dili", "East_Timor", "Asia/Dili",
-        "America/Detroit", "America_Eastern", "America/New_York",
-        "Africa/Libreville", "Africa_Western", "Africa/Lagos",
-        "Pacific/Ponape", "Ponape", "Pacific/Ponape",
-        "Pacific/Wallis", "Wallis", "Pacific/Wallis",
-        "Asia/Vladivostok", "Vladivostok", "Asia/Vladivostok",
-        "Africa/Lubumbashi", "Africa_Central", "Africa/Maputo",
-        "Africa/Asmera", "Africa_Eastern", "Africa/Nairobi",
-        "Pacific/Guam", "Chamorro", "Pacific/Saipan",
-        "America/Chicago", "America_Central", "America/Chicago",
-        "America/Swift_Current", "America_Central", "America/Chicago",
-        "America/Coral_Harbour", "America_Eastern", "America/New_York",
-        "America/Cambridge_Bay", "America_Mountain", "America/Denver",
-        "America/Costa_Rica", "America_Central", "America/Chicago",
-        "America/Curacao", "Atlantic", "America/Halifax",
-        "America/Recife", "Brasilia", "America/Sao_Paulo",
-        "Africa/Bangui", "Africa_Western", "Africa/Lagos",
-        "America/Cordoba", "Argentina", "America/Buenos_Aires",
-        "Asia/Baghdad", "Arabian", "Asia/Riyadh",
-        "America/Shiprock", "America_Mountain", "America/Denver",
-        "America/Glace_Bay", "Atlantic", "America/Halifax",
-        "America/North_Dakota/Center", "America_Central", "America/Chicago",
-        "Europe/Stockholm", "Europe_Central", "Europe/Paris",
-        "America/Halifax", "Atlantic", "America/Halifax",
-        "Atlantic/Canary", "Europe_Western", "Atlantic/Canary",
-        "Europe/Volgograd", "Volgograd", "Europe/Volgograd",
-        "America/Moncton", "Atlantic", "America/Halifax",
-        "Pacific/Tongatapu", "Tonga", "Pacific/Tongatapu",
-        "America/Argentina/Buenos_Aires", "Argentina", "America/Buenos_Aires",
-        "Asia/Samarkand", "Uzbekistan", "Asia/Tashkent",
-        "Pacific/Apia", "Samoa", "Pacific/Apia",
-        "America/Sitka", "Alaska", "America/Juneau",
-        "Europe/Warsaw", "Europe_Central", "Europe/Paris",
         "Africa/Accra", "GMT", "Atlantic/Reykjavik",
-        "Europe/Bratislava", "Europe_Central", "Europe/Paris",
-        "Europe/Zurich", "Europe_Central", "Europe/Paris",
-        "Indian/Reunion", "Reunion", "Indian/Reunion",
-        "America/Mazatlan", "America_Mountain", "America/Denver",
-        "Pacific/Tarawa", "Gilbert_Islands", "Pacific/Tarawa",
-        "America/Indiana/Knox", "America_Central", "America/Chicago",
-        "Asia/Tbilisi", "Georgia", "Asia/Tbilisi",
-        "Asia/Novosibirsk", "Novosibirsk", "Asia/Novosibirsk",
-        "Atlantic/Faeroe", "Europe_Western", "Atlantic/Canary",
-        "Africa/Bissau", "GMT", "Atlantic/Reykjavik",
-        "Asia/Amman", "Europe_Eastern", "Europe/Bucharest",
-        "Africa/Lagos", "Africa_Western", "Africa/Lagos",
-        "Africa/Banjul", "GMT", "Atlantic/Reykjavik",
-        "America/Araguaina", "Brasilia", "America/Sao_Paulo",
-        "America/Nipigon", "America_Eastern", "America/New_York",
-        "Europe/Vilnius", "Europe_Eastern", "Europe/Bucharest",
-        "America/Montserrat", "Atlantic", "America/Halifax",
-        "Asia/Baku", "Azerbaijan", "Asia/Baku",
-        "Africa/Lusaka", "Africa_Central", "Africa/Maputo",
-        "Europe/Uzhgorod", "Europe_Eastern", "Europe/Bucharest",
-        "America/Argentina/Rio_Gallegos", "Argentina", "America/Buenos_Aires",
-        "America/Blanc-Sablon", "Atlantic", "America/Halifax",
-        "Asia/Kabul", "Afghanistan", "Asia/Kabul",
-        "America/Jamaica", "America_Eastern", "America/New_York",
-        "Europe/Vatican", "Europe_Central", "Europe/Paris",
-        "Africa/Nouakchott", "GMT", "Atlantic/Reykjavik",
         "Africa/Addis_Ababa", "Africa_Eastern", "Africa/Nairobi",
-        "Europe/Athens", "Europe_Eastern", "Europe/Bucharest",
-        "Atlantic/Madeira", "Europe_Western", "Atlantic/Canary",
-        "America/Thunder_Bay", "America_Eastern", "America/New_York",
-        "Europe/Brussels", "Europe_Central", "Europe/Paris",
-        "Africa/Luanda", "Africa_Western", "Africa/Lagos",
-        "Africa/Mogadishu", "Africa_Eastern", "Africa/Nairobi",
-        "America/Matamoros", "America_Central", "America/Chicago",
-        "Pacific/Norfolk", "Norfolk", "Pacific/Norfolk",
-        "America/Scoresbysund", "Greenland_Eastern", "America/Scoresbysund",
-        "America/Indianapolis", "America_Eastern", "America/New_York",
-        "Pacific/Pitcairn", "Pitcairn", "Pacific/Pitcairn",
-        "Asia/Singapore", "Singapore", "Asia/Singapore",
-        "America/Port-au-Prince", "America_Eastern", "America/New_York",
-        "Pacific/Honolulu", "Hawaii_Aleutian", "Pacific/Honolulu",
-        "Antarctica/Syowa", "Syowa", "Antarctica/Syowa",
-        "Atlantic/Cape_Verde", "Cape_Verde", "Atlantic/Cape_Verde",
-        "America/Asuncion", "Paraguay", "America/Asuncion",
-        "America/Martinique", "Atlantic", "America/Halifax",
-        "Europe/Gibraltar", "Europe_Central", "Europe/Paris",
-        "Africa/Lome", "GMT", "Atlantic/Reykjavik",
-        "Australia/Lord_Howe", "Lord_Howe", "Australia/Lord_Howe",
-        "America/Argentina/La_Rioja", "Argentina", "America/Buenos_Aires",
-        "Europe/Jersey", "GMT", "Atlantic/Reykjavik",
-        "America/Kentucky/Louisville", "America_Eastern", "America/New_York",
-        "America/Monterrey", "America_Central", "America/Chicago",
-        "Europe/Belgrade", "Europe_Central", "Europe/Paris",
-        "Asia/Gaza", "Europe_Eastern", "Europe/Bucharest",
-        "Asia/Ho_Chi_Minh", "Indochina", "Asia/Saigon",
-        "Europe/Prague", "Europe_Central", "Europe/Paris",
-        "Indian/Christmas", "Christmas", "Indian/Christmas",
-        "Pacific/Fakaofo", "Tokelau", "Pacific/Fakaofo",
-        "America/Dominica", "Atlantic", "America/Halifax",
-        "America/Ojinaga", "America_Mountain", "America/Denver",
-        "Asia/Colombo", "India", "Asia/Calcutta",
-        "Asia/Nicosia", "Europe_Eastern", "Europe/Bucharest",
-        "Europe/Copenhagen", "Europe_Central", "Europe/Paris",
-        "America/Creston", "America_Mountain", "America/Denver",
-        "Asia/Ashgabat", "Turkmenistan", "Asia/Ashgabat",
-        "Asia/Shanghai", "China", "Asia/Shanghai",
-        "Pacific/Easter", "Easter", "Pacific/Easter",
-        "Africa/Maseru", "Africa_Southern", "Africa/Johannesburg",
-        "America/La_Paz", "Bolivia", "America/La_Paz",
-        "Pacific/Truk", "Truk", "Pacific/Truk",
-        "America/Inuvik", "America_Mountain", "America/Denver",
-        "America/Belem", "Brasilia", "America/Sao_Paulo",
-        "Asia/Hebron", "Europe_Eastern", "Europe/Bucharest",
-        "Asia/Jerusalem", "Israel", "Asia/Jerusalem",
-        "America/Belize", "America_Central", "America/Chicago",
-        "America/Rio_Branco", "Amazon", "America/Manaus",
-        "America/Dawson_Creek", "America_Mountain", "America/Denver",
-        "America/Anguilla", "Atlantic", "America/Halifax",
-        "America/Port_of_Spain", "Atlantic", "America/Halifax",
-        "America/St_Barthelemy", "Atlantic", "America/Halifax",
-        "America/Indiana/Marengo", "America_Eastern", "America/New_York",
-        "America/St_Johns", "Newfoundland", "America/St_Johns",
-        "Asia/Jayapura", "Indonesia_Eastern", "Asia/Jayapura",
-        "Europe/Riga", "Europe_Eastern", "Europe/Bucharest",
-        "America/Phoenix", "America_Mountain", "America/Denver",
-        "America/Boise", "America_Mountain", "America/Denver",
-        "Pacific/Kiritimati", "Line_Islands", "Pacific/Kiritimati",
-        "Africa/Johannesburg", "Africa_Southern", "Africa/Johannesburg",
-        "America/Pangnirtung", "America_Eastern", "America/New_York",
-        "America/Toronto", "America_Eastern", "America/New_York",
-        "Australia/Brisbane", "Australia_Eastern", "Australia/Sydney",
-        "Asia/Aqtau", "Kazakhstan_Western", "Asia/Aqtobe",
-        "America/Vancouver", "America_Pacific", "America/Los_Angeles",
-        "Africa/Mbabane", "Africa_Southern", "Africa/Johannesburg",
-        "Europe/Vaduz", "Europe_Central", "Europe/Paris",
-        "Asia/Karachi", "Pakistan", "Asia/Karachi",
-        "Asia/Riyadh", "Arabian", "Asia/Riyadh",
-        "Indian/Maldives", "Maldives", "Indian/Maldives",
-        "Asia/Anadyr", "Magadan", "Asia/Magadan",
-        "Europe/Helsinki", "Europe_Eastern", "Europe/Bucharest",
-        "America/Nome", "Alaska", "America/Juneau",
-        "Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk",
-        "Africa/Conakry", "GMT", "Atlantic/Reykjavik",
-        "Asia/Seoul", "Korea", "Asia/Seoul",
-        "America/Antigua", "Atlantic", "America/Halifax",
-        "Asia/Almaty", "Kazakhstan_Eastern", "Asia/Almaty",
-        "America/Fortaleza", "Brasilia", "America/Sao_Paulo",
-        "Pacific/Tahiti", "Tahiti", "Pacific/Tahiti",
-        "Asia/Kashgar", "China", "Asia/Shanghai",
-        "America/Whitehorse", "America_Pacific", "America/Los_Angeles",
-        "Europe/Kaliningrad", "Europe_Eastern", "Europe/Bucharest",
-        "Pacific/Enderbury", "Phoenix_Islands", "Pacific/Enderbury",
-        "America/St_Lucia", "Atlantic", "America/Halifax",
-        "Atlantic/Stanley", "Falkland", "Atlantic/Stanley",
-        "Asia/Omsk", "Omsk", "Asia/Omsk",
-        "America/Menominee", "America_Central", "America/Chicago",
-        "Asia/Novokuznetsk", "Novosibirsk", "Asia/Novosibirsk",
-        "Asia/Sakhalin", "Sakhalin", "Asia/Sakhalin",
-        "Asia/Muscat", "Gulf", "Asia/Dubai",
-        "Pacific/Noumea", "New_Caledonia", "Pacific/Noumea",
-        "Asia/Phnom_Penh", "Indochina", "Asia/Saigon",
-        "Antarctica/Mawson", "Mawson", "Antarctica/Mawson",
-        "Indian/Cocos", "Cocos", "Indian/Cocos",
-        "Europe/Tallinn", "Europe_Eastern", "Europe/Bucharest",
-        "Africa/Nairobi", "Africa_Eastern", "Africa/Nairobi",
-        "Europe/Ljubljana", "Europe_Central", "Europe/Paris",
-        "America/Montreal", "America_Eastern", "America/New_York",
-        "Asia/Kuala_Lumpur", "Malaysia", "Asia/Kuching",
-        "Asia/Magadan", "Magadan", "Asia/Magadan",
+        "Africa/Algiers", "Europe_Central", "Europe/Paris",
+        "Africa/Asmara", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Asmera", "Africa_Eastern", "Africa/Nairobi",
         "Africa/Bamako", "GMT", "Atlantic/Reykjavik",
-        "Australia/Broken_Hill", "Australia_Central", "Australia/Adelaide",
-        "America/Indiana/Indianapolis", "America_Eastern", "America/New_York",
-        "Asia/Taipei", "Taipei", "Asia/Taipei",
-        "Europe/Samara", "Moscow", "Europe/Moscow",
-        "America/Indiana/Vevay", "America_Eastern", "America/New_York",
-        "Atlantic/South_Georgia", "South_Georgia", "Atlantic/South_Georgia",
-        "Pacific/Wake", "Wake", "Pacific/Wake",
-        "Asia/Tashkent", "Uzbekistan", "Asia/Tashkent",
-        "America/St_Thomas", "Atlantic", "America/Halifax",
-        "America/Argentina/San_Luis", "Argentina_Western", "America/Argentina/San_Luis",
-        "Arctic/Longyearbyen", "Europe_Central", "Europe/Paris",
-        "Asia/Chongqing", "China", "Asia/Shanghai",
-        "Europe/Monaco", "Europe_Central", "Europe/Paris",
-        "Asia/Qatar", "Arabian", "Asia/Riyadh",
-        "America/Chihuahua", "America_Mountain", "America/Denver",
-        "America/Havana", "Cuba", "America/Havana",
-        "Pacific/Auckland", "New_Zealand", "Pacific/Auckland",
-        "America/Jujuy", "Argentina", "America/Buenos_Aires",
-        "America/Goose_Bay", "Atlantic", "America/Halifax",
+        "Africa/Bangui", "Africa_Western", "Africa/Lagos",
+        "Africa/Banjul", "GMT", "Atlantic/Reykjavik",
+        "Africa/Bissau", "GMT", "Atlantic/Reykjavik",
+        "Africa/Blantyre", "Africa_Central", "Africa/Maputo",
+        "Africa/Brazzaville", "Africa_Western", "Africa/Lagos",
+        "Africa/Bujumbura", "Africa_Central", "Africa/Maputo",
+        "Africa/Cairo", "Europe_Eastern", "Europe/Bucharest",
+        "Africa/Casablanca", "Europe_Western", "Atlantic/Canary",
+        "Africa/Ceuta", "Europe_Central", "Europe/Paris",
+        "Africa/Conakry", "GMT", "Atlantic/Reykjavik",
+        "Africa/Dakar", "GMT", "Atlantic/Reykjavik",
+        "Africa/Dar_es_Salaam", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Djibouti", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Douala", "Africa_Western", "Africa/Lagos",
+        "Africa/El_Aaiun", "Europe_Western", "Atlantic/Canary",
+        "Africa/Freetown", "GMT", "Atlantic/Reykjavik",
+        "Africa/Gaborone", "Africa_Central", "Africa/Maputo",
+        "Africa/Harare", "Africa_Central", "Africa/Maputo",
+        "Africa/Johannesburg", "Africa_Southern", "Africa/Johannesburg",
+        "Africa/Juba", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Kampala", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Khartoum", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Kigali", "Africa_Central", "Africa/Maputo",
+        "Africa/Kinshasa", "Africa_Western", "Africa/Lagos",
+        "Africa/Lagos", "Africa_Western", "Africa/Lagos",
+        "Africa/Libreville", "Africa_Western", "Africa/Lagos",
+        "Africa/Lome", "GMT", "Atlantic/Reykjavik",
+        "Africa/Luanda", "Africa_Western", "Africa/Lagos",
+        "Africa/Lubumbashi", "Africa_Central", "Africa/Maputo",
+        "Africa/Lusaka", "Africa_Central", "Africa/Maputo",
+        "Africa/Malabo", "Africa_Western", "Africa/Lagos",
+        "Africa/Maputo", "Africa_Central", "Africa/Maputo",
+        "Africa/Maseru", "Africa_Southern", "Africa/Johannesburg",
+        "Africa/Mbabane", "Africa_Southern", "Africa/Johannesburg",
+        "Africa/Mogadishu", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Monrovia", "GMT", "Atlantic/Reykjavik",
+        "Africa/Nairobi", "Africa_Eastern", "Africa/Nairobi",
+        "Africa/Ndjamena", "Africa_Western", "Africa/Lagos",
         "Africa/Niamey", "Africa_Western", "Africa/Lagos",
-        "Asia/Kathmandu", "Nepal", "Asia/Katmandu",
-        "America/Caracas", "Venezuela", "America/Caracas",
-        "Indian/Comoro", "Africa_Eastern", "Africa/Nairobi",
-        "America/Argentina/Jujuy", "Argentina", "America/Buenos_Aires",
-        "America/Guyana", "Guyana", "America/Guyana",
-        "America/Indiana/Tell_City", "America_Central", "America/Chicago",
-        "America/Metlakatla", "America_Pacific", "America/Los_Angeles",
-        "Europe/Mariehamn", "Europe_Eastern", "Europe/Bucharest",
-        "Europe/Dublin", "GMT", "Atlantic/Reykjavik",
-        "Europe/Lisbon", "Europe_Western", "Atlantic/Canary",
-        "America/Puerto_Rico", "Atlantic", "America/Halifax",
-        "Asia/Pyongyang", "Korea", "Asia/Seoul",
-        "America/North_Dakota/New_Salem", "America_Central", "America/Chicago",
-        "Asia/Dhaka", "Bangladesh", "Asia/Dhaka",
-        "America/Rankin_Inlet", "America_Central", "America/Chicago",
+        "Africa/Nouakchott", "GMT", "Atlantic/Reykjavik",
+        "Africa/Ouagadougou", "GMT", "Atlantic/Reykjavik",
+        "Africa/Porto-Novo", "Africa_Western", "Africa/Lagos",
+        "Africa/Sao_Tome", "GMT", "Atlantic/Reykjavik",
+        "Africa/Timbuktu", "GMT", "Atlantic/Reykjavik",
+        "Africa/Tripoli", "Europe_Eastern", "Europe/Bucharest",
+        "Africa/Tunis", "Europe_Central", "Europe/Paris",
+        "Africa/Windhoek", "Africa_Western", "Africa/Lagos",
         "America/Adak", "Hawaii_Aleutian", "Pacific/Honolulu",
-        "America/Campo_Grande", "Amazon", "America/Manaus",
-        "Europe/Chisinau", "Europe_Eastern", "Europe/Bucharest",
-        "Pacific/Saipan", "Chamorro", "Pacific/Saipan",
-        "Pacific/Niue", "Niue", "Pacific/Niue",
-        "Europe/Madrid", "Europe_Central", "Europe/Paris",
-        "Pacific/Kwajalein", "Marshall_Islands", "Pacific/Majuro",
-        "America/Porto_Velho", "Amazon", "America/Manaus",
-        "Indian/Kerguelen", "French_Southern", "Indian/Kerguelen",
-        "America/Santarem", "Brasilia", "America/Sao_Paulo",
-        "Asia/Kuching", "Malaysia", "Asia/Kuching",
-        "Australia/Adelaide", "Australia_Central", "Australia/Adelaide",
-        "Europe/Bucharest", "Europe_Eastern", "Europe/Bucharest",
-        "Australia/Perth", "Australia_Western", "Australia/Perth",
-        "Europe/Sofia", "Europe_Eastern", "Europe/Bucharest",
-        "Indian/Chagos", "Indian_Ocean", "Indian/Chagos",
-        "America/Yellowknife", "America_Mountain", "America/Denver",
-        "America/Managua", "America_Central", "America/Chicago",
-        "America/Iqaluit", "America_Eastern", "America/New_York",
-        "Pacific/Kosrae", "Kosrae", "Pacific/Kosrae",
-        "Pacific/Guadalcanal", "Solomon", "Pacific/Guadalcanal",
-        "America/Barbados", "Atlantic", "America/Halifax",
-        "America/Aruba", "Atlantic", "America/Halifax",
-        "Europe/Andorra", "Europe_Central", "Europe/Paris",
-        "Pacific/Chatham", "Chatham", "Pacific/Chatham",
-        "America/Santo_Domingo", "Atlantic", "America/Halifax",
-        "America/Indiana/Vincennes", "America_Eastern", "America/New_York",
-        "Europe/Kiev", "Europe_Eastern", "Europe/Bucharest",
-        "Pacific/Funafuti", "Tuvalu", "Pacific/Funafuti",
-        "America/Mexico_City", "America_Central", "America/Chicago",
-        "America/Kentucky/Monticello", "America_Eastern", "America/New_York",
+        "America/Anchorage", "Alaska", "America/Juneau",
+        "America/Anguilla", "Atlantic", "America/Halifax",
+        "America/Antigua", "Atlantic", "America/Halifax",
+        "America/Araguaina", "Brasilia", "America/Sao_Paulo",
+        "America/Argentina/Buenos_Aires", "Argentina", "America/Buenos_Aires",
         "America/Argentina/Catamarca", "Argentina", "America/Buenos_Aires",
-        "Pacific/Johnston", "Hawaii_Aleutian", "Pacific/Honolulu",
-        "Europe/Podgorica", "Europe_Central", "Europe/Paris",
-        "Europe/Zagreb", "Europe_Central", "Europe/Paris",
-        "Pacific/Pohnpei", "Ponape", "Pacific/Ponape",
-        "Antarctica/Palmer", "Chile", "America/Santiago",
+        "America/Argentina/ComodRivadavia", "Argentina", "America/Buenos_Aires",
+        "America/Argentina/Cordoba", "Argentina", "America/Buenos_Aires",
+        "America/Argentina/Jujuy", "Argentina", "America/Buenos_Aires",
+        "America/Argentina/La_Rioja", "Argentina", "America/Buenos_Aires",
         "America/Argentina/Mendoza", "Argentina", "America/Buenos_Aires",
-        "America/Lima", "Peru", "America/Lima",
-        "Antarctica/Macquarie", "Macquarie", "Antarctica/Macquarie",
-        "Europe/Malta", "Europe_Central", "Europe/Paris",
+        "America/Argentina/Rio_Gallegos", "Argentina", "America/Buenos_Aires",
+        "America/Argentina/Salta", "Argentina", "America/Buenos_Aires",
+        "America/Argentina/San_Juan", "Argentina", "America/Buenos_Aires",
+        "America/Argentina/San_Luis", "Argentina_Western", "America/Argentina/San_Luis",
+        "America/Argentina/Tucuman", "Argentina", "America/Buenos_Aires",
+        "America/Argentina/Ushuaia", "Argentina", "America/Buenos_Aires",
+        "America/Aruba", "Atlantic", "America/Halifax",
+        "America/Asuncion", "Paraguay", "America/Asuncion",
+        "America/Atikokan", "America_Eastern", "America/New_York",
+        "America/Atka", "Hawaii_Aleutian", "Pacific/Honolulu",
+        "America/Bahia", "Brasilia", "America/Sao_Paulo",
+        "America/Bahia_Banderas", "America_Central", "America/Chicago",
+        "America/Barbados", "Atlantic", "America/Halifax",
+        "America/Belem", "Brasilia", "America/Sao_Paulo",
+        "America/Belize", "America_Central", "America/Chicago",
+        "America/Blanc-Sablon", "Atlantic", "America/Halifax",
+        "America/Boa_Vista", "Amazon", "America/Manaus",
+        "America/Bogota", "Colombia", "America/Bogota",
+        "America/Boise", "America_Mountain", "America/Denver",
+        "America/Buenos_Aires", "Argentina", "America/Buenos_Aires",
+        "America/Cambridge_Bay", "America_Mountain", "America/Denver",
+        "America/Campo_Grande", "Amazon", "America/Manaus",
+        "America/Cancun", "America_Eastern", "America/New_York",
+        "America/Caracas", "Venezuela", "America/Caracas",
+        "America/Catamarca", "Argentina", "America/Buenos_Aires",
+        "America/Cayenne", "French_Guiana", "America/Cayenne",
+        "America/Cayman", "America_Eastern", "America/New_York",
+        "America/Chicago", "America_Central", "America/Chicago",
+        "America/Chihuahua", "Mexico_Pacific", "America/Mazatlan",
+        "America/Coral_Harbour", "America_Eastern", "America/New_York",
+        "America/Cordoba", "Argentina", "America/Buenos_Aires",
+        "America/Costa_Rica", "America_Central", "America/Chicago",
+        "America/Creston", "America_Mountain", "America/Denver",
+        "America/Cuiaba", "Amazon", "America/Manaus",
+        "America/Curacao", "Atlantic", "America/Halifax",
         "America/Danmarkshavn", "GMT", "Atlantic/Reykjavik",
+        "America/Dawson", "America_Pacific", "America/Los_Angeles",
+        "America/Dawson_Creek", "America_Mountain", "America/Denver",
+        "America/Denver", "America_Mountain", "America/Denver",
+        "America/Detroit", "America_Eastern", "America/New_York",
+        "America/Dominica", "Atlantic", "America/Halifax",
+        "America/Edmonton", "America_Mountain", "America/Denver",
+        "America/Eirunepe", "Acre", "America/Rio_Branco",
+        "America/El_Salvador", "America_Central", "America/Chicago",
+        "America/Ensenada", "America_Pacific", "America/Los_Angeles",
+        "America/Fort_Nelson", "America_Mountain", "America/Denver",
+        "America/Fort_Wayne", "America_Eastern", "America/New_York",
+        "America/Fortaleza", "Brasilia", "America/Sao_Paulo",
+        "America/Glace_Bay", "Atlantic", "America/Halifax",
+        "America/Godthab", "Greenland_Western", "America/Godthab",
+        "America/Goose_Bay", "Atlantic", "America/Halifax",
+        "America/Grand_Turk", "Atlantic", "America/Halifax",
+        "America/Grenada", "Atlantic", "America/Halifax",
+        "America/Guadeloupe", "Atlantic", "America/Halifax",
+        "America/Guatemala", "America_Central", "America/Chicago",
+        "America/Guayaquil", "Ecuador", "America/Guayaquil",
+        "America/Guyana", "Guyana", "America/Guyana",
+        "America/Halifax", "Atlantic", "America/Halifax",
+        "America/Havana", "Cuba", "America/Havana",
+        "America/Hermosillo", "Mexico_Pacific", "America/Mazatlan",
+        "America/Indiana/Indianapolis", "America_Eastern", "America/New_York",
+        "America/Indiana/Knox", "America_Central", "America/Chicago",
+        "America/Indiana/Marengo", "America_Eastern", "America/New_York",
+        "America/Indiana/Petersburg", "America_Eastern", "America/New_York",
+        "America/Indiana/Tell_City", "America_Central", "America/Chicago",
+        "America/Indiana/Vevay", "America_Eastern", "America/New_York",
+        "America/Indiana/Vincennes", "America_Eastern", "America/New_York",
+        "America/Indiana/Winamac", "America_Eastern", "America/New_York",
+        "America/Indianapolis", "America_Eastern", "America/New_York",
+        "America/Inuvik", "America_Mountain", "America/Denver",
+        "America/Iqaluit", "America_Eastern", "America/New_York",
+        "America/Jamaica", "America_Eastern", "America/New_York",
+        "America/Jujuy", "Argentina", "America/Buenos_Aires",
+        "America/Juneau", "Alaska", "America/Juneau",
+        "America/Kentucky/Louisville", "America_Eastern", "America/New_York",
+        "America/Kentucky/Monticello", "America_Eastern", "America/New_York",
+        "America/Knox_IN", "America_Central", "America/Chicago",
+        "America/Kralendijk", "Atlantic", "America/Halifax",
+        "America/La_Paz", "Bolivia", "America/La_Paz",
+        "America/Lima", "Peru", "America/Lima",
+        "America/Los_Angeles", "America_Pacific", "America/Los_Angeles",
+        "America/Louisville", "America_Eastern", "America/New_York",
+        "America/Lower_Princes", "Atlantic", "America/Halifax",
+        "America/Maceio", "Brasilia", "America/Sao_Paulo",
+        "America/Managua", "America_Central", "America/Chicago",
+        "America/Manaus", "Amazon", "America/Manaus",
+        "America/Marigot", "Atlantic", "America/Halifax",
+        "America/Martinique", "Atlantic", "America/Halifax",
+        "America/Matamoros", "America_Central", "America/Chicago",
+        "America/Mazatlan", "Mexico_Pacific", "America/Mazatlan",
+        "America/Mendoza", "Argentina", "America/Buenos_Aires",
+        "America/Menominee", "America_Central", "America/Chicago",
+        "America/Merida", "America_Central", "America/Chicago",
+        "America/Metlakatla", "Alaska", "America/Juneau",
+        "America/Mexico_City", "America_Central", "America/Chicago",
+        "America/Miquelon", "Pierre_Miquelon", "America/Miquelon",
+        "America/Moncton", "Atlantic", "America/Halifax",
+        "America/Monterrey", "America_Central", "America/Chicago",
+        "America/Montevideo", "Uruguay", "America/Montevideo",
+        "America/Montserrat", "Atlantic", "America/Halifax",
+        "America/Nassau", "America_Eastern", "America/New_York",
+        "America/New_York", "America_Eastern", "America/New_York",
+        "America/Nipigon", "America_Eastern", "America/New_York",
+        "America/Nome", "Alaska", "America/Juneau",
+        "America/Noronha", "Noronha", "America/Noronha",
+        "America/North_Dakota/Beulah", "America_Central", "America/Chicago",
+        "America/North_Dakota/Center", "America_Central", "America/Chicago",
+        "America/North_Dakota/New_Salem", "America_Central", "America/Chicago",
+        "America/Ojinaga", "America_Mountain", "America/Denver",
+        "America/Panama", "America_Eastern", "America/New_York",
+        "America/Pangnirtung", "America_Eastern", "America/New_York",
+        "America/Paramaribo", "Suriname", "America/Paramaribo",
+        "America/Phoenix", "America_Mountain", "America/Denver",
+        "America/Port-au-Prince", "America_Eastern", "America/New_York",
+        "America/Port_of_Spain", "Atlantic", "America/Halifax",
+        "America/Porto_Acre", "Acre", "America/Rio_Branco",
+        "America/Porto_Velho", "Amazon", "America/Manaus",
+        "America/Puerto_Rico", "Atlantic", "America/Halifax",
+        "America/Rainy_River", "America_Central", "America/Chicago",
+        "America/Rankin_Inlet", "America_Central", "America/Chicago",
+        "America/Recife", "Brasilia", "America/Sao_Paulo",
+        "America/Regina", "America_Central", "America/Chicago",
+        "America/Resolute", "America_Central", "America/Chicago",
+        "America/Rio_Branco", "Acre", "America/Rio_Branco",
+        "America/Rosario", "Argentina", "America/Buenos_Aires",
+        "America/Santa_Isabel", "Mexico_Northwest", "America/Santa_Isabel",
+        "America/Santarem", "Brasilia", "America/Sao_Paulo",
+        "America/Santiago", "Chile", "America/Santiago",
+        "America/Santo_Domingo", "Atlantic", "America/Halifax",
+        "America/Sao_Paulo", "Brasilia", "America/Sao_Paulo",
+        "America/Scoresbysund", "Greenland_Eastern", "America/Scoresbysund",
+        "America/Shiprock", "America_Mountain", "America/Denver",
+        "America/Sitka", "Alaska", "America/Juneau",
+        "America/St_Barthelemy", "Atlantic", "America/Halifax",
+        "America/St_Johns", "Newfoundland", "America/St_Johns",
+        "America/St_Kitts", "Atlantic", "America/Halifax",
+        "America/St_Lucia", "Atlantic", "America/Halifax",
+        "America/St_Thomas", "Atlantic", "America/Halifax",
+        "America/St_Vincent", "Atlantic", "America/Halifax",
+        "America/Swift_Current", "America_Central", "America/Chicago",
+        "America/Tegucigalpa", "America_Central", "America/Chicago",
+        "America/Thule", "Atlantic", "America/Halifax",
+        "America/Thunder_Bay", "America_Eastern", "America/New_York",
+        "America/Tijuana", "America_Pacific", "America/Los_Angeles",
+        "America/Toronto", "America_Eastern", "America/New_York",
+        "America/Tortola", "Atlantic", "America/Halifax",
+        "America/Vancouver", "America_Pacific", "America/Los_Angeles",
+        "America/Virgin", "Atlantic", "America/Halifax",
+        "America/Whitehorse", "America_Pacific", "America/Los_Angeles",
+        "America/Winnipeg", "America_Central", "America/Chicago",
+        "America/Yakutat", "Alaska", "America/Juneau",
+        "America/Yellowknife", "America_Mountain", "America/Denver",
+        "Antarctica/Casey", "Australia_Western", "Australia/Perth",
+        "Antarctica/Davis", "Davis", "Antarctica/Davis",
+        "Antarctica/DumontDUrville", "DumontDUrville", "Antarctica/DumontDUrville",
+        "Antarctica/Macquarie", "Macquarie", "Antarctica/Macquarie",
+        "Antarctica/Mawson", "Mawson", "Antarctica/Mawson",
+        "Antarctica/McMurdo", "New_Zealand", "Pacific/Auckland",
+        "Antarctica/Palmer", "Chile", "America/Santiago",
+        "Antarctica/Rothera", "Rothera", "Antarctica/Rothera",
+        "Antarctica/South_Pole", "New_Zealand", "Pacific/Auckland",
+        "Antarctica/Syowa", "Syowa", "Antarctica/Syowa",
+        "Antarctica/Troll", "GMT", "Atlantic/Reykjavik",
+        "Antarctica/Vostok", "Vostok", "Antarctica/Vostok",
+        "Arctic/Longyearbyen", "Europe_Central", "Europe/Paris",
+        "Asia/Aden", "Arabian", "Asia/Riyadh",
+        "Asia/Almaty", "Kazakhstan_Eastern", "Asia/Almaty",
+        "Asia/Amman", "Europe_Eastern", "Europe/Bucharest",
+        "Asia/Anadyr", "Magadan", "Asia/Magadan",
+        "Asia/Aqtau", "Kazakhstan_Western", "Asia/Aqtobe",
+        "Asia/Aqtobe", "Kazakhstan_Western", "Asia/Aqtobe",
+        "Asia/Ashgabat", "Turkmenistan", "Asia/Ashgabat",
+        "Asia/Ashkhabad", "Turkmenistan", "Asia/Ashgabat",
+        "Asia/Baghdad", "Arabian", "Asia/Riyadh",
+        "Asia/Bahrain", "Arabian", "Asia/Riyadh",
+        "Asia/Baku", "Azerbaijan", "Asia/Baku",
+        "Asia/Bangkok", "Indochina", "Asia/Bangkok",
+        "Asia/Beirut", "Europe_Eastern", "Europe/Bucharest",
+        "Asia/Bishkek", "Kyrgystan", "Asia/Bishkek",
+        "Asia/Brunei", "Brunei", "Asia/Brunei",
+        "Asia/Calcutta", "India", "Asia/Calcutta",
+        "Asia/Chita", "Yakutsk", "Asia/Yakutsk",
+        "Asia/Choibalsan", "Choibalsan", "Asia/Choibalsan",
+        "Asia/Chongqing", "China", "Asia/Shanghai",
+        "Asia/Chungking", "China", "Asia/Shanghai",
+        "Asia/Colombo", "India", "Asia/Calcutta",
+        "Asia/Dacca", "Bangladesh", "Asia/Dhaka",
+        "Asia/Damascus", "Europe_Eastern", "Europe/Bucharest",
+        "Asia/Dhaka", "Bangladesh", "Asia/Dhaka",
+        "Asia/Dili", "East_Timor", "Asia/Dili",
+        "Asia/Dubai", "Gulf", "Asia/Dubai",
+        "Asia/Dushanbe", "Tajikistan", "Asia/Dushanbe",
+        "Asia/Gaza", "Europe_Eastern", "Europe/Bucharest",
+        "Asia/Harbin", "China", "Asia/Shanghai",
+        "Asia/Hebron", "Europe_Eastern", "Europe/Bucharest",
+        "Asia/Ho_Chi_Minh", "Indochina", "Asia/Bangkok",
+        "Asia/Hong_Kong", "Hong_Kong", "Asia/Hong_Kong",
+        "Asia/Hovd", "Hovd", "Asia/Hovd",
+        "Asia/Irkutsk", "Irkutsk", "Asia/Irkutsk",
+        "Asia/Istanbul", "Europe_Eastern", "Europe/Bucharest",
+        "Asia/Jakarta", "Indonesia_Western", "Asia/Jakarta",
+        "Asia/Jayapura", "Indonesia_Eastern", "Asia/Jayapura",
+        "Asia/Jerusalem", "Israel", "Asia/Jerusalem",
+        "Asia/Kabul", "Afghanistan", "Asia/Kabul",
+        "Asia/Kamchatka", "Kamchatka", "Asia/Kamchatka",
+        "Asia/Karachi", "Pakistan", "Asia/Karachi",
+        "Asia/Kashgar", "Urumqi", "Asia/Urumqi",
+        "Asia/Kathmandu", "Nepal", "Asia/Katmandu",
+        "Asia/Katmandu", "Nepal", "Asia/Katmandu",
+        "Asia/Khandyga", "Yakutsk", "Asia/Yakutsk",
+        "Asia/Kolkata", "India", "Asia/Calcutta",
+        "Asia/Krasnoyarsk", "Krasnoyarsk", "Asia/Krasnoyarsk",
+        "Asia/Kuala_Lumpur", "Malaysia", "Asia/Kuching",
+        "Asia/Kuching", "Malaysia", "Asia/Kuching",
+        "Asia/Kuwait", "Arabian", "Asia/Riyadh",
+        "Asia/Macao", "China", "Asia/Shanghai",
+        "Asia/Macau", "China", "Asia/Shanghai",
+        "Asia/Magadan", "Magadan", "Asia/Magadan",
+        "Asia/Makassar", "Indonesia_Central", "Asia/Makassar",
+        "Asia/Manila", "Philippines", "Asia/Manila",
+        "Asia/Muscat", "Gulf", "Asia/Dubai",
+        "Asia/Nicosia", "Europe_Eastern", "Europe/Bucharest",
+        "Asia/Novokuznetsk", "Krasnoyarsk", "Asia/Krasnoyarsk",
+        "Asia/Novosibirsk", "Novosibirsk", "Asia/Novosibirsk",
+        "Asia/Omsk", "Omsk", "Asia/Omsk",
+        "Asia/Oral", "Kazakhstan_Western", "Asia/Aqtobe",
+        "Asia/Phnom_Penh", "Indochina", "Asia/Bangkok",
+        "Asia/Pontianak", "Indonesia_Western", "Asia/Jakarta",
+        "Asia/Pyongyang", "Pyongyang", "Asia/Pyongyang",
+        "Asia/Qatar", "Arabian", "Asia/Riyadh",
+        "Asia/Qyzylorda", "Kazakhstan_Eastern", "Asia/Almaty",
+        "Asia/Rangoon", "Myanmar", "Asia/Rangoon",
+        "Asia/Riyadh", "Arabian", "Asia/Riyadh",
+        "Asia/Saigon", "Indochina", "Asia/Bangkok",
+        "Asia/Sakhalin", "Sakhalin", "Asia/Sakhalin",
+        "Asia/Samarkand", "Uzbekistan", "Asia/Tashkent",
+        "Asia/Seoul", "Korea", "Asia/Seoul",
+        "Asia/Shanghai", "China", "Asia/Shanghai",
+        "Asia/Singapore", "Singapore", "Asia/Singapore",
+        "Asia/Srednekolymsk", "Singapore", "Asia/Singapore",
+        "Asia/Taipei", "Taipei", "Asia/Taipei",
+        "Asia/Tashkent", "Uzbekistan", "Asia/Tashkent",
+        "Asia/Tbilisi", "Georgia", "Asia/Tbilisi",
+        "Asia/Tehran", "Iran", "Asia/Tehran",
+        "Asia/Tel_Aviv", "Israel", "Asia/Jerusalem",
+        "Asia/Thimbu", "Bhutan", "Asia/Thimphu",
+        "Asia/Thimphu", "Bhutan", "Asia/Thimphu",
+        "Asia/Tokyo", "Japan", "Asia/Tokyo",
+        "Asia/Ujung_Pandang", "Indonesia_Central", "Asia/Makassar",
+        "Asia/Ulaanbaatar", "Mongolia", "Asia/Ulaanbaatar",
+        "Asia/Ulan_Bator", "Mongolia", "Asia/Ulaanbaatar",
+        "Asia/Urumqi", "Urumqi", "Asia/Urumqi",
+        "Asia/Ust-Nera", "Vladivostok", "Asia/Vladivostok",
+        "Asia/Vientiane", "Indochina", "Asia/Bangkok",
+        "Asia/Vladivostok", "Vladivostok", "Asia/Vladivostok",
+        "Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk",
+        "Asia/Yekaterinburg", "Yekaterinburg", "Asia/Yekaterinburg",
+        "Asia/Yerevan", "Armenia", "Asia/Yerevan",
+        "Atlantic/Azores", "Azores", "Atlantic/Azores",
+        "Atlantic/Bermuda", "Atlantic", "America/Halifax",
+        "Atlantic/Canary", "Europe_Western", "Atlantic/Canary",
+        "Atlantic/Cape_Verde", "Cape_Verde", "Atlantic/Cape_Verde",
+        "Atlantic/Faeroe", "Europe_Western", "Atlantic/Canary",
+        "Atlantic/Faroe", "Europe_Western", "Atlantic/Canary",
+        "Atlantic/Jan_Mayen", "Europe_Central", "Europe/Paris",
+        "Atlantic/Madeira", "Europe_Western", "Atlantic/Canary",
+        "Atlantic/Reykjavik", "GMT", "Atlantic/Reykjavik",
+        "Atlantic/South_Georgia", "South_Georgia", "Atlantic/South_Georgia",
+        "Atlantic/St_Helena", "GMT", "Atlantic/Reykjavik",
+        "Atlantic/Stanley", "Falkland", "Atlantic/Stanley",
+        "Australia/ACT", "Australia_Eastern", "Australia/Sydney",
+        "Australia/Adelaide", "Australia_Central", "Australia/Adelaide",
+        "Australia/Brisbane", "Australia_Eastern", "Australia/Sydney",
+        "Australia/Broken_Hill", "Australia_Central", "Australia/Adelaide",
+        "Australia/Canberra", "Australia_Eastern", "Australia/Sydney",
+        "Australia/Currie", "Australia_Eastern", "Australia/Sydney",
+        "Australia/Darwin", "Australia_Central", "Australia/Adelaide",
+        "Australia/Eucla", "Australia_CentralWestern", "Australia/Eucla",
+        "Australia/Hobart", "Australia_Eastern", "Australia/Sydney",
+        "Australia/LHI", "Lord_Howe", "Australia/Lord_Howe",
+        "Australia/Lindeman", "Australia_Eastern", "Australia/Sydney",
+        "Australia/Lord_Howe", "Lord_Howe", "Australia/Lord_Howe",
+        "Australia/Melbourne", "Australia_Eastern", "Australia/Sydney",
+        "Australia/NSW", "Australia_Eastern", "Australia/Sydney",
+        "Australia/North", "Australia_Central", "Australia/Adelaide",
+        "Australia/Perth", "Australia_Western", "Australia/Perth",
+        "Australia/Queensland", "Australia_Eastern", "Australia/Sydney",
+        "Australia/South", "Australia_Central", "Australia/Adelaide",
+        "Australia/Sydney", "Australia_Eastern", "Australia/Sydney",
+        "Australia/Tasmania", "Australia_Eastern", "Australia/Sydney",
+        "Australia/Victoria", "Australia_Eastern", "Australia/Sydney",
+        "Australia/West", "Australia_Western", "Australia/Perth",
+        "Australia/Yancowinna", "Australia_Central", "Australia/Adelaide",
+        "Brazil/Acre", "Acre", "America/Rio_Branco",
+        "Brazil/DeNoronha", "Noronha", "America/Noronha",
+        "Brazil/East", "Brasilia", "America/Sao_Paulo",
+        "Brazil/West", "Amazon", "America/Manaus",
+        "CST6CDT", "America_Central", "America/Chicago",
+        "Canada/Atlantic", "Atlantic", "America/Halifax",
+        "Canada/Central", "America_Central", "America/Chicago",
+        "Canada/East-Saskatchewan", "America_Central", "America/Chicago",
+        "Canada/Eastern", "America_Eastern", "America/New_York",
+        "Canada/Mountain", "America_Mountain", "America/Denver",
+        "Canada/Newfoundland", "Newfoundland", "America/St_Johns",
+        "Canada/Pacific", "America_Pacific", "America/Los_Angeles",
+        "Canada/Saskatchewan", "America_Central", "America/Chicago",
+        "Canada/Yukon", "America_Pacific", "America/Los_Angeles",
+        "Chile/Continental", "Chile", "America/Santiago",
+        "Chile/EasterIsland", "Easter", "Pacific/Easter",
+        "Cuba", "Cuba", "America/Havana",
+        "EST5EDT", "America_Eastern", "America/New_York",
+        "Egypt", "Europe_Eastern", "Europe/Bucharest",
+        "Eire", "GMT", "Atlantic/Reykjavik",
+        "Europe/Amsterdam", "Europe_Central", "Europe/Paris",
+        "Europe/Andorra", "Europe_Central", "Europe/Paris",
+        "Europe/Athens", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Belfast", "GMT", "Atlantic/Reykjavik",
+        "Europe/Belgrade", "Europe_Central", "Europe/Paris",
+        "Europe/Berlin", "Europe_Central", "Europe/Paris",
+        "Europe/Bratislava", "Europe_Central", "Europe/Paris",
+        "Europe/Brussels", "Europe_Central", "Europe/Paris",
+        "Europe/Bucharest", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Budapest", "Europe_Central", "Europe/Paris",
+        "Europe/Busingen", "Europe_Central", "Europe/Paris",
+        "Europe/Chisinau", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Copenhagen", "Europe_Central", "Europe/Paris",
+        "Europe/Dublin", "GMT", "Atlantic/Reykjavik",
+        "Europe/Gibraltar", "Europe_Central", "Europe/Paris",
+        "Europe/Guernsey", "GMT", "Atlantic/Reykjavik",
+        "Europe/Helsinki", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Isle_of_Man", "GMT", "Atlantic/Reykjavik",
+        "Europe/Istanbul", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Jersey", "GMT", "Atlantic/Reykjavik",
+        "Europe/Kaliningrad", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Kiev", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Lisbon", "Europe_Western", "Atlantic/Canary",
+        "Europe/Ljubljana", "Europe_Central", "Europe/Paris",
+        "Europe/London", "GMT", "Atlantic/Reykjavik",
+        "Europe/Luxembourg", "Europe_Central", "Europe/Paris",
+        "Europe/Madrid", "Europe_Central", "Europe/Paris",
+        "Europe/Malta", "Europe_Central", "Europe/Paris",
+        "Europe/Mariehamn", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Minsk", "Europe_Further_Eastern", "Europe/Minsk",
+        "Europe/Monaco", "Europe_Central", "Europe/Paris",
+        "Europe/Moscow", "Moscow", "Europe/Moscow",
+        "Europe/Nicosia", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Oslo", "Europe_Central", "Europe/Paris",
+        "Europe/Paris", "Europe_Central", "Europe/Paris",
+        "Europe/Podgorica", "Europe_Central", "Europe/Paris",
+        "Europe/Prague", "Europe_Central", "Europe/Paris",
+        "Europe/Riga", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Rome", "Europe_Central", "Europe/Paris",
+        "Europe/Samara", "Samara", "Europe/Samara",
+        "Europe/San_Marino", "Europe_Central", "Europe/Paris",
+        "Europe/Sarajevo", "Europe_Central", "Europe/Paris",
+        "Europe/Simferopol", "Moscow", "Europe/Moscow",
+        "Europe/Skopje", "Europe_Central", "Europe/Paris",
+        "Europe/Sofia", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Stockholm", "Europe_Central", "Europe/Paris",
+        "Europe/Tallinn", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Tirane", "Europe_Central", "Europe/Paris",
+        "Europe/Tiraspol", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Uzhgorod", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Vaduz", "Europe_Central", "Europe/Paris",
+        "Europe/Vatican", "Europe_Central", "Europe/Paris",
+        "Europe/Vienna", "Europe_Central", "Europe/Paris",
+        "Europe/Vilnius", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Volgograd", "Moscow", "Europe/Moscow",
+        "Europe/Warsaw", "Europe_Central", "Europe/Paris",
+        "Europe/Zagreb", "Europe_Central", "Europe/Paris",
+        "Europe/Zaporozhye", "Europe_Eastern", "Europe/Bucharest",
+        "Europe/Zurich", "Europe_Central", "Europe/Paris",
+        "GB", "GMT", "Atlantic/Reykjavik",
+        "GB-Eire", "GMT", "Atlantic/Reykjavik",
+        "Hongkong", "Hong_Kong", "Asia/Hong_Kong",
+        "Iceland", "GMT", "Atlantic/Reykjavik",
+        "Indian/Antananarivo", "Africa_Eastern", "Africa/Nairobi",
+        "Indian/Chagos", "Indian_Ocean", "Indian/Chagos",
+        "Indian/Christmas", "Christmas", "Indian/Christmas",
+        "Indian/Cocos", "Cocos", "Indian/Cocos",
+        "Indian/Comoro", "Africa_Eastern", "Africa/Nairobi",
+        "Indian/Kerguelen", "French_Southern", "Indian/Kerguelen",
+        "Indian/Mahe", "Seychelles", "Indian/Mahe",
+        "Indian/Maldives", "Maldives", "Indian/Maldives",
+        "Indian/Mauritius", "Mauritius", "Indian/Mauritius",
+        "Indian/Mayotte", "Africa_Eastern", "Africa/Nairobi",
+        "Indian/Reunion", "Reunion", "Indian/Reunion",
+        "Iran", "Iran", "Asia/Tehran",
+        "Israel", "Israel", "Asia/Jerusalem",
+        "Jamaica", "America_Eastern", "America/New_York",
+        "Japan", "Japan", "Asia/Tokyo",
+        "Kwajalein", "Marshall_Islands", "Pacific/Majuro",
+        "Libya", "Europe_Eastern", "Europe/Bucharest",
+        "MST7MDT", "America_Mountain", "America/Denver",
+        "Mexico/BajaNorte", "America_Pacific", "America/Los_Angeles",
+        "Mexico/BajaSur", "Mexico_Pacific", "America/Mazatlan",
+        "Mexico/General", "America_Central", "America/Chicago",
+        "NZ", "New_Zealand", "Pacific/Auckland",
+        "NZ-CHAT", "Chatham", "Pacific/Chatham",
+        "Navajo", "America_Mountain", "America/Denver",
+        "PRC", "China", "Asia/Shanghai",
+        "PST8PDT", "America_Pacific", "America/Los_Angeles",
+        "Pacific/Apia", "Apia", "Pacific/Apia",
+        "Pacific/Auckland", "New_Zealand", "Pacific/Auckland",
+        "Pacific/Bougainville", "New_Zealand", "Pacific/Auckland",
+        "Pacific/Chatham", "Chatham", "Pacific/Chatham",
+        "Pacific/Chuuk", "Truk", "Pacific/Truk",
+        "Pacific/Easter", "Easter", "Pacific/Easter",
+        "Pacific/Efate", "Vanuatu", "Pacific/Efate",
+        "Pacific/Enderbury", "Phoenix_Islands", "Pacific/Enderbury",
+        "Pacific/Fakaofo", "Tokelau", "Pacific/Fakaofo",
+        "Pacific/Fiji", "Fiji", "Pacific/Fiji",
+        "Pacific/Funafuti", "Tuvalu", "Pacific/Funafuti",
+        "Pacific/Galapagos", "Galapagos", "Pacific/Galapagos",
+        "Pacific/Gambier", "Gambier", "Pacific/Gambier",
+        "Pacific/Guadalcanal", "Solomon", "Pacific/Guadalcanal",
+        "Pacific/Guam", "Chamorro", "Pacific/Saipan",
+        "Pacific/Honolulu", "Hawaii_Aleutian", "Pacific/Honolulu",
+        "Pacific/Johnston", "Hawaii_Aleutian", "Pacific/Honolulu",
+        "Pacific/Kiritimati", "Line_Islands", "Pacific/Kiritimati",
+        "Pacific/Kosrae", "Kosrae", "Pacific/Kosrae",
+        "Pacific/Kwajalein", "Marshall_Islands", "Pacific/Majuro",
+        "Pacific/Majuro", "Marshall_Islands", "Pacific/Majuro",
+        "Pacific/Marquesas", "Marquesas", "Pacific/Marquesas",
+        "Pacific/Midway", "Samoa", "Pacific/Pago_Pago",
+        "Pacific/Nauru", "Nauru", "Pacific/Nauru",
+        "Pacific/Niue", "Niue", "Pacific/Niue",
+        "Pacific/Norfolk", "Norfolk", "Pacific/Norfolk",
+        "Pacific/Noumea", "New_Caledonia", "Pacific/Noumea",
+        "Pacific/Pago_Pago", "Samoa", "Pacific/Pago_Pago",
+        "Pacific/Palau", "Palau", "Pacific/Palau",
+        "Pacific/Pitcairn", "Pitcairn", "Pacific/Pitcairn",
+        "Pacific/Pohnpei", "Ponape", "Pacific/Ponape",
+        "Pacific/Ponape", "Ponape", "Pacific/Ponape",
+        "Pacific/Port_Moresby", "Papua_New_Guinea", "Pacific/Port_Moresby",
+        "Pacific/Rarotonga", "Cook", "Pacific/Rarotonga",
+        "Pacific/Saipan", "Chamorro", "Pacific/Saipan",
+        "Pacific/Samoa", "Samoa", "Pacific/Pago_Pago",
+        "Pacific/Tahiti", "Tahiti", "Pacific/Tahiti",
+        "Pacific/Tarawa", "Gilbert_Islands", "Pacific/Tarawa",
+        "Pacific/Tongatapu", "Tonga", "Pacific/Tongatapu",
+        "Pacific/Truk", "Truk", "Pacific/Truk",
+        "Pacific/Wake", "Wake", "Pacific/Wake",
+        "Pacific/Wallis", "Wallis", "Pacific/Wallis",
+        "Pacific/Yap", "Truk", "Pacific/Truk",
+        "Poland", "Europe_Central", "Europe/Paris",
+        "Portugal", "Europe_Western", "Atlantic/Canary",
+        "ROK", "Korea", "Asia/Seoul",
+        "Singapore", "Singapore", "Asia/Singapore",
+        "Turkey", "Europe_Eastern", "Europe/Bucharest",
+        "US/Alaska", "Alaska", "America/Juneau",
+        "US/Aleutian", "Hawaii_Aleutian", "Pacific/Honolulu",
+        "US/Arizona", "America_Mountain", "America/Denver",
+        "US/Central", "America_Central", "America/Chicago",
+        "US/East-Indiana", "America_Eastern", "America/New_York",
+        "US/Eastern", "America_Eastern", "America/New_York",
+        "US/Hawaii", "Hawaii_Aleutian", "Pacific/Honolulu",
+        "US/Indiana-Starke", "America_Central", "America/Chicago",
+        "US/Michigan", "America_Eastern", "America/New_York",
+        "US/Mountain", "America_Mountain", "America/Denver",
+        "US/Pacific", "America_Pacific", "America/Los_Angeles",
+        "US/Samoa", "Samoa", "Pacific/Pago_Pago",
+        "W-SU", "Moscow", "Europe/Moscow",
+
+        // From tzdb
+        "Africa/Khartoum", "Africa_Central", "Africa/Maputo", // tzdata2017c
+        "Africa/Windhoek", "Africa_Central", "Africa/Maputo", // tzdata2017c
+        "Africa/Sao_Tome", "Africa_Western", "Africa/Lagos",  // tzdata2018c
     };
     private static final String[] mzoneMap = new String[] {
-        "America_Eastern", "TC", "America/Grand_Turk",
-        "America_Eastern", "BS", "America/Nassau",
-        "America_Eastern", "CA", "America/Toronto",
-        "America_Eastern", "KY", "America/Cayman",
-        "America_Eastern", "PA", "America/Panama",
-        "America_Eastern", "JM", "America/Jamaica",
-        "America_Pacific", "CA", "America/Vancouver",
-        "America_Pacific", "MX", "America/Tijuana",
-        "Europe_Western", "FO", "Atlantic/Faeroe",
-        "Arabian", "YE", "Asia/Aden",
-        "Arabian", "BH", "Asia/Bahrain",
-        "Arabian", "KW", "Asia/Kuwait",
-        "Arabian", "QA", "Asia/Qatar",
-        "Arabian", "IQ", "Asia/Baghdad",
-        "Korea", "KP", "Asia/Pyongyang",
-        "Africa_Central", "ZW", "Africa/Harare",
-        "Africa_Central", "ZM", "Africa/Lusaka",
-        "Africa_Central", "MW", "Africa/Blantyre",
+        // From metaZones.xml
+        "Africa_Central", "BI", "Africa/Bujumbura",
         "Africa_Central", "BW", "Africa/Gaborone",
         "Africa_Central", "CD", "Africa/Lubumbashi",
-        "Africa_Central", "BI", "Africa/Bujumbura",
+        "Africa_Central", "MW", "Africa/Blantyre",
         "Africa_Central", "RW", "Africa/Kigali",
-        "Africa_Western", "CF", "Africa/Bangui",
+        "Africa_Central", "ZM", "Africa/Lusaka",
+        "Africa_Central", "ZW", "Africa/Harare",
+        "Africa_Eastern", "DJ", "Africa/Djibouti",
+        "Africa_Eastern", "ER", "Africa/Asmera",
+        "Africa_Eastern", "ET", "Africa/Addis_Ababa",
+        "Africa_Eastern", "KM", "Indian/Comoro",
+        "Africa_Eastern", "MG", "Indian/Antananarivo",
+        "Africa_Eastern", "SO", "Africa/Mogadishu",
+        "Africa_Eastern", "TZ", "Africa/Dar_es_Salaam",
+        "Africa_Eastern", "UG", "Africa/Kampala",
+        "Africa_Eastern", "YT", "Indian/Mayotte",
+        "Africa_Southern", "LS", "Africa/Maseru",
+        "Africa_Southern", "SZ", "Africa/Mbabane",
         "Africa_Western", "AO", "Africa/Luanda",
-        "Africa_Western", "NE", "Africa/Niamey",
+        "Africa_Western", "BJ", "Africa/Porto-Novo",
         "Africa_Western", "CD", "Africa/Kinshasa",
-        "Africa_Western", "CM", "Africa/Douala",
+        "Africa_Western", "CF", "Africa/Bangui",
         "Africa_Western", "CG", "Africa/Brazzaville",
-        "Africa_Western", "GQ", "Africa/Malabo",
-        "Africa_Western", "TD", "Africa/Ndjamena",
+        "Africa_Western", "CM", "Africa/Douala",
         "Africa_Western", "GA", "Africa/Libreville",
-        "Atlantic", "PR", "America/Puerto_Rico",
-        "Atlantic", "AN", "America/Curacao",
-        "Atlantic", "VI", "America/St_Thomas",
-        "Atlantic", "GP", "America/Guadeloupe",
-        "Atlantic", "TT", "America/Port_of_Spain",
+        "Africa_Western", "GQ", "Africa/Malabo",
+        "Africa_Western", "NE", "Africa/Niamey",
+        "Africa_Western", "TD", "Africa/Ndjamena",
+        "America_Central", "BZ", "America/Belize",
+        "America_Central", "CA", "America/Winnipeg",
+        "America_Central", "CR", "America/Costa_Rica",
+        "America_Central", "GT", "America/Guatemala",
+        "America_Central", "HN", "America/Tegucigalpa",
+        "America_Central", "MX", "America/Mexico_City",
+        "America_Central", "SV", "America/El_Salvador",
+        "America_Eastern", "BS", "America/Nassau",
+        "America_Eastern", "CA", "America/Toronto",
+        "America_Eastern", "HT", "America/Port-au-Prince",
+        "America_Eastern", "JM", "America/Jamaica",
+        "America_Eastern", "KY", "America/Cayman",
+        "America_Eastern", "PA", "America/Panama",
+        "America_Mountain", "CA", "America/Edmonton",
+        "America_Mountain", "MX", "America/Hermosillo",
+        "America_Pacific", "CA", "America/Vancouver",
+        "America_Pacific", "MX", "America/Tijuana",
+        "Arabian", "BH", "Asia/Bahrain",
+        "Arabian", "IQ", "Asia/Baghdad",
+        "Arabian", "KW", "Asia/Kuwait",
+        "Arabian", "QA", "Asia/Qatar",
+        "Arabian", "YE", "Asia/Aden",
         "Atlantic", "AG", "America/Antigua",
-        "Atlantic", "MF", "America/Marigot",
-        "Atlantic", "DM", "America/Dominica",
-        "Atlantic", "VG", "America/Tortola",
-        "Atlantic", "MQ", "America/Martinique",
-        "Atlantic", "GL", "America/Thule",
         "Atlantic", "AI", "America/Anguilla",
+        "Atlantic", "AN", "America/Curacao",
+        "Atlantic", "AW", "America/Aruba",
         "Atlantic", "BB", "America/Barbados",
         "Atlantic", "BM", "Atlantic/Bermuda",
         "Atlantic", "BQ", "America/Kralendijk",
-        "Atlantic", "LC", "America/St_Lucia",
-        "Atlantic", "MS", "America/Montserrat",
-        "Atlantic", "SX", "America/Lower_Princes",
+        "Atlantic", "DM", "America/Dominica",
         "Atlantic", "GD", "America/Grenada",
-        "Atlantic", "VC", "America/St_Vincent",
+        "Atlantic", "GL", "America/Thule",
+        "Atlantic", "GP", "America/Guadeloupe",
         "Atlantic", "KN", "America/St_Kitts",
-        "Atlantic", "AW", "America/Aruba",
-        "GMT", "GM", "Africa/Banjul",
-        "GMT", "LR", "Africa/Monrovia",
-        "GMT", "ML", "Africa/Bamako",
-        "GMT", "SH", "Atlantic/St_Helena",
-        "GMT", "TG", "Africa/Lome",
-        "GMT", "GB", "Europe/London",
-        "GMT", "MR", "Africa/Nouakchott",
-        "GMT", "GN", "Africa/Conakry",
-        "GMT", "SL", "Africa/Freetown",
-        "GMT", "BF", "Africa/Ouagadougou",
-        "GMT", "ST", "Africa/Sao_Tome",
-        "GMT", "SN", "Africa/Dakar",
-        "GMT", "CI", "Africa/Abidjan",
-        "GMT", "IE", "Europe/Dublin",
-        "GMT", "GH", "Africa/Accra",
-        "Chile", "AQ", "Antarctica/Palmer",
-        "America_Central", "CR", "America/Costa_Rica",
-        "America_Central", "HN", "America/Tegucigalpa",
-        "America_Central", "CA", "America/Winnipeg",
-        "America_Central", "SV", "America/El_Salvador",
-        "America_Central", "MX", "America/Mexico_City",
-        "America_Central", "BZ", "America/Belize",
-        "America_Central", "GT", "America/Guatemala",
-        "America_Mountain", "CA", "America/Edmonton",
-        "America_Mountain", "MX", "America/Hermosillo",
-        "New_Zealand", "AQ", "Antarctica/McMurdo",
-        "India", "LK", "Asia/Colombo",
-        "Gulf", "OM", "Asia/Muscat",
-        "China", "MO", "Asia/Macau",
-        "Africa_Eastern", "ER", "Africa/Asmera",
-        "Africa_Eastern", "TZ", "Africa/Dar_es_Salaam",
-        "Africa_Eastern", "SO", "Africa/Mogadishu",
-        "Africa_Eastern", "DJ", "Africa/Djibouti",
-        "Africa_Eastern", "MG", "Indian/Antananarivo",
-        "Africa_Eastern", "KM", "Indian/Comoro",
-        "Africa_Eastern", "UG", "Africa/Kampala",
-        "Africa_Eastern", "YT", "Indian/Mayotte",
-        "Africa_Eastern", "ET", "Africa/Addis_Ababa",
+        "Atlantic", "LC", "America/St_Lucia",
+        "Atlantic", "MF", "America/Marigot",
+        "Atlantic", "MQ", "America/Martinique",
+        "Atlantic", "MS", "America/Montserrat",
+        "Atlantic", "PR", "America/Puerto_Rico",
+        "Atlantic", "SX", "America/Lower_Princes",
+        "Atlantic", "TT", "America/Port_of_Spain",
+        "Atlantic", "VC", "America/St_Vincent",
+        "Atlantic", "VG", "America/Tortola",
+        "Atlantic", "VI", "America/St_Thomas",
         "Chamorro", "GU", "Pacific/Guam",
-        "Africa_Southern", "LS", "Africa/Maseru",
-        "Africa_Southern", "SZ", "Africa/Mbabane",
-        "Indochina", "KH", "Asia/Phnom_Penh",
-        "Indochina", "TH", "Asia/Bangkok",
-        "Indochina", "LA", "Asia/Vientiane",
+        "Chile", "AQ", "Antarctica/Palmer",
+        "Europe_Central", "AD", "Europe/Andorra",
+        "Europe_Central", "AL", "Europe/Tirane",
         "Europe_Central", "AT", "Europe/Vienna",
-        "Europe_Central", "SK", "Europe/Bratislava",
         "Europe_Central", "BA", "Europe/Sarajevo",
-        "Europe_Central", "CZ", "Europe/Prague",
         "Europe_Central", "BE", "Europe/Brussels",
-        "Europe_Central", "RS", "Europe/Belgrade",
-        "Europe_Central", "SE", "Europe/Stockholm",
-        "Europe_Central", "MT", "Europe/Malta",
-        "Europe_Central", "IT", "Europe/Rome",
-        "Europe_Central", "LU", "Europe/Luxembourg",
+        "Europe_Central", "CH", "Europe/Zurich",
+        "Europe_Central", "CZ", "Europe/Prague",
+        "Europe_Central", "DE", "Europe/Berlin",
+        "Europe_Central", "DK", "Europe/Copenhagen",
+        "Europe_Central", "ES", "Europe/Madrid",
+        "Europe_Central", "GI", "Europe/Gibraltar",
+        "Europe_Central", "HR", "Europe/Zagreb",
         "Europe_Central", "HU", "Europe/Budapest",
-        "Europe_Central", "NO", "Europe/Oslo",
+        "Europe_Central", "IT", "Europe/Rome",
+        "Europe_Central", "LI", "Europe/Vaduz",
+        "Europe_Central", "LU", "Europe/Luxembourg",
+        "Europe_Central", "MC", "Europe/Monaco",
         "Europe_Central", "ME", "Europe/Podgorica",
         "Europe_Central", "MK", "Europe/Skopje",
+        "Europe_Central", "MT", "Europe/Malta",
         "Europe_Central", "NL", "Europe/Amsterdam",
-        "Europe_Central", "LI", "Europe/Vaduz",
+        "Europe_Central", "NO", "Europe/Oslo",
         "Europe_Central", "PL", "Europe/Warsaw",
-        "Europe_Central", "ES", "Europe/Madrid",
-        "Europe_Central", "TN", "Africa/Tunis",
+        "Europe_Central", "RS", "Europe/Belgrade",
+        "Europe_Central", "SE", "Europe/Stockholm",
         "Europe_Central", "SI", "Europe/Ljubljana",
-        "Europe_Central", "DE", "Europe/Berlin",
-        "Europe_Central", "GI", "Europe/Gibraltar",
-        "Europe_Central", "CH", "Europe/Zurich",
-        "Europe_Central", "MC", "Europe/Monaco",
-        "Europe_Central", "VA", "Europe/Vatican",
-        "Europe_Central", "HR", "Europe/Zagreb",
-        "Europe_Central", "AL", "Europe/Tirane",
-        "Europe_Central", "AD", "Europe/Andorra",
-        "Europe_Central", "DK", "Europe/Copenhagen",
+        "Europe_Central", "SK", "Europe/Bratislava",
         "Europe_Central", "SM", "Europe/San_Marino",
-        "Europe_Eastern", "SY", "Asia/Damascus",
-        "Europe_Eastern", "FI", "Europe/Helsinki",
+        "Europe_Central", "TN", "Africa/Tunis",
+        "Europe_Central", "VA", "Europe/Vatican",
+        "Europe_Central", "XK", "Europe/Belgrade",
         "Europe_Eastern", "AX", "Europe/Mariehamn",
         "Europe_Eastern", "BG", "Europe/Sofia",
+        "Europe_Eastern", "CY", "Asia/Nicosia",
         "Europe_Eastern", "EG", "Africa/Cairo",
-        "Europe_Eastern", "LB", "Asia/Beirut",
+        "Europe_Eastern", "FI", "Europe/Helsinki",
         "Europe_Eastern", "GR", "Europe/Athens",
         "Europe_Eastern", "JO", "Asia/Amman",
-        "Europe_Eastern", "CY", "Asia/Nicosia",
+        "Europe_Eastern", "LB", "Asia/Beirut",
+        "Europe_Eastern", "SY", "Asia/Damascus",
+        "Europe_Further_Eastern", "RU", "Europe/Kaliningrad",
+        "Europe_Western", "FO", "Atlantic/Faeroe",
+        "GMT", "BF", "Africa/Ouagadougou",
+        "GMT", "CI", "Africa/Abidjan",
+        "GMT", "GB", "Europe/London",
+        "GMT", "GH", "Africa/Accra",
+        "GMT", "GM", "Africa/Banjul",
+        "GMT", "GN", "Africa/Conakry",
+        "GMT", "IE", "Europe/Dublin",
+        "GMT", "ML", "Africa/Bamako",
+        "GMT", "MR", "Africa/Nouakchott",
+        "GMT", "SH", "Atlantic/St_Helena",
+        "GMT", "SL", "Africa/Freetown",
+        "GMT", "SN", "Africa/Dakar",
+        "GMT", "ST", "Africa/Sao_Tome",
+        "GMT", "TG", "Africa/Lome",
+        "Gulf", "OM", "Asia/Muscat",
+        "India", "LK", "Asia/Colombo",
+        "Indochina", "KH", "Asia/Phnom_Penh",
+        "Indochina", "LA", "Asia/Vientiane",
+        "Korea", "KP", "Asia/Pyongyang",
+        "New_Zealand", "AQ", "Antarctica/McMurdo",
+
+        // From tzdb
+        "Africa_Western", "ST", "Africa/Sao_Tome", // tzdata2018c
     };
     private static final String[] aliasMap = new String[] {
-        "Mexico/BajaNorte", "America/Tijuana",
-        "Antarctica/South_Pole", "Antarctica/McMurdo",
-        "US/Michigan", "America/Detroit",
-        "America/Porto_Acre", "America/Rio_Branco",
-        "US/Alaska", "America/Anchorage",
-        "Asia/Ujung_Pandang", "Asia/Makassar",
-        "Canada/Atlantic", "America/Halifax",
-        "W-SU", "Europe/Moscow",
-        "Kwajalein", "Pacific/Kwajalein",
-        "Europe/Bratislava", "Europe/Prague",
-        "Canada/Central", "America/Winnipeg",
-        "Canada/Mountain", "America/Edmonton",
-        "Iceland", "Atlantic/Reykjavik",
-        "Asia/Ulan_Bator", "Asia/Ulaanbaatar",
-        "UTC", "Etc/UTC",
-        "Europe/Guernsey", "Europe/London",
-        "Singapore", "Asia/Singapore",
-        "Atlantic/Faeroe", "Atlantic/Faroe",
-        "Greenwich", "Etc/GMT",
-        "America/Fort_Wayne", "America/Indiana/Indianapolis",
-        "Etc/Universal", "Etc/UTC",
-        "Chile/EasterIsland", "Pacific/Easter",
-        "Pacific/Samoa", "Pacific/Pago_Pago",
-        "Europe/Nicosia", "Asia/Nicosia",
-        "Etc/Zulu", "Etc/UTC",
-        "Asia/Ashkhabad", "Asia/Ashgabat",
-        "America/Louisville", "America/Kentucky/Louisville",
-        "Australia/North", "Australia/Darwin",
-        "America/Atka", "America/Adak",
-        "America/Marigot", "America/Guadeloupe",
-        "Brazil/DeNoronha", "America/Noronha",
-        "Turkey", "Europe/Istanbul",
-        "Zulu", "Etc/UTC",
-        "Europe/Vatican", "Europe/Rome",
-        "Israel", "Asia/Jerusalem",
-        "America/Rosario", "America/Argentina/Cordoba",
-        "Jamaica", "America/Jamaica",
-        "Asia/Katmandu", "Asia/Kathmandu",
-        "Canada/East-Saskatchewan", "America/Regina",
-        "ROK", "Asia/Seoul",
-        "Asia/Macao", "Asia/Macau",
-        "Australia/South", "Australia/Adelaide",
-        "US/Arizona", "America/Phoenix",
-        "Australia/Yancowinna", "Australia/Broken_Hill",
-        "Canada/Pacific", "America/Vancouver",
-        "Libya", "Africa/Tripoli",
-        "Japan", "Asia/Tokyo",
-        "Arctic/Longyearbyen", "Europe/Oslo",
+        // From supplementalMetadata.xml
         "Africa/Timbuktu", "Africa/Bamako",
-        "America/Indianapolis", "America/Indiana/Indianapolis",
-        "Etc/Greenwich", "Etc/GMT",
-        "Australia/ACT", "Australia/Sydney",
-        "GMT", "Etc/GMT",
-        "Mexico/BajaSur", "America/Mazatlan",
-        "Cuba", "America/Havana",
-        "Brazil/West", "America/Manaus",
-        "Asia/Saigon", "Asia/Ho_Chi_Minh",
-        "America/Jujuy", "America/Argentina/Jujuy",
-        "Australia/Victoria", "Australia/Melbourne",
-        "America/Catamarca", "America/Argentina/Catamarca",
-        "America/Ensenada", "America/Tijuana",
-        "Europe/San_Marino", "Europe/Rome",
-        "Europe/Isle_of_Man", "Europe/London",
-        "Mexico/General", "America/Mexico_City",
-        "US/Hawaii", "Pacific/Honolulu",
-        "Europe/Mariehamn", "Europe/Helsinki",
-        "US/Indiana-Starke", "America/Indiana/Knox",
-        "Australia/NSW", "Australia/Sydney",
-        "Australia/West", "Australia/Perth",
-        "Brazil/Acre", "America/Rio_Branco",
-        "Australia/Tasmania", "Australia/Hobart",
-        "Atlantic/Jan_Mayen", "Europe/Oslo",
-        "America/Buenos_Aires", "America/Argentina/Buenos_Aires",
-        "Europe/Jersey", "Europe/London",
-        "Brazil/East", "America/Sao_Paulo",
-        "America/Virgin", "America/St_Thomas",
-        "Navajo", "America/Denver",
-        "GB", "Europe/London",
-        "Poland", "Europe/Warsaw",
-        "Pacific/Yap", "Pacific/Chuuk",
-        "America/Argentina/ComodRivadavia", "America/Argentina/Catamarca",
-        "Asia/Calcutta", "Asia/Kolkata",
-        "America/Mendoza", "America/Argentina/Mendoza",
-        "Universal", "Etc/UTC",
-        "Australia/Queensland", "Australia/Brisbane",
-        "Asia/Dacca", "Asia/Dhaka",
-        "US/Pacific", "America/Los_Angeles",
-        "Asia/Chungking", "Asia/Chongqing",
-        "Pacific/Truk", "Pacific/Chuuk",
-        "ROC", "Asia/Taipei",
-        "US/Aleutian", "America/Adak",
-        "Pacific/Ponape", "Pacific/Pohnpei",
-        "Canada/Yukon", "America/Whitehorse",
-        "PRC", "Asia/Shanghai",
-        "Africa/Asmera", "Africa/Asmara",
-        "GB-Eire", "Europe/London",
-        "America/St_Barthelemy", "America/Guadeloupe",
-        "US/Central", "America/Chicago",
-        "Egypt", "Africa/Cairo",
-        "Chile/Continental", "America/Santiago",
-        "Portugal", "Europe/Lisbon",
-        "Europe/Tiraspol", "Europe/Chisinau",
-        "America/Coral_Harbour", "America/Atikokan",
-        "Europe/Belfast", "Europe/London",
-        "America/Cordoba", "America/Argentina/Cordoba",
+        "America/Montreal", "America/Toronto",
         "America/Shiprock", "America/Denver",
-        "NZ-CHAT", "Pacific/Chatham",
-        "Eire", "Europe/Dublin",
-        "US/East-Indiana", "America/Indiana/Indianapolis",
-        "Australia/Canberra", "Australia/Sydney",
-        "Canada/Newfoundland", "America/St_Johns",
-        "UCT", "Etc/UCT",
-        "Australia/LHI", "Australia/Lord_Howe",
-        "Iran", "Asia/Tehran",
-        "US/Eastern", "America/New_York",
-        "Canada/Eastern", "America/Toronto",
-        "US/Samoa", "Pacific/Pago_Pago",
+        "Antarctica/South_Pole", "Pacific/Auckland",
+        "Asia/Chongqing", "Asia/Shanghai",
+        "Asia/Harbin", "Asia/Shanghai",
+        "Asia/Kashgar", "Asia/Urumqi",
+        "Atlantic/Jan_Mayen", "Europe/Oslo",
+        "EST", "America/Indianapolis",
+        "Europe/Belfast", "Europe/London",
+        "HST", "Pacific/Honolulu",
+        "MST", "America/Phoenix",
+        "Pacific/Yap", "Pacific/Truk",
+        "SystemV/AST4", "America/Puerto_Rico",
+        "SystemV/AST4ADT", "America/Halifax",
+        "SystemV/CST6", "America/Regina",
+        "SystemV/CST6CDT", "America/Chicago",
+        "SystemV/EST5", "America/Indianapolis",
+        "SystemV/EST5EDT", "America/New_York",
+        "SystemV/HST10", "Pacific/Honolulu",
+        "SystemV/MST7", "America/Phoenix",
+        "SystemV/MST7MDT", "America/Denver",
+        "SystemV/PST8", "Pacific/Pitcairn",
+        "SystemV/PST8PDT", "America/Los_Angeles",
+        "SystemV/YST9", "Pacific/Gambier",
+        "SystemV/YST9YDT", "America/Anchorage",
+
+        // From tzdb
+        "Africa/Addis_Ababa", "Africa/Nairobi",
+        "Africa/Asmara", "Africa/Nairobi",
+        "Africa/Asmera", "Africa/Nairobi",
+        "Africa/Bamako", "Africa/Abidjan",
+        "Africa/Bangui", "Africa/Lagos",
+        "Africa/Banjul", "Africa/Abidjan",
+        "Africa/Blantyre", "Africa/Maputo",
+        "Africa/Brazzaville", "Africa/Lagos",
+        "Africa/Bujumbura", "Africa/Maputo",
+        "Africa/Conakry", "Africa/Abidjan",
+        "Africa/Dakar", "Africa/Abidjan",
+        "Africa/Dar_es_Salaam", "Africa/Nairobi",
+        "Africa/Djibouti", "Africa/Nairobi",
+        "Africa/Douala", "Africa/Lagos",
+        "Africa/Freetown", "Africa/Abidjan",
+        "Africa/Gaborone", "Africa/Maputo",
+        "Africa/Harare", "Africa/Maputo",
+        "Africa/Kampala", "Africa/Nairobi",
+        "Africa/Kigali", "Africa/Maputo",
+        "Africa/Kinshasa", "Africa/Lagos",
+        "Africa/Libreville", "Africa/Lagos",
+        "Africa/Lome", "Africa/Abidjan",
+        "Africa/Luanda", "Africa/Lagos",
+        "Africa/Lubumbashi", "Africa/Maputo",
+        "Africa/Lusaka", "Africa/Maputo",
+        "Africa/Malabo", "Africa/Lagos",
+        "Africa/Maseru", "Africa/Johannesburg",
+        "Africa/Mbabane", "Africa/Johannesburg",
+        "Africa/Mogadishu", "Africa/Nairobi",
+        "Africa/Niamey", "Africa/Lagos",
+        "Africa/Nouakchott", "Africa/Abidjan",
+        "Africa/Ouagadougou", "Africa/Abidjan",
+        "Africa/Porto-Novo", "Africa/Lagos",
+        "Africa/Timbuktu", "Africa/Abidjan",
+        "America/Anguilla", "America/Port_of_Spain",
+        "America/Antigua", "America/Port_of_Spain",
+        "America/Argentina/ComodRivadavia", "America/Argentina/Catamarca",
+        "America/Aruba", "America/Curacao",
+        "America/Atka", "America/Adak",
+        "America/Buenos_Aires", "America/Argentina/Buenos_Aires",
+        "America/Catamarca", "America/Argentina/Catamarca",
+        "America/Cayman", "America/Panama",
+        "America/Coral_Harbour", "America/Atikokan",
+        "America/Cordoba", "America/Argentina/Cordoba",
+        "America/Dominica", "America/Port_of_Spain",
+        "America/Ensenada", "America/Tijuana",
+        "America/Fort_Wayne", "America/Indiana/Indianapolis",
+        "America/Godthab", "America/Nuuk",
+        "America/Grenada", "America/Port_of_Spain",
+        "America/Guadeloupe", "America/Port_of_Spain",
+        "America/Indianapolis", "America/Indiana/Indianapolis",
+        "America/Jujuy", "America/Argentina/Jujuy",
         "America/Knox_IN", "America/Indiana/Knox",
-        "Canada/Saskatchewan", "America/Regina",
-        "Asia/Thimbu", "Asia/Thimphu",
-        "US/Mountain", "America/Denver",
-        "NZ", "Pacific/Auckland",
+        "America/Kralendijk", "America/Curacao",
+        "America/Louisville", "America/Kentucky/Louisville",
+        "America/Lower_Princes", "America/Curacao",
+        "America/Marigot", "America/Port_of_Spain",
+        "America/Mendoza", "America/Argentina/Mendoza",
+        "America/Montreal", "America/Toronto",
+        "America/Montserrat", "America/Port_of_Spain",
+        "America/Porto_Acre", "America/Rio_Branco",
+        "America/Rosario", "America/Argentina/Cordoba",
+        "America/Santa_Isabel", "America/Tijuana",
+        "America/Shiprock", "America/Denver",
+        "America/St_Barthelemy", "America/Port_of_Spain",
+        "America/St_Kitts", "America/Port_of_Spain",
+        "America/St_Lucia", "America/Port_of_Spain",
+        "America/St_Thomas", "America/Port_of_Spain",
+        "America/St_Vincent", "America/Port_of_Spain",
+        "America/Tortola", "America/Port_of_Spain",
+        "America/Virgin", "America/Port_of_Spain",
+        "Antarctica/McMurdo", "Pacific/Auckland",
+        "Antarctica/South_Pole", "Pacific/Auckland",
+        "Arctic/Longyearbyen", "Europe/Oslo",
+        "Asia/Aden", "Asia/Riyadh",
+        "Asia/Ashkhabad", "Asia/Ashgabat",
+        "Asia/Bahrain", "Asia/Qatar",
+        "Asia/Calcutta", "Asia/Kolkata",
+        "Asia/Chongqing", "Asia/Shanghai",
+        "Asia/Chungking", "Asia/Shanghai",
+        "Asia/Dacca", "Asia/Dhaka",
+        "Asia/Harbin", "Asia/Shanghai",
+        "Asia/Istanbul", "Europe/Istanbul",
+        "Asia/Kashgar", "Asia/Urumqi",
+        "Asia/Katmandu", "Asia/Kathmandu",
+        "Asia/Kuwait", "Asia/Riyadh",
+        "Asia/Macao", "Asia/Macau",
+        "Asia/Muscat", "Asia/Dubai",
+        "Asia/Phnom_Penh", "Asia/Bangkok",
+        "Asia/Rangoon", "Asia/Yangon",
+        "Asia/Saigon", "Asia/Ho_Chi_Minh",
         "Asia/Tel_Aviv", "Asia/Jerusalem",
+        "Asia/Thimbu", "Asia/Thimphu",
+        "Asia/Ujung_Pandang", "Asia/Makassar",
+        "Asia/Ulan_Bator", "Asia/Ulaanbaatar",
+        "Asia/Vientiane", "Asia/Bangkok",
+        "Atlantic/Faeroe", "Atlantic/Faroe",
+        "Atlantic/Jan_Mayen", "Europe/Oslo",
+        "Atlantic/St_Helena", "Africa/Abidjan",
+        "Australia/ACT", "Australia/Sydney",
+        "Australia/Canberra", "Australia/Sydney",
+        "Australia/LHI", "Australia/Lord_Howe",
+        "Australia/NSW", "Australia/Sydney",
+        "Australia/North", "Australia/Darwin",
+        "Australia/Queensland", "Australia/Brisbane",
+        "Australia/South", "Australia/Adelaide",
+        "Australia/Tasmania", "Australia/Hobart",
+        "Australia/Victoria", "Australia/Melbourne",
+        "Australia/West", "Australia/Perth",
+        "Australia/Yancowinna", "Australia/Broken_Hill",
+        "Brazil/Acre", "America/Rio_Branco",
+        "Brazil/DeNoronha", "America/Noronha",
+        "Brazil/East", "America/Sao_Paulo",
+        "Brazil/West", "America/Manaus",
+        "Canada/Atlantic", "America/Halifax",
+        "Canada/Central", "America/Winnipeg",
+        "Canada/Eastern", "America/Toronto",
+        "Canada/Mountain", "America/Edmonton",
+        "Canada/Newfoundland", "America/St_Johns",
+        "Canada/Pacific", "America/Vancouver",
+        "Canada/Saskatchewan", "America/Regina",
+        "Canada/Yukon", "America/Whitehorse",
+        "Chile/Continental", "America/Santiago",
+        "Chile/EasterIsland", "Pacific/Easter",
+        "Cuba", "America/Havana",
+        "Egypt", "Africa/Cairo",
+        "Eire", "Europe/Dublin",
+        "Etc/GMT+0", "Etc/GMT",
+        "Etc/GMT-0", "Etc/GMT",
+        "Etc/GMT0", "Etc/GMT",
+        "Etc/Greenwich", "Etc/GMT",
+        "Etc/Universal", "Etc/UTC",
+        "Etc/Zulu", "Etc/UTC",
+        "Europe/Belfast", "Europe/London",
+        "Europe/Bratislava", "Europe/Prague",
+        "Europe/Busingen", "Europe/Zurich",
+        "Europe/Guernsey", "Europe/London",
+        "Europe/Isle_of_Man", "Europe/London",
+        "Europe/Jersey", "Europe/London",
+        "Europe/Ljubljana", "Europe/Belgrade",
+        "Europe/Mariehamn", "Europe/Helsinki",
+        "Europe/Nicosia", "Asia/Nicosia",
+        "Europe/Podgorica", "Europe/Belgrade",
+        "Europe/San_Marino", "Europe/Rome",
+        "Europe/Sarajevo", "Europe/Belgrade",
+        "Europe/Skopje", "Europe/Belgrade",
+        "Europe/Tiraspol", "Europe/Chisinau",
+        "Europe/Vaduz", "Europe/Zurich",
+        "Europe/Vatican", "Europe/Rome",
+        "Europe/Zagreb", "Europe/Belgrade",
+        "GB", "Europe/London",
+        "GB-Eire", "Europe/London",
+        "GMT", "Etc/GMT",
+        "GMT+0", "Etc/GMT",
+        "GMT-0", "Etc/GMT",
+        "GMT0", "Etc/GMT",
+        "Greenwich", "Etc/GMT",
         "Hongkong", "Asia/Hong_Kong",
+        "Iceland", "Atlantic/Reykjavik",
+        "Indian/Antananarivo", "Africa/Nairobi",
+        "Indian/Comoro", "Africa/Nairobi",
+        "Indian/Mayotte", "Africa/Nairobi",
+        "Iran", "Asia/Tehran",
+        "Israel", "Asia/Jerusalem",
+        "Jamaica", "America/Jamaica",
+        "Japan", "Asia/Tokyo",
+        "Kwajalein", "Pacific/Kwajalein",
+        "Libya", "Africa/Tripoli",
+        "Mexico/BajaNorte", "America/Tijuana",
+        "Mexico/BajaSur", "America/Mazatlan",
+        "Mexico/General", "America/Mexico_City",
+        "Mideast/Riyadh87", "Asia/Riyadh87",
+        "Mideast/Riyadh88", "Asia/Riyadh88",
+        "Mideast/Riyadh89", "Asia/Riyadh89",
+        "NZ", "Pacific/Auckland",
+        "NZ-CHAT", "Pacific/Chatham",
+        "Navajo", "America/Denver",
+        "PRC", "Asia/Shanghai",
+        "Pacific/Johnston", "Pacific/Honolulu",
+        "Pacific/Midway", "Pacific/Pago_Pago",
+        "Pacific/Ponape", "Pacific/Pohnpei",
+        "Pacific/Saipan", "Pacific/Guam",
+        "Pacific/Samoa", "Pacific/Pago_Pago",
+        "Pacific/Truk", "Pacific/Chuuk",
+        "Pacific/Yap", "Pacific/Chuuk",
+        "Poland", "Europe/Warsaw",
+        "Portugal", "Europe/Lisbon",
+        "ROC", "Asia/Taipei",
+        "ROK", "Asia/Seoul",
+        "Singapore", "Asia/Singapore",
+        "Turkey", "Europe/Istanbul",
+        "UCT", "Etc/UCT",
+        "US/Alaska", "America/Anchorage",
+        "US/Aleutian", "America/Adak",
+        "US/Arizona", "America/Phoenix",
+        "US/Central", "America/Chicago",
+        "US/East-Indiana", "America/Indiana/Indianapolis",
+        "US/Eastern", "America/New_York",
+        "US/Hawaii", "Pacific/Honolulu",
+        "US/Indiana-Starke", "America/Indiana/Knox",
+        "US/Michigan", "America/Detroit",
+        "US/Mountain", "America/Denver",
+        "US/Pacific", "America/Los_Angeles",
+        "US/Samoa", "Pacific/Pago_Pago",
+        "UTC", "Etc/UTC",
+        "Universal", "Etc/UTC",
+        "W-SU", "Europe/Moscow",
+        "Zulu", "Etc/UTC",
     };
 
     private static final Map<String, String> zidToMzone = new HashMap<>();
diff --git a/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java b/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java
index 4946ccd..df51dbb 100644
--- a/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java
+++ b/ojluni/src/test/java/time/test/java/time/temporal/TestChronoField.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -123,7 +123,6 @@
     public void test_IsoFields_week_based_year() {
         Locale locale = Locale.US;
         String name = IsoFields.WEEK_OF_WEEK_BASED_YEAR.getDisplayName(locale);
-        // Android-changed: week is lower-case in CLDR.
         assertEquals(name, "week");
     }
 
@@ -137,7 +136,6 @@
         Locale locale = Locale.US;
         TemporalField weekOfYearField = WeekFields.SUNDAY_START.weekOfYear();
         String name = weekOfYearField.getDisplayName(locale);
-        // Android-changed: week is lower-case in CLDR.
         assertEquals(name, "week");
     }
 
diff --git a/ojluni/src/test/java/time/test/java/time/temporal/TestIsoWeekFields.java b/ojluni/src/test/java/time/test/java/time/temporal/TestIsoWeekFields.java
index d79d13f..71916c1 100644
--- a/ojluni/src/test/java/time/test/java/time/temporal/TestIsoWeekFields.java
+++ b/ojluni/src/test/java/time/test/java/time/temporal/TestIsoWeekFields.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -121,6 +121,14 @@
         assertEquals(IsoFields.WEEK_BASED_YEAR.isSupportedBy(ThaiBuddhistDate.now()), false);
     }
 
+    @Test
+    public void test_Unit_isSupportedBy_ISO() {
+        assertEquals(IsoFields.WEEK_BASED_YEARS.isSupportedBy(LocalDate.now()),true);
+        assertEquals(IsoFields.WEEK_BASED_YEARS.isSupportedBy(ThaiBuddhistDate.now()),false);
+        assertEquals(IsoFields.QUARTER_YEARS.isSupportedBy(LocalDate.now()),true);
+        assertEquals(IsoFields.QUARTER_YEARS.isSupportedBy(ThaiBuddhistDate.now()),false);
+    }
+
     @Test(dataProvider = "fields")
     public void test_WBY_range(TemporalField weekField, TemporalField yearField) {
         assertEquals(yearField.range(), ValueRange.of(Year.MIN_VALUE, Year.MAX_VALUE));
diff --git a/ojluni/src/test/java/time/test/java/time/zone/TestZoneRules.java b/ojluni/src/test/java/time/test/java/time/zone/TestZoneRules.java
new file mode 100644
index 0000000..03ff71f
--- /dev/null
+++ b/ojluni/src/test/java/time/test/java/time/zone/TestZoneRules.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.java.time.zone;
+
+import static org.testng.Assert.assertEquals;
+
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.zone.ZoneOffsetTransition;
+import java.time.zone.ZoneRules;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @summary Test ZoneRules whether the savings are positive in time zones that have
+ *      negative savings in the source TZ files. Also, check the transition cutover
+ *      time beyond 24:00, which should translate into the next day.
+ *
+ * @bug 8212970
+ */
+@Test
+public class TestZoneRules {
+
+    private static final ZoneId DUBLIN = ZoneId.of("Europe/Dublin");
+    private static final ZoneId PRAGUE = ZoneId.of("Europe/Prague");
+    private static final ZoneId WINDHOEK = ZoneId.of("Africa/Windhoek");
+    private static final ZoneId CASABLANCA = ZoneId.of("Africa/Casablanca");
+
+    private static final ZoneId TOKYO = ZoneId.of("Asia/Tokyo");
+    private static final LocalTime ONE_AM = LocalTime.of(1, 0);
+
+    @DataProvider
+    private Object[][] negativeDST () {
+        return new Object[][] {
+            // ZoneId, localDate, offset, standard offset, isDaylightSavings
+            // Europe/Dublin for the Rule "Eire"
+            // Android-changed: During 1969 - 1971 summers, Europe/Dublin is using GMT+1 as the standard time.
+            // {DUBLIN, LocalDate.of(1970, 6, 23), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+            // {DUBLIN, LocalDate.of(1971, 6, 23), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+            {DUBLIN, LocalDate.of(1970, 6, 23), ZoneOffset.ofHours(1), ZoneOffset.ofHours(1), false},
+            {DUBLIN, LocalDate.of(1971, 6, 23), ZoneOffset.ofHours(1), ZoneOffset.ofHours(1), false},
+            {DUBLIN, LocalDate.of(1971, 11, 1), ZoneOffset.ofHours(0), ZoneOffset.ofHours(0), false},
+            {DUBLIN, LocalDate.of(2019, 6, 23), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+            {DUBLIN, LocalDate.of(2019, 12, 23), ZoneOffset.ofHours(0), ZoneOffset.ofHours(0), false},
+
+            // Europe/Prague which contains fixed negative savings (not a named Rule)
+            {PRAGUE, LocalDate.of(1946, 9, 30), ZoneOffset.ofHours(2), ZoneOffset.ofHours(1), true},
+            {PRAGUE, LocalDate.of(1946, 10, 10), ZoneOffset.ofHours(1), ZoneOffset.ofHours(1), false},
+            {PRAGUE, LocalDate.of(1946, 12, 3), ZoneOffset.ofHours(0), ZoneOffset.ofHours(0), false},
+            {PRAGUE, LocalDate.of(1947, 2, 25), ZoneOffset.ofHours(1), ZoneOffset.ofHours(1), false},
+            {PRAGUE, LocalDate.of(1947, 4, 30), ZoneOffset.ofHours(2), ZoneOffset.ofHours(1), true},
+
+            // Africa/Windhoek for the Rule "Namibia"
+            {WINDHOEK, LocalDate.of(1994, 3, 23), ZoneOffset.ofHours(1), ZoneOffset.ofHours(1), false},
+            {WINDHOEK, LocalDate.of(2016, 9, 23), ZoneOffset.ofHours(2), ZoneOffset.ofHours(1), true},
+
+            // Africa/Casablanca for the Rule "Morocco" Defines negative DST till 2037 as of 2019a.
+            {CASABLANCA, LocalDate.of(1939, 9, 13), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+            {CASABLANCA, LocalDate.of(1939, 11, 20), ZoneOffset.ofHours(0), ZoneOffset.ofHours(0), false},
+            {CASABLANCA, LocalDate.of(2018, 6, 18), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+            {CASABLANCA, LocalDate.of(2019, 1, 1), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+            {CASABLANCA, LocalDate.of(2019, 5, 6), ZoneOffset.ofHours(0), ZoneOffset.ofHours(0), false},
+            {CASABLANCA, LocalDate.of(2037, 10, 5), ZoneOffset.ofHours(0), ZoneOffset.ofHours(0), false},
+            {CASABLANCA, LocalDate.of(2037, 11, 16), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+            {CASABLANCA, LocalDate.of(2038, 11, 8), ZoneOffset.ofHours(1), ZoneOffset.ofHours(0), true},
+        };
+    }
+
+    @DataProvider
+    private Object[][] transitionBeyondDay() {
+        return new Object[][] {
+            // ZoneId, LocalDateTime, beforeOffset, afterOffset
+
+            // Asserts that the rule:
+            // Rule Japan   1948    1951    -   Sep Sat>=8  25:00   0   S
+            // translates to the next day.
+            {TOKYO, LocalDateTime.of(LocalDate.of(1948, 9, 12), ONE_AM), ZoneOffset.ofHours(10), ZoneOffset.ofHours(9)},
+            {TOKYO, LocalDateTime.of(LocalDate.of(1949, 9, 11), ONE_AM), ZoneOffset.ofHours(10), ZoneOffset.ofHours(9)},
+            {TOKYO, LocalDateTime.of(LocalDate.of(1950, 9, 10), ONE_AM), ZoneOffset.ofHours(10), ZoneOffset.ofHours(9)},
+            {TOKYO, LocalDateTime.of(LocalDate.of(1951, 9, 9), ONE_AM), ZoneOffset.ofHours(10), ZoneOffset.ofHours(9)},
+        };
+    }
+
+    // Android-changed: Android doesn't support negative DST yet.
+    @Test(dataProvider="negativeDST")
+    public void test_NegativeDST(ZoneId zid, LocalDate ld, ZoneOffset offset, ZoneOffset stdOffset, boolean isDST) {
+        Instant i = Instant.from(ZonedDateTime.of(ld, LocalTime.MIN, zid));
+        ZoneRules zr = zid.getRules();
+        assertEquals(zr.getOffset(i), offset);
+        assertEquals(zr.getStandardOffset(i), stdOffset);
+        assertEquals(zr.isDaylightSavings(i), isDST);
+    }
+
+    @Test(dataProvider="transitionBeyondDay")
+    public void test_TransitionBeyondDay(ZoneId zid, LocalDateTime ldt, ZoneOffset before, ZoneOffset after) {
+        ZoneOffsetTransition zot = ZoneOffsetTransition.of(ldt, before, after);
+        ZoneRules zr = zid.getRules();
+        assertTrue(zr.getTransitions().contains(zot));
+    }
+}
diff --git a/ojluni/src/test/java/time/test/java/util/TestFormatter.java b/ojluni/src/test/java/time/test/java/util/TestFormatter.java
index 7b405ca..d2167a6 100644
--- a/ojluni/src/test/java/time/test/java/util/TestFormatter.java
+++ b/ojluni/src/test/java/time/test/java/util/TestFormatter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
 import java.time.temporal.ChronoField;
 import java.time.temporal.TemporalQueries;
 import java.time.temporal.TemporalAccessor;
+import java.time.temporal.UnsupportedTemporalTypeException;
 
 import java.util.*;
 
@@ -46,7 +47,7 @@
 
 /* @test
  * @summary Unit test for j.u.Formatter threeten date/time support
- * @bug 8003680 8012638
+ * @bug 8003680 8043387 8012638
  */
 @Test
 public class TestFormatter {
@@ -161,6 +162,47 @@
         if (verbose) {
             System.out.printf("%-24s  : %s%n", getClassName(dt), out);
         }
+
+        // expected usually comes from Calendar which only has milliseconds
+        // precision. So we're going to replace it's N:[nanos] stamp with
+        // the correct value for nanos.
+        if ((dt instanceof TemporalAccessor) && expected != null) {
+            try {
+                // Get millis & nanos from the dt
+                final TemporalAccessor ta = (TemporalAccessor) dt;
+                // Android-changed: Formatter doesn't support nanosecond yet.
+                // TODO: Revert this patch when Formatter is upgraded from 8 to 11 version.
+                // final int nanos = ta.get(ChronoField.NANO_OF_SECOND);
+                final int millis = ta.get(ChronoField.MILLI_OF_SECOND);
+                final int nanos = millis * 1000000;
+                final String nanstr = String.valueOf(nanos);
+                final String mistr = String.valueOf(millis);
+
+                // Compute the value of the N:[nanos] field that we expect
+                // to find in 'out'
+                final StringBuilder sb = new StringBuilder();
+                sb.append("N:[");
+                for (int i=nanstr.length(); i<9; i++) {
+                    sb.append('0');
+                }
+                sb.append(nanos).append("]");
+
+                // Compute the truncated value of N:[nanos] field that might
+                // be in 'expected' when expected was built from Calendar.
+                final StringBuilder sbm = new StringBuilder();
+                sbm.append("N:[");
+                for (int i=mistr.length(); i<3; i++) {
+                    sbm.append('0');
+                }
+                sbm.append(mistr).append("000000]");
+
+                // if expected contains the truncated value, replace it with
+                // the complete value.
+                expected = expected.replace(sbm.toString(), sb.toString());
+            } catch (UnsupportedTemporalTypeException e) {
+                // nano seconds unsupported - nothing to do...
+            }
+        }
         if (expected != null && !out.equals(expected)) {
             System.out.printf("%-24s  actual: %s%n                FAILED; expected: %s%n",
                               getClassName(dt), out, expected);
@@ -204,11 +246,6 @@
         }
     }
 
-    private String toZoneIdStr(String expected) {
-        // Android-changed: java.util.Calendar and java.time types are formatted identically.
-        return expected;
-    }
-
     private String toZoneOffsetStr(String expected) {
         // Android-changed: Android Matcher doesn't support named groups. Also GMT/Z is formatted as
         // "GMT+00:00" or "GMT".
@@ -219,8 +256,7 @@
     private void testZoneId(Locale locale, ChronoZonedDateTime<?> zdt, Calendar cal) {
         String fmtStr = "z:[%tz] z:[%1$Tz] Z:[%1$tZ] Z:[%1$TZ]";
         printFmtStr(locale, fmtStr);
-        String calOutput = test(fmtStr, locale, null, cal);
-        String expected = toZoneIdStr(calOutput);
+        String expected = test(fmtStr, locale, null, cal);
         test(fmtStr, locale, expected, zdt);
         // get a new cal with fixed tz
         Calendar cal0 = Calendar.getInstance();
@@ -236,7 +272,7 @@
         // datetime + zid
         fmtStr = "c:[%tc] c:[%1$Tc]";
         printFmtStr(locale, fmtStr);
-        expected = toZoneIdStr(test(fmtStr, locale, null, cal));
+        expected = test(fmtStr, locale, null, cal);
         test(fmtStr, locale, expected, zdt);
     }
 
diff --git a/ojluni/src/test/java/util/Arrays/ArraysEqCmpTest.java b/ojluni/src/test/java/util/Arrays/ArraysEqCmpTest.java
new file mode 100644
index 0000000..727f7dc
--- /dev/null
+++ b/ojluni/src/test/java/util/Arrays/ArraysEqCmpTest.java
@@ -0,0 +1,1117 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Arrays;
+
+/*
+ * @test
+ * @bug 8033148 8141409
+ * @summary tests for array equals and compare
+ * @run testng ArraysEqCmpTest
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiFunction;
+import java.util.function.LongFunction;
+import java.util.stream.IntStream;
+
+public class ArraysEqCmpTest {
+
+    // Maximum width in bits
+    static final int MAX_WIDTH = 512;
+
+    static final Map<Class, Integer> typeToWidth;
+
+    static {
+        typeToWidth = new HashMap<>();
+        typeToWidth.put(boolean.class, Byte.SIZE);
+        typeToWidth.put(byte.class, Byte.SIZE);
+        typeToWidth.put(short.class, Short.SIZE);
+        typeToWidth.put(char.class, Character.SIZE);
+        typeToWidth.put(int.class, Integer.SIZE);
+        typeToWidth.put(long.class, Long.SIZE);
+        typeToWidth.put(float.class, Float.SIZE);
+        typeToWidth.put(double.class, Double.SIZE);
+        typeToWidth.put(Object.class, Integer.SIZE); // @@@ 32 or 64?
+    }
+
+    static int arraySizeFor(Class<?> type) {
+        type = type.isPrimitive() ? type : Object.class;
+        return 4 * MAX_WIDTH / typeToWidth.get(type);
+    }
+
+    static abstract class ArrayType<T> {
+        final Class<?> arrayType;
+        final Class<?> componentType;
+        final boolean unsigned;
+
+        final MethodHandle cpy;
+
+        final MethodHandle eq;
+        final MethodHandle eqr;
+        final MethodHandle cmp;
+        final MethodHandle cmpr;
+        final MethodHandle mm;
+        final MethodHandle mmr;
+
+        final MethodHandle getter;
+
+        final MethodHandle toString;
+
+        public ArrayType(Class<T> arrayType) {
+            this(arrayType, false);
+        }
+
+        public ArrayType(Class<T> arrayType, boolean unsigned) {
+            this.arrayType = arrayType;
+            this.componentType = arrayType.getComponentType();
+            this.unsigned = unsigned;
+
+            try {
+                MethodHandles.Lookup l = MethodHandles.lookup();
+
+                getter = MethodHandles.arrayElementGetter(arrayType);
+
+                if (componentType.isPrimitive()) {
+                    cpy = l.findStatic(Arrays.class, "copyOfRange",
+                            MethodType.methodType(arrayType, arrayType, int.class, int.class));
+
+                    MethodType eqt = MethodType.methodType(
+                            boolean.class, arrayType, arrayType);
+                    MethodType eqrt = MethodType.methodType(
+                            boolean.class, arrayType, int.class, int.class, arrayType, int.class, int.class);
+
+                    eq = l.findStatic(Arrays.class, "equals", eqt);
+                    eqr = l.findStatic(Arrays.class, "equals", eqrt);
+
+                    String compareName = unsigned ? "compareUnsigned" : "compare";
+                    cmp = l.findStatic(Arrays.class, compareName,
+                            eqt.changeReturnType(int.class));
+                    cmpr = l.findStatic(Arrays.class, compareName,
+                            eqrt.changeReturnType(int.class));
+
+                    mm = l.findStatic(Arrays.class, "mismatch",
+                            eqt.changeReturnType(int.class));
+                    mmr = l.findStatic(Arrays.class, "mismatch",
+                            eqrt.changeReturnType(int.class));
+
+                    toString = l.findStatic(Arrays.class, "toString",
+                            MethodType.methodType(String.class, arrayType));
+                }
+                else {
+                    cpy = l.findStatic(Arrays.class, "copyOfRange",
+                            MethodType.methodType(Object[].class, Object[].class, int.class, int.class));
+
+                    MethodType eqt = MethodType.methodType(
+                            boolean.class, Object[].class, Object[].class);
+                    MethodType eqrt = MethodType.methodType(
+                            boolean.class, Object[].class, int.class, int.class, Object[].class, int.class, int.class);
+
+                    eq = l.findStatic(Arrays.class, "equals", eqt);
+                    eqr = l.findStatic(Arrays.class, "equals", eqrt);
+
+                    MethodType cmpt = MethodType.methodType(
+                            int.class, Comparable[].class, Comparable[].class);
+                    MethodType cmprt = MethodType.methodType(
+                            int.class, Comparable[].class, int.class, int.class, Comparable[].class, int.class, int.class);
+
+                    cmp = l.findStatic(Arrays.class, "compare", cmpt);
+                    cmpr = l.findStatic(Arrays.class, "compare", cmprt);
+
+                    mm = l.findStatic(Arrays.class, "mismatch",
+                            eqt.changeReturnType(int.class));
+                    mmr = l.findStatic(Arrays.class, "mismatch",
+                            eqrt.changeReturnType(int.class));
+
+                    toString = l.findStatic(Arrays.class, "toString",
+                            MethodType.methodType(String.class, Object[].class));
+                }
+
+            }
+            catch (Exception e) {
+                throw new Error(e);
+            }
+        }
+
+        @Override
+        public String toString() {
+            String s = arrayType.getCanonicalName();
+            return unsigned ? "unsigned " + s : s;
+        }
+
+        Object construct(int length) {
+            return Array.newInstance(componentType, length);
+        }
+
+        Object copyOf(Object a) {
+            return copyOf(a, 0, Array.getLength(a));
+        }
+
+        Object copyOf(Object a, int from, int to) {
+            try {
+                return (Object) cpy.invoke(a, from, to);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        Object get(Object a, int i) {
+            try {
+                return (Object) getter.invoke(a, i);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        abstract void set(Object a, int i, Object v);
+
+        boolean equals(Object a, Object b) {
+            try {
+                return (boolean) eq.invoke(a, b);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        boolean equals(Object a, int aFromIndex, int aToIndex,
+                Object b, int bFromIndex, int bToIndex) {
+            try {
+                return (boolean) eqr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        int compare(Object a, Object b) {
+            try {
+                return (int) cmp.invoke(a, b);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        int compare(Object a, int aFromIndex, int aToIndex,
+                Object b, int bFromIndex, int bToIndex) {
+            try {
+                return (int) cmpr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        int mismatch(Object a, Object b) {
+            try {
+                return (int) mm.invoke(a, b);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        int mismatch(Object a, int aFromIndex, int aToIndex,
+                Object b, int bFromIndex, int bToIndex) {
+            try {
+                return (int) mmr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        String toString(Object a) {
+            try {
+                return (String) toString.invoke(a);
+            }
+            catch (RuntimeException | Error e) {
+                throw e;
+            }
+            catch (Throwable t) {
+                throw new Error(t);
+            }
+        }
+
+        static class BoxedIntegers extends ArrayType<Integer[]> {
+            public BoxedIntegers() {
+                super(Integer[].class);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                // Ensure unique reference
+                ((Integer[]) a)[i] = v != null ? new Integer((Integer) v) : null;
+            }
+        }
+
+        static class BoxedIntegersWithReverseComparator extends BoxedIntegers {
+            final Comparator<Integer> c = (a, b) -> {
+                // Nulls sort after non-nulls
+                if (a == null || b == null)
+                    return a == null ? b == null ? 0 : 1 : -1;
+
+                return Integer.compare(b, a);
+            };
+
+            final MethodHandle eqc;
+            final MethodHandle eqcr;
+            final MethodHandle cmpc;
+            final MethodHandle cmpcr;
+            final MethodHandle mismatchc;
+            final MethodHandle mismatchcr;
+
+            public BoxedIntegersWithReverseComparator() {
+                try {
+                    MethodHandles.Lookup l = MethodHandles.lookup();
+
+                    MethodType cmpt = MethodType.methodType(
+                            int.class, Object[].class, Object[].class, Comparator.class);
+                    MethodType cmprt = MethodType.methodType(
+                            int.class, Object[].class, int.class, int.class,
+                            Object[].class, int.class, int.class, Comparator.class);
+
+                    eqc = l.findStatic(Arrays.class, "equals", cmpt.changeReturnType(boolean.class));
+                    eqcr = l.findStatic(Arrays.class, "equals", cmprt.changeReturnType(boolean.class));
+                    cmpc = l.findStatic(Arrays.class, "compare", cmpt);
+                    cmpcr = l.findStatic(Arrays.class, "compare", cmprt);
+                    mismatchc = l.findStatic(Arrays.class, "mismatch", cmpt);
+                    mismatchcr = l.findStatic(Arrays.class, "mismatch", cmprt);
+                }
+                catch (Exception e) {
+                    throw new Error(e);
+                }
+            }
+
+            @Override
+            boolean equals(Object a, Object b) {
+                try {
+                    return (boolean) eqc.invoke(a, b, c);
+                }
+                catch (RuntimeException | Error e) {
+                    throw e;
+                }
+                catch (Throwable t) {
+                    throw new Error(t);
+                }
+            }
+
+            @Override
+            boolean equals(Object a, int aFromIndex, int aToIndex,
+                    Object b, int bFromIndex, int bToIndex) {
+                try {
+                    return (boolean) eqcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c);
+                }
+                catch (RuntimeException | Error e) {
+                    throw e;
+                }
+                catch (Throwable t) {
+                    throw new Error(t);
+                }
+            }
+
+            @Override
+            int compare(Object a, Object b) {
+                try {
+                    return (int) cmpc.invoke(a, b, c);
+                }
+                catch (RuntimeException | Error e) {
+                    throw e;
+                }
+                catch (Throwable t) {
+                    throw new Error(t);
+                }
+            }
+
+            @Override
+            int compare(Object a, int aFromIndex, int aToIndex,
+                    Object b, int bFromIndex, int bToIndex) {
+                try {
+                    return (int) cmpcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c);
+                }
+                catch (RuntimeException | Error e) {
+                    throw e;
+                }
+                catch (Throwable t) {
+                    throw new Error(t);
+                }
+            }
+
+            @Override
+            int mismatch(Object a, Object b) {
+                try {
+                    return (int) mismatchc.invoke(a, b, c);
+                }
+                catch (RuntimeException | Error e) {
+                    throw e;
+                }
+                catch (Throwable t) {
+                    throw new Error(t);
+                }
+            }
+
+            @Override
+            int mismatch(Object a, int aFromIndex, int aToIndex,
+                    Object b, int bFromIndex, int bToIndex) {
+                try {
+                    return (int) mismatchcr.invoke(a, aFromIndex, aToIndex, b, bFromIndex, bToIndex, c);
+                }
+                catch (RuntimeException | Error e) {
+                    throw e;
+                }
+                catch (Throwable t) {
+                    throw new Error(t);
+                }
+            }
+
+            @Override
+            public String toString() {
+                return arrayType.getCanonicalName() + " with Comparator";
+            }
+        }
+
+        static class Booleans extends ArrayType<boolean[]> {
+            public Booleans() {
+                super(boolean[].class);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                boolean pv;
+                if (v instanceof Boolean) {
+                    pv = (Boolean) v;
+                }
+                else if (v instanceof Integer) {
+                    pv = ((Integer) v) >= 0;
+                }
+                else throw new IllegalStateException();
+
+                ((boolean[]) a)[i] = pv;
+            }
+        }
+
+        static class Bytes extends ArrayType<byte[]> {
+            public Bytes(boolean unsigned) {
+                super(byte[].class, unsigned);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                byte pv;
+                if (v instanceof Byte) {
+                    pv = (Byte) v;
+                }
+                else if (v instanceof Integer) {
+                    pv = ((Integer) v).byteValue();
+                }
+                else throw new IllegalStateException();
+
+                ((byte[]) a)[i] = pv;
+            }
+        }
+
+        static class Characters extends ArrayType<char[]> {
+            public Characters() {
+                super(char[].class);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                char pv;
+                if (v instanceof Character) {
+                    pv = (Character) v;
+                }
+                else if (v instanceof Integer) {
+                    pv = (char) ((Integer) v).intValue();
+                }
+                else throw new IllegalStateException();
+
+                ((char[]) a)[i] = pv;
+            }
+        }
+
+        static class Shorts extends ArrayType<short[]> {
+            public Shorts(boolean unsigned) {
+                super(short[].class, unsigned);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                short pv;
+                if (v instanceof Short) {
+                    pv = (Short) v;
+                }
+                else if (v instanceof Integer) {
+                    pv = ((Integer) v).shortValue();
+                }
+                else throw new IllegalStateException();
+
+                ((short[]) a)[i] = pv;
+            }
+        }
+
+        static class Integers extends ArrayType<int[]> {
+            public Integers(boolean unsigned) {
+                super(int[].class, unsigned);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                int pv;
+                if (v instanceof Integer) {
+                    pv = ((Integer) v).shortValue();
+                }
+                else throw new IllegalStateException();
+
+                ((int[]) a)[i] = pv;
+            }
+        }
+
+        static class Longs extends ArrayType<long[]> {
+            public Longs(boolean unsigned) {
+                super(long[].class, unsigned);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                long pv;
+                if (v instanceof Long) {
+                    pv = (Long) v;
+                }
+                else if (v instanceof Integer) {
+                    pv = ((Integer) v).longValue();
+                }
+                else throw new IllegalStateException();
+
+                ((long[]) a)[i] = pv;
+            }
+        }
+
+        static class Floats extends ArrayType<float[]> {
+            public Floats() {
+                super(float[].class);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                float pv;
+                if (v instanceof Float) {
+                    pv = (Float) v;
+                }
+                else if (v instanceof Integer) {
+                    pv = ((Integer) v).floatValue();
+                }
+                else throw new IllegalStateException();
+
+                ((float[]) a)[i] = pv;
+            }
+        }
+
+        static class Doubles extends ArrayType<double[]> {
+            public Doubles() {
+                super(double[].class);
+            }
+
+            @Override
+            void set(Object a, int i, Object v) {
+                double pv;
+                if (v instanceof Double) {
+                    pv = (Double) v;
+                }
+                else if (v instanceof Integer) {
+                    pv = ((Integer) v).doubleValue();
+                }
+                else throw new IllegalStateException();
+
+                ((double[]) a)[i] = pv;
+            }
+        }
+    }
+
+    static Object[][] arrayTypes;
+
+    @DataProvider
+    public static Object[][] arrayTypesProvider() {
+        if (arrayTypes == null) {
+            arrayTypes = new Object[][]{
+                    new Object[]{new ArrayType.BoxedIntegers()},
+                    new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()},
+                    new Object[]{new ArrayType.Booleans()},
+                    new Object[]{new ArrayType.Bytes(false)},
+                    new Object[]{new ArrayType.Bytes(true)},
+                    new Object[]{new ArrayType.Characters()},
+                    new Object[]{new ArrayType.Shorts(false)},
+                    new Object[]{new ArrayType.Shorts(true)},
+                    new Object[]{new ArrayType.Integers(false)},
+                    new Object[]{new ArrayType.Integers(true)},
+                    new Object[]{new ArrayType.Longs(false)},
+                    new Object[]{new ArrayType.Longs(true)},
+                    new Object[]{new ArrayType.Floats()},
+                    new Object[]{new ArrayType.Doubles()},
+            };
+        }
+        return arrayTypes;
+    }
+
+    static Object[][] floatArrayTypes;
+
+    @DataProvider
+    public static Object[][] floatArrayTypesProvider() {
+        if (floatArrayTypes == null) {
+            LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
+            LongFunction<Object> bToD = Double::longBitsToDouble;
+
+            floatArrayTypes = new Object[][]{
+                    new Object[]{new ArrayType.Floats(), 0x7fc00000L, 0x7f800001L, bTof},
+                    new Object[]{new ArrayType.Doubles(), 0x7ff8000000000000L, 0x7ff0000000000001L, bToD},
+            };
+        }
+        return floatArrayTypes;
+    }
+
+    static Object[][] objectArrayTypes;
+
+    @DataProvider
+    public static Object[][] objectArrayTypesProvider() {
+        if (objectArrayTypes == null) {
+            LongFunction<Object> bTof = rb -> Float.intBitsToFloat((int) rb);
+            LongFunction<Object> bToD = Double::longBitsToDouble;
+
+            objectArrayTypes = new Object[][]{
+                    new Object[]{new ArrayType.BoxedIntegers()},
+                    new Object[]{new ArrayType.BoxedIntegersWithReverseComparator()},
+            };
+        }
+        return objectArrayTypes;
+    }
+
+
+    static Object[][] signedUnsignedArrayTypes;
+
+    @DataProvider
+    public static Object[][] signedUnsignedArrayTypes() {
+        if (signedUnsignedArrayTypes == null) {
+            signedUnsignedArrayTypes = new Object[][]{
+                    new Object[]{new ArrayType.Bytes(false), new ArrayType.Bytes(true)},
+                    new Object[]{new ArrayType.Shorts(false), new ArrayType.Shorts(true)},
+                    new Object[]{new ArrayType.Integers(false), new ArrayType.Integers(true)},
+                    new Object[]{new ArrayType.Longs(false), new ArrayType.Longs(true)},
+            };
+        }
+        return signedUnsignedArrayTypes;
+    }
+
+    // Equality and comparison tests
+
+    @Test(dataProvider = "arrayTypesProvider")
+    public void testArray(ArrayType<?> arrayType) {
+        BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
+            Object a = at.construct(s);
+            for (int x = 0; x < s; x++) {
+                at.set(a, x, x % 8);
+            }
+            return a;
+        };
+
+        BiFunction<ArrayType<?>, Object, Object> cloner = (at, a) ->
+                constructor.apply(at, Array.getLength(a));
+
+        testArrayType(arrayType, constructor, cloner);
+    }
+
+    @Test(dataProvider = "floatArrayTypesProvider")
+    public void testPrimitiveFloatArray(
+            ArrayType<?> arrayType,
+            long canonicalNanRawBits, long nonCanonicalNanRawBits,
+            LongFunction<Object> bitsToFloat) {
+        Object canonicalNan = bitsToFloat.apply(canonicalNanRawBits);
+        // If conversion is a signalling NaN it may be subject to conversion to a
+        // quiet NaN on some processors, even if a copy is performed
+        // The tests assume that if conversion occurs it does not convert to the
+        // canonical NaN
+        Object nonCanonicalNan = bitsToFloat.apply(nonCanonicalNanRawBits);
+
+        BiFunction<ArrayType<?>, Integer, Object> canonicalNaNs = (at, s) -> {
+            Object a = at.construct(s);
+            for (int x = 0; x < s; x++) {
+                at.set(a, x, canonicalNan);
+            }
+            return a;
+        };
+
+        BiFunction<ArrayType<?>, Object, Object> nonCanonicalNaNs = (at, a) -> {
+            int s = Array.getLength(a);
+            Object ac = at.construct(s);
+            for (int x = 0; x < s; x++) {
+                at.set(ac, x, nonCanonicalNan);
+            }
+            return ac;
+        };
+
+        BiFunction<ArrayType<?>, Object, Object> halfNonCanonicalNaNs = (at, a) -> {
+            int s = Array.getLength(a);
+            Object ac = at.construct(s);
+            for (int x = 0; x < s / 2; x++) {
+                at.set(ac, x, nonCanonicalNan);
+            }
+            for (int x = s / 2; x < s; x++) {
+                at.set(ac, x, 1);
+            }
+            return ac;
+        };
+
+        testArrayType(arrayType, canonicalNaNs, nonCanonicalNaNs);
+        testArrayType(arrayType, canonicalNaNs, halfNonCanonicalNaNs);
+    }
+
+    @Test(dataProvider = "objectArrayTypesProvider")
+    public void testNullElementsInObjectArray(ArrayType<?> arrayType) {
+        BiFunction<ArrayType<?>, Object, Object> cloner = ArrayType::copyOf;
+
+        // All nulls
+        testArrayType(arrayType,
+                (at, s) -> {
+                    Object a = at.construct(s);
+                    for (int x = 0; x < s; x++) {
+                        at.set(a, x, null);
+                    }
+                    return a;
+                },
+                cloner);
+
+
+        // Some nulls
+        testArrayType(arrayType,
+                (at, s) -> {
+                    Object a = at.construct(s);
+                    for (int x = 0; x < s; x++) {
+                        int v = x % 8;
+                        at.set(a, x, v == 0 ? null : v);
+                    }
+                    return a;
+                },
+                cloner);
+
+        Integer[] a = new Integer[]{null, 0};
+        Integer[] b = new Integer[]{0, 0};
+        Assert.assertTrue(Arrays.compare(a, b) < 0);
+        Assert.assertTrue(Arrays.compare(b, a) > 0);
+    }
+
+    @Test(dataProvider = "objectArrayTypesProvider")
+    public void testSameRefElementsInObjectArray(ArrayType<?> arrayType) {
+        BiFunction<ArrayType<?>, Object, Object> cloner = ArrayType::copyOf;
+
+        // One ref
+        Integer one = 1;
+        testArrayType(arrayType,
+                (at, s) -> {
+                    Integer[] a = (Integer[]) at.construct(s);
+                    for (int x = 0; x < s; x++) {
+                        a[x] = one;
+                    }
+                    return a;
+                },
+                cloner);
+
+        // All ref
+        testArrayType(arrayType,
+                (at, s) -> {
+                    Integer[] a = (Integer[]) at.construct(s);
+                    for (int x = 0; x < s; x++) {
+                        a[x] = Integer.valueOf(s);
+                    }
+                    return a;
+                },
+                cloner);
+
+        // Some same ref
+        testArrayType(arrayType,
+                (at, s) -> {
+                    Integer[] a = (Integer[]) at.construct(s);
+                    for (int x = 0; x < s; x++) {
+                        int v = x % 8;
+                        a[x] = v == 1 ? one : new Integer(v);
+                    }
+                    return a;
+                },
+                cloner);
+    }
+
+    @Test(dataProvider = "signedUnsignedArrayTypes")
+    public void testSignedUnsignedArray(ArrayType<?> sat, ArrayType<?> uat) {
+        BiFunction<ArrayType<?>, Integer, Object> constructor = (at, s) -> {
+            Object a = at.construct(s);
+            for (int x = 0; x < s; x++) {
+                at.set(a, x, 1);
+            }
+            return a;
+        };
+
+        int n = arraySizeFor(sat.componentType);
+
+        for (int s : ranges(0, n)) {
+            Object a = constructor.apply(sat, s);
+
+            for (int aFrom : ranges(0, s)) {
+                for (int aTo : ranges(aFrom, s)) {
+                    int aLength = aTo - aFrom;
+
+                    if (aLength > 0) {
+                        for (int i = aFrom; i < aTo; i++) {
+                            Object ac = sat.copyOf(a);
+                            // Create common prefix with a length of i - aFrom
+                            sat.set(ac, i, -1);
+
+                            int sc = sat.compare(ac, aFrom, aTo, a, aFrom, aTo);
+                            int uc = uat.compare(ac, aFrom, aTo, a, aFrom, aTo);
+
+                            Assert.assertTrue(sc < 0);
+                            Assert.assertTrue(uc > 0);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    void testArrayType(ArrayType<?> at,
+            BiFunction<ArrayType<?>, Integer, Object> constructor,
+            BiFunction<ArrayType<?>, Object, Object> cloner) {
+        int n = arraySizeFor(at.componentType);
+
+        for (int s : ranges(0, n)) {
+            Object a = constructor.apply(at, s);
+            Object b = cloner.apply(at, a);
+
+            for (int aFrom : ranges(0, s)) {
+                for (int aTo : ranges(aFrom, s)) {
+                    int aLength = aTo - aFrom;
+
+                    for (int bFrom : ranges(0, s)) {
+                        for (int bTo : ranges(bFrom, s)) {
+                            int bLength = bTo - bFrom;
+
+                            Object anr = at.copyOf(a, aFrom, aTo);
+                            Object bnr = at.copyOf(b, bFrom, bTo);
+
+                            boolean eq = isEqual(at, a, aFrom, aTo, b, bFrom, bTo);
+                            Assert.assertEquals(at.equals(a, aFrom, aTo, b, bFrom, bTo), eq);
+                            Assert.assertEquals(at.equals(b, bFrom, bTo, a, aFrom, aTo), eq);
+                            Assert.assertEquals(at.equals(anr, bnr), eq);
+                            Assert.assertEquals(at.equals(bnr, anr), eq);
+                            if (eq) {
+                                Assert.assertEquals(at.compare(a, aFrom, aTo, b, bFrom, bTo), 0);
+                                Assert.assertEquals(at.compare(b, bFrom, bTo, a, aFrom, aTo), 0);
+                                Assert.assertEquals(at.compare(anr, bnr), 0);
+                                Assert.assertEquals(at.compare(bnr, anr), 0);
+
+                                Assert.assertEquals(at.mismatch(a, aFrom, aTo, b, bFrom, bTo), -1);
+                                Assert.assertEquals(at.mismatch(b, bFrom, bTo, a, aFrom, aTo), -1);
+                                Assert.assertEquals(at.mismatch(anr, bnr), -1);
+                                Assert.assertEquals(at.mismatch(bnr, anr), -1);
+                            }
+                            else {
+                                int aCb = at.compare(a, aFrom, aTo, b, bFrom, bTo);
+                                int bCa = at.compare(b, bFrom, bTo, a, aFrom, aTo);
+                                int v = Integer.signum(aCb) * Integer.signum(bCa);
+                                Assert.assertTrue(v == -1);
+
+                                int anrCbnr = at.compare(anr, bnr);
+                                int bnrCanr = at.compare(bnr, anr);
+                                Assert.assertEquals(anrCbnr, aCb);
+                                Assert.assertEquals(bnrCanr, bCa);
+
+
+                                int aMb = at.mismatch(a, aFrom, aTo, b, bFrom, bTo);
+                                int bMa = at.mismatch(b, bFrom, bTo, a, aFrom, aTo);
+                                int anrMbnr = at.mismatch(anr, bnr);
+                                int bnrManr = at.mismatch(bnr, anr);
+
+                                Assert.assertNotEquals(aMb, -1);
+                                Assert.assertEquals(aMb, bMa);
+                                Assert.assertNotEquals(anrMbnr, -1);
+                                Assert.assertEquals(anrMbnr, bnrManr);
+                                Assert.assertEquals(aMb, anrMbnr);
+                                Assert.assertEquals(bMa, bnrManr);
+
+                                // Common or proper prefix
+                                Assert.assertTrue(at.equals(a, aFrom, aFrom + aMb, b, bFrom, bFrom + aMb));
+                                if (aMb < Math.min(aLength, bLength)) {
+                                    // Common prefix
+                                    Assert.assertFalse(isEqual(at, a, aFrom + aMb, b, bFrom + aMb));
+                                }
+                            }
+                        }
+                    }
+
+                    if (aLength > 0) {
+                        for (int i = aFrom; i < aTo; i++) {
+                            Object ac = at.copyOf(a);
+                            // Create common prefix with a length of i - aFrom
+                            at.set(ac, i, -1);
+
+                            Object acnr = at.copyOf(ac, aFrom, aTo);
+                            Object anr = at.copyOf(a, aFrom, aTo);
+
+                            Assert.assertFalse(at.equals(ac, aFrom, aTo, a, aFrom, aTo));
+                            Assert.assertFalse(at.equals(acnr, anr));
+
+                            int acCa = at.compare(ac, aFrom, aTo, a, aFrom, aTo);
+                            int aCac = at.compare(a, aFrom, aTo, ac, aFrom, aTo);
+                            int v = Integer.signum(acCa) * Integer.signum(aCac);
+                            Assert.assertTrue(v == -1);
+
+                            int acnrCanr = at.compare(acnr, anr);
+                            int anrCacnr = at.compare(anr, acnr);
+                            Assert.assertEquals(acnrCanr, acCa);
+                            Assert.assertEquals(anrCacnr, aCac);
+
+
+                            int acMa = at.mismatch(ac, aFrom, aTo, a, aFrom, aTo);
+                            int aMac = at.mismatch(a, aFrom, aTo, ac, aFrom, aTo);
+                            Assert.assertEquals(acMa, aMac);
+                            Assert.assertEquals(acMa, i - aFrom);
+
+                            int acnrManr = at.mismatch(acnr, anr);
+                            int anrMacnr = at.mismatch(anr, acnr);
+                            Assert.assertEquals(acnrManr, anrMacnr);
+                            Assert.assertEquals(acnrManr, i - aFrom);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    static boolean isEqual(ArrayType<?> at, Object a, int aFromIndex, int aToIndex,
+            Object b, int bFromIndex, int bToIndex) {
+        int aLength = aToIndex - aFromIndex;
+        int bLength = bToIndex - bFromIndex;
+        if (aLength != bLength)
+            return false;
+
+        for (int i = 0; i < aLength; i++) {
+            Object av = at.get(a, aFromIndex++);
+            Object bv = at.get(b, bFromIndex++);
+            if (!Objects.equals(av, bv)) return false;
+        }
+
+        return true;
+    }
+
+    static boolean isEqual(ArrayType<?> at, Object a, int aFrom, Object b, int bFrom) {
+        Object av = at.get(a, aFrom);
+        Object bv = at.get(b, bFrom);
+
+        return Objects.equals(av, bv);
+    }
+
+    static int[] ranges(int from, int to) {
+        int width = to - from;
+        switch (width) {
+            case 0:
+                return new int[]{};
+            case 1:
+                return new int[]{from, to};
+            case 2:
+                return new int[]{from, from + 1, to};
+            case 3:
+                return new int[]{from, from + 1, from + 2, to};
+            default:
+                return IntStream.of(from, from + 1, from + 2, to / 2 - 1, to / 2, to / 2 + 1, to - 2, to - 1, to)
+                        .filter(i -> i >= from && i <= to)
+                        .distinct().toArray();
+        }
+    }
+
+
+    // Null array reference tests
+
+    @Test(dataProvider = "arrayTypesProvider")
+    public void testNullArrayRefs(ArrayType<?> arrayType) {
+        Object n = null;
+        Object a = arrayType.construct(0);
+
+        Assert.assertTrue(arrayType.equals(n, n));
+        Assert.assertFalse(arrayType.equals(n, a));
+        Assert.assertFalse(arrayType.equals(a, n));
+
+        Assert.assertEquals(arrayType.compare(n, n), 0);
+        Assert.assertTrue(arrayType.compare(n, a) < 0);
+        Assert.assertTrue(arrayType.compare(a, n) > 0);
+    }
+
+
+    // Exception throwing tests
+
+    @Test(dataProvider = "arrayTypesProvider")
+    public void testNPEs(ArrayType<?> arrayType) {
+        Object[] values = new Object[]{null, arrayType.construct(0)};
+
+        for (Object o1 : values) {
+            for (Object o2 : values) {
+                if (o1 != null && o2 != null)
+                    continue;
+
+                testNPE(() -> arrayType.equals(o1, 0, 0, o2, 0, 0));
+                testNPE(() -> arrayType.compare(o1, 0, 0, o2, 0, 0));
+                testNPE(() -> arrayType.mismatch(o1, o2));
+                testNPE(() -> arrayType.mismatch(o1, 0, 0, o2, 0, 0));
+            }
+        }
+    }
+
+    @Test
+    public void testObjectNPEs() {
+        String[][] values = new String[][]{null, new String[0]};
+        Comparator<String> c = String::compareTo;
+        Comparator[] cs = new Comparator[]{null, c};
+
+        for (String[] o1 : values) {
+            for (String[] o2 : values) {
+                for (Comparator o3 : cs) {
+                    if (o1 != null && o2 != null && o3 != null)
+                        continue;
+
+                    if (o3 == null) {
+                        testNPE(() -> Arrays.equals(o1, o2, o3));
+                        testNPE(() -> Arrays.compare(o1, o2, o3));
+                        testNPE(() -> Arrays.mismatch(o1, o2, o3));
+                    }
+
+                    testNPE(() -> Arrays.equals(o1, 0, 0, o2, 0, 0, o3));
+                    testNPE(() -> Arrays.compare(o1, 0, 0, o2, 0, 0, o3));
+                    testNPE(() -> Arrays.mismatch(o1, 0, 0, o2, 0, 0, o3));
+                }
+            }
+        }
+    }
+
+    @Test(dataProvider = "arrayTypesProvider")
+    public void testIAEs(ArrayType<?> arrayType) {
+        List<Integer> values = Arrays.asList(0, 1);
+
+        for (int s : values) {
+            Object a = arrayType.construct(s);
+
+            for (int o1 : values) {
+                for (int o2 : values) {
+                    if (o1 <= o2) continue;
+
+                    testIAE(() -> arrayType.equals(a, o1, 0, a, o2, 0));
+                    testIAE(() -> arrayType.compare(a, o1, 0, a, o2, 0));
+                    testIAE(() -> arrayType.mismatch(a, o1, 0, a, o2, 0));
+                }
+            }
+        }
+    }
+
+    @Test(dataProvider = "arrayTypesProvider")
+    public void testAIOBEs(ArrayType<?> arrayType) {
+        List<Integer> froms = Arrays.asList(-1, 0);
+
+        for (int s : Arrays.asList(0, 1)) {
+            List<Integer> tos = Arrays.asList(s, s + 1);
+            Object a = arrayType.construct(s);
+
+            for (int aFrom : froms) {
+                for (int aTo : tos) {
+                    for (int bFrom : froms) {
+                        for (int bTo : tos) {
+                            if (aFrom >= 0 && aTo <= s &&
+                                    bFrom >= 0 && bTo <= s) continue;
+
+                            testAIOBE(() -> arrayType.equals(a, aFrom, aTo, a, bFrom, bTo));
+                            testAIOBE(() -> arrayType.compare(a, aFrom, aTo, a, bFrom, bTo));
+                            testAIOBE(() -> arrayType.mismatch(a, aFrom, aTo, a, bFrom, bTo));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    static void testNPE(Runnable r) {
+        testThrowable(r, NullPointerException.class);
+    }
+
+    static void testIAE(Runnable r) {
+        testThrowable(r, IllegalArgumentException.class);
+    }
+
+    static void testAIOBE(Runnable r) {
+        testThrowable(r, ArrayIndexOutOfBoundsException.class);
+    }
+
+    static void testThrowable(Runnable r, Class<? extends Throwable> expected) {
+        Throwable caught = null;
+        try {
+            r.run();
+        }
+        catch (Throwable t) {
+            caught = t;
+        }
+        Assert.assertNotNull(caught);
+        Assert.assertTrue(expected.isInstance(caught));
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Collection/BiggernYours.java b/ojluni/src/test/java/util/Collection/BiggernYours.java
new file mode 100644
index 0000000..397dcc7
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/BiggernYours.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6415641 6377302
+ * @summary Concurrent collections are permitted to lie about their size
+ * @author Martin Buchholz
+ */
+package test.java.util.Collection;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.NavigableSet;
+import java.util.Objects;
+import java.util.Random;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.PriorityBlockingQueue;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("unchecked")
+public class BiggernYours {
+
+    static final Random rnd = new Random(18675309);
+
+    static void compareCollections(Collection c1, Collection c2) {
+        Object[] c1Array = c1.toArray();
+        Object[] c2Array = c2.toArray();
+
+        Assert.assertEquals(c1Array.length, c2Array.length);
+        for (Object aC1 : c1Array) {
+            boolean found = false;
+            for (Object aC2 : c2Array) {
+                if (Objects.equals(aC1, aC2)) {
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found) {
+                Assert.fail(aC1 + " not found in " + Arrays.toString(c2Array));
+            }
+        }
+    }
+
+    static void compareMaps(Map m1, Map m2) {
+        compareCollections(m1.keySet(),
+                m2.keySet());
+        compareCollections(m1.values(),
+                m2.values());
+        compareCollections(m1.entrySet(),
+                m2.entrySet());
+    }
+
+    static void compareNavigableMaps(NavigableMap m1, NavigableMap m2) {
+        compareMaps(m1, m2);
+        compareMaps(m1.descendingMap(),
+                m2.descendingMap());
+        compareMaps(m1.tailMap(Integer.MIN_VALUE),
+                m2.tailMap(Integer.MIN_VALUE));
+        compareMaps(m1.headMap(Integer.MAX_VALUE),
+                m2.headMap(Integer.MAX_VALUE));
+    }
+
+    static void compareNavigableSets(NavigableSet s1, NavigableSet s2) {
+        compareCollections(s1, s2);
+        compareCollections(s1.descendingSet(),
+                s2.descendingSet());
+        compareCollections(s1.tailSet(Integer.MIN_VALUE),
+                s2.tailSet(Integer.MIN_VALUE));
+    }
+
+    abstract static class MapFrobber {
+
+        abstract void frob(Map m);
+    }
+
+    abstract static class ColFrobber {
+
+        abstract void frob(Collection c);
+    }
+
+    static ColFrobber adder(final int i) {
+        return new ColFrobber() {
+            void frob(Collection c) {
+                c.add(i);
+            }
+        };
+    }
+
+    static final ColFrobber[] adders =
+            {adder(1), adder(3), adder(2)};
+
+    static MapFrobber putter(final int k, final int v) {
+        return new MapFrobber() {
+            void frob(Map m) {
+                m.put(k, v);
+            }
+        };
+    }
+
+    static final MapFrobber[] putters =
+            {putter(1, -2), putter(3, -6), putter(2, -4)};
+
+    static void testCollections(Collection c1, Collection c2) {
+        try {
+            compareCollections(c1, c2);
+            for (ColFrobber adder : adders) {
+                for (Collection c : new Collection[]{c1, c2}) {
+                    adder.frob(c);
+                }
+                compareCollections(c1, c2);
+            }
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    static void testNavigableSets(NavigableSet s1, NavigableSet s2) {
+        try {
+            compareNavigableSets(s1, s2);
+            for (ColFrobber adder : adders) {
+                for (Set s : new Set[]{s1, s2}) {
+                    adder.frob(s);
+                }
+                compareNavigableSets(s1, s2);
+            }
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    static void testMaps(Map m1, Map m2) {
+        try {
+            compareMaps(m1, m2);
+            for (MapFrobber putter : putters) {
+                for (Map m : new Map[]{m1, m2}) {
+                    putter.frob(m);
+                }
+                compareMaps(m1, m2);
+            }
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    static void testNavigableMaps(NavigableMap m1, NavigableMap m2) {
+        try {
+            compareNavigableMaps(m1, m2);
+            for (MapFrobber putter : putters) {
+                for (Map m : new Map[]{m1, m2}) {
+                    putter.frob(m);
+                }
+                compareNavigableMaps(m1, m2);
+            }
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    static int randomize(int size) {
+        return rnd.nextInt(size + 2);
+    }
+
+    @Test
+    public void testConcurrentSkipListMap() {
+        testNavigableMaps(
+                new ConcurrentSkipListMap(),
+                new ConcurrentSkipListMap() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testConcurrentSkipListSet() {
+        testNavigableSets(
+                new ConcurrentSkipListSet(),
+                new ConcurrentSkipListSet() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testCopyOnWriteArraySet() {
+        testCollections(
+                new CopyOnWriteArraySet(),
+                new CopyOnWriteArraySet() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testCopyOnWriteArrayList() {
+        testCollections(
+                new CopyOnWriteArrayList(),
+                new CopyOnWriteArrayList() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testTreeSet() {
+        testCollections(
+                new TreeSet(),
+                new TreeSet() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testConcurrentHashMap() {
+        testMaps(
+                new ConcurrentHashMap(),
+                new ConcurrentHashMap() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testConcurrentLinkedDeque() {
+        testCollections(
+                new ConcurrentLinkedDeque(),
+                new ConcurrentLinkedDeque() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testConcurrentLinkedQueue() {
+        testCollections(
+                new ConcurrentLinkedQueue(),
+                new ConcurrentLinkedQueue() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testLinkedTransferQueue() {
+        testCollections(
+                new LinkedTransferQueue(),
+                new LinkedTransferQueue() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testLinkedBlockingQueue() {
+        testCollections(
+                new LinkedBlockingQueue(),
+                new LinkedBlockingQueue() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testLinkedBlockingDeque() {
+        testCollections(
+                new LinkedBlockingDeque(),
+                new LinkedBlockingDeque() {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testArrayBlockingQueue() {
+        testCollections(
+                new ArrayBlockingQueue(5),
+                new ArrayBlockingQueue(5) {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+
+    @Test
+    public void testPriorityBlockingQueue() {
+        testCollections(
+                new PriorityBlockingQueue(5),
+                new PriorityBlockingQueue(5) {
+                    public int size() {
+                        return randomize(super.size());
+                    }
+                });
+    }
+}
diff --git a/ojluni/src/test/java/util/Collection/CollectionDefaults.java b/ojluni/src/test/java/util/Collection/CollectionDefaults.java
new file mode 100644
index 0000000..000778f
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/CollectionDefaults.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Collection;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import java.util.SortedSet;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import test.java.util.Collection.testlibrary.CollectionAsserts;
+import test.java.util.Collection.testlibrary.CollectionSupplier;
+import test.java.util.Collection.testlibrary.ExtendsAbstractCollection;
+import test.java.util.Collection.testlibrary.ExtendsAbstractList;
+import test.java.util.Collection.testlibrary.ExtendsAbstractSet;
+
+/**
+ * @test
+ * @summary Unit tests for extension methods on Collection
+ * @library testlibrary
+ * @build CollectionAsserts CollectionSupplier ExtendsAbstractSet ExtendsAbstractCollection
+ * @run testng CollectionDefaults
+ */
+public class CollectionDefaults {
+
+    public static final Predicate<Integer> pEven = x -> 0 == x % 2;
+    public static final Predicate<Integer> pOdd = x -> 1 == x % 2;
+
+    private static final int SIZE = 100;
+
+    private static final List<Function<Collection<Integer>, Collection<Integer>>> TEST_SUPPLIERS = Arrays
+            .asList(
+                    // Collection
+                    ExtendsAbstractCollection<Integer>::new,
+                    java.util.ArrayDeque<Integer>::new,
+                    java.util.concurrent.ConcurrentLinkedDeque<Integer>::new,
+                    java.util.concurrent.ConcurrentLinkedQueue<Integer>::new,
+                    java.util.concurrent.LinkedBlockingDeque<Integer>::new,
+                    java.util.concurrent.LinkedBlockingQueue<Integer>::new,
+                    java.util.concurrent.LinkedTransferQueue<Integer>::new,
+                    (coll) -> new java.util.concurrent.ArrayBlockingQueue<Integer>(
+                            3 * SIZE, false, coll),
+
+                    // Lists
+                    java.util.ArrayList<Integer>::new,
+                    java.util.LinkedList<Integer>::new,
+                    java.util.Vector<Integer>::new,
+                    java.util.concurrent.CopyOnWriteArrayList<Integer>::new,
+                    ExtendsAbstractList<Integer>::new,
+
+                    // Sets
+                    java.util.HashSet<Integer>::new,
+                    java.util.LinkedHashSet<Integer>::new,
+                    java.util.TreeSet<Integer>::new,
+                    java.util.concurrent.ConcurrentSkipListSet<Integer>::new,
+                    java.util.concurrent.CopyOnWriteArraySet<Integer>::new,
+                    ExtendsAbstractSet<Integer>::new
+            );
+
+    @DataProvider(name = "setProvider", parallel = true)
+    public static Iterator<Object[]> setCases() {
+        final List<Object[]> cases = new LinkedList<>();
+        cases.add(new Object[]{new HashSet<>()});
+        cases.add(new Object[]{new LinkedHashSet<>()});
+        cases.add(new Object[]{new TreeSet<>()});
+        cases.add(new Object[]{new java.util.concurrent.ConcurrentSkipListSet<>()});
+        cases.add(new Object[]{new java.util.concurrent.CopyOnWriteArraySet<>()});
+
+        cases.add(new Object[]{new ExtendsAbstractSet<>()});
+
+        cases.add(new Object[]{Collections.newSetFromMap(new HashMap<>())});
+        cases.add(new Object[]{Collections.newSetFromMap(new LinkedHashMap<>())});
+        cases.add(new Object[]{Collections.newSetFromMap(new TreeMap<>())});
+        cases.add(new Object[]{Collections.newSetFromMap(new ConcurrentHashMap<>())});
+        cases.add(new Object[]{Collections.newSetFromMap(new ConcurrentSkipListMap<>())});
+
+        cases.add(new Object[]{new HashSet<Integer>() {{
+            add(42);
+        }}});
+        cases.add(new Object[]{new ExtendsAbstractSet<Integer>() {{
+            add(42);
+        }}});
+        cases.add(new Object[]{new LinkedHashSet<Integer>() {{
+            add(42);
+        }}});
+        cases.add(new Object[]{new TreeSet<Integer>() {{
+            add(42);
+        }}});
+        return cases.iterator();
+    }
+
+    @Test(dataProvider = "setProvider")
+    public void testProvidedWithNull(final Set<Integer> set) {
+        try {
+            set.forEach(null);
+            fail("expected NPE not thrown");
+        } catch (NullPointerException expected) { // expected
+        }
+        try {
+            set.removeIf(null);
+            fail("expected NPE not thrown");
+        } catch (NullPointerException expected) { // expected
+        }
+    }
+
+    @Test
+    public void testForEach() {
+        @SuppressWarnings("unchecked") final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(
+                TEST_SUPPLIERS, SIZE);
+
+        for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
+            final Collection<Integer> original = test.expected;
+            final Collection<Integer> set = test.collection;
+
+            try {
+                set.forEach(null);
+                fail("expected NPE not thrown");
+            } catch (NullPointerException expected) { // expected
+            }
+            if (set instanceof Set && !((set instanceof SortedSet)
+                    || (set instanceof LinkedHashSet))) {
+                CollectionAsserts.assertContentsUnordered(set, original, test.toString());
+            } else {
+                CollectionAsserts.assertContents(set, original, test.toString());
+            }
+
+            final List<Integer> actual = new LinkedList<>();
+            set.forEach(actual::add);
+            if (set instanceof Set && !((set instanceof SortedSet)
+                    || (set instanceof LinkedHashSet))) {
+                CollectionAsserts.assertContentsUnordered(actual, set, test.toString());
+                CollectionAsserts.assertContentsUnordered(actual, original, test.toString());
+            } else {
+                CollectionAsserts.assertContents(actual, set, test.toString());
+                CollectionAsserts.assertContents(actual, original, test.toString());
+            }
+        }
+    }
+
+    @Test
+    public void testRemoveIf() {
+        @SuppressWarnings("unchecked") final CollectionSupplier<Collection<Integer>> supplier = new CollectionSupplier(
+                TEST_SUPPLIERS, SIZE);
+        for (final CollectionSupplier.TestCase<Collection<Integer>> test : supplier.get()) {
+            final Collection<Integer> original = test.expected;
+            final Collection<Integer> set = test.collection;
+
+            try {
+                set.removeIf(null);
+                fail("expected NPE not thrown");
+            } catch (NullPointerException expected) { // expected
+            }
+            if (set instanceof Set && !((set instanceof SortedSet)
+                    || (set instanceof LinkedHashSet))) {
+                CollectionAsserts.assertContentsUnordered(set, original, test.toString());
+            } else {
+                CollectionAsserts.assertContents(set, original, test.toString());
+            }
+
+            set.removeIf(pEven);
+            for (int i : set) {
+                assertTrue((i % 2) == 1);
+            }
+            for (int i : original) {
+                if (i % 2 == 1) {
+                    assertTrue(set.contains(i));
+                }
+            }
+            set.removeIf(pOdd);
+            assertTrue(set.isEmpty());
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Collection/HotPotatoes.java b/ojluni/src/test/java/util/Collection/HotPotatoes.java
new file mode 100644
index 0000000..ef03de6
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/HotPotatoes.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6355660 6347106 6394004
+ * @summary methods taking concurrently mutating collection should work
+ * @author Martin Buchholz
+ */
+package test.java.util.Collection;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Vector;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.PriorityBlockingQueue;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("unchecked")
+public class HotPotatoes {
+
+    @Test
+    public void testVector() throws Throwable {
+        testImplementation(Vector.class);
+    }
+
+    @Test
+    public void testArrayList() throws Throwable {
+        testImplementation(ArrayList.class);
+    }
+
+    @Test
+    public void testPriorityQueue() throws Throwable {
+        testImplementation(PriorityQueue.class);
+    }
+
+    @Test
+    public void testPriorityBlockingQueue() throws Throwable {
+        testImplementation(PriorityBlockingQueue.class);
+    }
+
+    private static void testImplementation(Class<? extends Collection> implClazz) throws Throwable {
+        testPotato(implClazz, Vector.class);
+        testPotato(implClazz, CopyOnWriteArrayList.class);
+
+        final Constructor<? extends Collection> constr
+                = implClazz.getConstructor(Collection.class);
+        final Collection<Object> coll
+                = constr.newInstance(Arrays.asList(new String[]{}));
+        coll.add(1);
+        Assert.assertEquals(coll.toString(), "[1]");
+    }
+
+    private static void testPotato(Class<? extends Collection> implClazz,
+            Class<? extends List> argClazz) throws Throwable {
+        try {
+            System.out.printf("implClazz=%s, argClazz=%s\n",
+                    implClazz.getName(), argClazz.getName());
+            final int iterations = 100000;
+            final List<Integer> list = (List<Integer>)
+                    argClazz.getDeclaredConstructor().newInstance();
+            final Integer one = Integer.valueOf(1);
+            final List<Integer> oneElementList = Collections.singletonList(one);
+            final Constructor<? extends Collection> constr
+                    = implClazz.getConstructor(Collection.class);
+            final Thread t = new CheckedThread() {
+                public void realRun() {
+                    for (int i = 0; i < iterations; i++) {
+                        list.add(one);
+                        list.remove(one);
+                    }
+                }
+            };
+            t.setDaemon(true);
+            t.start();
+
+            for (int i = 0; i < iterations; i++) {
+                Collection<?> coll = constr.newInstance(list);
+                Object[] elts = coll.toArray();
+                Assert.assertTrue(elts.length == 0 || (elts.length == 1 && elts[0] == one));
+            }
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    private abstract static class CheckedThread extends Thread {
+
+        public abstract void realRun() throws Throwable;
+
+        public void run() {
+            try {
+                realRun();
+            } catch (Throwable t) {
+                Assert.fail("Unexpected exception: " + t.getMessage());
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Collection/IteratorAtEnd.java b/ojluni/src/test/java/util/Collection/IteratorAtEnd.java
new file mode 100644
index 0000000..b22d4d0
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/IteratorAtEnd.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6529795
+ * @summary next() does not change iterator state if throws NoSuchElementException
+ * @author Martin Buchholz
+ */
+package test.java.util.Collection;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.PriorityQueue;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Vector;
+import java.util.WeakHashMap;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.LinkedTransferQueue;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+@SuppressWarnings("unchecked")
+public class IteratorAtEnd {
+
+    private static final int SIZE = 6;
+
+    @Test
+    public void testArrayList() {
+        testCollection(new ArrayList());
+    }
+
+    @Test
+    public void testVector() {
+        testCollection(new Vector());
+    }
+
+    @Test
+    public void testLinkedList() {
+        testCollection(new LinkedList());
+    }
+
+    @Test
+    public void testArrayDeque() {
+        testCollection(new ArrayDeque());
+    }
+
+    @Test
+    public void testTreeSet() {
+        testCollection(new TreeSet());
+    }
+
+    @Test
+    public void testCopyOnWriteArrayList() {
+        testCollection(new CopyOnWriteArrayList());
+    }
+
+    @Test
+    public void testCopyOnWriteArraySet() {
+        testCollection(new CopyOnWriteArraySet());
+    }
+
+    @Test
+    public void testConcurrentSkipListSet() {
+        testCollection(new ConcurrentSkipListSet());
+    }
+
+    @Test
+    public void testPriorityQueue() {
+        testCollection(new PriorityQueue());
+    }
+
+    @Test
+    public void testLinkedBlockingQueue() {
+        testCollection(new LinkedBlockingQueue());
+    }
+
+    @Test
+    public void testArrayBlockingQueue() {
+        testCollection(new ArrayBlockingQueue(100));
+    }
+
+    @Test
+    public void testConcurrentLinkedDeque() {
+        testCollection(new ConcurrentLinkedDeque());
+    }
+
+    @Test
+    public void testConcurrentLinkedQueue() {
+        testCollection(new ConcurrentLinkedQueue());
+    }
+
+    @Test
+    public void testLinkedTransferQueue() {
+        testCollection(new LinkedTransferQueue());
+    }
+
+    @Test
+    public void testHashMap() {
+        testMap(new HashMap());
+    }
+
+    @Test
+    public void testHashtable() {
+        testMap(new Hashtable());
+    }
+
+    @Test
+    public void testLinkedHashMap() {
+        testMap(new LinkedHashMap());
+    }
+
+    @Test
+    public void testWeakHashMap() {
+        testMap(new WeakHashMap());
+    }
+
+    @Test
+    public void testIdentityHashMap() {
+        testMap(new IdentityHashMap());
+    }
+
+    @Test
+    public void testConcurrentHashMap() {
+        testMap(new ConcurrentHashMap());
+    }
+
+    @Test
+    public void testConcurrentSkipListMap() {
+        testMap(new ConcurrentSkipListMap());
+    }
+
+    @Test
+    public void testTreeMap() {
+        testMap(new TreeMap());
+    }
+
+    static void testCollection(Collection c) {
+        try {
+            for (int i = 0; i < SIZE; i++) {
+                c.add(i);
+            }
+            test(c);
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    static void testMap(Map m) {
+        try {
+            for (int i = 0; i < 3 * SIZE; i++) {
+                m.put(i, i);
+            }
+            test(m.values());
+            test(m.keySet());
+            test(m.entrySet());
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+    }
+
+    static void test(Collection c) {
+        try {
+            final Iterator it = c.iterator();
+            THROWS(NoSuchElementException.class,
+                    () -> {
+                        while (true) {
+                            it.next();
+                        }
+                    });
+            try {
+                it.remove();
+            } catch (UnsupportedOperationException exc) {
+                return;
+            }
+        } catch (Throwable t) {
+            Assert.fail("Unexpected exception: " + t.getMessage());
+        }
+
+        if (c instanceof List) {
+            final List list = (List) c;
+            try {
+                final ListIterator it = list.listIterator(0);
+                it.next();
+                final Object x = it.previous();
+                THROWS(NoSuchElementException.class, it::previous);
+                try {
+                    it.remove();
+                } catch (UnsupportedOperationException exc) {
+                    return;
+                }
+                Assert.assertFalse(list.get(0).equals(x));
+            } catch (Throwable t) {
+                Assert.fail("Unexpected exception: " + t.getMessage());
+            }
+
+            try {
+                final ListIterator it = list.listIterator(list.size());
+                it.previous();
+                final Object x = it.next();
+                THROWS(NoSuchElementException.class, it::next);
+                try {
+                    it.remove();
+                } catch (UnsupportedOperationException exc) {
+                    return;
+                }
+                Assert.assertFalse(list.get(list.size() - 1).equals(x));
+            } catch (Throwable t) {
+                Assert.fail("Unexpected exception: " + t.getMessage());
+            }
+        }
+    }
+
+    interface Fun {
+
+        void f() throws Throwable;
+    }
+
+    static void THROWS(Class<? extends Throwable> k, Fun... fs) {
+        for (Fun f : fs) {
+            try {
+                f.f();
+                Assert.fail("Expected " + k.getName() + " not thrown");
+            } catch (Throwable t) {
+                if (!k.isAssignableFrom(t.getClass())) {
+                    Assert.fail("Unexpected exception: " + t.getMessage());
+                }
+            }
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Collection/MOAT.java b/ojluni/src/test/java/util/Collection/MOAT.java
new file mode 100644
index 0000000..e0e7b0d
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/MOAT.java
@@ -0,0 +1,1795 @@
+/*
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     6207984 6272521 6192552 6269713 6197726 6260652 5073546 4137464
+ *          4155650 4216399 4294891 6282555 6318622 6355327 6383475 6420753
+ *          6431845 4802633 6570566 6570575 6570631 6570924 6691185 6691215
+ *          4802647 7123424 8024709 8193128
+ * @summary Run many tests on many Collection and Map implementations
+ * @author  Martin Buchholz
+ * @modules java.base/java.util:open
+ * @run main MOAT
+ * @key randomness
+ */
+
+/* Mother Of All (Collection) Tests
+ *
+ * Testing of collection classes is often spotty, because many tests
+ * need to be performed on many implementations, but the onus on
+ * writing the tests falls on the engineer introducing the new
+ * implementation.
+ *
+ * The idea of this mega-test is that:
+ *
+ * An engineer adding a new collection implementation could simply add
+ * their new implementation to a list of implementations in this
+ * test's main method.  Any general purpose Collection<Integer> or
+ * Map<Integer,Integer> class is appropriate.
+ *
+ * An engineer fixing a regression could add their regression test here and
+ * simultaneously test all other implementations.
+ */
+package test.java.util.Collection;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.*;
+import static java.util.Collections.*;
+import java.lang.reflect.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+// Android-added: run as TestNG test case.
+import org.testng.annotations.Test;
+
+public class MOAT {
+    // Collections under test must not be initialized to contain this value,
+    // and maps under test must not contain this value as a key.
+    // It's used as a sentinel for absent-element testing.
+    static final int ABSENT_VALUE = 778347983;
+
+    static final Integer[] integerArray;
+    static {
+        Integer[] ia = new Integer[20];
+        // fill with 1..20 inclusive
+        for (int i = 0; i < ia.length; i++) {
+            ia[i] = i + 1;
+        }
+        integerArray = ia;
+    }
+
+    // Android-changed: run as TestNG test case and do not accept arguments.
+    // public static void realMain(String[] args) {
+    @Test
+    public void realMain() {
+
+        testCollection(new NewAbstractCollection<Integer>());
+        testCollection(new NewAbstractSet<Integer>());
+        testCollection(new LinkedHashSet<Integer>());
+        testCollection(new HashSet<Integer>());
+        testCollection(new Vector<Integer>());
+        testCollection(new Vector<Integer>().subList(0,0));
+        testCollection(new ArrayDeque<Integer>());
+        testCollection(new ArrayList<Integer>());
+        testCollection(new ArrayList<Integer>().subList(0,0));
+        testCollection(new LinkedList<Integer>());
+        testCollection(new LinkedList<Integer>().subList(0,0));
+        testCollection(new TreeSet<Integer>());
+        testCollection(Collections.checkedList(new ArrayList<Integer>(), Integer.class));
+        testCollection(Collections.synchronizedList(new ArrayList<Integer>()));
+        testCollection(Collections.checkedSet(new HashSet<Integer>(), Integer.class));
+        testCollection(Collections.checkedSortedSet(new TreeSet<Integer>(), Integer.class));
+        testCollection(Collections.checkedNavigableSet(new TreeSet<Integer>(), Integer.class));
+        testCollection(Collections.synchronizedSet(new HashSet<Integer>()));
+        testCollection(Collections.synchronizedSortedSet(new TreeSet<Integer>()));
+        testCollection(Collections.synchronizedNavigableSet(new TreeSet<Integer>()));
+
+        testCollection(new CopyOnWriteArrayList<Integer>());
+        testCollection(new CopyOnWriteArrayList<Integer>().subList(0,0));
+        testCollection(new CopyOnWriteArraySet<Integer>());
+        testCollection(new PriorityQueue<Integer>());
+        testCollection(new PriorityBlockingQueue<Integer>());
+        testCollection(new ArrayBlockingQueue<Integer>(20));
+        testCollection(new LinkedBlockingQueue<Integer>(20));
+        testCollection(new LinkedBlockingDeque<Integer>(20));
+        testCollection(new ConcurrentLinkedDeque<Integer>());
+        testCollection(new ConcurrentLinkedQueue<Integer>());
+        testCollection(new LinkedTransferQueue<Integer>());
+        testCollection(new ConcurrentSkipListSet<Integer>());
+        testCollection(Arrays.asList(new Integer(42)));
+        testCollection(Arrays.asList(1,2,3));
+        testCollection(nCopies(25,1));
+        testImmutableList(nCopies(25,1));
+
+        testMap(new HashMap<Integer,Integer>());
+        testMap(new LinkedHashMap<Integer,Integer>());
+
+        // TODO: Add reliable support for WeakHashMap.
+        // This test is subject to very rare failures because the GC
+        // may remove unreferenced-keys from the map at any time.
+        // testMap(new WeakHashMap<Integer,Integer>());
+
+        testMap(new IdentityHashMap<Integer,Integer>());
+        testMap(new TreeMap<Integer,Integer>());
+        testMap(new Hashtable<Integer,Integer>());
+        testMap(new ConcurrentHashMap<Integer,Integer>(10, 0.5f));
+        testMap(new ConcurrentSkipListMap<Integer,Integer>());
+        testMap(Collections.checkedMap(new HashMap<Integer,Integer>(), Integer.class, Integer.class));
+        testMap(Collections.checkedSortedMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));
+        testMap(Collections.checkedNavigableMap(new TreeMap<Integer,Integer>(), Integer.class, Integer.class));
+        testMap(Collections.synchronizedMap(new HashMap<Integer,Integer>()));
+        testMap(Collections.synchronizedSortedMap(new TreeMap<Integer,Integer>()));
+        testMap(Collections.synchronizedNavigableMap(new TreeMap<Integer,Integer>()));
+
+        // Unmodifiable wrappers
+        testImmutableSet(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3))));
+        testImmutableList(unmodifiableList(Arrays.asList(1,2,3)));
+        testImmutableMap(unmodifiableMap(Collections.singletonMap(1,2)));
+        testCollMutatorsAlwaysThrow(unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3))));
+        testCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet()));
+        testEmptyCollMutatorsAlwaysThrow(unmodifiableSet(Collections.emptySet()));
+        testListMutatorsAlwaysThrow(unmodifiableList(Arrays.asList(1,2,3)));
+        testListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList()));
+        testEmptyListMutatorsAlwaysThrow(unmodifiableList(Collections.emptyList()));
+        testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.singletonMap(1,2)));
+        testMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap()));
+        testEmptyMapMutatorsAlwaysThrow(unmodifiableMap(Collections.emptyMap()));
+
+        // Empty collections
+        final List<Integer> emptyArray = Arrays.asList(new Integer[]{});
+        testCollection(emptyArray);
+        testEmptyList(emptyArray);
+        THROWS(IndexOutOfBoundsException.class, () -> emptyArray.set(0,1));
+        THROWS(UnsupportedOperationException.class, () -> emptyArray.add(0,1));
+
+        List<Integer> noOne = nCopies(0,1);
+        testCollection(noOne);
+        testEmptyList(noOne);
+        testImmutableList(noOne);
+
+        Set<Integer> emptySet = emptySet();
+        testCollection(emptySet);
+        testEmptySet(emptySet);
+        testEmptySet(EMPTY_SET);
+        testEmptySet(Collections.emptySet());
+        testEmptySet(Collections.emptySortedSet());
+        testEmptySet(Collections.emptyNavigableSet());
+        testImmutableSet(emptySet);
+
+        List<Integer> emptyList = emptyList();
+        testCollection(emptyList);
+        testEmptyList(emptyList);
+        testEmptyList(EMPTY_LIST);
+        testEmptyList(Collections.emptyList());
+        testImmutableList(emptyList);
+
+        Map<Integer,Integer> emptyMap = emptyMap();
+        testMap(emptyMap);
+        testEmptyMap(emptyMap);
+        testEmptyMap(EMPTY_MAP);
+        testEmptyMap(Collections.emptyMap());
+        testEmptyMap(Collections.emptySortedMap());
+        testEmptyMap(Collections.emptyNavigableMap());
+        testImmutableMap(emptyMap);
+        testImmutableMap(Collections.emptyMap());
+        testImmutableMap(Collections.emptySortedMap());
+        testImmutableMap(Collections.emptyNavigableMap());
+
+        // Singleton collections
+        Set<Integer> singletonSet = singleton(1);
+        equal(singletonSet.size(), 1);
+        testCollection(singletonSet);
+        testImmutableSet(singletonSet);
+
+        List<Integer> singletonList = singletonList(1);
+        equal(singletonList.size(), 1);
+        testCollection(singletonList);
+        testImmutableList(singletonList);
+        testImmutableList(singletonList.subList(0,1));
+        testImmutableList(singletonList.subList(0,1).subList(0,1));
+        testEmptyList(singletonList.subList(0,0));
+        testEmptyList(singletonList.subList(0,0).subList(0,0));
+
+        Map<Integer,Integer> singletonMap = singletonMap(1,2);
+        equal(singletonMap.size(), 1);
+        testMap(singletonMap);
+        testImmutableMap(singletonMap);
+
+        // Immutable List
+        testEmptyList(List.of());
+        testEmptyList(List.of().subList(0,0));
+        testListMutatorsAlwaysThrow(List.of());
+        testListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
+        testEmptyListMutatorsAlwaysThrow(List.of());
+        testEmptyListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
+        for (List<Integer> list : Arrays.asList(
+                List.<Integer>of(),
+                List.of(1),
+                List.of(1, 2),
+                List.of(1, 2, 3),
+                List.of(1, 2, 3, 4),
+                List.of(1, 2, 3, 4, 5),
+                List.of(1, 2, 3, 4, 5, 6),
+                List.of(1, 2, 3, 4, 5, 6, 7),
+                List.of(1, 2, 3, 4, 5, 6, 7, 8),
+                List.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
+                List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+                List.of(integerArray))) {
+            testCollection(list);
+            testImmutableList(list);
+            testListMutatorsAlwaysThrow(list);
+            if (list.size() >= 1) {
+                // test subLists
+                List<Integer> headList = list.subList(0, list.size() - 1);
+                List<Integer> tailList = list.subList(1, list.size());
+                testCollection(headList);
+                testCollection(tailList);
+                testImmutableList(headList);
+                testImmutableList(tailList);
+                testListMutatorsAlwaysThrow(headList);
+                testListMutatorsAlwaysThrow(tailList);
+            }
+        }
+
+        List<Integer> listCopy = List.copyOf(Arrays.asList(1, 2, 3));
+        testCollection(listCopy);
+        testImmutableList(listCopy);
+        testListMutatorsAlwaysThrow(listCopy);
+
+        List<Integer> listCollected = Stream.of(1, 2, 3).collect(Collectors.toUnmodifiableList());
+        equal(listCollected, List.of(1, 2, 3));
+        testCollection(listCollected);
+        testImmutableList(listCollected);
+        testListMutatorsAlwaysThrow(listCollected);
+
+        // List indexOf / lastIndexOf
+
+        // 0 element
+        System.out.println("testListIndexOf size 0");
+        testListIndexOf(-1, -1);
+
+        System.out.println("testListIndexOf size 1");
+        testListIndexOf(-1, -1, 0);
+        testListIndexOf(0, 0, 1);
+
+        System.out.println("testListIndexOf size 2");
+        testListIndexOf(-1, -1, 0, 0);
+        testListIndexOf(0, 0, 1, 0);
+        testListIndexOf(0, 1, 1, 1);
+        testListIndexOf(1, 1, 0, 1);
+
+
+        System.out.println("testListIndexOf size 3");
+        testListIndexOf(-1, -1, 0, 0, 0);
+        testListIndexOf(0, 0, 1, 0, 0);
+        testListIndexOf(0, 1, 1, 1, 0);
+        testListIndexOf(1, 2, 0, 1, 1);
+        testListIndexOf(2, 2, 0, 0, 1);
+
+        System.out.println("testListIndexOf size N");
+        testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0);
+        testListIndexOf(2, 6, 0, 0, 1, 0, 1, 0, 1);
+        testListIndexOf(4, 4, 0, 0, 0, 0, 1, 0, 0);
+        testListIndexOf(0, 6, 1, 1, 1, 1, 1, 1, 1);
+        testListIndexOf(0, 7, 1, 1, 1, 1, 1, 1, 1, 1);
+        testListIndexOf(0, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+        testListIndexOf(0, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+        testListIndexOf(0, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+        testListIndexOf(0, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+        testListIndexOf(0, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+        testListIndexOf(12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+        testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+        // Immutable Set
+        testEmptySet(Set.of());
+        testCollMutatorsAlwaysThrow(Set.of());
+        testEmptyCollMutatorsAlwaysThrow(Set.of());
+        for (Set<Integer> set : Arrays.asList(
+                Set.<Integer>of(),
+                Set.of(1),
+                Set.of(1, 2),
+                Set.of(1, 2, 3),
+                Set.of(1, 2, 3, 4),
+                Set.of(1, 2, 3, 4, 5),
+                Set.of(1, 2, 3, 4, 5, 6),
+                Set.of(1, 2, 3, 4, 5, 6, 7),
+                Set.of(1, 2, 3, 4, 5, 6, 7, 8),
+                Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9),
+                Set.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
+                Set.of(integerArray))) {
+            testCollection(set);
+            testImmutableSet(set);
+            testCollMutatorsAlwaysThrow(set);
+        }
+
+        Set<Integer> setCopy = Set.copyOf(Arrays.asList(1, 2, 3));
+        testCollection(setCopy);
+        testImmutableSet(setCopy);
+        testCollMutatorsAlwaysThrow(setCopy);
+
+        Set<Integer> setCollected = Stream.of(1, 1, 2, 3, 2, 3)
+                                          .collect(Collectors.toUnmodifiableSet());
+        equal(setCollected, Set.of(1, 2, 3));
+        testCollection(setCollected);
+        testImmutableSet(setCollected);
+        testCollMutatorsAlwaysThrow(setCollected);
+
+        // Immutable Map
+
+        @SuppressWarnings("unchecked")
+        Map.Entry<Integer,Integer>[] ea = (Map.Entry<Integer,Integer>[])new Map.Entry<?,?>[20];
+        for (int i = 0; i < ea.length; i++) {
+            ea[i] = Map.entry(i+1, i+101);
+        }
+
+        testEmptyMap(Map.of());
+        testMapMutatorsAlwaysThrow(Map.of());
+        testEmptyMapMutatorsAlwaysThrow(Map.of());
+        for (Map<Integer,Integer> map : Arrays.asList(
+                Map.<Integer,Integer>of(),
+                Map.of(1, 101),
+                Map.of(1, 101, 2, 202),
+                Map.of(1, 101, 2, 202, 3, 303),
+                Map.of(1, 101, 2, 202, 3, 303, 4, 404),
+                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505),
+                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606),
+                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707),
+                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808),
+                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909),
+                Map.of(1, 101, 2, 202, 3, 303, 4, 404, 5, 505, 6, 606, 7, 707, 8, 808, 9, 909, 10, 1010),
+                Map.ofEntries(ea))) {
+            testMap(map);
+            testImmutableMap(map);
+            testMapMutatorsAlwaysThrow(map);
+        }
+
+        Map<Integer,Integer> mapCopy = Map.copyOf(new HashMap<>(Map.of(1, 101, 2, 202, 3, 303)));
+        testMap(mapCopy);
+        testImmutableMap(mapCopy);
+        testMapMutatorsAlwaysThrow(mapCopy);
+
+        Map<Integer,Integer> mapCollected1 =
+            Stream.of(1, 2, 3)
+                  .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i));
+        equal(mapCollected1, Map.of(1, 101, 2, 202, 3, 303));
+        testMap(mapCollected1);
+        testImmutableMap(mapCollected1);
+        testMapMutatorsAlwaysThrow(mapCollected1);
+
+        try {
+            Stream.of(1, 1, 2, 3, 2, 3)
+                  .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i));
+            fail("duplicates should have thrown an exception");
+        } catch (IllegalStateException ise) {
+            pass();
+        }
+
+        Map<Integer,Integer> mapCollected2 =
+            Stream.of(1, 1, 2, 3, 2, 3)
+                  .collect(Collectors.toUnmodifiableMap(i -> i, i -> 101 * i, Integer::sum));
+        equal(mapCollected2, Map.of(1, 202, 2, 404, 3, 606));
+        testMap(mapCollected2);
+        testImmutableMap(mapCollected2);
+        testMapMutatorsAlwaysThrow(mapCollected2);
+    }
+
+    private static void checkContainsSelf(Collection<Integer> c) {
+        check(c.containsAll(c));
+        check(c.containsAll(Arrays.asList(c.toArray())));
+        check(c.containsAll(Arrays.asList(c.toArray(new Integer[0]))));
+    }
+
+    private static void checkContainsEmpty(Collection<Integer> c) {
+        check(c.containsAll(new ArrayList<Integer>()));
+    }
+
+    private static void checkUnique(Set<Integer> s) {
+        for (Integer i : s) {
+            int count = 0;
+            for (Integer j : s) {
+                if (Objects.equals(i,j))
+                    ++count;
+            }
+            check(count == 1);
+        }
+    }
+
+    private static <T> void testEmptyCollection(Collection<T> c) {
+        check(c.isEmpty());
+        equal(c.size(), 0);
+        equal(c.toString(),"[]");
+        equal(c.toArray().length, 0);
+        equal(c.toArray(new Object[0]).length, 0);
+        equal(c.toArray(Object[]::new).length, 0);
+        check(c.toArray(new Object[]{42})[0] == null);
+
+        Object[] a = new Object[1]; a[0] = Boolean.TRUE;
+        equal(c.toArray(a), a);
+        equal(a[0], null);
+        testEmptyIterator(c.iterator());
+    }
+
+    static <T> void testEmptyIterator(final Iterator<T> it) {
+        if (rnd.nextBoolean())
+            check(! it.hasNext());
+
+        THROWS(NoSuchElementException.class, () -> it.next());
+
+        try { it.remove(); }
+        catch (IllegalStateException ignored) { pass(); }
+        catch (UnsupportedOperationException ignored) { pass(); }
+        catch (Throwable t) { unexpected(t); }
+
+        if (rnd.nextBoolean())
+            check(! it.hasNext());
+    }
+
+    private static void testEmptyList(List<?> c) {
+        testEmptyCollection(c);
+        equal(c.hashCode(), 1);
+        equal2(c, Collections.<Integer>emptyList());
+    }
+
+    private static <T> void testEmptySet(Set<T> c) {
+        testEmptyCollection(c);
+        equal(c.hashCode(), 0);
+        equal2(c, Collections.<Integer>emptySet());
+        if (c instanceof NavigableSet<?>)
+            testEmptyIterator(((NavigableSet<T>)c).descendingIterator());
+    }
+
+    private static void testImmutableCollection(final Collection<Integer> c) {
+        THROWS(UnsupportedOperationException.class,
+               () -> c.add(99),
+               () -> c.addAll(singleton(99)));
+        if (! c.isEmpty()) {
+            final Integer first = c.iterator().next();
+            THROWS(UnsupportedOperationException.class,
+                   () -> c.clear(),
+                   () -> c.remove(first),
+                   () -> c.removeAll(singleton(first)),
+                   () -> c.retainAll(emptyList()));
+        }
+    }
+
+    private static void testImmutableSet(final Set<Integer> c) {
+        testImmutableCollection(c);
+    }
+
+    private static void testImmutableList(final List<Integer> c) {
+        testList(c);
+        testImmutableCollection(c);
+        THROWS(UnsupportedOperationException.class,
+               () -> c.set(0,42),
+               () -> c.add(0,42),
+               () -> c.addAll(0,singleton(86)));
+        if (! c.isEmpty())
+            THROWS(UnsupportedOperationException.class,
+                   () -> { Iterator<Integer> it = c.iterator();
+                           it.next();
+                           it.remove(); },
+                   () -> { ListIterator<Integer> it = c.listIterator();
+                           it.next();
+                           it.remove(); });
+    }
+
+    /**
+     * Test that calling a mutator always throws UOE, even if the mutator
+     * wouldn't actually do anything, given its arguments.
+     *
+     * @param c the collection instance to test
+     */
+    private static void testCollMutatorsAlwaysThrow(Collection<Integer> c) {
+        THROWS(UnsupportedOperationException.class,
+                () -> c.addAll(Collections.emptyList()),
+                () -> c.remove(ABSENT_VALUE),
+                () -> c.removeAll(Collections.emptyList()),
+                () -> c.removeIf(x -> false),
+                () -> c.retainAll(c));
+    }
+
+    /**
+     * Test that calling a mutator always throws UOE, even if the mutator
+     * wouldn't actually do anything on an empty collection.
+     *
+     * @param c the collection instance to test, must be empty
+     */
+    private static void testEmptyCollMutatorsAlwaysThrow(Collection<Integer> c) {
+        if (! c.isEmpty()) {
+            fail("collection is not empty");
+        }
+        THROWS(UnsupportedOperationException.class,
+                () -> c.clear());
+    }
+
+    /**
+     * As above, for a list.
+     *
+     * @param c the list instance to test
+     */
+    private static void testListMutatorsAlwaysThrow(List<Integer> c) {
+        testCollMutatorsAlwaysThrow(c);
+        THROWS(UnsupportedOperationException.class,
+                () -> c.addAll(0, Collections.emptyList()));
+    }
+
+    /**
+     * As above, for an empty list.
+     *
+     * @param c the list instance to test, must be empty
+     */
+    private static void testEmptyListMutatorsAlwaysThrow(List<Integer> c) {
+        if (! c.isEmpty()) {
+            fail("list is not empty");
+        }
+        testEmptyCollMutatorsAlwaysThrow(c);
+        THROWS(UnsupportedOperationException.class,
+                () -> c.replaceAll(x -> x),
+                () -> c.sort(null));
+    }
+
+    /**
+     * As above, for a map.
+     *
+     * @param m the map instance to test
+     */
+    private static void testMapMutatorsAlwaysThrow(Map<Integer,Integer> m) {
+        THROWS(UnsupportedOperationException.class,
+                () -> m.compute(ABSENT_VALUE, (k, v) -> null),
+                () -> m.computeIfAbsent(ABSENT_VALUE, k -> null),
+                () -> m.computeIfPresent(ABSENT_VALUE, (k, v) -> null),
+                () -> m.merge(ABSENT_VALUE, 0, (k, v) -> null),
+                () -> m.putAll(Collections.emptyMap()),
+                () -> m.remove(ABSENT_VALUE),
+                () -> m.remove(ABSENT_VALUE, 0),
+                () -> m.replace(ABSENT_VALUE, 0),
+                () -> m.replace(ABSENT_VALUE, 0, 1));
+    }
+
+    /**
+     * As above, for an empty map.
+     *
+     * @param map the map instance to test, must be empty
+     */
+    private static void testEmptyMapMutatorsAlwaysThrow(Map<Integer,Integer> m) {
+        if (! m.isEmpty()) {
+            fail("map is not empty");
+        }
+        THROWS(UnsupportedOperationException.class,
+                () -> m.clear(),
+                () -> m.replaceAll((k, v) -> v));
+    }
+
+    private static void clear(Collection<Integer> c) {
+        try { c.clear(); }
+        catch (Throwable t) { unexpected(t); }
+        testEmptyCollection(c);
+    }
+
+    private static <K,V> void testEmptyMap(final Map<K,V> m) {
+        check(m.isEmpty());
+        equal(m.size(), 0);
+        equal(m.toString(),"{}");
+        testEmptySet(m.keySet());
+        testEmptySet(m.entrySet());
+        testEmptyCollection(m.values());
+
+        try { check(! m.containsValue(null)); }
+        catch (NullPointerException ignored) { /* OK */ }
+        try { check(! m.containsKey(null)); }
+        catch (NullPointerException ignored) { /* OK */ }
+        check(! m.containsValue(1));
+        check(! m.containsKey(1));
+    }
+
+    private static void testImmutableMap(final Map<Integer,Integer> m) {
+        THROWS(UnsupportedOperationException.class,
+               () -> m.put(1,1),
+               () -> m.putAll(singletonMap(1,1)));
+        if (! m.isEmpty()) {
+            final Integer first = m.keySet().iterator().next();
+            THROWS(UnsupportedOperationException.class,
+                   () -> m.remove(first),
+                   () -> m.clear());
+            final Map.Entry<Integer,Integer> me
+                = m.entrySet().iterator().next();
+            Integer key = me.getKey();
+            Integer val = me.getValue();
+            THROWS(UnsupportedOperationException.class,
+                   () -> me.setValue(3));
+            equal(key, me.getKey());
+            equal(val, me.getValue());
+        }
+        testImmutableSet(m.keySet());
+        testImmutableCollection(m.values());
+        //testImmutableSet(m.entrySet());
+    }
+
+    private static void clear(Map<?,?> m) {
+        try { m.clear(); }
+        catch (Throwable t) { unexpected(t); }
+        testEmptyMap(m);
+    }
+
+    private static void oneElement(Collection<Integer> c) {
+        clear(c);
+        try {
+            check(c.add(-42));
+            equal(c.toString(), "[-42]");
+            if (c instanceof Set) check(! c.add(-42));
+        } catch (Throwable t) { unexpected(t); }
+        check(! c.isEmpty()); check(c.size() == 1);
+    }
+
+    private static boolean supportsAdd(Collection<Integer> c) {
+        try { check(c.add(ABSENT_VALUE)); }
+        catch (UnsupportedOperationException t) { return false; }
+        catch (Throwable t) { unexpected(t); }
+
+        try {
+            check(c.contains(ABSENT_VALUE));
+            check(c.remove(ABSENT_VALUE));
+        } catch (Throwable t) { unexpected(t); }
+        return true;
+    }
+
+    private static boolean supportsRemove(Collection<Integer> c) {
+        try { check(! c.remove(ABSENT_VALUE)); }
+        catch (UnsupportedOperationException t) { return false; }
+        catch (Throwable t) { unexpected(t); }
+        return true;
+    }
+
+    // 6260652: (coll) Arrays.asList(x).toArray().getClass()
+    //          should be Object[].class
+    // Fixed in jdk9, but not jdk8 ...
+    static final boolean needToWorkAround6260652 =
+        Arrays.asList("").toArray().getClass() != Object[].class;
+
+    private static void checkFunctionalInvariants(Collection<Integer> c) {
+        try {
+            checkContainsSelf(c);
+            checkContainsEmpty(c);
+            check(c.size() != 0 ^ c.isEmpty());
+            check(! c.contains(ABSENT_VALUE));
+
+            {
+                int size = 0;
+                for (Integer i : c) size++;
+                check(c.size() == size);
+            }
+
+            if (c instanceof Set) {
+                checkUnique((Set<Integer>)c);
+            }
+
+            check(c.toArray().length == c.size());
+            check(c.toArray().getClass() == Object[].class
+                  ||
+                  (needToWorkAround6260652 &&
+                   c.getClass().getName().equals("java.util.Arrays$ArrayList")));
+            for (int size : new int[]{0,1,c.size(), c.size()+1}) {
+                Integer[] a = c.toArray(new Integer[size]);
+                check((size > c.size()) || a.length == c.size());
+                int i = 0; for (Integer j : c) check(a[i++] == j);
+                check((size <= c.size()) || (a[c.size()] == null));
+                check(a.getClass() == Integer[].class);
+            }
+
+            {
+                Integer[] a = c.toArray(Integer[]::new);
+                equal(c.size(), a.length);
+                check(a.getClass() == Integer[].class);
+                check(Arrays.equals(c.toArray(new Integer[0]), a));
+            }
+
+            check(c.equals(c));
+            if (c instanceof Serializable) {
+                //System.out.printf("Serializing %s%n", c.getClass().getName());
+                try {
+                    Object clone = serialClone(c);
+                    equal(c instanceof Serializable,
+                          clone instanceof Serializable);
+                    equal(c instanceof RandomAccess,
+                          clone instanceof RandomAccess);
+                    if ((c instanceof List) || (c instanceof Set))
+                        equal(c, clone);
+                    else
+                        equal(new HashSet<Integer>(c),
+                              new HashSet<Integer>(serialClone(c)));
+                } catch (Error xxx) {
+                    if (! (xxx.getCause() instanceof NotSerializableException))
+                        throw xxx;
+                }
+            }
+        }
+        catch (Throwable t) { unexpected(t); }
+    }
+
+    //----------------------------------------------------------------
+    // If add(null) succeeds, contains(null) & remove(null) should succeed
+    //----------------------------------------------------------------
+    private static void testNullElement(Collection<Integer> c) {
+
+        try {
+            check(c.add(null));
+            if (c.size() == 1)
+                equal(c.toString(), "[null]");
+            try {
+                checkFunctionalInvariants(c);
+                check(c.contains(null));
+                check(c.remove(null));
+            }
+            catch (Throwable t) { unexpected(t); }
+        }
+        catch (NullPointerException e) { /* OK */ }
+        catch (Throwable t) { unexpected(t); }
+    }
+
+    //----------------------------------------------------------------
+    // If add("x") succeeds, contains("x") & remove("x") should succeed
+    //----------------------------------------------------------------
+    @SuppressWarnings("unchecked")
+    private static void testStringElement(Collection<Integer> c) {
+        Collection x = (Collection)c; // Make type-unsafe
+        try {
+            check(x.add("x"));
+            try {
+                check(x.contains("x"));
+                check(x.remove("x"));
+            } catch (Throwable t) { unexpected(t); }
+        }
+        catch (ClassCastException e) { /* OK */ }
+        catch (Throwable t) { unexpected(t); }
+    }
+
+    private static void testConcurrentCollection(Collection<Integer> c) {
+        try {
+            c.add(1);
+            Iterator<Integer> it = c.iterator();
+            check(it.hasNext());
+            clear(c);
+            check(it.next() instanceof Integer); // No CME
+            check(c.isEmpty());
+        }
+        catch (Throwable t) { unexpected(t); }
+    }
+
+    private static void testQueue(Queue<Integer> q) {
+        q.clear();
+        for (int i = 0; i < 5; i++) {
+            testQueueAddRemove(q, null);
+            testQueueAddRemove(q, 537);
+            q.add(i);
+        }
+        equal(q.size(), 5);
+        checkFunctionalInvariants(q);
+        q.poll();
+        equal(q.size(), 4);
+        checkFunctionalInvariants(q);
+        if ((q instanceof LinkedBlockingQueue)   ||
+            (q instanceof LinkedBlockingDeque)   ||
+            (q instanceof ConcurrentLinkedDeque) ||
+            (q instanceof ConcurrentLinkedQueue)) {
+            testQueueIteratorRemove(q);
+        }
+    }
+
+    private static void testQueueAddRemove(final Queue<Integer> q,
+                                           final Integer e) {
+        final List<Integer> originalContents = new ArrayList<>(q);
+        final boolean isEmpty = q.isEmpty();
+        final boolean isList = (q instanceof List);
+        final List asList = isList ? (List) q : null;
+        check(!q.contains(e));
+        try {
+            q.add(e);
+        } catch (NullPointerException npe) {
+            check(e == null);
+            return;                     // Null elements not supported
+        }
+        check(q.contains(e));
+        check(q.remove(e));
+        check(!q.contains(e));
+        equal(new ArrayList<Integer>(q), originalContents);
+
+        if (q instanceof Deque<?>) {
+            final Deque<Integer> deq = (Deque<Integer>) q;
+            final List<Integer> singleton = Collections.singletonList(e);
+
+            // insert, query, remove element at head
+            if (isEmpty) {
+                THROWS(NoSuchElementException.class,
+                       () -> deq.getFirst(),
+                       () -> deq.element(),
+                       () -> deq.iterator().next());
+                check(deq.peekFirst() == null);
+                check(deq.peek() == null);
+            } else {
+                check(deq.getFirst() != e);
+                check(deq.element() != e);
+                check(deq.iterator().next() != e);
+                check(deq.peekFirst() != e);
+                check(deq.peek() != e);
+            }
+            check(!deq.contains(e));
+            check(!deq.removeFirstOccurrence(e));
+            check(!deq.removeLastOccurrence(e));
+            if (isList) {
+                check(asList.indexOf(e) == -1);
+                check(asList.lastIndexOf(e) == -1);
+            }
+            switch (rnd.nextInt(isList ? 4 : 3)) {
+            case 0: deq.addFirst(e); break;
+            case 1: check(deq.offerFirst(e)); break;
+            case 2: deq.push(e); break;
+            case 3: asList.add(0, e); break;
+            default: throw new AssertionError();
+            }
+            check(deq.peekFirst() == e);
+            check(deq.getFirst() == e);
+            check(deq.element() == e);
+            check(deq.peek() == e);
+            check(deq.iterator().next() == e);
+            check(deq.contains(e));
+            if (isList) {
+                check(asList.get(0) == e);
+                check(asList.indexOf(e) == 0);
+                check(asList.lastIndexOf(e) == 0);
+                check(asList.subList(0, 1).equals(singleton));
+            }
+            switch (rnd.nextInt(isList ? 11 : 9)) {
+            case 0: check(deq.pollFirst() == e); break;
+            case 1: check(deq.removeFirst() == e); break;
+            case 2: check(deq.remove() == e); break;
+            case 3: check(deq.pop() == e); break;
+            case 4: check(deq.removeFirstOccurrence(e)); break;
+            case 5: check(deq.removeLastOccurrence(e)); break;
+            case 6: check(deq.remove(e)); break;
+            case 7: check(deq.removeAll(singleton)); break;
+            case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break;
+            case 9: asList.remove(0); break;
+            case 10: asList.subList(0, 1).clear(); break;
+            default: throw new AssertionError();
+            }
+            if (isEmpty) {
+                THROWS(NoSuchElementException.class,
+                       () -> deq.getFirst(),
+                       () -> deq.element(),
+                       () -> deq.iterator().next());
+                check(deq.peekFirst() == null);
+                check(deq.peek() == null);
+            } else {
+                check(deq.getFirst() != e);
+                check(deq.element() != e);
+                check(deq.iterator().next() != e);
+                check(deq.peekFirst() != e);
+                check(deq.peek() != e);
+            }
+            check(!deq.contains(e));
+            check(!deq.removeFirstOccurrence(e));
+            check(!deq.removeLastOccurrence(e));
+            if (isList) {
+                check(isEmpty || asList.get(0) != e);
+                check(asList.indexOf(e) == -1);
+                check(asList.lastIndexOf(e) == -1);
+            }
+            equal(new ArrayList<Integer>(deq), originalContents);
+
+            // insert, query, remove element at tail
+            if (isEmpty) {
+                check(deq.peekLast() == null);
+                THROWS(NoSuchElementException.class, () -> deq.getLast());
+            } else {
+                check(deq.peekLast() != e);
+                check(deq.getLast() != e);
+            }
+            switch (rnd.nextInt(isList ? 6 : 4)) {
+            case 0: deq.addLast(e); break;
+            case 1: check(deq.offerLast(e)); break;
+            case 2: check(deq.add(e)); break;
+            case 3: deq.addAll(singleton); break;
+            case 4: asList.addAll(deq.size(), singleton); break;
+            case 5: asList.add(deq.size(), e); break;
+            default: throw new AssertionError();
+            }
+            check(deq.peekLast() == e);
+            check(deq.getLast() == e);
+            check(deq.contains(e));
+            if (isList) {
+                ListIterator it = asList.listIterator(asList.size());
+                check(it.previous() == e);
+                check(asList.get(asList.size() - 1) == e);
+                check(asList.indexOf(e) == asList.size() - 1);
+                check(asList.lastIndexOf(e) == asList.size() - 1);
+                int size = asList.size();
+                check(asList.subList(size - 1, size).equals(singleton));
+            }
+            switch (rnd.nextInt(isList ? 8 : 6)) {
+            case 0: check(deq.pollLast() == e); break;
+            case 1: check(deq.removeLast() == e); break;
+            case 2: check(deq.removeFirstOccurrence(e)); break;
+            case 3: check(deq.removeLastOccurrence(e)); break;
+            case 4: check(deq.remove(e)); break;
+            case 5: check(deq.removeAll(singleton)); break;
+            case 6: asList.remove(asList.size() - 1); break;
+            case 7:
+                ListIterator it = asList.listIterator(asList.size());
+                it.previous();
+                it.remove();
+                break;
+            default: throw new AssertionError();
+            }
+            if (isEmpty) {
+                check(deq.peekLast() == null);
+                THROWS(NoSuchElementException.class, () -> deq.getLast());
+            } else {
+                check(deq.peekLast() != e);
+                check(deq.getLast() != e);
+            }
+            check(!deq.contains(e));
+            equal(new ArrayList<Integer>(deq), originalContents);
+
+            // Test operations on empty deque
+            switch (rnd.nextInt(isList ? 4 : 2)) {
+            case 0: deq.clear(); break;
+            case 1:
+                Iterator it = deq.iterator();
+                while (it.hasNext()) {
+                    it.next();
+                    it.remove();
+                }
+                break;
+            case 2: asList.subList(0, asList.size()).clear(); break;
+            case 3:
+                ListIterator lit = asList.listIterator(asList.size());
+                while (lit.hasPrevious()) {
+                    lit.previous();
+                    lit.remove();
+                }
+                break;
+            default: throw new AssertionError();
+            }
+            testEmptyCollection(deq);
+            check(!deq.iterator().hasNext());
+            if (isList) {
+                check(!asList.listIterator().hasPrevious());
+                THROWS(NoSuchElementException.class,
+                       () -> asList.listIterator().previous());
+            }
+            THROWS(NoSuchElementException.class,
+                   () -> deq.iterator().next(),
+                   () -> deq.element(),
+                   () -> deq.getFirst(),
+                   () -> deq.getLast(),
+                   () -> deq.pop(),
+                   () -> deq.remove(),
+                   () -> deq.removeFirst(),
+                   () -> deq.removeLast());
+
+            check(deq.poll() == null);
+            check(deq.pollFirst() == null);
+            check(deq.pollLast() == null);
+            check(deq.peek() == null);
+            check(deq.peekFirst() == null);
+            check(deq.peekLast() == null);
+            check(!deq.removeFirstOccurrence(e));
+            check(!deq.removeLastOccurrence(e));
+
+            check(deq.addAll(originalContents) == !isEmpty);
+            equal(new ArrayList<Integer>(deq), originalContents);
+            check(!deq.addAll(Collections.<Integer>emptyList()));
+            equal(new ArrayList<Integer>(deq), originalContents);
+        }
+    }
+
+    private static void testQueueIteratorRemove(Queue<Integer> q) {
+        System.err.printf("testQueueIteratorRemove %s%n",
+                          q.getClass().getSimpleName());
+        q.clear();
+        for (int i = 0; i < 5; i++)
+            q.add(i);
+        Iterator<Integer> it = q.iterator();
+        check(it.hasNext());
+        for (int i = 3; i >= 0; i--)
+            q.remove(i);
+        equal(it.next(), 0);
+        equal(it.next(), 4);
+
+        q.clear();
+        for (int i = 0; i < 5; i++)
+            q.add(i);
+        it = q.iterator();
+        equal(it.next(), 0);
+        check(it.hasNext());
+        for (int i = 1; i < 4; i++)
+            q.remove(i);
+        equal(it.next(), 1);
+        equal(it.next(), 4);
+    }
+
+    // for any array of integer values, check that the result of lastIndexOf(1)
+    // and indexOf(1) match assumptions for all types of List<Integer> we can
+    // construct
+    private static void testListIndexOf(final int index,
+                                        final int lastIndex,
+                                        final Integer ... values) {
+        if (values.length == 0) {
+            checkListIndexOf(emptyList(), index, lastIndex);
+        } else if (values.length == 1) {
+            checkListIndexOf(singletonList(values[0]), index, lastIndex);
+            checkListIndexOf(nCopies(25, values[0]), index, lastIndex == 0 ? 24 : -1);
+        }
+        List<Integer> l = List.of(values);
+        checkListIndexOf(l, index, lastIndex);
+        checkListIndexOf(Arrays.asList(values), index, lastIndex);
+        checkListIndexOf(new ArrayList(l), index, lastIndex);
+        checkListIndexOf(new LinkedList(l), index, lastIndex);
+        checkListIndexOf(new Vector(l), index, lastIndex);
+        checkListIndexOf(new CopyOnWriteArrayList(l), index, lastIndex);
+    }
+
+    private static void checkListIndexOf(final List<Integer> list,
+                                         final int index,
+                                         final int lastIndex) {
+        String msg = list.getClass().toString();
+        equal(list.indexOf(1), index, msg);
+        equal(list.lastIndexOf(1), lastIndex, msg);
+        equal(list.subList(0, list.size()).indexOf(1), index, msg);
+        equal(list.subList(0, list.size()).lastIndexOf(1), lastIndex, msg);
+    }
+
+    private static void testList(final List<Integer> l) {
+        //----------------------------------------------------------------
+        // 4802633: (coll) AbstractList.addAll(-1,emptyCollection)
+        // doesn't throw IndexOutOfBoundsException
+        //----------------------------------------------------------------
+        try {
+            l.addAll(-1, Collections.<Integer>emptyList());
+            fail("Expected IndexOutOfBoundsException not thrown");
+        }
+        catch (UnsupportedOperationException ignored) {/* OK */}
+        catch (IndexOutOfBoundsException ignored) {/* OK */}
+        catch (Throwable t) { unexpected(t); }
+
+//      equal(l instanceof Serializable,
+//            l.subList(0,0) instanceof Serializable);
+        if (l.subList(0,0) instanceof Serializable)
+            check(l instanceof Serializable);
+
+        equal(l instanceof RandomAccess,
+              l.subList(0,0) instanceof RandomAccess);
+
+        l.iterator();
+        l.listIterator();
+        l.listIterator(0);
+        l.listIterator(l.size());
+        THROWS(IndexOutOfBoundsException.class,
+               () -> l.listIterator(-1),
+               () -> l.listIterator(l.size() + 1));
+
+        if (l instanceof AbstractList) {
+            try {
+                int size = l.size();
+                AbstractList<Integer> abList = (AbstractList<Integer>) l;
+                Method m = AbstractList.class.getDeclaredMethod("removeRange", new Class[] { int.class, int.class });
+                m.setAccessible(true);
+                m.invoke(abList, new Object[] { 0, 0 });
+                m.invoke(abList, new Object[] { size, size });
+                equal(size, l.size());
+            }
+            catch (UnsupportedOperationException ignored) {/* OK */}
+            catch (Throwable t) { unexpected(t); }
+        }
+    }
+
+    private static void testCollection(Collection<Integer> c) {
+        try { testCollection1(c); }
+        catch (Throwable t) { unexpected(t); }
+    }
+
+    private static void testCollection1(Collection<Integer> c) {
+
+        System.out.println("\n==> " + c.getClass().getName());
+
+        checkFunctionalInvariants(c);
+
+        if (! supportsAdd(c)) return;
+        //System.out.println("add() supported");
+
+        if (c instanceof NavigableSet) {
+            System.out.println("NavigableSet tests...");
+
+            NavigableSet<Integer> ns = (NavigableSet<Integer>)c;
+            testNavigableSet(ns);
+            testNavigableSet(ns.headSet(6, false));
+            testNavigableSet(ns.headSet(5, true));
+            testNavigableSet(ns.tailSet(0, false));
+            testNavigableSet(ns.tailSet(1, true));
+            testNavigableSet(ns.subSet(0, false, 5, true));
+            testNavigableSet(ns.subSet(1, true, 6, false));
+        }
+
+        if (c instanceof Queue)
+            testQueue((Queue<Integer>)c);
+
+        if (c instanceof List)
+            testList((List<Integer>)c);
+
+        check(supportsRemove(c));
+
+        try {
+            oneElement(c);
+            checkFunctionalInvariants(c);
+        }
+        catch (Throwable t) { unexpected(t); }
+
+        clear(c);      testNullElement(c);
+        oneElement(c); testNullElement(c);
+
+        clear(c);      testStringElement(c);
+        oneElement(c); testStringElement(c);
+
+        if (c.getClass().getName().matches(".*concurrent.*"))
+            testConcurrentCollection(c);
+
+        //----------------------------------------------------------------
+        // The "all" operations should throw NPE when passed null
+        //----------------------------------------------------------------
+        {
+            clear(c);
+            try {
+                c.removeAll(null);
+                fail("Expected NullPointerException");
+            }
+            catch (NullPointerException e) { pass(); }
+            catch (Throwable t) { unexpected(t); }
+
+            oneElement(c);
+            try {
+                c.removeAll(null);
+                fail("Expected NullPointerException");
+            }
+            catch (NullPointerException e) { pass(); }
+            catch (Throwable t) { unexpected(t); }
+
+            clear(c);
+            try {
+                c.retainAll(null);
+                fail("Expected NullPointerException");
+            }
+            catch (NullPointerException e) { pass(); }
+            catch (Throwable t) { unexpected(t); }
+
+            oneElement(c);
+            try {
+                c.retainAll(null);
+                fail("Expected NullPointerException");
+            }
+            catch (NullPointerException e) { pass(); }
+            catch (Throwable t) { unexpected(t); }
+
+            oneElement(c);
+            try {
+                c.addAll(null);
+                fail("Expected NullPointerException");
+            }
+            catch (NullPointerException e) { pass(); }
+            catch (Throwable t) { unexpected(t); }
+
+            oneElement(c);
+            try {
+                c.containsAll(null);
+                fail("Expected NullPointerException");
+            }
+            catch (NullPointerException e) { pass(); }
+            catch (Throwable t) { unexpected(t); }
+        }
+    }
+
+    //----------------------------------------------------------------
+    // Map
+    //----------------------------------------------------------------
+    private static void checkFunctionalInvariants(Map<Integer,Integer> m) {
+        check(m.keySet().size() == m.entrySet().size());
+        check(m.keySet().size() == m.size());
+        checkFunctionalInvariants(m.keySet());
+        checkFunctionalInvariants(m.values());
+        check(m.size() != 0 ^ m.isEmpty());
+        check(! m.containsKey(ABSENT_VALUE));
+
+        if (m instanceof Serializable) {
+            //System.out.printf("Serializing %s%n", m.getClass().getName());
+            try {
+                Object clone = serialClone(m);
+                equal(m instanceof Serializable,
+                      clone instanceof Serializable);
+                equal(m, clone);
+            } catch (Error xxx) {
+                if (! (xxx.getCause() instanceof NotSerializableException))
+                    throw xxx;
+            }
+        }
+    }
+
+    private static void testMap(Map<Integer,Integer> m) {
+        System.out.println("\n==> " + m.getClass().getName());
+
+        if (m instanceof ConcurrentMap)
+            testConcurrentMap((ConcurrentMap<Integer,Integer>) m);
+
+        if (m instanceof NavigableMap) {
+            System.out.println("NavigableMap tests...");
+
+            NavigableMap<Integer,Integer> nm =
+                (NavigableMap<Integer,Integer>) m;
+            testNavigableMapRemovers(nm);
+            testNavigableMap(nm);
+            testNavigableMap(nm.headMap(6, false));
+            testNavigableMap(nm.headMap(5, true));
+            testNavigableMap(nm.tailMap(0, false));
+            testNavigableMap(nm.tailMap(1, true));
+            testNavigableMap(nm.subMap(1, true, 6, false));
+            testNavigableMap(nm.subMap(0, false, 5, true));
+        }
+
+        checkFunctionalInvariants(m);
+
+        if (supportsClear(m)) {
+            try { clear(m); }
+            catch (Throwable t) { unexpected(t); }
+        }
+
+        if (supportsPut(m)) {
+            try {
+                check(m.put(3333, 77777) == null);
+                check(m.put(9134, 74982) == null);
+                check(m.get(9134) == 74982);
+                check(m.put(9134, 1382) == 74982);
+                check(m.get(9134) == 1382);
+                check(m.size() == 2);
+                checkFunctionalInvariants(m);
+                checkNPEConsistency(m);
+            }
+            catch (Throwable t) { unexpected(t); }
+        }
+    }
+
+    private static boolean supportsPut(Map<Integer,Integer> m) {
+        // We're asking for .equals(...) semantics
+        if (m instanceof IdentityHashMap) return false;
+
+        try { check(m.put(ABSENT_VALUE,12735) == null); }
+        catch (UnsupportedOperationException t) { return false; }
+        catch (Throwable t) { unexpected(t); }
+
+        try {
+            check(m.containsKey(ABSENT_VALUE));
+            check(m.remove(ABSENT_VALUE) != null);
+        } catch (Throwable t) { unexpected(t); }
+        return true;
+    }
+
+    private static boolean supportsClear(Map<?,?> m) {
+        try { m.clear(); }
+        catch (UnsupportedOperationException t) { return false; }
+        catch (Throwable t) { unexpected(t); }
+        return true;
+    }
+
+    //----------------------------------------------------------------
+    // ConcurrentMap
+    //----------------------------------------------------------------
+    private static void testConcurrentMap(ConcurrentMap<Integer,Integer> m) {
+        System.out.println("ConcurrentMap tests...");
+
+        try {
+            clear(m);
+
+            check(m.putIfAbsent(18357,7346) == null);
+            check(m.containsKey(18357));
+            check(m.putIfAbsent(18357,8263) == 7346);
+            try { m.putIfAbsent(18357,null); fail("NPE"); }
+            catch (NullPointerException t) { }
+            check(m.containsKey(18357));
+
+            check(! m.replace(18357,8888,7777));
+            check(m.containsKey(18357));
+            try { m.replace(18357,null,7777); fail("NPE"); }
+            catch (NullPointerException t) { }
+            check(m.containsKey(18357));
+            check(m.get(18357) == 7346);
+            check(m.replace(18357,7346,5555));
+            check(m.replace(18357,5555,7346));
+            check(m.get(18357) == 7346);
+
+            check(m.replace(92347,7834) == null);
+            try { m.replace(18357,null); fail("NPE"); }
+            catch (NullPointerException t) { }
+            check(m.replace(18357,7346) == 7346);
+            check(m.replace(18357,5555) == 7346);
+            check(m.get(18357) == 5555);
+            check(m.replace(18357,7346) == 5555);
+            check(m.get(18357) == 7346);
+
+            check(! m.remove(18357,9999));
+            check(m.get(18357) == 7346);
+            check(m.containsKey(18357));
+            check(! m.remove(18357,null)); // 6272521
+            check(m.get(18357) == 7346);
+            check(m.remove(18357,7346));
+            check(m.get(18357) == null);
+            check(! m.containsKey(18357));
+            check(m.isEmpty());
+
+            m.putIfAbsent(1,2);
+            check(m.size() == 1);
+            check(! m.remove(1,null));
+            check(! m.remove(1,null));
+            check(! m.remove(1,1));
+            check(m.remove(1,2));
+            check(m.isEmpty());
+
+            testEmptyMap(m);
+        }
+        catch (Throwable t) { unexpected(t); }
+    }
+
+    private static void throwsConsistently(Class<? extends Throwable> k,
+                                           Iterable<Fun> fs) {
+        List<Class<? extends Throwable>> threw = new ArrayList<>();
+        for (Fun f : fs)
+            try { f.f(); threw.add(null); }
+            catch (Throwable t) {
+                check(k.isAssignableFrom(t.getClass()));
+                threw.add(t.getClass());
+            }
+        if (new HashSet<Object>(threw).size() != 1)
+            fail(threw.toString());
+    }
+
+    private static <T> void checkNPEConsistency(final Map<T,Integer> m) {
+        m.clear();
+        final ConcurrentMap<T,Integer> cm = (m instanceof ConcurrentMap)
+            ? (ConcurrentMap<T,Integer>) m
+            : null;
+        List<Fun> fs = new ArrayList<>();
+        fs.add(() -> check(! m.containsKey(null)));
+        fs.add(() -> equal(m.remove(null), null));
+        fs.add(() -> equal(m.get(null), null));
+        if (cm != null)
+            fs.add(() -> check(! cm.remove(null,null)));
+        throwsConsistently(NullPointerException.class, fs);
+
+        fs.clear();
+        final Map<T,Integer> sm = singletonMap(null,1);
+        fs.add(() -> { equal(m.put(null,1), null); m.clear();});
+        fs.add(() -> { m.putAll(sm); m.clear();});
+        if (cm != null) {
+            fs.add(() -> check(! cm.remove(null,null)));
+            fs.add(() -> equal(cm.putIfAbsent(null,1), 1));
+            fs.add(() -> equal(cm.replace(null,1), null));
+            fs.add(() -> equal(cm.replace(null,1, 1), 1));
+        }
+        throwsConsistently(NullPointerException.class, fs);
+    }
+
+    //----------------------------------------------------------------
+    // NavigableMap
+    //----------------------------------------------------------------
+    private static void
+        checkNavigableMapKeys(NavigableMap<Integer,Integer> m,
+                              Integer i,
+                              Integer lower,
+                              Integer floor,
+                              Integer ceiling,
+                              Integer higher) {
+        equal(m.lowerKey(i),   lower);
+        equal(m.floorKey(i),   floor);
+        equal(m.ceilingKey(i), ceiling);
+        equal(m.higherKey(i),  higher);
+    }
+
+    private static void
+        checkNavigableSetKeys(NavigableSet<Integer> m,
+                              Integer i,
+                              Integer lower,
+                              Integer floor,
+                              Integer ceiling,
+                              Integer higher) {
+        equal(m.lower(i),   lower);
+        equal(m.floor(i),   floor);
+        equal(m.ceiling(i), ceiling);
+        equal(m.higher(i),  higher);
+    }
+
+    static final Random rnd = new Random();
+    static void equalNext(final Iterator<?> it, Object expected) {
+        if (rnd.nextBoolean())
+            check(it.hasNext());
+        equal(it.next(), expected);
+    }
+
+    static void equalMaps(Map m1, Map m2) {
+        equal(m1, m2);
+        equal(m2, m1);
+        equal(m1.size(), m2.size());
+        equal(m1.isEmpty(), m2.isEmpty());
+        equal(m1.toString(), m2.toString());
+        check(Arrays.equals(m1.entrySet().toArray(), m2.entrySet().toArray()));
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    static void testNavigableMapRemovers(NavigableMap m)
+    {
+        final Map emptyMap = new HashMap();
+
+        final Map singletonMap = new HashMap();
+        singletonMap.put(1, 2);
+
+        abstract class NavigableMapView {
+            abstract NavigableMap view(NavigableMap m);
+        }
+
+        NavigableMapView[] views = {
+            new NavigableMapView() { NavigableMap view(NavigableMap m) {
+                return m; }},
+            new NavigableMapView() { NavigableMap view(NavigableMap m) {
+                return m.headMap(99, true); }},
+            new NavigableMapView() { NavigableMap view(NavigableMap m) {
+                return m.tailMap(-99, false); }},
+            new NavigableMapView() { NavigableMap view(NavigableMap m) {
+                return m.subMap(-99, true, 99, false); }},
+        };
+
+        abstract class Remover {
+            abstract void remove(NavigableMap m, Object k, Object v);
+        }
+
+        Remover[] removers = {
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                equal(m.remove(k), v); }},
+
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                equal(m.descendingMap().remove(k), v); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                equal(m.descendingMap().headMap(-86, false).remove(k), v); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                equal(m.descendingMap().tailMap(86, true).remove(k), v); }},
+
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                equal(m.headMap(86, true).remove(k), v); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                equal(m.tailMap(-86, true).remove(k), v); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                equal(m.subMap(-86, false, 86, true).remove(k), v); }},
+
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.keySet().remove(k)); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.navigableKeySet().remove(k)); }},
+
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.navigableKeySet().headSet(86, true).remove(k)); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.navigableKeySet().tailSet(-86, false).remove(k)); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.navigableKeySet().subSet(-86, true, 86, false)
+                      .remove(k)); }},
+
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.descendingKeySet().headSet(-86, false).remove(k)); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.descendingKeySet().tailSet(86, true).remove(k)); }},
+            new Remover() { void remove(NavigableMap m, Object k, Object v) {
+                check(m.descendingKeySet().subSet(86, true, -86, false)
+                      .remove(k)); }},
+        };
+
+        for (NavigableMapView view : views) {
+            for (Remover remover : removers) {
+                try {
+                    m.clear();
+                    equalMaps(m, emptyMap);
+                    equal(m.put(1, 2), null);
+                    equalMaps(m, singletonMap);
+                    NavigableMap v = view.view(m);
+                    remover.remove(v, 1, 2);
+                    equalMaps(m, emptyMap);
+                } catch (Throwable t) { unexpected(t); }
+            }
+        }
+    }
+
+    private static void testNavigableMap(NavigableMap<Integer,Integer> m)
+    {
+        clear(m);
+        checkNavigableMapKeys(m, 1, null, null, null, null);
+
+        equal(m.put(1, 2), null);
+        equal(m.put(3, 4), null);
+        equal(m.put(5, 9), null);
+
+        equal(m.put(1, 2), 2);
+        equal(m.put(3, 4), 4);
+        equal(m.put(5, 6), 9);
+
+        checkNavigableMapKeys(m, 0, null, null,    1,    1);
+        checkNavigableMapKeys(m, 1, null,    1,    1,    3);
+        checkNavigableMapKeys(m, 2,    1,    1,    3,    3);
+        checkNavigableMapKeys(m, 3,    1,    3,    3,    5);
+        checkNavigableMapKeys(m, 5,    3,    5,    5, null);
+        checkNavigableMapKeys(m, 6,    5,    5, null, null);
+
+        for (final Iterator<Integer> it :
+                 (Iterator<Integer>[])
+                 new Iterator<?>[] {
+                     m.descendingKeySet().iterator(),
+                     m.navigableKeySet().descendingIterator()}) {
+            equalNext(it, 5);
+            equalNext(it, 3);
+            equalNext(it, 1);
+            check(! it.hasNext());
+            THROWS(NoSuchElementException.class, () -> it.next());
+        }
+
+        {
+            final Iterator<Map.Entry<Integer,Integer>> it
+                = m.descendingMap().entrySet().iterator();
+            check(it.hasNext()); equal(it.next().getKey(), 5);
+            check(it.hasNext()); equal(it.next().getKey(), 3);
+            check(it.hasNext()); equal(it.next().getKey(), 1);
+            check(! it.hasNext());
+            THROWS(NoSuchElementException.class, () -> it.next());
+        }
+
+        prepMapForDescItrTests(m);
+        checkDescItrRmFirst(m.keySet(), m.navigableKeySet().descendingIterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmMid(m.keySet(), m.navigableKeySet().descendingIterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmLast(m.keySet(), m.navigableKeySet().descendingIterator());
+
+        prepMapForDescItrTests(m);
+        checkDescItrRmFirst(m.keySet(), m.descendingMap().keySet().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmMid(m.keySet(), m.descendingMap().keySet().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmLast(m.keySet(), m.descendingMap().keySet().iterator());
+
+        prepMapForDescItrTests(m);
+        checkDescItrRmFirst(m.keySet(), m.descendingKeySet().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmMid(m.keySet(), m.descendingKeySet().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmLast(m.keySet(), m.descendingKeySet().iterator());
+
+        prepMapForDescItrTests(m);
+        checkDescItrRmFirst(m.values(), m.descendingMap().values().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmMid(m.values(), m.descendingMap().values().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmLast(m.values(), m.descendingMap().values().iterator());
+
+        prepMapForDescItrTests(m);
+        checkDescItrRmFirst((Collection)m.entrySet(),
+                            m.descendingMap().entrySet().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmMid((Collection)m.entrySet(),
+                          m.descendingMap().entrySet().iterator());
+        prepMapForDescItrTests(m);
+        checkDescItrRmLast((Collection)m.entrySet(),
+                           m.descendingMap().entrySet().iterator());
+    }
+
+    private static void testNavigableSet(NavigableSet<Integer> s) {
+        clear(s);
+        checkNavigableSetKeys(s, 1, null, null, null, null);
+
+        check(s.add(1));
+        check(s.add(3));
+        check(s.add(5));
+
+        check(! s.add(1));
+        check(! s.add(3));
+        check(! s.add(5));
+
+        checkNavigableSetKeys(s, 0, null, null,    1,    1);
+        checkNavigableSetKeys(s, 1, null,    1,    1,    3);
+        checkNavigableSetKeys(s, 2,    1,    1,    3,    3);
+        checkNavigableSetKeys(s, 3,    1,    3,    3,    5);
+        checkNavigableSetKeys(s, 5,    3,    5,    5, null);
+        checkNavigableSetKeys(s, 6,    5,    5, null, null);
+
+        for (final Iterator<Integer> it :
+                 (Iterator<Integer>[])
+                 new Iterator<?>[] {
+                     s.descendingIterator(),
+                     s.descendingSet().iterator()}) {
+            equalNext(it, 5);
+            equalNext(it, 3);
+            equalNext(it, 1);
+            check(! it.hasNext());
+            THROWS(NoSuchElementException.class, () -> it.next());
+        }
+
+        prepSetForDescItrTests(s);
+        checkDescItrRmFirst(s, s.descendingIterator());
+        prepSetForDescItrTests(s);
+        checkDescItrRmMid(s, s.descendingIterator());
+        prepSetForDescItrTests(s);
+        checkDescItrRmLast(s, s.descendingIterator());
+
+        prepSetForDescItrTests(s);
+        checkDescItrRmFirst(s, s.descendingSet().iterator());
+        prepSetForDescItrTests(s);
+        checkDescItrRmMid(s, s.descendingSet().iterator());
+        prepSetForDescItrTests(s);
+        checkDescItrRmLast(s, s.descendingSet().iterator());
+    }
+
+    private static void prepSetForDescItrTests(Set s) {
+        clear(s);
+        check(s.add(1));
+        check(s.add(3));
+        check(s.add(5));
+    }
+
+    private static void prepMapForDescItrTests(Map m) {
+        clear(m);
+        equal(m.put(1, 2), null);
+        equal(m.put(3, 4), null);
+        equal(m.put(5, 9), null);
+    }
+
+    //--------------------------------------------------------------------
+    // Check behavior of descending iterator when first element is removed
+    //--------------------------------------------------------------------
+    private static <T> void checkDescItrRmFirst(Collection<T> ascColl,
+                                                Iterator<T> descItr) {
+        T[] expected = (T[]) ascColl.toArray();
+        int idx = expected.length -1;
+
+        equalNext(descItr, expected[idx--]);
+        descItr.remove();
+        while (idx >= 0 && descItr.hasNext()) {
+            equalNext(descItr, expected[idx--]);
+        }
+        equal(descItr.hasNext(), false);
+        equal(idx, -1);
+    }
+
+    //-----------------------------------------------------------------------
+    // Check behavior of descending iterator when a middle element is removed
+    //-----------------------------------------------------------------------
+    private static <T> void checkDescItrRmMid(Collection<T> ascColl,
+                                              Iterator<T> descItr) {
+        T[] expected = (T[]) ascColl.toArray();
+        int idx = expected.length -1;
+
+        while (idx >= expected.length / 2) {
+            equalNext(descItr, expected[idx--]);
+        }
+        descItr.remove();
+        while (idx >= 0 && descItr.hasNext()) {
+            equalNext(descItr, expected[idx--]);
+        }
+        equal(descItr.hasNext(), false);
+        equal(idx, -1);
+    }
+
+    //-----------------------------------------------------------------------
+    // Check behavior of descending iterator when the last element is removed
+    //-----------------------------------------------------------------------
+    private static <T> void checkDescItrRmLast(Collection<T> ascColl,
+                                               Iterator<T> descItr) {
+        T[] expected = (T[]) ascColl.toArray();
+        int idx = expected.length -1;
+
+        while (idx >= 0 && descItr.hasNext()) {
+            equalNext(descItr, expected[idx--]);
+        }
+        equal(idx, -1);
+        equal(descItr.hasNext(), false);
+        descItr.remove();
+        equal(ascColl.contains(expected[0]), false);
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    static volatile int passed = 0, failed = 0;
+    static void pass() { passed++; }
+    static void fail() { failed++; Thread.dumpStack(); }
+    static void fail(String msg) { System.out.println(msg); fail(); }
+    static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
+    static void check(boolean cond) { if (cond) pass(); else fail(); }
+    static void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else {System.out.println(x + " not equal to " + y); fail();}}
+    static void equal(Object x, Object y, String msg) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else {System.out.println(x + " not equal to " + y + " : " + msg); fail();}}
+    static void equal2(Object x, Object y) {equal(x, y); equal(y, x);}
+    // BEGIN Android-removed: we do not run tests via main.
+    /*
+    public static void main(String[] args) throws Throwable {
+        try { realMain(args); } catch (Throwable t) { unexpected(t); }
+
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new Exception("Some tests failed");
+    }
+    */
+    // END Android-removed: we do not run tests via main.
+    interface Fun {void f() throws Throwable;}
+    private static void THROWS(Class<? extends Throwable> k, Fun... fs) {
+        for (Fun f : fs)
+            try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
+            catch (Throwable t) {
+                if (k.isAssignableFrom(t.getClass())) pass();
+                else unexpected(t);}}
+    static byte[] serializedForm(Object obj) {
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            new ObjectOutputStream(baos).writeObject(obj);
+            return baos.toByteArray();
+        } catch (IOException e) { throw new Error(e); }}
+    static Object readObject(byte[] bytes)
+        throws IOException, ClassNotFoundException {
+        InputStream is = new ByteArrayInputStream(bytes);
+        return new ObjectInputStream(is).readObject();}
+    @SuppressWarnings("unchecked")
+    static <T> T serialClone(T obj) {
+        try { return (T) readObject(serializedForm(obj)); }
+        catch (Exception e) { throw new Error(e); }}
+    private static class NewAbstractCollection<E> extends AbstractCollection<E> {
+        ArrayList<E> list = new ArrayList<>();
+        public boolean remove(Object obj) {
+            return list.remove(obj);
+        }
+        public boolean add(E e) {
+            return list.add(e);
+        }
+        public Iterator<E> iterator() {
+            return list.iterator();
+        }
+        public int size() {
+            return list.size();
+        }
+    }
+    private static class NewAbstractSet<E> extends AbstractSet<E> {
+        HashSet<E> set = new HashSet<>();
+        public boolean remove(Object obj) {
+            return set.remove(obj);
+        }
+        public boolean add(E e) {
+            return set.add(e);
+        }
+        public Iterator<E> iterator() {
+            return set.iterator();
+        }
+        public int size() {
+            return set.size();
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/util/Collection/SetFactories.java b/ojluni/src/test/java/util/Collection/SetFactories.java
index 653f419..9da7377 100644
--- a/ojluni/src/test/java/util/Collection/SetFactories.java
+++ b/ojluni/src/test/java/util/Collection/SetFactories.java
@@ -22,17 +22,30 @@
  */
 package test.java.util.Collection;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 import static org.testng.Assert.assertEquals;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotEquals;
 import static org.testng.Assert.assertNotSame;
 import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 /*
  * @test
@@ -41,9 +54,246 @@
  * @run testng SetFactories
  */
 
-@Test
 public class SetFactories {
 
+    static final int NUM_STRINGS = 20; // should be larger than the largest fixed-arg overload
+    static final String[] stringArray;
+    static {
+        String[] sa = new String[NUM_STRINGS];
+        for (int i = 0; i < NUM_STRINGS; i++) {
+            sa[i] = String.valueOf((char)('a' + i));
+        }
+        stringArray = sa;
+    }
+
+    static Object[] a(Set<String> act, Set<String> exp) {
+        return new Object[] { act, exp };
+    }
+
+    static Set<String> hashSetOf(String... args) {
+        return new HashSet<>(Arrays.asList(args));
+    }
+
+    @DataProvider(name="empty")
+    public Iterator<Object[]> empty() {
+        return Collections.singletonList(
+            // actual, expected
+            a(Set.of(), Collections.emptySet())
+        ).iterator();
+    }
+
+    @DataProvider(name="nonempty")
+    public Iterator<Object[]> nonempty() {
+        return Arrays.asList(
+            // actual, expected
+            a(   Set.of("a"),
+              hashSetOf("a")),
+            a(   Set.of("a", "b"),
+              hashSetOf("a", "b")),
+            a(   Set.of("a", "b", "c"),
+              hashSetOf("a", "b", "c")),
+            a(   Set.of("a", "b", "c", "d"),
+              hashSetOf("a", "b", "c", "d")),
+            a(   Set.of("a", "b", "c", "d", "e"),
+              hashSetOf("a", "b", "c", "d", "e")),
+            a(   Set.of("a", "b", "c", "d", "e", "f"),
+              hashSetOf("a", "b", "c", "d", "e", "f")),
+            a(   Set.of("a", "b", "c", "d", "e", "f", "g"),
+              hashSetOf("a", "b", "c", "d", "e", "f", "g")),
+            a(   Set.of("a", "b", "c", "d", "e", "f", "g", "h"),
+              hashSetOf("a", "b", "c", "d", "e", "f", "g", "h")),
+            a(   Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i"),
+              hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i")),
+            a(   Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
+              hashSetOf("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")),
+            a(   Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j"),
+                 Set.of("j", "i", "h", "g", "f", "e", "d", "c", "b", "a")),
+            a(   Set.of(stringArray),
+              hashSetOf(stringArray))
+        ).iterator();
+    }
+
+    @DataProvider(name="all")
+    public Iterator<Object[]> all() {
+        List<Object[]> all = new ArrayList<>();
+        empty().forEachRemaining(all::add);
+        nonempty().forEachRemaining(all::add);
+        return all.iterator();
+    }
+
+    @Test(dataProvider="all", expectedExceptions=UnsupportedOperationException.class)
+    public void cannotAdd(Set<String> act, Set<String> exp) {
+        act.add("x");
+    }
+
+    @Test(dataProvider="nonempty", expectedExceptions=UnsupportedOperationException.class)
+    public void cannotRemove(Set<String> act, Set<String> exp) {
+        act.remove(act.iterator().next());
+    }
+
+    @Test(dataProvider="all")
+    public void contentsMatch(Set<String> act, Set<String> exp) {
+        assertEquals(act, exp);
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed2() {
+        Set<String> set = Set.of("a", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed3() {
+        Set<String> set = Set.of("a", "b", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed4() {
+        Set<String> set = Set.of("a", "b", "c", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed5() {
+        Set<String> set = Set.of("a", "b", "c", "d", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed6() {
+        Set<String> set = Set.of("a", "b", "c", "d", "e", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed7() {
+        Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed8() {
+        Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed9() {
+        Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowed10() {
+        Set<String> set = Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "a");
+    }
+
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void dupsDisallowedN() {
+        String[] array = stringArray.clone();
+        array[0] = array[1];
+        Set<String> set = Set.of(array);
+    }
+
+    @Test(dataProvider="all")
+    public void hashCodeEqual(Set<String> act, Set<String> exp) {
+        assertEquals(act.hashCode(), exp.hashCode());
+    }
+
+    @Test(dataProvider="all")
+    public void containsAll(Set<String> act, Set<String> exp) {
+        assertTrue(act.containsAll(exp));
+        assertTrue(exp.containsAll(act));
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed1() {
+        Set.of((String)null); // force one-arg overload
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed2a() {
+        Set.of("a", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed2b() {
+        Set.of(null, "b");
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed3() {
+        Set.of("a", "b", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed4() {
+        Set.of("a", "b", "c", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed5() {
+        Set.of("a", "b", "c", "d", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed6() {
+        Set.of("a", "b", "c", "d", "e", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed7() {
+        Set.of("a", "b", "c", "d", "e", "f", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed8() {
+        Set.of("a", "b", "c", "d", "e", "f", "g", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed9() {
+        Set.of("a", "b", "c", "d", "e", "f", "g", "h", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowed10() {
+        Set.of("a", "b", "c", "d", "e", "f", "g", "h", "i", null);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullDisallowedN() {
+        String[] array = stringArray.clone();
+        array[0] = null;
+        Set.of(array);
+    }
+
+    @Test(expectedExceptions=NullPointerException.class)
+    public void nullArrayDisallowed() {
+        Set.of((Object[])null);
+    }
+
+    @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+    public void containsNullShouldThrowNPE(Set<String> act, Set<String> exp) {
+        act.contains(null);
+    }
+
+    @Test(dataProvider="all")
+    public void serialEquality(Set<String> act, Set<String> exp) {
+        // assume that act.equals(exp) tested elsewhere
+        Set<String> copy = serialClone(act);
+        assertEquals(act, copy);
+        assertEquals(copy, exp);
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T> T serialClone(T obj) {
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+                oos.writeObject(obj);
+            }
+            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+            ObjectInputStream ois = new ObjectInputStream(bais);
+            return (T) ois.readObject();
+        } catch (IOException | ClassNotFoundException e) {
+            throw new AssertionError(e);
+        }
+    }
+
     Set<Integer> genSet() {
         return new HashSet<>(Arrays.asList(1, 2, 3));
     }
diff --git a/ojluni/src/test/java/util/Collection/testlibrary/CollectionAsserts.java b/ojluni/src/test/java/util/Collection/testlibrary/CollectionAsserts.java
new file mode 100644
index 0000000..9ae6590
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/testlibrary/CollectionAsserts.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Collection.testlibrary;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * @library
+ * CollectionAssert -- assertion methods for lambda test cases
+ */
+public class CollectionAsserts {
+
+    private CollectionAsserts() {
+        // no instances
+    }
+
+    public static void assertCountSum(Iterable<? super Integer> it, int count, int sum) {
+        assertCountSum(it.iterator(), count, sum);
+    }
+
+    public static void assertCountSum(Iterator<? super Integer> it, int count, int sum) {
+        int c = 0;
+        int s = 0;
+        while (it.hasNext()) {
+            int i = (Integer) it.next();
+            c++;
+            s += i;
+        }
+
+        assertEquals(c, count);
+        assertEquals(s, sum);
+    }
+
+    public static void assertConcat(Iterator<Character> it, String result) {
+        StringBuilder sb = new StringBuilder();
+        while (it.hasNext()) {
+            sb.append(it.next());
+        }
+
+        assertEquals(result, sb.toString());
+    }
+
+    public static<T extends Comparable<? super T>> void assertSorted(Iterator<T> i) {
+        if (!i.hasNext())
+            return;
+        T last = i.next();
+        while (i.hasNext()) {
+            T t = i.next();
+            assertTrue(last.compareTo(t) <= 0);
+            assertTrue(t.compareTo(last) >= 0);
+            last = t;
+        }
+    }
+
+    public static<T> void assertSorted(Iterator<T> i, Comparator<? super T> comp) {
+        if (!i.hasNext())
+            return;
+        T last = i.next();
+        while (i.hasNext()) {
+            T t = i.next();
+            assertTrue(comp.compare(last, t) <= 0);
+            assertTrue(comp.compare(t, last) >= 0);
+            last = t;
+        }
+    }
+
+    public static<T extends Comparable<? super T>> void assertSorted(Iterable<T> iter) {
+        assertSorted(iter.iterator());
+    }
+
+    public static<T> void assertSorted(Iterable<T> iter, Comparator<? super T> comp) {
+        assertSorted(iter.iterator(), comp);
+    }
+
+    public static <T> void assertUnique(Iterable<T> iter) {
+        assertUnique(iter.iterator());
+    }
+
+    public static<T> void assertUnique(Iterator<T> iter) {
+        if (!iter.hasNext()) {
+            return;
+        }
+
+        Set<T> uniq = new HashSet<>();
+        while (iter.hasNext()) {
+            T each = iter.next();
+            assertTrue(!uniq.contains(each));
+            uniq.add(each);
+        }
+    }
+
+    public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected) {
+        assertContents(actual, expected, null);
+    }
+
+    public static<T> void assertContents(Iterable<T> actual, Iterable<T> expected, String msg) {
+        assertContents(actual.iterator(), expected.iterator(), msg);
+    }
+
+    public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected) {
+        assertContents(actual, expected, null);
+    }
+
+    public static<T> void assertContents(Iterator<T> actual, Iterator<T> expected, String msg) {
+        List<T> history = new ArrayList<>();
+
+        while (expected.hasNext()) {
+            if (!actual.hasNext()) {
+                List<T> expectedData = new ArrayList<>(history);
+                while (expected.hasNext())
+                    expectedData.add(expected.next());
+                fail(String.format("%s Premature end of data; expected=%s, found=%s",
+                    (msg == null ? "" : msg), expectedData, history));
+            }
+            T a = actual.next();
+            T e = expected.next();
+            history.add(a);
+
+            if (!Objects.equals(a, e))
+                fail(String.format("%s Data mismatch; preceding=%s, nextExpected=%s, nextFound=%s",
+                    (msg == null ? "" : msg), history, e, a));
+        }
+        if (actual.hasNext()) {
+            List<T> rest = new ArrayList<>();
+            while (actual.hasNext())
+                rest.add(actual.next());
+            fail(String.format("%s Unexpected data %s after %s",
+                (msg == null ? "" : msg), rest, history));
+        }
+    }
+
+    @SafeVarargs
+    @SuppressWarnings("varargs")
+    public static<T> void assertContents(Iterator<T> actual, T... expected) {
+        assertContents(actual, Arrays.asList(expected).iterator());
+    }
+
+    public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected) {
+        assertContentsUnordered(actual, expected, null);
+    }
+
+    public static<T extends Comparable<? super T>> void assertContentsUnordered(Iterable<T> actual, Iterable<T> expected, String msg) {
+        List<T> allExpected = new ArrayList<>();
+        for (T t : expected) {
+            allExpected.add(t);
+        }
+
+        for (T t : actual) {
+            assertTrue(allExpected.remove(t), msg + " element '" + String.valueOf(t) + "' not found");
+        }
+
+        assertTrue(allExpected.isEmpty(), msg + "expected contained additional elements");
+    }
+
+    static <T> void assertSplitContents(Iterable<Iterable<T>> splits, Iterable<T> list) {
+        Iterator<Iterable<T>> mI = splits.iterator();
+        Iterator<T> pI = null;
+        Iterator<T> lI = list.iterator();
+
+        while (lI.hasNext()) {
+            if (pI == null)
+                pI = mI.next().iterator();
+            while (!pI.hasNext()) {
+                if (!mI.hasNext()) {
+                    break;
+                }
+                else {
+                    pI = mI.next().iterator();
+                }
+            }
+            assertTrue(pI.hasNext());
+            T pT = pI.next();
+            T lT = lI.next();
+            assertEquals(pT, lT);
+        }
+
+        if (pI != null) {
+            assertTrue(!pI.hasNext());
+        }
+
+        while (mI.hasNext()) {
+            pI = mI.next().iterator();
+            assertTrue(!pI.hasNext());
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Collection/testlibrary/CollectionSupplier.java b/ojluni/src/test/java/util/Collection/testlibrary/CollectionSupplier.java
new file mode 100644
index 0000000..61b009a
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/testlibrary/CollectionSupplier.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Collection.testlibrary;
+
+import java.lang.Exception;
+import java.lang.Integer;
+import java.lang.Iterable;
+import java.lang.Override;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+import org.testng.TestException;
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * @library
+ * @summary A Supplier of test cases for Collection tests
+ */
+public final class CollectionSupplier<C extends Collection<Integer>> implements Supplier<Iterable<CollectionSupplier.TestCase<C>>> {
+
+    private final List<Function<Collection<Integer>, C>> suppliers;
+    private final int size;
+
+    /**
+     * A Collection test case.
+     */
+    public static final class TestCase<C extends Collection<Integer>> {
+        /**
+         * The name of the test case.
+         */
+        public final String name;
+
+        /**
+         * The supplier of a collection
+         */
+        public Function<Collection<Integer>, C> supplier;
+
+        /**
+         * Unmodifiable reference collection, useful for comparisons.
+         */
+        public final List<Integer> expected;
+
+        /**
+         * A modifiable test collection.
+         */
+        public final C collection;
+
+        /**
+         * Create a Collection test case.
+         *
+         * @param name name of the test case
+         * @param collection the modifiable test collection
+         */
+        public TestCase(String name, Function<Collection<Integer>, C> supplier, C collection) {
+            this.name = name;
+            this.supplier = supplier;
+            this.expected = Collections.unmodifiableList(
+                Arrays.asList(collection.toArray(new Integer[0])));
+            this.collection = collection;
+        }
+
+        @Override
+        public String toString() {
+            return name + " " + collection.getClass().toString();
+        }
+    }
+
+    /**
+     * Shuffle a list using a PRNG with known seed for repeatability
+     *
+     * @param list the list to be shuffled
+     */
+    public static <E> void shuffle(final List<E> list) {
+        // PRNG with known seed for repeatable tests
+        final Random prng = new Random(13);
+        final int size = list.size();
+        for (int i = 0; i < size; i++) {
+            // random index in interval [i, size)
+            final int j = i + prng.nextInt(size - i);
+            // swap elements at indices i & j
+            final E e = list.get(i);
+            list.set(i, list.get(j));
+            list.set(j, e);
+        }
+    }
+
+    /**
+     * Create a {@code CollectionSupplier} that creates instances of specified
+     * collection suppliers of the specified size.
+     *
+     * @param suppliers the suppliers names that supply {@code Collection}
+     *        instances
+     * @param size the desired size of each collection
+     */
+    public CollectionSupplier(List<Function<Collection<Integer>, C>> suppliers, int size) {
+        this.suppliers = suppliers;
+        this.size = size;
+    }
+
+    @Override
+    public Iterable<TestCase<C>> get() {
+        final Collection<TestCase<C>> cases = new LinkedList<>();
+        for (final Function<Collection<Integer>, C> supplier : suppliers)
+            try {
+                cases.add(new TestCase<>("empty", supplier, supplier.apply(Collections.emptyList())));
+
+                cases.add(new TestCase<>("single", supplier, supplier.apply(Arrays.asList(42))));
+
+                final Collection<Integer> regular = new ArrayList<>();
+                for (int i = 0; i < size; i++) {
+                    regular.add(i);
+                }
+                cases.add(new TestCase<>("regular", supplier, supplier.apply(regular)));
+
+                final Collection<Integer> reverse = new ArrayList<>();
+                for (int i = size; i >= 0; i--) {
+                    reverse.add(i);
+                }
+                cases.add(new TestCase<>("reverse", supplier, supplier.apply(reverse)));
+
+                final Collection<Integer> odds = new ArrayList<>();
+                for (int i = 0; i < size; i++) {
+                    odds.add((i * 2) + 1);
+                }
+                cases.add(new TestCase<>("odds", supplier, supplier.apply(odds)));
+
+                final Collection<Integer> evens = new ArrayList<>();
+                for (int i = 0; i < size; i++) {
+                    evens.add(i * 2);
+                }
+                cases.add(new TestCase<>("evens", supplier, supplier.apply(evens)));
+
+                final Collection<Integer> fibonacci = new ArrayList<>();
+                int prev2 = 0;
+                int prev1 = 1;
+                for (int i = 0; i < size; i++) {
+                    final int n = prev1 + prev2;
+                    if (n < 0) { // stop on overflow
+                        break;
+                    }
+                    fibonacci.add(n);
+                    prev2 = prev1;
+                    prev1 = n;
+                }
+                cases.add(new TestCase<>("fibonacci", supplier, supplier.apply(fibonacci)));
+
+
+                boolean isStructurallyModifiable = false;
+                try {
+                    C t = supplier.apply(Collections.emptyList());
+                    t.add(1);
+                    isStructurallyModifiable = true;
+                } catch (UnsupportedOperationException e) { }
+
+                if (!isStructurallyModifiable)
+                    continue;
+
+
+                // variants where the size of the backing storage != reported size
+                // created by removing half of the elements
+                final C emptyWithSlack = supplier.apply(Collections.emptyList());
+                emptyWithSlack.add(42);
+                assertTrue(emptyWithSlack.remove(42));
+                cases.add(new TestCase<>("emptyWithSlack", supplier, emptyWithSlack));
+
+                final C singleWithSlack = supplier.apply(Collections.emptyList());
+                singleWithSlack.add(42);
+                singleWithSlack.add(43);
+                assertTrue(singleWithSlack.remove(43));
+                cases.add(new TestCase<>("singleWithSlack", supplier, singleWithSlack));
+
+                final C regularWithSlack = supplier.apply(Collections.emptyList());
+                for (int i = 0; i < (2 * size); i++) {
+                    regularWithSlack.add(i);
+                }
+                assertTrue(regularWithSlack.removeIf(x -> x < size));
+                cases.add(new TestCase<>("regularWithSlack", supplier, regularWithSlack));
+
+                final C reverseWithSlack = supplier.apply(Collections.emptyList());
+                for (int i = 2 * size; i >= 0; i--) {
+                    reverseWithSlack.add(i);
+                }
+                assertTrue(reverseWithSlack.removeIf(x -> x < size));
+                cases.add(new TestCase<>("reverseWithSlack", supplier, reverseWithSlack));
+
+                final C oddsWithSlack = supplier.apply(Collections.emptyList());
+                for (int i = 0; i < 2 * size; i++) {
+                    oddsWithSlack.add((i * 2) + 1);
+                }
+                assertTrue(oddsWithSlack.removeIf(x -> x >= size));
+                cases.add(new TestCase<>("oddsWithSlack", supplier, oddsWithSlack));
+
+                final C evensWithSlack = supplier.apply(Collections.emptyList());
+                for (int i = 0; i < 2 * size; i++) {
+                    evensWithSlack.add(i * 2);
+                }
+                assertTrue(evensWithSlack.removeIf(x -> x >= size));
+                cases.add(new TestCase<>("evensWithSlack", supplier, evensWithSlack));
+
+                final C fibonacciWithSlack = supplier.apply(Collections.emptyList());
+                prev2 = 0;
+                prev1 = 1;
+                for (int i = 0; i < size; i++) {
+                    final int n = prev1 + prev2;
+                    if (n < 0) { // stop on overflow
+                        break;
+                    }
+                    fibonacciWithSlack.add(n);
+                    prev2 = prev1;
+                    prev1 = n;
+                }
+                assertTrue(fibonacciWithSlack.removeIf(x -> x < 20));
+                cases.add(new TestCase<>("fibonacciWithSlack", supplier, fibonacciWithSlack));
+            }
+            catch (Exception failed) {
+                throw new TestException(failed);
+            }
+
+        return cases;
+    }
+
+}
diff --git a/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java b/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java
new file mode 100644
index 0000000..e85947f
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Collection.testlibrary;
+
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.function.Supplier;
+
+/**
+ * @library
+ *
+ * A simple mutable collection implementation that provides only default
+ * implementations of all methods. ie. none of the Collection interface default
+ * methods have overridden implementations.
+ *
+ * @param <E> type of collection elements
+ */
+public class ExtendsAbstractCollection<E> extends AbstractCollection<E> {
+
+    protected final Collection<E> coll;
+
+    public ExtendsAbstractCollection() {
+        this(ArrayList<E>::new);
+    }
+
+    public ExtendsAbstractCollection(Collection<E> source) {
+        this();
+        coll.addAll(source);
+    }
+
+    protected ExtendsAbstractCollection(Supplier<Collection<E>> backer) {
+        this.coll = backer.get();
+    }
+
+    public boolean add(E element) {
+        return coll.add(element);
+    }
+
+    public boolean remove(Object element) {
+        return coll.remove(element);
+    }
+
+    public Iterator<E> iterator() {
+        return new Iterator<E>() {
+            Iterator<E> source = coll.iterator();
+
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            public E next() {
+                return source.next();
+            }
+
+            public void remove() {
+                source.remove();
+            }
+        };
+    }
+
+    public int size() {
+        return coll.size();
+    }
+}
diff --git a/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractList.java b/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractList.java
new file mode 100644
index 0000000..c4fd0b9
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractList.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Collection.testlibrary;
+
+import java.util.ArrayList;
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Supplier;
+
+/**
+ * @library
+ *
+ * A simple mutable list implementation that provides only default
+ * implementations of all methods. ie. none of the List interface default
+ * methods have overridden implementations.
+ *
+ * @param <E> type of list elements
+ */
+public class ExtendsAbstractList<E> extends AbstractList<E> {
+
+    protected final List<E> list;
+
+    public ExtendsAbstractList() {
+        this(ArrayList<E>::new);
+    }
+
+    protected ExtendsAbstractList(Supplier<List<E>> supplier) {
+        this.list = supplier.get();
+    }
+
+    public ExtendsAbstractList(Collection<E> source) {
+        this();
+        addAll(source);
+    }
+
+    public boolean add(E element) {
+        return list.add(element);
+    }
+
+    public E get(int index) {
+        return list.get(index);
+    }
+
+    public boolean remove(Object element) {
+        return list.remove(element);
+    }
+
+    public E set(int index, E element) {
+        return list.set(index, element);
+    }
+
+    public void add(int index, E element) {
+        list.add(index, element);
+    }
+
+    public E remove(int index) {
+        return list.remove(index);
+    }
+
+    public Iterator<E> iterator() {
+        return new Iterator<E>() {
+            Iterator<E> source = list.iterator();
+
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            public E next() {
+                return source.next();
+            }
+
+            public void remove() {
+                source.remove();
+            }
+        };
+    }
+
+    public int size() {
+        return list.size();
+    }
+}
diff --git a/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractSet.java b/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractSet.java
new file mode 100644
index 0000000..358fab3
--- /dev/null
+++ b/ojluni/src/test/java/util/Collection/testlibrary/ExtendsAbstractSet.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Collection.testlibrary;
+
+import java.util.HashSet;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * @library
+ *
+ * A simple mutable set implementation that provides only default
+ * implementations of all methods. ie. none of the Set interface default methods
+ * have overridden implementations.
+ *
+ * @param <E> type of set members
+ */
+public class ExtendsAbstractSet<E> extends AbstractSet<E> {
+
+    protected final Set<E> set;
+
+    public ExtendsAbstractSet() {
+        this(HashSet<E>::new);
+    }
+
+    public ExtendsAbstractSet(Collection<E> source) {
+        this();
+        addAll(source);
+    }
+
+    protected ExtendsAbstractSet(Supplier<Set<E>> backer) {
+        this.set = backer.get();
+    }
+
+    public boolean add(E element) {
+        return set.add(element);
+    }
+
+    public boolean remove(Object element) {
+        return set.remove(element);
+    }
+
+    public Iterator<E> iterator() {
+        return new Iterator<E>() {
+            Iterator<E> source = set.iterator();
+
+            public boolean hasNext() {
+                return source.hasNext();
+            }
+
+            public E next() {
+                return source.next();
+            }
+
+            public void remove() {
+                source.remove();
+            }
+        };
+    }
+
+    public int size() {
+        return set.size();
+    }
+}
diff --git a/ojluni/src/test/java/util/Collections/EnumerationAsIterator.java b/ojluni/src/test/java/util/Collections/EnumerationAsIterator.java
new file mode 100644
index 0000000..60cad8f
--- /dev/null
+++ b/ojluni/src/test/java/util/Collections/EnumerationAsIterator.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Collections;
+
+/**
+ * @test
+ * @bug 8072726
+ * @summary Tests for Enumeration-to-Iterator conversion.
+ * @run testng EnumerationAsIterator
+ */
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+
+import static org.testng.Assert.*;
+
+@Test
+public class EnumerationAsIterator {
+    static Object[] of(String description, Supplier<Enumeration<?>> s, Collection<?> exp) {
+        return new Object[]{description, s, exp};
+    }
+
+    static Object[] of(String description, Collection<?> c, Collection<?> exp) {
+        return of(description, () -> Collections.enumeration(c), exp);
+    }
+
+    /**
+     * A wrapper Enumeration that doesn't override the
+     * default method on Enumeration.
+     */
+    static <T> Enumeration<T> wrapInDefault(Enumeration<T> e) {
+        return new Enumeration<>() {
+            @Override
+            public boolean hasMoreElements() {
+                return e.hasMoreElements();
+            }
+
+            @Override
+            public T nextElement() {
+                return e.nextElement();
+            }
+        };
+    }
+
+    @DataProvider
+    public static Iterator<Object[]> unmodifiable() {
+        return Arrays.asList(
+                of("Default-wrapped ArrayList",
+                        () -> wrapInDefault(
+                                Collections.enumeration(new ArrayList<>(Arrays.asList("a")))),
+                        Arrays.asList("a")),
+
+                of("Unmodifiable ArrayList",
+                        Collections.unmodifiableList(new ArrayList<>(Arrays.asList("a"))),
+                        Arrays.asList("a")),
+
+                of("Modifiable ArrayList",
+                        new ArrayList<>(Arrays.asList("a")),
+                        Arrays.asList("a"))
+        ).iterator();
+    }
+
+    @DataProvider
+    public static Iterator<Object[]> others() {
+        return Arrays.asList(
+                of("Default Collections.emptyEnumeration()",
+                        () -> wrapInDefault(Collections.emptyEnumeration()),
+                        Collections.emptyList()),
+
+                of("Collections.emptyEnumeration()",
+                        Collections::emptyEnumeration,
+                        Collections.emptyList()),
+
+                of("Collections.emptyList()",
+                        Collections.emptyList(),
+                        Collections.emptyList()),
+
+                of("Collections.singletonList()",
+                        Collections.singletonList("a"),
+                        Collections.singletonList("a")),
+
+                of("Arrays.asList(...)",
+                        Arrays.asList("a", "b", "c"),
+                        Arrays.asList("a", "b", "c"))
+        ).iterator();
+    }
+
+    @DataProvider
+    public static Iterator<Object[]> all() {
+        List<Object[]> all = new ArrayList<>();
+        unmodifiable().forEachRemaining(all::add);
+        others().forEachRemaining(all::add);
+        return all.iterator();
+    }
+
+    @Test(dataProvider = "all")
+    public void consumeByNext(String description, Supplier<Enumeration<?>> s, Collection<?> exp) {
+        Iterator<?> i = s.get().asIterator();
+        int count = 0;
+        while (i.hasNext()) {
+            assertTrue(i.hasNext());
+
+            i.next();
+            count++;
+        }
+        assertEquals(count, exp.size());
+
+        assertFalse(i.hasNext());
+
+        try {
+            i.next();
+            fail();
+        } catch (NoSuchElementException e) {
+        }
+    }
+
+    @Test(dataProvider = "all")
+    public void consumeByForEachRemaining(String description,
+            Supplier<Enumeration<?>> s,
+            Collection<?> exp) {
+        Iterator<?> i = s.get().asIterator();
+        AtomicInteger ai = new AtomicInteger();
+        i.forEachRemaining(e -> ai.getAndIncrement());
+        assertEquals(ai.get(), exp.size());
+        i.forEachRemaining(e -> ai.getAndIncrement());
+        assertEquals(ai.get(), exp.size());
+
+        assertFalse(i.hasNext());
+
+        try {
+            i.next();
+            fail();
+        } catch (NoSuchElementException e) {
+        }
+    }
+
+    @Test(dataProvider = "all")
+    public void consumeByNextThenForEachRemaining(String description,
+            Supplier<Enumeration<?>> s,
+            Collection<?> exp) {
+        Iterator<?> i = s.get().asIterator();
+        AtomicInteger ai = new AtomicInteger();
+        if (i.hasNext()) {
+            i.next();
+            ai.getAndIncrement();
+        }
+        i.forEachRemaining(e -> ai.getAndIncrement());
+        assertEquals(ai.get(), exp.size());
+        i.forEachRemaining(e -> ai.getAndIncrement());
+        assertEquals(ai.get(), exp.size());
+
+        assertFalse(i.hasNext());
+
+        try {
+            i.next();
+            fail();
+        } catch (NoSuchElementException e) {
+        }
+    }
+
+    @Test(dataProvider = "all")
+    public void contents(String description, Supplier<Enumeration<?>> s, Collection<?> exp) {
+        assertEquals(copy(s.get()), exp);
+    }
+
+    private List<?> copy(Enumeration<?> input) {
+        List<Object> output = new ArrayList<>();
+        input.asIterator().forEachRemaining(output::add);
+        return output;
+    }
+
+    @Test(dataProvider = "unmodifiable",
+            expectedExceptions=UnsupportedOperationException.class)
+    public void removeThrowsAfterAdvancingE(String description,
+            Supplier<Enumeration<?>> s,
+            Collection<?> exp) {
+        Enumeration<?> e = s.get();
+        e.nextElement();
+        e.asIterator().remove();
+    }
+
+    @Test(dataProvider = "unmodifiable",
+            expectedExceptions=UnsupportedOperationException.class)
+    public void removeThrowsAfterAdvancingI(String description,
+            Supplier<Enumeration<?>> s,
+            Collection<?> exp) {
+        Iterator<?> i = s.get().asIterator();
+        i.next();
+        i.remove();
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Date/DateTest.java b/ojluni/src/test/java/util/Date/DateTest.java
new file mode 100644
index 0000000..2eb8e9e
--- /dev/null
+++ b/ojluni/src/test/java/util/Date/DateTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 4143459
+ * @summary test Date
+ * @library /java/text/testlib
+ */
+package test.java.util.Date;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class DateTest {
+
+    /**
+     * Verify that the Date(String) constructor works.
+     */
+    @Test
+    public void testParseOfGMT()
+    {
+        Date OUT;
+
+        /* Input values */
+        String stringVal = "Jan 01 00:00:00 GMT 1900";
+        long expectedVal = -2208988800000L;
+
+        OUT = new Date( stringVal );
+
+        Assert.assertEquals(OUT.getTime( ), expectedVal );
+    }
+
+    // Check out Date's behavior with large negative year values; bug 664
+    // As of the fix to bug 4056585, Date should work correctly with
+    // large negative years.
+    @Test
+    public void testDateNegativeYears()
+    {
+        Date d1= new Date(80,-1,2);
+        d1= new Date(-80,-1,2);
+        try {
+            d1= new Date(-800000,-1,2);
+        }
+        catch (IllegalArgumentException ex) {
+            Assert.fail();
+        }
+    }
+
+    // Verify the behavior of Date
+    @Test
+    public void testDate480()
+    {
+        TimeZone save = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+            Date d1=new java.util.Date(97,8,13,10,8,13);
+            Date d2=new java.util.Date(97,8,13,30,8,13); // 20 hours later
+
+            double delta = (d2.getTime() - d1.getTime()) / 3600000;
+
+
+            Assert.assertEquals(delta, 20.0);
+
+            Calendar cal = Calendar.getInstance();
+            cal.clear();
+            cal.set(1997,8,13,10,8,13);
+            Date t1 = cal.getTime();
+            cal.clear();
+            cal.set(1997,8,13,30,8,13); // 20 hours later
+            Date t2 = cal.getTime();
+
+            double delta2 = (t2.getTime() - t1.getTime()) / 3600000;
+
+            Assert.assertEquals(delta2, 20.0);
+        }
+        finally {
+            TimeZone.setDefault(save);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumMap/DistinctEntrySetElements.java b/ojluni/src/test/java/util/EnumMap/DistinctEntrySetElements.java
new file mode 100644
index 0000000..6c310d1
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumMap/DistinctEntrySetElements.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2011 IBM Corporation
+ */
+
+/*
+ * @test
+ * @bug 6312706
+ * @summary Sets from Map.entrySet() return distinct objects for each Entry
+ * @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
+ */
+package test.java.util.EnumMap;
+
+import java.util.EnumMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class DistinctEntrySetElements {
+    static enum TestEnum { e00, e01, e02 }
+
+    @Test
+    public void testDistinctElements() {
+        final EnumMap<TestEnum, String> enumMap = new EnumMap<>(TestEnum.class);
+
+        for (TestEnum e : TestEnum.values()) {
+            enumMap.put(e, e.name());
+        }
+
+        Set<Map.Entry<TestEnum, String>> entrySet = enumMap.entrySet();
+        HashSet<Map.Entry<TestEnum, String>> hashSet = new HashSet<>(entrySet);
+
+        Assert.assertTrue(hashSet.equals(entrySet));
+        Assert.assertEquals(hashSet.hashCode(), entrySet.hashCode());
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumMap/EntrySetIteratorRemoveInvalidatesEntry.java b/ojluni/src/test/java/util/EnumMap/EntrySetIteratorRemoveInvalidatesEntry.java
new file mode 100644
index 0000000..0f2a6d0
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumMap/EntrySetIteratorRemoveInvalidatesEntry.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 6312706
+ * @summary Iterator.remove() from Map.entrySet().iterator() invalidates returned Entry.
+ * @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
+ */
+package test.java.util.EnumMap;
+
+import java.util.EnumMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class EntrySetIteratorRemoveInvalidatesEntry {
+    static enum TestEnum { e00, e01, e02 }
+
+    @Test
+    public void testInvalidatesEntry() throws Exception {
+        final EnumMap<TestEnum, String> enumMap = new EnumMap<>(TestEnum.class);
+
+        for (TestEnum e : TestEnum.values()) {
+            enumMap.put(e, e.name());
+        }
+
+        Iterator<Map.Entry<TestEnum, String>> entrySetIterator =
+                enumMap.entrySet().iterator();
+        Map.Entry<TestEnum, String> entry = entrySetIterator.next();
+
+        entrySetIterator.remove();
+
+        try {
+            entry.getKey();
+            Assert.fail();
+        } catch (Exception e) { }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumMap/EnumMapBash.java b/ojluni/src/test/java/util/EnumMap/EnumMapBash.java
new file mode 100644
index 0000000..b031971
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumMap/EnumMapBash.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug     4904140
+ * @summary Unit test for EnumMap
+ * @author  Josh Bloch
+ * @author  Yo Yo Ma
+ */
+package test.java.util.EnumMap;
+
+import java.util.*;
+import java.io.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class EnumMapBash {
+    static Random rnd = new Random();
+
+    @Test
+    public void testMapBash() {
+        bash(Silly31.class);
+        bash(Silly32.class);
+        bash(Silly33.class);
+        bash(Silly63.class);
+        bash(Silly64.class);
+        bash(Silly65.class);
+        bash(Silly127.class);
+        bash(Silly128.class);
+        bash(Silly129.class);
+        bash(Silly500.class);
+    }
+
+    static <T extends Enum<T>> void bash(Class<T> enumClass) {
+        Enum[] universe = enumClass.getEnumConstants();
+
+        int numItr = 100;
+
+        // Linked List test
+        for (int i=0; i<numItr; i++) {
+            int mapSize = universe.length * 7 / 8;
+
+            // Build the linked list
+            Map<T, T> m = new EnumMap<T, T>(enumClass);
+            if (!m.isEmpty())
+                fail("New instance non empty.");
+            Enum[] perm = (Enum[]) universe.clone();
+            Collections.shuffle(Arrays.asList(perm));
+            T head = (T) perm[0];
+            for (int j = 0; j < mapSize; j++)
+                m.put((T)perm[j], (T)perm[j + 1]);
+            T nil = (T)perm[mapSize];
+
+            if (m.size() != mapSize)
+                fail("Size not as expected.");
+
+            Map<T, T> tm = new TreeMap<T, T>(m);
+
+            if (m.hashCode() != tm.hashCode())
+                fail("Incorrect hashCode computation.");
+            if (!m.toString().equals(tm.toString()))
+                fail("Incorrect toString computation.");
+            if (!tm.equals(m))
+                fail("Incorrect equals (1).");
+            if (!m.equals(tm))
+                fail("Incorrect equals (2).");
+
+            Map<T, T> m2 = new EnumMap<T, T>(enumClass); m2.putAll(m);
+            m2.values().removeAll(m.keySet());
+            if (m2.size()!= 1 || !m2.containsValue(nil))
+                fail("Collection views test failed.");
+
+            int j=0;
+            while (head != nil) {
+                if (!m.containsKey(head))
+                    fail("Linked list doesn't contain a link.");
+                T newHead = m.get(head);
+                if (newHead == null)
+                    fail("Could not retrieve a link.");
+                m.remove(head);
+                head = newHead;
+                j++;
+            }
+            if (!m.isEmpty())
+                fail("Map nonempty after removing all links.");
+            if (j != mapSize)
+                fail("Linked list size not as expected.");
+        }
+
+        EnumMap<T, T> m = new EnumMap<T, T>(enumClass);
+        int mapSize = 0;
+        for (int i=0; i<universe.length; i += 2) {
+            if (m.put((T)universe[i], (T)universe[i]) != null)
+                fail("put returns a non-null value erroenously.");
+            mapSize++;
+        }
+        for (int i=0; i<universe.length; i++)
+            if (m.containsValue(universe[i]) != (i%2==0))
+                fail("contains value "+i);
+        if (m.put((T)universe[0], (T)universe[0]) == null)
+            fail("put returns a null value erroenously.");
+
+        Map<T, T>  m2 = m.clone();
+        cloneTest(m, m2);
+
+        m2 = new EnumMap<T,T>(enumClass);
+        m2.putAll(m);
+        cloneTest(m, m2);
+
+        m2 = new EnumMap<T, T>(m);
+        cloneTest(m, m2);
+
+        m2 = new EnumMap<T, T>((Map<T, T>) m);
+        cloneTest(m, m2);
+        if (!m.isEmpty()) {
+            m2 = new EnumMap<T, T>(new HashMap<T, T>(m));
+            cloneTest(m, m2);
+        }
+
+        m2 = deepCopy(m);
+        cloneTest(m, m2);
+
+        if (!m.equals(m2))
+            fail("Clone not equal to original. (1)");
+        if (!m2.equals(m))
+            fail("Clone not equal to original. (2)");
+
+        Set<Map.Entry<T,T>> s = m.entrySet(), s2 = m2.entrySet();
+
+        if (!s.equals(s2))
+            fail("Clone not equal to original. (3)");
+        if (!s2.equals(s))
+            fail("Clone not equal to original. (4)");
+        if (!s.containsAll(s2))
+            fail("Original doesn't contain clone!");
+        if (!s2.containsAll(s))
+            fail("Clone doesn't contain original!");
+
+        s2.removeAll(s);
+        if (!m2.isEmpty()) {
+            System.out.println(m2.size());
+            System.out.println(m2);
+            fail("entrySet().removeAll failed.");
+        }
+
+        m2.putAll(m);
+        m2.clear();
+        if (!m2.isEmpty())
+            fail("clear failed.");
+
+        Iterator i = m.entrySet().iterator();
+        while(i.hasNext()) {
+            i.next();
+            i.remove();
+        }
+        if (!m.isEmpty())
+            fail("Iterator.remove() failed");
+    }
+
+    // Done inefficiently so as to exercise various functions
+    static <K, V> void cloneTest(Map<K, V> m, Map<K, V> clone) {
+        if (!m.equals(clone))
+            fail("Map not equal to copy.");
+        if (!clone.equals(m))
+            fail("Copy not equal to map.");
+        if (!m.entrySet().containsAll(clone.entrySet()))
+            fail("Set does not contain copy.");
+        if (!clone.entrySet().containsAll(m.entrySet()))
+            fail("Copy does not contain set.");
+        if (!m.entrySet().equals(clone.entrySet()))
+            fail("Set not equal clone set");
+        if (!clone.entrySet().equals(m.entrySet()))
+            fail("Clone set not equal set");
+    }
+
+    // Utility method to do a deep copy of an object *very slowly* using
+    // serialization/deserialization
+    static <T> T deepCopy(T oldObj) {
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            ObjectOutputStream oos = new ObjectOutputStream(bos);
+            oos.writeObject(oldObj);
+            oos.flush();
+            ByteArrayInputStream bin = new ByteArrayInputStream(
+                    bos.toByteArray());
+            ObjectInputStream ois = new ObjectInputStream(bin);
+            return (T) ois.readObject();
+        } catch(Exception e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+
+    static void fail(String s) {
+        throw new RuntimeException(s);
+    }
+
+    public enum Silly31 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30
+    }
+
+    public enum Silly32 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31
+    }
+
+    public enum Silly33 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32
+    }
+
+    public enum Silly63 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62
+    }
+
+    public enum Silly64 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63
+    }
+
+    public enum Silly65 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64
+    }
+
+    public enum Silly127 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126
+    }
+
+    public enum Silly128 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126, e127
+    }
+
+    public enum Silly129 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128
+    }
+
+    public enum Silly500 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128, e129,
+        e130, e131, e132, e133, e134, e135, e136, e137, e138, e139, e140, e141,
+        e142, e143, e144, e145, e146, e147, e148, e149, e150, e151, e152, e153,
+        e154, e155, e156, e157, e158, e159, e160, e161, e162, e163, e164, e165,
+        e166, e167, e168, e169, e170, e171, e172, e173, e174, e175, e176, e177,
+        e178, e179, e180, e181, e182, e183, e184, e185, e186, e187, e188, e189,
+        e190, e191, e192, e193, e194, e195, e196, e197, e198, e199, e200, e201,
+        e202, e203, e204, e205, e206, e207, e208, e209, e210, e211, e212, e213,
+        e214, e215, e216, e217, e218, e219, e220, e221, e222, e223, e224, e225,
+        e226, e227, e228, e229, e230, e231, e232, e233, e234, e235, e236, e237,
+        e238, e239, e240, e241, e242, e243, e244, e245, e246, e247, e248, e249,
+        e250, e251, e252, e253, e254, e255, e256, e257, e258, e259, e260, e261,
+        e262, e263, e264, e265, e266, e267, e268, e269, e270, e271, e272, e273,
+        e274, e275, e276, e277, e278, e279, e280, e281, e282, e283, e284, e285,
+        e286, e287, e288, e289, e290, e291, e292, e293, e294, e295, e296, e297,
+        e298, e299, e300, e301, e302, e303, e304, e305, e306, e307, e308, e309,
+        e310, e311, e312, e313, e314, e315, e316, e317, e318, e319, e320, e321,
+        e322, e323, e324, e325, e326, e327, e328, e329, e330, e331, e332, e333,
+        e334, e335, e336, e337, e338, e339, e340, e341, e342, e343, e344, e345,
+        e346, e347, e348, e349, e350, e351, e352, e353, e354, e355, e356, e357,
+        e358, e359, e360, e361, e362, e363, e364, e365, e366, e367, e368, e369,
+        e370, e371, e372, e373, e374, e375, e376, e377, e378, e379, e380, e381,
+        e382, e383, e384, e385, e386, e387, e388, e389, e390, e391, e392, e393,
+        e394, e395, e396, e397, e398, e399, e400, e401, e402, e403, e404, e405,
+        e406, e407, e408, e409, e410, e411, e412, e413, e414, e415, e416, e417,
+        e418, e419, e420, e421, e422, e423, e424, e425, e426, e427, e428, e429,
+        e430, e431, e432, e433, e434, e435, e436, e437, e438, e439, e440, e441,
+        e442, e443, e444, e445, e446, e447, e448, e449, e450, e451, e452, e453,
+        e454, e455, e456, e457, e458, e459, e460, e461, e462, e463, e464, e465,
+        e466, e467, e468, e469, e470, e471, e472, e473, e474, e475, e476, e477,
+        e478, e479, e480, e481, e482, e483, e484, e485, e486, e487, e488, e489,
+        e490, e491, e492, e493, e494, e495, e496, e497, e498, e499
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumMap/SimpleSerialization.java b/ojluni/src/test/java/util/EnumMap/SimpleSerialization.java
new file mode 100644
index 0000000..93018be
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumMap/SimpleSerialization.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 6312706
+ * @summary A serialized EnumMap can be successfully de-serialized.
+ * @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
+ */
+package test.java.util.EnumMap;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.EnumMap;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class SimpleSerialization {
+    private enum TestEnum { e00, e01, e02, e03, e04, e05, e06, e07 }
+
+    @Test
+    public void testSimpleSerialization() throws Exception {
+        final EnumMap<TestEnum, String> enumMap = new EnumMap<>(TestEnum.class);
+
+        enumMap.put(TestEnum.e01, TestEnum.e01.name());
+        enumMap.put(TestEnum.e04, TestEnum.e04.name());
+        enumMap.put(TestEnum.e05, TestEnum.e05.name());
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        final ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+        oos.writeObject(enumMap);
+        oos.close();
+
+        final byte[] data = baos.toByteArray();
+        final ByteArrayInputStream bais = new ByteArrayInputStream(data);
+        final ObjectInputStream ois = new ObjectInputStream(bais);
+
+        final Object deserializedObject = ois.readObject();
+        ois.close();
+
+        Assert.assertTrue(enumMap.equals(deserializedObject));
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumMap/ToArray.java b/ojluni/src/test/java/util/EnumMap/ToArray.java
new file mode 100644
index 0000000..0917a30
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumMap/ToArray.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug     6310858
+ * @summary Tests for toArray
+ * @author  Martin Buchholz
+ */
+package test.java.util.EnumMap;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ToArray {
+    enum Country { FRENCH, POLISH }
+
+    @Test
+    public void testToArray() throws Throwable {
+        Map<Country, String> m = new EnumMap<Country, String>(Country.class);
+        m.put(Country.FRENCH, "connection");
+        m.put(Country.POLISH, "sausage");
+
+        Object[] z = m.entrySet().toArray();
+        Assert.assertEquals(z.getClass(), Object[].class);
+        Assert.assertEquals(z.length, 2);
+
+        Map.Entry[] x1 = new Map.Entry[3];
+        x1[2] = m.entrySet().iterator().next();
+        Map.Entry[] x2 = m.entrySet().toArray(x1);
+        Assert.assertEquals(x1, x2);
+        Assert.assertEquals(x2[0].getKey(), Country.FRENCH);
+        Assert.assertEquals(x2[1].getKey(), Country.POLISH);
+        Assert.assertEquals(x2[2], null);
+
+        Map.Entry[] y1 = new Map.Entry[1];
+        Map.Entry[] y2 = m.entrySet().toArray(y1);
+        Assert.assertTrue(y1 != y2);
+        Assert.assertEquals(y2.length, 2);
+        Assert.assertEquals(y2[0].getKey(), Country.FRENCH);
+        Assert.assertEquals(y2[1].getKey(), Country.POLISH);
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumMap/UniqueNullValue.java b/ojluni/src/test/java/util/EnumMap/UniqueNullValue.java
new file mode 100644
index 0000000..e346395
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumMap/UniqueNullValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 7123229
+ * @summary (coll) EnumMap.containsValue(null) returns true
+ * @author ngmr
+ */
+package test.java.util.EnumMap;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class UniqueNullValue {
+    static enum TestEnum { e00, e01 }
+
+    @Test
+    public void testUniqueNull() {
+        Map<TestEnum, Integer> map = new EnumMap<>(TestEnum.class);
+
+        map.put(TestEnum.e00, 0);
+        Assert.assertTrue(map.containsValue(0));
+        Assert.assertFalse(map.containsValue(null));
+
+        map.put(TestEnum.e00, null);
+        Assert.assertFalse(map.containsValue(0));
+        Assert.assertTrue(map.containsValue(null));
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/AllOf.java b/ojluni/src/test/java/util/EnumSet/AllOf.java
new file mode 100644
index 0000000..604d0ab
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/AllOf.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     4946090
+ * @summary AllOf static factory is broken in Regular and Jumbo enum set
+ * @author  Josh Bloch
+ */
+package test.java.util.EnumSet;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class AllOf {
+
+    @Test
+    public void testAllOf() throws Exception {
+        test(Test0.class, 0);
+        test(Test33.class, 33);
+        test(Test127.class, 127);
+        test(Test128.class, 128);
+    }
+
+    static <T extends Enum<T>> void test(Class<T> enumClass,
+            int expected) {
+        EnumSet<T> set = EnumSet.allOf(enumClass);
+        Assert.assertEquals(set.size(), expected);
+    }
+
+    public enum Test0 {}
+
+    public enum Test33 {
+        T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16,
+        T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+        T31, T32, T33
+    }
+
+    public enum Test127 {
+        T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126
+    }
+
+    public enum Test128 {
+        T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126, T127
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/ComplementOf.java b/ojluni/src/test/java/util/EnumSet/ComplementOf.java
new file mode 100644
index 0000000..0ef66f9
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/ComplementOf.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug     4946096
+ * @summary ComplementOf static factory is broken in Regular and Jumbo enum set
+ * @author  Josh Bloch
+ */
+package test.java.util.EnumSet;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ComplementOf {
+
+    @Test
+    public void testComplementOf() {
+        test(Test0.class);
+        test(MonthTest10.class);
+        test(Test127.class);
+        test(Test128.class);
+    }
+
+    static <T extends Enum<T>> void test(Class<T> enumClass) {
+        EnumSet<T> set = EnumSet.allOf(enumClass);
+        EnumSet<T> setComplement = EnumSet.complementOf(set);
+        Assert.assertEquals(setComplement.size(), 0);
+    }
+
+    public enum Test0 { }
+
+    public enum MonthTest10 { Jan,Feb,Mar,Apr,May,Jun,July,Aug,Sep,Oct }
+
+    public enum Test127 {
+        T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126
+    }
+
+    public enum Test128 {
+        T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126, T127
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/EnumSetBash.java b/ojluni/src/test/java/util/EnumSet/EnumSetBash.java
new file mode 100644
index 0000000..10fd790
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/EnumSetBash.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug     4904135 4923181
+ * @summary Unit test for EnumSet
+ * @author  Josh Bloch
+ * @author  Neal Gafter
+ * @author  Yo Ma Ma
+ * @key randomness
+ */
+package test.java.util.EnumSet;
+
+import java.util.*;
+import java.io.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class EnumSetBash {
+    static Random rnd = new Random();
+
+    @Test
+    public void testEnumSetBash() {
+        bash(Silly0.class);
+        bash(Silly1.class);
+        bash(Silly31.class);
+        bash(Silly32.class);
+        bash(Silly33.class);
+        bash(Silly63.class);
+        bash(Silly64.class);
+        bash(Silly65.class);
+        bash(Silly127.class);
+        bash(Silly128.class);
+        bash(Silly129.class);
+        bash(Silly500.class);
+    }
+
+    static <T extends Enum<T>> void bash(Class<T> enumClass) {
+        Enum[] universe = EnumSet.allOf(enumClass).toArray(new Enum[0]);
+        int numItr = 1000;
+
+        for (int i=0; i<numItr; i++) {
+            EnumSet<T> s1 = EnumSet.noneOf(enumClass);
+            EnumSet<T> s2 = clone(s1, enumClass);
+            AddRandoms(s1, universe);
+            AddRandoms(s2, universe);
+
+            EnumSet<T> intersection = clone(s1, enumClass);
+            intersection.retainAll(s2);
+            EnumSet<T> diff1 = clone(s1, enumClass); diff1.removeAll(s2);
+            EnumSet<T> diff2 = clone(s2, enumClass); diff2.removeAll(s1);
+            EnumSet<T> union = clone(s1, enumClass); union.addAll(s2);
+
+            Assert.assertFalse(diff1.removeAll(diff2));
+            Assert.assertFalse(diff1.removeAll(intersection));
+            Assert.assertFalse(diff2.removeAll(diff1));
+            Assert.assertFalse(diff2.removeAll(intersection));
+            Assert.assertFalse(intersection.removeAll(diff1));
+            Assert.assertFalse(intersection.removeAll(diff1));
+
+            intersection.addAll(diff1); intersection.addAll(diff2);
+            Assert.assertTrue(intersection.equals(union));
+
+            Assert.assertEquals(new HashSet<T>(union).hashCode(), union.hashCode());
+
+            Iterator e = union.iterator();
+            while (e.hasNext())
+                Assert.assertTrue(intersection.remove(e.next()));
+            Assert.assertTrue(intersection.isEmpty());
+
+            e = union.iterator();
+            while (e.hasNext()) {
+                Object o = e.next();
+                Assert.assertTrue(union.contains(o));
+                e.remove();
+                Assert.assertFalse(union.contains(o));
+            }
+            Assert.assertTrue(union.isEmpty());
+
+            s1.clear();
+            Assert.assertTrue(s1.isEmpty());
+        }
+    }
+
+    // Done inefficiently so as to exercise various functions
+    static <E extends Enum<E>> EnumSet<E> clone(EnumSet<E> s, Class<E> cl) {
+        EnumSet<E> clone = null;
+        int method = rnd.nextInt(6);
+        switch(method) {
+            case 0:
+                clone = s.clone();
+                break;
+            case 1:
+                clone = EnumSet.noneOf(cl);
+                Collection arrayList = (Collection)Arrays.asList(s.toArray());
+                clone.addAll((Collection<E>)arrayList);
+                break;
+            case 2:
+                clone = EnumSet.copyOf(s);
+                break;
+            case 3:
+                clone = EnumSet.copyOf((Collection<E>)s);
+                break;
+            case 4:
+                if (s.isEmpty())
+                    clone = EnumSet.copyOf((Collection<E>)s);
+                else
+                    clone = EnumSet.copyOf((Collection<E>)(Collection)
+                            Arrays.asList(s.toArray()));
+                break;
+            case 5:
+                clone = (EnumSet<E>) deepCopy(s);
+        }
+        Assert.assertTrue(s.equals(clone));
+        Assert.assertTrue(s.containsAll(clone));
+        Assert.assertTrue(clone.containsAll(s));
+        return clone;
+    }
+
+    // Utility method to do a deep copy of an object *very slowly* using
+    // serialization/deserialization
+    static <T> T deepCopy(T oldObj) {
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            ObjectOutputStream oos = new ObjectOutputStream(bos);
+            oos.writeObject(oldObj);
+            oos.flush();
+            ByteArrayInputStream bin = new ByteArrayInputStream(
+                    bos.toByteArray());
+            ObjectInputStream ois = new ObjectInputStream(bin);
+            return (T) ois.readObject();
+        } catch(Exception e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+    }
+
+    static <T extends Enum<T>> void AddRandoms(EnumSet<T> s, Enum[] universe) {
+        for (int i=0; i < universe.length * 2 / 3; i++) {
+            T e = (T) universe[rnd.nextInt(universe.length)];
+
+            boolean prePresent = s.contains(e);
+            int preSize = s.size();
+            boolean added = s.add(e);
+            Assert.assertTrue(s.contains(e));
+            Assert.assertFalse(added == prePresent);
+            int postSize = s.size();
+            Assert.assertFalse(added && preSize == postSize);
+            Assert.assertFalse(!added && preSize != postSize);
+        }
+    }
+
+    public enum Silly0 { };
+
+    public enum Silly1 { e1 }
+
+    public enum Silly31 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30
+    }
+
+    public enum Silly32 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31
+    }
+
+    public enum Silly33 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32
+    }
+
+    public enum Silly63 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62
+    }
+
+    public enum Silly64 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63
+    }
+
+    public enum Silly65 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64
+    }
+
+    public enum Silly127 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126
+    }
+
+    public enum Silly128 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126, e127
+    }
+
+    public enum Silly129 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128
+    }
+
+    public enum Silly500 {
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
+        e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
+        e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
+        e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
+        e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
+        e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
+        e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
+        e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
+        e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128, e129,
+        e130, e131, e132, e133, e134, e135, e136, e137, e138, e139, e140, e141,
+        e142, e143, e144, e145, e146, e147, e148, e149, e150, e151, e152, e153,
+        e154, e155, e156, e157, e158, e159, e160, e161, e162, e163, e164, e165,
+        e166, e167, e168, e169, e170, e171, e172, e173, e174, e175, e176, e177,
+        e178, e179, e180, e181, e182, e183, e184, e185, e186, e187, e188, e189,
+        e190, e191, e192, e193, e194, e195, e196, e197, e198, e199, e200, e201,
+        e202, e203, e204, e205, e206, e207, e208, e209, e210, e211, e212, e213,
+        e214, e215, e216, e217, e218, e219, e220, e221, e222, e223, e224, e225,
+        e226, e227, e228, e229, e230, e231, e232, e233, e234, e235, e236, e237,
+        e238, e239, e240, e241, e242, e243, e244, e245, e246, e247, e248, e249,
+        e250, e251, e252, e253, e254, e255, e256, e257, e258, e259, e260, e261,
+        e262, e263, e264, e265, e266, e267, e268, e269, e270, e271, e272, e273,
+        e274, e275, e276, e277, e278, e279, e280, e281, e282, e283, e284, e285,
+        e286, e287, e288, e289, e290, e291, e292, e293, e294, e295, e296, e297,
+        e298, e299, e300, e301, e302, e303, e304, e305, e306, e307, e308, e309,
+        e310, e311, e312, e313, e314, e315, e316, e317, e318, e319, e320, e321,
+        e322, e323, e324, e325, e326, e327, e328, e329, e330, e331, e332, e333,
+        e334, e335, e336, e337, e338, e339, e340, e341, e342, e343, e344, e345,
+        e346, e347, e348, e349, e350, e351, e352, e353, e354, e355, e356, e357,
+        e358, e359, e360, e361, e362, e363, e364, e365, e366, e367, e368, e369,
+        e370, e371, e372, e373, e374, e375, e376, e377, e378, e379, e380, e381,
+        e382, e383, e384, e385, e386, e387, e388, e389, e390, e391, e392, e393,
+        e394, e395, e396, e397, e398, e399, e400, e401, e402, e403, e404, e405,
+        e406, e407, e408, e409, e410, e411, e412, e413, e414, e415, e416, e417,
+        e418, e419, e420, e421, e422, e423, e424, e425, e426, e427, e428, e429,
+        e430, e431, e432, e433, e434, e435, e436, e437, e438, e439, e440, e441,
+        e442, e443, e444, e445, e446, e447, e448, e449, e450, e451, e452, e453,
+        e454, e455, e456, e457, e458, e459, e460, e461, e462, e463, e464, e465,
+        e466, e467, e468, e469, e470, e471, e472, e473, e474, e475, e476, e477,
+        e478, e479, e480, e481, e482, e483, e484, e485, e486, e487, e488, e489,
+        e490, e491, e492, e493, e494, e495, e496, e497, e498, e499
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/InsertWrongType.java b/ojluni/src/test/java/util/EnumSet/InsertWrongType.java
new file mode 100644
index 0000000..f57df62
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/InsertWrongType.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug     5050285
+ * @summary Inserting enum of wrong type does horrible things to EnumSet/Map
+ * @author  Josh Bloch
+ */
+package test.java.util.EnumSet;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class InsertWrongType {
+
+    @Test
+    public void testInsertWrongType() {
+        // Ordinal in range
+        addIllTypedElt(Test32.class,  Test33.T1);  // Regular
+        addIllTypedElt(Test127.class, Test128.T1); // Jumbo
+
+        // Ordinal out of range
+        addIllTypedElt(Test32.class,  Test33.T33);   // Regular
+        addIllTypedElt(Test127.class, Test128.T128); // Jumbo
+
+        // Ordinal in range
+        addAllIllTypedElt(Test32.class,  Test33.T1);  // Regular
+        addAllIllTypedElt(Test127.class, Test128.T1); // Jumbo
+
+        // Ordinal out of range
+        addAllIllTypedElt(Test32.class,  Test33.T33);   // Regular
+        addAllIllTypedElt(Test127.class, Test128.T128); // Jumbo
+
+        addAllEmptyMistypedEnumSet(Test32.class, Test33.class);   // Regular
+        addAllEmptyMistypedEnumSet(Test127.class, Test128.class); // Jumbo
+
+        heterogeneousCopyOf(Test32.T1,  Test33.T2);     // Regular
+        heterogeneousCopyOf(Test127.T1,  Test128.T2);   // Jumbo
+
+        heterogeneousOf2(Test32.T1,  Test33.T2);     // Regular
+        heterogeneousOf2(Test127.T1,  Test128.T2);   // Jumbo
+
+        heterogeneousOf3(Test32.T1,  Test33.T2);     // Regular
+        heterogeneousOf3(Test127.T1,  Test128.T2);   // Jumbo
+
+        heterogeneousOf4(Test32.T1,  Test33.T2);     // Regular
+        heterogeneousOf4(Test127.T1,  Test128.T2);   // Jumbo
+
+        heterogeneousOf5(Test32.T1,  Test33.T2);     // Regular
+        heterogeneousOf5(Test127.T1,  Test128.T2);   // Jumbo
+
+        heterogeneousOfVar(Test32.T1,  Test33.T2);     // Regular
+        heterogeneousOfVar(Test127.T1,  Test128.T2);   // Jumbo
+
+        putIllTypedKey(Test32.class,  Test33.T1);
+        putIllTypedKey(Test32.class,  Test33.T33);
+
+        putAllIllTypedKey(Test32.class,  Test33.T1);
+        putAllIllTypedKey(Test32.class,  Test33.T33);
+
+        putAllIllTypedKeyEnumMap(Test32.class,  Test33.T1);
+        putAllIllTypedKeyEnumMap(Test32.class,  Test33.T33);
+
+        putAllEmptyMistypedEnumMap(Test32.class, Test33.class);
+    }
+
+
+    static void addIllTypedElt(Class enumClass, Enum elt) {
+        EnumSet set = EnumSet.noneOf(enumClass);
+        try {
+            set.add(elt);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void addAllIllTypedElt(Class enumClass, Enum elt) {
+        EnumSet set = EnumSet.noneOf(enumClass);
+        try {
+            set.addAll(Collections.singleton(elt));
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void addAllEmptyMistypedEnumSet(Class destClass, Class srcClass) {
+        EnumSet dest = EnumSet.noneOf(destClass);
+        EnumSet src  = EnumSet.noneOf(srcClass);
+        dest.addAll(src);
+    }
+
+    static void heterogeneousCopyOf(Enum e1, Enum e2) {
+        List list = new ArrayList();
+        list.add(e1);
+        list.add(e2);
+        try {
+            EnumSet.copyOf(list);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void heterogeneousOf2(Enum e1, Enum e2) {
+        try {
+            EnumSet.of(e1, e2);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void heterogeneousOf3(Enum e1, Enum e2) {
+        try {
+            EnumSet.of(e1, e1, e2);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void heterogeneousOf4(Enum e1, Enum e2) {
+        try {
+            EnumSet.of(e1, e1, e1, e2);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void heterogeneousOf5(Enum e1, Enum e2) {
+        try {
+            EnumSet.of(e1, e1, e1, e1, e2);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void heterogeneousOfVar(Enum e1, Enum e2) {
+        try {
+            EnumSet.of(e1, e1, e1, e1, e1, e2);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void putIllTypedKey(Class enumClass, Enum elt) {
+        EnumMap map = new EnumMap(enumClass);
+        try {
+            map.put(elt, "foofy");
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void putAllIllTypedKey(Class enumClass, Enum elt) {
+        EnumMap dest = new EnumMap(enumClass);
+        Map src = new HashMap();
+        src.put(elt, "goofy");
+        try {
+            dest.putAll(src);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void putAllIllTypedKeyEnumMap(Class enumClass, Enum elt) {
+        EnumMap dest = new EnumMap(enumClass);
+        Map src = new EnumMap(elt.getClass());
+        src.put(elt, "goofy");
+        try {
+            dest.putAll(src);
+            Assert.fail();
+        } catch(ClassCastException e) {}
+    }
+
+    static void putAllEmptyMistypedEnumMap(Class destClass, Class srcClass) {
+        EnumMap dest = new EnumMap(destClass);
+        EnumMap src = new EnumMap(srcClass);
+        dest.putAll(src);
+    }
+
+    enum Test32 {
+        T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16,
+        T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+        T31, T32
+    }
+
+    enum Test33 {
+        T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16,
+        T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+        T31, T32, T33
+    }
+
+    enum Test127 {
+        T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126, T127
+    }
+
+    enum Test128 {
+        T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126, T127, T128
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/JumboRange.java b/ojluni/src/test/java/util/EnumSet/JumboRange.java
new file mode 100644
index 0000000..571db85
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/JumboRange.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug     4958003
+ * @summary Range static factory fails to compute size in Jumbo enum set
+ * @author  Josh Bloch
+ */
+package test.java.util.EnumSet;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class JumboRange {
+
+    @Test
+    public void testJumboRange() {
+        test(Test127.class, Test127.T2, Test127.T6);
+        test(Test127.class, Test127.T126, Test127.T126);
+        test(Test127.class, Test127.T0, Test127.T126);
+    }
+
+    static <T extends Enum<T>> void test(Class<T> enumClass, T e0,T e1) {
+        EnumSet<T> range = EnumSet.range(e0, e1);
+        Assert.assertEquals(range.size(), e1.ordinal() - e0.ordinal() + 1);
+    }
+
+    public enum Test127 {
+        T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/LargeEnumIteratorRemoveResilience.java b/ojluni/src/test/java/util/EnumSet/LargeEnumIteratorRemoveResilience.java
new file mode 100644
index 0000000..79071f6
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/LargeEnumIteratorRemoveResilience.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2011 IBM Corporation
+ */
+
+/*
+ * @test
+ * @bug 7014637
+ * @summary EnumSet's iterator.remove() can be resilient to set's modification.
+ * @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
+ */
+package test.java.util.EnumSet;
+
+
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class LargeEnumIteratorRemoveResilience {
+    // enum with more than 64 values
+    private enum LargeEnum {
+        e00, e01, e02, e03, e04, e05, e06, e07,
+        e08, e09, e0A, e0B, e0C, e0D, e0E, e0F,
+        e10, e11, e12, e13, e14, e15, e16, e17,
+        e18, e19, e1A, e1B, e1C, e1D, e1E, e1F,
+        e20, e21, e22, e23, e24, e25, e26, e27,
+        e28, e29, e2A, e2B, e2C, e2D, e2E, e2F,
+        e30, e31, e32, e33, e34, e35, e36, e37,
+        e38, e39, e3A, e3B, e3C, e3D, e3E, e3F,
+        e40, e41, e42, e43, e44, e45, e46, e47,
+        e48, e49, e4A, e4B, e4C, e4D, e4E, e4F,
+    }
+
+    @Test
+    public void testLargeEnumIterator() throws Exception {
+        final Set<LargeEnum> set = EnumSet.noneOf(LargeEnum.class);
+
+        set.add(LargeEnum.e2D);
+        set.add(LargeEnum.e42);
+
+        final Iterator<LargeEnum> iterator = set.iterator();
+
+        int size = set.size();
+        LargeEnum element = iterator.next();
+
+        iterator.remove();
+        checkSetAfterRemoval(set, size, element);
+
+        size = set.size();
+        element = iterator.next();
+
+        set.remove(element);
+        checkSetAfterRemoval(set, size, element);
+
+        // The Java API declares that the behaviour here - to call
+        // iterator.remove() after the underlying collection has been
+        // modified - is "unspecified".
+        // However, in the case of iterators for EnumSet, it is easy to
+        // implement their remove() operation such that the set is
+        // unmodified if it is called for an element that has already been
+        // removed from the set - this being the naturally "resilient"
+        // behaviour.
+        iterator.remove();
+        checkSetAfterRemoval(set, size, element);
+    }
+
+    private static void checkSetAfterRemoval(final Set<LargeEnum> set,
+            final int origSize, final LargeEnum removedElement) {
+        Assert.assertEquals(set.size(), (origSize - 1));
+        Assert.assertFalse(set.contains(removedElement));
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/Range.java b/ojluni/src/test/java/util/EnumSet/Range.java
new file mode 100644
index 0000000..8c1a875
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/Range.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug     4952736
+ * @summary Range static factory is broken in Regular and Jumbo enum set
+ * @author  Josh Bloch
+ */
+package test.java.util.EnumSet;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class Range {
+
+    @Test
+    public void testRange() {
+        test(Test33.class, Test33.T6, Test33.T2);
+        test(Test127.class, Test127.T6, Test127.T2);
+    }
+
+    static <T extends Enum<T>> void test(Class<T> enumClass, T e0,T e1) {
+        try {
+            EnumSet<T> range = EnumSet.range(e0, e1);
+            Assert.fail();
+        } catch(IllegalArgumentException e) {
+            return;
+        }
+        throw new RuntimeException(enumClass.toString());
+    }
+
+    public enum Test33 {
+        T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16,
+        T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+        T31, T32, T33
+    }
+
+    public enum Test127 {
+        T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+        T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+        T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+        T44, T45, T46, T47, T48, T49, T50, T51, T52, T53, T54, T55, T56, T57,
+        T58, T59, T60, T61, T62, T63, T64, T65, T66, T67, T68, T69, T70, T71,
+        T72, T73, T74, T75, T76, T77, T78, T79, T80, T81, T82, T83, T84, T85,
+        T86, T87, T88, T89, T90, T91, T92, T93, T94, T95, T96, T97, T98, T99,
+        T100, T101, T102, T103, T104, T105, T106, T107, T108, T109, T110, T111,
+        T112, T113, T114, T115, T116, T117, T118, T119, T120, T121, T122, T123,
+        T124, T125, T126
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/EnumSet/SmallEnumIteratorRemoveResilience.java b/ojluni/src/test/java/util/EnumSet/SmallEnumIteratorRemoveResilience.java
new file mode 100644
index 0000000..80f2e3e
--- /dev/null
+++ b/ojluni/src/test/java/util/EnumSet/SmallEnumIteratorRemoveResilience.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 7014637
+ * @summary EnumSet's iterator.remove() can be resilient to set's modification.
+ * @author Neil Richards <neil.richards@ngmr.net>, <neil_richards@uk.ibm.com>
+ */
+package test.java.util.EnumSet;
+
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class SmallEnumIteratorRemoveResilience {
+    // enum with less than 64 values
+    private enum SmallEnum { e0, e1, e2 }
+
+    @Test
+    public void testSmallEnumRemoveResilience() {
+        final Set<SmallEnum> set = EnumSet.noneOf(SmallEnum.class);
+
+        set.add(SmallEnum.e0);
+        set.add(SmallEnum.e1);
+
+        final Iterator<SmallEnum> iterator = set.iterator();
+
+        int size = set.size();
+        SmallEnum element = iterator.next();
+
+        iterator.remove();
+        checkSetAfterRemoval(set, size, element);
+
+        size = set.size();
+        element = iterator.next();
+
+        set.remove(element);
+        checkSetAfterRemoval(set, size, element);
+
+        // The Java API declares that the behaviour here - to call
+        // iterator.remove() after the underlying collection has been
+        // modified - is "unspecified".
+        // However, in the case of iterators for EnumSet, it is easy to
+        // implement their remove() operation such that the set is
+        // unmodified if it is called for an element that has already been
+        // removed from the set - this being the naturally "resilient"
+        // behaviour.
+        iterator.remove();
+        checkSetAfterRemoval(set, size, element);
+    }
+
+    private static void checkSetAfterRemoval(final Set<SmallEnum> set,
+            final int origSize, final SmallEnum removedElement) {
+        Assert.assertEquals(set.size(), (origSize - 1));
+        Assert.assertFalse(set.contains(removedElement));
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/GregorianCalendar/GregorianCalendarTest.java b/ojluni/src/test/java/util/GregorianCalendar/GregorianCalendarTest.java
new file mode 100644
index 0000000..74f351f
--- /dev/null
+++ b/ojluni/src/test/java/util/GregorianCalendar/GregorianCalendarTest.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4614842
+ * @summary Make sure that a Date and a GregorianCalendar produce the same date/time. Both are new implementations in 1.5.
+ * @run main DateGregorianCalendarTest 15
+ */
+package test.java.util.GregorianCalendar;
+
+import java.util.*;
+
+import org.testng.annotations.Test;
+
+public class GregorianCalendarTest {
+    static volatile boolean runrun = true;
+    static int nThreads;
+
+    @Test
+    public void testGregorianCalendar() {
+        int duration = 600;
+
+        TimeZone savedTZ = TimeZone.getDefault();
+        try {
+            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+            Thread[] t = new Thread[10]; // for future bugs...
+            int index = 0;
+            t[index++] = new Thread(new Runnable() {
+                public void run() {
+                    GregorianCalendar gc = new GregorianCalendar();
+
+                    long delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000);
+                    long count = 0;
+                    try {
+                        for (long t = Long.MIN_VALUE; runrun && t < Long.MAX_VALUE-delta; t += delta) {
+                            gc.setTimeInMillis(t);
+                            Date date = new Date(t);
+                            int y;
+                            if (!((y = gc.get(java.util.Calendar.YEAR)) == (date.getYear()+1900) &&
+                                    gc.get(java.util.Calendar.MONTH) == date.getMonth() &&
+                                    gc.get(java.util.Calendar.DAY_OF_MONTH) == date.getDate() &&
+                                    gc.get(java.util.Calendar.HOUR_OF_DAY) == date.getHours() &&
+                                    gc.get(java.util.Calendar.MINUTE) == date.getMinutes() &&
+                                    gc.get(java.util.Calendar.SECOND) == date.getSeconds())) {
+                                throw new RuntimeException("GregorinCalendar and Date returned different dates."
+                                        +" (millis=" + t + ")\n"
+                                        +"GC=" + gc + "\nDate=" + date);
+                            }
+                            ++count;
+                            if (y >= 1) {
+                                delta = (long)(365.2422 * 24 * 60 * 60 * 1000);
+                            }
+                            if (y >= 1970) {
+                                delta = (24 * 60 * 60 * 1000);
+                            }
+                            if (y >= 2039) {
+                                delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000);
+                            }
+                        }
+                    } catch (RuntimeException e) {
+                        runrun = false;
+                        throw e;
+                    } finally {
+                        decrementCounter();
+                    }
+                }
+            });
+
+            t[index++] = new Thread(new Runnable() {
+                public void run() {
+                    GregorianCalendar gc = new GregorianCalendar();
+
+                    long count = 0;
+                    int delta;
+                    try {
+                        for (long year = Integer.MIN_VALUE+1900;
+                                runrun && year <= Integer.MAX_VALUE; year += delta) {
+                            checkTimes(gc, year, java.util.Calendar.JANUARY,
+                                    1, 0, 0, 0);
+                            ++count;
+                            delta = getDelta((int)year);
+                        }
+
+                        for (long month = Integer.MIN_VALUE;
+                                runrun && month <= Integer.MAX_VALUE; month += delta) {
+                            checkTimes(gc, 1900, month, 1,
+                                    0, 0, 0);
+                            ++count;
+                            delta = getDelta(gc.get(java.util.Calendar.YEAR));
+                        }
+
+                        for (long dayOfMonth = Integer.MIN_VALUE;
+                                runrun && dayOfMonth <= Integer.MAX_VALUE; dayOfMonth += delta) {
+                            checkTimes(gc, 1900, java.util.Calendar.JANUARY, dayOfMonth,
+                                    0, 0, 0);
+                            ++count;
+                            delta = getDelta(gc.get(java.util.Calendar.YEAR));
+                        }
+                    } catch (RuntimeException e) {
+                        runrun = false;
+                        throw e;
+                    } finally {
+                        decrementCounter();
+                    }
+                }
+            });
+
+            // t3 takes more than 10 minutes (on Ultra-60 450MHz) without
+            // the 4936355 fix due to getting the small delta.
+            t[index++] = new Thread(new Runnable() {
+                public void run() {
+                    GregorianCalendar gc = new GregorianCalendar();
+
+                    long count = 0;
+                    int delta;
+                    try {
+                        for (long hourOfDay = Integer.MIN_VALUE;
+                                runrun && hourOfDay <= Integer.MAX_VALUE; hourOfDay += delta) {
+                            checkTimes(gc, 1970, java.util.Calendar.JANUARY,
+                                    1, hourOfDay, 0, 0);
+                            ++count;
+                            delta = getDelta(gc.get(java.util.Calendar.YEAR));
+                        }
+                        for (long minutes = Integer.MIN_VALUE;
+                                runrun && minutes <= Integer.MAX_VALUE; minutes += delta) {
+                            checkTimes(gc, 1970, java.util.Calendar.JANUARY,
+                                    1, 0, minutes, 0);
+                            ++count;
+                            delta = getDelta(gc.get(java.util.Calendar.YEAR)) * 60;
+                        }
+                        for (long seconds = Integer.MIN_VALUE;
+                                runrun && seconds <= Integer.MAX_VALUE; seconds += delta) {
+                            checkTimes(gc, 1970, java.util.Calendar.JANUARY,
+                                    1, 0, 0, seconds);
+                            ++count;
+                            delta = getDelta(gc.get(java.util.Calendar.YEAR)) * 60 * 60;
+                        }
+                    } catch (RuntimeException e) {
+                        runrun = false;
+                        throw e;
+                    } finally {
+                        decrementCounter();
+                    }
+                }
+            });
+
+            for (int i = 0; i < index; i++) {
+                incrementCounter();
+                t[i].start();
+            }
+
+            try {
+                for (int i = 0; getCounter() > 0 && i < duration; i++) {
+                    Thread.sleep(1000);
+                }
+                runrun = false;
+                for (int i = 0; i < index; i++) {
+                    t[i].join();
+                }
+            } catch (InterruptedException e) {
+            }
+        } finally {
+            TimeZone.setDefault(savedTZ);
+        }
+    }
+
+    static void checkTimes(GregorianCalendar gc, long year, long month, long dayOfMonth,
+            long hourOfDay, long minutes, long seconds) {
+        gc.clear();
+        gc.set((int)year, (int)month, (int)dayOfMonth, (int)hourOfDay, (int)minutes, (int)seconds);
+        long time = gc.getTimeInMillis();
+        Date date = new Date((int)year - 1900, (int)month, (int)dayOfMonth,
+                (int)hourOfDay, (int)minutes, (int)seconds);
+        long time2 = date.getTime();
+        if (time != time2) {
+            throw new RuntimeException("GregorianCalendar and Date returned different values.\n"
+                    +"year="+year+", month="+month+", dayOfMonth="+dayOfMonth
+                    +"\nhourOfDay="+hourOfDay+", minutes="+minutes+", seconds="+seconds
+                    +"\ntime=" + time + ", time2=" + time2
+                    +"\nGC=" + gc + "\nDate=" + date);
+        }
+    }
+
+    static final int getDelta(int year) {
+        return (year >= 1970 && year <= 2039) ? 1 : 1<<13;
+    }
+
+    synchronized static void incrementCounter() {
+        nThreads++;
+    }
+
+    synchronized static void decrementCounter() {
+        nThreads--;
+    }
+
+    synchronized static int getCounter() {
+        return nThreads;
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/LinkedHashMap/Basic.java b/ojluni/src/test/java/util/LinkedHashMap/Basic.java
new file mode 100644
index 0000000..897cf09
--- /dev/null
+++ b/ojluni/src/test/java/util/LinkedHashMap/Basic.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4245809 8029795
+ * @summary Basic test for LinkedHashMap.  (Based on MapBash)
+ */
+package test.java.util.LinkedHashMap;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Random;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class Basic {
+    static final Random rnd = new Random(666);
+    static final Integer nil = new Integer(0);
+
+    @Test
+    public void testBasic() {
+        int numItr =  500;
+        int mapSize = 500;
+
+        // Linked List testk
+        for (int i=0; i<numItr; i++) {
+            Map<Integer,Integer> m = new LinkedHashMap();
+            Integer head = nil;
+
+            for (int j=0; j<mapSize; j++) {
+                Integer newHead;
+                do {
+                    newHead = new Integer(rnd.nextInt());
+                } while (m.containsKey(newHead));
+                m.put(newHead, head);
+                head = newHead;
+            }
+            Assert.assertEquals(m.size(), mapSize);
+
+            Assert.assertEquals(new HashMap(m).hashCode(), m.hashCode());
+
+            Map<Integer,Integer> m2 = new LinkedHashMap(); m2.putAll(m);
+            m2.values().removeAll(m.keySet());
+            Assert.assertFalse(m2.size()!= 1 || !m2.containsValue(nil));
+
+            int j=0;
+            while (head != nil) {
+                Assert.assertTrue(m.containsKey(head));
+                Integer newHead = m.get(head);
+                Assert.assertTrue(newHead != null);
+                m.remove(head);
+                head = newHead;
+                j++;
+            }
+            Assert.assertTrue(m.isEmpty());
+            Assert.assertEquals(j, mapSize);
+        }
+
+        Map<Integer,Integer> m = new LinkedHashMap();
+        for (int i=0; i<mapSize; i++)
+            Assert.assertEquals(m.put(new Integer(i), new Integer(2*i)), null);
+        for (int i=0; i<2*mapSize; i++)
+            Assert.assertEquals(m.containsValue(new Integer(i)), (i%2==0));
+        Assert.assertFalse(m.put(nil, nil) == null);
+        Map<Integer,Integer> m2 = new LinkedHashMap(); m2.putAll(m);
+        Assert.assertTrue(m.equals(m2));
+        Assert.assertTrue(m2.equals(m));
+        Set<Map.Entry<Integer,Integer>> s = m.entrySet(), s2 = m2.entrySet();
+        Assert.assertTrue(s.equals(s2));
+        Assert.assertTrue(s2.equals(s));
+        Assert.assertTrue(s.containsAll(s2));
+        Assert.assertTrue(s2.containsAll(s));
+
+        m2 = serClone(m);
+        Assert.assertTrue(m.equals(m2));
+        Assert.assertTrue(m2.equals(m));
+        s = m.entrySet(); s2 = m2.entrySet();
+        Assert.assertTrue(s.equals(s2));
+        Assert.assertTrue(s2.equals(s));
+        Assert.assertTrue(s.containsAll(s2));
+        Assert.assertTrue(s2.containsAll(s));
+
+        s2.removeAll(s);
+        Assert.assertTrue(m2.isEmpty());
+
+        m2.putAll(m);
+        m2.clear();
+        Assert.assertTrue(m2.isEmpty());
+
+        Iterator it = m.entrySet().iterator();
+        while (it.hasNext()) {
+            it.next();
+            it.remove();
+        }
+        Assert.assertTrue(m.isEmpty());
+
+        // Test ordering properties with insert order
+        m = new LinkedHashMap();
+        List<Integer> l = new ArrayList(mapSize);
+        for (int i=0; i<mapSize; i++) {
+            Integer x = new Integer(i);
+            m.put(x, x);
+            l.add(x);
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l));
+        for (int i=mapSize-1; i>=0; i--) {
+            Integer x = (Integer) l.get(i);
+            Assert.assertTrue(m.get(x).equals(x));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l));
+
+        for (int i=mapSize-1; i>=0; i--) {
+            Integer x = (Integer) l.get(i);
+            m.put(x, x);
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l));
+
+        m2 = (Map) ((LinkedHashMap)m).clone();
+        Assert.assertTrue(m.equals(m2));
+
+        List<Integer> l2 = new ArrayList(l);
+        Collections.shuffle(l2);
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(m2.get(x).equals(x));
+        }
+        Assert.assertTrue(new ArrayList(m2.keySet()).equals(l));
+
+        // Test ordering properties with access order
+        m = new LinkedHashMap(2*mapSize, .75f, true);
+        for (int i=0; i<mapSize; i++) {
+            Integer x = new Integer(i);
+            m.put(x, x);
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(m.get(x).equals(x));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(m.getOrDefault(x, new Integer(i + 1000)).equals(x));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(m.replace(x, x).equals(x));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(m.replace(x, x, x));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        BiFunction<Integer,Integer,Integer> f = (Integer y, Integer z) -> {
+            Assert.assertTrue(Objects.equals(y,z));
+            return new Integer(z);
+        };
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(x.equals(m.merge(x, x, f)));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(x.equals(m.compute(x, f)));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(x.equals(m.remove(x)));
+            Assert.assertTrue(x.equals(m.computeIfAbsent(x, Integer::valueOf)));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l2.get(i);
+            Assert.assertTrue(x.equals(m.computeIfPresent(x, f)));
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l2));
+
+        for (int i=0; i<mapSize; i++) {
+            Integer x = new Integer(i);
+            m.put(x, x);
+        }
+        Assert.assertTrue(new ArrayList(m.keySet()).equals(l));
+
+        m2 = (Map) ((LinkedHashMap)m).clone();
+        Assert.assertTrue(m.equals(m2));
+        for (int i=0; i<mapSize; i++) {
+            Integer x = (Integer) l.get(i);
+            Assert.assertTrue(m2.get(x).equals(x));
+        }
+        Assert.assertTrue(new ArrayList(m2.keySet()).equals(l));
+
+    }
+
+    private static Map serClone(Map m) {
+        Map result = null;
+        try {
+            // Serialize
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream(bos);
+            out.writeObject(m);
+            out.flush();
+
+            // Deserialize
+            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+            out.close();
+            ObjectInputStream in = new ObjectInputStream(bis);
+            result = (Map)in.readObject();
+            in.close();
+        } catch (Exception e) {
+            Assert.fail();
+        }
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/LinkedHashMap/Cache.java b/ojluni/src/test/java/util/LinkedHashMap/Cache.java
new file mode 100644
index 0000000..a53e40c
--- /dev/null
+++ b/ojluni/src/test/java/util/LinkedHashMap/Cache.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4245809
+ * @summary Basic test of removeEldestElement method.
+ */
+package test.java.util.LinkedHashMap;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class Cache {
+    private static final int MAP_SIZE = 10;
+    private static final int NUM_KEYS = 100;
+
+    @Test
+    public void testCache() throws Exception {
+        Map m = new LinkedHashMap() {
+            protected boolean removeEldestEntry(Map.Entry eldest) {
+                return size() > MAP_SIZE;
+            }
+        };
+
+        for (int i = 0; i < NUM_KEYS; i++) {
+            m.put(new Integer(i), "");
+            int eldest = ((Integer) m.keySet().iterator().next()).intValue();
+            Assert.assertEquals(eldest, Math.max(i-9, 0));
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/LinkedHashMap/ComputeIfAbsentAccessOrder.java b/ojluni/src/test/java/util/LinkedHashMap/ComputeIfAbsentAccessOrder.java
new file mode 100644
index 0000000..ccd0935
--- /dev/null
+++ b/ojluni/src/test/java/util/LinkedHashMap/ComputeIfAbsentAccessOrder.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.LinkedHashMap;
+
+import java.util.*;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8030016
+ * @summary computeIfAbsent would generate spurious access
+ */
+public class ComputeIfAbsentAccessOrder {
+
+    @Test
+    public void testComputeIfAbsent() {
+        LinkedHashMap<String,Object> map = new LinkedHashMap<>(2, 0.75f, true);
+        map.put("first", null);
+        map.put("second", null);
+
+        map.computeIfAbsent("first", l -> null); // should do nothing
+
+        Optional<String> key = map.keySet().stream()
+                .findFirst();
+        Assert.assertFalse(key.isEmpty());
+        Assert.assertTrue("first".equals(key.get()));
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/LinkedHashMap/EmptyMapIterator.java b/ojluni/src/test/java/util/LinkedHashMap/EmptyMapIterator.java
new file mode 100644
index 0000000..4672c1f
--- /dev/null
+++ b/ojluni/src/test/java/util/LinkedHashMap/EmptyMapIterator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4473440
+ * @summary iterators on collection views of empty map weren't fail-fast.
+ */
+package test.java.util.LinkedHashMap;
+
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class EmptyMapIterator {
+
+    @Test
+    public void testEmptyMapIterator() {
+        HashMap map = new HashMap();
+        Iterator iter = map.entrySet().iterator();
+        map.put("key", "value");
+
+        try {
+            iter.next();
+            Assert.fail();
+        } catch (ConcurrentModificationException e) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/LinkedHashSet/Basic.java b/ojluni/src/test/java/util/LinkedHashSet/Basic.java
new file mode 100644
index 0000000..82f470f
--- /dev/null
+++ b/ojluni/src/test/java/util/LinkedHashSet/Basic.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4245809
+ * @summary Basic test for LinkedHashSet.  (Based on SetBash)
+ */
+package test.java.util.LinkedHashSet;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Random;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class Basic {
+    static Random rnd = new Random(666);
+
+    @Test
+    public void testBasic() {
+        int numItr =  500;
+        int setSize = 500;
+
+        for (int i=0; i<numItr; i++) {
+            Set s1 = new LinkedHashSet();
+            AddRandoms(s1, setSize);
+
+            Set s2 = new LinkedHashSet();
+            AddRandoms(s2, setSize);
+
+            Set intersection = clone(s1);
+            intersection.retainAll(s2);
+            Set diff1 = clone(s1); diff1.removeAll(s2);
+            Set diff2 = clone(s2); diff2.removeAll(s1);
+            Set union = clone(s1); union.addAll(s2);
+
+            Assert.assertFalse(diff1.removeAll(diff2));
+            Assert.assertFalse(diff1.removeAll(intersection));
+            Assert.assertFalse(diff2.removeAll(diff1));
+            Assert.assertFalse(diff2.removeAll(intersection));
+            Assert.assertFalse(intersection.removeAll(diff1));
+            Assert.assertFalse(intersection.removeAll(diff1));
+
+            intersection.addAll(diff1); intersection.addAll(diff2);
+            Assert.assertTrue(intersection.equals(union));
+
+            Assert.assertEquals(new LinkedHashSet(union).hashCode(), union.hashCode());
+
+            Iterator e = union.iterator();
+            while (e.hasNext())
+                Assert.assertTrue(intersection.remove(e.next()));
+            Assert.assertTrue(intersection.isEmpty());
+
+            e = union.iterator();
+            while (e.hasNext()) {
+                Object o = e.next();
+                Assert.assertTrue(union.contains(o));
+                e.remove();
+                Assert.assertFalse(union.contains(o));
+            }
+            Assert.assertTrue(union.isEmpty());
+
+            s1.clear();
+            Assert.assertTrue(s1.isEmpty());
+        }
+    }
+
+    static Set clone(Set s) {
+        Set clone;
+        int method = rnd.nextInt(3);
+        clone = (method==0 ? (Set) ((LinkedHashSet)s).clone() :
+                (method==1 ? new LinkedHashSet(Arrays.asList(s.toArray())) :
+                        serClone(s)));
+        Assert.assertTrue(s.equals(clone));
+        Assert.assertTrue(s.containsAll(clone));
+        Assert.assertTrue(clone.containsAll(s));
+        return clone;
+    }
+
+    private static Set serClone(Set m) {
+        Set result = null;
+        try {
+            // Serialize
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream(bos);
+            out.writeObject(m);
+            out.flush();
+
+            // Deserialize
+            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+            out.close();
+            ObjectInputStream in = new ObjectInputStream(bis);
+            result = (Set)in.readObject();
+            in.close();
+        } catch (Exception e) {
+            Assert.fail();
+        }
+        return result;
+    }
+
+    static void AddRandoms(Set s, int n) {
+        for (int i = 0; i < n; i++) {
+            Integer e = rnd.nextInt(n);
+
+            int preSize = s.size();
+            boolean prePresent = s.contains(e);
+            boolean added = s.add(e);
+            Assert.assertTrue(s.contains(e));
+            Assert.assertFalse(added == prePresent);
+            int postSize = s.size();
+            Assert.assertFalse(added && preSize == postSize);
+            Assert.assertFalse(!added && preSize != postSize);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/BasicSerialization.java b/ojluni/src/test/java/util/Map/BasicSerialization.java
new file mode 100644
index 0000000..a68bee8
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/BasicSerialization.java
@@ -0,0 +1,218 @@
+
+
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 8011200
+ * @run testng BasicSerialization
+ * @summary Ensure Maps can be serialized and deserialized.
+ * @author Mike Duigou
+ */
+package test.java.util.Map;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.fail;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
+
+public class BasicSerialization {
+
+    enum IntegerEnum {
+
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
+        e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
+        e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
+        e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
+        e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
+        e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
+        e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
+        e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
+        e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
+        e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
+        EXTRA_KEY;
+        public static final int SIZE = values().length;
+    };
+    private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
+    /**
+     * Realized keys ensure that there is always a hard ref to all test objects.
+     */
+    private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
+    /**
+     * Realized values ensure that there is always a hard ref to all test
+     * objects.
+     */
+    private static final String[] VALUES = new String[TEST_SIZE];
+
+    static {
+        IntegerEnum[] keys = IntegerEnum.values();
+        for (int each = 0; each < TEST_SIZE; each++) {
+            KEYS[each] = keys[each];
+            VALUES[each] = keys[each].name();
+        }
+    }
+    private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
+    private static final String EXTRA_VALUE = IntegerEnum.EXTRA_KEY.name();
+
+    public static <K, V> Map<K, V> mapClone(Map<K, V> map) {
+        Method cloneMethod;
+
+        try {
+            cloneMethod = map.getClass().getMethod("clone", new Class[]{});
+        } catch (NoSuchMethodException | SecurityException all) {
+            cloneMethod = null;
+        }
+
+        if (null != cloneMethod) {
+            try {
+                Map<K, V> result = (Map<K, V>)cloneMethod.invoke(map, new Object[]{});
+                return result;
+            } catch (Exception all) {
+                fail("clone() failed " + map.getClass().getSimpleName(), all);
+                return null;
+            }
+        } else {
+            Constructor<? extends Map> copyConstructor;
+            try {
+                copyConstructor = (Constructor<? extends Map>)map.getClass().getConstructor(new Class[]{Map.class});
+
+                Map<K, V> result = (Map<K, V>)copyConstructor.newInstance(new Object[]{map});
+
+                return result;
+            } catch (Exception all) {
+                return serialClone(map);
+            }
+        }
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String>")
+    public void testSerialization(String description, Map<IntegerEnum, String> map) {
+        Object foo = new Object();
+
+        Map<IntegerEnum, String> clone = mapClone(map);
+        Map<IntegerEnum, String> serialClone = serialClone(map);
+
+        assertEquals(map, map, description + ":should equal self");
+        assertEquals(clone, map, description + ":should equal clone");
+        assertEquals(map, clone, description + ": should equal original map");
+        assertEquals(serialClone, map, description + ": should equal deserialized clone");
+        assertEquals(map, serialClone, description + ": should equal original map");
+        assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
+        assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
+
+        assertFalse(map.containsKey(EXTRA_KEY), description + ":unexpected key");
+        assertFalse(clone.containsKey(EXTRA_KEY), description + ":unexpected key");
+        assertFalse(serialClone.containsKey(EXTRA_KEY), description + ":unexpected key");
+        map.put(EXTRA_KEY, EXTRA_VALUE);
+        clone.put(EXTRA_KEY, EXTRA_VALUE);
+        serialClone.put(EXTRA_KEY, EXTRA_VALUE);
+        assertTrue(map.containsKey(EXTRA_KEY), description + ":missing key");
+        assertTrue(clone.containsKey(EXTRA_KEY), description + ":missing key");
+        assertTrue(serialClone.containsKey(EXTRA_KEY), description + ":missing key");
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
+        assertSame(clone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
+        assertSame(serialClone.get(EXTRA_KEY), EXTRA_VALUE, description + ":wrong value");
+
+        assertEquals(map, map, description + ":should equal self");
+        assertEquals(clone, map, description + ":should equal clone");
+        assertEquals(map, clone, description + ": should equal i map");
+        assertEquals(serialClone, map, description + ": should equal deserialized clone");
+        assertEquals(map, serialClone, description + ": should equal original map");
+        assertEquals(serialClone, clone, description + ": deserialized clone should equal clone");
+        assertEquals(clone, serialClone, description + ": clone should equal deserialized clone");
+    }
+
+    static byte[] serializedForm(Object obj) {
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            new ObjectOutputStream(baos).writeObject(obj);
+            return baos.toByteArray();
+        } catch (IOException e) {
+            fail("Unexpected Exception", e);
+            return null;
+        }
+    }
+
+    static Object readObject(byte[] bytes) throws IOException, ClassNotFoundException {
+        InputStream is = new ByteArrayInputStream(bytes);
+        return new ObjectInputStream(is).readObject();
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T> T serialClone(T obj) {
+        try {
+            return (T)readObject(serializedForm(obj));
+        } catch (IOException | ClassNotFoundException e) {
+            fail("Unexpected Exception", e);
+            return null;
+        }
+    }
+
+    @DataProvider(name = "Map<IntegerEnum,String>", parallel = true)
+    private static Iterator<Object[]> makeMaps() {
+        return Arrays.asList(
+                // empty
+                new Object[]{"HashMap", new HashMap()},
+                new Object[]{"LinkedHashMap", new LinkedHashMap()},
+                new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(new HashMap(), IntegerEnum.class, String.class)},
+                new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(new HashMap())},
+                // null hostile
+                new Object[]{"EnumMap", new EnumMap(IntegerEnum.class)},
+                new Object[]{"Hashtable", new Hashtable()},
+                new Object[]{"TreeMap", new TreeMap()},
+                new Object[]{"ConcurrentHashMap", new ConcurrentHashMap()},
+                new Object[]{"ConcurrentSkipListMap", new ConcurrentSkipListMap()},
+                new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(new ConcurrentHashMap(), IntegerEnum.class, String.class)},
+                new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(new EnumMap(IntegerEnum.class))},
+                // filled
+                new Object[]{"HashMap", fillMap(new HashMap())},
+                new Object[]{"LinkedHashMap", fillMap(new LinkedHashMap())},
+                new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(fillMap(new HashMap()), IntegerEnum.class, String.class)},
+                new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(fillMap(new HashMap()))},
+                // null hostile
+                new Object[]{"EnumMap", fillMap(new EnumMap(IntegerEnum.class))},
+                new Object[]{"Hashtable", fillMap(new Hashtable())},
+                new Object[]{"TreeMap", fillMap(new TreeMap())},
+                new Object[]{"ConcurrentHashMap", fillMap(new ConcurrentHashMap())},
+                new Object[]{"ConcurrentSkipListMap", fillMap(new ConcurrentSkipListMap())},
+                new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(fillMap(new ConcurrentHashMap()), IntegerEnum.class, String.class)},
+                new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(fillMap(new EnumMap(IntegerEnum.class)))}).iterator();
+    }
+
+    private static Map<IntegerEnum, String> fillMap(Map<IntegerEnum, String> result) {
+        for (int each = 0; each < TEST_SIZE; each++) {
+            result.put(KEYS[each], VALUES[each]);
+        }
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/Collisions.java b/ojluni/src/test/java/util/Map/Collisions.java
new file mode 100644
index 0000000..2312ee4
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/Collisions.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 7126277
+ * @run testng/othervm -Dtest.map.collisions.shortrun=true Collisions
+ * @summary Ensure Maps behave well with lots of hashCode() collisions.
+ */
+package test.java.util.Map;
+
+import java.util.BitSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+public class Collisions extends MapWithCollisionsProviders {
+
+    @Test(dataProvider = "mapsWithObjects")
+    public void testIntegerIteration(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val) {
+        Map<IntKey, IntKey> map = ms.get();
+        int mapSize = map.size();
+
+        BitSet all = new BitSet(mapSize);
+        for (Map.Entry<IntKey, IntKey> each : map.entrySet()) {
+            assertFalse(all.get(each.getKey().getValue()), "Iteration: key already seen");
+            all.set(each.getKey().getValue());
+        }
+
+        all.flip(0, mapSize);
+        assertTrue(all.isEmpty(), "Iteration: some keys not visited");
+
+        for (IntKey each : map.keySet()) {
+            assertFalse(all.get(each.getValue()), "Iteration: key already seen");
+            all.set(each.getValue());
+        }
+
+        all.flip(0, mapSize);
+        assertTrue(all.isEmpty(), "Iteration: some keys not visited");
+
+        int count = 0;
+        for (IntKey each : map.values()) {
+            count++;
+        }
+
+        assertEquals(map.size(), count,
+                String.format("Iteration: value count matches size m%d != c%d", map.size(), count));
+    }
+
+    @Test(dataProvider = "mapsWithStrings")
+    public void testStringIteration(String desc, Supplier<Map<String, String>> ms, String val) {
+        Map<String, String> map = ms.get();
+        int mapSize = map.size();
+
+        BitSet all = new BitSet(mapSize);
+        for (Map.Entry<String, String> each : map.entrySet()) {
+            String key = each.getKey();
+            boolean longKey = key.length() > 5;
+            int index = key.hashCode() + (longKey ? mapSize / 2 : 0);
+            assertFalse(all.get(index), "key already seen");
+            all.set(index);
+        }
+
+        all.flip(0, mapSize);
+        assertTrue(all.isEmpty(), "some keys not visited");
+
+        for (String each : map.keySet()) {
+            boolean longKey = each.length() > 5;
+            int index = each.hashCode() + (longKey ? mapSize / 2 : 0);
+            assertFalse(all.get(index), "key already seen");
+            all.set(index);
+        }
+
+        all.flip(0, mapSize);
+        assertTrue(all.isEmpty(), "some keys not visited");
+
+        int count = 0;
+        for (String each : map.values()) {
+            count++;
+        }
+
+        assertEquals(map.size(), mapSize,
+                String.format("value count matches size m%d != k%d", map.size(), mapSize));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+
+        for (int i = 0; i < keys.length; i++) {
+            Object each = keys[i];
+            assertNotNull(map.remove(each),
+                    String.format("remove: %s[%d]%s", desc, i, each));
+        }
+
+        assertTrue(map.size() == 0 && map.isEmpty(),
+                String.format("remove: map empty. size=%d", map.size()));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testKeysIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+
+        Iterator<Object> each = map.keySet().iterator();
+        while (each.hasNext()) {
+            Object t = each.next();
+            each.remove();
+            assertFalse(map.containsKey(t), String.format("not removed: %s", each));
+        }
+
+        assertTrue(map.size() == 0 && map.isEmpty(),
+                String.format("remove: map empty. size=%d", map.size()));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testValuesIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+
+        Iterator<Object> each = map.values().iterator();
+        while (each.hasNext()) {
+            Object t = each.next();
+            each.remove();
+            assertFalse(map.containsValue(t), String.format("not removed: %s", each));
+        }
+
+        assertTrue(map.size() == 0 && map.isEmpty(),
+                String.format("remove: map empty. size=%d", map.size()));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testEntriesIteratorRemove(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+
+        Iterator<Map.Entry<Object, Object>> each = map.entrySet().iterator();
+        while (each.hasNext()) {
+            Map.Entry<Object, Object> t = each.next();
+            Object key = t.getKey();
+            Object value = t.getValue();
+            each.remove();
+            assertTrue((map instanceof IdentityHashMap) || !map.entrySet().contains(t),
+                    String.format("not removed: %s", each));
+            assertFalse(map.containsKey(key),
+                    String.format("not removed: %s", each));
+            assertFalse(map.containsValue(value),
+                    String.format("not removed: %s", each));
+        }
+
+        assertTrue(map.size() == 0 && map.isEmpty(),
+                String.format("remove: map empty. size=%d", map.size()));
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/Defaults.java b/ojluni/src/test/java/util/Map/Defaults.java
new file mode 100644
index 0000000..21b1339
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/Defaults.java
@@ -0,0 +1,1044 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 8010122 8004518 8024331 8024688
+ * @summary Test Map default methods
+ * @author Mike Duigou
+ * @run testng Defaults
+ */
+package test.java.util.Map;
+
+import org.testng.Assert.ThrowingRunnable;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import static java.util.Objects.requireNonNull;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertThrows;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+public class Defaults {
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull")
+    public void testGetOrDefaultNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(null), description + ": null key absent");
+        assertNull(map.get(null), description + ": value not null");
+        assertSame(map.get(null), map.getOrDefault(null, EXTRA_VALUE), description + ": values should match");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=all values=all")
+    public void testGetOrDefault(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(KEYS[1]), "expected key missing");
+        assertSame(map.get(KEYS[1]), map.getOrDefault(KEYS[1], EXTRA_VALUE), "values should match");
+        assertFalse(map.containsKey(EXTRA_KEY), "expected absent key");
+        assertSame(map.getOrDefault(EXTRA_KEY, EXTRA_VALUE), EXTRA_VALUE, "value not returned as default");
+        assertNull(map.getOrDefault(EXTRA_KEY, null), "null not returned as default");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+    public void testPutIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
+        // null -> null
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
+        // null -> EXTRA_VALUE
+        assertTrue(map.containsKey(null), "null key absent");
+        assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
+        assertSame(map.putIfAbsent(null, null), EXTRA_VALUE, "previous not expected value");
+        assertTrue(map.containsKey(null), "null key absent");
+        assertSame(map.get(null), EXTRA_VALUE, "unexpected value");
+        assertSame(map.remove(null), EXTRA_VALUE, "removed unexpected value");
+        // null -> <absent>
+
+        assertFalse(map.containsKey(null), description + ": key present after remove");
+        assertNull(map.putIfAbsent(null, null), "previous not null");
+        // null -> null
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertNull(map.putIfAbsent(null, EXTRA_VALUE), "previous not null");
+        assertSame(map.get(null), EXTRA_VALUE, "value not expected");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testPutIfAbsent(String description, Map<IntegerEnum, String> map) {
+        // 1 -> 1
+        assertTrue(map.containsKey(KEYS[1]));
+        Object expected = map.get(KEYS[1]);
+        assertTrue(null == expected || expected == VALUES[1]);
+        assertSame(map.putIfAbsent(KEYS[1], EXTRA_VALUE), expected);
+        assertSame(map.get(KEYS[1]), expected);
+
+        // EXTRA_KEY -> <absent>
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertSame(map.putIfAbsent(EXTRA_KEY, EXTRA_VALUE), null);
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+        assertSame(map.putIfAbsent(EXTRA_KEY, VALUES[2]), EXTRA_VALUE);
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=all keys=all values=all")
+    public void testForEach(String description, Map<IntegerEnum, String> map) {
+        IntegerEnum[] EACH_KEY = new IntegerEnum[map.size()];
+
+        map.forEach((k, v) -> {
+            int idx = (null == k) ? 0 : k.ordinal(); // substitute for index.
+            assertNull(EACH_KEY[idx]);
+            EACH_KEY[idx] = (idx == 0) ? KEYS[0] : k; // substitute for comparison.
+            assertSame(v, map.get(k));
+        });
+
+        assertEquals(KEYS, EACH_KEY, description);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public static void testReplaceAll(String description, Map<IntegerEnum, String> map) {
+        IntegerEnum[] EACH_KEY = new IntegerEnum[map.size()];
+        Set<String> EACH_REPLACE = new HashSet<>(map.size());
+
+        map.replaceAll((k,v) -> {
+            int idx = (null == k) ? 0 : k.ordinal(); // substitute for index.
+            assertNull(EACH_KEY[idx]);
+            EACH_KEY[idx] = (idx == 0) ? KEYS[0] : k; // substitute for comparison.
+            assertSame(v, map.get(k));
+            String replacement = v + " replaced";
+            EACH_REPLACE.add(replacement);
+            return replacement;
+        });
+
+        assertEquals(KEYS, EACH_KEY, description);
+        assertEquals(map.values().size(), EACH_REPLACE.size(), description + EACH_REPLACE);
+        assertTrue(EACH_REPLACE.containsAll(map.values()), description + " : " + EACH_REPLACE + " != " + map.values());
+        assertTrue(map.values().containsAll(EACH_REPLACE), description + " : " + EACH_REPLACE + " != " + map.values());
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
+    public static void testReplaceAllNoNullReplacement(String description, Map<IntegerEnum, String> map) {
+        assertThrowsNPE(() -> map.replaceAll(null));
+        assertThrowsNPE(() -> map.replaceAll((k,v) -> null)); //should not allow replacement with null value
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+    public static void testRemoveNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertFalse(map.remove(null, EXTRA_VALUE), description);
+        assertTrue(map.containsKey(null));
+        assertNull(map.get(null));
+        assertTrue(map.remove(null, null));
+        assertFalse(map.containsKey(null));
+        assertNull(map.get(null));
+        assertFalse(map.remove(null, null));
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testRemove(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(KEYS[1]));
+        Object expected = map.get(KEYS[1]);
+        assertTrue(null == expected || expected == VALUES[1]);
+        assertFalse(map.remove(KEYS[1], EXTRA_VALUE), description);
+        assertSame(map.get(KEYS[1]), expected);
+        assertTrue(map.remove(KEYS[1], expected));
+        assertNull(map.get(KEYS[1]));
+        assertFalse(map.remove(KEYS[1], expected));
+
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertFalse(map.remove(EXTRA_KEY, EXTRA_VALUE));
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+    public void testReplaceKVNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertSame(map.replace(null, EXTRA_VALUE), null);
+        assertSame(map.get(null), EXTRA_VALUE);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
+    public void testReplaceKVNoNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
+        assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
+        assertThrowsNPE(() -> map.replace(FIRST_KEY, null));
+        assertSame(map.replace(FIRST_KEY, EXTRA_VALUE), FIRST_VALUE, description + ": replaced wrong value");
+        assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testReplaceKV(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(KEYS[1]));
+        Object expected = map.get(KEYS[1]);
+        assertTrue(null == expected || expected == VALUES[1]);
+        assertSame(map.replace(KEYS[1], EXTRA_VALUE), expected);
+        assertSame(map.get(KEYS[1]), EXTRA_VALUE);
+
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertNull(map.replace(EXTRA_KEY, EXTRA_VALUE));
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertNull(map.get(EXTRA_KEY));
+        assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+        assertSame(map.replace(EXTRA_KEY, (String)expected), EXTRA_VALUE);
+        assertSame(map.get(EXTRA_KEY), expected);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+    public void testReplaceKVVNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertFalse(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
+        assertNull(map.get(null));
+        assertTrue(map.replace(null, null, EXTRA_VALUE));
+        assertSame(map.get(null), EXTRA_VALUE);
+        assertTrue(map.replace(null, EXTRA_VALUE, EXTRA_VALUE));
+        assertSame(map.get(null), EXTRA_VALUE);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull")
+    public void testReplaceKVVNoNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(FIRST_KEY), "expected key missing");
+        assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value");
+        assertThrowsNPE(() -> map.replace(FIRST_KEY, FIRST_VALUE, null));
+        assertThrowsNPE(
+                () -> {
+                    if (!map.replace(FIRST_KEY, null, EXTRA_VALUE)) {
+                        throw new NullPointerException("default returns false rather than throwing");
+                    }
+                });
+        assertTrue(map.replace(FIRST_KEY, FIRST_VALUE, EXTRA_VALUE), description + ": replaced wrong value");
+        assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testReplaceKVV(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(KEYS[1]));
+        Object expected = map.get(KEYS[1]);
+        assertTrue(null == expected || expected == VALUES[1]);
+        assertFalse(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
+        assertSame(map.get(KEYS[1]), expected);
+        assertTrue(map.replace(KEYS[1], (String)expected, EXTRA_VALUE));
+        assertSame(map.get(KEYS[1]), EXTRA_VALUE);
+        assertTrue(map.replace(KEYS[1], EXTRA_VALUE, EXTRA_VALUE));
+        assertSame(map.get(KEYS[1]), EXTRA_VALUE);
+
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertFalse(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertNull(map.get(EXTRA_KEY));
+        assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
+        assertTrue(map.containsKey(EXTRA_KEY));
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+        assertTrue(map.replace(EXTRA_KEY, EXTRA_VALUE, EXTRA_VALUE));
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+    public void testComputeIfAbsentNulls(String description, Map<IntegerEnum, String> map) {
+        // null -> null
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertSame(map.computeIfAbsent(null, (k) -> null), null,  "not expected result");
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertSame(map.computeIfAbsent(null, (k) -> EXTRA_VALUE), EXTRA_VALUE, "not mapped to result");
+        // null -> EXTRA_VALUE
+        assertTrue(map.containsKey(null), "null key absent");
+        assertSame(map.get(null), EXTRA_VALUE,  "not expected value");
+        assertSame(map.remove(null), EXTRA_VALUE, "removed unexpected value");
+        // null -> <absent>
+        assertFalse(map.containsKey(null), "null key present");
+        assertSame(map.computeIfAbsent(null, (k) -> EXTRA_VALUE), EXTRA_VALUE, "not mapped to result");
+        // null -> EXTRA_VALUE
+        assertTrue(map.containsKey(null), "null key absent");
+        assertSame(map.get(null), EXTRA_VALUE,  "not expected value");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testComputeIfAbsent(String description, Map<IntegerEnum, String> map) {
+        // 1 -> 1
+        assertTrue(map.containsKey(KEYS[1]));
+        Object expected = map.get(KEYS[1]);
+        assertTrue(null == expected || expected == VALUES[1], description + String.valueOf(expected));
+        expected = (null == expected) ? EXTRA_VALUE : expected;
+        assertSame(map.computeIfAbsent(KEYS[1], (k) -> EXTRA_VALUE), expected, description);
+        assertSame(map.get(KEYS[1]), expected, description);
+
+        // EXTRA_KEY -> <absent>
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertNull(map.computeIfAbsent(EXTRA_KEY, (k) -> null));
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertSame(map.computeIfAbsent(EXTRA_KEY, (k) -> EXTRA_VALUE), EXTRA_VALUE);
+        // EXTRA_KEY -> EXTRA_VALUE
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testComputeIfAbsentNullFunction(String description, Map<IntegerEnum, String> map) {
+        assertThrowsNPE(() -> map.computeIfAbsent(KEYS[1], null));
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+    public void testComputeIfPresentNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(null), description + ": null key absent");
+        assertNull(map.get(null), description + ": value not null");
+        assertSame(map.computeIfPresent(null, (k, v) -> {
+            fail(description + ": null value is not deemed present");
+            return EXTRA_VALUE;
+        }), null, description);
+        assertTrue(map.containsKey(null));
+        assertNull(map.get(null), description);
+        assertNull(map.remove(EXTRA_KEY), description + ": unexpected mapping");
+        assertNull(map.put(EXTRA_KEY, null), description + ": unexpected value");
+        assertSame(map.computeIfPresent(EXTRA_KEY, (k, v) -> {
+            fail(description + ": null value is not deemed present");
+            return EXTRA_VALUE;
+        }), null, description);
+        assertNull(map.get(EXTRA_KEY), description + ": null mapping gone");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testComputeIfPresent(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(KEYS[1]));
+        Object value = map.get(KEYS[1]);
+        assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
+        Object expected = (null == value) ? null : EXTRA_VALUE;
+        assertSame(map.computeIfPresent(KEYS[1], (k, v) -> {
+            assertSame(v, value);
+            return EXTRA_VALUE;
+        }), expected, description);
+        assertSame(map.get(KEYS[1]), expected, description);
+
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertSame(map.computeIfPresent(EXTRA_KEY, (k, v) -> {
+            fail();
+            return EXTRA_VALUE;
+        }), null);
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertSame(map.get(EXTRA_KEY), null);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testComputeIfPresentNullFunction(String description, Map<IntegerEnum, String> map) {
+        assertThrowsNPE(() -> map.computeIfPresent(KEYS[1], null));
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull")
+    public void testComputeNulls(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(null), "null key absent");
+        assertNull(map.get(null), "value not null");
+        assertSame(map.compute(null, (k, v) -> {
+            assertNull(k);
+            assertNull(v);
+            return null;
+        }), null, description);
+        assertFalse(map.containsKey(null), description + ": null key present.");
+        assertSame(map.compute(null, (k, v) -> {
+            assertSame(k, null);
+            assertNull(v);
+            return EXTRA_VALUE;
+        }), EXTRA_VALUE, description);
+        assertTrue(map.containsKey(null));
+        assertSame(map.get(null), EXTRA_VALUE, description);
+        assertSame(map.remove(null), EXTRA_VALUE, description + ": removed value not expected");
+        // no mapping before and after
+        assertFalse(map.containsKey(null), description + ": null key present");
+        assertSame(map.compute(null, (k, v) -> {
+            assertNull(k);
+            assertNull(v);
+            return null;
+        }), null, description + ": expected null result" );
+        assertFalse(map.containsKey(null), description + ": null key present");
+        // compute with map not containing value
+        assertNull(map.remove(EXTRA_KEY),  description + ": unexpected mapping");
+        assertFalse(map.containsKey(EXTRA_KEY),  description + ": key present");
+        assertSame(map.compute(EXTRA_KEY, (k, v) -> {
+            assertSame(k, EXTRA_KEY);
+            assertNull(v);
+            return null;
+        }), null, description);
+        assertFalse(map.containsKey(EXTRA_KEY),  description + ": null key present");
+        // ensure removal.
+        assertNull(map.put(EXTRA_KEY, EXTRA_VALUE));
+        assertSame(map.compute(EXTRA_KEY, (k, v) -> {
+            assertSame(k, EXTRA_KEY);
+            assertSame(v, EXTRA_VALUE);
+            return null;
+        }), null, description + ": null resulted expected");
+        assertFalse(map.containsKey(EXTRA_KEY),  description + ": null key present");
+        // compute with map containing null value
+        assertNull(map.put(EXTRA_KEY, null),  description + ": unexpected value");
+        assertSame(map.compute(EXTRA_KEY, (k, v) -> {
+            assertSame(k, EXTRA_KEY);
+            assertNull(v);
+            return null;
+        }), null, description);
+        assertFalse(map.containsKey(EXTRA_KEY),  description + ": null key present");
+        assertNull(map.put(EXTRA_KEY, null),  description + ": unexpected value");
+        assertSame(map.compute(EXTRA_KEY, (k, v) -> {
+            assertSame(k, EXTRA_KEY);
+            assertNull(v);
+            return EXTRA_VALUE;
+        }), EXTRA_VALUE, description);
+        assertTrue(map.containsKey(EXTRA_KEY), "null key present");
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testCompute(String description, Map<IntegerEnum, String> map) {
+        assertTrue(map.containsKey(KEYS[1]));
+        Object value = map.get(KEYS[1]);
+        assertTrue(null == value || value == VALUES[1], description + String.valueOf(value));
+        assertSame(map.compute(KEYS[1], (k, v) -> {
+            assertSame(k, KEYS[1]);
+            assertSame(v, value);
+            return EXTRA_VALUE;
+        }), EXTRA_VALUE, description);
+        assertSame(map.get(KEYS[1]), EXTRA_VALUE, description);
+        assertNull(map.compute(KEYS[1], (k, v) -> {
+            assertSame(v, EXTRA_VALUE);
+            return null;
+        }), description);
+        assertFalse(map.containsKey(KEYS[1]));
+
+        assertFalse(map.containsKey(EXTRA_KEY));
+        assertSame(map.compute(EXTRA_KEY, (k, v) -> {
+            assertNull(v);
+            return EXTRA_VALUE;
+        }), EXTRA_VALUE);
+        assertTrue(map.containsKey(EXTRA_KEY));
+        assertSame(map.get(EXTRA_KEY), EXTRA_VALUE);
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testComputeNullFunction(String description, Map<IntegerEnum, String> map) {
+        assertThrowsNPE(() -> map.compute(KEYS[1], null));
+    }
+
+    @Test(dataProvider = "MergeCases")
+    public void testMerge(String description, Map<IntegerEnum, String> map, Merging.Value oldValue, Merging.Value newValue, Merging.Merger merger, Merging.Value put, Merging.Value result) {
+        // add and check initial conditions.
+        switch (oldValue) {
+            case ABSENT :
+                map.remove(EXTRA_KEY);
+                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
+                break;
+            case NULL :
+                map.put(EXTRA_KEY, null);
+                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+                assertNull(map.get(EXTRA_KEY), "wrong value");
+                break;
+            case OLDVALUE :
+                map.put(EXTRA_KEY, VALUES[1]);
+                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+                assertSame(map.get(EXTRA_KEY), VALUES[1], "wrong value");
+                break;
+            default:
+                fail("unexpected old value");
+        }
+
+        String returned = map.merge(EXTRA_KEY,
+                newValue == Merging.Value.NULL ? (String) null : VALUES[2],
+                merger
+        );
+
+        // check result
+
+        switch (result) {
+            case NULL :
+                assertNull(returned, "wrong value");
+                break;
+            case NEWVALUE :
+                assertSame(returned, VALUES[2], "wrong value");
+                break;
+            case RESULT :
+                assertSame(returned, VALUES[3], "wrong value");
+                break;
+            default:
+                fail("unexpected new value");
+        }
+
+        // check map
+        switch (put) {
+            case ABSENT :
+                assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
+                break;
+            case NULL :
+                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+                assertNull(map.get(EXTRA_KEY), "wrong value");
+                break;
+            case NEWVALUE :
+                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+                assertSame(map.get(EXTRA_KEY), VALUES[2], "wrong value");
+                break;
+            case RESULT :
+                assertTrue(map.containsKey(EXTRA_KEY), "key absent");
+                assertSame(map.get(EXTRA_KEY), VALUES[3], "wrong value");
+                break;
+            default:
+                fail("unexpected new value");
+        }
+    }
+
+    @Test(dataProvider = "Map<IntegerEnum,String> rw=true keys=all values=all")
+    public void testMergeNullMerger(String description, Map<IntegerEnum, String> map) {
+        assertThrowsNPE(() -> map.merge(KEYS[1], VALUES[1], null));
+    }
+
+    /** A function that flipflops between running two other functions. */
+    static <T,U,V> BiFunction<T,U,V> twoStep(AtomicBoolean b,
+            BiFunction<T,U,V> first,
+            BiFunction<T,U,V> second) {
+        return (t, u) -> {
+            boolean bb = b.get();
+            try {
+                return (b.get() ? first : second).apply(t, u);
+            } finally {
+                b.set(!bb);
+            }};
+    }
+
+    /**
+     * Simulates races by modifying the map within the mapping function.
+     */
+    @Test
+    public void testConcurrentMap_computeIfAbsent_racy() {
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        Function<Long,Long> f, g;
+
+        // race not detected if function returns null
+        f = (k) -> { map.put(two, 42L); return null; };
+        assertNull(map.computeIfAbsent(two, f));
+        assertEquals(42L, (long)map.get(two));
+
+        map.clear();
+        f = (k) -> { map.put(two, 42L); return 86L; };
+        assertEquals(42L, (long)map.computeIfAbsent(two, f));
+        assertEquals(42L, (long)map.get(two));
+
+        // mapping function ignored if value already exists
+        map.put(two, 99L);
+        assertEquals(99L, (long)map.computeIfAbsent(two, f));
+        assertEquals(99L, (long)map.get(two));
+    }
+
+    /**
+     * Simulates races by modifying the map within the remapping function.
+     */
+    @Test
+    public void testConcurrentMap_computeIfPresent_racy() {
+        final AtomicBoolean b = new AtomicBoolean(true);
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        BiFunction<Long,Long,Long> f, g;
+
+        for (Long val : new Long[] { null, 86L }) {
+            map.clear();
+
+            // Function not invoked if no mapping exists
+            f = (k, v) -> { map.put(two, 42L); return val; };
+            assertNull(map.computeIfPresent(two, f));
+            assertNull(map.get(two));
+
+            map.put(two, 42L);
+            f = (k, v) -> { map.put(two, 86L); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertEquals(86L, (long)v);
+                return null;
+            };
+            assertNull(map.computeIfPresent(two, twoStep(b, f, g)));
+            assertFalse(map.containsKey(two));
+            assertTrue(b.get());
+
+            map.put(two, 42L);
+            f = (k, v) -> { map.put(two, 86L); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertEquals(86L, (long)v);
+                return 99L;
+            };
+            assertEquals(99L, (long)map.computeIfPresent(two, twoStep(b, f, g)));
+            assertTrue(map.containsKey(two));
+            assertTrue(b.get());
+        }
+    }
+
+    @Test
+    public void testConcurrentMap_compute_simple() {
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        BiFunction<Long,Long,Long> fun = (k, v) -> ((v == null) ? 0L : k + v);
+        assertEquals(Long.valueOf(0L), map.compute(3L, fun));
+        assertEquals(Long.valueOf(3L), map.compute(3L, fun));
+        assertEquals(Long.valueOf(6L), map.compute(3L, fun));
+        assertNull(map.compute(3L, (k, v) -> null));
+        assertTrue(map.isEmpty());
+
+        assertEquals(Long.valueOf(0L), map.compute(new Long(3L), fun));
+        assertEquals(Long.valueOf(3L), map.compute(new Long(3L), fun));
+        assertEquals(Long.valueOf(6L), map.compute(new Long(3L), fun));
+        assertNull(map.compute(3L, (k, v) -> null));
+        assertTrue(map.isEmpty());
+    }
+
+    /**
+     * Simulates races by modifying the map within the remapping function.
+     */
+    @Test
+    public void testConcurrentMap_compute_racy() {
+        final AtomicBoolean b = new AtomicBoolean(true);
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        BiFunction<Long,Long,Long> f, g;
+
+        // null -> null is a no-op; race not detected
+        f = (k, v) -> { map.put(two, 42L); return null; };
+        assertNull(map.compute(two, f));
+        assertEquals(42L, (long)map.get(two));
+
+        for (Long val : new Long[] { null, 86L }) {
+            map.clear();
+
+            f = (k, v) -> { map.put(two, 42L); return 86L; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertEquals(42L, (long)v);
+                return k + v;
+            };
+            assertEquals(44L, (long)map.compute(two, twoStep(b, f, g)));
+            assertEquals(44L, (long)map.get(two));
+            assertTrue(b.get());
+
+            f = (k, v) -> { map.remove(two); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertNull(v);
+                return 44L;
+            };
+            assertEquals(44L, (long)map.compute(two, twoStep(b, f, g)));
+            assertEquals(44L, (long)map.get(two));
+            assertTrue(map.containsKey(two));
+            assertTrue(b.get());
+
+            f = (k, v) -> { map.remove(two); return val; };
+            g = (k, v) -> {
+                assertSame(two, k);
+                assertNull(v);
+                return null;
+            };
+            assertNull(map.compute(two, twoStep(b, f, g)));
+            assertNull(map.get(two));
+            assertFalse(map.containsKey(two));
+            assertTrue(b.get());
+        }
+    }
+
+    /**
+     * Simulates races by modifying the map within the remapping function.
+     */
+    @Test
+    public void testConcurrentMap_merge_racy() {
+        final AtomicBoolean b = new AtomicBoolean(true);
+        final ConcurrentMap<Long,Long> map = new ImplementsConcurrentMap<>();
+        final Long two = 2L;
+        BiFunction<Long,Long,Long> f, g;
+
+        for (Long val : new Long[] { null, 86L }) {
+            map.clear();
+
+            f = (v, w) -> { throw new AssertionError(); };
+            assertEquals(99L, (long)map.merge(two, 99L, f));
+            assertEquals(99L, (long)map.get(two));
+
+            f = (v, w) -> { map.put(two, 42L); return val; };
+            g = (v, w) -> {
+                assertEquals(42L, (long)v);
+                assertEquals(3L, (long)w);
+                return v + w;
+            };
+            assertEquals(45L, (long)map.merge(two, 3L, twoStep(b, f, g)));
+            assertEquals(45L, (long)map.get(two));
+            assertTrue(b.get());
+
+            f = (v, w) -> { map.remove(two); return val; };
+            g = (k, v) -> { throw new AssertionError(); };
+            assertEquals(55L, (long)map.merge(two, 55L, twoStep(b, f, g)));
+            assertEquals(55L, (long)map.get(two));
+            assertTrue(map.containsKey(two));
+            assertFalse(b.get()); b.set(true);
+        }
+    }
+
+    public enum IntegerEnum {
+
+        e0, e1, e2, e3, e4, e5, e6, e7, e8, e9,
+        e10, e11, e12, e13, e14, e15, e16, e17, e18, e19,
+        e20, e21, e22, e23, e24, e25, e26, e27, e28, e29,
+        e30, e31, e32, e33, e34, e35, e36, e37, e38, e39,
+        e40, e41, e42, e43, e44, e45, e46, e47, e48, e49,
+        e50, e51, e52, e53, e54, e55, e56, e57, e58, e59,
+        e60, e61, e62, e63, e64, e65, e66, e67, e68, e69,
+        e70, e71, e72, e73, e74, e75, e76, e77, e78, e79,
+        e80, e81, e82, e83, e84, e85, e86, e87, e88, e89,
+        e90, e91, e92, e93, e94, e95, e96, e97, e98, e99,
+        EXTRA_KEY;
+        public static final int SIZE = values().length;
+    }
+    private static final int TEST_SIZE = IntegerEnum.SIZE - 1;
+    /**
+     * Realized keys ensure that there is always a hard ref to all test objects.
+     */
+    private static final IntegerEnum[] KEYS = new IntegerEnum[TEST_SIZE];
+    /**
+     * Realized values ensure that there is always a hard ref to all test
+     * objects.
+     */
+    private static final String[] VALUES = new String[TEST_SIZE];
+
+    static {
+        IntegerEnum[] keys = IntegerEnum.values();
+        for (int each = 0; each < TEST_SIZE; each++) {
+            KEYS[each] = keys[each];
+            VALUES[each] = String.valueOf(each);
+        }
+    }
+
+    private static final IntegerEnum FIRST_KEY = KEYS[0];
+    private static final String FIRST_VALUE = VALUES[0];
+    private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY;
+    private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE);
+
+    @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=all values=all", parallel = true)
+    public static Iterator<Object[]> allMapProvider() {
+        return makeAllMaps().iterator();
+    }
+
+    @DataProvider(name = "Map<IntegerEnum,String> rw=all keys=withNull values=withNull", parallel = true)
+    public static Iterator<Object[]> allMapWithNullsProvider() {
+        return makeAllMapsWithNulls().iterator();
+    }
+
+    @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=nonNull", parallel = true)
+    public static Iterator<Object[]> rwNonNullMapProvider() {
+        return makeRWNoNullsMaps().iterator();
+    }
+
+    @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=nonNull values=all", parallel = true)
+    public static Iterator<Object[]> rwNonNullKeysMapProvider() {
+        return makeRWMapsNoNulls().iterator();
+    }
+
+    @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=all values=all", parallel = true)
+    public static Iterator<Object[]> rwMapProvider() {
+        return makeAllRWMaps().iterator();
+    }
+
+    @DataProvider(name = "Map<IntegerEnum,String> rw=true keys=withNull values=withNull", parallel = true)
+    public static Iterator<Object[]> rwNullsMapProvider() {
+        return makeAllRWMapsWithNulls().iterator();
+    }
+
+    private static Collection<Object[]> makeAllRWMapsWithNulls() {
+        Collection<Object[]> all = new ArrayList<>();
+
+        all.addAll(makeRWMaps(true, true));
+
+        return all;
+    }
+
+    private static Collection<Object[]> makeRWMapsNoNulls() {
+        Collection<Object[]> all = new ArrayList<>();
+
+        all.addAll(makeRWNoNullKeysMaps(false));
+        all.addAll(makeRWNoNullsMaps());
+
+        return all;
+    }
+
+    private static Collection<Object[]> makeAllROMaps() {
+        Collection<Object[]> all = new ArrayList<>();
+
+        all.addAll(makeROMaps(false));
+        all.addAll(makeROMaps(true));
+
+        return all;
+    }
+
+    private static Collection<Object[]> makeAllRWMaps() {
+        Collection<Object[]> all = new ArrayList<>();
+
+        all.addAll(makeRWNoNullsMaps());
+        all.addAll(makeRWMaps(false,true));
+        all.addAll(makeRWMaps(true,true));
+        all.addAll(makeRWNoNullKeysMaps(true));
+        return all;
+    }
+
+    private static Collection<Object[]> makeAllMaps() {
+        Collection<Object[]> all = new ArrayList<>();
+
+        all.addAll(makeAllROMaps());
+        all.addAll(makeAllRWMaps());
+
+        return all;
+    }
+
+    private static Collection<Object[]> makeAllMapsWithNulls() {
+        Collection<Object[]> all = new ArrayList<>();
+
+        all.addAll(makeROMaps(true));
+        all.addAll(makeRWMaps(true,true));
+
+        return all;
+    }
+
+    /**
+     * @param nullKeys include null keys
+     * @param nullValues include null values
+     * @return
+     */
+    private static Collection<Object[]> makeRWMaps(boolean nullKeys, boolean nullValues) {
+        return Arrays.asList(
+                new Object[]{"HashMap", makeMap(HashMap::new, nullKeys, nullValues)},
+                new Object[]{"IdentityHashMap", makeMap(IdentityHashMap::new, nullKeys, nullValues)},
+                new Object[]{"LinkedHashMap", makeMap(LinkedHashMap::new, nullKeys, nullValues)},
+                new Object[]{"WeakHashMap", makeMap(WeakHashMap::new, nullKeys, nullValues)},
+                new Object[]{"Collections.checkedMap(HashMap)", Collections.checkedMap(makeMap(HashMap::new, nullKeys, nullValues), IntegerEnum.class, String.class)},
+                new Object[]{"Collections.synchronizedMap(HashMap)", Collections.synchronizedMap(makeMap(HashMap::new, nullKeys, nullValues))},
+                new Object[]{"ExtendsAbstractMap", makeMap(ExtendsAbstractMap::new, nullKeys, nullValues)});
+    }
+
+    /**
+     * @param nulls include null values
+     * @return
+     */
+    private static Collection<Object[]> makeRWNoNullKeysMaps(boolean nulls) {
+        return Arrays.asList(
+                // null key hostile
+                new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls)},
+                new Object[]{"TreeMap", makeMap(TreeMap::new, false, nulls)},
+                new Object[]{"ExtendsAbstractMap(TreeMap)", makeMap(() -> {return new ExtendsAbstractMap(new TreeMap());}, false, nulls)},
+                new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls))}
+        );
+    }
+
+    private static Collection<Object[]> makeRWNoNullsMaps() {
+        return Arrays.asList(
+                // null key and value hostile
+                new Object[]{"Hashtable", makeMap(Hashtable::new, false, false)},
+                new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false, false)},
+                new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false, false)},
+                new Object[]{"Collections.synchronizedMap(ConcurrentHashMap)", Collections.synchronizedMap(makeMap(ConcurrentHashMap::new, false, false))},
+                new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false, false), IntegerEnum.class, String.class)},
+                new Object[]{"ExtendsAbstractMap(ConcurrentHashMap)", makeMap(() -> {return new ExtendsAbstractMap(new ConcurrentHashMap());}, false, false)},
+                new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false, false)}
+        );
+    }
+
+    /**
+     * @param nulls include nulls
+     * @return
+     */
+    private static Collection<Object[]> makeROMaps(boolean nulls) {
+        return Arrays.asList(new Object[][]{
+                new Object[]{"Collections.unmodifiableMap(HashMap)", Collections.unmodifiableMap(makeMap(HashMap::new, nulls, nulls))}
+        });
+    }
+
+    /**
+     * @param supplier a supplier of mutable map instances.
+     *
+     * @param nullKeys   include null keys
+     * @param nullValues include null values
+     * @return
+     */
+    private static Map<IntegerEnum, String> makeMap(Supplier<Map<IntegerEnum, String>> supplier, boolean nullKeys, boolean nullValues) {
+        Map<IntegerEnum, String> result = supplier.get();
+
+        for (int each = 0; each < TEST_SIZE; each++) {
+            IntegerEnum key = nullKeys ? (each == 0) ? null : KEYS[each] : KEYS[each];
+            String value = nullValues ? (each == 0) ? null : VALUES[each] : VALUES[each];
+
+            result.put(key, value);
+        }
+
+        return result;
+    }
+
+    static class Merging {
+        public enum Value {
+            ABSENT,
+            NULL,
+            OLDVALUE,
+            NEWVALUE,
+            RESULT
+        }
+
+        public enum Merger implements BiFunction<String,String,String> {
+            UNUSED {
+                public String apply(String oldValue, String newValue) {
+                    fail("should not be called");
+                    return null;
+                }
+            },
+            NULL {
+                public String apply(String oldValue, String newValue) {
+                    return null;
+                }
+            },
+            RESULT {
+                public String apply(String oldValue, String newValue) {
+                    return VALUES[3];
+                }
+            },
+        }
+    }
+
+    @DataProvider(name = "MergeCases", parallel = true)
+    public Iterator<Object[]> mergeCasesProvider() {
+        Collection<Object[]> cases = new ArrayList<>();
+
+        cases.addAll(makeMergeTestCases());
+
+        return cases.iterator();
+    }
+
+    static Collection<Object[]> makeMergeTestCases() {
+        Collection<Object[]> cases = new ArrayList<>();
+
+        for (Object[] mapParams : makeAllRWMaps() ) {
+            cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.ABSENT, Merging.Value.NEWVALUE, Merging.Merger.UNUSED, Merging.Value.NEWVALUE, Merging.Value.NEWVALUE });
+        }
+
+        for (Object[] mapParams : makeAllRWMaps() ) {
+            cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.NULL, Merging.Value.ABSENT, Merging.Value.NULL });
+        }
+
+        for (Object[] mapParams : makeAllRWMaps() ) {
+            cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.RESULT, Merging.Value.RESULT, Merging.Value.RESULT });
+        }
+
+        return cases;
+    }
+
+    public static void assertThrowsNPE(ThrowingRunnable r) {
+        assertThrows(NullPointerException.class, r);
+    }
+
+    /**
+     * A simple mutable map implementation that provides only default
+     * implementations of all methods. ie. none of the Map interface default
+     * methods have overridden implementations.
+     *
+     * @param <K> Type of keys
+     * @param <V> Type of values
+     */
+    public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K,V> {
+
+        protected final M map;
+
+        public ExtendsAbstractMap() { this( (M) new HashMap<K,V>()); }
+
+        protected ExtendsAbstractMap(M map) { this.map = map; }
+
+        @Override public Set<Map.Entry<K,V>> entrySet() {
+            return new AbstractSet<Map.Entry<K,V>>() {
+                @Override public int size() {
+                    return map.size();
+                }
+
+                @Override public Iterator<Map.Entry<K,V>> iterator() {
+                    final Iterator<Map.Entry<K,V>> source = map.entrySet().iterator();
+                    return new Iterator<Map.Entry<K,V>>() {
+                        public boolean hasNext() { return source.hasNext(); }
+                        public Map.Entry<K,V> next() { return source.next(); }
+                        public void remove() { source.remove(); }
+                    };
+                }
+
+                @Override public boolean add(Map.Entry<K,V> e) {
+                    return map.entrySet().add(e);
+                }
+            };
+        }
+
+        @Override public V put(K key, V value) {
+            return map.put(key, value);
+        }
+    }
+
+    /**
+     * A simple mutable concurrent map implementation that provides only default
+     * implementations of all methods, i.e. none of the ConcurrentMap interface
+     * default methods have overridden implementations.
+     *
+     * @param <K> Type of keys
+     * @param <V> Type of values
+     */
+    public static class ImplementsConcurrentMap<K,V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
+        public ImplementsConcurrentMap() { super(new ConcurrentHashMap<K,V>()); }
+
+        // ConcurrentMap reabstracts these methods.
+        //
+        // Unlike ConcurrentHashMap, we have zero tolerance for null values.
+
+        @Override public V replace(K k, V v) {
+            return map.replace(requireNonNull(k), requireNonNull(v));
+        }
+
+        @Override public boolean replace(K k, V v, V vv) {
+            return map.replace(requireNonNull(k),
+                    requireNonNull(v),
+                    requireNonNull(vv));
+        }
+
+        @Override public boolean remove(Object k, Object v) {
+            return map.remove(requireNonNull(k), requireNonNull(v));
+        }
+
+        @Override public V putIfAbsent(K k, V v) {
+            return map.putIfAbsent(requireNonNull(k), requireNonNull(v));
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/EntryComparators.java b/ojluni/src/test/java/util/Map/EntryComparators.java
new file mode 100644
index 0000000..28dbffc
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/EntryComparators.java
@@ -0,0 +1,138 @@
+
+
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 8009736 8010279
+ * @run testng EntryComparators
+ */
+package test.java.util.Map;
+
+import java.util.Comparator;
+import java.util.AbstractMap;
+import java.util.Map;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+/**
+ * Unit tests for Map.Entry.comparing
+ */
+@Test(groups = "unit")
+public class EntryComparators {
+
+    private <K, V> void assertPairComparison(K k1, V v1, K k2, V v2,
+            Comparator<Map.Entry<K, V>> ck,
+            Comparator<Map.Entry<K, V>> cv) {
+        final Map.Entry<K, V> p11 = new AbstractMap.SimpleImmutableEntry<>(k1, v1);
+        final Map.Entry<K, V> p12 = new AbstractMap.SimpleImmutableEntry<>(k1, v2);
+        final Map.Entry<K, V> p21 = new AbstractMap.SimpleImmutableEntry<>(k2, v1);
+        final Map.Entry<K, V> p22 = new AbstractMap.SimpleImmutableEntry<>(k2, v2);
+
+        assertTrue(ck.compare(p11, p11) == 0);
+        assertTrue(ck.compare(p12, p11) == 0);
+        assertTrue(ck.compare(p11, p12) == 0);
+        assertTrue(ck.compare(p12, p22) < 0);
+        assertTrue(ck.compare(p12, p21) < 0);
+        assertTrue(ck.compare(p21, p11) > 0);
+        assertTrue(ck.compare(p21, p12) > 0);
+
+        assertTrue(cv.compare(p11, p11) == 0);
+        assertTrue(cv.compare(p12, p11) > 0);
+        assertTrue(cv.compare(p11, p12) < 0);
+        assertTrue(cv.compare(p12, p22) == 0);
+        assertTrue(cv.compare(p12, p21) > 0);
+        assertTrue(cv.compare(p21, p11) == 0);
+        assertTrue(cv.compare(p21, p12) < 0);
+
+        Comparator<Map.Entry<K, V>> cmp = ck.thenComparing(cv);
+        assertTrue(cmp.compare(p11, p11) == 0);
+        assertTrue(cmp.compare(p12, p11) > 0);
+        assertTrue(cmp.compare(p11, p12) < 0);
+        assertTrue(cmp.compare(p12, p22) < 0);
+        assertTrue(cmp.compare(p12, p21) < 0);
+        assertTrue(cmp.compare(p21, p11) > 0);
+        assertTrue(cmp.compare(p21, p12) > 0);
+
+        cmp = cv.thenComparing(ck);
+        assertTrue(cmp.compare(p11, p11) == 0);
+        assertTrue(cmp.compare(p12, p11) > 0);
+        assertTrue(cmp.compare(p11, p12) < 0);
+        assertTrue(cmp.compare(p12, p22) < 0);
+        assertTrue(cmp.compare(p12, p21) > 0);
+        assertTrue(cmp.compare(p21, p11) > 0);
+        assertTrue(cmp.compare(p21, p12) < 0);
+    }
+
+    @Test
+    public void testKVComparables() {
+        assertPairComparison(1, "ABC", 2, "XYZ",
+                Map.Entry.<Integer, String>comparingByKey(),
+                Map.Entry.<Integer, String>comparingByValue());
+    }
+
+    private static class People {
+        final String firstName;
+        final String lastName;
+        final int age;
+
+        People(String first, String last, int age) {
+            firstName = first;
+            lastName = last;
+            this.age = age;
+        }
+
+        String getFirstName() { return firstName; }
+        String getLastName() { return lastName; }
+        int getAge() { return age; }
+    }
+
+    private final People people[] = {
+            new People("John", "Doe", 34),
+            new People("Mary", "Doe", 30),
+    };
+
+    @Test
+    public void testKVComparators() {
+        // Comparator<People> cmp = Comparator.naturalOrder(); // Should fail to compiler as People is not comparable
+        // We can use simple comparator, but those have been tested above.
+        // Thus choose to do compose for some level of interaction.
+        Comparator<People> cmp1 = Comparator.comparing(People::getFirstName);
+        Comparator<People> cmp2 = Comparator.comparing(People::getLastName);
+        Comparator<People> cmp = cmp1.thenComparing(cmp2);
+
+        assertPairComparison(people[0], people[0], people[1], people[1],
+                Map.Entry.<People, People>comparingByKey(cmp),
+                Map.Entry.<People, People>comparingByValue(cmp));
+
+    }
+
+    @Test
+    public void testNulls() {
+        try {
+            Comparator<Map.Entry<String, String>> cmp = Map.Entry.comparingByKey(null);
+            fail("comparingByKey(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+
+        try {
+            Comparator<Map.Entry<String, String>> cmp = Map.Entry.comparingByValue(null);
+            fail("comparingByValue(null) should throw NPE");
+        } catch (NullPointerException npe) {}
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/EntryHashCode.java b/ojluni/src/test/java/util/Map/EntryHashCode.java
new file mode 100644
index 0000000..d7bd3ff
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/EntryHashCode.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 8000955
+ * @summary Map.Entry implementations need to comply with Map.Entry.hashCode() defined behaviour.
+ * @author ngmr
+ */
+package test.java.util.Map;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.junit.Assert;
+import org.testng.annotations.Test;
+
+public class EntryHashCode {
+    private static final int TEST_SIZE = 100;
+
+    static final Object[][] entryData = {
+            new Object[TEST_SIZE],
+            new Object[TEST_SIZE]
+    };
+
+    @SuppressWarnings("unchecked")
+    static final Map<Object,Object>[] maps = (Map<Object,Object>[])new Map[] {
+            new HashMap<>(),
+            new Hashtable<>(),
+            new IdentityHashMap<>(),
+            new LinkedHashMap<>(),
+            new TreeMap<>(),
+            new WeakHashMap<>(),
+            new ConcurrentHashMap<>(),
+            new ConcurrentSkipListMap<>()
+    };
+
+    static {
+        for (int i = 0; i < entryData[0].length; i++) {
+            // key objects need to be Comparable for use in TreeMap
+            entryData[0][i] = new Comparable<Object>() {
+                public int compareTo(Object o) {
+                    return (hashCode() - o.hashCode());
+                }
+            };
+            entryData[1][i] = new Object();
+        }
+    }
+
+    private static void addTestData(Map<Object,Object> map) {
+        for (int i = 0; i < entryData[0].length; i++) {
+            map.put(entryData[0][i], entryData[1][i]);
+        }
+    }
+
+    @Test
+    public void testEntryHashCode() throws Exception {
+        Exception failure = null;
+        for (Map<Object,Object> map: maps) {
+            addTestData(map);
+
+            try {
+                for (Map.Entry<Object,Object> e: map.entrySet()) {
+                    Object key = e.getKey();
+                    Object value = e.getValue();
+                    int expectedEntryHashCode =
+                            (Objects.hashCode(key) ^ Objects.hashCode(value));
+
+                    Assert.assertEquals(e.hashCode(), expectedEntryHashCode);
+                }
+            } catch (Exception e) {
+                if (failure == null) {
+                    failure = e;
+                } else {
+                    failure.addSuppressed(e);
+                }
+            } finally {
+                map.clear();
+            }
+        }
+        if (failure != null) {
+            Assert.fail();;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/EntrySetIterator.java b/ojluni/src/test/java/util/Map/EntrySetIterator.java
new file mode 100644
index 0000000..784d329
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/EntrySetIterator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 8139233
+ * @summary ensure entry set's iterator doesn't have side effects on the entry set
+ * @run testng EntrySetIterator
+ */
+package test.java.util.Map;
+
+import java.util.*;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+
+public class EntrySetIterator {
+    @Test
+    public void testEntrySetIterator() {
+        Map<String, String> map = Map.of("a", "1", "b", "2", "c", "3");
+        Set<Map.Entry<String, String>> entrySet = map.entrySet();
+        Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
+
+        assertTrue(iterator.hasNext());
+
+        // copying implicitly iterates an iterator
+        Set<Map.Entry<String, String>> copy1 = new HashSet<>(entrySet);
+        Set<Map.Entry<String, String>> copy2 = new HashSet<>(entrySet);
+
+        assertEquals(copy2, copy1);
+        assertTrue(iterator.hasNext());
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/Get.java b/ojluni/src/test/java/util/Map/Get.java
new file mode 100644
index 0000000..6b0ad3a
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/Get.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 6306829
+ * @summary Verify assertions in get() javadocs
+ * @author Martin Buchholz
+ */
+package test.java.util.Map;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class Get {
+
+    @Test
+    public void testGet() {
+        testMap(new Hashtable<>());
+        testMap(new HashMap<>());
+        testMap(new IdentityHashMap<>());
+        testMap(new LinkedHashMap<>());
+        testMap(new ConcurrentHashMap<>());
+        testMap(new WeakHashMap<>());
+        testMap(new TreeMap<>());
+        testMap(new ConcurrentSkipListMap<>());
+    }
+
+    private static void put(Map<Character,Boolean> m,
+            Character key, Boolean value,
+            Boolean oldValue) {
+        if (oldValue != null) {
+            Assert.assertTrue(m.containsValue(oldValue));
+            Assert.assertTrue(m.values().contains(oldValue));
+        }
+        Assert.assertEquals(m.put(key, value), oldValue);
+        Assert.assertEquals(m.get(key), value);
+        Assert.assertTrue(m.containsKey(key));
+        Assert.assertTrue(m.keySet().contains(key));
+        Assert.assertTrue(m.containsValue(value));
+        Assert.assertTrue(m.values().contains(value));
+        Assert.assertTrue(! m.isEmpty());
+    }
+
+    private static void testMap(Map<Character,Boolean> m) {
+        // We verify following assertions in get(Object) method javadocs
+        boolean permitsNullKeys = (! (m instanceof ConcurrentMap ||
+                m instanceof Hashtable     ||
+                m instanceof SortedMap));
+        boolean permitsNullValues = (! (m instanceof ConcurrentMap ||
+                m instanceof Hashtable));
+        boolean usesIdentity = m instanceof IdentityHashMap;
+
+        System.err.println(m.getClass());
+        put(m, 'A', true,  null);
+        put(m, 'A', false, true);       // Guaranteed identical by JLS
+        put(m, 'B', true,  null);
+        put(m, new Character('A'), false, usesIdentity ? null : false);
+        if (permitsNullKeys) {
+            try {
+                put(m, null, true,  null);
+                put(m, null, false, true);
+            }
+            catch (Throwable t) { Assert.fail(); }
+        } else {
+            try { m.get(null); Assert.fail(m.getClass().getName() + " did not reject null key"); }
+            catch (NullPointerException e) {}
+            catch (Throwable t) { Assert.fail(); }
+
+            try { m.put(null, true); Assert.fail(m.getClass().getName() + " did not reject null key"); }
+            catch (NullPointerException e) {}
+            catch (Throwable t) { Assert.fail(); }
+        }
+        if (permitsNullValues) {
+            try {
+                put(m, 'C', null, null);
+                put(m, 'C', true, null);
+                put(m, 'C', null, true);
+            }
+            catch (Throwable t) { Assert.fail(); }
+        } else {
+            try { m.put('A', null); Assert.fail(m.getClass().getName() + " did not reject null key"); }
+            catch (NullPointerException e) {}
+            catch (Throwable t) { Assert.fail(); }
+
+            try { m.put('C', null); Assert.fail(m.getClass().getName() + " did not reject null key"); }
+            catch (NullPointerException e) {}
+            catch (Throwable t) { Assert.fail(); }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/InPlaceOpsCollisions.java b/ojluni/src/test/java/util/Map/InPlaceOpsCollisions.java
new file mode 100644
index 0000000..1f0a83b
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/InPlaceOpsCollisions.java
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 8005698
+ * @run testng/othervm -Dtest.map.collisions.shortrun=true InPlaceOpsCollisions
+ * @summary Ensure overrides of in-place operations in Maps behave well with lots of collisions.
+ */
+package test.java.util.Map;
+
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+public class InPlaceOpsCollisions extends MapWithCollisionsProviders {
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testPutIfAbsent(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        Object retVal;
+        removeOddKeys(map, keys);
+        for (int i = 0; i < keys.length; i++) {
+            retVal = map.putIfAbsent(keys[i], val);
+            if (i % 2 == 0) { // even: not absent, not put
+
+                assertEquals(retVal, keys[i],
+                        String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
+                assertEquals(keys[i], map.get(keys[i]),
+                        String.format("putIfAbsent: get(%s[%d])", desc, i));
+                assertTrue(map.containsValue(keys[i]),
+                        String.format("putIfAbsent: containsValue(%s[%d])", desc, i));
+            } else { // odd: absent, was put
+                assertNull(retVal,
+                        String.format("putIfAbsent: (%s[%d]) retVal", desc, i));
+                assertEquals(val, map.get(keys[i]),
+                        String.format("putIfAbsent: get(%s[%d])", desc, i));
+                assertFalse(map.containsValue(keys[i]),
+                        String.format("putIfAbsent: !containsValue(%s[%d])", desc, i));
+            }
+            assertTrue(map.containsKey(keys[i]),
+                    String.format("insertion: containsKey(%s[%d])", desc, i));
+        }
+        assertEquals(map.size(), keys.length,
+                String.format("map expected size m%d != k%d", map.size(), keys.length));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testRemoveMapping(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        boolean removed;
+        int removes = 0;
+        remapOddKeys(map, keys, val);
+        for (int i = 0; i < keys.length; i++) {
+            removed = map.remove(keys[i], keys[i]);
+            if (i % 2 == 0) { // even: original mapping, should be removed
+                assertTrue(removed,
+                        String.format("removeMapping: retVal(%s[%d])", desc, i));
+                assertNull(map.get(keys[i]),
+                        String.format("removeMapping: get(%s[%d])", desc, i));
+                assertFalse(map.containsKey(keys[i]),
+                        String.format("removeMapping: !containsKey(%s[%d])", desc, i));
+                assertFalse(map.containsValue(keys[i]),
+                        String.format("removeMapping: !containsValue(%s[%d])", desc, i));
+                removes++;
+            } else { // odd: new mapping, not removed
+                assertFalse(removed,
+                        String.format("removeMapping: retVal(%s[%d])", desc, i));
+                assertEquals(val, map.get(keys[i]),
+                        String.format("removeMapping: get(%s[%d])", desc, i));
+                assertTrue(map.containsKey(keys[i]),
+                        String.format("removeMapping: containsKey(%s[%d])", desc, i));
+                assertTrue(map.containsValue(val),
+                        String.format("removeMapping: containsValue(%s[%d])", desc, i));
+            }
+        }
+        assertEquals(map.size(), keys.length - removes,
+                String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testReplaceOldValue(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        // remap odds to val
+        // call replace to replace for val, for all keys
+        // check that all keys map to value from keys array
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        boolean replaced;
+        remapOddKeys(map, keys, val);
+
+        for (int i = 0; i < keys.length; i++) {
+            replaced = map.replace(keys[i], val, keys[i]);
+            if (i % 2 == 0) { // even: original mapping, should not be replaced
+                assertFalse(replaced,
+                        String.format("replaceOldValue: retVal(%s[%d])", desc, i));
+            } else { // odd: new mapping, should be replaced
+                assertTrue(replaced,
+                        String.format("replaceOldValue: get(%s[%d])", desc, i));
+            }
+            assertEquals(keys[i], map.get(keys[i]),
+                    String.format("replaceOldValue: get(%s[%d])", desc, i));
+            assertTrue(map.containsKey(keys[i]),
+                    String.format("replaceOldValue: containsKey(%s[%d])", desc, i));
+            assertTrue(map.containsValue(keys[i]),
+                    String.format("replaceOldValue: containsValue(%s[%d])", desc, i));
+        }
+        assertFalse(map.containsValue(val),
+                String.format("replaceOldValue: !containsValue(%s[%s])", desc, val));
+        assertEquals(map.size(), keys.length,
+                String.format("map expected size m%d != k%d", map.size(), keys.length));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testReplaceIfMapped(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        // remove odd keys
+        // call replace for all keys[]
+        // odd keys should remain absent, even keys should be mapped to EXTRA, no value from keys[] should be in map
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        int expectedSize1 = 0;
+        removeOddKeys(map, keys);
+        int expectedSize2 = map.size();
+
+        for (int i = 0; i < keys.length; i++) {
+            Object retVal = map.replace(keys[i], val);
+            if (i % 2 == 0) { // even: still in map, should be replaced
+                assertEquals(retVal, keys[i],
+                        String.format("replaceIfMapped: retVal(%s[%d])", desc, i));
+                assertEquals(val, map.get(keys[i]),
+                        String.format("replaceIfMapped: get(%s[%d])", desc, i));
+                assertTrue(map.containsKey(keys[i]),
+                        String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
+                expectedSize1++;
+            } else { // odd: was removed, should not be replaced
+                assertNull(retVal,
+                        String.format("replaceIfMapped: retVal(%s[%d])", desc, i));
+                assertNull(map.get(keys[i]),
+                        String.format("replaceIfMapped: get(%s[%d])", desc, i));
+                assertFalse(map.containsKey(keys[i]),
+                        String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
+            }
+            assertFalse(map.containsValue(keys[i]),
+                    String.format("replaceIfMapped: !containsValue(%s[%d])", desc, i));
+        }
+        assertTrue(map.containsValue(val),
+                String.format("replaceIfMapped: containsValue(%s[%s])", desc, val));
+        assertEquals(map.size(), expectedSize1,
+                String.format("map expected size#1 m%d != k%d", map.size(), expectedSize1));
+        assertEquals(map.size(), expectedSize2,
+                String.format("map expected size#2 m%d != k%d", map.size(), expectedSize2));
+
+    }
+
+    private static <T> void testComputeIfAbsent(Map<T, T> map, String desc, T[] keys,
+            Function<T, T> mappingFunction) {
+        // remove a third of the keys
+        // call computeIfAbsent for all keys, func returns EXTRA
+        // check that removed keys now -> EXTRA, other keys -> original val
+        T expectedVal = mappingFunction.apply(keys[0]);
+        T retVal;
+        int expectedSize = 0;
+        removeThirdKeys(map, keys);
+        for (int i = 0; i < keys.length; i++) {
+            retVal = map.computeIfAbsent(keys[i], mappingFunction);
+            if (i % 3 != 2) { // key present, not computed
+                assertEquals(retVal, keys[i],
+                        String.format("computeIfAbsent: (%s[%d]) retVal", desc, i));
+                assertEquals(keys[i], map.get(keys[i]),
+                        String.format("computeIfAbsent: get(%s[%d])", desc, i));
+                assertTrue(map.containsValue(keys[i]),
+                        String.format("computeIfAbsent: containsValue(%s[%d])", desc, i));
+                assertTrue(map.containsKey(keys[i]),
+                        String.format("insertion: containsKey(%s[%d])", desc, i));
+                expectedSize++;
+            } else { // key absent, computed unless function return null
+                assertEquals(retVal, expectedVal,
+                        String.format("computeIfAbsent: (%s[%d]) retVal", desc, i));
+                assertEquals(expectedVal, map.get(keys[i]),
+                        String.format("computeIfAbsent: get(%s[%d])", desc, i));
+                assertFalse(map.containsValue(keys[i]),
+                        String.format("computeIfAbsent: !containsValue(%s[%d])", desc, i));
+                // mapping should not be added if function returns null
+                assertTrue(map.containsKey(keys[i]) != (expectedVal == null),
+                        String.format("insertion: containsKey(%s[%d])", desc, i));
+                if (expectedVal != null) {
+                    expectedSize++;
+                }
+            }
+        }
+        if (expectedVal != null) {
+            assertTrue(map.containsValue(expectedVal),
+                    String.format("computeIfAbsent: containsValue(%s[%s])", desc, expectedVal));
+        }
+        assertEquals(map.size(), expectedSize,
+                String.format("map expected size m%d != k%d", map.size(), expectedSize));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testComputeIfAbsentNonNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        testComputeIfAbsent(map, desc, keys, (k) -> val);
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testComputeIfAbsentNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        testComputeIfAbsent(map, desc, keys, (k) -> null);
+    }
+
+    private static <T> void testComputeIfPresent(Map<T, T> map, String desc, T[] keys,
+            BiFunction<T, T, T> mappingFunction) {
+        // remove a third of the keys
+        // call testComputeIfPresent for all keys[]
+        // removed keys should remain absent, even keys should be mapped to $RESULT
+        // no value from keys[] should be in map
+        T funcResult = mappingFunction.apply(keys[0], keys[0]);
+        int expectedSize1 = 0;
+        removeThirdKeys(map, keys);
+
+        for (int i = 0; i < keys.length; i++) {
+            T retVal = map.computeIfPresent(keys[i], mappingFunction);
+            if (i % 3 != 2) { // key present
+                if (funcResult == null) { // was removed
+                    assertFalse(map.containsKey(keys[i]),
+                            String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
+                } else { // value was replaced
+                    assertTrue(map.containsKey(keys[i]),
+                            String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
+                    expectedSize1++;
+                }
+                assertEquals(retVal, funcResult,
+                        String.format("computeIfPresent: retVal(%s[%s])", desc, i));
+                assertEquals(funcResult, map.get(keys[i]),
+                        String.format("replaceIfMapped: get(%s[%d])", desc, i));
+
+            } else { // odd: was removed, should not be replaced
+                assertNull(retVal,
+                        String.format("replaceIfMapped: retVal(%s[%d])", desc, i));
+                assertNull(map.get(keys[i]),
+                        String.format("replaceIfMapped: get(%s[%d])", desc, i));
+                assertFalse(map.containsKey(keys[i]),
+                        String.format("replaceIfMapped: containsKey(%s[%d])", desc, i));
+            }
+            assertFalse(map.containsValue(keys[i]),
+                    String.format("replaceIfMapped: !containsValue(%s[%d])", desc, i));
+        }
+        assertEquals(map.size(), expectedSize1,
+                String.format("map expected size#1 m%d != k%d", map.size(), expectedSize1));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testComputeIfPresentNonNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        testComputeIfPresent(map, desc, keys, (k, v) -> val);
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testComputeIfPresentNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        testComputeIfPresent(map, desc, keys, (k, v) -> null);
+    }
+
+    @Test(dataProvider = "hashMapsWithObjects")
+    public void testComputeNonNull(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val) {
+        // remove a third of the keys
+        // call compute() for all keys[]
+        // all keys should be present: removed keys -> EXTRA, others to k-1
+        Map<IntKey, IntKey> map = ms.get();
+        IntKey[] keys = map.keySet().stream().sorted().toArray(IntKey[]::new);
+        BiFunction<IntKey, IntKey, IntKey> mappingFunction = (k, v) -> {
+            if (v == null) {
+                return val;
+            } else {
+                return keys[k.getValue() - 1];
+            }
+        };
+        removeThirdKeys(map, keys);
+        for (int i = 1; i < keys.length; i++) {
+            IntKey retVal = map.compute(keys[i], mappingFunction);
+            if (i % 3 != 2) { // key present, should be mapped to k-1
+                assertEquals(retVal, keys[i - 1],
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertEquals(keys[i - 1], map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+            } else { // odd: was removed, should be replaced with EXTRA
+                assertEquals(retVal, val,
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertEquals(val, map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+            }
+            assertTrue(map.containsKey(keys[i]),
+                    String.format("compute: containsKey(%s[%d])", desc, i));
+        }
+        assertEquals(map.size(), keys.length,
+                String.format("map expected size#1 m%d != k%d", map.size(), keys.length));
+        assertTrue(map.containsValue(val),
+                String.format("compute: containsValue(%s[%s])", desc, val));
+        assertFalse(map.containsValue(null),
+                String.format("compute: !containsValue(%s,[null])", desc));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testComputeNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        // remove a third of the keys
+        // call compute() for all keys[]
+        // removed keys should -> EXTRA
+        // for other keys: func returns null, should have no mapping
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        BiFunction<Object, Object, Object> mappingFunction = (k, v) -> {
+            // if absent/null -> EXTRA
+            // if present -> null
+            if (v == null) {
+                return val;
+            } else {
+                return null;
+            }
+        };
+        int expectedSize = 0;
+        removeThirdKeys(map, keys);
+        for (int i = 0; i < keys.length; i++) {
+            Object retVal = map.compute(keys[i], mappingFunction);
+            if (i % 3 != 2) { // key present, func returned null, should be absent from map
+                assertNull(retVal,
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertNull(map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+                assertFalse(map.containsKey(keys[i]),
+                        String.format("compute: containsKey(%s[%d])", desc, i));
+                assertFalse(map.containsValue(keys[i]),
+                        String.format("compute: containsValue(%s[%s])", desc, i));
+            } else { // odd: was removed, should now be mapped to EXTRA
+                assertEquals(retVal, val,
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertEquals(val, map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+                assertTrue(map.containsKey(keys[i]),
+                        String.format("compute: containsKey(%s[%d])", desc, i));
+                expectedSize++;
+            }
+        }
+        assertTrue(map.containsValue(val),
+                String.format("compute: containsValue(%s[%s])", desc, val));
+        assertEquals(map.size(), expectedSize,
+                String.format("map expected size#1 m%d != k%d", map.size(), expectedSize));
+    }
+
+    @Test(dataProvider = "hashMapsWithObjects")
+    public void testMergeNonNull(String desc, Supplier<Map<IntKey, IntKey>> ms, IntKey val) {
+        // remove a third of the keys
+        // call merge() for all keys[]
+        // all keys should be present: removed keys now -> EXTRA, other keys -> k-1
+        Map<IntKey, IntKey> map = ms.get();
+        IntKey[] keys = map.keySet().stream().sorted().toArray(IntKey[]::new);
+
+        // Map to preceding key
+        BiFunction<IntKey, IntKey, IntKey> mappingFunction
+                = (k, v) -> keys[k.getValue() - 1];
+        removeThirdKeys(map, keys);
+        for (int i = 1; i < keys.length; i++) {
+            IntKey retVal = map.merge(keys[i], val, mappingFunction);
+            if (i % 3 != 2) { // key present, should be mapped to k-1
+                assertEquals(retVal, keys[i - 1],
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertEquals(keys[i - 1], map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+            } else { // odd: was removed, should be replaced with EXTRA
+                assertEquals(retVal, val,
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertEquals(val, map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+            }
+            assertTrue(map.containsKey(keys[i]),
+                    String.format("compute: containsKey(%s[%d])", desc, i));
+        }
+
+        assertEquals(map.size(), keys.length,
+                String.format("map expected size#1 m%d != k%d", map.size(), keys.length));
+        assertTrue(map.containsValue(val),
+                String.format("compute: containsValue(%s[%s])", desc, val));
+        assertFalse(map.containsValue(null),
+                String.format("compute: !containsValue(%s,[null])", desc));
+    }
+
+    @Test(dataProvider = "mapsWithObjectsAndStrings")
+    public void testMergeNull(String desc, Supplier<Map<Object, Object>> ms, Object val) {
+        // remove a third of the keys
+        // call merge() for all keys[]
+        // result: removed keys -> EXTRA, other keys absent
+
+        Map<Object, Object> map = ms.get();
+        Object[] keys = map.keySet().toArray();
+        BiFunction<Object, Object, Object> mappingFunction = (k, v) -> null;
+        int expectedSize = 0;
+        removeThirdKeys(map, keys);
+        for (int i = 0; i < keys.length; i++) {
+            Object retVal = map.merge(keys[i], val, mappingFunction);
+            if (i % 3 != 2) { // key present, func returned null, should be absent from map
+                assertNull(retVal,
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertNull(map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+                assertFalse(map.containsKey(keys[i]),
+                        String.format("compute: containsKey(%s[%d])", desc, i));
+            } else { // odd: was removed, should now be mapped to EXTRA
+                assertEquals(retVal, val,
+                        String.format("compute: retVal(%s[%d])", desc, i));
+                assertEquals(val, map.get(keys[i]),
+                        String.format("compute: get(%s[%d])", desc, i));
+                assertTrue(map.containsKey(keys[i]),
+                        String.format("compute: containsKey(%s[%d])", desc, i));
+                expectedSize++;
+            }
+            assertFalse(map.containsValue(keys[i]),
+                    String.format("compute: containsValue(%s[%s])", desc, i));
+        }
+        assertTrue(map.containsValue(val),
+                String.format("compute: containsValue(%s[%s])", desc, val));
+        assertEquals(map.size(), expectedSize,
+                String.format("map expected size#1 m%d != k%d", map.size(), expectedSize));
+    }
+
+    /*
+     * Remove half of the keys
+     */
+    private static <T> void removeOddKeys(Map<T, T> map, /*String keys_desc, */ T[] keys) {
+        int removes = 0;
+        for (int i = 0; i < keys.length; i++) {
+            if (i % 2 != 0) {
+                map.remove(keys[i]);
+                removes++;
+            }
+        }
+        assertEquals(map.size(), keys.length - removes,
+                String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
+    }
+
+    /*
+     * Remove every third key
+     * This will hopefully leave some removed keys in TreeBins for, e.g., computeIfAbsent
+     * w/ a func that returns null.
+     *
+     * TODO: consider using this in other tests (and maybe adding a remapThirdKeys)
+     */
+    private static <T> void removeThirdKeys(Map<T, T> map, /*String keys_desc, */ T[] keys) {
+        int removes = 0;
+        for (int i = 0; i < keys.length; i++) {
+            if (i % 3 == 2) {
+                map.remove(keys[i]);
+                removes++;
+            }
+        }
+        assertEquals(map.size(), keys.length - removes,
+                String.format("map expected size m%d != k%d", map.size(), keys.length - removes));
+    }
+
+    /*
+     * Re-map the odd-numbered keys to map to the EXTRA value
+     */
+    private static <T> void remapOddKeys(Map<T, T> map, T[] keys, T val) {
+        for (int i = 0; i < keys.length; i++) {
+            if (i % 2 != 0) {
+                map.put(keys[i], val);
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/LockStep.java b/ojluni/src/test/java/util/Map/LockStep.java
new file mode 100644
index 0000000..1e4eb69
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/LockStep.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 6612102
+ * @summary Test Map implementations for mutual compatibility
+ * @key randomness
+ */
+package test.java.util.Map;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.TreeMap;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+/**
+ * Based on the strange scenario required to reproduce
+ * (coll) IdentityHashMap.iterator().remove() might decrement size twice
+ *
+ * It would be good to add more "Lockstep-style" tests to this file.
+ */
+public class LockStep {
+    void mapsEqual(Map m1, Map m2) {
+        Assert.assertEquals(m1, m2);
+        Assert.assertEquals(m2, m1);
+        Assert.assertEquals(m1.size(), m2.size());
+        Assert.assertEquals(m1.isEmpty(), m2.isEmpty());
+        Assert.assertEquals(m1.keySet(), m2.keySet());
+        Assert.assertEquals(m2.keySet(), m1.keySet());
+    }
+
+    void mapsEqual(List<Map> maps) {
+        Map first = maps.get(0);
+        for (Map map : maps)
+            mapsEqual(first, map);
+    }
+
+    void put(List<Map> maps, Object key, Object val) {
+        for (Map map : maps)
+            map.put(key, val);
+        mapsEqual(maps);
+    }
+
+    void removeLastTwo(List<Map> maps) {
+        Map first = maps.get(0);
+        int size = first.size();
+        Iterator fit = first.keySet().iterator();
+        for (int j = 0; j < size - 2; j++)
+            fit.next();
+        Object x1 = fit.next();
+        Object x2 = fit.next();
+
+        for (Map map : maps) {
+            Iterator it = map.keySet().iterator();
+            while (it.hasNext()) {
+                Object x = it.next();
+                if (x == x1 || x == x2)
+                    it.remove();
+            }
+        }
+        mapsEqual(maps);
+    }
+
+    @Test
+    public void testLockStep() throws Throwable {
+        final int iterations = 100;
+        final Random r = new Random();
+
+        for (int i = 0; i < iterations; i++) {
+            List<Map> maps = List.of(
+                    new IdentityHashMap(11),
+                    new HashMap(16),
+                    new LinkedHashMap(16),
+                    new WeakHashMap(16),
+                    new Hashtable(16),
+                    new TreeMap(),
+                    new ConcurrentHashMap(16),
+                    new ConcurrentSkipListMap(),
+                    Collections.checkedMap(new HashMap(16), Integer.class, Integer.class),
+                    Collections.checkedSortedMap(new TreeMap(), Integer.class, Integer.class),
+                    Collections.checkedNavigableMap(new TreeMap(), Integer.class, Integer.class),
+                    Collections.synchronizedMap(new HashMap(16)),
+                    Collections.synchronizedSortedMap(new TreeMap()),
+                    Collections.synchronizedNavigableMap(new TreeMap()));
+
+            for (int j = 0; j < 10; j++)
+                put(maps, r.nextInt(100), r.nextInt(100));
+            removeLastTwo(maps);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/MapBinToFromTreeTest.java b/ojluni/src/test/java/util/Map/MapBinToFromTreeTest.java
new file mode 100644
index 0000000..1834b38
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/MapBinToFromTreeTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Map;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static org.testng.Assert.assertEquals;
+
+/*
+ * @test
+ * @bug 8023463
+ * @summary Test the case where a bin is treeified and vice verser
+ * @run testng MapBinToFromTreeTest
+ */
+
+@Test
+public class MapBinToFromTreeTest {
+
+    // Initial capacity of map
+    // Should be >= the map capacity for treeifiying, see HashMap/ConcurrentMap.MIN_TREEIFY_CAPACITY
+    static final int INITIAL_CAPACITY = 64;
+
+    // Maximum size of map
+    // Should be > the treeify threshold, see HashMap/ConcurrentMap.TREEIFY_THRESHOLD
+    // Should be > INITIAL_CAPACITY to ensure resize occurs
+    static final int SIZE = 256;
+
+    // Load factor of map
+    // A value 1.0 will ensure that a new threshold == capacity
+    static final float LOAD_FACTOR = 1.0f;
+
+    @DataProvider(name = "maps")
+    static Object[][] mapProvider() {
+        return new Object[][] {
+                // Pass in the class name as a description for test reporting
+                // purposes
+                { HashMap.class.getName(), new HashMap(INITIAL_CAPACITY, LOAD_FACTOR) },
+                { LinkedHashMap.class.getName(), new LinkedHashMap(INITIAL_CAPACITY, LOAD_FACTOR) },
+                { ConcurrentHashMap.class.getName(), new ConcurrentHashMap(INITIAL_CAPACITY, LOAD_FACTOR) },
+        };
+    }
+
+    @Test(dataProvider = "maps")
+    public void testPutThenGet(String d, Map<HashCodeInteger, Integer> m) {
+        put(SIZE, m, (i, s) -> {
+            for (int j = 0; j < s; j++) {
+                assertEquals(m.get(new HashCodeInteger(j)).intValue(), j,
+                        String.format("Map.get(%d)", j));
+            }
+        });
+    }
+
+    @Test(dataProvider = "maps")
+    public void testPutThenTraverse(String d, Map<HashCodeInteger, Integer> m) {
+        Collector<Integer, ?, ? extends Collection<Integer>> c = getCollector(m);
+
+        put(SIZE, m, (i, s) -> {
+            // Note that it is OK to collect to a Set (HashSet) as long as
+            // integer values are used since these tests only check for
+            // collisions and other tests will verify more general functionality
+            Collection<Integer> actual = m.keySet().stream().map(e -> e.value).collect(c);
+            Collection<Integer> expected = IntStream.range(0, s).boxed().collect(c);
+            assertEquals(actual, expected, "Map.keySet()");
+        });
+    }
+
+    @Test(dataProvider = "maps")
+    public void testRemoveThenGet(String d, Map<HashCodeInteger, Integer> m) {
+        put(SIZE, m, (i, s) -> { });
+
+        remove(m, (i, s) -> {
+            for (int j = i + 1; j < SIZE; j++) {
+                assertEquals(m.get(new HashCodeInteger(j)).intValue(), j,
+                        String.format("Map.get(%d)", j));
+            }
+        });
+    }
+
+    @Test(dataProvider = "maps")
+    public void testRemoveThenTraverse(String d, Map<HashCodeInteger, Integer> m) {
+        put(SIZE, m, (i, s) -> { });
+
+        Collector<Integer, ?, ? extends Collection<Integer>> c = getCollector(m);
+
+        remove(m, (i, s) -> {
+            Collection<Integer> actual = m.keySet().stream().map(e -> e.value).collect(c);
+            Collection<Integer> expected = IntStream.range(i + 1, SIZE).boxed().collect(c);
+            assertEquals(actual, expected, "Map.keySet()");
+        });
+    }
+
+    @Test(dataProvider = "maps")
+    public void testUntreeifyOnResizeWithGet(String d, Map<HashCodeInteger, Integer> m) {
+        // Fill the map with 64 entries grouped into 4 buckets
+        put(INITIAL_CAPACITY, m, (i, s) -> { });
+
+        for (int i = INITIAL_CAPACITY; i < SIZE; i++) {
+            // Add further entries in the 0'th bucket so as not to disturb
+            // other buckets, entries of which may be distributed and/or
+            // the bucket untreeified on resize
+            m.put(new HashCodeInteger(i, 0), i);
+
+            for (int j = 0; j < INITIAL_CAPACITY; j++) {
+                assertEquals(m.get(new HashCodeInteger(j)).intValue(), j,
+                        String.format("Map.get(%d) < INITIAL_CAPACITY", j));
+            }
+            for (int j = INITIAL_CAPACITY; j <= i; j++) {
+                assertEquals(m.get(new HashCodeInteger(j, 0)).intValue(), j,
+                        String.format("Map.get(%d) >= INITIAL_CAPACITY", j));
+            }
+        }
+    }
+
+    @Test(dataProvider = "maps")
+    public void testUntreeifyOnResizeWithTraverse(String d, Map<HashCodeInteger, Integer> m) {
+        // Fill the map with 64 entries grouped into 4 buckets
+        put(INITIAL_CAPACITY, m, (i, s) -> { });
+
+        Collector<Integer, ?, ? extends Collection<Integer>> c = getCollector(m);
+
+        for (int i = INITIAL_CAPACITY; i < SIZE; i++) {
+            // Add further entries in the 0'th bucket so as not to disturb
+            // other buckets, entries of which may be distributed and/or
+            // the bucket untreeified on resize
+            m.put(new HashCodeInteger(i, 0), i);
+
+            Collection<Integer> actual = m.keySet().stream().map(e -> e.value).collect(c);
+            Collection<Integer> expected = IntStream.rangeClosed(0, i).boxed().collect(c);
+            assertEquals(actual, expected, "Key set");
+        }
+    }
+
+    Collector<Integer, ?, ? extends Collection<Integer>> getCollector(Map<?, ?> m) {
+        Collector<Integer, ?, ? extends Collection<Integer>> collector = m instanceof LinkedHashMap
+                ? Collectors.toList()
+                : Collectors.toSet();
+        return collector;
+    }
+
+    void put(int size, Map<HashCodeInteger, Integer> m, BiConsumer<Integer, Integer> c) {
+        for (int i = 0; i < size; i++) {
+            m.put(new HashCodeInteger(i), i);
+
+            c.accept(i, m.size());
+        }
+    }
+
+    void remove(Map<HashCodeInteger, Integer> m, BiConsumer<Integer, Integer> c) {
+        int size = m.size();
+        // Remove all elements thus ensuring at some point trees will be
+        // converting back to bins
+        for (int i = 0; i < size; i++) {
+            m.remove(new HashCodeInteger(i));
+
+            c.accept(i, m.size());
+        }
+    }
+
+    static final class HashCodeInteger implements Comparable<HashCodeInteger> {
+        final int value;
+
+        final int hashcode;
+
+        HashCodeInteger(int value) {
+            this(value, hash(value));
+        }
+
+        HashCodeInteger(int value, int hashcode) {
+            this.value = value;
+            this.hashcode = hashcode;
+        }
+
+        static int hash(int i) {
+            // Assuming 64 entries with keys from 0 to 63 then a map:
+            // - of capacity 64 will have 4 buckets with 16 entries per-bucket
+            // - of capacity 128 will have 8 buckets with 8 entries per-bucket
+            // - of capacity 256 will have 16 buckets with 4 entries per-bucket
+            //
+            // Re-sizing will result in re-distribution, doubling the buckets
+            // and reducing the entries by half. This will result in
+            // untreeifying when the number of entries is less than untreeify
+            // threshold (see HashMap/ConcurrentMap.UNTREEIFY_THRESHOLD)
+            return (i % 4) + (i / 4) * INITIAL_CAPACITY;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof HashCodeInteger) {
+                HashCodeInteger other = (HashCodeInteger) obj;
+                return other.value == value;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return hashcode;
+        }
+
+        @Override
+        public int compareTo(HashCodeInteger o) {
+            return value - o.value;
+        }
+
+        @Override
+        public String toString() {
+            return Integer.toString(value);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/MapWithCollisionsProviders.java b/ojluni/src/test/java/util/Map/MapWithCollisionsProviders.java
new file mode 100644
index 0000000..917c582
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/MapWithCollisionsProviders.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2021 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 test.java.util.Map;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.function.Supplier;
+
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+
+public class MapWithCollisionsProviders {
+
+    private static final int TEST_SIZE
+            = Boolean.valueOf(System.getProperty("test.map.collisions.shortrun"))
+            ? 2500
+            : 5000;
+
+    private static final IntKey EXTRA_INTKEY_VAL
+            = new IntKey(TEST_SIZE, Integer.MAX_VALUE);
+
+    private static final String EXTRA_STRING_VAL = "Extra Value";
+
+    public static final class IntKey implements Comparable<IntKey> {
+
+        private final int value;
+        private final int hashmask; //yes duplication
+
+        IntKey(int value, int hashmask) {
+            this.value = value;
+            this.hashmask = hashmask;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof IntKey) {
+                IntKey other = (IntKey) obj;
+
+                return other.value == value;
+            }
+
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return value % hashmask;
+        }
+
+        @Override
+        public int compareTo(IntKey o) {
+            return value - o.value;
+        }
+
+        @Override
+        public String toString() {
+            return Integer.toString(value);
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+    private static Object[] createUniqueObjectKeys() {
+        IntKey UNIQUE_OBJECTS[] = new IntKey[TEST_SIZE];
+        for (int i = 0; i < TEST_SIZE; i++) {
+            UNIQUE_OBJECTS[i] = new IntKey(i, Integer.MAX_VALUE);
+        }
+        return UNIQUE_OBJECTS;
+    }
+
+    private static Object[] createUniqueStringKeys() {
+        String UNIQUE_STRINGS[] = new String[TEST_SIZE];
+        for (int i = 0; i < TEST_SIZE; i++) {
+            UNIQUE_STRINGS[i] = unhash(i);
+        }
+        return UNIQUE_STRINGS;
+    }
+
+    private static Object[] createCollidingObjectKeys() {
+        IntKey COLLIDING_OBJECTS[] = new IntKey[TEST_SIZE];
+        for (int i = 0; i < TEST_SIZE; i++) {
+            COLLIDING_OBJECTS[i] = new IntKey(i, 10);
+        }
+        return COLLIDING_OBJECTS;
+    }
+
+    private static Object[] createCollidingStringKeys() {
+        String COLLIDING_STRINGS[] = new String[TEST_SIZE];
+        String UNIQUE_STRINGS[] = new String[TEST_SIZE];
+        for (int i = 0; i < TEST_SIZE; i++) {
+            UNIQUE_STRINGS[i] = unhash(i);
+            COLLIDING_STRINGS[i] = (0 == i % 2)
+                    ? UNIQUE_STRINGS[i / 2]
+                    : "\u0000\u0000\u0000\u0000\u0000" + COLLIDING_STRINGS[i - 1];
+        }
+        return COLLIDING_STRINGS;
+    }
+
+    /**
+     * Returns a string with a hash equal to the argument.
+     *
+     * @return string with a hash equal to the argument.
+     */
+    private static String unhash(int target) {
+        StringBuilder answer = new StringBuilder();
+        if (target < 0) {
+            // String with hash of Integer.MIN_VALUE, 0x80000000
+            answer.append("\\u0915\\u0009\\u001e\\u000c\\u0002");
+
+            if (target == Integer.MIN_VALUE) {
+                return answer.toString();
+            }
+            // Find target without sign bit set
+            target = target & Integer.MAX_VALUE;
+        }
+
+        unhash0(answer, target);
+        return answer.toString();
+    }
+
+    private static void unhash0(StringBuilder partial, int target) {
+        int div = target / 31;
+        int rem = target % 31;
+
+        if (div <= Character.MAX_VALUE) {
+            if (div != 0) {
+                partial.append((char) div);
+            }
+            partial.append((char) rem);
+        } else {
+            unhash0(partial, div);
+            partial.append((char) rem);
+        }
+    }
+
+    private static <T> Map<T, T> fillMap(Map<T, T> m, T[] keys) {
+        for (T k : keys) {
+            m.put(k, k);
+            assertTrue(m.containsKey(k));
+            assertTrue(m.containsValue(k));
+        }
+        assertEquals(m.size(), keys.length);
+        return m;
+    }
+
+    private static <T> Supplier<Map<T, T>> createMap(Map<T, T> m, T[] keys) {
+        return () -> fillMap(m, keys);
+    }
+
+    private static <T> Object[] createCase(String desc, Map<T, T> m, T[] keys, T val) {
+        return new Object[]{desc, createMap(m, keys), val};
+    }
+
+    private static <T> Collection<Object[]> makeMapsMoreTypes(String desc,
+            T[] keys,
+            T val) {
+        Collection<Object[]> cases = new ArrayList<>();
+        cases.add(createCase("Hashtable with " + desc,
+                new Hashtable<>(), keys, val));
+        cases.add(createCase("IdentityHashMap with " + desc,
+                new IdentityHashMap<>(), keys, val));
+        cases.add(createCase("TreeMap with " + desc,
+                new TreeMap<>(), keys, val));
+        cases.add(createCase("WeakHashMap with " + desc,
+                new WeakHashMap<>(), keys, val));
+        cases.add(createCase("ConcurrentHashMap with " + desc,
+                new ConcurrentHashMap<>(), keys, val));
+        cases.add(createCase("ConcurrentSkipListMap with " + desc,
+                new ConcurrentSkipListMap<>(), keys, val));
+        return cases;
+    }
+
+    private static <T> Collection<Object[]> makeMapsHashMap(String desc,
+            T[] keys,
+            T val) {
+        Collection<Object[]> cases = new ArrayList<>();
+        cases.add(createCase("HashMap with " + desc,
+                new HashMap<>(), keys, val));
+        cases.add(createCase("LinkedHashMap with " + desc,
+                new LinkedHashMap<>(), keys, val));
+        return cases;
+    }
+
+    private static <T> Collection<Object[]> makeMaps(String desc, T[] keys, T val) {
+        Collection<Object[]> cases = new ArrayList<>();
+        cases.addAll(makeMapsHashMap(desc, keys, val));
+        cases.addAll(makeMapsMoreTypes(desc, keys, val));
+        return cases;
+    }
+
+    private static <T> Collection<Object[]> makeObjectsCases(String desc, T[] keys) {
+        return makeMaps(desc, keys, EXTRA_INTKEY_VAL);
+    }
+
+    private static <T> Collection<Object[]> makeStringsCases(String desc,
+            T[] keys) {
+        return makeMaps(desc, keys, EXTRA_STRING_VAL);
+    }
+
+    private static final Collection<Object[]> mapsWithObjectsCases
+            = new ArrayList<>() {
+        {
+            addAll(makeObjectsCases("unique objects", createUniqueObjectKeys()));
+            addAll(makeObjectsCases("colliding objects", createCollidingObjectKeys()));
+        }
+    };
+
+    private static final Collection<Object[]> mapsWithStringsCases
+            = new ArrayList<>() {
+        {
+            addAll(makeStringsCases("unique strings", createUniqueStringKeys()));
+            addAll(makeStringsCases("colliding strings", createCollidingStringKeys()));
+        }
+    };
+
+    private static final Collection<Object[]> mapsWithObjectsAndStringsCases
+            = new ArrayList<>() {
+        {
+            addAll(mapsWithObjectsCases);
+            addAll(mapsWithStringsCases);
+        }
+    };
+
+    private static final Collection<Object[]> hashMapsWithObjectsCases
+            = new ArrayList<>() {
+        {
+            addAll(makeMapsHashMap("unique objects",
+                    createUniqueObjectKeys(), EXTRA_INTKEY_VAL));
+            addAll(makeMapsHashMap("collisions objects",
+                    createCollidingObjectKeys(), EXTRA_INTKEY_VAL));
+        }
+    };
+
+    @DataProvider
+    public Iterator<Object[]> mapsWithObjects() {
+        return mapsWithObjectsCases.iterator();
+    }
+
+    @DataProvider
+    public Iterator<Object[]> mapsWithStrings() {
+        return mapsWithStringsCases.iterator();
+    }
+
+    @DataProvider
+    public Iterator<Object[]> mapsWithObjectsAndStrings() {
+        return mapsWithObjectsAndStringsCases.iterator();
+    }
+
+    @DataProvider
+    public Iterator<Object[]> hashMapsWithObjects() {
+        return hashMapsWithObjectsCases.iterator();
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Map/ToArray.java b/ojluni/src/test/java/util/Map/ToArray.java
new file mode 100644
index 0000000..68b3021
--- /dev/null
+++ b/ojluni/src/test/java/util/Map/ToArray.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * @test
+ * @bug 8008785
+ * @summary Ensure toArray() implementations return correct results.
+ * @author Mike Duigou
+ */
+package test.java.util.Map;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.testng.annotations.Test;
+import org.testng.Assert;
+
+public class ToArray {
+
+    /**
+     * Number of elements per map.
+     */
+    private static final int TEST_SIZE = 5000;
+
+    @Test
+    public void testToArray() throws Throwable {
+        Map<Integer, Long>[] maps = (Map<Integer, Long>[]) new Map[]{
+                new HashMap<>(),
+                new Hashtable<>(),
+                new IdentityHashMap<>(),
+                new LinkedHashMap<>(),
+                new TreeMap<>(),
+                new WeakHashMap<>(),
+                new ConcurrentHashMap<>(),
+                new ConcurrentSkipListMap<>()
+        };
+
+        // for each map type.
+        for (Map<Integer, Long> map : maps) {
+            testMap(map);
+        }
+    }
+
+    private static final Integer[] KEYS = new Integer[TEST_SIZE];
+
+    private static final Long[] VALUES = new Long[TEST_SIZE];
+
+    static {
+        for (int each = 0; each < TEST_SIZE; each++) {
+            KEYS[each]   = Integer.valueOf(each);
+            VALUES[each] = Long.valueOf(each + TEST_SIZE);
+        }
+    }
+
+
+    private static void testMap(Map<Integer, Long> map) {
+
+        // Fill the map
+        for (int each = 0; each < TEST_SIZE; each++) {
+            map.put(KEYS[each], VALUES[each]);
+        }
+
+        // check the keys
+        Object[] keys = map.keySet().toArray();
+        Arrays.sort(keys);
+
+        for(int each = 0; each < TEST_SIZE; each++) {
+            Assert.assertTrue( keys[each] == KEYS[each]);
+        }
+
+        // check the values
+        Object[] values = map.values().toArray();
+        Arrays.sort(values);
+
+        for(int each = 0; each < TEST_SIZE; each++) {
+            Assert.assertTrue( values[each] == VALUES[each]);
+        }
+
+        // check the entries
+        Map.Entry<Integer,Long>[] entries = map.entrySet().toArray(new Map.Entry[TEST_SIZE]);
+        Arrays.sort( entries,new Comparator<Map.Entry<Integer,Long>>() {
+            public int compare(Map.Entry<Integer,Long> o1, Map.Entry<Integer,Long> o2) {
+                return o1.getKey().compareTo(o2.getKey());
+            }});
+
+        for(int each = 0; each < TEST_SIZE; each++) {
+            Assert.assertTrue( entries[each].getKey() == KEYS[each] && entries[each].getValue() == VALUES[each]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/Optional/Basic.java b/ojluni/src/test/java/util/Optional/Basic.java
new file mode 100644
index 0000000..89f8a5e
--- /dev/null
+++ b/ojluni/src/test/java/util/Optional/Basic.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8195649
+ * @summary Basic functional test of Optional
+ * @author Mike Duigou
+ * @build ObscureException
+ * @run testng Basic
+ */
+package test.java.util.Optional;
+
+// Android-added: support for wrapper to avoid d8 backporting of Optional methods (b/191859202).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static java.util.stream.Collectors.toList;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class Basic {
+
+    /**
+     * Checks a block of assertions over an empty Optional.
+     */
+    void checkEmpty(Optional<String> empty) {
+        assertTrue(empty.equals(Optional.empty()));
+        assertTrue(Optional.empty().equals(empty));
+        assertFalse(empty.equals(Optional.of("unexpected")));
+        assertFalse(Optional.of("unexpected").equals(empty));
+        assertFalse(empty.equals("unexpected"));
+
+        assertFalse(empty.isPresent());
+        // Android-changed: use Optional_isEmpty() to a void d8 backporting (b/191859202).
+        // assertTrue(empty.isEmpty());
+        assertTrue(Optional_isEmpty(empty));
+        assertEquals(empty.hashCode(), 0);
+        assertEquals(empty.orElse("x"), "x");
+        assertEquals(empty.orElseGet(() -> "y"), "y");
+
+        assertThrows(NoSuchElementException.class, () -> empty.get());
+        // Android-changed: use Optional_orElseThrow() to a void d8 backporting (b/191859202).
+        // assertThrows(NoSuchElementException.class, () -> empty.orElseThrow());
+        assertThrows(NoSuchElementException.class, () -> Optional_orElseThrow(empty));
+        assertThrows(ObscureException.class,       () -> empty.orElseThrow(ObscureException::new));
+
+        AtomicBoolean b = new AtomicBoolean();
+        empty.ifPresent(s -> b.set(true));
+        assertFalse(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202).
+        // empty.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        Optional_ifPresentOrElse(empty, s -> b1.set(true), () -> b2.set(true));
+        assertFalse(b1.get());
+        assertTrue(b2.get());
+
+        assertEquals(empty.toString(), "Optional.empty");
+    }
+
+    /**
+     * Checks a block of assertions over an Optional that is expected to
+     * have a particular value present.
+     */
+    void checkPresent(Optional<String> opt, String expected) {
+        assertFalse(opt.equals(Optional.empty()));
+        assertFalse(Optional.empty().equals(opt));
+        assertTrue(opt.equals(Optional.of(expected)));
+        assertTrue(Optional.of(expected).equals(opt));
+        assertFalse(opt.equals(Optional.of("unexpected")));
+        assertFalse(Optional.of("unexpected").equals(opt));
+        assertFalse(opt.equals("unexpected"));
+
+        assertTrue(opt.isPresent());
+        // Android-changed: use Optional_isEmpty() to a void d8 backporting (b/191859202).
+        //assertFalse(opt.isEmpty());
+        assertFalse(Optional_isEmpty(opt));
+        assertEquals(opt.hashCode(), expected.hashCode());
+        assertEquals(opt.orElse("unexpected"), expected);
+        assertEquals(opt.orElseGet(() -> "unexpected"), expected);
+
+        assertEquals(opt.get(), expected);
+        // Android-changed: use Optional_orElseThrow() to a void d8 backporting (b/191859202).
+        // assertEquals(opt.orElseThrow(), expected);
+        assertEquals(Optional_orElseThrow(opt), expected);
+        assertEquals(opt.orElseThrow(ObscureException::new), expected);
+
+        AtomicBoolean b = new AtomicBoolean(false);
+        opt.ifPresent(s -> b.set(true));
+        assertTrue(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202).
+        // opt.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        Optional_ifPresentOrElse(opt, s -> b1.set(true), () -> b2.set(true));
+        assertTrue(b1.get());
+        assertFalse(b2.get());
+
+        assertEquals(opt.toString(), "Optional[" + expected + "]");
+    }
+
+    @Test
+    public void testEmpty() {
+        checkEmpty(Optional.empty());
+    }
+
+    @Test
+    public void testOfNull() {
+        assertThrows(NullPointerException.class, () -> Optional.of(null));
+    }
+
+    @Test
+    public void testOfPresent() {
+        checkPresent(Optional.of("xyzzy"), "xyzzy");
+    }
+
+    @Test
+    public void testOfNullableNull() {
+        checkEmpty(Optional.ofNullable(null));
+    }
+
+    @Test
+    public void testOfNullablePresent() {
+        checkPresent(Optional.ofNullable("xyzzy"), "xyzzy");
+    }
+
+    @Test
+    public void testFilterEmpty() {
+        checkEmpty(Optional.<String>empty().filter(s -> { fail(); return true; }));
+    }
+
+    @Test
+    public void testFilterFalse() {
+        checkEmpty(Optional.of("xyzzy").filter(s -> s.equals("plugh")));
+    }
+
+    @Test
+    public void testFilterTrue() {
+        checkPresent(Optional.of("xyzzy").filter(s -> s.equals("xyzzy")), "xyzzy");
+    }
+
+    @Test
+    public void testMapEmpty() {
+        checkEmpty(Optional.empty().map(s -> { fail(); return ""; }));
+    }
+
+    @Test
+    public void testMapPresent() {
+        checkPresent(Optional.of("xyzzy").map(s -> s.replace("xyzzy", "plugh")), "plugh");
+    }
+
+    @Test
+    public void testFlatMapEmpty() {
+        checkEmpty(Optional.empty().flatMap(s -> { fail(); return Optional.of(""); }));
+    }
+
+    @Test
+    public void testFlatMapPresentReturnEmpty() {
+        checkEmpty(Optional.of("xyzzy")
+                           .flatMap(s -> { assertEquals(s, "xyzzy"); return Optional.empty(); }));
+    }
+
+    @Test
+    public void testFlatMapPresentReturnPresent() {
+        checkPresent(Optional.of("xyzzy")
+                             .flatMap(s -> { assertEquals(s, "xyzzy"); return Optional.of("plugh"); }),
+                     "plugh");
+    }
+
+    @Test
+    public void testOrEmptyEmpty() {
+        // Android-changed: use Optional_or() to a void d8 backporting (b/191859202).
+        // checkEmpty(Optional.<String>empty().or(() -> Optional.empty()));
+        checkEmpty(Optional_or(Optional.<String>empty(), () -> Optional.empty()));
+    }
+
+    @Test
+    public void testOrEmptyPresent() {
+        // Android-changed: use Optional_or() to a void d8 backporting (b/191859202).
+        // checkPresent(Optional.<String>empty().or(() -> Optional.of("plugh")), "plugh");
+        checkPresent(Optional_or(Optional.<String>empty(), () -> Optional.of("plugh")), "plugh");
+    }
+
+    @Test
+    public void testOrPresentDontCare() {
+        // Android-changed: use Optional_or() to a void d8 backporting (b/191859202).
+        // checkPresent(Optional.of("xyzzy").or(() -> { fail(); return Optional.of("plugh"); }), "xyzzy");
+        checkPresent(Optional_or(Optional.of("xyzzy"), () -> { fail(); return Optional.of("plugh"); }), "xyzzy");
+    }
+
+    @Test
+    public void testStreamEmpty() {
+        // Android-changed: use Optional_stream() to a void d8 backporting (b/191859202).
+        // assertEquals(Optional.empty().stream().collect(toList()), List.of());
+        assertEquals(Optional_stream(Optional.empty()).collect(toList()), List.of());
+    }
+
+    @Test
+    public void testStreamPresent() {
+        // Android-changed: use Optional_stream() to a void d8 backporting (b/191859202).
+        // assertEquals(Optional.of("xyzzy").stream().collect(toList()), List.of("xyzzy"));
+        assertEquals(Optional_stream(Optional.of("xyzzy")).collect(toList()), List.of("xyzzy"));
+    }
+
+    // BEGIN Android-added: More tests for coverage http://b/203822442.
+    // Also improves coverage for Optional{Int,Long,Double}
+    private static final Optional<Integer> P = Optional.<Integer>of(3);
+    private static final Optional<Integer> E = Optional.<Integer>empty();
+
+    @Test
+    void testIfPresentOrElse_empty() {
+        AtomicInteger flag = new AtomicInteger(0);
+        // Note use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202).
+        // E.ifPresentOrElse(integer -> flag.set(1), () -> flag.set(2));
+        Optional_ifPresentOrElse(E, integer -> flag.set(1), () -> flag.set(2));
+        assertEquals(flag.get(), 2);
+    }
+
+    @Test
+    void testIfPresentOrElse_present() {
+        AtomicInteger flag = new AtomicInteger(0);
+        // Note use Optional_ifPresentOrElse() to a void d8 backporting (b/191859202).
+        // P.ifPresentOrElse(integer -> flag.set(1), () -> flag.set(2));
+        Optional_ifPresentOrElse(P, integer -> flag.set(1), () -> flag.set(2));
+        assertEquals(flag.get(), 1);
+    }
+
+    @Test
+    void testOr_empty() {
+        // Note use Optional_or() to a void d8 backporting (b/191859202).
+        Optional<Integer> o = Optional_or(E, () -> Optional.of(5));
+        assertEquals((int) o.get(), 5);
+    }
+
+    @Test
+    void testOr_present() {
+        // Note use Optional_or() to a void d8 backporting (b/191859202).
+        // Optional<Integer> o = P.or(() -> Optional.of(5));
+        Optional<Integer> o = Optional_or(P, () -> Optional.of(5));
+        assertEquals((int) o.get(), 3);
+    }
+
+    @Test
+    public void testStream_empty() {
+        // Not use Optional_stream() to a void d8 backporting (b/191859202).
+        // Stream<Integer> s = E.stream();
+        Stream<Integer> s = Optional_stream(E);
+        assertEquals(s.collect(Collectors.toList()), List.of());
+    }
+
+    @Test
+    public void testStream_present() {
+        // Not use Optional_stream() to a void d8 backporting (b/191859202).
+        // Stream<Integer> s = P.stream();
+        Stream<Integer> s = Optional_stream(P);
+        assertEquals(s.collect(Collectors.toList()), List.of(3));
+    }
+
+    @Test(expectedExceptions = NoSuchElementException.class)
+    public void testOrElseThrow_empty() {
+        // Note use Optional_orElseThrow() to a void d8 backporting (b/191859202).
+        // E.orElseThrow();
+        Optional_orElseThrow(E);
+    }
+
+    @Test
+    public void testOrElseThrow_present() {
+        // Note use Optional_orElseThrow() to a void d8 backporting (b/191859202).
+        // assertEquals((int) P.orElseThrow(), 3);
+        assertEquals((int) Optional_orElseThrow(P), 3);
+    }
+
+    @Test
+    public void testIsEmpty_empty() {
+        // Note use Optional_isEmpty() to a void d8 backporting (b/191859202).
+        // assertTrue(E.isEmpty());
+        assertTrue(Optional_isEmpty(E));
+    }
+
+    @Test
+    public void testIsEmpty_present() {
+        // Note use Optional_isEmpty() to a void d8 backporting (b/191859202).
+        // assertFalse(P.isEmpty());
+        assertFalse(Optional_isEmpty(P));
+    }
+    // END Android-added: More tests for coverage http://b/203822442.
+
+    // Android-added: wrapper to avoid d8 backporting of Optional.ifPresentOrElse() (b/191859202).
+    private static <T> void Optional_ifPresentOrElse(
+            Optional<T> receiver, Consumer<? super T> action, Runnable emptyAction) {
+        try {
+            MethodType type = MethodType.methodType(void.class, Consumer.class, Runnable.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(Optional.class, "ifPresentOrElse", type);
+            mh.invokeExact(receiver, action, emptyAction);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of Optional.isEmpty() (b/191859202).
+    private static <T> boolean Optional_isEmpty(Optional<T> receiver) {
+        try {
+            MethodType type = MethodType.methodType(boolean.class);
+            MethodHandle mh = MethodHandles.lookup().findVirtual(Optional.class, "isEmpty", type);
+            return (boolean) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of Optional.or(Supplier) (b/191859202).
+    private static <T> Optional<T> Optional_or(Optional<T> receiver,
+                                               Supplier<? extends Optional<? extends T>> supplier) {
+        try {
+            MethodType type = MethodType.methodType(Optional.class, Supplier.class);
+            MethodHandle mh = MethodHandles.lookup().findVirtual(Optional.class, "or", type);
+            return (Optional<T>) mh.invokeExact(receiver, supplier);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of Optional.orElseThrow() (b/191859202).
+    private static <T> T Optional_orElseThrow(Optional<T> receiver) {
+        try {
+            MethodType type = MethodType.methodType(Object.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(Optional.class, "orElseThrow", type);
+            return (T) mh.invokeExact(receiver);
+        } catch (NoSuchElementException expected) {
+            throw expected;  // Underlying method may throw NoSuchElementException
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backporting of Optional.stream() (b/191859202).
+    private static <T> Stream<T> Optional_stream(Optional<T> receiver) {
+        try {
+            MethodType type = MethodType.methodType(Stream.class);
+            MethodHandle mh = MethodHandles.lookup().findVirtual(Optional.class, "stream", type);
+            return (Stream<T>) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Optional/BasicDouble.java b/ojluni/src/test/java/util/Optional/BasicDouble.java
new file mode 100644
index 0000000..5dd44f7
--- /dev/null
+++ b/ojluni/src/test/java/util/Optional/BasicDouble.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8195649
+ * @summary Basic functional test of OptionalDouble
+ * @author Mike Duigou
+ * @build ObscureException
+ * @run testng BasicDouble
+ */
+package test.java.util.Optional;
+
+// Android-added: support for wrapper to avoid d8 backporting of Optional methods (b/191859202).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.function.DoubleConsumer;
+import java.util.stream.DoubleStream;
+
+import java.util.NoSuchElementException;
+import java.util.OptionalDouble;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class BasicDouble {
+    static final double DOUBLEVAL = Math.PI;
+    static final double UNEXPECTED = 6.62607004E-34;
+
+    /**
+     * Checks a block of assertions over an empty OptionalDouble.
+     */
+    void checkEmpty(OptionalDouble empty) {
+        assertTrue(empty.equals(OptionalDouble.empty()));
+        assertTrue(OptionalDouble.empty().equals(empty));
+        assertFalse(empty.equals(OptionalDouble.of(UNEXPECTED)));
+        assertFalse(OptionalDouble.of(UNEXPECTED).equals(empty));
+        assertFalse(empty.equals("unexpected"));
+
+        assertFalse(empty.isPresent());
+        // Android-changed: Avoid backporting of isEmpty() (b/191859202).
+        // assertTrue(empty.isEmpty());
+        assertTrue(OptionalDouble_isEmpty(empty));
+        assertEquals(empty.hashCode(), 0);
+        assertEquals(empty.orElse(UNEXPECTED), UNEXPECTED);
+        assertEquals(empty.orElseGet(() -> UNEXPECTED), UNEXPECTED);
+
+        assertThrows(NoSuchElementException.class, () -> empty.getAsDouble());
+        // Android-changed: Avoid backporting of orElseThrow() (b/191859202).
+        // assertThrows(NoSuchElementException.class, () -> empty.orElseThrow());
+        assertThrows(NoSuchElementException.class, () -> OptionalDouble_orElseThrow(empty));
+        assertThrows(ObscureException.class,       () -> empty.orElseThrow(ObscureException::new));
+
+        AtomicBoolean b = new AtomicBoolean();
+        empty.ifPresent(s -> b.set(true));
+        assertFalse(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202).
+        // empty.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        OptionalDouble_ifPresentOrElse(empty, s -> b1.set(true), () -> b2.set(true));
+        assertFalse(b1.get());
+        assertTrue(b2.get());
+
+        assertEquals(empty.toString(), "OptionalDouble.empty");
+    }
+
+    /**
+     * Checks a block of assertions over an OptionalDouble that is expected to
+     * have a particular value present.
+     */
+    void checkPresent(OptionalDouble opt, double expected) {
+        assertFalse(opt.equals(OptionalDouble.empty()));
+        assertFalse(OptionalDouble.empty().equals(opt));
+        assertTrue(opt.equals(OptionalDouble.of(expected)));
+        assertTrue(OptionalDouble.of(expected).equals(opt));
+        assertFalse(opt.equals(OptionalDouble.of(UNEXPECTED)));
+        assertFalse(OptionalDouble.of(UNEXPECTED).equals(opt));
+        assertFalse(opt.equals("unexpected"));
+
+        assertTrue(opt.isPresent());
+        // Android-changed: Avoid backporting of isEmpty() (b/191859202).
+        // assertFalse(opt.isEmpty());
+        assertFalse(OptionalDouble_isEmpty(opt));
+        assertEquals(opt.hashCode(), Double.hashCode(expected));
+        assertEquals(opt.orElse(UNEXPECTED), expected);
+        assertEquals(opt.orElseGet(() -> UNEXPECTED), expected);
+
+        assertEquals(opt.getAsDouble(), expected);
+        // Android-changed: Avoid backporting of orElseThrow() (b/191859202).
+        // assertEquals(opt.orElseThrow(), expected);
+        assertEquals(OptionalDouble_orElseThrow(opt), expected);
+        assertEquals(opt.orElseThrow(ObscureException::new), expected);
+
+        AtomicBoolean b = new AtomicBoolean(false);
+        opt.ifPresent(s -> b.set(true));
+        assertTrue(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202).
+        // opt.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        OptionalDouble_ifPresentOrElse(opt, s -> b1.set(true), () -> b2.set(true));
+        assertTrue(b1.get());
+        assertFalse(b2.get());
+
+        assertEquals(opt.toString(), "OptionalDouble[" + expected + "]");
+    }
+
+    @Test
+    public void testEmpty() {
+        checkEmpty(OptionalDouble.empty());
+    }
+
+    @Test
+    public void testPresent() {
+        checkPresent(OptionalDouble.of(DOUBLEVAL), DOUBLEVAL);
+    }
+
+    @Test
+    public void testStreamEmpty() {
+        // Android-changed: Avoid backporting of stream() (b/191859202).
+        // assertEquals(OptionalDouble.empty().stream().toArray(), new double[] { });
+        assertEquals(OptionalDouble_stream(OptionalDouble.empty()).toArray(), new double[] { });
+    }
+
+    @Test
+    public void testStreamPresent() {
+        // Android-changed: Avoid backporting of stream() (b/191859202).
+        // assertEquals(OptionalDouble.of(DOUBLEVAL).stream().toArray(), new double[] { DOUBLEVAL });
+        assertEquals(OptionalDouble_stream(OptionalDouble.of(DOUBLEVAL)).toArray(),
+                     new double[] { DOUBLEVAL });
+    }
+
+    // Android-added: wrapper for d8 backport of OptionalDouble.ifPresentOrElse() (b/191859202).
+    private static void OptionalDouble_ifPresentOrElse(
+            OptionalDouble receiver, DoubleConsumer action, Runnable emptyAction) {
+        try {
+            MethodType type =
+                    MethodType.methodType(void.class, DoubleConsumer.class, Runnable.class);
+            MethodHandle mh = MethodHandles.lookup().findVirtual(OptionalDouble.class,
+                                                                 "ifPresentOrElse",
+                                                                 type);
+            mh.invokeExact(receiver, action, emptyAction);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalDouble.isEmpty() (b/191859202).
+    private static boolean OptionalDouble_isEmpty(OptionalDouble receiver) {
+        try {
+            MethodType type = MethodType.methodType(boolean.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalDouble.class, "isEmpty", type);
+            return (boolean) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalDouble.orElseThrow() (b/191859202).
+    private static double OptionalDouble_orElseThrow(OptionalDouble receiver) {
+        try {
+            MethodType type = MethodType.methodType(double.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalDouble.class, "orElseThrow", type);
+            return (double) mh.invokeExact(receiver);
+        } catch (NoSuchElementException expected) {
+            throw expected;  // Underlying method may throw NoSuchElementException
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalDouble.stream() (b/191859202).
+    private static DoubleStream OptionalDouble_stream(OptionalDouble receiver) {
+        try {
+            MethodType type = MethodType.methodType(DoubleStream.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalDouble.class, "stream", type);
+            return (DoubleStream) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Optional/BasicInt.java b/ojluni/src/test/java/util/Optional/BasicInt.java
new file mode 100644
index 0000000..81f49a5
--- /dev/null
+++ b/ojluni/src/test/java/util/Optional/BasicInt.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8195649
+ * @summary Basic functional test of OptionalInt
+ * @author Mike Duigou
+ * @build ObscureException
+ * @run testng BasicInt
+ */
+package test.java.util.Optional;
+
+// Android-added: support for wrapper to avoid d8 backporting of Optional methods (b/191859202).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.function.IntConsumer;
+import java.util.stream.IntStream;
+
+import java.util.NoSuchElementException;
+import java.util.OptionalInt;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class BasicInt {
+
+    static final int INTVAL = 33_550_336;
+    static final int UNEXPECTED = 0xCAFEBABE;
+
+    /**
+     * Checks a block of assertions over an empty OptionalInt.
+     */
+    void checkEmpty(OptionalInt empty) {
+        assertTrue(empty.equals(OptionalInt.empty()));
+        assertTrue(OptionalInt.empty().equals(empty));
+        assertFalse(empty.equals(OptionalInt.of(UNEXPECTED)));
+        assertFalse(OptionalInt.of(UNEXPECTED).equals(empty));
+        assertFalse(empty.equals("unexpected"));
+
+        assertFalse(empty.isPresent());
+        // Android-changed: Avoid backporting of isEmpty() (b/191859202).
+        // assertTrue(empty.isEmpty());
+        assertTrue(OptionalInt_isEmpty(empty));
+        assertEquals(empty.hashCode(), 0);
+        assertEquals(empty.orElse(UNEXPECTED), UNEXPECTED);
+        assertEquals(empty.orElseGet(() -> UNEXPECTED), UNEXPECTED);
+
+        assertThrows(NoSuchElementException.class, () -> empty.getAsInt());
+        // Android-changed: Avoid backporting of orElseThrow() (b/191859202).
+        // assertThrows(NoSuchElementException.class, () -> empty.orElseThrow());
+        assertThrows(NoSuchElementException.class, () -> OptionalInt_orElseThrow(empty));
+        assertThrows(ObscureException.class,       () -> empty.orElseThrow(ObscureException::new));
+
+        AtomicBoolean b = new AtomicBoolean();
+        empty.ifPresent(s -> b.set(true));
+        assertFalse(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202).
+        // empty.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        OptionalInt_ifPresentOrElse(empty, s -> b1.set(true), () -> b2.set(true));
+        assertFalse(b1.get());
+        assertTrue(b2.get());
+
+        assertEquals(empty.toString(), "OptionalInt.empty");
+    }
+
+    /**
+     * Checks a block of assertions over an OptionalInt that is expected to
+     * have a particular value present.
+     */
+    void checkPresent(OptionalInt opt, int expected) {
+        assertFalse(opt.equals(OptionalInt.empty()));
+        assertFalse(OptionalInt.empty().equals(opt));
+        assertTrue(opt.equals(OptionalInt.of(expected)));
+        assertTrue(OptionalInt.of(expected).equals(opt));
+        assertFalse(opt.equals(OptionalInt.of(UNEXPECTED)));
+        assertFalse(OptionalInt.of(UNEXPECTED).equals(opt));
+        assertFalse(opt.equals("unexpected"));
+
+        assertTrue(opt.isPresent());
+        // Android-changed: Avoid backporting of isEmpty() (b/191859202).
+        // assertFalse(opt.isEmpty());
+        assertFalse(OptionalInt_isEmpty(opt));
+        assertEquals(opt.hashCode(), Integer.hashCode(expected));
+        assertEquals(opt.orElse(UNEXPECTED), expected);
+        assertEquals(opt.orElseGet(() -> UNEXPECTED), expected);
+
+        assertEquals(opt.getAsInt(), expected);
+        // Android-changed: Avoid backporting of orElseThrow() (b/191859202).
+        assertEquals(OptionalInt_orElseThrow(opt), expected);
+        assertEquals(opt.orElseThrow(ObscureException::new), expected);
+
+        AtomicBoolean b = new AtomicBoolean(false);
+        opt.ifPresent(s -> b.set(true));
+        assertTrue(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202).
+        // opt.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        OptionalInt_ifPresentOrElse(opt, s -> b1.set(true), () -> b2.set(true));
+        assertTrue(b1.get());
+        assertFalse(b2.get());
+
+        assertEquals(opt.toString(), "OptionalInt[" + expected + "]");
+    }
+
+    @Test
+    public void testEmpty() {
+        checkEmpty(OptionalInt.empty());
+    }
+
+    @Test
+    public void testPresent() {
+        checkPresent(OptionalInt.of(INTVAL), INTVAL);
+    }
+
+    @Test
+    public void testStreamEmpty() {
+        // Android-changed: Avoid backporting of stream() (b/191859202).
+        // assertEquals(OptionalInt.empty().stream().toArray(), new int[] { });
+        assertEquals(OptionalInt_stream(OptionalInt.empty()).toArray(), new int[] { });
+    }
+
+    @Test
+    public void testStreamPresent() {
+        // Android-changed: Avoid backporting of stream() (b/191859202).
+        // assertEquals(OptionalInt.of(INTVAL).stream().toArray(), new int[] { INTVAL });
+        assertEquals(OptionalInt_stream(OptionalInt.of(INTVAL)).toArray(), new int[] { INTVAL });
+    }
+
+        // Android-added: wrapper for d8 backport of OptionalInt.ifPresentOrElse() (b/191859202).
+    private static void OptionalInt_ifPresentOrElse(
+            OptionalInt receiver, IntConsumer action, Runnable emptyAction) {
+        try {
+            MethodType type = MethodType.methodType(void.class, IntConsumer.class, Runnable.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalInt.class, "ifPresentOrElse", type);
+            mh.invokeExact(receiver, action, emptyAction);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalInt.isEmpty() (b/191859202).
+    private static boolean OptionalInt_isEmpty(OptionalInt receiver) {
+        try {
+            MethodType type = MethodType.methodType(boolean.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalInt.class, "isEmpty", type);
+            return (boolean) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalInt.orElseThrow() (b/191859202).
+    private static int OptionalInt_orElseThrow(OptionalInt receiver) {
+        try {
+            MethodType type = MethodType.methodType(int.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalInt.class, "orElseThrow", type);
+            return (int) mh.invokeExact(receiver);
+        } catch (NoSuchElementException expected) {
+            throw expected;  // Underlying method may throw NoSuchElementException
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalInt.stream() (b/191859202).
+    private static IntStream OptionalInt_stream(OptionalInt receiver) {
+        try {
+            MethodType type = MethodType.methodType(IntStream.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalInt.class, "stream", type);
+            return (IntStream) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Optional/BasicLong.java b/ojluni/src/test/java/util/Optional/BasicLong.java
new file mode 100644
index 0000000..d9eeb89
--- /dev/null
+++ b/ojluni/src/test/java/util/Optional/BasicLong.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8195649
+ * @summary Basic functional test of OptionalLong
+ * @author Mike Duigou
+ * @build ObscureException
+ * @run testng BasicLong
+ */
+package test.java.util.Optional;
+
+// Android-added: support for wrapper to avoid d8 backporting of Optional methods (b/191859202).
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.function.LongConsumer;
+import java.util.stream.LongStream;
+
+import java.util.NoSuchElementException;
+import java.util.OptionalLong;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class BasicLong {
+    static final long LONGVAL = 2_305_843_008_139_952_128L;
+    static final long UNEXPECTED = 0xFEEDBEEFCAFEBABEL;
+
+    /**
+     * Checks a block of assertions over an empty OptionalLong.
+     */
+    void checkEmpty(OptionalLong empty) {
+        assertTrue(empty.equals(OptionalLong.empty()));
+        assertTrue(OptionalLong.empty().equals(empty));
+        assertFalse(empty.equals(OptionalLong.of(UNEXPECTED)));
+        assertFalse(OptionalLong.of(UNEXPECTED).equals(empty));
+        assertFalse(empty.equals("unexpected"));
+
+        assertFalse(empty.isPresent());
+        // Android-changed: Avoid backporting of isEmpty()) (b/191859202).
+        // assertTrue(empty.isEmpty());
+        assertTrue(OptionalLong_isEmpty(empty));
+        assertEquals(empty.hashCode(), 0);
+        assertEquals(empty.orElse(UNEXPECTED), UNEXPECTED);
+        assertEquals(empty.orElseGet(() -> UNEXPECTED), UNEXPECTED);
+
+        assertThrows(NoSuchElementException.class, () -> empty.getAsLong());
+        // Android-changed: Avoid backporting of orElseThrow()) (b/191859202).
+        // assertThrows(NoSuchElementException.class, () -> empty.orElseThrow());
+        assertThrows(NoSuchElementException.class, () -> OptionalLong_orElseThrow(empty));
+        assertThrows(ObscureException.class,       () -> empty.orElseThrow(ObscureException::new));
+
+        AtomicBoolean b = new AtomicBoolean();
+        empty.ifPresent(s -> b.set(true));
+        assertFalse(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202).
+        // empty.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        OptionalLong_ifPresentOrElse(empty, s -> b1.set(true), () -> b2.set(true));
+        assertFalse(b1.get());
+        assertTrue(b2.get());
+
+        assertEquals(empty.toString(), "OptionalLong.empty");
+    }
+
+    /**
+     * Checks a block of assertions over an OptionalLong that is expected to
+     * have a particular value present.
+     */
+    void checkPresent(OptionalLong opt, long expected) {
+        assertFalse(opt.equals(OptionalLong.empty()));
+        assertFalse(OptionalLong.empty().equals(opt));
+        assertTrue(opt.equals(OptionalLong.of(expected)));
+        assertTrue(OptionalLong.of(expected).equals(opt));
+        assertFalse(opt.equals(OptionalLong.of(UNEXPECTED)));
+        assertFalse(OptionalLong.of(UNEXPECTED).equals(opt));
+        assertFalse(opt.equals("unexpected"));
+
+        assertTrue(opt.isPresent());
+        // Android-changed: Avoid backporting of isEmpty()) (b/191859202).
+        // assertFalse(opt.isEmpty());
+        assertFalse(OptionalLong_isEmpty(opt));
+        assertEquals(opt.hashCode(), Long.hashCode(expected));
+        assertEquals(opt.orElse(UNEXPECTED), expected);
+        assertEquals(opt.orElseGet(() -> UNEXPECTED), expected);
+
+        assertEquals(opt.getAsLong(), expected);
+        // Android-changed: Avoid backporting of orElseThrow()) (b/191859202).
+        // assertEquals(opt.orElseThrow(), expected);
+        assertEquals(OptionalLong_orElseThrow(opt), expected);
+        assertEquals(opt.orElseThrow(ObscureException::new), expected);
+
+        AtomicBoolean b = new AtomicBoolean(false);
+        opt.ifPresent(s -> b.set(true));
+        assertTrue(b.get());
+
+        AtomicBoolean b1 = new AtomicBoolean(false);
+        AtomicBoolean b2 = new AtomicBoolean(false);
+        // Android-changed: Avoid backporting of ifPresentOrElse() (b/191859202).
+        // opt.ifPresentOrElse(s -> b1.set(true), () -> b2.set(true));
+        OptionalLong_ifPresentOrElse(opt, s -> b1.set(true), () -> b2.set(true));
+        assertTrue(b1.get());
+        assertFalse(b2.get());
+
+        assertEquals(opt.toString(), "OptionalLong[" + expected + "]");
+    }
+
+    @Test
+    public void testEmpty() {
+        checkEmpty(OptionalLong.empty());
+    }
+
+    @Test
+    public void testPresent() {
+        checkPresent(OptionalLong.of(LONGVAL), LONGVAL);
+    }
+
+    @Test
+    public void testStreamEmpty() {
+        // Android-changed: Avoid backporting of stream() (b/191859202).
+        // assertEquals(OptionalLong.empty().stream().toArray(), new long[] { });
+        assertEquals(OptionalLong_stream(OptionalLong.empty()).toArray(), new long[] { });
+    }
+
+    @Test
+    public void testStreamPresent() {
+        // Android-changed: Avoid backporting of stream() (b/191859202).
+        // assertEquals(OptionalLong.of(LONGVAL).stream().toArray(), new long[] { LONGVAL });
+        assertEquals(OptionalLong_stream(OptionalLong.of(LONGVAL)).toArray(),
+                     new long[] { LONGVAL });
+    }
+
+    // Android-added: wrapper for d8 backport of OptionalLong.ifPresentOrElse() (b/191859202).
+    private static void OptionalLong_ifPresentOrElse(
+            OptionalLong receiver, LongConsumer action, Runnable emptyAction) {
+        try {
+            MethodType type =
+                    MethodType.methodType(void.class, LongConsumer.class, Runnable.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalLong.class, "ifPresentOrElse", type);
+            mh.invokeExact(receiver, action, emptyAction);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalLong.isEmpty() (b/191859202).
+    private static boolean OptionalLong_isEmpty(OptionalLong receiver) {
+        try {
+            MethodType type = MethodType.methodType(boolean.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalLong.class, "isEmpty", type);
+            return (boolean) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalLong.orElseThrow() (b/191859202).
+    private static long OptionalLong_orElseThrow(OptionalLong receiver) {
+        try {
+            MethodType type = MethodType.methodType(long.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalLong.class, "orElseThrow", type);
+            return (long) mh.invokeExact(receiver);
+        } catch (NoSuchElementException expected) {
+            throw expected;  // Underlying method may throw NoSuchElementException
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    // Android-added: wrapper to avoid d8 backport of OptionalLong.stream() (b/191859202).
+    private static LongStream OptionalLong_stream(OptionalLong receiver) {
+        try {
+            MethodType type = MethodType.methodType(LongStream.class);
+            MethodHandle mh =
+                    MethodHandles.lookup().findVirtual(OptionalLong.class, "stream", type);
+            return (LongStream) mh.invokeExact(receiver);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+}
diff --git a/ojluni/src/test/java/util/Optional/ObscureException.java b/ojluni/src/test/java/util/Optional/ObscureException.java
new file mode 100644
index 0000000..f814f00
--- /dev/null
+++ b/ojluni/src/test/java/util/Optional/ObscureException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.Optional;
+
+/**
+ * A unique exception used for checking exception types.
+ */
+public class ObscureException extends RuntimeException { }
diff --git a/ojluni/src/test/java/util/TimeZone/SimpleTimeZoneCloneRaceTest.java b/ojluni/src/test/java/util/TimeZone/SimpleTimeZoneCloneRaceTest.java
new file mode 100644
index 0000000..136bdf5
--- /dev/null
+++ b/ojluni/src/test/java/util/TimeZone/SimpleTimeZoneCloneRaceTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.TimeZone;
+
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+import java.util.function.Supplier;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+/*
+ * @test
+ * @bug 8191216
+ * @summary test that provokes race between cloning and lazily initializing
+ *          SimpleTimeZone cache fields
+ */
+public class SimpleTimeZoneCloneRaceTest {
+
+    @Test
+    public void testSimpleTimeZone() throws InterruptedException {
+
+        // shared TZ user repeatedly samples sharedTZ and calculates offset
+        // using the shared instance
+        TimeZoneUser sharedTZuser = new TimeZoneUser(() -> sharedTZ);
+
+        // cloned TZ user repeatedly samples sharedTZ then clones it and
+        // calculates offset using the clone...
+        TimeZoneUser clonedTZuser = new TimeZoneUser(() -> {
+            // sample shared TZ
+            TimeZone tz = sharedTZ;
+            // do some computation that takes roughly the same time as it takes
+            // sharedTZUser to start changing cache fields in shared TZ
+            cpuHogTZ.getOffset(time);
+            // now clone the sampled TZ and return it, hoping the clone is done
+            // at about the right time....
+            return (TimeZone) tz.clone();
+        });
+
+        // start threads
+        Thread t1 = new Thread(sharedTZuser);
+        Thread t2 = new Thread(clonedTZuser);
+        t1.start();
+        t2.start();
+
+        // plant new SimpleTimeZone instances for 2 seconds
+        long t0 = System.currentTimeMillis();
+        do {
+            TimeZone tz1 = createSTZ();
+            TimeZone tz2 = createSTZ();
+            cpuHogTZ = tz1;
+            sharedTZ = tz2;
+        } while (System.currentTimeMillis() - t0 < 2000L);
+
+        sharedTZuser.stop = true;
+        clonedTZuser.stop = true;
+        t1.join();
+        t2.join();
+
+        Assert.assertFalse(clonedTZuser.incorrectCount > 0, clonedTZuser.incorrectCount +
+                    " fatal data races detected");
+    }
+
+    static SimpleTimeZone createSTZ() {
+        return new SimpleTimeZone(-28800000,
+                "America/Los_Angeles",
+                Calendar.APRIL, 1, -Calendar.SUNDAY,
+                7200000,
+                Calendar.OCTOBER, -1, Calendar.SUNDAY,
+                7200000,
+                3600000);
+    }
+
+    static volatile TimeZone cpuHogTZ = createSTZ();
+    static volatile TimeZone sharedTZ = createSTZ();
+    static final long time;
+    static final long correctOffset;
+
+    static {
+        TimeZone tz = createSTZ();
+        Calendar cal = Calendar.getInstance(tz, Locale.ROOT);
+        cal.set(2000, Calendar.MAY, 1, 0, 0, 0);
+        time = cal.getTimeInMillis();
+        correctOffset = tz.getOffset(time);
+    }
+
+    static class TimeZoneUser implements Runnable {
+        private final Supplier<? extends TimeZone> tzSupplier;
+
+        TimeZoneUser(Supplier<? extends TimeZone> tzSupplier) {
+            this.tzSupplier = tzSupplier;
+        }
+
+        volatile boolean stop;
+        int correctCount, incorrectCount;
+
+        @Override
+        public void run() {
+            while (!stop) {
+                TimeZone tz = tzSupplier.get();
+                int offset = tz.getOffset(time);
+                if (offset == correctOffset) {
+                    correctCount++;
+                } else {
+                    incorrectCount++;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/concurrent/tck/ArrayDequeTest.java b/ojluni/src/test/java/util/concurrent/tck/ArrayDequeTest.java
index 1cff7ff..2b926be 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ArrayDequeTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ArrayDequeTest.java
@@ -775,7 +775,7 @@
         ArrayDeque l = new ArrayDeque();
         l.add(new Object());
         try {
-            l.toArray(null);
+            l.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/ojluni/src/test/java/util/concurrent/tck/BlockingQueueTest.java b/ojluni/src/test/java/util/concurrent/tck/BlockingQueueTest.java
index 6aab850..5d70bf4 100644
--- a/ojluni/src/test/java/util/concurrent/tck/BlockingQueueTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/BlockingQueueTest.java
@@ -162,7 +162,7 @@
     public void testToArray_NullArray() {
         final Collection q = emptyCollection();
         try {
-            q.toArray(null);
+            q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/ojluni/src/test/java/util/concurrent/tck/Collection8Test.java b/ojluni/src/test/java/util/concurrent/tck/Collection8Test.java
index d95bbe3..cab640a 100644
--- a/ojluni/src/test/java/util/concurrent/tck/Collection8Test.java
+++ b/ojluni/src/test/java/util/concurrent/tck/Collection8Test.java
@@ -203,7 +203,7 @@
             () -> c.iterator().forEachRemaining(null),
             () -> c.spliterator().forEachRemaining(null),
             () -> c.spliterator().tryAdvance(null),
-            () -> c.toArray(null));
+            () -> c.toArray((Object[])null));
 
         if (!impl.permitsNulls()) {
             assertThrows(
diff --git a/ojluni/src/test/java/util/concurrent/tck/CompletableFutureTest.java b/ojluni/src/test/java/util/concurrent/tck/CompletableFutureTest.java
index e97a0ab..ada751c 100644
--- a/ojluni/src/test/java/util/concurrent/tck/CompletableFutureTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/CompletableFutureTest.java
@@ -170,7 +170,7 @@
         assertFalse(f.isCancelled());
         assertTrue(f.isDone());
         assertTrue(f.isCompletedExceptionally());
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
+        assertTrue(f.toString().contains("[Completed exceptionally:"));
     }
 
     void checkCompletedWithWrappedCFException(CompletableFuture<?> f) {
@@ -225,7 +225,7 @@
         assertTrue(f.isDone());
         assertTrue(f.isCompletedExceptionally());
         assertTrue(f.isCancelled());
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
+        assertTrue(f.toString().contains("[Completed exceptionally:"));
     }
 
     /**
@@ -372,12 +372,12 @@
 
         f = new CompletableFuture<String>();
         assertTrue(f.completeExceptionally(new IndexOutOfBoundsException()));
-        assertTrue(f.toString().contains("[Completed exceptionally]"));
+        assertTrue(f.toString().contains("[Completed exceptionally:"));
 
         for (boolean mayInterruptIfRunning : new boolean[] { true, false }) {
             f = new CompletableFuture<String>();
             assertTrue(f.cancel(mayInterruptIfRunning));
-            assertTrue(f.toString().contains("[Completed exceptionally]"));
+            assertTrue(f.toString().contains("[Completed exceptionally:"));
         }
     }
 
diff --git a/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java b/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java
index 90dbc71..1547ed6 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedDequeTest.java
@@ -711,7 +711,7 @@
     public void testToArray_NullArg() {
         ConcurrentLinkedDeque q = populatedDeque(SIZE);
         try {
-            q.toArray(null);
+            q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java b/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java
index 1d1e875..4a1399c 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ConcurrentLinkedQueueTest.java
@@ -441,7 +441,7 @@
     public void testToArray_NullArg() {
         ConcurrentLinkedQueue q = populatedQueue(SIZE);
         try {
-            q.toArray(null);
+            q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java b/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java
index 575a8f3..f821a3b 100644
--- a/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java
+++ b/ojluni/src/test/java/util/concurrent/tck/JSR166TestCase.java
@@ -590,6 +590,7 @@
                 "AtomicReferenceArray9Test",
                 "ExecutorCompletionService9Test",
                 "ForkJoinPool9Test",
+                "SubmissionPublisherTest",
             };
             addNamedTestClasses(suite, java9TestClassNames);
         }
diff --git a/ojluni/src/test/java/util/concurrent/tck/LinkedListTest.java b/ojluni/src/test/java/util/concurrent/tck/LinkedListTest.java
index b0afd4f..6c570cb 100644
--- a/ojluni/src/test/java/util/concurrent/tck/LinkedListTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/LinkedListTest.java
@@ -404,7 +404,7 @@
         LinkedList l = new LinkedList();
         l.add(new Object());
         try {
-            l.toArray(null);
+            l.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java b/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java
index d0e4182..ce8baa8 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java
@@ -856,7 +856,9 @@
                                             1, 1, MILLISECONDS));
         periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
                                                1, 1, MILLISECONDS));
-        delayeds.add(p.schedule(task, 1, MILLISECONDS));
+        // Android-changed: Use a longer delay to ensure task does not expire
+        // delayeds.add(p.schedule(task, 1, MILLISECONDS));
+        delayeds.add(p.schedule(task, LONG_DELAY_MS, MILLISECONDS));
 
         assertTrue(p.getQueue().containsAll(periodics));
         assertTrue(p.getQueue().containsAll(delayeds));
diff --git a/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorTest.java b/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorTest.java
index 7f85917..803adaf 100644
--- a/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/ScheduledExecutorTest.java
@@ -804,7 +804,9 @@
                                             1, 1, MILLISECONDS));
         periodics.add(p.scheduleWithFixedDelay(countDowner(periodicLatch2),
                                                1, 1, MILLISECONDS));
-        delayeds.add(p.schedule(task, 1, MILLISECONDS));
+        // Android-changed: Use a longer delay to ensure task does not expire
+        // delayeds.add(p.schedule(task, 1, MILLISECONDS));
+        delayeds.add(p.schedule(task, LONG_DELAY_MS, MILLISECONDS));
 
         assertTrue(p.getQueue().containsAll(periodics));
         assertTrue(p.getQueue().containsAll(delayeds));
diff --git a/ojluni/src/test/java/util/concurrent/tck/SplittableRandomTest.java b/ojluni/src/test/java/util/concurrent/tck/SplittableRandomTest.java
index 99c4bde..b4363b3 100644
--- a/ojluni/src/test/java/util/concurrent/tck/SplittableRandomTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/SplittableRandomTest.java
@@ -553,4 +553,38 @@
         assertEquals(size, counter.sum());
     }
 
+    /**
+     * Repeated calls to nextBytes produce at least values of different signs for every byte
+     */
+    public void testNextBytes() {
+        SplittableRandom sr = new SplittableRandom();
+        int n = sr.nextInt(1, 20);
+        byte[] bytes = new byte[n];
+        outer:
+        for (int i = 0; i < n; i++) {
+            for (int tries = NCALLS; tries-->0; ) {
+                byte before = bytes[i];
+                sr.nextBytes(bytes);
+                byte after = bytes[i];
+                if (after * before < 0)
+                    continue outer;
+            }
+            fail("not enough variation in random bytes");
+        }
+    }
+
+    /**
+     * Filling an empty array with random bytes succeeds without effect.
+     */
+    public void testNextBytes_emptyArray() {
+        new SplittableRandom().nextBytes(new byte[0]);
+    }
+
+    public void testNextBytes_nullArray() {
+        try {
+            new SplittableRandom().nextBytes(null);
+            fail();
+        } catch (NullPointerException success) {
+        }
+    }
 }
diff --git a/ojluni/src/test/java/util/concurrent/tck/SubmissionPublisherTest.java b/ojluni/src/test/java/util/concurrent/tck/SubmissionPublisherTest.java
new file mode 100644
index 0000000..bfdecbe
--- /dev/null
+++ b/ojluni/src/test/java/util/concurrent/tck/SubmissionPublisherTest.java
@@ -0,0 +1,1036 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz 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 test.java.util.concurrent.tck;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Flow;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.SubmissionPublisher;
+import java.util.concurrent.atomic.AtomicInteger;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import static java.util.concurrent.Flow.Subscriber;
+import static java.util.concurrent.Flow.Subscription;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+public class SubmissionPublisherTest extends JSR166TestCase {
+
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(SubmissionPublisherTest.class);
+    }
+
+    final Executor basicExecutor = basicPublisher().getExecutor();
+
+    static SubmissionPublisher<Integer> basicPublisher() {
+        return new SubmissionPublisher<Integer>();
+    }
+
+    static class SPException extends RuntimeException {}
+
+    class TestSubscriber implements Subscriber<Integer> {
+        volatile Subscription sn;
+        int last;  // Requires that onNexts are in numeric order
+        volatile int nexts;
+        volatile int errors;
+        volatile int completes;
+        volatile boolean throwOnCall = false;
+        volatile boolean request = true;
+        volatile Throwable lastError;
+
+        public synchronized void onSubscribe(Subscription s) {
+            threadAssertTrue(sn == null);
+            sn = s;
+            notifyAll();
+            if (throwOnCall)
+                throw new SPException();
+            if (request)
+                sn.request(1L);
+        }
+        public synchronized void onNext(Integer t) {
+            ++nexts;
+            notifyAll();
+            int current = t.intValue();
+            threadAssertTrue(current >= last);
+            last = current;
+            if (request)
+                sn.request(1L);
+            if (throwOnCall)
+                throw new SPException();
+        }
+        public synchronized void onError(Throwable t) {
+            threadAssertTrue(completes == 0);
+            threadAssertTrue(errors == 0);
+            lastError = t;
+            ++errors;
+            notifyAll();
+        }
+        public synchronized void onComplete() {
+            threadAssertTrue(completes == 0);
+            ++completes;
+            notifyAll();
+        }
+
+        synchronized void awaitSubscribe() {
+            while (sn == null) {
+                try {
+                    wait();
+                } catch (Exception ex) {
+                    threadUnexpectedException(ex);
+                    break;
+                }
+            }
+        }
+        synchronized void awaitNext(int n) {
+            while (nexts < n) {
+                try {
+                    wait();
+                } catch (Exception ex) {
+                    threadUnexpectedException(ex);
+                    break;
+                }
+            }
+        }
+        synchronized void awaitComplete() {
+            while (completes == 0 && errors == 0) {
+                try {
+                    wait();
+                } catch (Exception ex) {
+                    threadUnexpectedException(ex);
+                    break;
+                }
+            }
+        }
+        synchronized void awaitError() {
+            while (errors == 0) {
+                try {
+                    wait();
+                } catch (Exception ex) {
+                    threadUnexpectedException(ex);
+                    break;
+                }
+            }
+        }
+
+    }
+
+    /**
+     * A new SubmissionPublisher has no subscribers, a non-null
+     * executor, a power-of-two capacity, is not closed, and reports
+     * zero demand and lag
+     */
+    void checkInitialState(SubmissionPublisher<?> p) {
+        assertFalse(p.hasSubscribers());
+        assertEquals(0, p.getNumberOfSubscribers());
+        assertTrue(p.getSubscribers().isEmpty());
+        assertFalse(p.isClosed());
+        assertNull(p.getClosedException());
+        int n = p.getMaxBufferCapacity();
+        assertTrue((n & (n - 1)) == 0); // power of two
+        assertNotNull(p.getExecutor());
+        assertEquals(0, p.estimateMinimumDemand());
+        assertEquals(0, p.estimateMaximumLag());
+    }
+
+    /**
+     * A default-constructed SubmissionPublisher has no subscribers,
+     * is not closed, has default buffer size, and uses the
+     * defaultExecutor
+     */
+    public void testConstructor1() {
+        SubmissionPublisher<Integer> p = new SubmissionPublisher<>();
+        checkInitialState(p);
+        assertEquals(p.getMaxBufferCapacity(), Flow.defaultBufferSize());
+        Executor e = p.getExecutor(), c = ForkJoinPool.commonPool();
+        if (ForkJoinPool.getCommonPoolParallelism() > 1)
+            assertSame(e, c);
+        else
+            assertNotSame(e, c);
+    }
+
+    /**
+     * A new SubmissionPublisher has no subscribers, is not closed,
+     * has the given buffer size, and uses the given executor
+     */
+    public void testConstructor2() {
+        Executor e = Executors.newFixedThreadPool(1);
+        SubmissionPublisher<Integer> p = new SubmissionPublisher<>(e, 8);
+        checkInitialState(p);
+        assertSame(p.getExecutor(), e);
+        assertEquals(8, p.getMaxBufferCapacity());
+    }
+
+    /**
+     * A null Executor argument to SubmissionPublisher constructor
+     * throws NullPointerException
+     */
+    public void testConstructor3() {
+        try {
+            new SubmissionPublisher<Integer>(null, 8);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * A negative capacity argument to SubmissionPublisher constructor
+     * throws IllegalArgumentException
+     */
+    public void testConstructor4() {
+        Executor e = Executors.newFixedThreadPool(1);
+        try {
+            new SubmissionPublisher<Integer>(e, -1);
+            shouldThrow();
+        } catch (IllegalArgumentException success) {}
+    }
+
+    /**
+     * A closed publisher reports isClosed with no closedException and
+     * throws IllegalStateException upon attempted submission; a
+     * subsequent close or closeExceptionally has no additional
+     * effect.
+     */
+    public void testClose() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        checkInitialState(p);
+        p.close();
+        assertTrue(p.isClosed());
+        assertNull(p.getClosedException());
+        try {
+            p.submit(1);
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+        Throwable ex = new SPException();
+        p.closeExceptionally(ex);
+        assertTrue(p.isClosed());
+        assertNull(p.getClosedException());
+    }
+
+    /**
+     * A publisher closedExceptionally reports isClosed with the
+     * closedException and throws IllegalStateException upon attempted
+     * submission; a subsequent close or closeExceptionally has no
+     * additional effect.
+     */
+    public void testCloseExceptionally() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        checkInitialState(p);
+        Throwable ex = new SPException();
+        p.closeExceptionally(ex);
+        assertTrue(p.isClosed());
+        assertSame(p.getClosedException(), ex);
+        try {
+            p.submit(1);
+            shouldThrow();
+        } catch (IllegalStateException success) {}
+        p.close();
+        assertTrue(p.isClosed());
+        assertSame(p.getClosedException(), ex);
+    }
+
+    /**
+     * Upon subscription, the subscriber's onSubscribe is called, no
+     * other Subscriber methods are invoked, the publisher
+     * hasSubscribers, isSubscribed is true, and existing
+     * subscriptions are unaffected.
+     */
+    public void testSubscribe1() {
+        TestSubscriber s = new TestSubscriber();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        p.subscribe(s);
+        assertTrue(p.hasSubscribers());
+        assertEquals(1, p.getNumberOfSubscribers());
+        assertTrue(p.getSubscribers().contains(s));
+        assertTrue(p.isSubscribed(s));
+        s.awaitSubscribe();
+        assertNotNull(s.sn);
+        assertEquals(0, s.nexts);
+        assertEquals(0, s.errors);
+        assertEquals(0, s.completes);
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s2);
+        assertTrue(p.hasSubscribers());
+        assertEquals(2, p.getNumberOfSubscribers());
+        assertTrue(p.getSubscribers().contains(s));
+        assertTrue(p.getSubscribers().contains(s2));
+        assertTrue(p.isSubscribed(s));
+        assertTrue(p.isSubscribed(s2));
+        s2.awaitSubscribe();
+        assertNotNull(s2.sn);
+        assertEquals(0, s2.nexts);
+        assertEquals(0, s2.errors);
+        assertEquals(0, s2.completes);
+        p.close();
+    }
+
+    /**
+     * If closed, upon subscription, the subscriber's onComplete
+     * method is invoked
+     */
+    public void testSubscribe2() {
+        TestSubscriber s = new TestSubscriber();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        p.close();
+        p.subscribe(s);
+        s.awaitComplete();
+        assertEquals(0, s.nexts);
+        assertEquals(0, s.errors);
+        assertEquals(1, s.completes, 1);
+    }
+
+    /**
+     * If closedExceptionally, upon subscription, the subscriber's
+     * onError method is invoked
+     */
+    public void testSubscribe3() {
+        TestSubscriber s = new TestSubscriber();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        Throwable ex = new SPException();
+        p.closeExceptionally(ex);
+        assertTrue(p.isClosed());
+        assertSame(p.getClosedException(), ex);
+        p.subscribe(s);
+        s.awaitError();
+        assertEquals(0, s.nexts);
+        assertEquals(1, s.errors);
+    }
+
+    /**
+     * Upon attempted resubscription, the subscriber's onError is
+     * called and the subscription is cancelled.
+     */
+    public void testSubscribe4() {
+        TestSubscriber s = new TestSubscriber();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        p.subscribe(s);
+        assertTrue(p.hasSubscribers());
+        assertEquals(1, p.getNumberOfSubscribers());
+        assertTrue(p.getSubscribers().contains(s));
+        assertTrue(p.isSubscribed(s));
+        s.awaitSubscribe();
+        assertNotNull(s.sn);
+        assertEquals(0, s.nexts);
+        assertEquals(0, s.errors);
+        assertEquals(0, s.completes);
+        p.subscribe(s);
+        s.awaitError();
+        assertEquals(0, s.nexts);
+        assertEquals(1, s.errors);
+        assertFalse(p.isSubscribed(s));
+    }
+
+    /**
+     * An exception thrown in onSubscribe causes onError
+     */
+    public void testSubscribe5() {
+        TestSubscriber s = new TestSubscriber();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        s.throwOnCall = true;
+        p.subscribe(s);
+        s.awaitError();
+        assertEquals(0, s.nexts);
+        assertEquals(1, s.errors);
+        assertEquals(0, s.completes);
+    }
+
+    /**
+     * subscribe(null) throws NPE
+     */
+    public void testSubscribe6() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        try {
+            p.subscribe(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+        checkInitialState(p);
+    }
+
+    /**
+     * Closing a publisher causes onComplete to subscribers
+     */
+    public void testCloseCompletes() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        p.submit(1);
+        p.close();
+        assertTrue(p.isClosed());
+        assertNull(p.getClosedException());
+        s1.awaitComplete();
+        assertEquals(1, s1.nexts);
+        assertEquals(1, s1.completes);
+        s2.awaitComplete();
+        assertEquals(1, s2.nexts);
+        assertEquals(1, s2.completes);
+    }
+
+    /**
+     * Closing a publisher exceptionally causes onError to subscribers
+     * after they are subscribed
+     */
+    public void testCloseExceptionallyError() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        p.submit(1);
+        p.closeExceptionally(new SPException());
+        assertTrue(p.isClosed());
+        s1.awaitSubscribe();
+        s1.awaitError();
+        assertTrue(s1.nexts <= 1);
+        assertEquals(1, s1.errors);
+        s2.awaitSubscribe();
+        s2.awaitError();
+        assertTrue(s2.nexts <= 1);
+        assertEquals(1, s2.errors);
+    }
+
+    /**
+     * Cancelling a subscription eventually causes no more onNexts to be issued
+     */
+    public void testCancel() {
+        SubmissionPublisher<Integer> p =
+            new SubmissionPublisher<>(basicExecutor, 4); // must be < 20
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s1.awaitSubscribe();
+        p.submit(1);
+        s1.sn.cancel();
+        for (int i = 2; i <= 20; ++i)
+            p.submit(i);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(20, s2.nexts);
+        assertEquals(1, s2.completes);
+        assertTrue(s1.nexts < 20);
+        assertFalse(p.isSubscribed(s1));
+    }
+
+    /**
+     * Throwing an exception in onNext causes onError
+     */
+    public void testThrowOnNext() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s1.awaitSubscribe();
+        p.submit(1);
+        s1.throwOnCall = true;
+        p.submit(2);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(2, s2.nexts);
+        s1.awaitComplete();
+        assertEquals(1, s1.errors);
+    }
+
+    /**
+     * If a handler is supplied in constructor, it is invoked when
+     * subscriber throws an exception in onNext
+     */
+    public void testThrowOnNextHandler() {
+        AtomicInteger calls = new AtomicInteger();
+        SubmissionPublisher<Integer> p = new SubmissionPublisher<>(
+            basicExecutor, 8, (s, e) -> calls.getAndIncrement());
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s1.awaitSubscribe();
+        p.submit(1);
+        s1.throwOnCall = true;
+        p.submit(2);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(2, s2.nexts);
+        assertEquals(1, s2.completes);
+        s1.awaitError();
+        assertEquals(1, s1.errors);
+        assertEquals(1, calls.get());
+    }
+
+    /**
+     * onNext items are issued in the same order to each subscriber
+     */
+    public void testOrder() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        for (int i = 1; i <= 20; ++i)
+            p.submit(i);
+        p.close();
+        s2.awaitComplete();
+        s1.awaitComplete();
+        assertEquals(20, s2.nexts);
+        assertEquals(1, s2.completes);
+        assertEquals(20, s1.nexts);
+        assertEquals(1, s1.completes);
+    }
+
+    /**
+     * onNext is issued only if requested
+     */
+    public void testRequest1() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        p.subscribe(s1);
+        s1.awaitSubscribe();
+        assertEquals(0, p.estimateMinimumDemand());
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s2);
+        p.submit(1);
+        p.submit(2);
+        s2.awaitNext(1);
+        assertEquals(0, s1.nexts);
+        s1.sn.request(3);
+        p.submit(3);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(3, s2.nexts);
+        assertEquals(1, s2.completes);
+        s1.awaitComplete();
+        assertTrue(s1.nexts > 0);
+        assertEquals(1, s1.completes);
+    }
+
+    /**
+     * onNext is not issued when requests become zero
+     */
+    public void testRequest2() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        s1.request = false;
+        p.submit(1);
+        p.submit(2);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(2, s2.nexts);
+        assertEquals(1, s2.completes);
+        s1.awaitNext(1);
+        assertEquals(1, s1.nexts);
+    }
+
+    /**
+     * Non-positive request causes error
+     */
+    public void testRequest3() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        TestSubscriber s3 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        p.subscribe(s3);
+        s3.awaitSubscribe();
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        s1.sn.request(-1L);
+        s3.sn.request(0L);
+        p.submit(1);
+        p.submit(2);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(2, s2.nexts);
+        assertEquals(1, s2.completes);
+        s1.awaitError();
+        assertEquals(1, s1.errors);
+        assertTrue(s1.lastError instanceof IllegalArgumentException);
+        s3.awaitError();
+        assertEquals(1, s3.errors);
+        assertTrue(s3.lastError instanceof IllegalArgumentException);
+    }
+
+    /**
+     * estimateMinimumDemand reports 0 until request, nonzero after
+     * request
+     */
+    public void testEstimateMinimumDemand() {
+        TestSubscriber s = new TestSubscriber();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        s.request = false;
+        p.subscribe(s);
+        s.awaitSubscribe();
+        assertEquals(0, p.estimateMinimumDemand());
+        s.sn.request(1);
+        assertEquals(1, p.estimateMinimumDemand());
+    }
+
+    /**
+     * submit to a publisher with no subscribers returns lag 0
+     */
+    public void testEmptySubmit() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        assertEquals(0, p.submit(1));
+    }
+
+    /**
+     * submit(null) throws NPE
+     */
+    public void testNullSubmit() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        try {
+            p.submit(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * submit returns number of lagged items, compatible with result
+     * of estimateMaximumLag.
+     */
+    public void testLaggedSubmit() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        assertEquals(1, p.submit(1));
+        assertTrue(p.estimateMaximumLag() >= 1);
+        assertTrue(p.submit(2) >= 2);
+        assertTrue(p.estimateMaximumLag() >= 2);
+        s1.sn.request(4);
+        assertTrue(p.submit(3) >= 3);
+        assertTrue(p.estimateMaximumLag() >= 3);
+        s2.sn.request(4);
+        p.submit(4);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(4, s2.nexts);
+        s1.awaitComplete();
+        assertEquals(4, s2.nexts);
+    }
+
+    /**
+     * submit eventually issues requested items when buffer capacity is 1
+     */
+    public void testCap1Submit() {
+        SubmissionPublisher<Integer> p
+            = new SubmissionPublisher<>(basicExecutor, 1);
+        TestSubscriber s1 = new TestSubscriber();
+        TestSubscriber s2 = new TestSubscriber();
+        p.subscribe(s1);
+        p.subscribe(s2);
+        for (int i = 1; i <= 20; ++i) {
+            assertTrue(p.submit(i) >= 0);
+        }
+        p.close();
+        s2.awaitComplete();
+        s1.awaitComplete();
+        assertEquals(20, s2.nexts);
+        assertEquals(1, s2.completes);
+        assertEquals(20, s1.nexts);
+        assertEquals(1, s1.completes);
+    }
+
+    static boolean noopHandle(AtomicInteger count) {
+        count.getAndIncrement();
+        return false;
+    }
+
+    static boolean reqHandle(AtomicInteger count, Subscriber s) {
+        count.getAndIncrement();
+        ((TestSubscriber)s).sn.request(Long.MAX_VALUE);
+        return true;
+    }
+
+    /**
+     * offer to a publisher with no subscribers returns lag 0
+     */
+    public void testEmptyOffer() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        assertEquals(0, p.offer(1, null));
+    }
+
+    /**
+     * offer(null) throws NPE
+     */
+    public void testNullOffer() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        try {
+            p.offer(null, null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * offer returns number of lagged items if not saturated
+     */
+    public void testLaggedOffer() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        assertTrue(p.offer(1, null) >= 1);
+        assertTrue(p.offer(2, null) >= 2);
+        s1.sn.request(4);
+        assertTrue(p.offer(3, null) >= 3);
+        s2.sn.request(4);
+        p.offer(4, null);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(4, s2.nexts);
+        s1.awaitComplete();
+        assertEquals(4, s2.nexts);
+    }
+
+    /**
+     * offer reports drops if saturated
+     */
+    public void testDroppedOffer() {
+        SubmissionPublisher<Integer> p
+            = new SubmissionPublisher<>(basicExecutor, 4);
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        for (int i = 1; i <= 4; ++i)
+            assertTrue(p.offer(i, null) >= 0);
+        p.offer(5, null);
+        assertTrue(p.offer(6, null) < 0);
+        s1.sn.request(64);
+        assertTrue(p.offer(7, null) < 0);
+        s2.sn.request(64);
+        p.close();
+        s2.awaitComplete();
+        assertTrue(s2.nexts >= 4);
+        s1.awaitComplete();
+        assertTrue(s1.nexts >= 4);
+    }
+
+    /**
+     * offer invokes drop handler if saturated
+     */
+    public void testHandledDroppedOffer() {
+        AtomicInteger calls = new AtomicInteger();
+        SubmissionPublisher<Integer> p
+            = new SubmissionPublisher<>(basicExecutor, 4);
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        for (int i = 1; i <= 4; ++i)
+            assertTrue(p.offer(i, (s, x) -> noopHandle(calls)) >= 0);
+        p.offer(4, (s, x) -> noopHandle(calls));
+        assertTrue(p.offer(6, (s, x) -> noopHandle(calls)) < 0);
+        s1.sn.request(64);
+        assertTrue(p.offer(7, (s, x) -> noopHandle(calls)) < 0);
+        s2.sn.request(64);
+        p.close();
+        s2.awaitComplete();
+        s1.awaitComplete();
+        assertTrue(calls.get() >= 4);
+    }
+
+    /**
+     * offer succeeds if drop handler forces request
+     */
+    public void testRecoveredHandledDroppedOffer() {
+        AtomicInteger calls = new AtomicInteger();
+        SubmissionPublisher<Integer> p
+            = new SubmissionPublisher<>(basicExecutor, 4);
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        int n = 0;
+        for (int i = 1; i <= 8; ++i) {
+            int d = p.offer(i, (s, x) -> reqHandle(calls, s));
+            n = n + 2 + (d < 0 ? d : 0);
+        }
+        p.close();
+        s2.awaitComplete();
+        s1.awaitComplete();
+        assertEquals(n, s1.nexts + s2.nexts);
+        assertTrue(calls.get() >= 2);
+    }
+
+    /**
+     * Timed offer to a publisher with no subscribers returns lag 0
+     */
+    public void testEmptyTimedOffer() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        long startTime = System.nanoTime();
+        assertEquals(0, p.offer(1, LONG_DELAY_MS, MILLISECONDS, null));
+        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
+    }
+
+    /**
+     * Timed offer with null item or TimeUnit throws NPE
+     */
+    public void testNullTimedOffer() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        long startTime = System.nanoTime();
+        try {
+            p.offer(null, LONG_DELAY_MS, MILLISECONDS, null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+        try {
+            p.offer(1, LONG_DELAY_MS, null, null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
+    }
+
+    /**
+     * Timed offer returns number of lagged items if not saturated
+     */
+    public void testLaggedTimedOffer() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        long startTime = System.nanoTime();
+        assertTrue(p.offer(1, LONG_DELAY_MS, MILLISECONDS, null) >= 1);
+        assertTrue(p.offer(2, LONG_DELAY_MS, MILLISECONDS, null) >= 2);
+        s1.sn.request(4);
+        assertTrue(p.offer(3, LONG_DELAY_MS, MILLISECONDS, null) >= 3);
+        s2.sn.request(4);
+        p.offer(4, LONG_DELAY_MS, MILLISECONDS, null);
+        p.close();
+        s2.awaitComplete();
+        assertEquals(4, s2.nexts);
+        s1.awaitComplete();
+        assertEquals(4, s2.nexts);
+        assertTrue(millisElapsedSince(startTime) < LONG_DELAY_MS / 2);
+    }
+
+    /**
+     * Timed offer reports drops if saturated
+     */
+    public void testDroppedTimedOffer() {
+        SubmissionPublisher<Integer> p
+            = new SubmissionPublisher<>(basicExecutor, 4);
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        long delay = timeoutMillis();
+        for (int i = 1; i <= 4; ++i)
+            assertTrue(p.offer(i, delay, MILLISECONDS, null) >= 0);
+        long startTime = System.nanoTime();
+        assertTrue(p.offer(5, delay, MILLISECONDS, null) < 0);
+        s1.sn.request(64);
+        assertTrue(p.offer(6, delay, MILLISECONDS, null) < 0);
+        // 2 * delay should elapse but check only 1 * delay to allow timer slop
+        assertTrue(millisElapsedSince(startTime) >= delay);
+        s2.sn.request(64);
+        p.close();
+        s2.awaitComplete();
+        assertTrue(s2.nexts >= 2);
+        s1.awaitComplete();
+        assertTrue(s1.nexts >= 2);
+    }
+
+    /**
+     * Timed offer invokes drop handler if saturated
+     */
+    public void testHandledDroppedTimedOffer() {
+        AtomicInteger calls = new AtomicInteger();
+        SubmissionPublisher<Integer> p
+            = new SubmissionPublisher<>(basicExecutor, 4);
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        long delay = timeoutMillis();
+        for (int i = 1; i <= 4; ++i)
+            assertTrue(p.offer(i, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) >= 0);
+        long startTime = System.nanoTime();
+        assertTrue(p.offer(5, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) < 0);
+        s1.sn.request(64);
+        assertTrue(p.offer(6, delay, MILLISECONDS, (s, x) -> noopHandle(calls)) < 0);
+        assertTrue(millisElapsedSince(startTime) >= delay);
+        s2.sn.request(64);
+        p.close();
+        s2.awaitComplete();
+        s1.awaitComplete();
+        assertTrue(calls.get() >= 2);
+    }
+
+    /**
+     * Timed offer succeeds if drop handler forces request
+     */
+    public void testRecoveredHandledDroppedTimedOffer() {
+        AtomicInteger calls = new AtomicInteger();
+        SubmissionPublisher<Integer> p
+            = new SubmissionPublisher<>(basicExecutor, 4);
+        TestSubscriber s1 = new TestSubscriber();
+        s1.request = false;
+        TestSubscriber s2 = new TestSubscriber();
+        s2.request = false;
+        p.subscribe(s1);
+        p.subscribe(s2);
+        s2.awaitSubscribe();
+        s1.awaitSubscribe();
+        int n = 0;
+        long delay = timeoutMillis();
+        long startTime = System.nanoTime();
+        for (int i = 1; i <= 6; ++i) {
+            int d = p.offer(i, delay, MILLISECONDS, (s, x) -> reqHandle(calls, s));
+            n = n + 2 + (d < 0 ? d : 0);
+        }
+        assertTrue(millisElapsedSince(startTime) >= delay);
+        p.close();
+        s2.awaitComplete();
+        s1.awaitComplete();
+        assertEquals(n, s1.nexts + s2.nexts);
+        assertTrue(calls.get() >= 2);
+    }
+
+    /**
+     * consume returns a CompletableFuture that is done when
+     * publisher completes
+     */
+    public void testConsume() {
+        AtomicInteger sum = new AtomicInteger();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        CompletableFuture<Void> f =
+            p.consume((Integer x) -> sum.getAndAdd(x.intValue()));
+        int n = 20;
+        for (int i = 1; i <= n; ++i)
+            p.submit(i);
+        p.close();
+        f.join();
+        assertEquals((n * (n + 1)) / 2, sum.get());
+    }
+
+    /**
+     * consume(null) throws NPE
+     */
+    public void testConsumeNPE() {
+        SubmissionPublisher<Integer> p = basicPublisher();
+        try {
+            CompletableFuture<Void> f = p.consume(null);
+            shouldThrow();
+        } catch (NullPointerException success) {}
+    }
+
+    /**
+     * consume eventually stops processing published items if cancelled
+     */
+    public void testCancelledConsume() {
+        AtomicInteger count = new AtomicInteger();
+        SubmissionPublisher<Integer> p = basicPublisher();
+        CompletableFuture<Void> f = p.consume(x -> count.getAndIncrement());
+        f.cancel(true);
+        int n = 1000000; // arbitrary limit
+        for (int i = 1; i <= n; ++i)
+            p.submit(i);
+        assertTrue(count.get() < n);
+    }
+
+    /**
+     * Tests scenario for
+     * JDK-8187947: A race condition in SubmissionPublisher
+     * cvs update -D '2017-11-25' src/main/java/util/concurrent/SubmissionPublisher.java && ant -Djsr166.expensiveTests=true -Djsr166.tckTestClass=SubmissionPublisherTest -Djsr166.methodFilter=testMissedSignal tck; cvs update -A src/main/java/util/concurrent/SubmissionPublisher.java
+     */
+    public void testMissedSignal_8187947() throws Exception {
+        if (!atLeastJava9()) return; // backport to jdk8 too hard
+        final int N = expensiveTests ? (1 << 20) : (1 << 10);
+        final CountDownLatch finished = new CountDownLatch(1);
+        final SubmissionPublisher<Boolean> pub = new SubmissionPublisher<>();
+        class Sub implements Subscriber<Boolean> {
+            int received;
+            public void onSubscribe(Subscription s) {
+                s.request(N);
+            }
+            public void onNext(Boolean item) {
+                if (++received == N)
+                    finished.countDown();
+                else
+                    CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE));
+            }
+            public void onError(Throwable t) { throw new AssertionError(t); }
+            public void onComplete() {}
+        }
+        pub.subscribe(new Sub());
+        CompletableFuture.runAsync(() -> pub.submit(Boolean.TRUE));
+        await(finished);
+    }
+}
diff --git a/ojluni/src/test/java/util/concurrent/tck/SynchronousQueueTest.java b/ojluni/src/test/java/util/concurrent/tck/SynchronousQueueTest.java
index 5ff8ea2..ce4c1e5 100644
--- a/ojluni/src/test/java/util/concurrent/tck/SynchronousQueueTest.java
+++ b/ojluni/src/test/java/util/concurrent/tck/SynchronousQueueTest.java
@@ -451,7 +451,7 @@
     public void testToArray_null(boolean fair) {
         final SynchronousQueue q = new SynchronousQueue(fair);
         try {
-            Object[] o = q.toArray(null);
+            Object[] o = q.toArray((Object[])null);
             shouldThrow();
         } catch (NullPointerException success) {}
     }
diff --git a/ojluni/src/test/java/util/concurrent/tck/TimeUnit8Test.java b/ojluni/src/test/java/util/concurrent/tck/TimeUnit8Test.java
new file mode 100644
index 0000000..5cddf1c
--- /dev/null
+++ b/ojluni/src/test/java/util/concurrent/tck/TimeUnit8Test.java
@@ -0,0 +1,189 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz 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 test.java.util.concurrent.tck;
+import static java.util.concurrent.TimeUnit.DAYS;
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.LongStream;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class TimeUnit8Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+
+    public static Test suite() {
+        return new TestSuite(TimeUnit8Test.class);
+    }
+
+    /**
+     * tests for toChronoUnit.
+     */
+    public void testToChronoUnit() throws Exception {
+        assertSame(ChronoUnit.NANOS,   NANOSECONDS.toChronoUnit());
+        assertSame(ChronoUnit.MICROS,  MICROSECONDS.toChronoUnit());
+        assertSame(ChronoUnit.MILLIS,  MILLISECONDS.toChronoUnit());
+        assertSame(ChronoUnit.SECONDS, SECONDS.toChronoUnit());
+        assertSame(ChronoUnit.MINUTES, MINUTES.toChronoUnit());
+        assertSame(ChronoUnit.HOURS,   HOURS.toChronoUnit());
+        assertSame(ChronoUnit.DAYS,    DAYS.toChronoUnit());
+
+        // Every TimeUnit has a defined ChronoUnit equivalent
+        for (TimeUnit x : TimeUnit.values())
+            assertSame(x, TimeUnit.of(x.toChronoUnit()));
+    }
+
+    /**
+     * tests for TimeUnit.of(ChronoUnit).
+     */
+    public void testTimeUnitOf() throws Exception {
+        assertSame(NANOSECONDS,  TimeUnit.of(ChronoUnit.NANOS));
+        assertSame(MICROSECONDS, TimeUnit.of(ChronoUnit.MICROS));
+        assertSame(MILLISECONDS, TimeUnit.of(ChronoUnit.MILLIS));
+        assertSame(SECONDS,      TimeUnit.of(ChronoUnit.SECONDS));
+        assertSame(MINUTES,      TimeUnit.of(ChronoUnit.MINUTES));
+        assertSame(HOURS,        TimeUnit.of(ChronoUnit.HOURS));
+        assertSame(DAYS,         TimeUnit.of(ChronoUnit.DAYS));
+
+        assertThrows(NullPointerException.class,
+                     () -> TimeUnit.of((ChronoUnit)null));
+
+        // ChronoUnits either round trip to their TimeUnit
+        // equivalents, or throw IllegalArgumentException.
+        for (ChronoUnit cu : ChronoUnit.values()) {
+            final TimeUnit tu;
+            try {
+                tu = TimeUnit.of(cu);
+            } catch (IllegalArgumentException acceptable) {
+                continue;
+            }
+            assertSame(cu, tu.toChronoUnit());
+        }
+    }
+
+    /**
+     * convert(Duration) roundtrips with Duration.ofXXXX and Duration.of(long, ChronoUnit)
+     */
+    public void testConvertDuration_roundtripDurationOf() {
+        long n = ThreadLocalRandom.current().nextLong();
+
+        assertEquals(n, NANOSECONDS.convert(Duration.ofNanos(n)));
+        assertEquals(n, NANOSECONDS.convert(Duration.of(n, ChronoUnit.NANOS)));
+        assertEquals(n, MILLISECONDS.convert(Duration.ofMillis(n)));
+        assertEquals(n, MILLISECONDS.convert(Duration.of(n, ChronoUnit.MILLIS)));
+        assertEquals(n, SECONDS.convert(Duration.ofSeconds(n)));
+        assertEquals(n, SECONDS.convert(Duration.of(n, ChronoUnit.SECONDS)));
+        n /= 60;
+        assertEquals(n, MINUTES.convert(Duration.ofMinutes(n)));
+        assertEquals(n, MINUTES.convert(Duration.of(n, ChronoUnit.MINUTES)));
+        n /= 60;
+        assertEquals(n, HOURS.convert(Duration.ofHours(n)));
+        assertEquals(n, HOURS.convert(Duration.of(n, ChronoUnit.HOURS)));
+        n /= 24;
+        assertEquals(n, DAYS.convert(Duration.ofDays(n)));
+        assertEquals(n, DAYS.convert(Duration.of(n, ChronoUnit.DAYS)));
+    }
+
+    /**
+     * convert(Duration.ofNanos(n)) agrees with convert(n, NANOSECONDS)
+     */
+    public void testConvertDuration_roundtripDurationOfNanos() {
+        // Test values near unit transitions and near overflow.
+        LongStream.concat(
+                Arrays.stream(TimeUnit.values()).mapToLong(u -> u.toNanos(1)),
+                LongStream.of(Long.MAX_VALUE, Long.MIN_VALUE))
+            .flatMap(n -> LongStream.of(n, n + 1, n - 1))
+            .flatMap(n -> LongStream.of(n, n + 1_000_000_000, n - 1_000_000_000))
+            .flatMap(n -> LongStream.of(n, -n))
+            // .peek(System.err::println)
+            .forEach(n -> Arrays.stream(TimeUnit.values()).forEach(
+                u -> assertEquals(u.convert(n, NANOSECONDS),
+                                  u.convert(Duration.ofNanos(n)))));
+    }
+
+    /**
+     * convert(Duration) doesn't misbehave near Long.MAX_VALUE and Long.MIN_VALUE.
+     */
+    public void testConvertDuration_nearOverflow() {
+        ChronoUnit NANOS = ChronoUnit.NANOS;
+        Duration maxDuration = Duration.ofSeconds(Long.MAX_VALUE, 999_999_999);
+        Duration minDuration = Duration.ofSeconds(Long.MIN_VALUE, 0);
+
+        for (TimeUnit u : TimeUnit.values()) {
+            ChronoUnit cu = u.toChronoUnit();
+            long r;
+            if (u.toNanos(1) > SECONDS.toNanos(1)) {
+                r = u.toNanos(1) / SECONDS.toNanos(1);
+
+                assertThrows(ArithmeticException.class,
+                             () -> Duration.of(Long.MAX_VALUE, cu),
+                             () -> Duration.of(Long.MIN_VALUE, cu));
+            } else {
+                r = 1;
+
+                Duration max = Duration.of(Long.MAX_VALUE, cu);
+                Duration min = Duration.of(Long.MIN_VALUE, cu);
+                assertEquals(Long.MAX_VALUE, u.convert(max));
+                assertEquals(Long.MAX_VALUE - 1, u.convert(max.minus(1, NANOS)));
+                assertEquals(Long.MAX_VALUE - 1, u.convert(max.minus(1, cu)));
+                assertEquals(Long.MIN_VALUE, u.convert(min));
+                assertEquals(Long.MIN_VALUE + 1, u.convert(min.plus(1, NANOS)));
+                assertEquals(Long.MIN_VALUE + 1, u.convert(min.plus(1, cu)));
+                assertEquals(Long.MAX_VALUE, u.convert(max.plus(1, NANOS)));
+                if (u != SECONDS) {
+                    assertEquals(Long.MAX_VALUE, u.convert(max.plus(1, cu)));
+                    assertEquals(Long.MIN_VALUE, u.convert(min.minus(1, NANOS)));
+                    assertEquals(Long.MIN_VALUE, u.convert(min.minus(1, cu)));
+                }
+            }
+
+            assertEquals(Long.MAX_VALUE / r, u.convert(maxDuration));
+            assertEquals(Long.MIN_VALUE / r, u.convert(minDuration));
+        }
+    }
+
+}
diff --git a/ojluni/src/test/java/util/function/PredicateNotTest.java b/ojluni/src/test/java/util/function/PredicateNotTest.java
new file mode 100644
index 0000000..4c3ec25
--- /dev/null
+++ b/ojluni/src/test/java/util/function/PredicateNotTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8050818
+ * @run testng PredicateNotTest
+ */
+package test.java.util.function;
+
+// Android-added: workaround for d8 backports.
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import java.util.List;
+import java.util.function.Predicate;
+import org.testng.annotations.Test;
+
+import static java.util.stream.Collectors.joining;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class PredicateNotTest {
+    // BEGIN Android-added
+    // MethodHandle for invoking Predicate.not() to prevent d8 inserting it's backported
+    // `Predicate.not()` method (b/191859202, OpenJDK 11) and masking test coverage results.
+    static final MethodHandle NOT = initializeNot();
+
+    private static MethodHandle initializeNot()
+    {
+        try {
+            MethodType notType = MethodType.methodType(Predicate.class, Predicate.class);
+            return MethodHandles.lookup().findStatic(Predicate.class, "not", notType);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+
+    static <T> Predicate<T> not​(Predicate<? super T> target) {
+        try {
+            return (Predicate<T>) NOT.invoke(target);
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+    }
+    // END Android-added
+
+    static class IsEmptyPredicate implements Predicate<String> {
+        @Override
+        public boolean test(String s) {
+            return s.isEmpty();
+        }
+    }
+
+    @Test
+    public void test() {
+        List<String> test = List.of(
+           "A non-empty line",
+           "",
+           "A non-empty line",
+           "",
+           "A non-empty line",
+           "",
+           "A non-empty line",
+           ""
+        );
+        String expected = "A non-empty line\nA non-empty line\nA non-empty line\nA non-empty line";
+
+        assertEquals(test.stream().filter(not(String::isEmpty)).collect(joining("\n")), expected);
+        assertEquals(test.stream().filter(not(s -> s.isEmpty())).collect(joining("\n")), expected);
+        assertEquals(test.stream().filter(not(new IsEmptyPredicate())).collect(joining("\n")), expected);
+        assertEquals(test.stream().filter(not(not(not(String::isEmpty)))).collect(joining("\n")), expected);
+        assertEquals(test.stream().filter(not(not(not(s -> s.isEmpty())))).collect(joining("\n")), expected);
+        assertEquals(test.stream().filter(not(not(not(new IsEmptyPredicate())))).collect(joining("\n")), expected);
+    }
+}
+
diff --git a/ojluni/src/test/java/util/stream/Collectors/CollectorsTest.java b/ojluni/src/test/java/util/stream/Collectors/CollectorsTest.java
new file mode 100644
index 0000000..20e47a2
--- /dev/null
+++ b/ojluni/src/test/java/util/stream/Collectors/CollectorsTest.java
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.stream.Collectors;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.testng.annotations.Test;
+import org.openjdk.testlib.java.util.stream.LambdaTestHelpers;
+import org.openjdk.testlib.java.util.stream.StreamOpFlagTestHelper;
+import org.openjdk.testlib.java.util.stream.StreamTestDataProvider;
+import org.openjdk.testlib.java.util.stream.TestData;
+import org.openjdk.testlib.java.util.stream.OpTestCase;
+
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.flatMapping;
+import static java.util.stream.Collectors.filtering;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.groupingByConcurrent;
+import static java.util.stream.Collectors.mapping;
+import static java.util.stream.Collectors.partitioningBy;
+import static java.util.stream.Collectors.reducing;
+import static java.util.stream.Collectors.toCollection;
+import static java.util.stream.Collectors.toConcurrentMap;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toSet;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.assertContents;
+import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.assertContentsUnordered;
+import static org.openjdk.testlib.java.util.stream.LambdaTestHelpers.mDoubler;
+
+/*
+ * @test
+ * @bug 8071600 8144675
+ * @summary Test for collectors.
+ */
+public class CollectorsTest extends OpTestCase {
+
+    private abstract static class CollectorAssertion<T, U> {
+        abstract void assertValue(U value,
+                Supplier<Stream<T>> source,
+                boolean ordered) throws ReflectiveOperationException;
+    }
+
+    static class MappingAssertion<T, V, R> extends CollectorAssertion<T, R> {
+        private final Function<T, V> mapper;
+        private final CollectorAssertion<V, R> downstream;
+
+        MappingAssertion(Function<T, V> mapper, CollectorAssertion<V, R> downstream) {
+            this.mapper = mapper;
+            this.downstream = downstream;
+        }
+
+        @Override
+        void assertValue(R value, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
+            downstream.assertValue(value,
+                    () -> source.get().map(mapper::apply),
+                    ordered);
+        }
+    }
+
+    static class FlatMappingAssertion<T, V, R> extends CollectorAssertion<T, R> {
+        private final Function<T, Stream<V>> mapper;
+        private final CollectorAssertion<V, R> downstream;
+
+        FlatMappingAssertion(Function<T, Stream<V>> mapper,
+                CollectorAssertion<V, R> downstream) {
+            this.mapper = mapper;
+            this.downstream = downstream;
+        }
+
+        @Override
+        void assertValue(R value, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
+            downstream.assertValue(value,
+                    () -> source.get().flatMap(mapper::apply),
+                    ordered);
+        }
+    }
+
+    static class FilteringAssertion<T, R> extends CollectorAssertion<T, R> {
+        private final Predicate<T> filter;
+        private final CollectorAssertion<T, R> downstream;
+
+        public FilteringAssertion(Predicate<T> filter, CollectorAssertion<T, R> downstream) {
+            this.filter = filter;
+            this.downstream = downstream;
+        }
+
+        @Override
+        void assertValue(R value, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
+            downstream.assertValue(value,
+                    () -> source.get().filter(filter),
+                    ordered);
+        }
+    }
+
+    static class GroupingByAssertion<T, K, V, M extends Map<K, ? extends V>> extends CollectorAssertion<T, M> {
+        private final Class<? extends Map> clazz;
+        private final Function<T, K> classifier;
+        private final CollectorAssertion<T,V> downstream;
+
+        GroupingByAssertion(Function<T, K> classifier, Class<? extends Map> clazz,
+                CollectorAssertion<T, V> downstream) {
+            this.clazz = clazz;
+            this.classifier = classifier;
+            this.downstream = downstream;
+        }
+
+        @Override
+        void assertValue(M map,
+                Supplier<Stream<T>> source,
+                boolean ordered) throws ReflectiveOperationException {
+            if (!clazz.isAssignableFrom(map.getClass()))
+                fail(String.format("Class mismatch in GroupingByAssertion: %s, %s", clazz, map.getClass()));
+            assertContentsUnordered(map.keySet(), source.get().map(classifier).collect(toSet()));
+            for (Map.Entry<K, ? extends V> entry : map.entrySet()) {
+                K key = entry.getKey();
+                downstream.assertValue(entry.getValue(),
+                        () -> source.get().filter(e -> classifier.apply(e).equals(key)),
+                        ordered);
+            }
+        }
+    }
+
+    static class ToMapAssertion<T, K, V, M extends Map<K,V>> extends CollectorAssertion<T, M> {
+        private final Class<? extends Map> clazz;
+        private final Function<T, K> keyFn;
+        private final Function<T, V> valueFn;
+        private final BinaryOperator<V> mergeFn;
+
+        ToMapAssertion(Function<T, K> keyFn,
+                Function<T, V> valueFn,
+                BinaryOperator<V> mergeFn,
+                Class<? extends Map> clazz) {
+            this.clazz = clazz;
+            this.keyFn = keyFn;
+            this.valueFn = valueFn;
+            this.mergeFn = mergeFn;
+        }
+
+        @Override
+        void assertValue(M map, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
+            if (!clazz.isAssignableFrom(map.getClass()))
+                fail(String.format("Class mismatch in ToMapAssertion: %s, %s", clazz, map.getClass()));
+            Set<K> uniqueKeys = source.get().map(keyFn).collect(toSet());
+            assertEquals(uniqueKeys, map.keySet());
+            source.get().forEach(t -> {
+                K key = keyFn.apply(t);
+                V v = source.get()
+                        .filter(e -> key.equals(keyFn.apply(e)))
+                        .map(valueFn)
+                        .reduce(mergeFn)
+                        .get();
+                assertEquals(map.get(key), v);
+            });
+        }
+    }
+
+    static class PartitioningByAssertion<T, D> extends CollectorAssertion<T, Map<Boolean,D>> {
+        private final Predicate<T> predicate;
+        private final CollectorAssertion<T,D> downstream;
+
+        PartitioningByAssertion(Predicate<T> predicate, CollectorAssertion<T, D> downstream) {
+            this.predicate = predicate;
+            this.downstream = downstream;
+        }
+
+        @Override
+        void assertValue(Map<Boolean, D> map,
+                Supplier<Stream<T>> source,
+                boolean ordered) throws ReflectiveOperationException {
+            if (!Map.class.isAssignableFrom(map.getClass()))
+                fail(String.format("Class mismatch in PartitioningByAssertion: %s", map.getClass()));
+            assertEquals(2, map.size());
+            downstream.assertValue(map.get(true), () -> source.get().filter(predicate), ordered);
+            downstream.assertValue(map.get(false), () -> source.get().filter(predicate.negate()), ordered);
+        }
+    }
+
+    static class ToListAssertion<T> extends CollectorAssertion<T, List<T>> {
+        @Override
+        void assertValue(List<T> value, Supplier<Stream<T>> source, boolean ordered)
+                throws ReflectiveOperationException {
+            if (!List.class.isAssignableFrom(value.getClass()))
+                fail(String.format("Class mismatch in ToListAssertion: %s", value.getClass()));
+            Stream<T> stream = source.get();
+            List<T> result = new ArrayList<>();
+            for (Iterator<T> it = stream.iterator(); it.hasNext(); ) // avoid capturing result::add
+                result.add(it.next());
+            if (StreamOpFlagTestHelper.isStreamOrdered(stream) && ordered)
+                assertContents(value, result);
+            else
+                assertContentsUnordered(value, result);
+        }
+    }
+
+    static class ToCollectionAssertion<T> extends CollectorAssertion<T, Collection<T>> {
+        private final Class<? extends Collection> clazz;
+        private final boolean targetOrdered;
+
+        ToCollectionAssertion(Class<? extends Collection> clazz, boolean targetOrdered) {
+            this.clazz = clazz;
+            this.targetOrdered = targetOrdered;
+        }
+
+        @Override
+        void assertValue(Collection<T> value, Supplier<Stream<T>> source, boolean ordered)
+                throws ReflectiveOperationException {
+            if (!clazz.isAssignableFrom(value.getClass()))
+                fail(String.format("Class mismatch in ToCollectionAssertion: %s, %s", clazz, value.getClass()));
+            Stream<T> stream = source.get();
+            Collection<T> result = clazz.newInstance();
+            for (Iterator<T> it = stream.iterator(); it.hasNext(); ) // avoid capturing result::add
+                result.add(it.next());
+            if (StreamOpFlagTestHelper.isStreamOrdered(stream) && targetOrdered && ordered)
+                assertContents(value, result);
+            else
+                assertContentsUnordered(value, result);
+        }
+    }
+
+    static class ReducingAssertion<T, U> extends CollectorAssertion<T, U> {
+        private final U identity;
+        private final Function<T, U> mapper;
+        private final BinaryOperator<U> reducer;
+
+        ReducingAssertion(U identity, Function<T, U> mapper, BinaryOperator<U> reducer) {
+            this.identity = identity;
+            this.mapper = mapper;
+            this.reducer = reducer;
+        }
+
+        @Override
+        void assertValue(U value, Supplier<Stream<T>> source, boolean ordered)
+                throws ReflectiveOperationException {
+            Optional<U> reduced = source.get().map(mapper).reduce(reducer);
+            if (value == null)
+                assertTrue(!reduced.isPresent());
+            else if (!reduced.isPresent()) {
+                assertEquals(value, identity);
+            }
+            else {
+                assertEquals(value, reduced.get());
+            }
+        }
+    }
+
+    private <T> ResultAsserter<T> mapTabulationAsserter(boolean ordered) {
+        return (act, exp, ord, par) -> {
+            if (par && (!ordered || !ord)) {
+                CollectorsTest.nestedMapEqualityAssertion(act, exp);
+            }
+            else {
+                LambdaTestHelpers.assertContentsEqual(act, exp);
+            }
+        };
+    }
+
+    private<T, M extends Map>
+    void exerciseMapCollection(TestData<T, Stream<T>> data,
+            Collector<T, ?, ? extends M> collector,
+            CollectorAssertion<T, M> assertion)
+            throws ReflectiveOperationException {
+        boolean ordered = !collector.characteristics().contains(Collector.Characteristics.UNORDERED);
+
+        M m = withData(data)
+                .terminal(s -> s.collect(collector))
+                .resultAsserter(mapTabulationAsserter(ordered))
+                .exercise();
+        assertion.assertValue(m, () -> data.stream(), ordered);
+
+        m = withData(data)
+                .terminal(s -> s.unordered().collect(collector))
+                .resultAsserter(mapTabulationAsserter(ordered))
+                .exercise();
+        assertion.assertValue(m, () -> data.stream(), false);
+    }
+
+    private static void nestedMapEqualityAssertion(Object o1, Object o2) {
+        if (o1 instanceof Map) {
+            Map m1 = (Map) o1;
+            Map m2 = (Map) o2;
+            assertContentsUnordered(m1.keySet(), m2.keySet());
+            for (Object k : m1.keySet())
+                nestedMapEqualityAssertion(m1.get(k), m2.get(k));
+        }
+        else if (o1 instanceof Collection) {
+            assertContentsUnordered(((Collection) o1), ((Collection) o2));
+        }
+        else
+            assertEquals(o1, o2);
+    }
+
+    private<T, R> void assertCollect(TestData.OfRef<T> data,
+            Collector<T, ?, R> collector,
+            Function<Stream<T>, R> streamReduction) {
+        R check = streamReduction.apply(data.stream());
+        withData(data).terminal(s -> s.collect(collector)).expectedResult(check).exercise();
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testReducing(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        assertCollect(data, Collectors.reducing(0, Integer::sum),
+                s -> s.reduce(0, Integer::sum));
+        assertCollect(data, Collectors.reducing(Integer.MAX_VALUE, Integer::min),
+                s -> s.min(Integer::compare).orElse(Integer.MAX_VALUE));
+        assertCollect(data, Collectors.reducing(Integer.MIN_VALUE, Integer::max),
+                s -> s.max(Integer::compare).orElse(Integer.MIN_VALUE));
+
+        assertCollect(data, Collectors.reducing(Integer::sum),
+                s -> s.reduce(Integer::sum));
+        assertCollect(data, Collectors.minBy(Comparator.naturalOrder()),
+                s -> s.min(Integer::compare));
+        assertCollect(data, Collectors.maxBy(Comparator.naturalOrder()),
+                s -> s.max(Integer::compare));
+
+        assertCollect(data, Collectors.reducing(0, x -> x*2, Integer::sum),
+                s -> s.map(x -> x*2).reduce(0, Integer::sum));
+
+        assertCollect(data, Collectors.summingLong(x -> x * 2L),
+                s -> s.map(x -> x*2L).reduce(0L, Long::sum));
+        assertCollect(data, Collectors.summingInt(x -> x * 2),
+                s -> s.map(x -> x*2).reduce(0, Integer::sum));
+        assertCollect(data, Collectors.summingDouble(x -> x * 2.0d),
+                s -> s.map(x -> x * 2.0d).reduce(0.0d, Double::sum));
+
+        assertCollect(data, Collectors.averagingInt(x -> x * 2),
+                s -> s.mapToInt(x -> x * 2).average().orElse(0));
+        assertCollect(data, Collectors.averagingLong(x -> x * 2),
+                s -> s.mapToLong(x -> x * 2).average().orElse(0));
+        assertCollect(data, Collectors.averagingDouble(x -> x * 2),
+                s -> s.mapToDouble(x -> x * 2).average().orElse(0));
+
+        // Test explicit Collector.of
+        Collector<Integer, long[], Double> avg2xint = Collector.of(() -> new long[2],
+                (a, b) -> {
+                    a[0] += b * 2;
+                    a[1]++;
+                },
+                (a, b) -> {
+                    a[0] += b[0];
+                    a[1] += b[1];
+                    return a;
+                },
+                a -> a[1] == 0 ? 0.0d : (double) a[0] / a[1]);
+        assertCollect(data, avg2xint,
+                s -> s.mapToInt(x -> x * 2).average().orElse(0));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testJoining(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        withData(data)
+                .terminal(s -> s.map(Object::toString).collect(Collectors.joining()))
+                .expectedResult(join(data, ""))
+                .exercise();
+
+        Collector<String, StringBuilder, String> likeJoining = Collector.of(StringBuilder::new, StringBuilder::append, (sb1, sb2) -> sb1.append(sb2.toString()), StringBuilder::toString);
+        withData(data)
+                .terminal(s -> s.map(Object::toString).collect(likeJoining))
+                .expectedResult(join(data, ""))
+                .exercise();
+
+        withData(data)
+                .terminal(s -> s.map(Object::toString).collect(Collectors.joining(",")))
+                .expectedResult(join(data, ","))
+                .exercise();
+
+        withData(data)
+                .terminal(s -> s.map(Object::toString).collect(Collectors.joining(",", "[", "]")))
+                .expectedResult("[" + join(data, ",") + "]")
+                .exercise();
+
+        withData(data)
+                .terminal(s -> s.map(Object::toString)
+                        .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
+                        .toString())
+                .expectedResult(join(data, ""))
+                .exercise();
+
+        withData(data)
+                .terminal(s -> s.map(Object::toString)
+                        .collect(() -> new StringJoiner(","),
+                                (sj, cs) -> sj.add(cs),
+                                (j1, j2) -> j1.merge(j2))
+                        .toString())
+                .expectedResult(join(data, ","))
+                .exercise();
+
+        withData(data)
+                .terminal(s -> s.map(Object::toString)
+                        .collect(() -> new StringJoiner(",", "[", "]"),
+                                (sj, cs) -> sj.add(cs),
+                                (j1, j2) -> j1.merge(j2))
+                        .toString())
+                .expectedResult("[" + join(data, ",") + "]")
+                .exercise();
+    }
+
+    private<T> String join(TestData.OfRef<T> data, String delim) {
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (T i : data) {
+            if (!first)
+                sb.append(delim);
+            sb.append(i.toString());
+            first = false;
+        }
+        return sb.toString();
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testSimpleToMap(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Function<Integer, Integer> keyFn = i -> i * 2;
+        Function<Integer, Integer> valueFn = i -> i * 4;
+
+        List<Integer> dataAsList = Arrays.asList(data.stream().toArray(Integer[]::new));
+        Set<Integer> dataAsSet = new HashSet<>(dataAsList);
+
+        BinaryOperator<Integer> sum = Integer::sum;
+        for (BinaryOperator<Integer> op : Arrays.asList((u, v) -> u,
+                (u, v) -> v,
+                sum)) {
+            try {
+                exerciseMapCollection(data, toMap(keyFn, valueFn),
+                        new ToMapAssertion<>(keyFn, valueFn, op, HashMap.class));
+                if (dataAsList.size() != dataAsSet.size())
+                    fail("Expected ISE on input with duplicates");
+            }
+            catch (IllegalStateException e) {
+                if (dataAsList.size() == dataAsSet.size())
+                    fail("Expected no ISE on input without duplicates");
+            }
+
+            exerciseMapCollection(data, toMap(keyFn, valueFn, op),
+                    new ToMapAssertion<>(keyFn, valueFn, op, HashMap.class));
+
+            exerciseMapCollection(data, toMap(keyFn, valueFn, op, TreeMap::new),
+                    new ToMapAssertion<>(keyFn, valueFn, op, TreeMap.class));
+        }
+
+        // For concurrent maps, only use commutative merge functions
+        try {
+            exerciseMapCollection(data, toConcurrentMap(keyFn, valueFn),
+                    new ToMapAssertion<>(keyFn, valueFn, sum, ConcurrentHashMap.class));
+            if (dataAsList.size() != dataAsSet.size())
+                fail("Expected ISE on input with duplicates");
+        }
+        catch (IllegalStateException e) {
+            if (dataAsList.size() == dataAsSet.size())
+                fail("Expected no ISE on input without duplicates");
+        }
+
+        exerciseMapCollection(data, toConcurrentMap(keyFn, valueFn, sum),
+                new ToMapAssertion<>(keyFn, valueFn, sum, ConcurrentHashMap.class));
+
+        exerciseMapCollection(data, toConcurrentMap(keyFn, valueFn, sum, ConcurrentSkipListMap::new),
+                new ToMapAssertion<>(keyFn, valueFn, sum, ConcurrentSkipListMap.class));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testSimpleGroupingBy(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Function<Integer, Integer> classifier = i -> i % 3;
+
+        // Single-level groupBy
+        exerciseMapCollection(data, groupingBy(classifier),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new ToListAssertion<>()));
+        exerciseMapCollection(data, groupingByConcurrent(classifier),
+                new GroupingByAssertion<>(classifier, ConcurrentHashMap.class,
+                        new ToListAssertion<>()));
+
+        // With explicit constructors
+        exerciseMapCollection(data,
+                groupingBy(classifier, TreeMap::new, toCollection(HashSet::new)),
+                new GroupingByAssertion<>(classifier, TreeMap.class,
+                        new ToCollectionAssertion<Integer>(HashSet.class, false)));
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, ConcurrentSkipListMap::new,
+                        toCollection(HashSet::new)),
+                new GroupingByAssertion<>(classifier, ConcurrentSkipListMap.class,
+                        new ToCollectionAssertion<Integer>(HashSet.class, false)));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testGroupingByWithMapping(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Function<Integer, Integer> classifier = i -> i % 3;
+        Function<Integer, Integer> mapper = i -> i * 2;
+
+        exerciseMapCollection(data,
+                groupingBy(classifier, mapping(mapper, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new MappingAssertion<>(mapper,
+                                new ToListAssertion<>())));
+    }
+
+    @Test(groups = { "serialization-hostile" })
+    public void testFlatMappingClose() {
+        Function<Integer, Integer> classifier = i -> i;
+        AtomicInteger ai = new AtomicInteger();
+        Function<Integer, Stream<Integer>> flatMapper = i -> Stream.of(i, i).onClose(ai::getAndIncrement);
+        Map<Integer, List<Integer>> m = Stream.of(1, 2).collect(groupingBy(classifier, flatMapping(flatMapper, toList())));
+        assertEquals(m.size(), ai.get());
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testGroupingByWithFlatMapping(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Function<Integer, Integer> classifier = i -> i % 3;
+        Function<Integer, Stream<Integer>> flatMapperByNull = i -> null;
+        Function<Integer, Stream<Integer>> flatMapperBy0 = i -> Stream.empty();
+        Function<Integer, Stream<Integer>> flatMapperBy2 = i -> Stream.of(i, i);
+
+        exerciseMapCollection(data,
+                groupingBy(classifier, flatMapping(flatMapperByNull, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new FlatMappingAssertion<>(flatMapperBy0,
+                                new ToListAssertion<>())));
+        exerciseMapCollection(data,
+                groupingBy(classifier, flatMapping(flatMapperBy0, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new FlatMappingAssertion<>(flatMapperBy0,
+                                new ToListAssertion<>())));
+        exerciseMapCollection(data,
+                groupingBy(classifier, flatMapping(flatMapperBy2, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new FlatMappingAssertion<>(flatMapperBy2,
+                                new ToListAssertion<>())));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testGroupingByWithFiltering(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Function<Integer, Integer> classifier = i -> i % 3;
+        Predicate<Integer> filteringByMod2 = i -> i % 2 == 0;
+        Predicate<Integer> filteringByUnder100 = i -> i % 2 < 100;
+        Predicate<Integer> filteringByTrue = i -> true;
+        Predicate<Integer> filteringByFalse = i -> false;
+
+        exerciseMapCollection(data,
+                groupingBy(classifier, filtering(filteringByMod2, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new FilteringAssertion<>(filteringByMod2,
+                                new ToListAssertion<>())));
+        exerciseMapCollection(data,
+                groupingBy(classifier, filtering(filteringByUnder100, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new FilteringAssertion<>(filteringByUnder100,
+                                new ToListAssertion<>())));
+        exerciseMapCollection(data,
+                groupingBy(classifier, filtering(filteringByTrue, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new FilteringAssertion<>(filteringByTrue,
+                                new ToListAssertion<>())));
+        exerciseMapCollection(data,
+                groupingBy(classifier, filtering(filteringByFalse, toList())),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new FilteringAssertion<>(filteringByFalse,
+                                new ToListAssertion<>())));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testTwoLevelGroupingBy(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Function<Integer, Integer> classifier = i -> i % 6;
+        Function<Integer, Integer> classifier2 = i -> i % 23;
+
+        // Two-level groupBy
+        exerciseMapCollection(data,
+                groupingBy(classifier, groupingBy(classifier2)),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new GroupingByAssertion<>(classifier2, HashMap.class,
+                                new ToListAssertion<>())));
+        // with concurrent as upstream
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, groupingBy(classifier2)),
+                new GroupingByAssertion<>(classifier, ConcurrentHashMap.class,
+                        new GroupingByAssertion<>(classifier2, HashMap.class,
+                                new ToListAssertion<>())));
+        // with concurrent as downstream
+        exerciseMapCollection(data,
+                groupingBy(classifier, groupingByConcurrent(classifier2)),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new GroupingByAssertion<>(classifier2, ConcurrentHashMap.class,
+                                new ToListAssertion<>())));
+        // with concurrent as upstream and downstream
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, groupingByConcurrent(classifier2)),
+                new GroupingByAssertion<>(classifier, ConcurrentHashMap.class,
+                        new GroupingByAssertion<>(classifier2, ConcurrentHashMap.class,
+                                new ToListAssertion<>())));
+
+        // With explicit constructors
+        exerciseMapCollection(data,
+                groupingBy(classifier, TreeMap::new, groupingBy(classifier2, TreeMap::new, toCollection(HashSet::new))),
+                new GroupingByAssertion<>(classifier, TreeMap.class,
+                        new GroupingByAssertion<>(classifier2, TreeMap.class,
+                                new ToCollectionAssertion<Integer>(HashSet.class, false))));
+        // with concurrent as upstream
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, ConcurrentSkipListMap::new, groupingBy(classifier2, TreeMap::new, toList())),
+                new GroupingByAssertion<>(classifier, ConcurrentSkipListMap.class,
+                        new GroupingByAssertion<>(classifier2, TreeMap.class,
+                                new ToListAssertion<>())));
+        // with concurrent as downstream
+        exerciseMapCollection(data,
+                groupingBy(classifier, TreeMap::new, groupingByConcurrent(classifier2, ConcurrentSkipListMap::new, toList())),
+                new GroupingByAssertion<>(classifier, TreeMap.class,
+                        new GroupingByAssertion<>(classifier2, ConcurrentSkipListMap.class,
+                                new ToListAssertion<>())));
+        // with concurrent as upstream and downstream
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, ConcurrentSkipListMap::new, groupingByConcurrent(classifier2, ConcurrentSkipListMap::new, toList())),
+                new GroupingByAssertion<>(classifier, ConcurrentSkipListMap.class,
+                        new GroupingByAssertion<>(classifier2, ConcurrentSkipListMap.class,
+                                new ToListAssertion<>())));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testGroupubgByWithReducing(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Function<Integer, Integer> classifier = i -> i % 3;
+
+        // Single-level simple reduce
+        exerciseMapCollection(data,
+                groupingBy(classifier, reducing(0, Integer::sum)),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new ReducingAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum)));
+        // with concurrent
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, reducing(0, Integer::sum)),
+                new GroupingByAssertion<>(classifier, ConcurrentHashMap.class,
+                        new ReducingAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum)));
+
+        // With explicit constructors
+        exerciseMapCollection(data,
+                groupingBy(classifier, TreeMap::new, reducing(0, Integer::sum)),
+                new GroupingByAssertion<>(classifier, TreeMap.class,
+                        new ReducingAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum)));
+        // with concurrent
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, ConcurrentSkipListMap::new, reducing(0, Integer::sum)),
+                new GroupingByAssertion<>(classifier, ConcurrentSkipListMap.class,
+                        new ReducingAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum)));
+
+        // Single-level map-reduce
+        exerciseMapCollection(data,
+                groupingBy(classifier, reducing(0, mDoubler, Integer::sum)),
+                new GroupingByAssertion<>(classifier, HashMap.class,
+                        new ReducingAssertion<>(0, mDoubler, Integer::sum)));
+        // with concurrent
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, reducing(0, mDoubler, Integer::sum)),
+                new GroupingByAssertion<>(classifier, ConcurrentHashMap.class,
+                        new ReducingAssertion<>(0, mDoubler, Integer::sum)));
+
+        // With explicit constructors
+        exerciseMapCollection(data,
+                groupingBy(classifier, TreeMap::new, reducing(0, mDoubler, Integer::sum)),
+                new GroupingByAssertion<>(classifier, TreeMap.class,
+                        new ReducingAssertion<>(0, mDoubler, Integer::sum)));
+        // with concurrent
+        exerciseMapCollection(data,
+                groupingByConcurrent(classifier, ConcurrentSkipListMap::new, reducing(0, mDoubler, Integer::sum)),
+                new GroupingByAssertion<>(classifier, ConcurrentSkipListMap.class,
+                        new ReducingAssertion<>(0, mDoubler, Integer::sum)));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testSimplePartitioningBy(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Predicate<Integer> classifier = i -> i % 3 == 0;
+
+        // Single-level partition to downstream List
+        exerciseMapCollection(data,
+                partitioningBy(classifier),
+                new PartitioningByAssertion<>(classifier, new ToListAssertion<>()));
+        exerciseMapCollection(data,
+                partitioningBy(classifier, toList()),
+                new PartitioningByAssertion<>(classifier, new ToListAssertion<>()));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testTwoLevelPartitioningBy(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        Predicate<Integer> classifier = i -> i % 3 == 0;
+        Predicate<Integer> classifier2 = i -> i % 7 == 0;
+
+        // Two level partition
+        exerciseMapCollection(data,
+                partitioningBy(classifier, partitioningBy(classifier2)),
+                new PartitioningByAssertion<>(classifier,
+                        new PartitioningByAssertion(classifier2, new ToListAssertion<>())));
+
+        // Two level partition with reduce
+        exerciseMapCollection(data,
+                partitioningBy(classifier, reducing(0, Integer::sum)),
+                new PartitioningByAssertion<>(classifier,
+                        new ReducingAssertion<>(0, LambdaTestHelpers.identity(), Integer::sum)));
+    }
+
+    @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+    public void testComposeFinisher(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+        List<Integer> asList = exerciseTerminalOps(data, s -> s.collect(toList()));
+        List<Integer> asImmutableList = exerciseTerminalOps(data, s -> s.collect(collectingAndThen(toList(), Collections::unmodifiableList)));
+        assertEquals(asList, asImmutableList);
+        try {
+            asImmutableList.add(0);
+            fail("Expecting immutable result");
+        }
+        catch (UnsupportedOperationException ignored) { }
+    }
+
+}
\ No newline at end of file
diff --git a/ojluni/src/test/java/util/zip/ZipFile/Zip64SizeTest.java b/ojluni/src/test/java/util/zip/ZipFile/Zip64SizeTest.java
new file mode 100644
index 0000000..1185740
--- /dev/null
+++ b/ojluni/src/test/java/util/zip/ZipFile/Zip64SizeTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.java.util.zip.ZipFile;
+
+import java.nio.file.FileSystems;
+import java.nio.file.Paths;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import static org.testng.Assert.assertTrue;
+
+/**
+ * @test
+ * @bug 8226530
+ * @summary ZIP File System tests that leverage DirectoryStream
+ * @modules java.base
+ * @compile Zip64SizeTest.java
+ * @run testng Zip64SizeTest
+ */
+public class Zip64SizeTest {
+
+    // Android-changed: Speed up the test with a larger buffer
+    // private static final int BUFFER_SIZE = 2048;
+    private static final int BUFFER_SIZE = 1024 * 1024; // 1MB
+    // ZIP file to create
+    // Android-changed: Create file in a temp dir.
+    // private static final String ZIP_FILE_NAME = "Zip64SizeTest.zip";
+    private static final String TMPDIR = System.getProperty("java.io.tmpdir");
+    private static final String ZIP_FILE_NAME = Paths.get(TMPDIR, "Zip64SizeTest.zip").toString();
+    private static final String LARGE_FILE = Paths.get(TMPDIR, "LargeZipEntry.txt").toString();
+    private static final String SMALL_FILE = Paths.get(TMPDIR, "SmallZipEntry.txt").toString();
+    // File that will be created with a size greater than 0xFFFFFFFF
+    private static final String LARGE_FILE_NAME = "LargeZipEntry.txt";
+    // File that will be created with a size less than 0xFFFFFFFF
+    private static final String SMALL_FILE_NAME = "SmallZipEntry.txt";
+    // List of files to be added to the ZIP file
+    // Android-changed: Create file in a temp dir.
+    // private static final List<String> ZIP_ENTRIES = List.of(LARGE_FILE_NAME,
+    //         SMALL_FILE_NAME);
+    private static final List<String> ZIP_ENTRIES = List.of(LARGE_FILE, SMALL_FILE);
+    private static final long LARGE_FILE_SIZE = 5L * 1024L * 1024L * 1024L; // 5GB
+    private static final long SMALL_FILE_SIZE = 0x100000L; // 1024L x 1024L;
+
+    /**
+     * Validate that if the size of a ZIP entry exceeds 0xFFFFFFFF, that the
+     * correct size is returned from the ZIP64 Extended information.
+     * @throws IOException
+     */
+    // Android-changed: Disabled the test as it's long-running for CTS. http://b/227925195
+    // TODO: Enable this test on host or non-CTS device environment.
+    // @Test
+    // Android-changed: The test method needs to be public.
+    // private static void validateZipEntrySizes() throws IOException {
+    public void validateZipEntrySizes() throws IOException {
+        createFiles();
+        createZipFile();
+        System.out.println("Validating Zip Entry Sizes");
+        try (ZipFile zip = new ZipFile(ZIP_FILE_NAME)) {
+            ZipEntry ze = zip.getEntry(LARGE_FILE_NAME);
+            System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize());
+            assertTrue(ze.getSize() == LARGE_FILE_SIZE);
+            ze = zip.getEntry(SMALL_FILE_NAME);
+            System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize());
+            assertTrue(ze.getSize() == SMALL_FILE_SIZE);
+
+        }
+    }
+
+    /**
+     * Delete the files created for use by the test
+     * @throws IOException if an error occurs deleting the files
+     */
+    private static void deleteFiles() throws IOException {
+        // Android-changed: Path.of() isn't supported yet.
+        // Files.deleteIfExists(Path.of(ZIP_FILE_NAME));
+        // Files.deleteIfExists(Path.of(LARGE_FILE_NAME));
+        // Files.deleteIfExists(Path.of(SMALL_FILE_NAME));
+        Files.deleteIfExists(FileSystems.getDefault().getPath(ZIP_FILE_NAME));
+        Files.deleteIfExists(FileSystems.getDefault().getPath(LARGE_FILE));
+        Files.deleteIfExists(FileSystems.getDefault().getPath(SMALL_FILE));
+    }
+
+    /**
+     * Create the ZIP file adding an entry whose size exceeds 0xFFFFFFFF
+     * @throws IOException if an error occurs creating the ZIP File
+     */
+    private static void createZipFile() throws IOException {
+        try (FileOutputStream fos = new FileOutputStream(ZIP_FILE_NAME);
+             ZipOutputStream zos = new ZipOutputStream(fos)) {
+            System.out.printf("Creating Zip file: %s%n", ZIP_FILE_NAME);
+            for (String srcFile : ZIP_ENTRIES) {
+                System.out.printf("...Adding Entry: %s%n", srcFile);
+                File fileToZip = new File(srcFile);
+                try (FileInputStream fis = new FileInputStream(fileToZip)) {
+                    ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
+                    zipEntry.setSize(fileToZip.length());
+                    zos.putNextEntry(zipEntry);
+                    byte[] bytes = new byte[BUFFER_SIZE];
+                    int length;
+                    while ((length = fis.read(bytes)) >= 0) {
+                        zos.write(bytes, 0, length);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Create the files that will be added to the ZIP file
+     * @throws IOException if there is a problem  creating the files
+     */
+    private static void createFiles() throws IOException {
+        // Android-changed: Create file in a temp dir.
+        // try (RandomAccessFile largeFile = new RandomAccessFile(LARGE_FILE_NAME, "rw");
+        //     RandomAccessFile smallFile = new RandomAccessFile(SMALL_FILE_NAME, "rw")) {
+        try (RandomAccessFile largeFile = new RandomAccessFile(LARGE_FILE, "rw");
+             RandomAccessFile smallFile = new RandomAccessFile(SMALL_FILE, "rw")) {
+            System.out.printf("Creating %s%n", LARGE_FILE_NAME);
+            largeFile.setLength(LARGE_FILE_SIZE);
+            System.out.printf("Creating %s%n", SMALL_FILE_NAME);
+            smallFile.setLength(SMALL_FILE_SIZE);
+        }
+    }
+
+    /**
+     * Make sure the needed test files do not exist prior to executing the test
+     * @throws IOException
+     */
+    @BeforeMethod
+    public void setUp() throws IOException {
+        deleteFiles();
+    }
+
+    /**
+     * Remove the files created for the test
+     * @throws IOException
+     */
+    @AfterMethod
+    public void tearDown() throws IOException {
+        deleteFiles();
+    }
+}
\ No newline at end of file
diff --git a/ojluni/src/test/sun/invoke/util/WrapperTest.java b/ojluni/src/test/sun/invoke/util/WrapperTest.java
new file mode 100644
index 0000000..fdad209
--- /dev/null
+++ b/ojluni/src/test/sun/invoke/util/WrapperTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.sun.invoke.util;
+
+// Android-changed: Remove unused import.
+// import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MethodHandle;
+// Android-changed: Remove unused imports.
+// import java.io.Serializable;
+// import java.util.Arrays;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/* @test
+ * @summary unit tests to assert Wrapper zero identities and conversion behave correctly
+ * @modules java.base/sun.invoke.util
+ * @compile -XDignore.symbol.file WrapperTest.java
+ * @run junit test.sun.invoke.util.WrapperTest
+ */
+public class WrapperTest {
+
+    @Test
+    public void testShortZeroConversion() throws Throwable {
+        MethodHandle h1 = MethodHandles.constant(Short.class, (short)42);
+        MethodHandle h2 = h1.asType(MethodType.methodType(void.class));  // drop 42
+        MethodHandle h3 = h2.asType(MethodType.methodType(short.class));  // add 0
+        MethodHandle h4 = h3.asType(MethodType.methodType(Object.class));  // box
+
+        Object x = h4.invokeExact();
+        assertEquals(x, (short)0);
+        assertTrue(x == Short.valueOf((short)0));
+        assertTrue(x == Wrapper.SHORT.zero());
+    }
+
+    @Test
+    public void testIntZeroConversion() throws Throwable {
+        MethodHandle h1 = MethodHandles.constant(Integer.class, 42);
+        MethodHandle h2 = h1.asType(MethodType.methodType(void.class));  // drop 42
+        MethodHandle h3 = h2.asType(MethodType.methodType(int.class));  // add 0
+        MethodHandle h4 = h3.asType(MethodType.methodType(Object.class));  // box
+
+        Object x = h4.invokeExact();
+        assertEquals(x, 0);
+        assertTrue(x == Integer.valueOf(0));
+        assertTrue(x == Wrapper.INT.zero());
+    }
+
+    @Test
+    public void testLongZeroConversion() throws Throwable {
+        MethodHandle h1 = MethodHandles.constant(Long.class, 42L);
+        MethodHandle h2 = h1.asType(MethodType.methodType(void.class));  // drop 42
+        MethodHandle h3 = h2.asType(MethodType.methodType(long.class));  // add 0
+        MethodHandle h4 = h3.asType(MethodType.methodType(Object.class));  // box
+
+        Object x = h4.invokeExact();
+        assertEquals(x, 0L);
+        assertTrue(x == Long.valueOf(0));
+        assertTrue(x == Wrapper.LONG.zero());
+    }
+
+    @Test
+    public void testByteZeroConversion() throws Throwable {
+        MethodHandle h1 = MethodHandles.constant(Byte.class, (byte)42);
+        MethodHandle h2 = h1.asType(MethodType.methodType(void.class));  // drop 42
+        MethodHandle h3 = h2.asType(MethodType.methodType(byte.class));  // add 0
+        MethodHandle h4 = h3.asType(MethodType.methodType(Object.class));  // box
+
+        Object x = h4.invokeExact();
+        assertEquals(x, (byte)0);
+        assertTrue(x == Byte.valueOf((byte)0));
+        assertTrue(x == Wrapper.BYTE.zero());
+    }
+
+    @Test
+    public void testCharacterZeroConversion() throws Throwable {
+        MethodHandle h1 = MethodHandles.constant(Character.class, (char)42);
+        MethodHandle h2 = h1.asType(MethodType.methodType(void.class));  // drop 42
+        MethodHandle h3 = h2.asType(MethodType.methodType(char.class));  // add 0
+        MethodHandle h4 = h3.asType(MethodType.methodType(Object.class));  // box
+
+        Object x = h4.invokeExact();
+        assertEquals(x, (char)0);
+        assertTrue(x == Character.valueOf((char)0));
+        assertTrue(x == Wrapper.CHAR.zero());
+    }
+}
diff --git a/ojluni/src/tools/Android.bp b/ojluni/src/tools/Android.bp
new file mode 100644
index 0000000..b4a0bd7
--- /dev/null
+++ b/ojluni/src/tools/Android.bp
@@ -0,0 +1,9 @@
+package {
+    default_applicable_licenses: ["libcore_ojluni_license"],
+}
+
+java_binary_host {
+    name: "spp",
+    srcs: ["build/tools/spp/*.java"],
+    manifest: "build/tools/spp/MANIFEST.MF",
+}
diff --git a/ojluni/src/tools/build/tools/java.nio-generator/gen_java_nio.py b/ojluni/src/tools/build/tools/java.nio-generator/gen_java_nio.py
new file mode 100755
index 0000000..eec51c4
--- /dev/null
+++ b/ojluni/src/tools/build/tools/java.nio-generator/gen_java_nio.py
@@ -0,0 +1,249 @@
+#!/usr/bin/env python
+#
+# This code is derived from GensrcBuffer.gmk which carries the following copyright.
+#
+# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+"""
+Prints out the commands for generating the buffer classes in the java.nio package from templates.
+
+Run with "gen_java_nio.py <input directory> <output directory>"
+
+"""
+
+from enum import Enum, auto
+import math
+import os.path
+import argparse
+import sys
+
+PRIMITIVE_BYTE = "byte"
+PRIMITIVE_CHAR = "char"
+PRIMITIVE_SHORT = "short"
+PRIMITIVE_INT = "int"
+PRIMITIVE_LONG = "long"
+PRIMITIVE_FLOAT = "float"
+PRIMITIVE_DOUBLE = "double"
+
+PRIMITIVE_TO_BUFFER_PREFIX = {
+    PRIMITIVE_BYTE: "Byte",
+    PRIMITIVE_CHAR: "Char",
+    PRIMITIVE_SHORT: "Short",
+    PRIMITIVE_INT: "Int",
+    PRIMITIVE_LONG: "Long",
+    PRIMITIVE_FLOAT: "Float",
+    PRIMITIVE_DOUBLE: "Double",
+}
+
+PRIMITIVES = PRIMITIVE_TO_BUFFER_PREFIX.keys()
+
+PRIMITIVE_TO_REFERENCE_TYPE = {
+    PRIMITIVE_BYTE: "Byte",
+    PRIMITIVE_CHAR: "Character",
+    PRIMITIVE_SHORT: "Short",
+    PRIMITIVE_INT: "Integer",
+    PRIMITIVE_LONG: "Long",
+    PRIMITIVE_FLOAT: "Float",
+    PRIMITIVE_DOUBLE: "Double",
+}
+
+PRIMITIVE_TO_BYTES_PER_VALUE = {
+    PRIMITIVE_BYTE: 1,
+    PRIMITIVE_CHAR: 2,
+    PRIMITIVE_SHORT: 2,
+    PRIMITIVE_INT: 4,
+    PRIMITIVE_LONG: 8,
+    PRIMITIVE_FLOAT: 4,
+    PRIMITIVE_DOUBLE: 8,
+}
+
+BYTE_ORDER_DEFAULT = ""
+BYTE_ORDER_LITTLE_ENDIAN = "L"
+BYTE_ORDER_BIG_ENDIAN = "B"
+BYTE_ORDER_UNSWAPPED = "U"
+BYTE_ORDER_SWAPPED = "S"
+
+SPP = "java build.tools.spp.Spp "
+
+def generate_buffer(template_file, output_file, primitive_type,
+                    bin_ops="", read_only=False, byte_order=BYTE_ORDER_DEFAULT, append=" > "):
+    # fixRW
+    the_rw_key = "ro" if read_only else "rw"
+
+    # typesAndBits
+    the_a = "a"
+    the_A = "A"
+    the_x = primitive_type[0]
+    the_Type = primitive_type
+    the_type = the_Type.lower()
+    the_Fulltype = PRIMITIVE_TO_REFERENCE_TYPE[primitive_type.lower()]
+    the_fulltype = the_Fulltype.lower()
+    the_category = "integralType"
+    the_streams = ""
+    the_streamtype = ""
+    the_Streamtype = ""
+    the_BPV = PRIMITIVE_TO_BYTES_PER_VALUE[primitive_type.lower()]
+    the_LBPV = math.log2(the_BPV)
+    the_RW = "R" if read_only else ""
+
+    if primitive_type == PRIMITIVE_CHAR:
+        the_streams = "streamableType"
+        the_streamtype = "int"
+        the_Streamtype = "Int"
+    elif primitive_type == PRIMITIVE_INT:
+        the_a = "an"
+        the_A = "An"
+    elif primitive_type == PRIMITIVE_FLOAT or primitive_type == PRIMITIVE_DOUBLE:
+        the_category = "floatingPointType"
+
+    the_Swaptype = the_Type
+    the_memType = the_type
+    the_MemType = the_Type
+    the_fromBits = ""
+    the_toBits = ""
+    if primitive_type == PRIMITIVE_FLOAT:
+        the_fromBits = "Float.intBitsToFloat"
+        the_toBits = "Float.floatToRawIntBits"
+    elif primitive_type == PRIMITIVE_DOUBLE:
+        the_fromBits = "Double.longBitsToDouble"
+        the_toBits = "Double.doubleToRawLongBits"
+
+    the_swap = ""
+
+    command = SPP
+    command = command + " -K" + the_type
+    command = command + " -K" + the_category
+    command = command + " -K" + the_streams
+    command = command + " -Dtype=" + the_type
+    command = command + " -DType=" + the_Type
+    command = command + " -Dfulltype=" + the_fulltype
+    command = command + " -DFulltype=" + the_Fulltype
+    command = command + " -Dstreamtype=" + the_streamtype
+    command = command + " -DStreamtype=" + the_Streamtype
+    command = command + " -Dx=" + the_x
+    command = command + " -Dmemtype=" + the_memType
+    command = command + " -DMemtype=" + the_MemType
+    command = command + " -DSwaptype=" + the_Swaptype
+    command = command + " -DfromBits=" + the_fromBits
+    command = command + " -DtoBits=" + the_toBits
+    command = command + " -DLG_BYTES_PER_VALUE=" + str(the_LBPV)
+    command = command + " -DBYTES_PER_VALUE=" + str(the_BPV)
+    command = command + " -DBO=" + byte_order
+    command = command + " -Dswap=" + the_swap
+    command = command + " -DRW=" + the_RW
+    command = command + " -K" + the_rw_key
+    command = command + " -Da=" + the_a
+    command = command + " -DA=" + the_A
+    if (append == " >> "):
+        command = command + " -be"
+    if byte_order:
+        command = command + " -Kbo" + byte_order
+    command = command + " < " + template_file
+    command = command + append + output_file
+    print(command)
+
+    if bin_ops:
+        for primitive in PRIMITIVES:
+            if (primitive == PRIMITIVE_BYTE): continue
+            buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
+            generate_buffer(bin_ops, output_file, buffer_prefix, "", False, "", " >> ")
+
+
+
+def iterate_through_primitives(input_dir, output_dir, template_name, output_name, byte_order):
+    for primitive in PRIMITIVES:
+        if (primitive == PRIMITIVE_BYTE): continue
+        buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
+        template_file = os.path.join(input_dir, template_name)
+        output_file = os.path.join(output_dir, output_name + buffer_prefix + "Buffer" + byte_order + ".java")
+        output_file_r = os.path.join(output_dir, output_name + buffer_prefix + "BufferR" + byte_order + ".java")
+        generate_buffer(template_file, output_file, buffer_prefix, "", False, byte_order)
+        print("\n")
+        generate_buffer(template_file, output_file_r, buffer_prefix, "", True, byte_order)
+        print("\n")
+
+    # Generate X-Buffers
+def main():
+    parser = argparse.ArgumentParser(
+        description='Parse input and output directories')
+    parser.add_argument('input', help='Path to the directory that contains the template files')
+    parser.add_argument('output', help='Path to the directory where the output files should be placed')
+    args = parser.parse_args()
+
+    template_dir = args.input
+    output_dir = args.output
+    print("\nX-Buffer\n")
+
+    for primitive in PRIMITIVES:
+        bin_ops = os.path.join(template_dir, "X-Buffer-bin.java.template") if primitive == PRIMITIVE_BYTE else ""
+        buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
+        template_file = os.path.join(template_dir, "X-Buffer.java.template")
+        output_file = os.path.join(output_dir, buffer_prefix + "Buffer.java")
+        generate_buffer(template_file, output_file, buffer_prefix, bin_ops)
+        print("\n")
+
+    print("\nHeap-X-Buffer\n")
+
+    for primitive in PRIMITIVES:
+        buffer_prefix = PRIMITIVE_TO_BUFFER_PREFIX[primitive]
+        template_file = os.path.join(template_dir, "Heap-X-Buffer.java.template")
+        output_file = os.path.join(output_dir, "Heap" + buffer_prefix + "Buffer.java")
+        output_file_r = os.path.join(output_dir, "Heap" + buffer_prefix + "BufferR.java")
+        generate_buffer(template_file, output_file, buffer_prefix, "")
+        print("\n")
+        generate_buffer(template_file, output_file_r, buffer_prefix, "", True)
+        print("\n")
+
+    print("\nDirect-X-Buffer\n")
+
+    generate_buffer(os.path.join(template_dir, "Direct-X-Buffer.java.template"),
+        os.path.join(output_dir, "DirectByteBuffer.java"), "Byte",
+        os.path.join(template_dir, "Direct-X-Buffer-bin.java.template"))
+    print("\n")
+    generate_buffer(os.path.join(template_dir, "Direct-X-Buffer.java.template"),
+        os.path.join(output_dir, "DirectByteBufferR.java"), "Byte",
+        os.path.join(template_dir, "Direct-X-Buffer-bin.java.template"), True)
+    print("\n")
+
+    print("\nDirect-X-Buffer Unswapped\n")
+
+    iterate_through_primitives(template_dir, output_dir, "Direct-X-Buffer.java.template", "Direct", "U")
+
+    print("\nDirect-X-Buffer Swapped\n")
+
+    iterate_through_primitives(template_dir, output_dir, "Direct-X-Buffer.java.template", "Direct", "S")
+
+    print("\nByteBufferAs-X-Buffer BigEndian\n")
+
+    iterate_through_primitives(template_dir, output_dir, "ByteBufferAs-X-Buffer.java.template", "ByteBufferAs", "B")
+
+    print("\nByteBufferAs-X-Buffer LittleEndian\n")
+
+    iterate_through_primitives(template_dir, output_dir, "ByteBufferAs-X-Buffer.java.template", "ByteBufferAs", "L")
+
+    print("\nDONE\n")
+
+
+main()
\ No newline at end of file
diff --git a/ojluni/src/tools/build/tools/spp/MANIFEST.MF b/ojluni/src/tools/build/tools/spp/MANIFEST.MF
new file mode 100644
index 0000000..fbfeacc
--- /dev/null
+++ b/ojluni/src/tools/build/tools/spp/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0

+Main-Class: build.tools.spp.Spp

diff --git a/ojluni/src/tools/build/tools/spp/Spp.java b/ojluni/src/tools/build/tools/spp/Spp.java
new file mode 100644
index 0000000..9bbebe6
--- /dev/null
+++ b/ojluni/src/tools/build/tools/spp/Spp.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.spp;
+
+import java.util.*;
+import java.util.regex.*;
+
+/*
+ * Spp: A simple regex-based stream preprocessor based on Mark Reinhold's
+ *      sed-based spp.sh
+ *
+ * Usage: java build.tools.spp.Spp [-be] [-nel] [-Kkey] -Dvar=value ... <in >out
+ *
+ * If -nel is declared then empty lines will not be substituted for lines of
+ * text in the template that do not appear in the output.
+ *
+ *   Meaningful only at beginning of line, works with any number of keys:
+ *
+ *    #if[key]              Includes text between #if/#end if -Kkey specified,
+ *    #else[key]            otherwise changes text to blank lines; key test
+ *    #end[key]             may be negated by prefixing !, e.g., #if[!key]
+ *
+ *    #begin                If -be is specified then lines up to and including
+ *    #end                  #begin, and from #end to EOF, are deleted
+ *
+ *    #warn                 Changed into warning that file is generated
+ *
+ *    // ##                 Changed into blank line
+ *
+ *  Meaningful anywhere in line
+ *
+ *    {#if[key]?yes}        Expands to yes if -Kkey specified
+ *    {#if[key]?yes:no}     Expands to yes if -Kkey, otherwise no
+ *    {#if[!key]?yes}       Expands to yes if -Kother
+ *    {#if[!key]?yes:no}    Expands to yes if -Kother, otherwise no
+ *    $var$                 Expands to value if -Dvar=value given
+ *
+ *    yes, no must not contain whitespace
+ *
+ * @author Xueming Shen
+ */
+
+public class Spp {
+    public static void main(String args[]) throws Exception {
+        Map<String, String> vars = new HashMap<>();
+        Set<String> keys = new HashSet<>();
+        boolean be = false;
+        boolean el = true;
+
+        for (String arg:args) {
+            if (arg.startsWith("-D")) {
+                int i = arg.indexOf('=');
+                vars.put(arg.substring(2, i),arg.substring(i+1));
+            } else if (arg.startsWith("-K")) {
+                keys.add(arg.substring(2));
+            } else if ("-be".equals(arg)) {
+                be = true;
+            } else if ("-nel".equals(arg)) {
+                el = false;
+            } else {
+                System.err.println("Usage: java build.tools.spp.Spp [-be] [-nel] [-Kkey] -Dvar=value ... <in >out");
+                System.exit(-1);
+            }
+        }
+
+        StringBuffer out = new StringBuffer();
+        new Spp().spp(new Scanner(System.in),
+                      out, "",
+                      keys, vars, be, el,
+                      false);
+        System.out.print(out.toString());
+    }
+
+    static final String LNSEP = System.getProperty("line.separator");
+    static final String KEY = "([a-zA-Z0-9]+)";
+    static final String VAR = "([a-zA-Z0-9_\\-]+)";
+    static final String TEXT = "([a-zA-Z0-9&;,.<>/#() \\?\\[\\]\\$]+)"; // $ -- hack embedded $var$
+
+    static final int GN_NOT = 1;
+    static final int GN_KEY = 2;
+    static final int GN_YES = 3;
+    static final int GN_NO  = 5;
+    static final int GN_VAR = 6;
+
+    final Matcher   ifkey = Pattern.compile("^#if\\[(!)?" + KEY + "\\]").matcher("");
+    final Matcher elsekey = Pattern.compile("^#else\\[(!)?" + KEY + "\\]").matcher("");
+    final Matcher  endkey = Pattern.compile("^#end\\[(!)?" + KEY + "\\]").matcher("");
+    final Matcher  vardef = Pattern.compile("\\{#if\\[(!)?" + KEY + "\\]\\?" + TEXT + "(:"+ TEXT + ")?\\}|\\$" + VAR + "\\$").matcher("");
+    final Matcher vardef2 = Pattern.compile("\\$" + VAR + "\\$").matcher("");
+
+    void append(StringBuffer buf, String ln,
+                Set<String> keys, Map<String, String> vars) {
+        vardef.reset(ln);
+        while (vardef.find()) {
+            String repl = "";
+            if (vardef.group(GN_VAR) != null)
+                repl = vars.get(vardef.group(GN_VAR));
+            else {
+                boolean test = keys.contains(vardef.group(GN_KEY));
+                if (vardef.group(GN_NOT) != null)
+                    test = !test;
+                repl = test?vardef.group(GN_YES):vardef.group(GN_NO);
+                if (repl == null)
+                    repl = "";
+                else {  // embedded $var$
+                    while (vardef2.reset(repl).find()) {
+                        repl = vardef2.replaceFirst(vars.get(vardef2.group(1)));
+                    }
+                }
+            }
+            vardef.appendReplacement(buf, repl);
+        }
+        vardef.appendTail(buf);
+    }
+
+    // return true if #end[key], #end or EOF reached
+    boolean spp(Scanner in, StringBuffer buf, String key,
+                Set<String> keys, Map<String, String> vars,
+                boolean be, boolean el, boolean skip) {
+        while (in.hasNextLine()) {
+            String ln = in.nextLine();
+            if (be) {
+                if (ln.startsWith("#begin")) {
+                    buf.setLength(0);      //clean up to this line
+                    continue;
+                }
+                if (ln.equals("#end")) {
+                    while (in.hasNextLine())
+                        in.nextLine();
+                    return true;           //discard the rest to EOF
+                }
+            }
+            if (ifkey.reset(ln).find()) {
+                String k = ifkey.group(GN_KEY);
+                boolean test = keys.contains(k);
+                if (ifkey.group(GN_NOT) != null)
+                    test = !test;
+                if (el) buf.append(LNSEP);
+                if (!spp(in, buf, k, keys, vars, be, el, skip || !test)) {
+                    spp(in, buf, k, keys, vars, be, el, skip || test);
+                }
+                continue;
+            }
+            if (elsekey.reset(ln).find()) {
+                if (!key.equals(elsekey.group(GN_KEY))) {
+                    throw new Error("Mis-matched #if-else-end at line <" + ln + ">");
+                }
+                if (el) buf.append(LNSEP);
+                return false;
+            }
+            if (endkey.reset(ln).find()) {
+                if (!key.equals(endkey.group(GN_KEY))) {
+                    throw new Error("Mis-matched #if-else-end at line <" + ln + ">");
+                }
+                if (el) buf.append(LNSEP);
+                return true;
+            }
+            if (ln.startsWith("#warn")) {
+                ln = "// -- This file was mechanically generated: Do not edit! -- //";
+            } else if (ln.trim().startsWith("// ##")) {
+                ln = "";
+            }
+            if (!skip) {
+                append(buf, ln, keys, vars);
+                if (!el) buf.append(LNSEP);
+            }
+            if (el) buf.append(LNSEP);
+        }
+        return true;
+    }
+}
diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp
index a9f1dee..3f1005e 100644
--- a/openjdk_java_files.bp
+++ b/openjdk_java_files.bp
@@ -144,6 +144,7 @@
         "ojluni/src/main/java/java/lang/IllegalAccessError.java",
         "ojluni/src/main/java/java/lang/IllegalAccessException.java",
         "ojluni/src/main/java/java/lang/IllegalArgumentException.java",
+        "ojluni/src/main/java/java/lang/IllegalCallerException.java",
         "ojluni/src/main/java/java/lang/IllegalMonitorStateException.java",
         "ojluni/src/main/java/java/lang/IllegalStateException.java",
         "ojluni/src/main/java/java/lang/IllegalThreadStateException.java",
@@ -205,6 +206,7 @@
         "ojluni/src/main/java/java/lang/reflect/WeakCache.java",
         "ojluni/src/main/java/java/lang/reflect/WildcardType.java",
         "ojluni/src/main/java/java/lang/reflect/package-info.java",
+        "ojluni/src/main/java/java/lang/ref/Cleaner.java",
         "ojluni/src/main/java/java/lang/ref/PhantomReference.java",
         "ojluni/src/main/java/java/lang/ref/Reference.java",
         "ojluni/src/main/java/java/lang/ref/ReferenceQueue.java",
@@ -226,6 +228,7 @@
         "ojluni/src/main/java/java/lang/StringBuilder.java",
         "ojluni/src/main/java/java/lang/StringIndexOutOfBoundsException.java",
         "ojluni/src/main/java/java/lang/String.java",
+        "ojluni/src/main/java/java/lang/StringUTF16.java",
         "ojluni/src/main/java/java/lang/SuppressWarnings.java",
         "ojluni/src/main/java/java/lang/System.java",
         "ojluni/src/main/java/java/lang/ThreadDeath.java",
@@ -588,6 +591,7 @@
         "ojluni/src/main/java/java/security/cert/PolicyNode.java",
         "ojluni/src/main/java/java/security/cert/PolicyQualifierInfo.java",
         "ojluni/src/main/java/java/security/cert/TrustAnchor.java",
+        "ojluni/src/main/java/java/security/cert/URICertStoreParameters.java",
         "ojluni/src/main/java/java/security/cert/X509Certificate.java",
         "ojluni/src/main/java/java/security/cert/X509CertSelector.java",
         "ojluni/src/main/java/java/security/cert/X509CRLEntry.java",
@@ -616,11 +620,17 @@
         "ojluni/src/main/java/java/security/interfaces/ECKey.java",
         "ojluni/src/main/java/java/security/interfaces/ECPrivateKey.java",
         "ojluni/src/main/java/java/security/interfaces/ECPublicKey.java",
+        "ojluni/src/main/java/java/security/interfaces/EdECKey.java",
+        "ojluni/src/main/java/java/security/interfaces/EdECPrivateKey.java",
+        "ojluni/src/main/java/java/security/interfaces/EdECPublicKey.java",
         "ojluni/src/main/java/java/security/interfaces/RSAKey.java",
         "ojluni/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java",
         "ojluni/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java",
         "ojluni/src/main/java/java/security/interfaces/RSAPrivateKey.java",
         "ojluni/src/main/java/java/security/interfaces/RSAPublicKey.java",
+        "ojluni/src/main/java/java/security/interfaces/XECKey.java",
+        "ojluni/src/main/java/java/security/interfaces/XECPublicKey.java",
+        "ojluni/src/main/java/java/security/interfaces/XECPrivateKey.java",
         "ojluni/src/main/java/java/security/interfaces/package-info.java",
         "ojluni/src/main/java/java/security/InvalidAlgorithmParameterException.java",
         "ojluni/src/main/java/java/security/InvalidKeyException.java",
@@ -671,19 +681,23 @@
         "ojluni/src/main/java/java/security/spec/DSAPrivateKeySpec.java",
         "ojluni/src/main/java/java/security/spec/DSAPublicKeySpec.java",
         "ojluni/src/main/java/java/security/spec/ECFieldF2m.java",
-        "ojluni/src/main/java/java/security/spec/ECFieldFp.java",
         "ojluni/src/main/java/java/security/spec/ECField.java",
+        "ojluni/src/main/java/java/security/spec/ECFieldFp.java",
         "ojluni/src/main/java/java/security/spec/ECGenParameterSpec.java",
         "ojluni/src/main/java/java/security/spec/ECParameterSpec.java",
         "ojluni/src/main/java/java/security/spec/ECPoint.java",
         "ojluni/src/main/java/java/security/spec/ECPrivateKeySpec.java",
         "ojluni/src/main/java/java/security/spec/ECPublicKeySpec.java",
+        "ojluni/src/main/java/java/security/spec/EdECPoint.java",
+        "ojluni/src/main/java/java/security/spec/EdECPrivateKeySpec.java",
+        "ojluni/src/main/java/java/security/spec/EdECPublicKeySpec.java",
         "ojluni/src/main/java/java/security/spec/EllipticCurve.java",
         "ojluni/src/main/java/java/security/spec/EncodedKeySpec.java",
         "ojluni/src/main/java/java/security/spec/InvalidKeySpecException.java",
         "ojluni/src/main/java/java/security/spec/InvalidParameterSpecException.java",
         "ojluni/src/main/java/java/security/spec/KeySpec.java",
         "ojluni/src/main/java/java/security/spec/MGF1ParameterSpec.java",
+        "ojluni/src/main/java/java/security/spec/NamedParameterSpec.java",
         "ojluni/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java",
         "ojluni/src/main/java/java/security/spec/PSSParameterSpec.java",
         "ojluni/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java",
@@ -692,6 +706,8 @@
         "ojluni/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java",
         "ojluni/src/main/java/java/security/spec/RSAPrivateKeySpec.java",
         "ojluni/src/main/java/java/security/spec/RSAPublicKeySpec.java",
+        "ojluni/src/main/java/java/security/spec/XECPrivateKeySpec.java",
+        "ojluni/src/main/java/java/security/spec/XECPublicKeySpec.java",
         "ojluni/src/main/java/java/security/spec/X509EncodedKeySpec.java",
         "ojluni/src/main/java/java/security/spec/package-info.java",
         "ojluni/src/main/java/java/security/Timestamp.java",
@@ -979,6 +995,7 @@
         "ojluni/src/main/java/java/util/concurrent/ScheduledFuture.java",
         "ojluni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java",
         "ojluni/src/main/java/java/util/concurrent/Semaphore.java",
+        "ojluni/src/main/java/java/util/concurrent/SubmissionPublisher.java",
         "ojluni/src/main/java/java/util/concurrent/SynchronousQueue.java",
         "ojluni/src/main/java/java/util/concurrent/ThreadFactory.java",
         "ojluni/src/main/java/java/util/concurrent/ThreadLocalRandom.java",
@@ -1408,7 +1425,7 @@
 // sources, these API annotations can be placed in .annotated.java stub files
 // under ojluni/annotations/mmodule. Classes must be hidden using the
 // libcore.api.Hide annotation, and then the class and the members to be exposed
-// must be annotated with libcore.api.CorePlatformApi and/or
+// must be annotated with android.annotation.SystemApi and/or
 // libcore.api.IntraCoreApi.
 filegroup {
     name: "openjdk_mmodule_extra_files",
@@ -1444,13 +1461,27 @@
         "ojluni/src/main/java/java/util/ImmutableCollections.java",
         "ojluni/src/main/java/java/util/KeyValueHolder.java",
         "ojluni/src/main/java/java/util/JapaneseImperialCalendar.java",
-        "ojluni/src/main/java/sun/misc/FDBigInteger.java",
-        "ojluni/src/main/java/sun/misc/FloatingDecimal.java",
         "ojluni/src/main/java/jdk/net/ExtendedSocketOptions.java",
         "ojluni/src/main/java/jdk/net/NetworkPermission.java",
         "ojluni/src/main/java/jdk/net/SocketFlow.java",
         "ojluni/src/main/java/jdk/net/Sockets.java",
+        "ojluni/src/main/java/jdk/internal/HotSpotIntrinsicCandidate.java",
+        "ojluni/src/main/java/jdk/internal/misc/InnocuousThread.java",
+        "ojluni/src/main/java/jdk/internal/misc/JavaIOFileDescriptorAccess.java",
+        "ojluni/src/main/java/jdk/internal/misc/JavaObjectInputStreamAccess.java",
+        "ojluni/src/main/java/jdk/internal/misc/SharedSecrets.java",
+        "ojluni/src/main/java/jdk/internal/misc/Unsafe.java",
+        "ojluni/src/main/java/jdk/internal/misc/VM.java",
+        "ojluni/src/main/java/jdk/internal/ref/Cleaner.java",
+        "ojluni/src/main/java/jdk/internal/ref/CleanerFactory.java",
+        "ojluni/src/main/java/jdk/internal/ref/CleanerImpl.java",
+        "ojluni/src/main/java/jdk/internal/ref/PhantomCleanable.java",
+        "ojluni/src/main/java/jdk/internal/reflect/CallerSensitive.java",
+        "ojluni/src/main/java/jdk/internal/reflect/Reflection.java",
+        "ojluni/src/main/java/jdk/internal/vm/annotation/Contended.java",
+        "ojluni/src/main/java/jdk/internal/vm/annotation/ReservedStackAccess.java",
         "ojluni/src/main/java/jdk/internal/vm/annotation/Stable.java",
+        "ojluni/src/main/java/jdk/internal/util/ArraysSupport.java",
         "ojluni/src/main/java/jdk/internal/util/Preconditions.java",
         "ojluni/src/main/java/sun/invoke/util/BytecodeDescriptor.java",
         "ojluni/src/main/java/sun/invoke/util/Wrapper.java",
@@ -1463,10 +1494,7 @@
         "ojluni/src/main/java/sun/misc/CharacterDecoder.java",
         "ojluni/src/main/java/sun/misc/CharacterEncoder.java",
         "ojluni/src/main/java/sun/misc/CompoundEnumeration.java",
-        "ojluni/src/main/java/sun/misc/DoubleConsts.java",
         "ojluni/src/main/java/sun/misc/FileURLMapper.java",
-        "ojluni/src/main/java/sun/misc/FloatConsts.java",
-        "ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java",
         "ojluni/src/main/java/sun/misc/FpUtils.java",
         "ojluni/src/main/java/sun/misc/HexDumpEncoder.java",
         "ojluni/src/main/java/sun/misc/InvalidJarIndexException.java",
@@ -1487,6 +1515,7 @@
         "ojluni/src/main/java/sun/net/ApplicationProxy.java",
         "ojluni/src/main/java/sun/net/ConnectionResetException.java",
         "ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java",
+        "ojluni/src/main/java/sun/net/ext/ExtendedSocketOptions.java",
         "ojluni/src/main/java/sun/net/ftp/FtpClient.java",
         "ojluni/src/main/java/sun/net/ftp/FtpClientProvider.java",
         "ojluni/src/main/java/sun/net/ftp/FtpDirEntry.java",
@@ -1704,6 +1733,7 @@
         "ojluni/src/main/java/sun/security/util/DerOutputStream.java",
         "ojluni/src/main/java/sun/security/util/DerValue.java",
         "ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java",
+        "ojluni/src/main/java/sun/security/util/HexDumpEncoder.java",
         "ojluni/src/main/java/sun/security/util/KeyUtil.java",
         "ojluni/src/main/java/sun/security/util/Length.java",
         "ojluni/src/main/java/sun/security/util/ManifestDigester.java",
@@ -1814,6 +1844,11 @@
         "ojluni/src/main/java/sun/util/logging/PlatformLogger.java",
         "ojluni/src/main/java/sun/util/ResourceBundleEnumeration.java",
         "ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java",
+        "ojluni/src/main/java/jdk/internal/math/DoubleConsts.java",
+        "ojluni/src/main/java/jdk/internal/math/FDBigInteger.java",
+        "ojluni/src/main/java/jdk/internal/math/FloatConsts.java",
+        "ojluni/src/main/java/jdk/internal/math/FloatingDecimal.java",
+        "ojluni/src/main/java/jdk/internal/math/FormattedFloatingDecimal.java",
     ],
 }
 
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index 64392e4..df1a135 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.security.Provider;
 import java.security.Security;
 import java.security.spec.DSAPrivateKeySpec;
 import java.security.spec.DSAPublicKeySpec;
@@ -98,6 +99,15 @@
         assertTrue("Duplicate " + type + " " + algorithm,
                    algorithms.add(algorithm.toUpperCase(Locale.ROOT)));
     }
+    // Only add to PROVIDER_ALGORITHMS if actually present
+    private static void provideOptional(String type, String algorithm) {
+        for (Provider p : Security.getProviders()) {
+            if (p.getService(type, algorithm) != null) {
+                provide(type, algorithm);
+                return;
+            }
+        }
+    }
     private static void unprovide(String type, String algorithm) {
         Set<String> algorithms = PROVIDER_ALGORITHMS.get(type);
         assertNotNull(algorithms);
@@ -420,6 +430,7 @@
             provide("Signature", "SHA256withRSA/PSS");
             provide("Signature", "SHA384withRSA/PSS");
             provide("Signature", "SHA512withRSA/PSS");
+            provideOptional("Signature", "ED25519");
 
             // different names: ARCFOUR vs ARC4
             unprovide("Cipher", "ARCFOUR");
diff --git a/tools/docs/crypto/format_supported_algorithm_table.py b/tools/docs/crypto/format_supported_algorithm_table.py
index 1fc96065..599d752 100755
--- a/tools/docs/crypto/format_supported_algorithm_table.py
+++ b/tools/docs/crypto/format_supported_algorithm_table.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2017 The Android Open Source Project
 #
@@ -263,7 +263,7 @@
     if args.for_javadoc:
         for i in range(len(output)):
             output[i] = ' * ' + output[i]
-    print '\n'.join(output)
+    print('\n'.join(output))
 
 
 if __name__ == '__main__':
diff --git a/tools/docs/crypto/update_crypto_support.py b/tools/docs/crypto/update_crypto_support.py
index 83c4ec8..64fba8e 100755
--- a/tools/docs/crypto/update_crypto_support.py
+++ b/tools/docs/crypto/update_crypto_support.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2017 The Android Open Source Project
 #
@@ -273,8 +273,7 @@
             new_data, f, indent=2, sort_keys=True, separators=(',', ': '))
         f.close()
     else:
-        print json.dumps(
-            new_data, indent=2, sort_keys=True, separators=(',', ': '))
+        print(json.dumps(new_data, indent=2, sort_keys=True, separators=(',', ': ')))
 
 
 if __name__ == '__main__':
diff --git a/tools/docs/crypto/update_crypto_support_test.py b/tools/docs/crypto/update_crypto_support_test.py
index bf02438..7485cb5 100755
--- a/tools/docs/crypto/update_crypto_support_test.py
+++ b/tools/docs/crypto/update_crypto_support_test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2017 The Android Open Source Project
 #
@@ -14,8 +14,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from io import StringIO
+
 import datetime
-import StringIO
 import unittest
 import update_crypto_support
 
@@ -80,7 +81,7 @@
 
     def test_get_current_data(self):
         self.assertEqual(update_crypto_support.get_current_data(
-            StringIO.StringIO(
+            StringIO(
                 '''
                 BEGIN ALGORITHM LIST
                 Mac Bob
@@ -97,7 +98,7 @@
               'JONES': 'Jones',
               'JIM': 'Jim'}))
         self.assertEqual(update_crypto_support.get_current_data(
-            StringIO.StringIO(
+            StringIO(
                 '''
                 BEGIN ALGORITHM LIST
                 Mac Dupe
@@ -115,7 +116,7 @@
               'JONES': 'Jones',
               'JIM': 'Jim'}))
         self.assertEqual(update_crypto_support.get_current_data(
-            StringIO.StringIO(
+            StringIO(
                 '''
                 Mac NotAValue
                 BEGIN ALGORITHM LIST
@@ -134,7 +135,7 @@
               'JONES': 'Jones',
               'JIM': 'Jim'}))
         self.assertEqual(update_crypto_support.get_current_data(
-            StringIO.StringIO(
+            StringIO(
                 '''
                 BEGIN ALGORITHM LIST OF LISTS
                 Mac NotAValue
@@ -153,7 +154,7 @@
               'JONES': 'Jones',
               'JIM': 'Jim'}))
         with self.assertRaises(EOFError):
-            update_crypto_support.get_current_data(StringIO.StringIO(
+            update_crypto_support.get_current_data(StringIO(
                 '''
                 NOTBEGIN ALGORITHM LIST
                 Mac Bob
@@ -164,7 +165,7 @@
                 END ALGORITHM LIST
                 '''))
         with self.assertRaises(EOFError):
-            update_crypto_support.get_current_data(StringIO.StringIO(
+            update_crypto_support.get_current_data(StringIO(
                 '''
                 BEGIN ALGORITHM LIST
                 Mac Bob
@@ -173,7 +174,7 @@
                 Mac Amy
                 OtherThing Mary'''))
         with self.assertRaises(ValueError):
-            update_crypto_support.get_current_data(StringIO.StringIO(
+            update_crypto_support.get_current_data(StringIO(
                 '''
                 BEGIN ALGORITHM LIST
                 Mac Bob
@@ -184,7 +185,7 @@
                 END ALGORITHM LIST
                 '''))
         with self.assertRaises(ValueError):
-            update_crypto_support.get_current_data(StringIO.StringIO(
+            update_crypto_support.get_current_data(StringIO(
                 '''
                 BEGIN ALGORITHM LIST
                 Mac Bob
diff --git a/tools/expected_upstream/README.md b/tools/expected_upstream/README.md
new file mode 100644
index 0000000..a660fe9
--- /dev/null
+++ b/tools/expected_upstream/README.md
@@ -0,0 +1,229 @@
+If you want to import files from the OpenJDK into `libcore/`, you are reading
+the right documentation.
+
+The general idea is to get a change from OpenJDK into libcore in AOSP by
+`git merge` from an OpenJDK branch. However, each file in `ojluni/` can come
+from a different OpenJDK version. `expected_upstream` is a staging branch
+storing the OpenJDK version of each file. Thus, we can use `git merge` when
+we update an `ojluni/` file from a new upstream version, and the command should
+automatically merge the file if no merge conflict.
+
+# Directory Layout
+in the `aosp/expected_upstream` branch.
+1. `ojluni/`
+    * It has the same layout as the ojluni/ files in `aosp/master`
+2. `EXPECTED_UPSTREAM` file
+    * The table has 3 columns, i.e.
+        1. Destination path in `ojluni/`
+        2. Expected upstream version / an upstream git tag
+        3. Upstream source path
+    * The file format is like .csv file using a `,` separator
+3. `tools/expected_upstream/`
+    * Contains the tools
+
+# Understanding your change
+## Changes that shouldn't happen in the `aosp/expected_upstream` branch
+In general, if you want to change an `ojluni/` file by a text editor / IDE
+manually, you should make the change on `aosp/master`.
+
+1. Changes to non-OpenJDK files
+    * Those files are usually under the `luni/` folder, you can make the change
+      directly on `aosp/master`
+2. Adding / updating a patch to an existing `ojluni/` file
+    * You can make the change directly on `aosp/master`. Please follow this
+      [patch style guideline](https://goto.google.com/libcore-openjdk8-verify).
+3. Cherry-picking a commit from upstream
+    * You should first try to update an `ojluni/` file to a particular upstream
+      version. If you can't but still want to cherry-pick a upstream fix, you
+      should do so on the `aosp/master` branch.
+4. Changes to non-OpenJDK files in `ojluni/`
+    * Files, e.g. Android.bp, don't come from the upstream. You can make the
+      change directly on `aosp/master`.
+
+## Changes that should be made via the `aosp/expected_upstream` branch
+
+1. Add or upgrade a file from the upstream OpenJDK
+    * You are reading the right document! This documentation tells you how to
+      import the file from the upstream. Later, you can merge the file and
+      `expected_upstream` into `aosp/master` branch.
+2. Remove an `ojluni/` file that originally came from the OpenJDK
+    * Please remove the file on both `aosp/master` and `aosp/expected_upstream`
+      branches. Don't forget to remove the entry in the `EXPECTED_UPSTREAM` too.
+3. Revert the merge commit on `aosp/master` from `expected_upstream`
+    * If you don't plan to re-land your change on `aosp/master`, you should
+      probably revert the change `aosp/expected_upstream` as well.
+    * If you plan to re-land your change, your re-landing commit won't be
+      a merge commit, because `git` doesn't allow you to merge the same commit
+      twice into the same branch. You have 2 options
+        1. Revert your change on `expected_upsteam` too and start over again
+          when you reland your change
+        2. Just accept that the re-landing commit won't be a merge commit.
+
+## Life of a typical change
+
+Commit graph of a typical change
+```text
+----11.0.13-ga----------------   openjdk/jdk11u
+         \
+          A
+           \
+------------B-----C------------   expected_upstream
+                   \
+--------------------D---E------   master
+```
+
+Typically, you will need 5 CLs
+* Commit `A` imports the file and moves the file in the `ojluni/` folder
+* Commit `B` merges the file into the expected_upstream with other `ojluni`
+  files
+    * Commit `A` and `B` are created by the `ojluni_refresh_files` script
+* Commit `C` edits the entry in the `EXPECTED_UPSTREAM` file
+* Commit `D` is a merge commit created by `git merge`
+* Commit `E` adds Android patches
+    * Includes other changes to non-OpenJDK files, e.g. `Android.bp`,
+      `api/current.txt`.
+
+### Why can't have a single commit to replace the commits `A`, `B` and `C`?
+* Preserve the upstream history. We can later `git blame` with the upstream
+  history.
+
+# Tools
+
+## Prerequisite
+* python3
+* pip3
+* A remote `aosp` is setup in your local git repository
+
+## List of the scripts
+### tools/expected_upstream/install_tools.sh
+* Installs the dependency libraries
+* Installs the other tools into your current shell process
+
+### ojluni_modify_expectation
+* Command line tool that can help modify the EXPECTED_UPSTREAM file
+
+### ojluni_refresh_files
+* Reads the EXPECTED_UPSTREAM file and updates the files contents in ojluni/
+accordingly
+
+## Workflow in command lines
+### Setup
+1. Switch to the expected_upstream branch
+```shell
+git branch <local_branch> aosp/expected_upstream
+git checkout <local_branch>
+```
+
+2. Install tools
+```shell
+source ./tools/expected_upstream/install_tools.sh
+```
+## Upgrade a java class to a higher OpenJDK version
+For example, upgrade `java.lang.String` to 11.0.13-ga version:
+
+```shell
+ojluni_modify_expectation modify java.lang.String jdk11u/jdk-11.0.13-ga
+ojluni_refresh_files
+```
+
+or if `java.lang.String` is missing in EXPECTED_UPSTREAM:
+```shell
+ojluni_modify_expectation add jdk11u/jdk-11.0.13-ga java.lang.String
+ojluni_refresh_files
+```
+2 commits should be created to update the `ojluni/src/main/java/java/lang/String.java`.
+You can verify and view the diff by the following command
+
+```shell
+git diff aosp/expected_upstream -- ojluni/src/main/java/java/lang/String.java
+```
+
+You can then upload your change to AOSP gerrit.
+```shell
+repo upload --cbr -t . # -t sets a topic to the CLs in the gerrit
+```
+
+Remember to commit your EXPECTED_UPSTREAM file change into a new commit
+```shell
+git commit -- EXPECTED_UPSTREAM
+```
+
+Then upload your change to AOSP gerrit.
+```shell
+repo upload --cbr .
+```
+
+Then you can switch back to your local `master` branch to apply the changes
+```shell
+git checkout <local_master_branch>
+git merge local_expected_upstream
+# Resolve any merge conflict
+git commit --amend # Amend the commit message and add the bug number you are working on
+repo upload .
+```
+
+### Add a java test from the upstream
+
+The process is similar to the above commands, but needs to run
+`ojluni_modify_expectation` with an `add` subcommand.
+
+For example, add a test for `String.isEmpty()` method:
+```shell
+ojluni_modify_expectation add jdk8u/jdk8u121-b13 java.lang.String.IsEmpty
+```
+Note: `java.lang.String.IsEmpty` is a test class in the upstream repository.
+
+# Submit your change in [AOSP gerrit](http://r.android.com/)
+```text
+----11.0.13-ga----------------   openjdk/jdk11u
+         \
+          A
+           \
+------------B-----C------------   expected_upstream
+                   \
+--------------------D---E------   master
+```
+Here are the order of events / votes required to submit your CL on gerrit as of
+Nov 2021.
+1. `Presubmit-Verified +2` on all 5 CLs
+   * Due to [b/204973624](http://b/204973624), you may `Bypass-Presubmit +1`
+     on commit `A` and `B` if the presubmit fails.
+2. `Code-review +2` on all 5 CLs from an Android Core Library team member
+3. If needed, `API-review +1` on commit `E` from an Android API council member
+4. Click the submit button / `Autosubmit +1` on commit `B`, `C` and `E`
+    * Never submit commit `A` individually without submitting `B` together.
+        * Otherwise, gerrit will create another merge commit from `A` without
+          submitting `B`.
+    * Due a Gerrit bug, you can't submit the commit `C` before submitting `B`
+      first manually, even though `B` is the direct parent of `C`. So just
+      submit `B` yourself manually.
+    * If you can't submit the CL due a permission issue, ask an Android Core
+      Library member to submit.
+
+# Known bugs
+* `repo upload` may not succeed because gerrit returns error.
+    1. Just try to run `repo upload` again!
+        * The initial upload takes a long time because it tries to sync with the
+          remote AOSP gerrit server. The second upload is much faster because
+          the `git` objects have been uploaded.
+    2. `repo upload` returns TimeOutException, but the CL has been uploaded.
+       Just find your CL in http://r.android.com/. See http://b/202848945
+    3. Try to upload the merge commits 1 by 1
+    ```shell
+    git rev-parse HEAD # a sha is printed and you will need it later
+    git reset HEAD~1 # reset to a earlier commit
+    repo upload --cbr . # try to upload it again
+    git reset <the sha printed above>
+    ```
+* After `ojluni_modify_expectation add` and `ojluni_refresh_files`, a `git commit -a`
+  would include more files than just EXPECTED_UPSTREAM, because `git`, e.g. `git status`,
+  isn't aware of changes in the working tree / in the file system. This can lead to
+  an error when checking out the branch that is based on master.
+    1. Do a `git checkout --hard <initial commit before the add>`
+    2. Rerun the `ojluni_modify_expectation add` and `ojluni_refresh_files`
+    3. `git stash && git stash pop`
+    4. Commit the updated EXPECTED_UPSTREAM and proceed
+
+# Report bugs
+* Report bugs if the git repository is corrupt!
+    * Sometimes, you can recover the repository by running `git reset aosp/expected_upstream`
diff --git a/tools/expected_upstream/common_util.py b/tools/expected_upstream/common_util.py
new file mode 100644
index 0000000..4d431b9
--- /dev/null
+++ b/tools/expected_upstream/common_util.py
@@ -0,0 +1,364 @@
+# Copyright 2021 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.
+
+"""Common Utils."""
+
+# pylint: disable=g-importing-member
+from dataclasses import dataclass
+from pathlib import Path
+from pathlib import PurePath
+import sys
+from typing import List
+from typing import Set
+
+# pylint: disable=g-import-not-at-top
+try:
+  from git import Blob
+  from git import Commit
+  from git import Tree
+except ModuleNotFoundError:
+  print(
+      'ERROR: Please install GitPython by `pip3 install GitPython`.',
+      file=sys.stderr)
+  exit(1)
+
+THIS_DIR = Path(__file__).resolve().parent
+LIBCORE_DIR = THIS_DIR.parent.parent.resolve()
+
+UPSTREAM_CLASS_PATHS = [
+    'jdk/src/share/classes/',
+    'src/java.base/share/classes/',
+    'src/java.base/linux/classes/',
+    'src/java.base/unix/classes/',
+    'src/java.sql/share/classes/',
+    'src/java.logging/share/classes/',
+    'src/java.prefs/share/classes/',
+    'src/java.net/share/classes/',
+]
+
+UPSTREAM_TEST_PATHS = [
+    'jdk/test/',
+    'test/jdk/',
+]
+
+UPSTREAM_SEARCH_PATHS = UPSTREAM_CLASS_PATHS + UPSTREAM_TEST_PATHS
+
+OJLUNI_JAVA_BASE_PATH = 'ojluni/src/main/java/'
+OJLUNI_TEST_PATH = 'ojluni/src/'
+
+
+@dataclass
+class ExpectedUpstreamEntry:
+  """A map entry in the EXPECTED_UPSTREAM file."""
+  dst_path: str  # destination path
+  git_ref: str  # a git reference to an upstream commit
+  src_path: str  # source path in the commit pointed by the git_ref
+  comment_lines: str = ''  # The comment lines above the entry line
+
+
+class ExpectedUpstreamFile:
+  """A file object representing the EXPECTED_UPSTREAM file."""
+
+  def __init__(self, file_path: str = LIBCORE_DIR / 'EXPECTED_UPSTREAM'):
+    self.path = Path(file_path)
+
+  def read_all_entries(self) -> List[ExpectedUpstreamEntry]:
+    """Read all entries from the file."""
+    result: List[ExpectedUpstreamEntry] = []
+    with self.path.open() as file:
+      comment_lines = ''  # Store the comment lines in the next entry
+      for line in file:
+        stripped = line.strip()
+        # Ignore empty lines and comments starting with '#'
+        if not stripped or stripped.startswith('#'):
+          comment_lines += line
+          continue
+
+        entry = self.parse_line(stripped, comment_lines)
+        result.append(entry)
+        comment_lines = ''
+
+    return result
+
+  def write_all_entries(self, entries: List[ExpectedUpstreamEntry]) -> None:
+    """Write all entries into the file."""
+    with self.path.open('w') as file:
+      for e in entries:
+        file.write(e.comment_lines)
+        file.write(','.join([e.dst_path, e.git_ref, e.src_path]))
+        file.write('\n')
+
+  def write_new_entry(self, entry: ExpectedUpstreamEntry,
+                      entries: List[ExpectedUpstreamEntry] = None) -> None:
+    if entries is None:
+      entries = self.read_all_entries()
+
+    entries.append(entry)
+    self.sort_and_write_all_entries(entries)
+
+  def sort_and_write_all_entries(self,
+                                 entries: List[ExpectedUpstreamEntry]) -> None:
+    header = entries[0].comment_lines
+    entries[0].comment_lines = ''
+    entries.sort(key=lambda e: e.dst_path)
+    # Keep the header above the first entry
+    entries[0].comment_lines = header + entries[0].comment_lines
+    self.write_all_entries(entries)
+
+  @staticmethod
+  def parse_line(line: str, comment_lines: str) -> ExpectedUpstreamEntry:
+    items = line.split(',')
+    size = len(items)
+    if size != 3:
+      raise ValueError(
+          f"The size must be 3, but is {size}. The line is '{line}'")
+
+    return ExpectedUpstreamEntry(items[0], items[1], items[2], comment_lines)
+
+
+class OjluniFinder:
+  """Finder for java classes or ojluni/ paths."""
+
+  def __init__(self, existing_paths: List[str]):
+    self.existing_paths = existing_paths
+
+  @staticmethod
+  def translate_from_class_name_to_ojluni_path(class_or_path: str) -> str:
+    """Returns a ojluni path from a class name."""
+    # if it contains '/', then it's a path
+    if '/' in class_or_path:
+      return class_or_path
+
+    base_path = OJLUNI_TEST_PATH if class_or_path.startswith(
+        'test.') else OJLUNI_JAVA_BASE_PATH
+
+    relative_path = class_or_path.replace('.', '/')
+    return f'{base_path}{relative_path}.java'
+
+  def match_path_prefix(self, input_path: str) -> Set[str]:
+    """Returns a set of existing file paths matching the given partial path."""
+    path_matches = list(
+        filter(lambda path: path.startswith(input_path), self.existing_paths))
+    result_set: Set[str] = set()
+    # if it's found, just return the result
+    if input_path in path_matches:
+      result_set.add(input_path)
+    else:
+      input_ojluni_path = PurePath(input_path)
+      # the input ends with '/', the autocompletion result contain the children
+      # instead of the matching the prefix in its parent directory
+      input_path_parent_or_self = input_ojluni_path
+      if not input_path.endswith('/'):
+        input_path_parent_or_self = input_path_parent_or_self.parent
+      n_parts = len(input_path_parent_or_self.parts)
+      for match in path_matches:
+        path = PurePath(match)
+        # path.parts[n_parts] should not exceed the index and should be
+        # a valid child path because input_path_parent_or_self must be a
+        # valid directory
+        child = list(path.parts)[n_parts]
+        result = (input_path_parent_or_self / child).as_posix()
+        # if result is not exact, the result represents a directory.
+        if result != match:
+          result += '/'
+        result_set.add(result)
+
+    return result_set
+
+  def match_classname_prefix(self, input_class_name: str) -> List[str]:
+    """Returns a list of package / class names given the partial class name."""
+    # If '/' exists, it's probably a path, not a partial class name
+    if '/' in input_class_name:
+      return []
+
+    result_list = []
+    partial_relative_path = input_class_name.replace('.', '/')
+    for base_path in [OJLUNI_JAVA_BASE_PATH, OJLUNI_TEST_PATH]:
+      partial_ojluni_path = base_path + partial_relative_path
+      result_paths = self.match_path_prefix(partial_ojluni_path)
+      # pylint: disable=cell-var-from-loop
+      result_list.extend(
+          map(lambda path: convert_path_to_java_class_name(path, base_path),
+              list(result_paths)))
+
+    return result_list
+
+
+class OpenjdkFinder:
+  """Finder for java classes or paths in a upstream OpenJDK commit."""
+
+  def __init__(self, commit: Commit):
+    self.commit = commit
+
+  @staticmethod
+  def translate_src_path_to_ojluni_path(src_path: str) -> str:
+    """Returns None if src_path isn't in a known source directory."""
+    relative_path = None
+    for base_path in UPSTREAM_TEST_PATHS:
+      if src_path.startswith(base_path):
+        length = len(base_path)
+        relative_path = src_path[length:]
+        break
+
+    if relative_path:
+      return f'{OJLUNI_TEST_PATH}test/{relative_path}'
+
+    for base_path in UPSTREAM_CLASS_PATHS:
+      if src_path.startswith(base_path):
+        length = len(base_path)
+        relative_path = src_path[length:]
+        break
+
+    if relative_path:
+      return f'{OJLUNI_JAVA_BASE_PATH}{relative_path}'
+
+    return None
+
+  def find_src_path_from_classname(self, class_or_path: str) -> str:
+    """Finds a valid source path given a valid class name or path."""
+    # if it contains '/', then it's a path
+    if '/' in class_or_path:
+      if self.has_file(class_or_path):
+        return class_or_path
+      else:
+        return None
+
+    relative_path = class_or_path.replace('.', '/')
+    src_path = None
+    for base_path in UPSTREAM_SEARCH_PATHS:
+      full_path = f'{base_path}{relative_path}.java'
+      if self.has_file(full_path):
+        src_path = full_path
+        break
+
+    return src_path
+
+  def get_search_paths(self) -> List[str]:
+    return UPSTREAM_SEARCH_PATHS
+
+  def find_src_path_from_ojluni_path(self, ojluni_path: str) -> str:
+    """Returns a source path that guessed from the ojluni_path."""
+    base_paths = None
+    relative_path = None
+
+    TEST_PATH = OJLUNI_TEST_PATH + 'test/'
+    if ojluni_path.startswith(OJLUNI_JAVA_BASE_PATH):
+      base_paths = UPSTREAM_CLASS_PATHS
+      length = len(OJLUNI_JAVA_BASE_PATH)
+      relative_path = ojluni_path[length:]
+    elif ojluni_path.startswith(TEST_PATH):
+      base_paths = UPSTREAM_TEST_PATHS
+      length = len(TEST_PATH)
+      relative_path = ojluni_path[length:]
+    else:
+      return None
+
+    for base_path in base_paths:
+      full_path = base_path + relative_path
+      if self.has_file(full_path):
+        return full_path
+
+    return None
+
+  def match_path_prefix(self, input_path: str) -> List[str]:
+    """Returns a list of source paths matching the given partial string."""
+    result_list = []
+
+    search_tree = self.commit.tree
+    path_obj = PurePath(input_path)
+    is_exact = self.has_file(path_obj.as_posix())
+    is_directory_path = input_path.endswith('/')
+    exact_obj = search_tree[path_obj.as_posix()] if is_exact else None
+    search_word = ''
+    if is_exact and isinstance(exact_obj, Blob):
+      # an exact file path
+      result_list.append(input_path)
+      return result_list
+    elif is_directory_path:
+      # an exact directory path and can't be a prefix directory name.
+      if is_exact:
+        search_tree = exact_obj
+      else:
+        # Such path doesn't exist, and thus returns empty list
+        return result_list
+    elif len(path_obj.parts) >= 2 and not is_directory_path:
+      parent_path = path_obj.parent.as_posix()
+      if self.has_file(parent_path):
+        search_tree = search_tree[parent_path]
+        search_word = path_obj.name
+      else:
+        # Return empty list because no such path is found
+        return result_list
+    else:
+      search_word = input_path
+
+    for tree in search_tree.trees:
+      tree_path = PurePath(tree.path)
+      if tree_path.name.startswith(search_word):
+        # Append '/' to indicate directory type. If the result has this item
+        # only, shell should auto-fill the input, and thus
+        # next tabbing in shell should fall into the above condition
+        # `is_exact and input_path.endswith('/')` and will search in the child
+        # tree.
+        result_path = tree.path + '/'
+        result_list.append(result_path)
+
+    for blob in search_tree.blobs:
+      blob_path = PurePath(blob.path)
+      if blob_path.name.startswith(search_word):
+        result_list.append(blob.path)
+
+    return result_list
+
+  def match_classname_prefix(self, input_class_name: str) -> List[str]:
+    """Return a list of package / class names from given commit and input."""
+    # If '/' exists, it's probably a path, not a class name.
+    if '/' in input_class_name:
+      return []
+
+    result_list = []
+    for base_path in UPSTREAM_SEARCH_PATHS:
+      base_len = len(base_path)
+      path = base_path + input_class_name.replace('.', '/')
+      path_results = self.match_path_prefix(path)
+      for p in path_results:
+        relative_path = p[base_len:]
+        if relative_path.endswith('.java'):
+          relative_path = relative_path[0:-5]
+        result_list.append(relative_path.replace('/', '.'))
+
+    return result_list
+
+  def has_file(self, path: str) -> bool:
+    """Returns True if the directory / file exists in the tree."""
+    return has_file_in_tree(path, self.commit.tree)
+
+
+def convert_path_to_java_class_name(path: str, base_path: str) -> str:
+  base_len = len(base_path)
+  result = path[base_len:]
+  if result.endswith('.java'):
+    result = result[0:-5]
+  result = result.replace('/', '.')
+  return result
+
+
+def has_file_in_tree(path: str, tree: Tree) -> bool:
+  """Returns True if the directory / file exists in the tree."""
+  try:
+    # pylint: disable=pointless-statement
+    tree[path]
+    return True
+  except KeyError:
+    return False
diff --git a/tools/expected_upstream/install_tools.sh b/tools/expected_upstream/install_tools.sh
new file mode 100755
index 0000000..4991d70
--- /dev/null
+++ b/tools/expected_upstream/install_tools.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# prerequisite to run the script
+pip3 install GitPython
+
+git fetch aosp upstream-openjdk7u
+git fetch aosp upstream-openjdk8u
+git fetch aosp upstream-openjdk9
+git fetch aosp upstream-openjdk11u
+git fetch aosp upstream-openjdk17u
+
+THIS_DIR=$(realpath $(dirname ${BASH_SOURCE[0]:-$0}))
+alias ojluni_refresh_files=${THIS_DIR}/ojluni_refresh_files.py
+alias ojluni_modify_expectation=${THIS_DIR}/ojluni_modify_expectation.py
+alias ojluni_run_tool_tests='PYTHONPATH=${PYTHONPATH}:${THIS_DIR} python3 -B -m unittest discover -v -s tests -p "*_test.py"'
+alias ojluni_upgrade_identicals=${THIS_DIR}/ojluni_upgrade_identicals.py
+alias ojluni_versions_report=${THIS_DIR}/ojluni_versions_report.py
+
+
+_ojluni_modify_expectation ()
+{
+  COMPREPLY=( $(ojluni_modify_expectation --autocomplete $COMP_CWORD ${COMP_WORDS[@]:1}))
+
+  return 0
+}
+
+complete -o nospace -F _ojluni_modify_expectation ojluni_modify_expectation
diff --git a/tools/expected_upstream/ojluni_modify_expectation.py b/tools/expected_upstream/ojluni_modify_expectation.py
new file mode 100755
index 0000000..705ef49
--- /dev/null
+++ b/tools/expected_upstream/ojluni_modify_expectation.py
@@ -0,0 +1,256 @@
+#!/usr/bin/python3 -B
+
+# Copyright 2021 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.
+"""ojluni_modify_expectation is a command-line tool for modifying the EXPECTED_UPSTREAM file."""
+
+import argparse
+import sys
+
+# pylint: disable=g-importing-member
+# pylint: disable=g-multiple-import
+from typing import (
+    Sequence,
+    List,
+)
+
+from common_util import (
+    ExpectedUpstreamEntry,
+    ExpectedUpstreamFile,
+    LIBCORE_DIR,
+    OpenjdkFinder,
+    OjluniFinder,
+)
+
+# Import git only after common_util because common_util will
+# produce informative error
+from git import (Commit, Repo)
+from gitdb.exc import BadName
+
+LIBCORE_REPO = Repo(LIBCORE_DIR.as_posix())
+
+AUTOCOMPLETE_TAGS = [
+    'jdk7u/jdk7u40-b60',
+    'jdk8u/jdk8u121-b13',
+    'jdk8u/jdk8u60-b31',
+    'jdk9/jdk-9+181',
+    'jdk11u/jdk-11+28',
+    'jdk11u/jdk-11.0.13-ga',
+]
+
+
+def error_and_exit(msg: str) -> None:
+  print(f'Error: {msg}', file=sys.stderr)
+  sys.exit(1)
+
+
+def get_commit_or_exit(git_ref: str) -> Commit:
+  try:
+    return LIBCORE_REPO.commit(git_ref)
+  except BadName as e:
+    error_and_exit(f'{e}')
+
+
+def autocomplete_tag_or_commit(str_tag_or_commit: str) -> List[str]:
+  """Returns a list of tags / commits matching the given partial string."""
+  if str_tag_or_commit is None:
+    str_tag_or_commit = ''
+  return list(
+      filter(lambda tag: tag.startswith(str_tag_or_commit), AUTOCOMPLETE_TAGS))
+
+
+COMMAND_ACTIONS = ['add', 'modify', 'sort']
+
+
+def autocomplete_action(partial_str: str) -> None:
+  result_list = list(
+      filter(lambda action: action.startswith(partial_str), COMMAND_ACTIONS))
+  print('\n'.join(result_list))
+  exit(0)
+
+
+def main(argv: Sequence[str]) -> None:
+  is_auto_complete = len(argv) >= 2 and argv[0] == '--autocomplete'
+  # argparse can't help autocomplete subcommand. We implement this without
+  # argparse here.
+  if is_auto_complete and argv[1] == '1':
+    action = argv[2] if len(argv) >= 3 else ''
+    autocomplete_action(action)
+
+  # If it's for autocompletion, then all arguments are optional.
+  parser_nargs = '?' if is_auto_complete else 1
+
+  main_parser = argparse.ArgumentParser(
+      description='A command line tool modifying the EXPECTED_UPSTREAM file.')
+  # --autocomplete <int> is an 'int' argument because the value represents
+  # the raw index of the argument to be autocompleted received in the Shell,
+  # and this number is not always the same as the number of arguments
+  # received here, i.e. len(argv), for examples of empty value in the
+  # argument or autocompleting the middle argument, not last argument.
+  main_parser.add_argument(
+      '--autocomplete', type=int, help='flag when tabbing in command line')
+  subparsers = main_parser.add_subparsers(
+      dest='command', help='sub-command help')
+
+  add_parser = subparsers.add_parser(
+      'add', help='Add a new entry into the EXPECTED_UPSTREAM '
+      'file')
+  add_parser.add_argument(
+      'tag_or_commit',
+      nargs=parser_nargs,
+      help='A git tag or commit in the upstream-openjdkXXX branch')
+  add_parser.add_argument(
+      'class_or_source_file',
+      nargs=parser_nargs,
+      help='Fully qualified class name or upstream source path')
+  add_parser.add_argument(
+      'ojluni_path', nargs='?', help='Destination path in ojluni/')
+
+  modify_parser = subparsers.add_parser(
+      'modify', help='Modify an entry in the EXPECTED_UPSTREAM file')
+  modify_parser.add_argument(
+      'class_or_ojluni_path', nargs=parser_nargs, help='File path in ojluni/')
+  modify_parser.add_argument(
+      'tag_or_commit',
+      nargs=parser_nargs,
+      help='A git tag or commit in the upstream-openjdkXXX branch')
+  modify_parser.add_argument(
+      'source_file', nargs='?', help='A upstream source path')
+
+  subparsers.add_parser(
+      'sort', help='Sort the entries in the EXPECTED_UPSTREAM file')
+
+  args = main_parser.parse_args(argv)
+
+  expected_upstream_file = ExpectedUpstreamFile()
+  expected_entries = expected_upstream_file.read_all_entries()
+
+  if is_auto_complete:
+    no_args = args.autocomplete
+
+    autocomp_result = []
+    if args.command == 'modify':
+      if no_args == 2:
+        input_class_or_ojluni_path = args.class_or_ojluni_path
+        if input_class_or_ojluni_path is None:
+          input_class_or_ojluni_path = ''
+
+        existing_dst_paths = list(
+            map(lambda entry: entry.dst_path, expected_entries))
+        ojluni_finder: OjluniFinder = OjluniFinder(existing_dst_paths)
+        # Case 1: Treat the input as file path
+        autocomp_result += ojluni_finder.match_path_prefix(
+            input_class_or_ojluni_path)
+
+        # Case 2: Treat the input as java package / class name
+        autocomp_result += ojluni_finder.match_classname_prefix(
+            input_class_or_ojluni_path)
+      elif no_args == 3:
+        autocomp_result += autocomplete_tag_or_commit(args.tag_or_commit)
+    elif args.command == 'add':
+      if no_args == 2:
+        autocomp_result += autocomplete_tag_or_commit(args.tag_or_commit)
+      elif no_args == 3:
+        commit = get_commit_or_exit(args.tag_or_commit)
+        class_or_src_path = args.class_or_source_file
+        if class_or_src_path is None:
+          class_or_src_path = ''
+
+        openjdk_finder: OpenjdkFinder = OpenjdkFinder(commit)
+
+        matches = openjdk_finder.match_path_prefix(
+            class_or_src_path)
+
+        matches += openjdk_finder.match_classname_prefix(
+            class_or_src_path)
+
+        existing_dst_paths = set(map(lambda e: e.dst_path, expected_entries))
+
+        # Translate the class names or source paths to dst paths and exclude
+        # such matches from the auto-completion result
+        def source_not_exists(src_path_or_class: str) -> bool:
+          nonlocal existing_dst_paths, openjdk_finder
+          t_src_path = openjdk_finder.find_src_path_from_classname(
+              src_path_or_class)
+          if t_src_path is None:
+            # t_src_path is a java package. It must not in existing_dst_paths.
+            return True
+          t_dst_path = OpenjdkFinder.translate_src_path_to_ojluni_path(
+              t_src_path)
+          return t_dst_path not in existing_dst_paths
+
+        autocomp_result += list(filter(source_not_exists, matches))
+
+    print('\n'.join(autocomp_result))
+    exit(0)
+
+  if args.command == 'modify':
+    dst_class_or_file = args.class_or_ojluni_path[0]
+    dst_path = OjluniFinder.translate_from_class_name_to_ojluni_path(
+        dst_class_or_file)
+    matches = list(filter(lambda e: dst_path == e.dst_path, expected_entries))
+    if not matches:
+      error_and_exit(f'{dst_path} is not found in the EXPECTED_UPSTREAM.')
+    entry: ExpectedUpstreamEntry = matches[0]
+    str_tag_or_commit = args.tag_or_commit[0]
+    is_src_given = args.source_file is not None
+    src_path = args.source_file if is_src_given else entry.src_path
+    commit = get_commit_or_exit(str_tag_or_commit)
+    openjdk_finder: OpenjdkFinder = OpenjdkFinder(commit)
+    if openjdk_finder.has_file(src_path):
+      pass
+    elif not is_src_given:
+      guessed_src_path = openjdk_finder.find_src_path_from_ojluni_path(dst_path)
+      if guessed_src_path is None:
+        error_and_exit('[source_file] argument is required.')
+      src_path = guessed_src_path
+    else:
+      error_and_exit(f'{src_path} is not found in the {str_tag_or_commit}')
+    entry.git_ref = str_tag_or_commit
+    entry.src_path = src_path
+    expected_upstream_file.write_all_entries(expected_entries)
+    print(f'Modified the entry {entry}')
+  elif args.command == 'add':
+    class_or_src_path = args.class_or_source_file[0]
+    str_tag_or_commit = args.tag_or_commit[0]
+    commit = get_commit_or_exit(str_tag_or_commit)
+    openjdk_finder = OpenjdkFinder(commit)
+    src_path = openjdk_finder.find_src_path_from_classname(class_or_src_path)
+    if src_path is None:
+      search_paths = openjdk_finder.get_search_paths()
+      error_and_exit(f'{class_or_src_path} is not found in {commit}. '
+                     f'The search paths are:\n{search_paths}')
+    ojluni_path = args.ojluni_path
+    # Guess the source path if it's not given in the argument
+    if ojluni_path is None:
+      ojluni_path = OpenjdkFinder.translate_src_path_to_ojluni_path(src_path)
+    if ojluni_path is None:
+      error_and_exit('The ojluni destination path is not given.')
+
+    matches = list(
+        filter(lambda e: ojluni_path == e.dst_path, expected_entries))
+    if matches:
+      error_and_exit(f"Can't add the file {ojluni_path} because "
+                     f'{class_or_src_path} exists in the EXPECTED_UPSTREAM')
+
+    new_entry = ExpectedUpstreamEntry(ojluni_path, str_tag_or_commit, src_path)
+    expected_upstream_file.write_new_entry(new_entry, expected_entries)
+  elif args.command == 'sort':
+    expected_upstream_file.sort_and_write_all_entries(expected_entries)
+  else:
+    error_and_exit(f'Unknown subcommand: {args.command}')
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/tools/expected_upstream/ojluni_refresh_files.py b/tools/expected_upstream/ojluni_refresh_files.py
new file mode 100755
index 0000000..fed28ad
--- /dev/null
+++ b/tools/expected_upstream/ojluni_refresh_files.py
@@ -0,0 +1,259 @@
+#!/usr/bin/python3 -B
+
+# Copyright 2021 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.
+"""Read the EXPECTED_UPSTREAM and update the files from the upstream."""
+import argparse
+import logging
+# pylint: disable=g-importing-member
+from pathlib import Path
+import sys
+from typing import List
+from typing import Sequence
+
+# pylint: disable=g-multiple-import
+from common_util import (
+    ExpectedUpstreamEntry,
+    ExpectedUpstreamFile,
+    has_file_in_tree,
+    LIBCORE_DIR,
+)
+
+from git import (
+    Blob,
+    IndexFile,
+    Repo,
+)
+
+# Enable INFO logging for error emitted by GitPython
+logging.basicConfig(level=logging.INFO)
+
+# Pick an arbitrary existing commit with an empty tree
+EMPTY_COMMIT_SHA = "d85bc16ba1cdcc20bec6fcbfe46dc90f9fcd2f78"
+
+
+def validate_and_remove_updated_entries(
+    entries: List[ExpectedUpstreamEntry],
+    repo: Repo) -> List[ExpectedUpstreamEntry]:
+  """Returns a list of entries of which the file content needs to be updated."""
+  head_tree = repo.head.commit.tree
+  result: List[ExpectedUpstreamEntry] = []
+
+  for e in entries:
+    try:
+      # The following step validate each entry by querying the git database
+      commit = repo.commit(e.git_ref)
+      source_blob = commit.tree.join(e.src_path)
+      if not has_file_in_tree(e.dst_path, head_tree):
+        # Add the entry if the file is missing in the HEAD
+        result.append(e)
+        continue
+
+      dst_blob = head_tree.join(e.dst_path)
+      # Add the entry if the content is different.
+      # data_stream will be close during GC.
+      if source_blob.data_stream.read() != dst_blob.data_stream.read():
+        result.append(e)
+    except:
+      print(f"ERROR: reading entry: {e}", file=sys.stderr)
+      raise
+
+  return result
+
+
+def partition_entries_by_ref(
+    entries: List[ExpectedUpstreamEntry]) -> List[List[ExpectedUpstreamEntry]]:
+  result_map = {}
+  for e in entries:
+    if result_map.get(e.git_ref) is None:
+      result_map[e.git_ref] = []
+    result_map[e.git_ref].append(e)
+
+  return list(result_map.values())
+
+
+THIS_TOOL_PATH = Path(__file__).relative_to(LIBCORE_DIR)
+MSG_FIRST_COMMIT = ("Import {summary} from {ref}\n"
+                    "\n"
+                    "List of files:\n"
+                    "  {files}\n"
+                    "\n"
+                    f"Generated by {THIS_TOOL_PATH}"
+                    "\n"
+                    "Test: N/A")
+
+MSG_SECOND_COMMIT = ("Merge {summary} from {ref} into the "
+                     "expected_upstream branch\n"
+                     "\n"
+                     "List of files:\n"
+                     "  {files}\n"
+                     "\n"
+                     f"Generated by {THIS_TOOL_PATH}"
+                     "\n"
+                     "Test: N/A")
+
+
+def merge_files_and_create_commit(entry_set: List[ExpectedUpstreamEntry],
+                                  repo: Repo, checkout_only: bool) -> None:
+  r"""Create the commits importing the given files into the current branch.
+
+  `--------<ref>---------------   aosp/upstream_openjdkXXX
+             \
+        <first_commit>
+              \
+  -------<second_commit>------   expected_upstream
+
+  This function creates the 2 commits, i.e. first_commit and second_commit, in
+  the diagram. The goal is to checkout a subset files specified in the
+  entry_set, and merged into the pected_upstream branch in order to keep the
+  git-blame history of the individual files. first_commit is needed in order
+  to move the files specified in the entry_set.
+
+  In the implementation, first_commit isn't really modified from the ref, but
+  created from an empty tree, and all files in entry_set will be added into
+  the first_commit, second_commit is a merged commit and modified from
+  the parent in the expected_upstream branch, and any file contents in the
+  first commit will override the file content in the second commit.
+
+  You may reference the following git commands for understanding which should
+  create the same commits, but the python implementation is cleaner, because
+  it doesn't change the working tree or create a new branch.
+  first_commit:
+      git checkout -b temp_branch <entry.git_ref>
+      rm -r * .jcheck/ .hgignore .hgtags # Remove hidden files
+      git checkout <entry.git_ref> <entry.src_path>
+      mkdir -p <entry.dst_path>.directory && git mv <entry.src_path>
+      <entry.dst_path>
+      git commit -a
+  second_commit:
+      git merge temp_branch
+      git checkout HEAD -- ojluni/ # Force checkout to resolve merge conflict
+      git checkout temp_branch -- <entry.dst_path>
+      git commit
+
+  Args:
+    entry_set: a list of entries
+    repo: the repository object
+    checkout_only: True if it creates no commit
+  """
+  ref = entry_set[0].git_ref
+  upstream_commit = repo.commit(ref)
+
+  dst_paths = [e.dst_path for e in entry_set]
+  str_dst_paths = "\n  ".join(dst_paths)
+
+  for entry in entry_set:
+    src_blob = upstream_commit.tree[entry.src_path]
+    # Write into the file system directly because GitPython provides no API
+    # writing into the index in memory. IndexFile.move doesn't help here,
+    # because the API requires the file on the working tree too.
+    # However, it's fine, because we later reset the HEAD to the second commit.
+    # The user expects the file showing in the file system, and the file is
+    # not staged/untracked because the file is in the second commit too.
+    absolute_dst_path = Path(LIBCORE_DIR, entry.dst_path)
+    absolute_dst_path.parent.mkdir(parents=True, exist_ok=True)
+    with absolute_dst_path.open("wb") as file:
+      file.write(src_blob.data_stream.read())
+
+  if not checkout_only:
+    # We need an index empty initially, i.e. no staged files. Note that the
+    # empty commit is not the parent. The parents can be set later.
+    first_index = IndexFile.from_tree(repo, repo.commit(EMPTY_COMMIT_SHA))
+    for entry in entry_set:
+      first_index.add(entry.dst_path)
+
+    summary_msg = "files"
+    if len(entry_set) == 1:
+      summary_msg = Path(entry_set[0].dst_path).stem
+    msg = MSG_FIRST_COMMIT.format(
+        summary=summary_msg, ref=ref, files=str_dst_paths)
+
+    first_commit = first_index.commit(
+        message=msg, parent_commits=[upstream_commit], head=False)
+
+    # The second commit is a merge commit. It doesn't use the current index,
+    # i.e. repo.index, to avoid affecting the current staged files.
+    prev_head = repo.active_branch.commit
+    second_index = IndexFile.from_tree(repo, prev_head)
+    blob_filter = lambda obj, i: isinstance(obj, Blob)
+    blobs = first_commit.tree.traverse(blob_filter)
+    second_index.add(blobs)
+    msg = MSG_SECOND_COMMIT.format(
+        summary=summary_msg, ref=ref, files=str_dst_paths)
+    second_commit = second_index.commit(
+        message=msg, parent_commits=[prev_head, first_commit], head=True)
+
+    # We updated the HEAD to the second commit. Thus, git-reset updates the
+    # current index. Otherwise, the current index, aka, repo.index, shows that
+    # the files are deleted.
+    repo.index.reset()
+
+  if checkout_only:
+    print(f"Checked out the following files from {ref}:")
+  else:
+    print(f"New merge commit {second_commit} contains:")
+  print(f"  {str_dst_paths}")
+
+
+def create_commits(repo: Repo, checkout_only: bool) -> None:
+  """Create the commits importing files according to the EXPECTED_UPSTREAM."""
+  current_tracking_branch = repo.active_branch.tracking_branch()
+  if current_tracking_branch.name != "aosp/expected_upstream":
+    print("This script should only run on aosp/expected_upstream branch. "
+          f"Currently, this is on branch {repo.active_branch} "
+          f"tracking {current_tracking_branch}")
+    return
+
+  print("Reading EXPECTED_UPSTREAM file...")
+  expected_upstream_entries = ExpectedUpstreamFile().read_all_entries()
+
+  outdated_entries = validate_and_remove_updated_entries(
+      expected_upstream_entries, repo)
+
+  if not outdated_entries:
+    print("No need to update. All files are updated.")
+    return
+
+  print("The following entries will be updated from upstream")
+  for e in outdated_entries:
+    print(f"  {e.dst_path}")
+
+  entry_sets_to_be_merged = partition_entries_by_ref(outdated_entries)
+
+  for entry_set in entry_sets_to_be_merged:
+    merge_files_and_create_commit(entry_set, repo, checkout_only)
+
+
+def main(argv: Sequence[str]) -> None:
+  arg_parser = argparse.ArgumentParser(
+      description="Read the EXPECTED_UPSTREAM and update the files from the "
+                  "OpenJDK. By default, it creates commits forking from "
+                  "the upstream version in order to preserve the line history.")
+  arg_parser.add_argument(
+      "--checkout-only", action="store_true",
+      help="Checkout the files, but creates no commits")
+
+  args = arg_parser.parse_args(argv)
+
+  checkout_only = args.checkout_only
+
+  repo = Repo(LIBCORE_DIR.as_posix())
+  try:
+    create_commits(repo, checkout_only)
+  finally:
+    repo.close()
+
+
+if __name__ == "__main__":
+  main(sys.argv[1:])
diff --git a/tools/expected_upstream/ojluni_upgrade_identicals.py b/tools/expected_upstream/ojluni_upgrade_identicals.py
new file mode 100755
index 0000000..1e49bb9
--- /dev/null
+++ b/tools/expected_upstream/ojluni_upgrade_identicals.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python3 -B
+
+# Copyright 2021 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.
+"""ojluni_modify_expectation is a command-line tool for modifying the EXPECTED_UPSTREAM file."""
+
+import argparse
+import sys
+from typing import Sequence
+
+from common_util import ExpectedUpstreamFile
+from common_util import LIBCORE_DIR
+from common_util import OpenjdkFinder
+
+# Import git only after common_util because common_util will
+# produce informative error
+from git import Commit
+from git import Repo
+from gitdb.exc import BadName
+
+LIBCORE_REPO = Repo(LIBCORE_DIR.as_posix())
+
+
+def error_and_exit(msg: str) -> None:
+  print(f'Error: {msg}', file=sys.stderr)
+  sys.exit(1)
+
+
+def get_commit_or_exit(git_ref: str) -> Commit:
+  try:
+    return LIBCORE_REPO.commit(git_ref)
+  except BadName as e:
+    error_and_exit(f'{e}')
+
+
+def main(argv: Sequence[str]) -> None:
+  arg_parser = argparse.ArgumentParser(
+      description='Set an entry in EXCPETED_UPSTREAM to the given version if'
+                  ' the current and given version are identical.')
+  arg_parser.add_argument(
+      'target_ref', nargs=1,
+      help='A git tag or commit in the upstream-openjdkXXX branch')
+  arg_parser.add_argument(
+      'source_ref', nargs='?',
+      help='A git tag or commit in the upstream-openjdkXXX branch')
+
+  args = arg_parser.parse_args(argv)
+
+  target_ref = args.target_ref[0]
+  source_ref = args.source_ref
+  commit = get_commit_or_exit(target_ref)
+
+  expected_upstream_file = ExpectedUpstreamFile()
+  expected_entries = expected_upstream_file.read_all_entries()
+
+  new_finder = OpenjdkFinder(commit)
+
+  for expected_entry in expected_entries:
+    if expected_entry.git_ref == target_ref:
+      continue
+
+    # If the source_ref is specified, skip any existing different source refs.
+    if source_ref is not None and expected_entry.git_ref != source_ref:
+      continue
+
+    current_commit = LIBCORE_REPO.commit(expected_entry.git_ref)
+    current_finder = OpenjdkFinder(current_commit)
+    if not current_finder.has_file(expected_entry.src_path):
+      error_and_exit(f'{expected_entry.src_path} is not found in '
+                     f'{expected_entry.git_ref}')
+
+    current_blob = current_commit.tree[expected_entry.src_path]
+
+    # Try to guess the new source path in the new version
+    new_src_path = expected_entry.src_path
+    if new_finder.has_file(new_src_path):
+      pass
+    else:
+      new_src_path = new_finder.find_src_path_from_ojluni_path(
+          expected_entry.dst_path)
+      if new_src_path is None:
+        print(f"Warning: can't find the upstream path for "
+              f"{expected_entry.dst_path}", file=sys.stderr)
+        continue
+
+    new_blob = commit.tree[new_src_path]
+    if current_blob.data_stream.read() == new_blob.data_stream.read():
+      expected_entry.git_ref = target_ref
+      expected_entry.src_path = new_src_path
+
+  expected_upstream_file.write_all_entries(expected_entries)
+
+
+if __name__ == '__main__':
+  main(sys.argv[1:])
diff --git a/tools/expected_upstream/ojluni_versions_report.py b/tools/expected_upstream/ojluni_versions_report.py
new file mode 100755
index 0000000..8993875
--- /dev/null
+++ b/tools/expected_upstream/ojluni_versions_report.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python3 -B
+
+# Copyright 2021 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.
+
+"""Command line tool to report the statistics of EXPECTED_UPSTREAM file."""
+
+import collections
+
+from common_util import ExpectedUpstreamFile
+from common_util import OJLUNI_JAVA_BASE_PATH
+
+
+def get_major_version(git_ref: str) -> str:
+  index = git_ref.find('/')
+  if index == -1:
+    return git_ref
+  return git_ref[:index]
+
+
+def main() -> None:
+  expected_upstream_file = ExpectedUpstreamFile()
+  expected_entries = expected_upstream_file.read_all_entries()
+
+  non_test_filter = lambda e: e.dst_path.startswith(OJLUNI_JAVA_BASE_PATH)
+  non_test_entries = list(filter(non_test_filter, expected_entries))
+  non_test_refs = list(map(lambda e: e.git_ref, non_test_entries))
+  total = len(non_test_refs)
+
+  minor_groups = dict(collections.Counter(non_test_refs))
+
+  top_tree = {}
+  for git_ref, count in minor_groups.items():
+    major_version = get_major_version(git_ref)
+    if major_version not in top_tree:
+      top_tree[major_version] = {}
+    top_tree[major_version][git_ref] = count
+
+  top_tree = {k: top_tree[k] for k in sorted(top_tree)}
+
+  print('=== Ojluni Version Report ===')
+  for major_version, counts in top_tree.items():
+    subtotal = sum(counts[key] for key in counts)
+    percentages = '{:.2%}'.format(subtotal / total)
+    print(f'{major_version}:\t{subtotal}\t{percentages}')
+    for minor_version, count in counts.items():
+      sub_percentages = '{:.2%}'.format(count / subtotal)
+      print(f'  {minor_version}:\t{count}\t{sub_percentages}')
+
+
+if __name__ == '__main__':
+  main()
diff --git a/mmodules/core_platform_api/api/legacy_platform/last-api.txt b/tools/expected_upstream/tests/__init__.py
similarity index 100%
rename from mmodules/core_platform_api/api/legacy_platform/last-api.txt
rename to tools/expected_upstream/tests/__init__.py
diff --git a/tools/expected_upstream/tests/common_util_test.py b/tools/expected_upstream/tests/common_util_test.py
new file mode 100755
index 0000000..05e2a6b
--- /dev/null
+++ b/tools/expected_upstream/tests/common_util_test.py
@@ -0,0 +1,293 @@
+#!/usr/bin/python3 -B
+
+# Copyright 2021 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.
+"""Tests for common_util."""
+
+from typing import List
+import unittest
+
+# pylint: disable=g-multiple-import
+from common_util import (
+    LIBCORE_DIR,
+    OpenjdkFinder,
+    OjluniFinder,
+)
+
+from git import Repo
+
+
+class OjluniFinderTest(unittest.TestCase):
+
+  LIST_OJLUNI_PATHS = [
+      'ojluni/src/main/java/java/lang/String.java',
+      'ojluni/src/main/java/java/lang/StringBuilder.java',
+      'ojluni/src/main/java/java/lang/package-info.java',
+      'ojluni/src/main/java/java/math/BigInteger.java',
+      'ojluni/src/test/java/math/BigInteger/BigIntegerTest.java',
+      'ojluni/src/main/native/System.c',
+  ]
+
+  def setUp(self):
+    super().setUp()
+    self.ojluni_finder = OjluniFinder(self.LIST_OJLUNI_PATHS)
+
+  def test_translate_from_class_name_to_ojluni_path(self):
+    # Translates a package
+    self.assert_class_to_path(
+        'java.lang.NullPointerException',
+        'ojluni/src/main/java/java/lang/NullPointerException.java')
+    self.assert_class_to_path(
+        'TopPackage.SubPackage.ClassA',
+        'ojluni/src/main/java/TopPackage/SubPackage/ClassA.java')
+
+    # Translates a test package
+    self.assert_class_to_path(
+        'test.java.lang.NullPointerException',
+        'ojluni/src/test/java/lang/NullPointerException.java')
+    self.assert_class_to_path(
+        'test.TopPackage.SubPackage.ClassA',
+        'ojluni/src/test/TopPackage/SubPackage/ClassA.java')
+
+    # Translates a path
+    self.assert_class_to_path(
+        'ojluni/src/main/java/java/lang/NullPointerException.java',
+        'ojluni/src/main/java/java/lang/NullPointerException.java')
+
+    # Test edge cases
+    self.assert_class_to_path('a', 'ojluni/src/main/java/a.java')
+    self.assert_class_to_path('test.a', 'ojluni/src/test/a.java')
+
+  def assert_class_to_path(self, classname: str, expected_path: str):
+    translated_path = OjluniFinder.translate_from_class_name_to_ojluni_path(
+        classname)
+    self.assertEqual(translated_path, expected_path)
+
+  def test_ojluni_match_path_prefix(self):
+    # directory path ending with / or not has different results
+    self.assert_match_ojluni_path('ojluni/src/main/java/java', [
+        'ojluni/src/main/java/java/',
+    ])
+    self.assert_match_ojluni_path('ojluni/src/main/java/java/', [
+        'ojluni/src/main/java/java/lang/',
+        'ojluni/src/main/java/java/math/',
+    ])
+
+    self.assert_match_ojluni_path('ojluni/src/main/java/java/lang/', [
+        'ojluni/src/main/java/java/lang/String.java',
+        'ojluni/src/main/java/java/lang/StringBuilder.java',
+        'ojluni/src/main/java/java/lang/package-info.java',
+    ])
+    self.assert_match_ojluni_path('ojluni/src/main/java/java/lang/String', [
+        'ojluni/src/main/java/java/lang/String.java',
+        'ojluni/src/main/java/java/lang/StringBuilder.java',
+    ])
+    self.assert_match_ojluni_path('ojluni/src/main/java/java/lang/StringB', [
+        'ojluni/src/main/java/java/lang/StringBuilder.java',
+    ])
+    self.assert_match_ojluni_path('ojluni/src/main/java/java/math/', [
+        'ojluni/src/main/java/java/math/BigInteger.java',
+    ])
+
+    self.assert_match_ojluni_path('ojluni/src/test/java/math/BigInteger/', [
+        'ojluni/src/test/java/math/BigInteger/BigIntegerTest.java',
+    ])
+    self.assert_match_ojluni_path('ojluni/src/test/java/math/BigInteger/', [
+        'ojluni/src/test/java/math/BigInteger/BigIntegerTest.java',
+    ])
+
+  def assert_match_ojluni_path(self, path_prefix: str, expected: List[str]):
+    result = self.ojluni_finder.match_path_prefix(path_prefix)
+    self.assertEqual(set(expected), result)
+
+  def test_ojluni_match_classname_prefix(self):
+    # directory path ending with / or not has different results
+    self.assert_match_ojluni_classname('java', ['java.'])
+    self.assert_match_ojluni_classname('java.', [
+        'java.lang.',
+        'java.math.',
+    ])
+
+    self.assert_match_ojluni_classname('java.lang.', [
+        'java.lang.String',
+        'java.lang.StringBuilder',
+        'java.lang.package-info',
+    ])
+    self.assert_match_ojluni_classname('java.lang.String', [
+        'java.lang.String',
+        'java.lang.StringBuilder',
+    ])
+    self.assert_match_ojluni_classname('java.lang.StringB', [
+        'java.lang.StringBuilder',
+    ])
+
+    self.assert_match_ojluni_classname('java.math.', [
+        'java.math.BigInteger',
+    ])
+    self.assert_match_ojluni_classname('java.math.BigInteger', [
+        'java.math.BigInteger',
+    ])
+    self.assert_match_ojluni_classname('test.java.math.BigInteger.', [
+        'test.java.math.BigInteger.BigIntegerTest',
+    ])
+
+  def assert_match_ojluni_classname(self, path_prefix: str,
+                                    expected: List[str]):
+    result = self.ojluni_finder.match_classname_prefix(path_prefix)
+    self.assertEqual(set(expected), set(result))
+
+
+class OpenJdkFinderTest(unittest.TestCase):
+
+  def setUp(self):
+    super().setUp()
+    self.repo = Repo(LIBCORE_DIR.as_posix())
+    commit = self.repo.commit('jdk11u/jdk-11.0.13-ga')
+    self.finder = OpenjdkFinder(commit)
+
+  def tearDown(self):
+    super().tearDown()
+    self.repo.close()
+
+  def test_translate_src_path_to_ojluni_path(self):
+    self.assertEqual(
+        'ojluni/src/main/java/java/lang/String.java',
+        OpenjdkFinder.translate_src_path_to_ojluni_path(
+            'src/java.base/share/classes/java/lang/String.java'))
+    self.assertEqual(
+        'ojluni/src/test/java/math/BigInteger/BigIntegerTest.java',
+        OpenjdkFinder.translate_src_path_to_ojluni_path(
+            'test/jdk/java/math/BigInteger/BigIntegerTest.java'))
+
+  def test_find_src_path_from_classname(self):
+    self.assertEqual(
+        'src/java.base/share/classes/java/lang/String.java',
+        self.finder.find_src_path_from_classname('java.lang.String'))
+    self.assertEqual(
+        'test/jdk/java/math/BigInteger/BigIntegerTest.java',
+        self.finder.find_src_path_from_classname(
+            'java.math.BigInteger.BigIntegerTest'))
+
+  def test_find_src_path_from_ojluni_path(self):
+    self.assertEqual(
+        'src/java.base/share/classes/java/lang/String.java',
+        self.finder.find_src_path_from_ojluni_path(
+            'ojluni/src/main/java/java/lang/String.java'))
+    self.assertEqual(
+        'test/jdk/java/math/BigInteger/BigIntegerTest.java',
+        self.finder.find_src_path_from_ojluni_path(
+            'ojluni/src/test/java/math/BigInteger/BigIntegerTest.java'))
+    self.assertEqual(
+        'src/java.base/unix/classes/sun/nio/fs/UnixPath.java',
+        self.finder.find_src_path_from_ojluni_path(
+            'ojluni/src/main/java/sun/nio/fs/UnixPath.java'))
+    self.assertEqual(
+        'src/java.sql/share/classes/java/sql/Array.java',
+        self.finder.find_src_path_from_ojluni_path(
+            'ojluni/src/main/java/java/sql/Array.java'))
+    self.assertEqual(
+        'src/java.logging/share/classes/java/util/logging/Formatter.java',
+        self.finder.find_src_path_from_ojluni_path(
+            'ojluni/src/main/java/java/util/logging/Formatter.java'))
+
+  def test_match_path_prefix(self):
+    self.assert_match_path_prefix([
+        'src/java.base/share/classes/java/',
+        'src/java.base/share/classes/javax/',
+    ], 'src/java.base/share/classes/java')
+    self.assert_match_path_prefix([
+        'src/java.base/share/classes/java/io/',
+        'src/java.base/share/classes/java/lang/',
+        'src/java.base/share/classes/java/math/',
+        'src/java.base/share/classes/java/net/',
+        'src/java.base/share/classes/java/nio/',
+        'src/java.base/share/classes/java/security/',
+        'src/java.base/share/classes/java/text/',
+        'src/java.base/share/classes/java/time/',
+        'src/java.base/share/classes/java/util/',
+    ], 'src/java.base/share/classes/java/')
+    self.assert_match_path_prefix([
+        'src/java.base/share/classes/java/lang/StringBuffer.java',
+        'src/java.base/share/classes/java/lang/StringIndexOutOfBoundsException.java',
+        'src/java.base/share/classes/java/lang/StringUTF16.java',
+        'src/java.base/share/classes/java/lang/String.java',
+        'src/java.base/share/classes/java/lang/StringConcatHelper.java',
+        'src/java.base/share/classes/java/lang/StringLatin1.java',
+        'src/java.base/share/classes/java/lang/StringBuilder.java',
+        'src/java.base/share/classes/java/lang/StringCoding.java',
+    ], 'src/java.base/share/classes/java/lang/String')
+    self.assert_match_path_prefix([
+        'test/jdk/java/math/BigInteger/BigIntegerTest.java',
+    ], 'test/jdk/java/math/BigInteger/BigInteger')
+
+  def assert_match_path_prefix(self, expected: List[str], prefix: str):
+    result = self.finder.match_path_prefix(prefix)
+    self.assertEqual(set(expected), set(result))
+
+  def test_match_classname_prefix(self):
+    self.assert_match_classname_prefix([
+        'java.',
+        'javax.',
+    ], 'java')
+    self.assert_match_classname_prefix([
+        'java.rmi.',
+        'java.math.',
+        'java.beans.',
+        'java.security.',
+        'java.util.',
+        'java.io.',
+        'java.lang.',
+        'java.nio.',
+        'java.awt.',
+        'java.sql.',
+        'java.text.',
+        'java.time.',
+        'java.net.',
+    ], 'java.')
+    self.assert_match_classname_prefix(
+        [
+            'java.math.BigInteger',
+            'java.math.BigInteger.',  # test package
+        ],
+        'java.math.BigInteger')
+    self.assert_match_classname_prefix([
+        'java.math.BigInteger.PrimitiveConversionTests',
+        'java.math.BigInteger.CompareToTests',
+        'java.math.BigInteger.UnicodeConstructor',
+        'java.math.BigInteger.BigIntegerTest',
+        'java.math.BigInteger.TestValueExact',
+        'java.math.BigInteger.StringConstructorOverflow',
+        'java.math.BigInteger.ExtremeShiftingTests',
+        'java.math.BigInteger.DivisionOverflow',
+        'java.math.BigInteger.OperatorNpeTests',
+        'java.math.BigInteger.ModPow65537',
+        'java.math.BigInteger.LargeValueExceptions',
+        'java.math.BigInteger.ProbablePrime',
+        'java.math.BigInteger.BitLengthOverflow',
+        'java.math.BigInteger.StringConstructor',
+        'java.math.BigInteger.PrimeTest',
+        'java.math.BigInteger.ModPow',
+        'java.math.BigInteger.ModInvTime',
+        'java.math.BigInteger.DoubleValueOverflow',
+        'java.math.BigInteger.SymmetricRangeTests',
+        'java.math.BigInteger.ModPowPowersof2',
+    ], 'java.math.BigInteger.')
+
+  def assert_match_classname_prefix(self, expected: List[str], prefix: str):
+    result = self.finder.match_classname_prefix(prefix)
+    self.assertEqual(set(expected), set(result))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/update-lint-baseline/build.soong.patch b/tools/update-lint-baseline/build.soong.patch
new file mode 100644
index 0000000..53871f2
--- /dev/null
+++ b/tools/update-lint-baseline/build.soong.patch
@@ -0,0 +1,12 @@
+diff --git a/java/lint.go b/java/lint.go
+index 7845c336b..499c0b8c1 100644
+--- a/java/lint.go
++++ b/java/lint.go
+@@ -432,6 +432,7 @@ func (l *linter) lint(ctx android.ModuleContext) {
+ 		FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
+ 		FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
+ 		Flag("--exitcode").
++		Flag("--nowarn").
+ 		Flags(l.properties.Lint.Flags).
+ 		Implicit(annotationsZipPath).
+ 		Implicit(apiVersionsXMLPath)
diff --git a/tools/update-lint-baseline/update-lint-baseline.sh b/tools/update-lint-baseline/update-lint-baseline.sh
new file mode 100755
index 0000000..8df57f4
--- /dev/null
+++ b/tools/update-lint-baseline/update-lint-baseline.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+#
+# Copyright (C) 2021 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.
+
+# This script is a temporary workaround for updating the
+# libcore/lint-baseline.xml file to avoid merge conflicts
+# (b/208656169).
+
+if [ -z "${ANDROID_BUILD_TOP}" ] ; then
+  echo "This script needs to be run after sourcing build/envsetup.sh."
+  exit 1
+fi
+
+if [ -z "${TARGET_PRODUCT}" ] ; then
+  echo "This script needs to be run after selecting a build target (lunch)."
+  exit 1
+fi
+
+SCRIPT_DIR=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
+LIBCORE_BASELINE="${ANDROID_BUILD_TOP}/libcore/lint-baseline.xml"
+NEW_BASELINE="out/soong/.intermediates/libcore/core-all/android_common/lint/lint-baseline.xml"
+
+# The patch file comes from go/mainline-newapi
+PATCH_FILE="$SCRIPT_DIR/build.soong.patch"
+
+# Check if it looks like the patch required has already been applied.
+cd "$ANDROID_BUILD_TOP/build/soong"
+if git diff-index --quiet HEAD ; then
+  echo "Applying $PATCH_FILE to build/soong."
+  git apply "$PATCH_FILE"
+else
+  echo "Assuming $PATCH_FILE is already applied (hit ctrl-C if this is not the case)."
+fi
+cd "$ANDROID_BUILD_TOP"
+
+echo "Re-generating baseline files."
+
+# Remove LIBCORE_BASELINE file if it exists to trigger generating a
+# new one in the out/ directory.
+if [ -f "${LIBCORE_BASELINE}" ]; then
+  rm "${LIBCORE_BASELINE}"
+fi
+
+if [ -f "${NEW_BASELINE}" ]; then
+  rm "${NEW_BASELINE}"
+fi
+
+# The build fails when generating the new baseline file so we ignore
+# the error and check if the output file exists. This is why this script
+# is a temporary kludge. No sensible person would choose to do this.
+build/soong/soong_ui.bash --build-mode --all-modules --dir="$PWD" "${NEW_BASELINE}"
+if [ ! -f "${NEW_BASELINE}" ] ; then
+  echo "Failed to generate ${NEW_BASELINE}"
+  exit 1
+fi
+
+# Generate suppressions at API Level 33
+sed -e '3i\' -e '<!-- generated by libcore/tools/update-lint-baseline/update-lint-baseline.sh -->' \
+    -e 's/level 32/level 33/' -e '/issues>/ {d;q}' "${NEW_BASELINE}" > "${LIBCORE_BASELINE}"
+
+# Add comment explaining the two halves of this file.
+cat<<MIDWAY >> "${LIBCORE_BASELINE}"
+    <!-- TODO(b/205570605): The following repeats all the issues above, but with
+         required API level 32 instead of 33 in the messages. This happens in
+         unbundled Mainline builds, e.g.
+         m TARGET_PRODUCT=mainline_modules_arm TARGET_BUILD_APPS=com.android.art TARGET_BUILD_UNBUNDLED=true lint-check
+    -->
+MIDWAY
+
+# Generate suppressions at API Level 32
+sed -e '0,/<issues/ d' "${NEW_BASELINE}" >> "${LIBCORE_BASELINE}"
+
+cat <<EPILOGUE
+Updated baseline generated.
+
+You will likely want to perform the following steps next:
+
+  # Remove soong patch added by this script
+  git -C $ANDROID_BUILD_TOP/build/soong co -- .
+
+  # Commit the updated lint-baseline.xml file
+  git -C $ANDROID_BUILD_TOP/libcore commit -a lint-baseline.xml
+
+EPILOGUE
+
diff --git a/tools/upstream/merge-from-upstream b/tools/upstream/merge-from-upstream
new file mode 100755
index 0000000..4f0aefd
--- /dev/null
+++ b/tools/upstream/merge-from-upstream
@@ -0,0 +1,411 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2021 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.
+
+
+"""
+Merges upstream files to ojluni. This is done by using git to perform a 3-way
+merge between the current (base) upstream version, ojluni and the new (target)
+upstream version. The 3-way merge is needed because ojluni sometimes contains
+some Android-specific changes from the upstream version.
+
+This tool is for libcore maintenance; if you're not maintaining libcore,
+you won't need it (and might not have access to some of the instructions
+below).
+
+The naming of the repositories (expected, ojluni, 7u40, 8u121-b13,
+9b113+, 9+181) is based on the directory name where corresponding
+snapshots are stored when following the instructions at
+http://go/libcore-o-verify
+
+This script tries to preserve Android changes to upstream code when moving to a
+newer version.
+
+All the work is made in a new directory which is initialized as a git
+repository. An example of the repository structure, where an update is made
+from version 9b113+ to 11+28, would be:
+
+    *   5593705 (HEAD -> main) Merge branch 'ojluni'
+    |\
+    | * 2effe03 (ojluni) Ojluni commit
+    * | 1bef5f3 Target commit (11+28)
+    |/
+    * 9ae2fbf Base commit (9b113+)
+
+The conflicts during the merge get resolved by git whenever possible. However,
+sometimes there are conflicts that need to be resolved manually. If that is the
+case, the script will terminate to allow for the resolving. Once the user has
+resolved the conflicts, they should rerun the script with the --continue
+option.
+
+Once the merge is complete, the script will copy the merged version back to
+ojluni within the $ANDROID_BUILD_TOP location.
+
+For the script to run correctly, it needs the following environment variables
+defined:
+    - OJLUNI_UPSTREAMS
+    - ANDROID_BUILD_TOP
+
+Possible uses:
+
+To merge in changes from a newer version of the upstream using a default
+working dir created in /tmp:
+    merge-from-upstream -f expected -t 11+28 java/util/concurrent
+
+To merge in changes from a newer version of the upstream using a custom
+working dir:
+    merge-from-upstream -f expected -t 11+28 \
+            -d $HOME/tmp/ojluni-merge java/util/concurrent
+
+To merge in changes for a single file:
+    merge-from-upstream -f 9b113+ -t 11+28 \
+        java/util/concurrent/atomic/AtomicInteger.java
+
+To merge in changes, using a custom folder, that require conflict resolution:
+    merge-from-upstream -f expected -t 11+28 \
+        -d $HOME/tmp/ojluni-merge \
+        java/util/concurrent
+    <manually resolve conflicts and add them to git staging>
+    merge-from-upstream --continue \
+        -d $HOME/tmp/ojluni-merge java/util/concurrent
+"""
+
+import argparse
+import os
+import os.path
+import subprocess
+import sys
+import shutil
+
+
+def printerr(msg):
+    sys.stderr.write(msg + "\r\n")
+
+
+def user_check(msg):
+    choice = str(input(msg + " [y/N] ")).strip().lower()
+    if choice[:1] == 'y':
+        return True
+    return False
+
+
+def check_env_vars():
+    keys = [
+        'OJLUNI_UPSTREAMS',
+        'ANDROID_BUILD_TOP',
+    ]
+    result = True
+    for key in keys:
+        if key not in os.environ:
+            printerr("Unable to run, you must have {} defined".format(key))
+            result = False
+    return result
+
+
+def get_upstream_path(version, rel_path):
+    upstreams = os.environ['OJLUNI_UPSTREAMS']
+    return '{}/{}/{}'.format(upstreams, version, rel_path)
+
+
+def get_ojluni_path(rel_path):
+    android_build_top = os.environ['ANDROID_BUILD_TOP']
+    return '{}/libcore/ojluni/src/main/java/{}'.format(
+        android_build_top, rel_path)
+
+
+def make_copy(src, dst):
+    print("Copy " + src + " -> " + dst)
+    if os.path.isfile(src):
+        if os.path.exists(dst) and os.path.isfile(dst):
+            os.remove(dst)
+        shutil.copy(src, dst)
+    else:
+        shutil.copytree(src, dst, dirs_exist_ok=True)
+
+
+class Repo:
+    def __init__(self, dir):
+        self.dir = dir
+
+    def init(self):
+        if 0 != subprocess.call(['git', 'init', '-b', 'main', self.dir]):
+            raise RuntimeError(
+                "Unable to initialize working git repository.")
+        subprocess.call(['git', '-C', self.dir,
+                         'config', 'rerere.enabled', 'true'])
+
+    def commit_all(self, id, msg):
+        if 0 != subprocess.call(['git', '-C', self.dir, 'add', '*']):
+            raise RuntimeError("Unable to add the {} files.".format(id))
+        if 0 != subprocess.call(['git', '-C', self.dir, 'commit',
+                                '-m', msg]):
+            raise RuntimeError("Unable to commit the {} files.".format(id))
+
+    def checkout_branch(self, branch, is_new=False):
+        cmd = ['git', '-C', self.dir, 'checkout']
+        if is_new:
+            cmd.append('-b')
+        cmd.append(branch)
+        if 0 != subprocess.call(cmd):
+            raise RuntimeError("Unable to checkout the {} branch."
+                               .format(branch))
+
+    def merge(self, branch):
+        """
+        Tries to merge in a branch and returns True if the merge commit has
+        been created. If there are conflicts to be resolved, this returns
+        False.
+        """
+        if 0 == subprocess.call(['git', '-C', self.dir,
+                                'merge', branch, '--no-edit']):
+            return True
+        if not self.is_merging():
+            raise RuntimeError("Unable to run merge for the {} branch."
+                               .format(branch))
+        subprocess.call(['git', '-C', self.dir, 'rerere'])
+        return False
+
+    def check_resolved_from_cache(self):
+        """
+        Checks if some conflicts have been resolved by the git rerere tool. The
+        tool only applies the previous resolution, but does not mark the file
+        as resolved afterwards. Therefore this function will go through the
+        unresolved files and see if there are outstanding conflicts. If all
+        conflicts have been resolved, the file gets stages.
+
+        Returns True if all conflicts are resolved, False otherwise.
+        """
+        # git diff --check will exit with error if there are conflicts to be
+        # resolved, therefore we need to use check=False option to avoid an
+        # exception to be raised
+        conflict_markers = subprocess.run(['git', '-C', self.dir,
+                                           'diff', '--check'],
+                                          stdout=subprocess.PIPE,
+                                          check=False).stdout
+        conflicts = subprocess.check_output(['git', '-C', self.dir, 'diff',
+                                             '--name-only', '--diff-filter=U'])
+
+        for filename in conflicts.splitlines():
+            if conflict_markers.find(filename) != -1:
+                print("{} still has conflicts, please resolve manually".
+                      format(filename))
+            else:
+                print("{} has been resolved, staging it".format(filename))
+                subprocess.call(['git', '-C', self.dir, 'add', filename])
+
+        return not self.has_conflicts()
+
+    def has_changes(self):
+        result = subprocess.check_output(['git', '-C', self.dir, 'status',
+                                          '--porcelain'])
+        return len(result) != 0
+
+    def has_conflicts(self):
+        conflicts = subprocess.check_output(['git', '-C', self.dir, 'diff',
+                                             '--name-only', '--diff-filter=U'])
+        return len(conflicts) != 0
+
+    def is_merging(self):
+        return 0 == subprocess.call(['git', '-C', self.dir, 'rev-parse',
+                                     '-q', '--verify', 'MERGE_HEAD'],
+                                    stdout=subprocess.DEVNULL)
+
+    def complete_merge(self):
+        print("Completing merge in {}".format(self.dir))
+        subprocess.call(['git', '-C', self.dir, 'rerere'])
+        if 0 != subprocess.call(['git', '-C', self.dir,
+                                 'commit', '--no-edit']):
+            raise RuntimeError("Unable to complete the merge in {}."
+                               .format(self.dir))
+        if self.is_merging():
+            raise RuntimeError(
+                "Merging in {} is not complete".format(self.dir))
+
+    def load_resolve_files(self, resolve_dir):
+        print("Loading resolve files from {}".format(resolve_dir))
+        if not os.path.lexists(resolve_dir):
+            print("Resolve dir {} not found, no resolutions will be used"
+                  .format(resolve_dir))
+            return
+        make_copy(resolve_dir, self.dir + "/.git/rr-cache")
+
+    def save_resolve_files(self, resolve_dir):
+        print("Saving resolve files to {}".format(resolve_dir))
+        if not os.path.lexists(resolve_dir):
+            os.makedirs(resolve_dir)
+        make_copy(self.dir + "/.git/rr-cache", resolve_dir)
+
+
+class Merger:
+    def __init__(self, repo_dir, rel_path, resolve_dir):
+        self.repo = Repo(repo_dir)
+        # Have all the source files copied inside a src dir, so we don't have
+        # any issue with copying back the .git dir
+        self.working_dir = repo_dir + "/src"
+        self.rel_path = rel_path
+        self.resolve_dir = resolve_dir
+
+    def create_working_dir(self):
+        if os.path.lexists(self.repo.dir):
+            if not user_check(
+                    '{} already exists. Can it be removed?'
+                    .format(self.repo.dir)):
+                raise RuntimeError(
+                    'Will not remove {}. Consider using another '
+                    'working dir'.format(self.repo.dir))
+            try:
+                shutil.rmtree(self.repo.dir)
+            except OSError:
+                printerr("Unable to delete {}.".format(self.repo.dir))
+                raise
+        os.makedirs(self.working_dir)
+        self.repo.init()
+        if self.resolve_dir is not None:
+            self.repo.load_resolve_files(self.resolve_dir)
+
+    def copy_upstream_files(self, version, msg):
+        full_path = get_upstream_path(version, self.rel_path)
+        make_copy(full_path, self.working_dir)
+        self.repo.commit_all(version, msg)
+
+    def copy_base_files(self, base_version):
+        self.copy_upstream_files(base_version,
+                                 'Base commit ({})'.format(base_version))
+
+    def copy_target_files(self, target_version):
+        self.copy_upstream_files(target_version,
+                                 'Target commit ({})'.format(target_version))
+
+    def copy_ojluni_files(self):
+        full_path = get_ojluni_path(self.rel_path)
+        make_copy(full_path, self.working_dir)
+        if self.repo.has_changes():
+            self.repo.commit_all('ojluni', 'Ojluni commit')
+            return True
+        else:
+            return False
+
+    def run_ojluni_merge(self):
+        if self.repo.merge('ojluni'):
+            return
+        if self.repo.check_resolved_from_cache():
+            self.repo.complete_merge()
+            return
+        raise RuntimeError('\r\nThere are conflicts to be resolved.'
+                           '\r\nManually merge the changes and rerun '
+                           'this script with --continue')
+
+    def copy_back_to_ojluni(self):
+        # Save any resolutions that were made for future reuse
+        if self.resolve_dir is not None:
+            self.repo.save_resolve_files(self.resolve_dir)
+
+        src_path = self.working_dir
+        dst_path = get_ojluni_path(self.rel_path)
+        if os.path.isfile(dst_path):
+            src_path += '/' + os.path.basename(self.rel_path)
+        make_copy(src_path, dst_path)
+
+    def run(self, base_version, target_version):
+        print("Merging {} from {} into ojluni (based on {}). "
+              "Using {} as working dir."
+              .format(self.rel_path, target_version,
+                      base_version, self.repo.dir))
+        self.create_working_dir()
+        self.copy_base_files(base_version)
+        # The ojluni code should be added in its own branch. This is to make
+        # Git perform the 3-way merge once a commit is added with the latest
+        # upstream code.
+        self.repo.checkout_branch('ojluni', is_new=True)
+        merge_needed = self.copy_ojluni_files()
+        self.repo.checkout_branch('main')
+        self.copy_target_files(target_version)
+        if merge_needed:
+            # Runs the merge in the working directory, if some conflicts need
+            # to be resolved manually, then an exception is raised which will
+            # terminate the script, informing the user that manual intervention
+            # is needed.
+            self.run_ojluni_merge()
+        else:
+            print("No merging needed as there were no "
+                  "Android-specific changes, forwarding to new version ({})"
+                  .format(target_version))
+        self.copy_back_to_ojluni()
+
+    def complete_existing_run(self):
+        if self.repo.is_merging():
+            self.repo.complete_merge()
+        self.copy_back_to_ojluni()
+
+
+def main():
+    if not check_env_vars():
+        return
+
+    upstreams = os.environ['OJLUNI_UPSTREAMS']
+    repositories = sorted(
+        [d for d in os.listdir(upstreams)
+         if os.path.isdir(os.path.join(upstreams, d))]
+    )
+
+    parser = argparse.ArgumentParser(
+        description='''
+        Merge upstream files from ${OJLUNI_UPSTREAMS} to libcore/ojluni.
+        Needs the base (from) repository as well as the target (to) repository.
+        Repositories can be chosen from:
+        ''' + ' '.join(repositories) + '.',
+        # include default values in help
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+    )
+    parser.add_argument('-f', '--from', default='expected',
+                        choices=repositories,
+                        dest='base',
+                        help='Repository on which the requested ojluni '
+                        'files are based.')
+    parser.add_argument('-t', '--to',
+                        choices=repositories,
+                        dest='target',
+                        help='Repository to which the requested ojluni '
+                        'files will be updated.')
+    parser.add_argument('-d', '--work-dir', default='/tmp/ojluni-merge',
+                        help='Path where the merge will be performed. '
+                        'Any existing files in the path will be removed')
+    parser.add_argument('-r', '--resolve-dir', default=None,
+                        dest='resolve_dir',
+                        help='Path where the git resolutions are cached. '
+                        'By default, no cache is used.')
+    parser.add_argument('--continue', action='store_true', dest='proceed',
+                        help='Flag to specify after merge conflicts '
+                        'are resolved')
+    parser.add_argument('rel_path', nargs=1, metavar='<relative_path>',
+                        help='File to merge: a relative path below '
+                        'libcore/ojluni/ which could point to '
+                        'a file or folder.')
+    args = parser.parse_args()
+    try:
+        merger = Merger(args.work_dir, args.rel_path[0], args.resolve_dir)
+        if args.proceed:
+            merger.complete_existing_run()
+        else:
+            if args.target is None:
+                raise RuntimeError('Please specify the target upstream '
+                                   'version using the -t/--to argument')
+            merger.run(args.base, args.target)
+    except Exception as e:
+        printerr(str(e))
+
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/upstream/pkg-status b/tools/upstream/pkg-status
new file mode 100755
index 0000000..b8bc163
--- /dev/null
+++ b/tools/upstream/pkg-status
@@ -0,0 +1,428 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2021 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.
+
+"""
+Reports on merge status of Java files in a package based on four
+repositories:
+
+baseline - upstream baseline used for previous Android release
+release  - files in previous Android release
+current  - target for merge
+upstream - new upstream being merged
+
+Example output:
+$ tools/upstream/pkg-status java.security.spec
+AlgorithmParameterSpec.java: Unchanged, Done
+DSAGenParameterSpec.java: Added, TO DO
+DSAParameterSpec.java: Unchanged, Done
+DSAPrivateKeySpec.java: Unchanged, Done
+DSAPublicKeySpec.java: Unchanged, Done
+ECField.java: Unchanged, Done
+ECFieldF2m.java: Unchanged, Done
+ECFieldFp.java: Unchanged, Done
+ECGenParameterSpec.java: Updated, TO DO
+[...]
+"""
+
+import argparse
+import hashlib
+import os
+import os.path
+import sys
+from enum import Enum
+from pathlib import Path
+
+RED = '\u001b[31m'
+GREEN = "\u001b[32m"
+YELLOW = "\u001b[33m"
+RESET = "\u001b[0m"
+
+
+def colourise(colour, string):
+    """Wrap a string with an ANSI colour code"""
+    return "%s%s%s" % (colour, string, RESET)
+
+
+def red(string):
+    """Wrap a string with a red ANSI colour code"""
+    return colourise(RED, string)
+
+
+def green(string):
+    """Wrap a string with a green ANSI colour code"""
+    return colourise(GREEN, string)
+
+
+def yellow(string):
+    """Wrap a string with a yellow ANSI colour code"""
+    return colourise(YELLOW, string)
+
+
+class WorkStatus(Enum):
+    """Enum for a file's work completion status"""
+    UNKNOWN = ('Unknown', red)
+    TODO = ('TO DO', yellow)
+    DONE = ('Done', green)
+    PROBABLY_DONE = ('Probably done', green)
+    ERROR = ('Error', red)
+
+    def colourise(self, string):
+        """Colourise a string using the method for this enum value"""
+        return self.colourfunc(string)
+
+    def __init__(self, description, colourfunc):
+        self.description = description
+        self.colourfunc = colourfunc
+
+
+class MergeStatus(Enum):
+    """Enum for a file's merge status"""
+    UNKNOWN = 'Unknown!'
+    MISSING = 'Missing'
+    ADDED = 'Added'
+    DELETED = 'Deleted or moved'
+    UNCHANGED = 'Unchanged'
+    UPDATED = 'Updated'
+
+    def __init__(self, description):
+        self.description = description
+
+
+class MergeConfig:
+    """
+    Configuration for an upstream merge.
+
+    Encapsulates the paths to each of the required code repositories.
+    """
+    def __init__(self, baseline, release, current, upstream) -> None:
+        self.baseline = baseline
+        self.release = release
+        self.current = current
+        self.upstream = upstream
+        try:
+            # Root of checked-out Android sources, set by the "lunch" command.
+            self.android_build_top = os.environ['ANDROID_BUILD_TOP']
+            # Root of repository snapshots.
+            self.ojluni_upstreams = os.environ['OJLUNI_UPSTREAMS']
+        except KeyError:
+            sys.exit('`lunch` and set OJLUNI_UPSTREAMS first.')
+
+
+    def java_dir(self, repo, pkg):
+        relpath = pkg.replace('.', '/')
+        if repo == self.current:
+            return '%s/libcore/%s/src/main/java/%s' % (
+                    self.android_build_top, self.current, relpath)
+        else:
+            return '%s/%s/%s' % (self.ojluni_upstreams, repo, relpath)
+
+    def baseline_dir(self, pkg):
+        return self.java_dir(self.baseline, pkg)
+
+    def release_dir(self, pkg):
+        return self.java_dir(self.release, pkg)
+
+    def current_dir(self, pkg):
+        return self.java_dir(self.current, pkg)
+
+    def upstream_dir(self, pkg):
+        return self.java_dir(self.upstream, pkg)
+
+
+class JavaPackage:
+    """
+    Encapsulates information about a single Java package, notably paths
+    to it within each repository.
+    """
+    def __init__(self, config, name) -> None:
+        self.name = name
+        self.baseline_dir = config.baseline_dir(name)
+        self.release_dir = config.release_dir(name)
+        self.current_dir = config.current_dir(name)
+        self.upstream_dir = config.upstream_dir(name)
+
+    @staticmethod
+    def list_candidate_files(path):
+        """Returns a list of all the Java filenames in a directory."""
+        return list(filter(
+                lambda f: f.endswith('.java') and f != 'package-info.java',
+                os.listdir(path)))
+
+    def all_files(self):
+        """Returns the union of all the Java filenames in all repositories."""
+        files = set(self.list_candidate_files(self.baseline_dir))
+        files.update(self.list_candidate_files(self.release_dir))
+        files.update(self.list_candidate_files(self.upstream_dir))
+        files.update(self.list_candidate_files(self.current_dir))
+        return sorted(list(files))
+
+    def java_files(self):
+        """Returns a list of JavaFiles corresponding to all filenames."""
+        return map(lambda f: JavaFile(self, f), self.all_files())
+
+    def baseline_path(self, filename):
+        return Path(self.baseline_dir + '/' + filename)
+
+    def release_path(self, filename):
+        return Path(self.release_dir + '/' + filename)
+
+    def current_path(self, filename):
+        return Path(self.current_dir + '/' + filename)
+
+    def upstream_path(self, filename):
+        return Path(self.upstream_dir + '/' + filename)
+
+    def report_merge_status(self):
+        """Report on the mergse status of this package."""
+        for file in self.java_files():
+            merge_status, work_status = file.status()
+            text = '%s: %s, %s' % \
+                   (
+                           file.name, merge_status.description,
+                           work_status.description)
+            print(work_status.colourise(text))
+            if work_status == WorkStatus.ERROR:
+                print(file.baseline_sum, file.baseline)
+                print(file.release_sum, file.release)
+                print(file.current_sum, file.current)
+                print(file.upstream_sum, file.upstream)
+
+
+class JavaFile:
+    """
+    Encapsulates information about a single Java file in a package across
+    all of the repositories involved in a merge.
+    """
+    def __init__(self, package, name):
+        self.package = package
+        self.name = name
+        # Paths for this file in each repository
+        self.baseline = package.baseline_path(name)
+        self.release = package.release_path(name)
+        self.upstream = package.upstream_path(name)
+        self.current = package.current_path(name)
+        # Checksums for this file in each repository, or None if absent
+        self.baseline_sum = self.checksum(self.baseline)
+        self.release_sum = self.checksum(self.release)
+        self.upstream_sum = self.checksum(self.upstream)
+        self.current_sum = self.checksum(self.current)
+        # List of methods for determining file's merge status.
+        # Order matters - see merge_status() for details
+        self.merge_status_methods = [
+                (self.check_for_missing, MergeStatus.MISSING),
+                (self.check_for_unchanged, MergeStatus.UNCHANGED),
+                (self.check_for_added_upstream, MergeStatus.ADDED),
+                (self.check_for_removed_upstream, MergeStatus.DELETED),
+                (self.check_for_changed_upstream, MergeStatus.UPDATED),
+        ]
+        # Map of methods from merge status to determine work status
+        self.work_status_methods = {
+                MergeStatus.MISSING: self.calculate_missing_work_status,
+                MergeStatus.UNCHANGED: self.calculate_unchanged_work_status,
+                MergeStatus.ADDED: self.calculate_added_work_status,
+                MergeStatus.DELETED: self.calculate_deleted_work_status,
+                MergeStatus.UPDATED: self.calculate_updated_work_status,
+        }
+
+    def is_android_changed(self):
+        """
+        Returns true if the file was changed between the baseline and Android
+        release.
+        """
+        return self.is_in_release() and self.baseline_sum != self.release_sum
+
+    def is_android_unchanged(self):
+        """
+        Returns true if the file is in the Android release and is unchanged.
+        """
+        return self.is_in_release() and self.baseline_sum == self.release_sum
+
+    def check_for_changed_upstream(self):
+        """Returns true if the file is changed upstream since the baseline."""
+        return self.baseline_sum != self.upstream_sum
+
+    def is_in_baseline(self):
+        return self.baseline_sum is not None
+
+    def is_in_release(self):
+        """Returns true if the file is present in the baseline and release."""
+        return self.is_in_baseline() and self.release_sum is not None
+
+    def is_in_current(self):
+        """Returns true if the file is in current, release and baseline."""
+        return self.is_in_release() and self.current_sum is not None
+
+    def is_in_upstream(self):
+        return self.upstream_sum is not None
+
+    def check_for_missing(self):
+        """
+        Returns true if the file is expected to be in current, but isn't.
+        """
+        return self.is_in_release() and self.is_in_upstream() \
+               and not self.is_in_current()
+
+    def removed_in_release(self):
+        """Returns true if the file was removed by Android in the release."""
+        return self.is_in_baseline() and not self.is_in_release()
+
+    def check_for_removed_upstream(self):
+        """Returns true if the file was removed upstream since the baseline."""
+        return self.is_in_baseline() and not self.is_in_upstream()
+
+    def check_for_added_upstream(self):
+        """Returns true if the file was added upstream since the baseline."""
+        return self.is_in_upstream() and not self.is_in_baseline()
+
+    def check_for_unchanged(self):
+        """Returns true if the file is unchanged upstream since the baseline."""
+        return not self.check_for_changed_upstream()
+
+    def merge_status(self):
+        """
+        Returns the merge status for this file, or UNKNOWN.
+        Tries each merge_status_method in turn, and if one returns true
+        then this method returns the associated merge status.
+        """
+        for (method, status) in self.merge_status_methods:
+            if method():
+                return status
+        return MergeStatus.UNKNOWN
+
+    def work_status(self):
+        """
+        Returns the work status for this file.
+        Looks up a status method based on the merge statis and uses that to
+        determine the work status.
+        """
+        status = self.merge_status()
+        if status in self.work_status_methods:
+            return self.work_status_methods[status]()
+        return WorkStatus.ERROR
+
+    @staticmethod
+    def calculate_missing_work_status():
+        """Missing files are always an error."""
+        return WorkStatus.ERROR
+
+    def calculate_unchanged_work_status(self):
+        """
+        File is unchanged upstream, so should be unchanged between release and
+        current.
+        """
+        if self.current_sum == self.release_sum:
+            return WorkStatus.DONE
+        return WorkStatus.UNKNOWN
+
+    def calculate_added_work_status(self):
+        """File was added upstream so needs to be added to current."""
+        if self.current_sum is None:
+            return WorkStatus.TODO
+        if self.current_sum == self.upstream_sum:
+            return WorkStatus.DONE
+        #     XXX check for change markers if android changed
+        return WorkStatus.UNKNOWN
+
+    def calculate_deleted_work_status(self):
+        """File was removed upstream so needs to be removed from current."""
+        if self.is_in_current():
+            return WorkStatus.TODO
+        return WorkStatus.DONE
+
+    def calculate_updated_work_status(self):
+        """File was updated upstream."""
+        if self.current_sum == self.upstream_sum:
+            if self.is_android_unchanged():
+                return WorkStatus.DONE
+            # Looks like Android changes are missing in current
+            return WorkStatus.ERROR
+        if self.is_android_unchanged():
+            return WorkStatus.TODO
+        # If we get here there are upstream and Android changes that need
+        # to be merged,  If possible use the file copyright date as a
+        # heuristic to determine if upstream has been merged into current
+        release_copyright = self.get_copyright(self.release)
+        current_copyright = self.get_copyright(self.current)
+        upstream_copyright = self.get_copyright(self.upstream)
+        if release_copyright == upstream_copyright:
+            # Upstream copyright same as last release, so can't infer anything
+            return WorkStatus.UNKNOWN
+        if current_copyright == upstream_copyright:
+            return WorkStatus.PROBABLY_DONE
+        if current_copyright == release_copyright:
+            return WorkStatus.TODO
+        # Give up
+        return WorkStatus.UNKNOWN
+
+    def status(self):
+        return self.merge_status(), self.work_status()
+
+    @staticmethod
+    def checksum(path):
+        """Returns a checksum string for a file, SHA256 as a hex string."""
+        try:
+            with open(path, 'rb') as file:
+                bytes = file.read()
+                return hashlib.sha256(bytes).hexdigest()
+        except:
+            return None
+
+    @staticmethod
+    def get_copyright(file):
+        """Returns the upstream copyright line for a file."""
+        try:
+            with open(file, 'r') as file:
+                for count in range(5):
+                    line = file.readline()
+                    if line.startswith(
+                            ' * Copyright') and 'Android' not in line:
+                        return line
+                return None
+        except:
+            return None
+
+
+def main():
+    parser = argparse.ArgumentParser(
+            description='Report on merge status of Java packages',
+            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+
+    # TODO(prb): Add help for available repositories
+    parser.add_argument('-b', '--baseline', default='expected',
+                        help='Baseline repo')
+    parser.add_argument('-r', '--release', default='sc-release',
+                        help='Last released repo')
+    parser.add_argument('-u', '--upstream', default='11+28',
+                        help='Upstream repo.')
+    parser.add_argument('-c', '--current', default='ojluni',
+                        help='Current repo.')
+    parser.add_argument('pkgs', nargs="+",
+                        help='Packages to report on')
+
+    args = parser.parse_args()
+    config = MergeConfig(args.baseline, args.release, args.current,
+                         args.upstream)
+
+    for pkg_name in args.pkgs:
+        try:
+            package = JavaPackage(config, pkg_name)
+            package.report_merge_status()
+        except Exception as e:
+            print(red("ERROR: Unable to process package " + pkg_name + e))
+
+
+if __name__ == "__main__":
+    main()
diff --git a/tools/upstream/src/main/java/libcore/CompareUpstreams.java b/tools/upstream/src/main/java/libcore/CompareUpstreams.java
index d9588a7..c2b6cde 100644
--- a/tools/upstream/src/main/java/libcore/CompareUpstreams.java
+++ b/tools/upstream/src/main/java/libcore/CompareUpstreams.java
@@ -165,6 +165,7 @@
             headers.add(upstream.name());
         }
         headers.add("diff");
+        headers.add("guessed_upstream_path");
         printTsv(out, headers);
 
         Path snapshotRoot = COMPARE_AGAINST_UPSTREAM_SNAPSHOT
@@ -217,6 +218,8 @@
             String changedCommentsSummary = androidChangedCommentsSummary(linesB);
 
             String diffCommand = "";
+            String guessed_upstream_path = guessedUpstream != null ?
+                "" + guessedUpstream.pathFromRepository(relPath) : "";
             if (!comparisons.get(0).equals("identical")) {
                 Path expectedUpstreamPath = expectedUpstream.pathFromRepository(relPath);
                 if (expectedUpstreamPath != null) {
@@ -232,6 +235,7 @@
             values.add(changedCommentsSummary);
             values.addAll(comparisons);
             values.add(diffCommand);
+            values.add(guessed_upstream_path);
             printTsv(out, values);
         }
     }
diff --git a/tools/upstream/src/main/java/libcore/Repository.java b/tools/upstream/src/main/java/libcore/Repository.java
index 4c7bbd7..51a3a69 100644
--- a/tools/upstream/src/main/java/libcore/Repository.java
+++ b/tools/upstream/src/main/java/libcore/Repository.java
@@ -167,6 +167,36 @@
     }
 
     /**
+     * A checkout of the hg repository of OpenJDK 11 or higher, located in the
+     * subdirectory {@code upstreamName} under the directory {@code upstreamRoot}.
+     */
+    public static Repository openJdk11(Path upstreamRoot, String upstreamName) {
+        List<String> sourceDirs = Arrays.asList(
+            "src/java.base/share/classes",
+            "src/java.logging/share/classes",
+            "src/java.prefs/share/classes",
+            "src/java.sql/share/classes",
+            "src/java.desktop/share/classes",
+            "src/java.base/solaris/classes",
+            "src/java.base/unix/classes",
+            "src/java.prefs/unix/classes",
+            "src/jdk.unsupported/share/classes",
+            "src/jdk.net/share/classes",
+            "src/java.base/linux/classes",
+            "build/linux-x86_64-normal-server-release/support/gensrc/java.base",
+
+            // Native (.c) files
+            "src/java.base/unix/native/libjava",
+            "src/java.base/share/native/libjava",
+            "src/java.base/unix/native/libnio",
+            "src/java.base/unix/native/libnio/ch",
+            "src/java.base/unix/native/libnio/fs",
+            "src/java.base/unix/native/libnet"
+        );
+        return new OpenJdkRepository(upstreamRoot, upstreamName, sourceDirs);
+    }
+
+    /**
      * A checkout of the hg repository of OpenJDK 8 or earlier, located in the
      * subdirectory {@code upstreamName} under the directory {@code upstreamRoot}.
      */
diff --git a/tools/upstream/src/main/java/libcore/StandardRepositories.java b/tools/upstream/src/main/java/libcore/StandardRepositories.java
index 7047c60..9b74f55 100644
--- a/tools/upstream/src/main/java/libcore/StandardRepositories.java
+++ b/tools/upstream/src/main/java/libcore/StandardRepositories.java
@@ -28,6 +28,7 @@
 import libcore.Repository.OjluniRepository;
 
 import static libcore.Repository.openJdk9;
+import static libcore.Repository.openJdk11;
 import static libcore.Repository.openJdkLegacy;
 
 public class StandardRepositories {
@@ -51,10 +52,12 @@
         this.openJdk8u222 = addAndReturn(allUpstreams, openJdkLegacy(upstreamRoot, "8u222-b01"));
         this.openJdk9p181 = addAndReturn(allUpstreams, openJdk9(upstreamRoot, "9+181"));
         Repository openJdk8u60 = addAndReturn(allUpstreams, openJdkLegacy(upstreamRoot, "8u60"));
+        Repository openJdk11p28 = addAndReturn(allUpstreams, openJdk11(upstreamRoot, "11+28"));
         this.openJdk7u40 = addAndReturn(allUpstreams, openJdkLegacy(upstreamRoot, "7u40"));
         this.allUpstreams = Collections.unmodifiableList(new ArrayList<>(allUpstreams));
         this.historicUpstreams = Collections.unmodifiableList(new ArrayList<>(
-                Arrays.asList(openJdk8u60, openJdk7u40)
+                Arrays.asList(openJdk8u121, openJdk8u60, openJdk11p28, openJdk9p181, openJdk9b113,
+                    openJdk7u40)
         ));
         this.ojluni = new OjluniRepository(buildTop);
     }
diff --git a/tools/upstream/upstream-diff b/tools/upstream/upstream-diff
index b689b33..8b8c9cf 100755
--- a/tools/upstream/upstream-diff
+++ b/tools/upstream/upstream-diff
@@ -40,9 +40,14 @@
   upstream-diff java/util/ArrayList.java
 
 To verify multiple files:
-
   upstream-diff java.util.ArrayList java.util.LinkedList
 
+To verify a folder:
+  upstream-diff java/util/concurrent
+
+To verify a package:
+  upstream-diff java.util.concurrent
+
 Use a three-way merge to integrate changes from 9+181 into ArrayList:
   upstream-diff -r 8u121-b13,ojluni,9+181 java/util/ArrayList.java
 or to investigate which version of upstream introduced a change:
@@ -56,27 +61,64 @@
 import subprocess
 import sys
 
+
+def get_path_type(rel_path):
+    ext = os.path.splitext(rel_path)[-1]
+    # Check the extension and if it is a C/C++ extension then we're dealing
+    # with a native path. Otherwise we would be dealing with a java path, which
+    # can be a filename, folder name, package name, or fully qualified class
+    # name.
+    if re.match('\\.(c|cc|cpp|cxx|h|hpp|hxx|icc)$', ext):
+        return 'native'
+    return 'java'
+
+
+def normalize_java_path(rel_path):
+    if re.match('.+\\.java$', rel_path):
+        # Path ends in '.java' so a filename with its path is expected
+        return rel_path
+
+    if '/' not in rel_path:
+        # Convert package name, or fully qualified class name into path
+        rel_path = rel_path.replace('.', '/')
+
+    if any(c.isupper() for c in rel_path):
+        # If the name includes an uppercase character, we guess that this is a
+        # class rather than a package name, so the extension needs to be appended
+        # to get the full filename
+        # Note: Test packages may have upper case characters in the package name,
+        # so, if trying to diff a test package, the ".java" suffix will be added
+        # unnecessarily, causing a wrong diff input. Therefore, for test packages,
+        # the tool should be used for each file individually
+        rel_path += '.java'
+    elif rel_path[-1] != '/':
+        # No upper case characters, so this must be a folder/package
+        rel_path += '/'
+
+    return rel_path
+
+
 def run_diff(diff, repositories, rel_paths):
     # Root of checked-out Android sources, set by the "lunch" command.
     android_build_top = os.environ['ANDROID_BUILD_TOP']
-    # Root of repository snapshots. See go/libcore-o-verify for how you'd want to set this.
+    # Root of repository snapshots. See go/libcore-o-verify for how you'd want
+    # to set this.
     ojluni_upstreams = os.environ['OJLUNI_UPSTREAMS']
     for rel_path in rel_paths:
-        # Paths end with a dot and lowercase file extension (.c, .java, ...) but
-        # fully qualified class names do not.
-        if ('/' not in rel_path) and (not re.match('.+\\.[a-z]{1,4}$', rel_path)):
-            # Assume a fully qualified class name
-            rel_path = rel_path.replace('.', '/') + '.java'
+        path_type = get_path_type(rel_path)
+        if path_type == 'java':
+            rel_path = normalize_java_path(rel_path)
         paths = []
+
         for repository in repositories:
             if repository == 'ojluni':
-                file_group = 'java/' if rel_path.endswith('.java') else 'native/'
                 paths.append('%s/libcore/ojluni/src/main/%s/%s'
-                             % (android_build_top, file_group, rel_path))
+                             % (android_build_top, path_type, rel_path))
             else:
                 paths.append('%s/%s/%s' % (ojluni_upstreams, repository, rel_path))
         subprocess.call([diff] + paths)
 
+
 def main():
     parser = argparse.ArgumentParser(
         description='Compare files between libcore/ojluni and ${OJLUNI_UPSTREAMS}.',
@@ -103,6 +145,6 @@
         sys.exit(1)
     run_diff(args.diff, repositories, args.rel_path)
 
+
 if __name__ == "__main__":
     main()
-